Envio do estado atual do projeto
Projeto ainda em desenvolvimento. Enviado para o repositório para manter estado atual.
This commit is contained in:
1 parent
e539e83c79
commit
24650484f1
94 files changed
+3575
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,18 @@
|
||||
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.rotation import Rotation
|
||||
|
||||
admin.site.register([
|
||||
User,
|
||||
Farm,
|
||||
PaddockGroup,
|
||||
Paddock,
|
||||
Animal,
|
||||
Batch,
|
||||
BatchAnimal,
|
||||
FeedingRecord,
|
||||
Rotation,
|
||||
])
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class EntitiesConfig(AppConfig):
|
||||
name = 'entities'
|
||||
@@ -0,0 +1,4 @@
|
||||
from .animal import *
|
||||
from .farm import *
|
||||
from .rotation import *
|
||||
from .user import *
|
||||
@@ -0,0 +1,45 @@
|
||||
from django import forms
|
||||
from ..models.animal import Batch, Animal
|
||||
|
||||
class AnimalCreateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Animal
|
||||
fields = ['identifier', 'birth', 'weight']
|
||||
|
||||
labels = {
|
||||
'identifier': 'Identificador',
|
||||
'birth': 'Data de Nascimento',
|
||||
'weight': 'Peso (kg)',
|
||||
}
|
||||
|
||||
widgets = {
|
||||
'birth': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
|
||||
'weight': forms.NumberInput(attrs={'step': '0.01'})
|
||||
}
|
||||
|
||||
class AnimalEditForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Animal
|
||||
fields = ['identifier', 'weight']
|
||||
|
||||
labels = {
|
||||
'identifier': 'Identificador',
|
||||
'weight': 'Peso (kg)',
|
||||
}
|
||||
|
||||
widgets = {
|
||||
'weight': forms.NumberInput(attrs={'step': '0.01'})
|
||||
}
|
||||
|
||||
class BatchForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Batch
|
||||
fields = ['identifier', 'animal_category', 'batch_type', 'animals']
|
||||
|
||||
labels = {
|
||||
'identifier': 'Identificador',
|
||||
'animal_category': 'Categoria animal',
|
||||
'batch_type': 'Tipo',
|
||||
'animals': 'Animais',
|
||||
}
|
||||
BatchCreateForm = BatchEditForm = BatchForm # Alias to BatchForm since its implementations are the same
|
||||
@@ -0,0 +1,37 @@
|
||||
from django import forms
|
||||
from ..models import Farm, PaddockGroup, Paddock
|
||||
|
||||
class FarmForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Farm
|
||||
fields = ['name', 'total_area']
|
||||
|
||||
labels = {
|
||||
'name': 'Nome',
|
||||
'total_area': 'Área total',
|
||||
}
|
||||
FarmCreateForm = FarmEditForm = FarmForm # Alias since its implementations are the same
|
||||
|
||||
class PaddockGroupForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = PaddockGroup
|
||||
fields = ['identifier', 'description']
|
||||
|
||||
labels = {
|
||||
'identifier': 'Identificador',
|
||||
'description': 'Descrição',
|
||||
}
|
||||
PaddockGroupCreateForm = PaddockGroupEditForm = PaddockGroupForm
|
||||
|
||||
class PaddockForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Paddock
|
||||
fields = ['paddock_number', 'area', 'load_capacity', 'paddock_group']
|
||||
|
||||
labels = {
|
||||
'paddock_number': 'Número do piquete',
|
||||
'area': 'Área',
|
||||
'load_capacity': 'Lotação máxima',
|
||||
'paddock_group': 'Bloco',
|
||||
}
|
||||
PaddockCreateForm = PaddockEditForm = PaddockForm
|
||||
@@ -0,0 +1,23 @@
|
||||
from django import forms
|
||||
from ..models import Rotation
|
||||
|
||||
class RotationEntryForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Rotation
|
||||
fields = ['batch', 'entry_height', 'paddock']
|
||||
|
||||
labels = {
|
||||
'batch': 'Lote de animais',
|
||||
'entry_height': 'Altura do pasto',
|
||||
'paddock': 'Piquete',
|
||||
}
|
||||
|
||||
class RotationExitForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Rotation
|
||||
fields = ['batch', 'exit_height']
|
||||
|
||||
labels = {
|
||||
'batch': 'Lote de animais',
|
||||
'exit_height': 'Altura do pasto',
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
from django import forms
|
||||
from ..models import User
|
||||
|
||||
class UserCreateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['name', 'login', 'email',]
|
||||
|
||||
labels = {
|
||||
'name': 'Nome',
|
||||
'login': 'Login',
|
||||
'email': 'E-mail',
|
||||
}
|
||||
|
||||
widgets = {
|
||||
'email': forms.EmailInput(),
|
||||
}
|
||||
|
||||
class UserEditForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['name', 'email',]
|
||||
|
||||
labels = {
|
||||
'name': 'Nome',
|
||||
'email': 'E-mail',
|
||||
}
|
||||
|
||||
widgets = {
|
||||
'email': forms.EmailInput(),
|
||||
}
|
||||
|
||||
class UserLoginForm(forms.Form):
|
||||
login = forms.CharField(max_length=45, label='Usuário')
|
||||
password = forms.CharField(widget=forms.PasswordInput, label='Senha')
|
||||
@@ -0,0 +1,145 @@
|
||||
# Generated by Django 6.0.2 on 2026-02-28 19:45
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import entities.models.user
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Animal',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('identifier', models.CharField(max_length=45)),
|
||||
('birth', models.DateField()),
|
||||
('weight', models.DecimalField(decimal_places=2, max_digits=10)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Batch',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('identifier', models.CharField(max_length=45)),
|
||||
('animal_category', models.CharField(blank=True, max_length=45, null=True)),
|
||||
('batch_type', models.CharField(blank=True, max_length=45, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Farm',
|
||||
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)),
|
||||
('total_area', models.IntegerField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PaddockGroup',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('identifier', models.CharField(max_length=45)),
|
||||
('description', models.TextField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BatchAnimal',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('animal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='entities.animal')),
|
||||
('batch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='entities.batch')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='batch',
|
||||
name='animals',
|
||||
field=models.ManyToManyField(related_name='batches', through='entities.BatchAnimal', to='entities.animal'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='animal',
|
||||
name='farm',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='animals', to='entities.farm'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='User',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('name', models.CharField(max_length=45)),
|
||||
('login', models.CharField(max_length=45, unique=True)),
|
||||
('email', models.EmailField(max_length=254, unique=True)),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('is_superuser', models.BooleanField(default=False)),
|
||||
('is_staff', models.BooleanField(default=False)),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('last_login', models.DateTimeField(blank=True, null=True)),
|
||||
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
|
||||
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
|
||||
('farms', models.ManyToManyField(related_name='users', to='entities.farm')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'User',
|
||||
'verbose_name_plural': 'Users',
|
||||
},
|
||||
managers=[
|
||||
('objects', entities.models.user.CustomUserManager()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Paddock',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('paddock_number', models.IntegerField()),
|
||||
('area', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
|
||||
('load_capacity', models.IntegerField(blank=True, null=True)),
|
||||
('occupied', models.BooleanField(default=False)),
|
||||
('farm', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='paddocks', to='entities.farm')),
|
||||
('paddock_group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='paddocks', to='entities.paddockgroup')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Rotation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('is_active', models.BooleanField(default=True)),
|
||||
('entry_date', models.DateTimeField()),
|
||||
('entry_height', models.DecimalField(decimal_places=2, max_digits=10)),
|
||||
('exit_date', models.DateTimeField(blank=True, null=True)),
|
||||
('exit_height', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
|
||||
('animal_count', models.IntegerField()),
|
||||
('livestock_unit', models.DecimalField(decimal_places=2, max_digits=10)),
|
||||
('batch', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rotations', to='entities.batch')),
|
||||
('paddock', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rotations', to='entities.paddock')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='FeedingRecord',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('feed_quantity', models.DecimalField(decimal_places=2, max_digits=10)),
|
||||
('animal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feeding_record', to='entities.animal')),
|
||||
('rotation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feeding_record', to='entities.rotation')),
|
||||
],
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='batchanimal',
|
||||
constraint=models.UniqueConstraint(condition=models.Q(('is_active', True)), fields=('animal',), name='unique_active_animal_batch_link'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='animal',
|
||||
constraint=models.UniqueConstraint(condition=models.Q(('is_active', True)), fields=('identifier', 'farm'), name='unique_active_farm_animal'),
|
||||
),
|
||||
]
|
||||
Whitespace-only changes.
@@ -0,0 +1,4 @@
|
||||
from .user import *
|
||||
from .farm import *
|
||||
from .animal import *
|
||||
from .rotation import *
|
||||
@@ -0,0 +1,103 @@
|
||||
from datetime import date
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
|
||||
class Animal(models.Model):
|
||||
is_active = models.BooleanField(default=True)
|
||||
identifier = models.CharField(max_length=45)
|
||||
birth = models.DateField()
|
||||
weight = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
farm = models.ForeignKey('entities.Farm', on_delete=models.CASCADE, related_name='animals')
|
||||
|
||||
def __str__(self):
|
||||
return f"Animal {self.identifier} - birth {self.birth} - weight {self.weight} - farm {self.farm} - is_active {self.is_active}"
|
||||
|
||||
@property
|
||||
def age(self):
|
||||
today = date.today()
|
||||
birth_date = self.birth
|
||||
|
||||
years = today.year - birth_date.year
|
||||
months = today.month - birth_date.month
|
||||
|
||||
if today.day < birth_date.day:
|
||||
months -= 1
|
||||
|
||||
if months < 0:
|
||||
months += 12
|
||||
years -= 1
|
||||
|
||||
if years > 0 and months > 0:
|
||||
return f"{years} anos e {months} meses" # YYYY years and MM months
|
||||
elif years > 0:
|
||||
return f"{years} anos" # YYYY years
|
||||
elif months > 0:
|
||||
return f"{months} meses" # MM months
|
||||
else:
|
||||
return "Menos de um mês" # Less than a month
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['identifier', 'farm'],
|
||||
condition=Q(is_active=True),
|
||||
name='unique_active_farm_animal'
|
||||
)
|
||||
]
|
||||
|
||||
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)
|
||||
animals = models.ManyToManyField(Animal, through='BatchAnimal', related_name='batches')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.__original_is_active = self.is_active
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
is_active_changed = self.__original_is_active != self.is_active
|
||||
|
||||
if is_active_changed:
|
||||
if self.is_active is False:
|
||||
self.batchanimal_set.all().update(is_active=False)
|
||||
|
||||
elif self.is_active is True:
|
||||
self.batchanimal_set.all().update(is_active=True)
|
||||
|
||||
self.__original_is_active = self.is_active
|
||||
|
||||
def __str__(self):
|
||||
return self.identifier
|
||||
|
||||
class BatchAnimal(models.Model):
|
||||
animal = models.ForeignKey(Animal, on_delete=models.CASCADE)
|
||||
batch = models.ForeignKey(Batch, on_delete=models.CASCADE)
|
||||
|
||||
is_active = models.BooleanField(default=True)
|
||||
|
||||
# When reactivating a batch, all its animals must not belong to any other active batch.
|
||||
# Otherwise, the database will raise an IntegrityError due to the unique constraint on active animals.
|
||||
# This is a rare use case, but any future code regarding it must implement error treatment
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['animal'],
|
||||
condition=Q(is_active=True),
|
||||
name='unique_active_animal_batch_link'
|
||||
)
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.animal.identifier} in {self.batch.identifier}"
|
||||
|
||||
class FeedingRecord(models.Model):
|
||||
animal = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name='feeding_record')
|
||||
rotation = models.ForeignKey('entities.Rotation', on_delete=models.CASCADE, related_name='feeding_record')
|
||||
feed_quantity = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
|
||||
def __str__(self):
|
||||
return f"Consumo de {self.animal.identifier} - {self.feed_quantity} kg"
|
||||
@@ -0,0 +1,30 @@
|
||||
from django.db import models
|
||||
|
||||
class Farm(models.Model):
|
||||
is_active = models.BooleanField(default=True)
|
||||
name = models.CharField(max_length=45)
|
||||
total_area = models.IntegerField(null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class PaddockGroup(models.Model):
|
||||
is_active = models.BooleanField(default=True)
|
||||
identifier = models.CharField(max_length=45)
|
||||
description = models.TextField(null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Bloco {self.id}"
|
||||
|
||||
|
||||
class Paddock(models.Model):
|
||||
is_active = models.BooleanField(default=True)
|
||||
paddock_number = models.IntegerField()
|
||||
area = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
|
||||
load_capacity = models.IntegerField(null=True, blank=True)
|
||||
occupied = models.BooleanField(default=False)
|
||||
farm = models.ForeignKey(Farm, on_delete=models.CASCADE, related_name='paddocks')
|
||||
paddock_group = models.ForeignKey(PaddockGroup, on_delete=models.SET_NULL, related_name='paddocks', null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"Piquete {self.paddock_number} - Bloco {self.paddock_group.id}"
|
||||
@@ -0,0 +1,15 @@
|
||||
from django.db import models
|
||||
|
||||
class Rotation(models.Model):
|
||||
is_active = models.BooleanField(default=True)
|
||||
entry_date = models.DateTimeField()
|
||||
entry_height = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
exit_date = models.DateTimeField(null=True, blank=True)
|
||||
exit_height = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
|
||||
animal_count = models.IntegerField()
|
||||
livestock_unit = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
batch = models.ForeignKey('entities.Batch', on_delete=models.SET_NULL, related_name='rotations', null=True, blank=True)
|
||||
paddock = models.ForeignKey('entities.Paddock', on_delete=models.CASCADE, related_name='rotations')
|
||||
|
||||
def __str__(self):
|
||||
return f"Movimentação {self.id} - Lote {self.batch.identifier}"
|
||||
@@ -0,0 +1,63 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import UserManager, AbstractBaseUser, PermissionsMixin
|
||||
from django.utils import timezone
|
||||
|
||||
class CustomUserManager(UserManager):
|
||||
def _create_user(self, name, login, email, password, **extra_fields):
|
||||
if not login:
|
||||
raise ValueError("Information provided is not a valid login")
|
||||
if not email:
|
||||
raise ValueError("You must inform an e-mail adress")
|
||||
|
||||
email = self.normalize_email(email)
|
||||
user = self.model(
|
||||
name = name,
|
||||
login = login,
|
||||
email = email,
|
||||
**extra_fields)
|
||||
user.set_password(password)
|
||||
user.save(using=self.db)
|
||||
|
||||
return user
|
||||
|
||||
def create_user(self, name=None, login=None, email=None, password=None, **extra_fields):
|
||||
extra_fields.setdefault('is_staff', False)
|
||||
extra_fields.setdefault('is_superuser', False)
|
||||
return self._create_user(name, login, email, password, **extra_fields)
|
||||
|
||||
def create_superuser(self, name=None, login=None, email=None, password=None, **extra_fields):
|
||||
extra_fields.setdefault('is_staff', True)
|
||||
extra_fields.setdefault('is_superuser', True)
|
||||
return self._create_user(name, login, email, password, **extra_fields)
|
||||
|
||||
class User(AbstractBaseUser, PermissionsMixin):
|
||||
name = models.CharField(max_length=45)
|
||||
login = models.CharField(max_length=45, unique=True)
|
||||
email = models.EmailField(unique=True)
|
||||
|
||||
farms = models.ManyToManyField('entities.Farm', related_name='users')
|
||||
|
||||
is_active = models.BooleanField(default=True)
|
||||
is_superuser = models.BooleanField(default=False)
|
||||
is_staff = models.BooleanField(default=False)
|
||||
|
||||
date_joined = models.DateTimeField(default=timezone.now)
|
||||
last_login = models.DateTimeField(blank=True, null=True)
|
||||
|
||||
objects = CustomUserManager()
|
||||
|
||||
USERNAME_FIELD = 'login'
|
||||
EMAIL_FIELD = 'email'
|
||||
REQUIRED_FIELDS = ['name', 'email']
|
||||
|
||||
class Meta:
|
||||
verbose_name = 'User'
|
||||
verbose_name_plural = 'Users'
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def short_name(self):
|
||||
return self.name.split(' ')[0] or self.email.split('@')[0]
|
||||
Whitespace-only changes.
@@ -0,0 +1,227 @@
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.db.models import Prefetch
|
||||
|
||||
from ..models import Animal, Batch
|
||||
from ..forms import AnimalCreateForm, AnimalEditForm, BatchForm
|
||||
from entities.models import Farm
|
||||
|
||||
|
||||
def get_selected_farm(request):
|
||||
return Farm.objects.get(id=request.session['selected_farm_id'])
|
||||
|
||||
|
||||
# Animal Services
|
||||
def get_animal_home_context(request):
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Animais'
|
||||
context['farm'] = selected_farm
|
||||
|
||||
animals = Animal.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
filter_query = request.GET.get('animal_search')
|
||||
|
||||
if filter_query:
|
||||
context['filter_query'] = filter_query
|
||||
animals = animals.filter(
|
||||
identifier__icontains=filter_query
|
||||
)
|
||||
|
||||
context['animals'] = animals
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_animal_new_context():
|
||||
form = AnimalCreateForm()
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Novo animal'
|
||||
context['form'] = form
|
||||
context['action_url'] = reverse('entities:animal:animal_new')
|
||||
context['return_url'] = reverse('entities:animal:animal_home')
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def create_animal(request):
|
||||
form = AnimalCreateForm(request.POST)
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
if form.is_valid():
|
||||
animal = form.save(commit=False)
|
||||
animal.farm = selected_farm
|
||||
animal.save()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def update_animal(request, animal_id):
|
||||
farm_id = request.session['selected_farm_id']
|
||||
animal = get_object_or_404(Animal, pk=animal_id, farm_id=farm_id)
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Editar animal'
|
||||
context['action_url'] = reverse(
|
||||
'entities:animal:animal_update',
|
||||
kwargs={'animal_id': animal.pk}
|
||||
)
|
||||
context['return_url'] = reverse('entities:animal:animal_home')
|
||||
|
||||
if request.method == 'GET':
|
||||
form = AnimalEditForm(instance=animal)
|
||||
|
||||
elif request.method == 'POST':
|
||||
form = AnimalEditForm(request.POST, instance=animal)
|
||||
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return {'redirect': 'entities:animal:animal_home'}
|
||||
|
||||
context['form'] = form
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def delete_animal(request, animal_id):
|
||||
farm_id = request.session['selected_farm_id']
|
||||
animal = get_object_or_404(Animal, pk=animal_id, farm_id=farm_id)
|
||||
animal.is_active = False
|
||||
animal.save()
|
||||
|
||||
|
||||
# Batch Services
|
||||
|
||||
def get_batch_home_context(request):
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Lotes'
|
||||
context['farm'] = selected_farm
|
||||
|
||||
all_batches = Batch.objects.filter(
|
||||
batchanimal__animal__farm=selected_farm,
|
||||
is_active=True
|
||||
).distinct().prefetch_related(
|
||||
Prefetch('animals', queryset=Animal.objects.filter(is_active=True))
|
||||
)
|
||||
|
||||
filter_query = request.GET.get('batch_search')
|
||||
|
||||
if filter_query:
|
||||
context['filter_query'] = filter_query
|
||||
all_batches = all_batches.filter(
|
||||
identifier__icontains=filter_query
|
||||
)
|
||||
|
||||
context['batches'] = all_batches
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def create_batch(request):
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
if request.method == 'GET':
|
||||
form = BatchForm()
|
||||
form.fields['animals'].queryset = Animal.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context = {
|
||||
'title': 'Novo Lote',
|
||||
'form': form,
|
||||
'action_url': reverse('entities:animal:batch_new'),
|
||||
'return_url': reverse('entities:animal:batch_home')
|
||||
}
|
||||
|
||||
return {'context': context}
|
||||
|
||||
elif request.method == 'POST':
|
||||
form = BatchForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
batch = form.save(commit=False)
|
||||
batch.save()
|
||||
form.save_m2m()
|
||||
|
||||
return {'redirect': 'entities:animal:batch_home'}
|
||||
|
||||
form.fields['animals'].queryset = Animal.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context = {
|
||||
'title': 'Novo Lote',
|
||||
'form': form,
|
||||
'action_url': reverse('entities:animal:batch_new'),
|
||||
'return_url': reverse('entities:animal:batch_home')
|
||||
}
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def update_batch(request, batch_id):
|
||||
batch_old = get_object_or_404(Batch, pk=batch_id, is_active=True)
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
context = {
|
||||
'title': f'Editar Lote {batch_old.identifier}',
|
||||
'return_url': reverse('entities:animal:batch_home')
|
||||
}
|
||||
|
||||
if request.method == 'GET':
|
||||
form = BatchForm(instance=batch_old)
|
||||
|
||||
form.fields['animals'].queryset = Animal.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context['action_url'] = reverse(
|
||||
'entities:animal:batch_update',
|
||||
kwargs={'batch_id': batch_old.pk}
|
||||
)
|
||||
|
||||
elif request.method == 'POST':
|
||||
form = BatchForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
batch_new = form.save(commit=False)
|
||||
batch_new.is_active = True
|
||||
|
||||
batch_old.is_active = False
|
||||
batch_old.save()
|
||||
|
||||
batch_new.save()
|
||||
form.save_m2m()
|
||||
|
||||
return {'redirect': 'entities:animal:batch_home'}
|
||||
|
||||
form.fields['animals'].queryset = Animal.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context['action_url'] = reverse(
|
||||
'entities:animal:batch_update',
|
||||
kwargs={'batch_id': batch_old.pk}
|
||||
)
|
||||
|
||||
context['form'] = form
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def delete_batch(batch_id):
|
||||
batch = get_object_or_404(Batch, pk=batch_id, is_active=True)
|
||||
batch.is_active = False
|
||||
batch.save()
|
||||
@@ -0,0 +1,293 @@
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.db.models import Prefetch
|
||||
|
||||
from ..models import Farm, Paddock, PaddockGroup
|
||||
from ..forms import FarmCreateForm, FarmEditForm, PaddockCreateForm, PaddockEditForm, PaddockGroupCreateForm, PaddockGroupEditForm
|
||||
|
||||
|
||||
def get_selected_farm(request):
|
||||
return Farm.objects.get(id=request.session['selected_farm_id'])
|
||||
|
||||
|
||||
# Farm Services
|
||||
def get_farm_home_context(request):
|
||||
authenticated_user = request.user
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Fazenda'
|
||||
|
||||
farms = Farm.objects.filter(
|
||||
users=authenticated_user, # Verificar se da para deixar apenas = ou deve usar um is in ou algo do tipo
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context['farms'] = farms
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def get_farm_new_context():
|
||||
form = FarmCreateForm()
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Nova fazenda'
|
||||
context['form'] = form
|
||||
context['action_url'] = reverse('entities:farm:farm_new')
|
||||
context['return_url'] = reverse('entities:farm:farm_home')
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def create_farm(request):
|
||||
form = FarmCreateForm(request.POST)
|
||||
authenticated_user = request.user
|
||||
|
||||
if form.is_valid():
|
||||
farm = form.save()
|
||||
farm.users.add(authenticated_user)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def update_farm(request, farm_id):
|
||||
farm = get_object_or_404(Farm, pk=farm_id, is_active=True)
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Editar fazenda'
|
||||
context['action_url'] = reverse(
|
||||
'entities:farm:farm_update',
|
||||
kwargs={'farm_id': farm.pk}
|
||||
)
|
||||
context['return_url'] = reverse('entities:farm:farm_home')
|
||||
|
||||
if request.method == 'GET':
|
||||
form = FarmEditForm(instance=farm)
|
||||
|
||||
elif request.method == 'POST':
|
||||
form = FarmEditForm(request.POST, instance=farm)
|
||||
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return {'redirect': 'entities:farm:farm_home'}
|
||||
|
||||
context['form'] = form
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def delete_farm(farm_id):
|
||||
farm = get_object_or_404(Farm, pk=farm_id, is_active=True)
|
||||
farm.is_active = False
|
||||
farm.save()
|
||||
|
||||
|
||||
# Paddock Services
|
||||
|
||||
def get_paddock_home_context(request):
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Piquete'
|
||||
context['farm'] = selected_farm
|
||||
|
||||
all_paddocks = Paddock.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
filter_query = request.GET.get('paddock_search')
|
||||
|
||||
if filter_query:
|
||||
context['filter_query'] = filter_query
|
||||
all_paddocks = all_paddocks.filter(
|
||||
identifier__icontains=filter_query
|
||||
)
|
||||
|
||||
context['paddocks'] = all_paddocks
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def create_paddock(request):
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
if request.method == 'GET':
|
||||
form = PaddockCreateForm()
|
||||
|
||||
context = {
|
||||
'title': 'Novo Piquete',
|
||||
'form': form,
|
||||
'action_url': reverse('entities:farm:paddock_new'),
|
||||
'return_url': reverse('entities:farm:paddock_home')
|
||||
}
|
||||
|
||||
return {'context': context}
|
||||
|
||||
elif request.method == 'POST':
|
||||
form = PaddockCreateForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
paddock = form.save(commit=False)
|
||||
paddock.farm = selected_farm
|
||||
paddock.save()
|
||||
|
||||
return {'redirect': 'entities:farm:paddock_home'}
|
||||
|
||||
context = {
|
||||
'title': 'Novo Piquete',
|
||||
'form': form,
|
||||
'action_url': reverse('entities:farm:paddock_new'),
|
||||
'return_url': reverse('entities:farm:paddock_home')
|
||||
}
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def update_paddock(request, paddock_id):
|
||||
farm_id = request.session['selected_farm_id']
|
||||
paddock = get_object_or_404(Paddock, pk=paddock_id, farm_id=farm_id, is_active=True)
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Editar piquete'
|
||||
context['action_url'] = reverse(
|
||||
'entities:farm:paddock_update',
|
||||
kwargs={'paddock_id': paddock.pk}
|
||||
)
|
||||
context['return_url'] = reverse('entities:farm:paddock_home')
|
||||
|
||||
if request.method == 'GET':
|
||||
form = PaddockEditForm(instance=paddock)
|
||||
|
||||
elif request.method == 'POST':
|
||||
form = PaddockEditForm(request.POST, instance=paddock)
|
||||
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return {'redirect': 'entities:farm:paddock_home'}
|
||||
|
||||
context['form'] = form
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def delete_paddock(paddock_id):
|
||||
paddock = get_object_or_404(Paddock, pk=paddock_id, is_active=True)
|
||||
paddock.is_active = False
|
||||
paddock.save()
|
||||
|
||||
|
||||
# Paddock Group Services
|
||||
|
||||
def get_paddock_group_home_context(request):
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
context = {}
|
||||
context['title'] = 'Blocos'
|
||||
context['farm'] = selected_farm
|
||||
|
||||
all_paddock_groups = PaddockGroup.objects.filter(
|
||||
paddocks__farm=selected_farm,
|
||||
is_active=True
|
||||
).distinct().prefetch_related(
|
||||
Prefetch('paddocks', queryset=Paddock.objects.filter(is_active=True))
|
||||
)
|
||||
|
||||
filter_query = request.GET.get('paddock_group_search')
|
||||
|
||||
if filter_query:
|
||||
context['filter_query'] = filter_query
|
||||
all_paddock_groups = all_paddock_groups.filter(
|
||||
identifier__icontains=filter_query
|
||||
)
|
||||
|
||||
context['paddock_groups'] = all_paddock_groups
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def create_paddock_group(request):
|
||||
selected_farm = get_selected_farm(request)
|
||||
|
||||
if request.method == 'GET':
|
||||
form = PaddockGroupCreateForm()
|
||||
form.fields['paddocks'].queryset = Paddock.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = PaddockGroupCreateForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
paddock_group = form.save(commit=False)
|
||||
paddock_group.save()
|
||||
|
||||
return {'redirect': 'entities:farm:paddock_group_home'}
|
||||
|
||||
form.fields['paddocks'].queryset = Paddock.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context = {
|
||||
'title': 'Novo Bloco',
|
||||
'form': form,
|
||||
'action_url': reverse('entities:farm:paddock_group_new'),
|
||||
'return_url': reverse('entities:farm:paddock_group_home')
|
||||
}
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def update_paddock_group(request, paddock_group_id):
|
||||
selected_farm = get_selected_farm(request)
|
||||
paddock_group = get_object_or_404(PaddockGroup, pk=paddock_group_id, is_active=True)
|
||||
|
||||
context = {
|
||||
'title': f'Editar Lote {paddock_group.identifier}',
|
||||
'return_url': reverse('entities:farm:paddock_group_home')
|
||||
}
|
||||
|
||||
if request.method == 'GET':
|
||||
form = PaddockGroupEditForm(instance=paddock_group)
|
||||
|
||||
form.fields['paddocks'].queryset = Paddock.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context['action_url'] = reverse(
|
||||
'entities:farm:paddock_group_update',
|
||||
kwargs={'paddock_group_id': paddock_group.pk}
|
||||
)
|
||||
|
||||
elif request.method == 'POST':
|
||||
form = PaddockGroupEditForm(request.POST, instance=paddock_group)
|
||||
|
||||
if form.is_valid():
|
||||
paddock_group = form.save()
|
||||
paddock_group.save()
|
||||
|
||||
return {'redirect': 'entities:farm:paddock_group_home'}
|
||||
|
||||
form.fields['paddocks'].queryset = Paddock.objects.filter(
|
||||
farm=selected_farm,
|
||||
is_active=True
|
||||
)
|
||||
|
||||
context['action_url'] = reverse(
|
||||
'entities:farm:paddock_group_update',
|
||||
kwargs={'paddock_group_id': paddock_group.pk}
|
||||
)
|
||||
|
||||
context['form'] = form
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def delete_paddock_group(paddock_group_id):
|
||||
paddock_group = get_object_or_404(PaddockGroup, pk=paddock_group_id, is_active=True)
|
||||
paddock_group.is_active = False
|
||||
paddock_group.save()
|
||||
@@ -0,0 +1,88 @@
|
||||
from django.shortcuts import redirect
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.db.models import Count
|
||||
|
||||
from ..forms import UserLoginForm
|
||||
|
||||
|
||||
def user_profile(request): # TO DO
|
||||
...
|
||||
|
||||
|
||||
def user_login(request):
|
||||
if request.user.is_authenticated:
|
||||
return {'redirect': 'entities:user:farm_select'}
|
||||
|
||||
context = {}
|
||||
context['fail_login'] = False
|
||||
form = UserLoginForm()
|
||||
|
||||
if request.method == "POST":
|
||||
form = UserLoginForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
username = form.cleaned_data['login']
|
||||
password = form.cleaned_data['password']
|
||||
user = authenticate(request, username=username, password=password)
|
||||
|
||||
if user is not None:
|
||||
login(request, user)
|
||||
context['title'] = 'Fazendas'
|
||||
return {'redirect': 'entities:user:farm_select'}
|
||||
else:
|
||||
context['fail_login'] = True
|
||||
else:
|
||||
context['fail_login'] = True
|
||||
|
||||
context['form'] = form
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def user_logout(request):
|
||||
logout(request)
|
||||
return redirect('entities:user:user_login')
|
||||
|
||||
|
||||
def user_signin(request): # TO DO
|
||||
...
|
||||
|
||||
|
||||
def farm_select(request):
|
||||
if 'selected_farm_id' in request.session:
|
||||
return {'redirect': 'entities:farm:farm_home'}
|
||||
|
||||
farms_query = request.user.farms.filter(is_active=True)
|
||||
farms_with_counts = farms_query.annotate(
|
||||
total_animals=Count('animals'),
|
||||
total_paddocks=Count('paddocks')
|
||||
)
|
||||
|
||||
context = {
|
||||
'farms': farms_with_counts
|
||||
}
|
||||
|
||||
return {'context': context}
|
||||
|
||||
|
||||
def farm_set(request, farm_id=None):
|
||||
# Allows setting the selected farm either via URL parameter or POST data
|
||||
farm_id = farm_id or request.POST.get("farm_id")
|
||||
next_url = request.POST.get("next")
|
||||
|
||||
if not farm_id:
|
||||
return redirect('entities:user:farm_select')
|
||||
|
||||
try:
|
||||
farm = request.user.farms.get(id=farm_id)
|
||||
request.session['selected_farm_id'] = farm.id
|
||||
|
||||
return redirect(next_url or 'entities:farm:farm_home')
|
||||
|
||||
except request.user.farms.model.DoesNotExist:
|
||||
return redirect('entities:user:farm_select')
|
||||
|
||||
def farm_deselect(request):
|
||||
if 'selected_farm_id' in request.session:
|
||||
del request.session['selected_farm_id']
|
||||
|
||||
return redirect('entities:user:farm_select')
|
||||
@@ -0,0 +1,152 @@
|
||||
/* ===== PAGE HEADER ===== */
|
||||
.animal_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-md);
|
||||
margin-bottom: var(--space-lg);
|
||||
}
|
||||
|
||||
.animal_title h1 {
|
||||
font-size: var(--font-xl);
|
||||
color: var(--color-text-dark);
|
||||
margin: 0;
|
||||
margin-right: var(--space-lg);
|
||||
}
|
||||
|
||||
/* ===== SEARCH FORM ===== */
|
||||
.form_animal_search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.form_animal_search label {
|
||||
font-size: var(--font-sm);
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
/* Input com altura igual ao botão */
|
||||
.form_animal_search input {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
font-size: var(--font-sm);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--border-radius-sm);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form_animal_search input:focus {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
/* Botão buscar */
|
||||
.form_animal_search button {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
border: none;
|
||||
border-radius: var(--border-radius-sm);
|
||||
background: var(--color-primary);
|
||||
color: var(--color-text-light);
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.form_animal_search button:hover {
|
||||
background: var(--color-secondary);
|
||||
}
|
||||
|
||||
/* ===== CLEAR FILTER ===== */
|
||||
.btn-clear-filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
background: var(--color-danger-light);
|
||||
color: var(--color-danger);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: var(--font-sm);
|
||||
}
|
||||
|
||||
.btn-clear-filter:hover {
|
||||
background: var(--color-danger);
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
|
||||
/* ===== NEW BUTTON ===== */
|
||||
.animal_title > a {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-md);
|
||||
background: var(--color-success);
|
||||
color: var(--color-text-light);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: var(--font-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.animal_title > a:hover {
|
||||
background: var(--color-success);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* ===== TABLE ===== */
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: var(--color-bg-white);
|
||||
border-radius: var(--border-radius-sm);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
table th {
|
||||
text-align: left;
|
||||
padding: var(--space-sm);
|
||||
font-size: var(--font-sm);
|
||||
background: var(--color-bg-dark);
|
||||
color: var(--color-text-light);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
table td {
|
||||
padding: var(--space-sm);
|
||||
font-size: var(--font-md);
|
||||
border-bottom: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
|
||||
table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
table tbody tr:hover {
|
||||
background: var(--color-bg-light);
|
||||
}
|
||||
|
||||
/* ===== ACTION ICONS ===== */
|
||||
table a {
|
||||
color: var(--color-primary);
|
||||
transition: color var(--transition-speed);
|
||||
}
|
||||
|
||||
table a:hover {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
/* DELETE BUTTON */
|
||||
.btn-icon-trash {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--color-danger);
|
||||
cursor: pointer;
|
||||
transition: color var(--transition-speed);
|
||||
}
|
||||
|
||||
.btn-icon-trash:hover {
|
||||
color: var(--color-danger);
|
||||
opacity: 0.7;
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/* ===== PAGE HEADER ===== */
|
||||
.batch_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-md);
|
||||
margin-bottom: var(--space-lg);
|
||||
}
|
||||
|
||||
.batch_title h1 {
|
||||
font-size: var(--font-xl);
|
||||
color: var(--color-text-dark);
|
||||
margin: 0;
|
||||
margin-right: var(--space-lg);
|
||||
}
|
||||
|
||||
/* ===== SEARCH FORM ===== */
|
||||
.form_batch_search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.form_batch_search label {
|
||||
font-size: var(--font-sm);
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.form_batch_search input {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
font-size: var(--font-sm);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--border-radius-sm);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form_batch_search input:focus {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.form_batch_search button {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
border: none;
|
||||
border-radius: var(--border-radius-sm);
|
||||
background: var(--color-primary);
|
||||
color: var(--color-text-light);
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.form_batch_search button:hover {
|
||||
background: var(--color-secondary);
|
||||
}
|
||||
|
||||
/* ===== CLEAR FILTER ===== */
|
||||
.btn-clear-filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
background: var(--color-danger-light);
|
||||
color: var(--color-danger);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: var(--font-sm);
|
||||
}
|
||||
|
||||
.btn-clear-filter:hover {
|
||||
background: var(--color-danger);
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
|
||||
/* ===== NEW BUTTON ===== */
|
||||
.batch_title > a {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-md);
|
||||
background: var(--color-success);
|
||||
color: var(--color-text-light);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: var(--font-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.batch_title > a:hover {
|
||||
background: var(--color-success);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* ===== TABLE ===== */
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: var(--color-bg-white);
|
||||
border-radius: var(--border-radius-sm);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
table th {
|
||||
text-align: left;
|
||||
padding: var(--space-sm);
|
||||
font-size: var(--font-sm);
|
||||
background: var(--color-bg-dark);
|
||||
color: var(--color-text-light);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
table td {
|
||||
padding: var(--space-sm);
|
||||
font-size: var(--font-md);
|
||||
border-bottom: 1px solid var(--color-border-subtle);
|
||||
}
|
||||
|
||||
table tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
table tbody tr:hover {
|
||||
background: var(--color-bg-light);
|
||||
}
|
||||
|
||||
/* ===== ACTION ICONS ===== */
|
||||
table a {
|
||||
color: var(--color-primary);
|
||||
transition: color var(--transition-speed);
|
||||
}
|
||||
|
||||
table a:hover {
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
/* DELETE BUTTON */
|
||||
.btn-icon-trash {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--color-danger);
|
||||
cursor: pointer;
|
||||
transition: color var(--transition-speed);
|
||||
}
|
||||
|
||||
.btn-icon-trash:hover {
|
||||
color: var(--color-danger);
|
||||
opacity: 0.7;
|
||||
}
|
||||
Whitespace-only changes.
@@ -0,0 +1,94 @@
|
||||
/* ===== PAGE HEADER ===== */
|
||||
.paddock_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-md);
|
||||
margin-bottom: var(--space-lg);
|
||||
}
|
||||
|
||||
.paddock_title h1 {
|
||||
font-size: var(--font-xl);
|
||||
color: var(--color-text-dark);
|
||||
margin: 0;
|
||||
margin-right: var(--space-lg);
|
||||
}
|
||||
|
||||
/* ===== SEARCH FORM ===== */
|
||||
.form_paddock_search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.form_paddock_search label {
|
||||
font-size: var(--font-sm);
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.form_paddock_search input {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
font-size: var(--font-sm);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--border-radius-sm);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form_paddock_search input:focus {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.form_paddock_search button {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
border: none;
|
||||
border-radius: var(--border-radius-sm);
|
||||
background: var(--color-primary);
|
||||
color: var(--color-text-light);
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.form_paddock_search button:hover {
|
||||
background: var(--color-secondary);
|
||||
}
|
||||
|
||||
/* ===== CLEAR FILTER ===== */
|
||||
.btn-clear-filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
background: var(--color-danger-light);
|
||||
color: var(--color-danger);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: var(--font-sm);
|
||||
}
|
||||
|
||||
.btn-clear-filter:hover {
|
||||
background: var(--color-danger);
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
|
||||
/* ===== NEW BUTTON ===== */
|
||||
.paddock_title > a {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-md);
|
||||
background: var(--color-success);
|
||||
color: var(--color-text-light);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: var(--font-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.paddock_title > a:hover {
|
||||
background: var(--color-success);
|
||||
opacity: 0.85;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/* ===== PAGE HEADER ===== */
|
||||
.paddock_group_title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-md);
|
||||
margin-bottom: var(--space-lg);
|
||||
}
|
||||
|
||||
.paddock_group_title h1 {
|
||||
font-size: var(--font-xl);
|
||||
color: var(--color-text-dark);
|
||||
margin: 0;
|
||||
margin-right: var(--space-lg);
|
||||
}
|
||||
|
||||
/* ===== SEARCH FORM ===== */
|
||||
.form_paddock_group_search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.form_paddock_group_search label {
|
||||
font-size: var(--font-sm);
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.form_paddock_group_search input {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
font-size: var(--font-sm);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
border-radius: var(--border-radius-sm);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.form_paddock_group_search input:focus {
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.form_paddock_group_search button {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-sm);
|
||||
border: none;
|
||||
border-radius: var(--border-radius-sm);
|
||||
background: var(--color-primary);
|
||||
color: var(--color-text-light);
|
||||
cursor: pointer;
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.form_paddock_group_search button:hover {
|
||||
background: var(--color-secondary);
|
||||
}
|
||||
|
||||
/* ===== NEW BUTTON ===== */
|
||||
.paddock_group_title > a {
|
||||
height: 32px;
|
||||
padding: 0 var(--space-md);
|
||||
background: var(--color-success);
|
||||
color: var(--color-text-light);
|
||||
border-radius: var(--border-radius-sm);
|
||||
text-decoration: none;
|
||||
font-size: var(--font-sm);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
transition: background var(--transition-speed);
|
||||
}
|
||||
|
||||
.paddock_group_title > a:hover {
|
||||
background: var(--color-success);
|
||||
opacity: 0.85;
|
||||
}
|
||||
Whitespace-only changes.
@@ -0,0 +1,162 @@
|
||||
/* CONTENT */
|
||||
body {
|
||||
display: block;
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
padding-top: var(--header-height);
|
||||
}
|
||||
|
||||
/* NAVBAR */
|
||||
.farm-select-navbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: var(--header-height);
|
||||
background-color: var(--color-bg-light);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 var(--space-lg);
|
||||
z-index: 950;
|
||||
}
|
||||
|
||||
/* SITE'S TITLE */
|
||||
.farm-select-navbar .navbar-brand {
|
||||
font-weight: bold;
|
||||
font-size: 1.5rem;
|
||||
color: var(--color-bg-sidebar, #444);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* .navbar-user-info and .username uses gap and align style from global.css */
|
||||
|
||||
/* SELECT CONTAINER */
|
||||
.farm-select-container {
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
margin: var(--space-xl) auto;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.farm-select-container h1 {
|
||||
font-size: var(--font-xl);
|
||||
color: #1f2937;
|
||||
margin-bottom: var(--space-xl);
|
||||
}
|
||||
|
||||
/* LIST OF FARMS */
|
||||
.farm-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.farm-button {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.farm-item {
|
||||
padding: var(--space-md);
|
||||
text-align: left;
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-left: 5px solid transparent;
|
||||
border-radius: 6px;
|
||||
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.farm-item:hover {
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
|
||||
border-color: var(--color-farm-select-hover);
|
||||
border-left-color: var(--color-farm-select-hover); /* Cor primária */
|
||||
}
|
||||
|
||||
.farm-name {
|
||||
font-size: 1.25rem;
|
||||
color: var(--color-text-dark);
|
||||
margin: 0 0 var(--space-xs);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.farm-description {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
gap: var(--space-sm);
|
||||
align-items: center;
|
||||
margin-top: var(--space-sm);
|
||||
font-size: var(--font-sm);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* DATA SEPARATOR */
|
||||
.total-area, .count-piquetes, .count-animais {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
color: var(--color-farm-select-info);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.total-area:after, .count-piquetes:after {
|
||||
content: "|";
|
||||
margin-left: var(--space-xs);
|
||||
color: var(--color-simple-light-gray);
|
||||
}
|
||||
|
||||
/* WHEN NO FARMS */
|
||||
.no-farms {
|
||||
padding: var(--space-lg);
|
||||
margin-top: var(--space-lg);
|
||||
border: 2px dashed #ccc;
|
||||
border-radius: var(--border-radius-sm);
|
||||
background-color: var(--color-bg-white);
|
||||
}
|
||||
|
||||
.no-farms p {
|
||||
color: var(--color-farm-select-info);
|
||||
font-size: var(--font-md);
|
||||
margin: var(--space-xs) 0;
|
||||
}
|
||||
|
||||
/* NEW FARM BUTTON */
|
||||
.no-farms a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
margin-top: var(--space-md);
|
||||
padding: var(--space-xs) var(--space-md);
|
||||
background-color: var(--color-new-farm-button);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.no-farms a:hover {
|
||||
background-color: var(--color-new-farm-hover);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
body {
|
||||
padding: 0;
|
||||
}
|
||||
.farm-select-navbar {
|
||||
padding: 0 var(--space-md);
|
||||
}
|
||||
.farm-select-container {
|
||||
padding: var(--space-md) var(--space-sm);
|
||||
margin: var(--header-height) 0 0 0;
|
||||
max-width: 100%;
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
background-color: var(--color-bg-light);
|
||||
color: var(--color-text-dark);
|
||||
}
|
||||
|
||||
.login-container {
|
||||
display: flex;
|
||||
width: 850px;
|
||||
max-width: 90%;
|
||||
min-height: 450px;
|
||||
border-radius: var(--border-radius-lg, 10px);
|
||||
overflow: hidden;
|
||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15);
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.ilustration-container {
|
||||
flex: 1;
|
||||
background: linear-gradient(135deg, var(--login-background-primary), var(--login-background-secondary));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: var(--space-lg);
|
||||
color: var(--color-text-light);
|
||||
text-align: center;
|
||||
font-size: var(--font-lg, 1.5rem);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ilustration-container h1 {
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.login-form-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: var(--space-xl);
|
||||
}
|
||||
|
||||
.login-form-container h1 {
|
||||
font-size: var(--font-xl);
|
||||
margin-bottom: var(--space-md);
|
||||
color: var(--color-text-dark);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-form-container form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.login-form-container input[type="text"],
|
||||
.login-form-container input[type="password"] {
|
||||
padding: var(--space-sm);
|
||||
font-size: var(--font-md);
|
||||
border-radius: var(--border-radius-sm);
|
||||
border: 1px solid var(--color-border-subtle);
|
||||
width: 100%;
|
||||
transition: border-color var(--transition-speed) ease;
|
||||
}
|
||||
|
||||
.login-form-container input:focus {
|
||||
border-color: var(--color-primary);
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 1px var(--color-primary-light, rgba(0, 123, 255, 0.2));
|
||||
}
|
||||
|
||||
.login-form-container button[type="submit"] {
|
||||
background-color: var(--color-login-button);
|
||||
color: white;
|
||||
padding: var(--space-xs);
|
||||
font-size: var(--font-lg);
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
border-radius: var(--border-radius-sm);
|
||||
cursor: pointer;
|
||||
margin-top: var(--space-sm);
|
||||
transition: background-color var(--transition-speed) ease;
|
||||
}
|
||||
|
||||
.login-form-container button[type="submit"]:hover {
|
||||
background-color: var(--color-login-button-focus);
|
||||
}
|
||||
|
||||
.login-fail {
|
||||
color: var(--color-danger);
|
||||
background-color: var(--color-danger-light);
|
||||
border: 1px solid var(--color-danger);
|
||||
padding: var(--space-xs);
|
||||
border-radius: var(--border-radius-sm);
|
||||
font-size: var(--font-sm);
|
||||
text-align: center;
|
||||
margin-top: var(--space-sm);
|
||||
}
|
||||
|
||||
.login-fail i {
|
||||
margin-right: var(--space-xs);
|
||||
}
|
||||
|
||||
.login-form-container p {
|
||||
text-align: center;
|
||||
font-size: var(--font-sm);
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
.login-form-container a {
|
||||
color: var(--color-primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.login-form-container a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.login-container {
|
||||
flex-direction: column;
|
||||
height: auto;
|
||||
max-width: 95%;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.ilustration-container, .login-form-container {
|
||||
flex: none;
|
||||
width: 100%;
|
||||
}
|
||||
.ilustration-container {
|
||||
padding: var(--space-md);
|
||||
}
|
||||
.ilustration-container h1 {
|
||||
font-size: var(--font-md);
|
||||
}
|
||||
.login-form-container {
|
||||
padding: var(--space-lg) var(--space-md);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'animal/css/animal.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="animal_title">
|
||||
<h1>Animais</h1>
|
||||
<form method="GET" action="{% url 'entities:animal:animal_home' %}" class="form_animal_search">
|
||||
{% if filter_query %}
|
||||
<a href="{% url 'entities:animal:animal_home' %}" class="btn-clear-filter">{{filter_query}}<i class="fa-solid fa-xmark"></i></a>
|
||||
{% endif %}
|
||||
<label for="animal_search">Buscar</label>
|
||||
<input type="text" name="animal_search" required>
|
||||
<button type="submit"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
</form>
|
||||
<a href="{% url 'entities:animal:animal_new' %}">Novo <i class="fa-solid fa-plus"></i></a>
|
||||
</div>
|
||||
{% if not animals %}
|
||||
<p>Nenhum animal encontrado.</p>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Identificador</th>
|
||||
<th>Idade</th>
|
||||
<th>Peso</th>
|
||||
<th>Editar</th>
|
||||
<th>Excluir</th>
|
||||
</tr>
|
||||
{% for animal in animals %}
|
||||
<tr>
|
||||
<td>{{ animal.identifier }}</td>
|
||||
<td>{{ animal.age }}</td>
|
||||
<td>{{ animal.weight }} Kg</td>
|
||||
<td><a href="{% url 'entities:animal:animal_update' animal.id %}"><i class="fa-solid fa-pen-to-square"></i></a></td>
|
||||
<td>
|
||||
<form method="POST" action="{% url 'entities:animal:animal_delete' animal.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn-icon-trash"><i class="fa-solid fa-trash"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'animal/css/animal.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
NOVO ANIMAL <br>
|
||||
{% include 'includes/_form.html' %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'animal/css/animal.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
EDITAR ANIMAL <br>
|
||||
{% include 'includes/_form.html' %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,48 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'animal/css/batch.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="batch_title">
|
||||
<h1>Lotes</h1>
|
||||
<form method="GET" action="{% url 'entities:animal:batch_home' %}" class="form_batch_search">
|
||||
{% if filter_query %}
|
||||
<a href="{% url 'entities:animal:batch_home' %}" class="btn-clear-filter">{{filter_query}}<i class="fa-solid fa-xmark"></i></a>
|
||||
{% endif %}
|
||||
<label for="batch_search">Buscar</label>
|
||||
<input type="text" name="batch_search" required>
|
||||
<button type="submit"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
</form>
|
||||
<a href="{% url 'entities:animal:batch_new' %}">Novo <i class="fa-solid fa-plus"></i></a>
|
||||
</div>
|
||||
{% if not batches %}
|
||||
<p>Nenhum lote encontrado.</p>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Identificador</th>
|
||||
<th>Categoria animal</th>
|
||||
<th>Tipo de lote</th>
|
||||
<th>Editar</th>
|
||||
<th>Excluir</th>
|
||||
</tr>
|
||||
{% for batch in batches %}
|
||||
<tr>
|
||||
<td>{{ batch.identifier }}</td>
|
||||
<td>{{ batch.animal_category }}</td>
|
||||
<td>{{ batch.batch_type }} Kg</td>
|
||||
<td><a href="{% url 'entities:animal:batch_update' batch.id %}"><i class="fa-solid fa-pen-to-square"></i></a></td>
|
||||
<td>
|
||||
<form method="POST" action="{% url 'entities:animal:batch_delete' batch.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn-icon-trash"><i class="fa-solid fa-trash"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'animal/css/batch.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
NOVO LOTE <br>
|
||||
{% include 'includes/_form.html' %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'animal/css/batch.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
EDITAR LOTE <br>
|
||||
{% include 'includes/_form.html' %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="farm_title">
|
||||
<h1>Fazendas</h1>
|
||||
<form method="GET" action="{% url 'entities:farm:farm_home' %}" class="form_farm_search">
|
||||
{% if filter_query %}
|
||||
<a href="{% url 'entities:farm:farm_home' %}" class="btn-clear-filter">{{filter_query}}<i class="fa-solid fa-xmark"></i></a>
|
||||
{% endif %}
|
||||
<label for="farm_search">Buscar</label>
|
||||
<input type="text" name="farm_search" required>
|
||||
<button type="submit"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
</form>
|
||||
<a href="{% url 'entities:farm:farm_new' %}">Novo <i class="fa-solid fa-plus"></i></a>
|
||||
</div>
|
||||
{% if not farms %}
|
||||
<p>Nenhuma fazenda encontrado.</p>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Nome</th>
|
||||
<th>Área total</th>
|
||||
<th>Editar</th>
|
||||
<th>Excluir</th>
|
||||
</tr>
|
||||
{% for farm in farms %}
|
||||
<tr>
|
||||
<td>{{ farm.name }}</td>
|
||||
<td>{{ farm.total_area }} m2</td>
|
||||
<td><a href="{% url 'entities:farm:farm_update' farm.id %}"><i class="fa-solid fa-pen-to-square"></i></a></td>
|
||||
<td>
|
||||
<form method="POST" action="{% url 'entities:farm:farm_delete' farm.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn-icon-trash"><i class="fa-solid fa-trash"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
New - Farm
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
Update - Farm
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,85 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/paddock.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="paddock_title">
|
||||
<h1>Piquetes</h1>
|
||||
|
||||
<form method="GET" action="{% url 'entities:farm:paddock_home' %}" class="form_paddock_search">
|
||||
{% if filter_query %}
|
||||
<a href="{% url 'entities:farm:paddock_home' %}" class="btn-clear-filter">
|
||||
{{filter_query}}<i class="fa-solid fa-xmark"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<label for="paddock_search">Buscar</label>
|
||||
<input type="text" name="paddock_search" required>
|
||||
|
||||
<button type="submit">
|
||||
<i class="fa-solid fa-magnifying-glass"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<a href="{% url 'entities:farm:paddock_new' %}">
|
||||
Novo <i class="fa-solid fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if not paddocks %}
|
||||
<p>Nenhum piquete encontrado.</p>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Número</th>
|
||||
<th>Área</th>
|
||||
<th>Capacidade</th>
|
||||
<th>Ocupado</th>
|
||||
<th>Bloco</th>
|
||||
<th>Editar</th>
|
||||
<th>Excluir</th>
|
||||
</tr>
|
||||
|
||||
{% for paddock in paddocks %}
|
||||
<tr>
|
||||
<td>{{ paddock.paddock_number }}</td>
|
||||
<td>{{ paddock.area }} ha</td>
|
||||
<td>{{ paddock.load_capacity }}</td>
|
||||
<td>
|
||||
{% if paddock.occupied %}
|
||||
Sim
|
||||
{% else %}
|
||||
Não
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if paddock.paddock_group %}
|
||||
{{ paddock.paddock_group.identifier }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="{% url 'entities:farm:paddock_update' paddock.id %}">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<form method="POST" action="{% url 'entities:farm:paddock_delete' paddock.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn-icon-trash">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
New - Paddock
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
Delete - Paddock
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,76 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/paddock_group.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="paddock_group_title">
|
||||
<h1>Blocos</h1>
|
||||
|
||||
<form method="GET" action="{% url 'entities:farm:paddock_group_home' %}" class="form_paddock_group_search">
|
||||
{% if filter_query %}
|
||||
<a href="{% url 'entities:farm:paddock_group_home' %}" class="btn-clear-filter">
|
||||
{{filter_query}}<i class="fa-solid fa-xmark"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<label for="paddock_group_search">Buscar</label>
|
||||
<input type="text" name="paddock_group_search" required>
|
||||
|
||||
<button type="submit">
|
||||
<i class="fa-solid fa-magnifying-glass"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<a href="{% url 'entities:farm:paddock_group_new' %}">
|
||||
Novo <i class="fa-solid fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% if not paddock_groups %}
|
||||
<p>Nenhum bloco encontrado.</p>
|
||||
{% else %}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Identificador</th>
|
||||
<th>Descrição</th>
|
||||
<th>Piquetes</th>
|
||||
<th>Editar</th>
|
||||
<th>Excluir</th>
|
||||
</tr>
|
||||
|
||||
{% for group in paddock_groups %}
|
||||
<tr>
|
||||
<td>{{ group.identifier }}</td>
|
||||
<td>{{ group.description }}</td>
|
||||
|
||||
<td>
|
||||
{% for paddock in group.paddocks.all %}
|
||||
{{ paddock.paddock_number }}{% if not forloop.last %}, {% endif %}
|
||||
{% empty %}
|
||||
-
|
||||
{% endfor %}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<a href="{% url 'entities:farm:paddock_group_update' group.id %}">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<form method="POST" action="{% url 'entities:farm:paddock_group_delete' group.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn-icon-trash">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
New - Paddock Group
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
Delete - Paddock Group
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
Home - Rotation
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
New - Rotation
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'farm/css/home.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
Delete - Rotation
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.urls import include, path
|
||||
|
||||
app_name = "entities"
|
||||
|
||||
urlpatterns = [
|
||||
path("animal/", include("entities.urls.animal", namespace='animal')),
|
||||
path("farm/", include("entities.urls.farm", namespace='farm')),
|
||||
path("rotation/", include("entities.urls.rotation", namespace='rotation')),
|
||||
path("user/", include("entities.urls.user", namespace='user')),
|
||||
]
|
||||
@@ -0,0 +1,17 @@
|
||||
from django.urls import path
|
||||
from ..views import animal as views
|
||||
|
||||
app_name = 'animal'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.animal_home, name='animal_home'),
|
||||
path('batch/', views.batch_home, name='batch_home'),
|
||||
|
||||
path('new/', views.animal_new, name='animal_new'),
|
||||
path('update/<int:animal_id>', views.animal_update, name='animal_update'),
|
||||
path('delete/<int:animal_id>', views.animal_delete, name='animal_delete'),
|
||||
|
||||
path('batch/new/', views.batch_new, name='batch_new'),
|
||||
path('batch/update/<int:batch_id>', views.batch_update, name='batch_update'),
|
||||
path('batch/delete/<int:batch_id>', views.batch_delete, name='batch_delete'),
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
from django.urls import path
|
||||
from ..views import farm as views
|
||||
|
||||
app_name = 'farm'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.farm_home, name='farm_home'),
|
||||
path('paddock/', views.paddock_home, name='paddock_home'),
|
||||
path("paddock/group/", views.paddock_group_home, name="paddock_group_home"),
|
||||
|
||||
path('new/', views.farm_new, name='farm_new'),
|
||||
path('update/<int:farm_id>', views.farm_update, name='farm_update'),
|
||||
path('delete/<int:farm_id>', views.farm_delete, name='farm_delete'),
|
||||
|
||||
path('paddock/new/', views.paddock_new, name='paddock_new'),
|
||||
path('paddock/update/<int:paddock_id>', views.paddock_update, name='paddock_update'),
|
||||
path('paddock/delete/<int:paddock_id>', views.paddock_delete, name='paddock_delete'),
|
||||
|
||||
path('paddock_group/new/', views.paddock_group_new, name='paddock_group_new'),
|
||||
path('paddock_group/update/<int:paddock_group_id>', views.paddock_group_update, name='paddock_group_update'),
|
||||
path('paddock_group/delete/<int:paddock_group_id>', views.paddock_group_delete, name='paddock_group_delete'),
|
||||
]
|
||||
@@ -0,0 +1,14 @@
|
||||
from django.urls import path
|
||||
from django.http import HttpResponse
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
from ..views import rotation as views
|
||||
|
||||
app_name = 'rotation'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.rotation_home, name='rotation_home'),
|
||||
|
||||
path('new/', views.rotation_new, name='rotation_new'),
|
||||
path('delete/<int:rotation_id>', views.rotation_delete, name='rotation_delete'),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
from django.urls import path
|
||||
from django.http import HttpResponse
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from ..views import user as views
|
||||
|
||||
app_name = 'user'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.user_profile, name='user_profile'),
|
||||
path('login/', views.user_login, name='user_login'),
|
||||
path('logout/', views.user_logout, name='user_logout'),
|
||||
path('signin/', views.user_signin, name='user_signin'),
|
||||
|
||||
path('farm-select/', views.farm_select, name='farm_select'),
|
||||
path('farm-set/<int:farm_id>/', views.farm_set, name='farm_set'),
|
||||
path('farm-set/', views.farm_set, name='farm_set_post'),
|
||||
path('farm-deselect/', views.farm_deselect, name='farm_deselect'),
|
||||
]
|
||||
@@ -0,0 +1,3 @@
|
||||
from .animal import *
|
||||
from .farm import *
|
||||
from .rotation import *
|
||||
@@ -0,0 +1,76 @@
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.shortcuts import redirect, render
|
||||
from core.decorators import farm_required
|
||||
|
||||
from ..services import animal as services
|
||||
|
||||
# Animal Views
|
||||
@farm_required
|
||||
def animal_home(request):
|
||||
context = services.get_animal_home_context(request)
|
||||
return render(request, 'animal/animal_home.html', context)
|
||||
|
||||
|
||||
@farm_required
|
||||
def animal_new(request):
|
||||
if request.method == 'GET':
|
||||
context = services.get_animal_new_context()
|
||||
return render(request, 'animal/animal_new.html', context)
|
||||
|
||||
elif request.method == 'POST':
|
||||
success = services.create_animal(request)
|
||||
if success:
|
||||
return redirect('entities:animal:animal_home')
|
||||
|
||||
return redirect('entities:animal:animal_new')
|
||||
|
||||
|
||||
@farm_required
|
||||
def animal_update(request, animal_id):
|
||||
result = services.update_animal(request, animal_id)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'animal/animal_update.html', result['context'])
|
||||
|
||||
|
||||
@farm_required
|
||||
@require_http_methods(["POST"])
|
||||
def animal_delete(request, animal_id):
|
||||
services.delete_animal(request, animal_id)
|
||||
return redirect('entities:animal:animal_home')
|
||||
|
||||
|
||||
# Batch Views
|
||||
@farm_required
|
||||
def batch_home(request):
|
||||
context = services.get_batch_home_context(request)
|
||||
return render(request, 'batch/batch_home.html', context)
|
||||
|
||||
|
||||
@farm_required
|
||||
def batch_new(request):
|
||||
result = services.create_batch(request)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'batch/batch_new.html', result['context'])
|
||||
|
||||
|
||||
@farm_required
|
||||
def batch_update(request, batch_id):
|
||||
result = services.update_batch(request, batch_id)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'batch/batch_update.html', result['context'])
|
||||
|
||||
|
||||
@farm_required
|
||||
@require_http_methods(["POST"])
|
||||
def batch_delete(request, batch_id):
|
||||
services.delete_batch(batch_id)
|
||||
return redirect('entities:animal:batch_home')
|
||||
@@ -0,0 +1,122 @@
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.shortcuts import redirect, render
|
||||
from core.decorators import farm_required
|
||||
from ..services import farm as services
|
||||
|
||||
# Farm Views
|
||||
@farm_required
|
||||
def farm_home(request):
|
||||
context = services.get_farm_home_context(request)
|
||||
return render(request, 'farm/farm_home.html', context)
|
||||
|
||||
|
||||
@farm_required
|
||||
def farm_new(request):
|
||||
if request.method == 'GET':
|
||||
context = services.get_farm_new_context()
|
||||
return render(request, 'farm/farm_new.html', context)
|
||||
|
||||
elif request.method == 'POST':
|
||||
success = services.create_farm(request)
|
||||
if success:
|
||||
return redirect('entities:farm:farm_home')
|
||||
|
||||
return redirect('entities:farm:farm_new')
|
||||
|
||||
|
||||
|
||||
@farm_required
|
||||
def farm_update(request, farm_id):
|
||||
result = services.update_farm(request, farm_id)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'farm/farm_update.html', result['context'])
|
||||
|
||||
|
||||
@farm_required
|
||||
@require_http_methods(["POST"])
|
||||
def farm_delete(request, farm_id):
|
||||
services.delete_farm(request, farm_id)
|
||||
return redirect('entities:farm:farm_home')
|
||||
|
||||
|
||||
# Paddock Views
|
||||
@farm_required
|
||||
def paddock_home(request):
|
||||
context = {}
|
||||
context['title'] = 'Piquete'
|
||||
return render(request, 'paddock/paddock_home.html', context)
|
||||
|
||||
|
||||
@farm_required
|
||||
def paddock_new(request):
|
||||
if request.method == 'GET':
|
||||
context = services.get_paddock_new_context()
|
||||
return render(request, 'paddock/paddock_new.html', context)
|
||||
|
||||
elif request.method == 'POST':
|
||||
success = services.create_paddock(request)
|
||||
if success:
|
||||
return redirect('entities:farm:paddock_home')
|
||||
|
||||
return redirect('entities:farm:paddock_new')
|
||||
|
||||
|
||||
|
||||
@farm_required
|
||||
def paddock_update(request, paddock_id):
|
||||
result = services.update_paddock(request, paddock_id)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'paddock/paddock_update.html', result['context'])
|
||||
|
||||
|
||||
@farm_required
|
||||
@require_http_methods(["POST"])
|
||||
def paddock_delete(request, paddock_id):
|
||||
services.delete_paddock(request, paddock_id)
|
||||
return redirect('entities:farm:paddock_home')
|
||||
|
||||
|
||||
# Paddock Group Views
|
||||
@farm_required
|
||||
def paddock_group_home(request):
|
||||
context = {}
|
||||
context['title'] = 'Bloco'
|
||||
return render(request, 'paddock_group/paddock_group_home.html', context)
|
||||
|
||||
|
||||
@farm_required
|
||||
def paddock_group_new(request):
|
||||
if request.method == 'GET':
|
||||
context = services.get_paddock_group_new_context()
|
||||
return render(request, 'paddock_group/paddock_group_new.html', context)
|
||||
|
||||
elif request.method == 'POST':
|
||||
success = services.create_paddock_group(request)
|
||||
if success:
|
||||
return redirect('entities:farm:paddock_group_home')
|
||||
|
||||
return redirect('entities:farm:paddock_group_new')
|
||||
|
||||
|
||||
|
||||
@farm_required
|
||||
def paddock_group_update(request, paddock_group_id):
|
||||
result = services.update_paddock_group(request, paddock_group_id)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'paddock_group/paddock_group_update.html', result['context'])
|
||||
|
||||
|
||||
@farm_required
|
||||
@require_http_methods(["POST"])
|
||||
def paddock_group_delete(request, paddock_group_id):
|
||||
services.delete_paddock_group(request, paddock_group_id)
|
||||
return redirect('entities:farm:paddock_group_home')
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
def rotation_home(request):
|
||||
return render(request, 'rotation/rotation_home.html')
|
||||
|
||||
def rotation_new(request):
|
||||
return render(request, 'rotation/rotation_new.html')
|
||||
|
||||
def rotation_delete(request):
|
||||
return render(request, 'rotation/rotation_delete.html')
|
||||
@@ -0,0 +1,40 @@
|
||||
from django.shortcuts import redirect, render
|
||||
from ..services import user as services
|
||||
|
||||
|
||||
def user_profile(request): # TO DO
|
||||
return services.user_profile(request)
|
||||
|
||||
|
||||
def user_login(request):
|
||||
result = services.user_login(request)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'login.html', result['context'])
|
||||
|
||||
|
||||
def user_logout(request):
|
||||
return services.user_logout(request)
|
||||
|
||||
|
||||
def user_signin(request): # TO DO
|
||||
return services.user_signin(request)
|
||||
|
||||
|
||||
def farm_select(request):
|
||||
result = services.farm_select(request)
|
||||
|
||||
if result.get('redirect'):
|
||||
return redirect(result['redirect'])
|
||||
|
||||
return render(request, 'farm_select.html', result['context'])
|
||||
|
||||
|
||||
def farm_set(request, farm_id=None):
|
||||
return services.farm_set(request, farm_id)
|
||||
|
||||
|
||||
def farm_deselect(request):
|
||||
return services.farm_deselect(request)
|
||||
Reference in new issue
Block a user