Skip to content

Commit

Permalink
Merge pull request #93 from leonardocintra/template-novo
Browse files Browse the repository at this point in the history
feat: outros tipos de produtos parte 1 #92
  • Loading branch information
leonardocintra authored May 2, 2022
2 parents fa89f07 + 096eef4 commit 11d1884
Show file tree
Hide file tree
Showing 19 changed files with 176 additions and 21 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ check:
@python3 manage.py check

migrate:
@python manage.py makemigrations
@python manage.py migrate
@python3 manage.py makemigrations
@python3 manage.py migrate

deploy-stage:
@git push stage main
@heroku run python manage.py migrate --remote stage
@heroku run python3 manage.py migrate --remote stage

deploy-prod:
@git push prod main
@heroku run python manage.py migrate --remote prod
@heroku run python3 manage.py migrate --remote prod

test:
@python3 manage.py test -v 2
Expand Down
1 change: 1 addition & 0 deletions catalogo/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class CorAdmin(admin.ModelAdmin):

class TipoProdutoAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('nome',)}
list_display = ['nome', 'icone_fontawesome', 'ativo', ]


class SubCategoriaAdmin(admin.ModelAdmin):
Expand Down
18 changes: 18 additions & 0 deletions catalogo/migrations/0066_tipoproduto_descricao.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.0.4 on 2022-05-02 15:09

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('catalogo', '0065_rename_categoria_tipoproduto_and_more'),
]

operations = [
migrations.AddField(
model_name='tipoproduto',
name='descricao',
field=models.TextField(default='Descrição não informada'),
),
]
12 changes: 11 additions & 1 deletion catalogo/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from cloudinary.models import CloudinaryField
from django.core.cache import cache
from django.db import models
from core.constants import CACHE_PRODUTOS_TELA_INICIAL
from core.constants import CACHE_PRODUTOS_TELA_INICIAL, CACHE_TIPOS_PRODUTOS

from seller.models import Seller

Expand All @@ -20,6 +20,7 @@ class TipoProduto(models.Model):
slug = models.SlugField('Identificador', max_length=100, unique=True)
ativo = models.BooleanField(default=True)
icone_fontawesome = models.CharField(max_length=50, null=True)
descricao = models.TextField(default='Descrição não informada')
created_at = models.DateTimeField('Criado em', auto_now_add=True)
updated_at = models.DateTimeField('Modificado em', auto_now=True)

Expand All @@ -31,6 +32,15 @@ class Meta:
def __str__(self):
return self.nome

@classmethod
def get_tipos_produto_ativo(cls):
tipos_produto = cache.get(CACHE_TIPOS_PRODUTOS)
if tipos_produto is not None:
return tipos_produto
tipos_produto = cls.objects.all().exclude(ativo=False)
cache.set(CACHE_TIPOS_PRODUTOS, tipos_produto)
return tipos_produto


class SubCategoria(models.Model):
"""Ex: camiseta cantor, camiseta carros, caneca programação, etc"""
Expand Down
Empty file.
13 changes: 13 additions & 0 deletions catalogo/templatetags/catalogo_extras.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django import template
from django.templatetags.static import static
from catalogo.models import TipoProduto

register = template.Library()


@register.simple_tag(name='imagem_tipo_produto')
def imagem_tipo_produto(tipo_produto_id=1):
# para incluir a imagem aqui precisa adicionar manualmente na pasta core/static/img
tipos_produto = TipoProduto.get_tipos_produto_ativo()
imagem = tipos_produto.filter(id=tipo_produto_id).first()
return static('img/' + imagem.icone_fontawesome + '.gif')
15 changes: 14 additions & 1 deletion catalogo/tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
SubCategoria, Modelo, SkuDimona, Cor, Tamanho, TamanhoModelo, CorModelo)
from django.db import IntegrityError

from core.constants import CACHE_TIPOS_PRODUTOS


class TamanhoModelTest(TestCase):
fixtures = ['fixtures/catalogo/tamanho.json', ]
Expand Down Expand Up @@ -94,7 +96,7 @@ class TipoProdutoModelTest(TestCase):
fixtures = ['fixtures/catalogo/tipo_produto.json', ]

def setUp(self) -> None:
return super().setUp()
cache.delete(CACHE_TIPOS_PRODUTOS)

def test_create(self):
self.assertTrue(TipoProduto.objects.exists())
Expand Down Expand Up @@ -145,6 +147,17 @@ def test_tipo_produto_slug_unique(self):
with self.assertRaises(IntegrityError):
TipoProduto.objects.create(nome='Camisetas', slug='camiseta')

def test_cache(self):
tipo_produto = TipoProduto.get_tipos_produto_ativo()
self.assertIsNotNone(tipo_produto)
self.assertEqual(4, len(tipo_produto))
TipoProduto.objects.create(nome='Teste', slug='teste')
novo_get = TipoProduto.get_tipos_produto_ativo()
self.assertEqual(4, len(novo_get))
cache.delete(CACHE_TIPOS_PRODUTOS)
novo_get2 = TipoProduto.get_tipos_produto_ativo()
self.assertEqual(5, len(novo_get2))


class SubCategoriaModelTest(TestCase):
fixtures = ['fixtures/catalogo/subcategoria.json', ]
Expand Down
1 change: 1 addition & 0 deletions core/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
CACHE_PRODUTOS_TELA_INICIAL = 'produtos-tela-inicial'
CACHE_TIPOS_PRODUTOS = 'tipos_produto'

TIPO_FRETE = (
('proprio', 'Frete proprio'),
Expand Down
Binary file added core/static/img/bone.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added core/static/img/camiseta.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added core/static/img/caneca.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added core/static/img/moleton.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 40 additions & 6 deletions core/tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
from django.test import TestCase, Client
from django.shortcuts import resolve_url as r
from django.urls import reverse
from catalogo.models import Produto, SubCategoria
from core.constants import CACHE_PRODUTOS_TELA_INICIAL
from catalogo.models import Produto, SubCategoria, TipoProduto
from core.constants import CACHE_PRODUTOS_TELA_INICIAL, CACHE_TIPOS_PRODUTOS


def create_produto(nome, slug, subcategoria, ativo=True, mostrar_tela_inicial=True):
Produto.objects.create(
Expand All @@ -19,6 +20,10 @@ def create_produto(nome, slug, subcategoria, ativo=True, mostrar_tela_inicial=Tr


class IndexViewTest(TestCase):
fixtures = [
'fixtures/catalogo/tipo_produto.json',
]

def setUp(self):
self.client = Client()
cache.delete(CACHE_PRODUTOS_TELA_INICIAL)
Expand Down Expand Up @@ -52,12 +57,14 @@ def test_pagina_com_produto_sem_paginacao(self):
def test_esta_trazendo_produtos_cadastrados_na_listagem(self):
quantidade_produtos = 50
for produto_id in range(quantidade_produtos):
create_produto(f'Camiseta {produto_id}', f'camiseta-{produto_id}', self.subcategoria)
create_produto(f'Camiseta {produto_id}',
f'camiseta-{produto_id}', self.subcategoria)
response = self.client.get(reverse('core:index'))
self.assertEqual(quantidade_produtos, len(Produto.objects.all()))
self.assertIsNotNone(response.context['produtos'])
cache.delete(CACHE_PRODUTOS_TELA_INICIAL)
self.assertEqual(quantidade_produtos, len(response.context['produtos']))
self.assertEqual(quantidade_produtos, len(
response.context['produtos']))

def test_nao_mostrar_produtos_ativo_false(self):
create_produto('Caneca Ativa', 'caneca-a', self.subcategoria)
Expand Down Expand Up @@ -105,7 +112,8 @@ def test_produtos_cacheados(self):
produtos_cacheados2 = Produto.get_produtos_ativos_e_tela_inicial_true()

# Ainda deve estar mostrando o valor cacheado e nao o valor alterado no banco
self.assertEqual(str(produtos_cacheados2.first()), 'Produto para cache')
self.assertEqual(str(produtos_cacheados2.first()),
'Produto para cache')
response = self.client.get(reverse('core:index'))
self.assertContains(response, 'Produto para cache')

Expand All @@ -114,13 +122,39 @@ def test_produtos_cacheados(self):

# Apos delete do cache deve mostrar o valor cacheado do ultimo update
produtos_cacheados3 = Produto.get_produtos_ativos_e_tela_inicial_true()
self.assertEqual(str(produtos_cacheados3.first()), 'Nome cache alterado')
self.assertEqual(str(produtos_cacheados3.first()),
'Nome cache alterado')

# No request na pagina deve mostrar o valor cacheado alterado
response = self.client.get(reverse('core:index'))
self.assertContains(response, 'Nome cache alterado')
self.assertNotContains(response, 'Produto para cache')

def test_frase_nossos_produtos(self):
response = self.client.get(reverse('core:index'))
frase = 'Nossos produtos'
self.assertContains(response, frase)

def test_tipos_produto(self):
response = self.client.get(reverse('core:index'))
self.assertIsNotNone(response.context['tipos_produto'])
self.assertEqual(4, len(response.context['tipos_produto']))

def test_tipos_produtos_somente_ativos(self):
response = self.client.get(reverse('core:index'))
self.assertEqual(4, len(response.context['tipos_produto']))
self.assertEqual(5, TipoProduto.objects.count())

def test_tipos_produtos_todos_desativados(self):
objs = TipoProduto.objects.filter(ativo=True)
for o in objs:
TipoProduto.objects.filter(pk=o.id).update(ativo=False)
cache.delete(CACHE_TIPOS_PRODUTOS)
response = self.client.get(reverse('core:index'))
self.assertEqual(0, len(response.context['tipos_produto']))
frase = 'Nossos produtos'
self.assertNotContains(response, frase)

def test_sem_paginacao(self):
pass

Expand Down
4 changes: 3 additions & 1 deletion core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.shortcuts import render
from django.views.generic.base import TemplateView

from catalogo.models import Produto, SubCategoria
from catalogo.models import Produto, SubCategoria, TipoProduto
from checkout.views import get_quantidade_items_carrinho


Expand All @@ -12,8 +12,10 @@ def index(request):
subcategorias = SubCategoria.get_subcategorias_ativas()
quantidade_item = get_quantidade_items_carrinho(request)
page_obj = __get_page_obj(request, produtos)
tipos_produto = TipoProduto.get_tipos_produto_ativo()

context = {
'tipos_produto': tipos_produto,
'produtos': produtos,
'page_obj': page_obj,
'subcategorias': subcategorias,
Expand Down
28 changes: 25 additions & 3 deletions fixtures/catalogo/tipo_produto.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"nome": "Camisetas",
"slug": "camisetas",
"ativo": true,
"icone_fontawesome": null,
"icone_fontawesome": "camiseta",
"created_at": "2022-02-28T14:58:38.492Z",
"updated_at": "2022-02-28T14:58:38.492Z"
}
Expand All @@ -16,7 +16,7 @@
"nome": "Canecas",
"slug": "canecas",
"ativo": true,
"icone_fontawesome": null,
"icone_fontawesome": "caneca",
"created_at": "2022-02-28T14:58:44.009Z",
"updated_at": "2022-02-28T14:58:44.009Z"
}
Expand All @@ -27,8 +27,30 @@
"nome": "Moletons",
"slug": "moletons",
"ativo": true,
"icone_fontawesome": null,
"icone_fontawesome": "moletons",
"created_at": "2022-02-28T14:58:52.750Z",
"updated_at": "2022-02-28T14:58:52.750Z"
}
}, {
"model": "catalogo.tipoproduto",
"pk": 4,
"fields": {
"nome": "Bonés",
"slug": "bone",
"ativo": true,
"icone_fontawesome": "bones",
"created_at": "2022-02-28T14:58:44.009Z",
"updated_at": "2022-02-28T14:58:44.009Z"
}
}, {
"model": "catalogo.tipoproduto",
"pk": 5,
"fields": {
"nome": "Tenis",
"slug": "tenis",
"ativo": false,
"icone_fontawesome": "tenis",
"created_at": "2022-04-28T14:58:44.009Z",
"updated_at": "2022-04-28T14:58:44.009Z"
}
}]
8 changes: 6 additions & 2 deletions pagamento/tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ def test_usuario_nao_autenticado(self):

@override_settings(DEBUG=True)
class PagamentoViewTest(TestCase):
fixtures = ['fixtures/evento/status.json', ]
fixtures = [
'fixtures/catalogo/tipo_produto.json',
'fixtures/evento/status.json',
]

def setUp(self):
get_fake_carrinho_com_items()
Expand Down Expand Up @@ -109,7 +112,8 @@ def test_topico_nao_mapeado(self):
def test_merchant_order_pedido_nao_encontrado(self):
response = self.client.post(
r('pagamento:mp_notifications') + '?topic=merchant_order&id=4076824593')
self.assertJSONEqual(response.content, {"pedido": "pedido-nao-encontrado"})
self.assertJSONEqual(response.content, {
"pedido": "pedido-nao-encontrado"})
self.assertEqual(200, response.status_code)

def test_notificacao_mp_ipn_pagamento_mp_nao_encontrado(self):
Expand Down
3 changes: 2 additions & 1 deletion templates/includes/_categorias.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
<h4>Clique numa <span class="badge bg-success"><i class="bi bi-app"></i> categoria</span> abaixo</h4>

{% for categoria in subcategorias %}
<a style="margin-top: 4px;" href="{% url 'catalogo:lista_por_subcategoria' categoria.slug %}" class="btn btn-outline-secondary btn-sm">
<a style="margin-top: 4px;" href="{% url 'catalogo:lista_por_subcategoria' categoria.slug %}"
class="btn btn-outline-secondary btn-sm">
<i class="fas fa-{{ categoria.icone_fontawesome }}"></i> {{ categoria.nome }}
</a>
{% empty %}
Expand Down
35 changes: 35 additions & 0 deletions templates/includes/_nossos_produtos.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{% load static %}
{% load catalogo_extras %}


<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Sofia">
<style>
.nossoProduto {
font-family: "Sofia", sans-serif;icone_fontawesome
}
</style>

<div class="container">
<h1 class="text-center nossoProduto">Nossos produtos</h1>

<div class="row row-cols-1 row-cols-md-2 g-4">
{% for tipo in tipos_produto %}
<div class="col">
<div class="card mb-3" style="max-width: 540px;">
<div class="row g-0">
<div class="col-md-4">
<img src="{% imagem_tipo_produto tipo.id %}" class="img-fluid rounded-start" alt="{{ tipo.icone_fontawesome }}">
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">{{ tipo }}</h5>
<p class="card-text">{{ tipo.descricao }}</p>
<a href="#" class="stretched-link">Mais detalhes</a>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
5 changes: 3 additions & 2 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
</div>
</div>


{% load static %}
{% if tipos_produto %}
{% include "includes/_nossos_produtos.html" %}
{% endif %}

{% include "catalogo/produtos.html" %}

Expand Down

0 comments on commit 11d1884

Please sign in to comment.