diff --git a/multigranja/apps/core/static/core/js/main.js b/multigranja/apps/core/static/core/js/main.js index ad7c8c0..6164005 100644 --- a/multigranja/apps/core/static/core/js/main.js +++ b/multigranja/apps/core/static/core/js/main.js @@ -41,4 +41,11 @@ document.addEventListener("DOMContentLoaded", () => { } }); }); +}); + +// Blocks scroll form changing the value on inputs type number +document.querySelectorAll('input[type="number"]').forEach(input => { + input.addEventListener('wheel', function(event) { + event.target.blur(); + }); }); \ No newline at end of file diff --git a/multigranja/apps/core/templates/layouts/base.html b/multigranja/apps/core/templates/layouts/base.html index 21ac856..8b88ec7 100644 --- a/multigranja/apps/core/templates/layouts/base.html +++ b/multigranja/apps/core/templates/layouts/base.html @@ -11,10 +11,12 @@ - + + + {% block extra_css %}{% endblock %} diff --git a/multigranja/apps/entities/admin.py b/multigranja/apps/entities/admin.py index 6c53895..d4374f7 100644 --- a/multigranja/apps/entities/admin.py +++ b/multigranja/apps/entities/admin.py @@ -2,7 +2,7 @@ from django.contrib import admin from .models.user import User from .models.farm import Farm, PaddockGroup, Paddock -from .models.animal import Animal, Batch, BatchAnimal, FeedingRecord +from .models.animal import Animal, BatchType, Batch, BatchAnimal, FeedingRecord from .models.rotation import Rotation admin.site.register([ @@ -15,4 +15,5 @@ admin.site.register([ BatchAnimal, FeedingRecord, Rotation, + BatchType ]) \ No newline at end of file diff --git a/multigranja/apps/entities/forms/animal.py b/multigranja/apps/entities/forms/animal.py index f7c9e93..6216035 100644 --- a/multigranja/apps/entities/forms/animal.py +++ b/multigranja/apps/entities/forms/animal.py @@ -1,5 +1,5 @@ from django import forms -from ..models.animal import Batch, Animal +from ..models.animal import Batch, Animal, BatchType class AnimalCreateForm(forms.ModelForm): class Meta: @@ -42,4 +42,15 @@ class BatchForm(forms.ModelForm): 'batch_type': 'Tipo', 'animals': 'Animais', } -BatchCreateForm = BatchEditForm = BatchForm # Alias to BatchForm since its implementations are the same \ No newline at end of file +BatchCreateForm = BatchEditForm = BatchForm # Alias to BatchForm since its implementations are the same + +class BatchTypeForm(forms.ModelForm): + class Meta: + model = BatchType + fields = ['name', 'consumption_factor'] + + labels = { + 'name': 'Nome', + 'consumption_factor': 'Fator de consumo', + } +BatchTypeCreateForm = BatchTypeEditForm = BatchTypeForm \ No newline at end of file diff --git a/multigranja/apps/entities/migrations/0002_batchtype_alter_batch_batch_type.py b/multigranja/apps/entities/migrations/0002_batchtype_alter_batch_batch_type.py new file mode 100644 index 0000000..d8e317b --- /dev/null +++ b/multigranja/apps/entities/migrations/0002_batchtype_alter_batch_batch_type.py @@ -0,0 +1,29 @@ +# Generated by Django 6.0.2 on 2026-05-30 03:13 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('entities', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='BatchType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('is_active', models.BooleanField(default=True)), + ('name', models.CharField(max_length=45)), + ('consumption_factor', models.DecimalField(decimal_places=2, default=1.0, max_digits=4)), + ('farm', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='batch_types', to='entities.farm')), + ], + ), + migrations.AlterField( + model_name='batch', + name='batch_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='batches', to='entities.batchtype'), + ), + ] diff --git a/multigranja/apps/entities/migrations/0003_farm_default_consumption_farm_summer_consumption_and_more.py b/multigranja/apps/entities/migrations/0003_farm_default_consumption_farm_summer_consumption_and_more.py new file mode 100644 index 0000000..346dc94 --- /dev/null +++ b/multigranja/apps/entities/migrations/0003_farm_default_consumption_farm_summer_consumption_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 6.0.2 on 2026-05-30 19:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('entities', '0002_batchtype_alter_batch_batch_type'), + ] + + operations = [ + migrations.AddField( + model_name='farm', + name='default_consumption', + field=models.DecimalField(decimal_places=2, default=1.0, max_digits=4), + ), + migrations.AddField( + model_name='farm', + name='summer_consumption', + field=models.DecimalField(decimal_places=2, default=1.0, max_digits=4), + ), + migrations.AddField( + model_name='farm', + name='winter_consumption', + field=models.DecimalField(decimal_places=2, default=1.0, max_digits=4), + ), + ] diff --git a/multigranja/apps/entities/models/animal.py b/multigranja/apps/entities/models/animal.py index 995fa4c..f3c9b83 100644 --- a/multigranja/apps/entities/models/animal.py +++ b/multigranja/apps/entities/models/animal.py @@ -35,6 +35,10 @@ class Animal(models.Model): return f"{months} meses" # MM months else: return "Menos de um mês" # Less than a month + + @property + def is_in_batch(self): + return self.batchanimal_set.filter(is_active=True).exists() class Meta: constraints = [ @@ -45,11 +49,25 @@ class Animal(models.Model): ) ] +class BatchType(models.Model): + is_active = models.BooleanField(default=True) + farm = models.ForeignKey('entities.Farm', on_delete=models.CASCADE, related_name='batch_types') + name = models.CharField(max_length=45) + consumption_factor = models.DecimalField(max_digits=4, decimal_places=2, default=1.00) + + def __str__(self): + state = 'Ativo' if self.is_active else 'Inativo' + return f"{state} - {self.name}, {self.consumption_factor}" + + @property + def consumption_percentage(self): + return int((self.consumption_factor - 1) * 100) + class Batch(models.Model): is_active = models.BooleanField(default=True) identifier = models.CharField(max_length=45) animal_category = models.CharField(max_length=45, null=True, blank=True) - batch_type = models.CharField(max_length=45, null=True, blank=True) + batch_type = models.ForeignKey(BatchType, on_delete=models.SET_NULL, related_name='batches', null=True, blank=True) animals = models.ManyToManyField(Animal, through='BatchAnimal', related_name='batches') def __init__(self, *args, **kwargs): @@ -93,6 +111,16 @@ class BatchAnimal(models.Model): def __str__(self): return f"{self.animal.identifier} in {self.batch.identifier}" + + def save(self, *args, **kwargs): + is_active_changed = self.__original_is_active != self.is_active + if is_active_changed and self.is_active: + raise ValueError( + "Reactivating a BatchAnimal is not allowed automatically because it may violate " + "the unique active batch constraint for an animal. Review the logic in " + "models/animal.py (BatchAnimal.save) before proceeding." + ) + super().save(*args, **kwargs) class FeedingRecord(models.Model): animal = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name='feeding_record') diff --git a/multigranja/apps/entities/models/farm.py b/multigranja/apps/entities/models/farm.py index ecc7aeb..db53649 100644 --- a/multigranja/apps/entities/models/farm.py +++ b/multigranja/apps/entities/models/farm.py @@ -4,9 +4,26 @@ class Farm(models.Model): is_active = models.BooleanField(default=True) name = models.CharField(max_length=45) total_area = models.IntegerField(null=True, blank=True) + default_consumption = models.DecimalField(max_digits=4, decimal_places=2, default=1.00) + summer_consumption = models.DecimalField(max_digits=4, decimal_places=2, default=1.00) + winter_consumption = models.DecimalField(max_digits=4, decimal_places=2, default=1.00) + def __str__(self): return self.name + + @property + def animal_count(self): + return self.animals.filter( + is_active=True + ).count() + + @property + def paddock_count(self): + return self.paddocks.filter( + is_active=True + ).count() + class PaddockGroup(models.Model): is_active = models.BooleanField(default=True) diff --git a/multigranja/apps/entities/services/animal.py b/multigranja/apps/entities/services/animal.py index 10f58d7..f180638 100644 --- a/multigranja/apps/entities/services/animal.py +++ b/multigranja/apps/entities/services/animal.py @@ -1,8 +1,8 @@ from django.shortcuts import get_object_or_404 from django.urls import reverse -from ..models import Animal, Batch -from ..forms import AnimalCreateForm, AnimalEditForm, BatchForm +from ..models import Animal, Batch, BatchType +from ..forms import AnimalCreateForm, AnimalEditForm, BatchForm, BatchTypeCreateForm, BatchTypeEditForm from entities.models import Farm # Local utility functions @@ -15,15 +15,36 @@ def _get_selected_farm(request): def _get_animal_by_id(request, animal_id): return get_object_or_404(Animal, pk=animal_id, farm_id=_get_selected_farm_id(request)) -def _get_farms_active_animals(request): - return Animal.objects.filter( - farm=_get_selected_farm_id(request), - is_active=True - ) +# def _get_farms_active_animals(request): +# return Animal.objects.filter( +# farm=_get_selected_farm_id(request), +# is_active=True +# ) def _get_batch_by_id(request, batch_id): return get_object_or_404(Batch, pk=batch_id, is_active=True) +def _get_farms_batch_types(request): + return BatchType.objects.filter(is_active=True, farm_id=_get_selected_farm_id(request)) + +def _get_no_batch_farms_animals(request): + return Animal.objects.filter( + farm_id=_get_selected_farm_id(request), + is_active=True + ).exclude( + batchanimal__is_active=True + ) + +def _get_animals_from_batch(batch_id): + return Batch.objects.get( + id=batch_id + ).animals.filter( + batchanimal__is_active=True + ) + +def _get_batchtype_by_id(request, batchtype_id): + return get_object_or_404(BatchType, pk=batchtype_id, is_active=True, farm=_get_selected_farm(request)) + # Animal Services def get_animal_create_context(): form = AnimalCreateForm() @@ -92,7 +113,8 @@ def delete_animal(request, animal_id): # Batch Services def get_batch_create_context(request): form = BatchForm() - form.fields['animals'].queryset = _get_farms_active_animals(request) + form.fields['animals'].queryset = _get_no_batch_farms_animals(request) + form.fields['batch_type'].queryset = _get_farms_batch_types(request) context = { 'title': 'Novo Lote', @@ -117,8 +139,12 @@ def create_batch(request): def get_batch_update_context(request, batch_id): batch_old = _get_batch_by_id(request, batch_id) + animals_querset = _get_no_batch_farms_animals(request) | _get_animals_from_batch(batch_id) + animals_querset = animals_querset.distinct() + form = BatchForm(instance=batch_old) - form.fields['animals'].queryset = _get_farms_active_animals(request) + form.fields['animals'].queryset = animals_querset + form.fields['batch_type'].queryset = _get_farms_batch_types(request) context = { 'title': f'Editar Lote {batch_old.identifier}', @@ -163,4 +189,76 @@ def get_batch_delete_context(request, batch_id): def delete_batch(request, batch_id): batch = _get_batch_by_id(request, batch_id) batch.is_active = False - batch.save() \ No newline at end of file + batch.save() + +# Batch Type Services +def get_batchtype_create_context(request): + form = BatchTypeCreateForm() + + context = { + 'title': 'Novo Tipo de Lote', + 'form': form, + 'action_url': reverse('entities:animal:batchtype_create'), + 'return_url': reverse('entities:farm:farm_home'), + } + + return context + +def create_batchtype(request): + form = BatchTypeCreateForm(request.POST) + + if form.is_valid(): + batchtype = form.save(commit=False) + batchtype.farm = _get_selected_farm(request) + batchtype.save() + + return True + + return False + +def get_batchtype_update_context(request, batchtype_id): + batchtype = _get_batchtype_by_id(request, batchtype_id) + form = BatchTypeEditForm(instance=batchtype) + + context = {} + context['title'] = 'Editar tipo de lote' + context['action_url'] = reverse( + 'entities:animal:batchtype_update', + kwargs={'batchtype_id': batchtype.pk} + ) + context['return_url'] = reverse('entities:farm:farm_home') + context['form'] = form + + return context + +def update_batchtype(request, batchtype_id): + batchtype = _get_batchtype_by_id(request, batchtype_id) + form = BatchTypeEditForm(request.POST, instance=batchtype) + + if form.is_valid(): + form.save() + return True + + return False + +def get_batchtype_delete_context(request, batchtype_id): + batchtype = _get_batchtype_by_id(request, batchtype_id) + context = {} + context['description'] = f"Excluir tipo de lote {batchtype.name}?" + context['positive_url'] = reverse('entities:animal:batchtype_delete', kwargs={'batchtype_id': batchtype_id}) + context['negative_url'] = reverse('entities:farm:farm_home') + + return context + +def delete_batchtype(request, batchtype_id): + batchtype = _get_batchtype_by_id(request, batchtype_id) + + Batch.objects.filter( + is_active=True, + batch_type=batchtype + ).update( + batch_type=None + ) + + batchtype.is_active = False + batchtype.save() \ No newline at end of file diff --git a/multigranja/apps/entities/services/farm.py b/multigranja/apps/entities/services/farm.py index f22008f..5ad9fcd 100644 --- a/multigranja/apps/entities/services/farm.py +++ b/multigranja/apps/entities/services/farm.py @@ -1,7 +1,9 @@ from django.shortcuts import get_object_or_404 from django.urls import reverse +from django.db.models import Count, Q +from decimal import Decimal -from ..models import Farm, Paddock, PaddockGroup +from ..models import Farm, Paddock, PaddockGroup, BatchType, User from ..forms import FarmCreateForm, FarmEditForm, PaddockCreateForm, PaddockEditForm, PaddockGroupCreateForm, PaddockGroupEditForm @@ -43,20 +45,36 @@ def _get_paddock_group_by_id(request, paddock_group_id): is_active=True ) +def _get_farms_batch_types(request): + return BatchType.objects.filter(is_active=True, farm=_get_selected_farm(request)) # Farm Services def get_farm_home_context(request): authenticated_user = request.user + selected_farm = _get_selected_farm(request) + + farms_query = authenticated_user.farms.filter(is_active=True) + farms_with_counts = farms_query.annotate( + total_animals=Count( + 'animals', + filter=Q(animals__is_active=True), + distinct=True + ), + total_paddocks=Count( + 'paddocks', + filter=Q(paddocks__is_active=True), + distinct=True + ) + ) + allowed_users = selected_farm.users.exclude(pk=authenticated_user.pk) + batch_types = _get_farms_batch_types(request) context = {} - context['title'] = 'Fazenda' - - farms = Farm.objects.filter( - users=authenticated_user, - is_active=True - ) - - context['farms'] = farms + context['title'] = selected_farm.name + context['selected_farm'] = selected_farm + context['farms'] = farms_with_counts + context['allowed_users'] = allowed_users + context['batch_types'] = batch_types return context @@ -67,7 +85,7 @@ def get_farm_create_context(): context['title'] = 'Nova fazenda' context['form'] = form context['action_url'] = reverse('entities:farm:farm_create') - context['return_url'] = reverse('entities:farm:farm_list') + context['return_url'] = reverse('entities:farm:farm_home') return context @@ -92,7 +110,7 @@ def get_update_farm_context(request, farm_id): 'entities:farm:farm_update', kwargs={'farm_id': farm.pk} ) - context['return_url'] = reverse('entities:farm:farm_list') + context['return_url'] = reverse('entities:farm:farm_home') context['form'] = form return context @@ -116,7 +134,7 @@ def get_farm_delete_context(request, farm_id): 'entities:farm:farm_delete', kwargs={'farm_id': farm_id} ) - context['negative_url'] = reverse('entities:farm:farm_list') + context['negative_url'] = reverse('entities:farm:farm_home') return context @@ -125,6 +143,17 @@ def delete_farm(request, farm_id): farm.is_active = False farm.save() +def update_consumption(request): + default_consumption = Decimal(request.POST.get('default-consume')) + summer_consumption = Decimal(request.POST.get('summer-consume')) + winter_consumption = Decimal(request.POST.get('winter-consume')) + + selected_farm = _get_selected_farm(request) + selected_farm.default_consumption = default_consumption + selected_farm.summer_consumption = summer_consumption + selected_farm.winter_consumption = winter_consumption + + selected_farm.save() # Paddock Services def get_paddock_create_context(): @@ -270,4 +299,41 @@ def get_paddock_group_delete_context(request, paddock_group_id): def delete_paddock_group(request, paddock_group_id): paddock_group = _get_paddock_group_by_id(request, paddock_group_id) paddock_group.is_active = False - paddock_group.save() \ No newline at end of file + paddock_group.save() + +# User Authorize Services +def authorize_user(request, user_id): + farm = _get_selected_farm(request) + user = get_object_or_404(User, id=user_id, is_active=True) + user.farms.add(farm) + +def get_deauthorize_user_context(request, user_id): + user = get_object_or_404(User, id=user_id, is_active=True) + + context = {} + context['description'] = f"Remover acesso de {user.short_name}?" + context['positive_url'] = reverse( + 'entities:farm:farm_user_deauthorize', + kwargs={'user_id': user_id} + ) + context['negative_url'] = reverse('entities:farm:farm_home') + + return context + +def deauthorize_user(request, user_id): + farm = _get_selected_farm(request) + user = get_object_or_404(User, id=user_id, is_active=True) + user.farms.remove(farm) + +def get_user_card_context(request): + context = {} + informed_username = request.GET.get('username') + + found_user = User.objects.filter(login=informed_username).first() + + if found_user.farms.contains(_get_selected_farm(request)): + context['already_allowed'] = 'True' + else: + context['found_user'] = found_user + + return context \ No newline at end of file diff --git a/multigranja/apps/entities/static/farm/css/user_authorize.css b/multigranja/apps/entities/static/farm/css/user_authorize.css new file mode 100644 index 0000000..4f9507a --- /dev/null +++ b/multigranja/apps/entities/static/farm/css/user_authorize.css @@ -0,0 +1,120 @@ +.user-authorize-title { + margin-bottom: 20px; + font-size: 28px; + font-weight: 600; +} + +.user-search { + background: #fff; + border: 1px solid #e9ecef; + border-radius: 12px; + padding: 20px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.user-search label { + display: block; + margin-bottom: 8px; + font-weight: 500; +} + +.user-search input { + width: 100%; + padding: 10px 12px; + border: 1px solid #dee2e6; + border-radius: 8px; + margin-bottom: 12px; + transition: border-color 0.2s ease; +} + +.user-search input:focus { + outline: none; + border-color: #198754; +} + +.user-search button { + width: 100%; + border: none; + border-radius: 8px; + padding: 10px; + cursor: pointer; + font-weight: 500; + color: white; + background: #198754; + transition: 0.2s ease; +} + +.user-search button:hover { + background: #157347; +} + +.user-card-container { + margin-top: 20px; + min-height: 150px; + width: 350px; +} + +.user-card { + border: 1px solid #e9ecef; + border-radius: 10px; + padding: 16px; + background: #fafafa; + display: flex; + flex-direction: column; + gap: 10px; +} + +.user-card .name { + margin: 0; + font-size: 16px; + font-weight: 600; +} + +.user-card .name i { + margin-right: 6px; + color: #6c757d; +} + +.user-card .alert { + margin: 0; + font-size: 13px; + color: #6c757d; +} + +.user-card button { + align-self: flex-end; + text-decoration: none; + background: #198754; + color: white; + padding: 8px 14px; + border-radius: 8px; + font-size: 14px; + font-weight: 500; + transition: 0.2s ease; +} + +.user-card button:hover { + background: #157347; +} + +.failed-user-find { + text-align: center; + padding: 15px; + color: #dc3545; + font-size: 14px; +} + +.failed-user-find p { + margin: 0; +} + +.already-allowed-user { + text-align: center; + padding: 15px; + color: #198754; + font-size: 14px; +} + +.already-allowed-user p { + margin: 0; +} \ No newline at end of file diff --git a/multigranja/apps/entities/static/rotation/js/rotation_list.js b/multigranja/apps/entities/static/rotation/js/rotation_list.js index a4247b2..44c4400 100644 --- a/multigranja/apps/entities/static/rotation/js/rotation_list.js +++ b/multigranja/apps/entities/static/rotation/js/rotation_list.js @@ -1,13 +1,16 @@ document.addEventListener("DOMContentLoaded", () => { const container = document.querySelector(".open-rotations-container"); - + if (!container) return; - + let targetScroll = container.scrollLeft; let currentScroll = container.scrollLeft; let isAnimating = false; - + container.addEventListener("wheel", (event) => { + let isMobile = window.innerWidth <= 768; + if (isMobile) return; + event.preventDefault(); const maxScroll = diff --git a/multigranja/apps/entities/templates/batch/batchtype_create.html b/multigranja/apps/entities/templates/batch/batchtype_create.html new file mode 100644 index 0000000..af837e3 --- /dev/null +++ b/multigranja/apps/entities/templates/batch/batchtype_create.html @@ -0,0 +1,11 @@ +{% extends 'layouts/base_modal.html' %} +{% load static %} + +{% block extra_css %} + +{% endblock %} + +{% block content %} + NOVO TIPO DE LOTE
+ {% include 'components/form.html' %} +{% endblock %} \ No newline at end of file diff --git a/multigranja/apps/entities/templates/batch/batchtype_update.html b/multigranja/apps/entities/templates/batch/batchtype_update.html new file mode 100644 index 0000000..2137f73 --- /dev/null +++ b/multigranja/apps/entities/templates/batch/batchtype_update.html @@ -0,0 +1,11 @@ +{% extends 'layouts/base_modal.html' %} +{% load static %} + +{% block extra_css %} + +{% endblock %} + +{% block content %} + EDITAR TIPO DE LOTE
+ {% include 'components/form.html' %} +{% endblock %} \ No newline at end of file diff --git a/multigranja/apps/entities/templates/farm/farm_home.html b/multigranja/apps/entities/templates/farm/farm_home.html index cbde976..66e6c6e 100644 --- a/multigranja/apps/entities/templates/farm/farm_home.html +++ b/multigranja/apps/entities/templates/farm/farm_home.html @@ -1,46 +1,105 @@ {% extends 'layouts/base.html' %} {% load static %} +{% load l10n %} {% block extra_css %} - + {{ block.super }} + {% endblock %} {% block content %} -
-

Fazendas

- + +
+
+

Tipos de lote

+ Tipo +
+ {% for type in batch_types %} +
+
+

{{ type.name }}

+

Multiplicativo de consumo: {{ type.consumption_factor }} ({{ type.consumption_percentage }}%)

+
+
+ Editar + Excluir +
+
+ {% endfor %} +
+ +
+
+

Usuários com acesso

+ Permissão +
+ {% if allowed_users|length < 1 %} +

Seu usuário é o único vinculado a essa fazenda

+ {% endif %} + {% for user in allowed_users %} +
+

{{user.name}}

+ +
+ {% endfor %} +
+ +
+

Suas fazendas

+ {% for farm in farms %} +
+

{{ farm.name }}

+
+

{{ farm.animal_count }} Animais

+

{{ farm.paddock_count }} Piquetes

+
+ +
+ {% endfor %}
- {% if not farms %} -

Nenhuma fazenda encontrado.

- {% else %} - - - - - - - - {% for farm in farms %} - - - - - - - {% endfor %} -
NomeÁrea totalEditarExcluir
{{ farm.name }}{{ farm.total_area }} m2 -
- {% csrf_token %} - -
-
- {% endif %} {% endblock %} \ No newline at end of file diff --git a/multigranja/apps/entities/templates/farm/user-auth-card.html b/multigranja/apps/entities/templates/farm/user-auth-card.html new file mode 100644 index 0000000..b8b3ba5 --- /dev/null +++ b/multigranja/apps/entities/templates/farm/user-auth-card.html @@ -0,0 +1,22 @@ +
+ {% if found_user %} +
+

{{found_user.full_name}}

+

Ao liberar esse usuário ele terá as mesmas permissões que você

+
+ {% csrf_token %} + +
+
+ {% else %} + {% if already_allowed %} +
+

O usuário já possui acesso a essa fazenda

+
+ {% else %} +
+

Não foi possível localizar esse usuário

+
+ {% endif %} + {% endif %} +
\ No newline at end of file diff --git a/multigranja/apps/entities/templates/farm/user_authorize.html b/multigranja/apps/entities/templates/farm/user_authorize.html new file mode 100644 index 0000000..72d5302 --- /dev/null +++ b/multigranja/apps/entities/templates/farm/user_authorize.html @@ -0,0 +1,12 @@ +{% extends 'layouts/base_modal.html' %} +{% load static %} + +{% block content %} +

Autorizar usuário

+ +{% endblock content %} \ No newline at end of file diff --git a/multigranja/apps/entities/templates/layouts/entity_list.html b/multigranja/apps/entities/templates/layouts/entity_list.html index b9c4a03..21b5d94 100644 --- a/multigranja/apps/entities/templates/layouts/entity_list.html +++ b/multigranja/apps/entities/templates/layouts/entity_list.html @@ -27,8 +27,8 @@ + Novo - Novo
{% if not object_list %} diff --git a/multigranja/apps/entities/urls/animal.py b/multigranja/apps/entities/urls/animal.py index 1629998..3d3307a 100644 --- a/multigranja/apps/entities/urls/animal.py +++ b/multigranja/apps/entities/urls/animal.py @@ -15,4 +15,8 @@ urlpatterns = [ path('batch/create/', views.batch_create, name='batch_create'), path('batch/update/', views.batch_update, name='batch_update'), path('batch/delete/', views.batch_delete, name='batch_delete'), + + path('batch/type/create/', views.batchtype_create, name='batchtype_create'), + path('batch/type/update/', views.batchtype_update, name='batchtype_update'), + path('batch/type/delete/', views.batchtype_delete, name='batchtype_delete'), ] \ No newline at end of file diff --git a/multigranja/apps/entities/urls/farm.py b/multigranja/apps/entities/urls/farm.py index 8a90ee3..1bdc766 100644 --- a/multigranja/apps/entities/urls/farm.py +++ b/multigranja/apps/entities/urls/farm.py @@ -5,6 +5,11 @@ from ..views import PaddockListView, PaddockGroupListView app_name = 'farm' urlpatterns = [ + path('usercard/', views.get_user_card, name='get_user_card'), + path('authorize/', views.farm_user_authorize, name='new_authorization'), + path('authorize/', views.farm_user_authorize, name='farm_user_authorize'), + path('deauthorize/', views.farm_user_deauthorize, name='farm_user_deauthorize'), + path('', views.farm_home, name='farm_home'), path('paddock/list/', PaddockListView.as_view(), name='paddock_list'), path('paddock/group/list/', PaddockGroupListView.as_view(), name='paddock_group_list'), @@ -12,6 +17,7 @@ urlpatterns = [ path('create/', views.farm_create, name='farm_create'), path('update/', views.farm_update, name='farm_update'), path('delete/', views.farm_delete, name='farm_delete'), + path('consumption/update', views.consumption_update, name='consumption_update'), path('paddock/create/', views.paddock_create, name='paddock_create'), path('paddock/update/', views.paddock_update, name='paddock_update'), diff --git a/multigranja/apps/entities/views/animal.py b/multigranja/apps/entities/views/animal.py index e6624c8..2487302 100644 --- a/multigranja/apps/entities/views/animal.py +++ b/multigranja/apps/entities/views/animal.py @@ -79,4 +79,40 @@ def batch_delete(request, batch_id): if request.method == 'POST': services.delete_batch(request, batch_id) - return redirect('entities:animal:batch_list') \ No newline at end of file + return redirect('entities:animal:batch_list') + +# Batch Type views +@farm_required +def batchtype_create(request): + context = services.get_batchtype_create_context(request) + if request.method == 'GET': + return render(request, 'batch/batchtype_create.html', context) + + if request.method == 'POST': + if services.create_batchtype(request): + return redirect('entities:farm:farm_home') + context['error'] = "Não foi possível criar o tipo de lote" + return render(request, 'batch/batchtype_create.html', context) + +@farm_required +def batchtype_update(request, batchtype_id): + context = services.get_batchtype_update_context(request, batchtype_id) + if request.method == 'GET': + return render(request, 'batch/batchtype_update.html', context) + + if request.method == 'POST': + if services.update_batchtype(request, batchtype_id): + return redirect('entities:farm:farm_home') + context['error'] = "Não foi possível editar o tipo de lote" + return render(request, 'batch/batchtype_update.html', context) + +@farm_required +def batchtype_delete(request, batchtype_id): + if request.method == 'GET': + context = services.get_batchtype_delete_context(request, batchtype_id) + return render(request, 'components/confirmation_popup.html', context) + + if request.method == 'POST': + services.delete_batchtype(request, batchtype_id) + + return redirect('entities:farm:farm_home') \ No newline at end of file diff --git a/multigranja/apps/entities/views/farm.py b/multigranja/apps/entities/views/farm.py index 37abfb3..cc68054 100644 --- a/multigranja/apps/entities/views/farm.py +++ b/multigranja/apps/entities/views/farm.py @@ -17,7 +17,7 @@ def farm_create(request): if request.method == 'POST': if services.create_farm(request): - return redirect('entities:farm:farm_list') + return redirect('entities:farm:farm_home') context['error'] = "Não foi possível criar a fazenda" return render(request, 'farm/farm_create.html', context) @@ -44,6 +44,11 @@ def farm_delete(request, farm_id): return redirect('entities:farm:farm_create') +def consumption_update(request): + if request.method=='POST': + services.update_consumption(request) + + return redirect('entities:farm:farm_home') # Paddock Views @farm_required @@ -120,4 +125,29 @@ def paddock_group_delete(request, paddock_group_id): if request.method == 'POST': services.delete_paddock_group(request, paddock_group_id) - return redirect('entities:farm:paddock_group_list') \ No newline at end of file + return redirect('entities:farm:paddock_group_list') + +# User Authorization Views +@farm_required +def farm_user_authorize(request, user_id=None): + if request.method == 'GET': + return render(request, 'farm/user_authorize.html') + if request.method == 'POST': + if not user_id: + return redirect('entities:farm:farm_home') + services.authorize_user(request, user_id) + return redirect('entities:farm:farm_home') + +@farm_required +def farm_user_deauthorize(request, user_id): + if request.method == 'GET': + context = services.get_deauthorize_user_context(request, user_id) + return render(request, 'components/confirmation_popup.html', context) + if request.method == 'POST': + services.deauthorize_user(request, user_id) + return redirect('entities:farm:farm_home') + +@farm_required +def get_user_card(request): + context = services.get_user_card_context(request) + return render(request, 'farm/user-auth-card.html', context) \ No newline at end of file