diff --git a/essenza/db.sqlite3 b/essenza/db.sqlite3 index 836a999..28442db 100644 Binary files a/essenza/db.sqlite3 and b/essenza/db.sqlite3 differ diff --git a/essenza/deploy.sh b/essenza/deploy.sh new file mode 100644 index 0000000..7d64b16 --- /dev/null +++ b/essenza/deploy.sh @@ -0,0 +1,7 @@ +pip install -r requirements.txt && \ +python manage.py flush --noinput && \ +python manage.py migrate --noinput && \ +# python manage.py collectstatic --noinput && \ +python manage.py loaddata user/sample/sample.json && \ +python manage.py loaddata product/sample/sample.json && \ +python manage.py loaddata order/sample/sample.json \ No newline at end of file diff --git a/essenza/order/models.py b/essenza/order/models.py index d623635..a06b75b 100644 --- a/essenza/order/models.py +++ b/essenza/order/models.py @@ -8,11 +8,17 @@ class Status(models.TextChoices): class Order(models.Model): user = models.ForeignKey('user.Usuario', on_delete=models.CASCADE, related_name='orders') - adress = models.CharField(max_length=255) + address = models.CharField(max_length=255) placed_at = models.DateTimeField(auto_now=True) - total_price = models.DecimalField(max_digits=10, decimal_places=2) status = models.CharField(max_length=10, choices=Status.choices, default=Status.PENDING) + @property + def total_price(self): + total = 0 + for product in self.order_products.all(): + total += product.quantity * product.product.price + return total + def __str__(self): return f"Order {self.id} by {self.user.email}" @@ -21,7 +27,6 @@ class OrderProduct(models.Model): order = models.ForeignKey('order.Order', on_delete=models.CASCADE, related_name='order_products') product = models.ForeignKey('product.Product', on_delete=models.CASCADE, related_name='product_orders') quantity = models.IntegerField() - unity_price = models.DecimalField(max_digits=10, decimal_places=2) def __str__(self): return f"{self.quantity} of {self.product.name} in order {self.order.id}" diff --git a/essenza/order/sample/sample.json b/essenza/order/sample/sample.json new file mode 100644 index 0000000..58bcedd --- /dev/null +++ b/essenza/order/sample/sample.json @@ -0,0 +1,151 @@ +[ + { + "model": "order.order", + "pk": 1, + "fields": { + "user": 1, + "address": "Calle Gran Vía, 23, Madrid, 28013", + "placed_at": "2024-02-12T10:45:00Z", + "status": "pending" + } + }, + { + "model": "order.order", + "pk": 2, + "fields": { + "user": 2, + "address": "Avenida de la Constitución, 8, Sevilla, 41001", + "placed_at": "2024-03-01T15:10:00Z", + "status": "paid" + } + }, + { + "model": "order.order", + "pk": 3, + "fields": { + "user": 3, + "address": "Carrer de Pau Claris, 60, Barcelona, 08010", + "placed_at": "2024-03-20T19:25:00Z", + "status": "shipped" + } + }, + { + "model": "order.order", + "pk": 4, + "fields": { + "user": 1, + "address": "Calle Alcalá, 120, Madrid, 28009", + "placed_at": "2024-04-05T09:00:00Z", + "status": "pending" + } + }, + { + "model": "order.order", + "pk": 5, + "fields": { + "user": 2, + "address": "Plaza Nueva, 10, Bilbao, 48001", + "placed_at": "2024-04-22T12:15:00Z", + "status": "shipped" + } + }, + { + "model": "order.orderproduct", + "pk": 1, + "fields": { + "order": 1, + "product": 1, + "quantity": 2 + } + }, + { + "model": "order.orderproduct", + "pk": 2, + "fields": { + "order": 1, + "product": 18, + "quantity": 1 + } + }, + { + "model": "order.orderproduct", + "pk": 3, + "fields": { + "order": 2, + "product": 5, + "quantity": 3 + } + }, + { + "model": "order.orderproduct", + "pk": 4, + "fields": { + "order": 2, + "product": 14, + "quantity": 2 + } + }, + { + "model": "order.orderproduct", + "pk": 5, + "fields": { + "order": 3, + "product": 3, + "quantity": 1 + } + }, + { + "model": "order.orderproduct", + "pk": 6, + "fields": { + "order": 3, + "product": 9, + "quantity": 2 + } + }, + { + "model": "order.orderproduct", + "pk": 7, + "fields": { + "order": 3, + "product": 10, + "quantity": 1 + } + }, + { + "model": "order.orderproduct", + "pk": 8, + "fields": { + "order": 4, + "product": 11, + "quantity": 2 + } + }, + { + "model": "order.orderproduct", + "pk": 9, + "fields": { + "order": 4, + "product": 15, + "quantity": 1 + } + }, + { + "model": "order.orderproduct", + "pk": 10, + "fields": { + "order": 5, + "product": 7, + "quantity": 4 + } + }, + { + "model": "order.orderproduct", + "pk": 11, + "fields": { + "order": 5, + "product": 20, + "quantity": 2 + } + } +] diff --git a/essenza/product/models.py b/essenza/product/models.py index b2cfaaf..12d3621 100644 --- a/essenza/product/models.py +++ b/essenza/product/models.py @@ -10,13 +10,14 @@ class Category(models.TextChoices): class Product(models.Model): name = models.CharField(max_length=255) description = models.TextField() - categoria = models.CharField(max_length=20, choices=Category.choices) + category = models.CharField(max_length=20, choices=Category.choices) brand = models.CharField(max_length=255) price = models.DecimalField(max_digits=10, decimal_places=2) - foto = models.ImageField(upload_to='profile_pics/', null=True, blank=True) + photo = models.ImageField(upload_to='profile_pics/', null=True, blank=True) stock = models.IntegerField() is_active = models.BooleanField(default=False) + def __str__(self): return self.name diff --git a/essenza/product/sample/sample.json b/essenza/product/sample/sample.json new file mode 100644 index 0000000..2f3e04a --- /dev/null +++ b/essenza/product/sample/sample.json @@ -0,0 +1,282 @@ +[ + { + "model": "product.product", + "pk": 1, + "fields": { + "name": "Maquillaje Base", + "description": "Base líquida para rostro, de acabado mate, 30ml.", + "category": "maquillaje", + "brand": "L'Oréal", + "price": 19.99, + "photo": "https://example.com/images/maquillaje_base.jpg", + "stock": 50, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 2, + "fields": { + "name": "Shampoo Reconstructivo", + "description": "Shampoo nutritivo para cabellos dañados, 500ml.", + "category": "tratamiento", + "brand": "Pantene", + "price": 6.99, + "photo": "https://example.com/images/shampoo_reconstructivo.jpg", + "stock": 100, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 3, + "fields": { + "name": "Secador de Pelo", + "description": "Secador de pelo con 3 niveles de temperatura, 2000W.", + "category": "herramienta", + "brand": "Braun", + "price": 45.99, + "photo": "https://example.com/images/secador_pelo.jpg", + "stock": 30, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 4, + "fields": { + "name": "Perfume Floral", + "description": "Perfume con notas de jazmín y rosa, 100ml.", + "category": "perfume", + "brand": "Chanel", + "price": 79.99, + "photo": "https://example.com/images/perfume_floral.jpg", + "stock": 20, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 5, + "fields": { + "name": "Crema Hidratante", + "description": "Crema hidratante para piel seca, 50ml.", + "category": "tratamiento", + "brand": "Nivea", + "price": 12.99, + "photo": "https://example.com/images/crema_hidratante.jpg", + "stock": 150, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 6, + "fields": { + "name": "Rizador de Pelo", + "description": "Rizador de pelo con control de temperatura, 25mm.", + "category": "herramienta", + "brand": "Remington", + "price": 29.99, + "photo": "https://example.com/images/rizador_pelo.jpg", + "stock": 40, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 7, + "fields": { + "name": "Gel Antibacterial", + "description": "Gel antibacterial para manos, 250ml.", + "category": "tratamiento", + "brand": "Dettol", + "price": 4.99, + "photo": "https://example.com/images/gel_antibacterial.jpg", + "stock": 200, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 8, + "fields": { + "name": "Shampoo Anticaspa", + "description": "Shampoo anticaspa para cuero cabelludo sensible, 400ml.", + "category": "tratamiento", + "brand": "Head & Shoulders", + "price": 7.99, + "photo": "https://example.com/images/shampoo_anticaspa.jpg", + "stock": 90, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 9, + "fields": { + "name": "Aceite Capilar", + "description": "Aceite nutritivo para el cabello, 150ml.", + "category": "tratamiento", + "brand": "Argan Oil", + "price": 15.99, + "photo": "https://example.com/images/aceite_capilar.jpg", + "stock": 60, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 10, + "fields": { + "name": "Tinte de Cabello", + "description": "Tinte permanente para cabello, color castaño claro.", + "category": "cabello", + "brand": "Garnier", + "price": 8.99, + "photo": "https://example.com/images/tinte_cabello.jpg", + "stock": 110, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 11, + "fields": { + "name": "Mascarilla Facial", + "description": "Mascarilla hidratante para todo tipo de piel, 100ml.", + "category": "tratamiento", + "brand": "L'Oréal", + "price": 18.99, + "photo": "https://example.com/images/mascarilla_facial.jpg", + "stock": 80, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 12, + "fields": { + "name": "Shampoo Voluminizador", + "description": "Shampoo voluminizador para cabellos finos, 300ml.", + "category": "tratamiento", + "brand": "TRESemmé", + "price": 5.99, + "photo": "https://example.com/images/shampoo_voluminizador.jpg", + "stock": 120, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 13, + "fields": { + "name": "Laca de Pelo", + "description": "Laca fijadora para todo el día, 400ml.", + "category": "cabello", + "brand": "Schwarzkopf", + "price": 10.99, + "photo": "https://example.com/images/laca_pelo.jpg", + "stock": 70, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 14, + "fields": { + "name": "Crema Solar", + "description": "Protección solar SPF 50+, 200ml.", + "category": "tratamiento", + "brand": "Hawaiian Tropic", + "price": 14.99, + "photo": "https://example.com/images/crema_solar.jpg", + "stock": 40, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 15, + "fields": { + "name": "Crema Antiedad", + "description": "Crema antiarrugas para el rostro, 50ml.", + "category": "tratamiento", + "brand": "Olay", + "price": 25.99, + "photo": "https://example.com/images/crema_antiedad.jpg", + "stock": 30, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 16, + "fields": { + "name": "Desodorante", + "description": "Desodorante en barra, 75g.", + "category": "tratamiento", + "brand": "Dove", + "price": 3.99, + "photo": "https://example.com/images/desodorante.jpg", + "stock": 150, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 17, + "fields": { + "name": "Toallitas Desmaquillantes", + "description": "Toallitas para desmaquillar, 25 unidades.", + "category": "tratamiento", + "brand": "Neutrogena", + "price": 4.49, + "photo": "https://example.com/images/toallitas_desmaquillantes.jpg", + "stock": 90, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 18, + "fields": { + "name": "Pincel de Maquillaje", + "description": "Pincel para base líquida, cerdas suaves.", + "category": "maquillaje", + "brand": "Real Techniques", + "price": 12.99, + "photo": "https://example.com/images/pincel_maquillaje.jpg", + "stock": 110, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 19, + "fields": { + "name": "Crema para Pies", + "description": "Crema reparadora para pies agrietados, 100ml.", + "category": "tratamiento", + "brand": "Eucerin", + "price": 9.99, + "photo": "https://example.com/images/crema_pies.jpg", + "stock": 80, + "is_active": true + } + }, + { + "model": "product.product", + "pk": 20, + "fields": { + "name": "Limpieza Facial", + "description": "Gel limpiador facial suave, 200ml.", + "category": "tratamiento", + "brand": "Neutrogena", + "price": 7.49, + "photo": "https://example.com/images/limpieza_facial.jpg", + "stock": 130, + "is_active": true + } + } +] diff --git a/essenza/static/images/img2.avif b/essenza/static/images/img2.avif deleted file mode 100644 index 5df7da0..0000000 Binary files a/essenza/static/images/img2.avif and /dev/null differ diff --git a/essenza/user/models.py b/essenza/user/models.py index 7a92bfb..40ab05e 100644 --- a/essenza/user/models.py +++ b/essenza/user/models.py @@ -6,7 +6,7 @@ class Role(models.TextChoices): USER = 'user', 'User' class Usuario(AbstractUser): - foto = models.ImageField(upload_to='images/', null=True, blank=True) + photo = models.ImageField(upload_to='images/', null=True, blank=True) role = models.CharField(max_length=10, choices=Role.choices, default=Role.USER) email = models.EmailField(unique=True) diff --git a/essenza/user/sample/sample.json b/essenza/user/sample/sample.json new file mode 100644 index 0000000..843a364 --- /dev/null +++ b/essenza/user/sample/sample.json @@ -0,0 +1,49 @@ +[ + { + "model": "user.usuario", + "pk": 1, + "fields": { + "email": "juan.perez@example.com", + "username": "juan", + "photo": "https://example.com/images/juan_perez.jpg", + "role": "user", + "password": "pbkdf2_sha256$1000000$6D2dFePeqIu7UN3iIkhrmg$jkb15BhOjo5s/2vveGH1YPZX2Eu5abDhXUpn6rHi61c=" + } + }, + { + "model": "user.usuario", + "pk": 2, + "fields": { + "email": "ana.martin@example.com", + "username": "ana", + "photo": "https://example.com/images/ana_martin.jpg", + "role": "user", + "password": "pbkdf2_sha256$1000000$sjZji3r8LgZ1Scf2lR8sDA$zwsaj6xrhTxpZqfLqPZtHD8w5obxhP5RKh5RUY8vcB0=" + } + }, + { + "model": "user.usuario", + "pk": 3, + "fields": { + "email": "carla.gonzalez@example.com", + "username": "carla", + "photo": "https://example.com/images/carla_gonzalez.jpg", + "role": "user", + "password": "pbkdf2_sha256$1000000$X4rPLmVEgJfrZJ3gVwUwKg$alBh41D6b/3X9GiA2fo2X8X5Q8aHT91Jk5mwY6GLgdE=" + } + }, + { + "model": "user.usuario", + "pk": 4, + "fields": { + "email": "admin@example.com", + "username": "admin", + "is_superuser": true, + "is_staff": true, + "is_active": true, + "photo": "https://example.com/images/admin.jpg", + "role": "admin", + "password": "pbkdf2_sha256$1000000$sazfnRvfJ4niYZE6ixBVKR$pboaUb8AWvEXwuJZkWoh3xwfYq++7nik9p2e0TxNPws=" + } + } +] \ No newline at end of file