ipp/relevamiento/forms.py
class JerarquizacionMarcaForm(autocomplete_light.ModelForm):
    class Meta:
class ProductoConMarcaForm(ModelForm):
    class Meta:
class PlanillaDeRelevamientoForm(ModelForm):
    class Meta:
class MuestraForm(ModelForm):
    class Meta:
class LecturaForm(ModelForm):
    class Meta:
class UserFormCreacion(UserCreationForm):
    class Meta:
class UserFormEdicion(ModelForm):
    class Meta:
class PerfilInlineFormSet(BaseInlineFormSet):
class VariacionForm(Form):
    def __init__(self, *args, **kwargs):
    def clean_producto_con_marca(self):
    def clean(self):
    def __init__(self, *args, **kwargs):
    def clean(self):
    def __init__(self, *args, **kwargs):
    def clean_planilla_modelo(self):
    def clean_zona(self):
    def clean_comercio(self):
    def clean(self):
    def __init__(self, *args, **kwargs):
    def __init__(self, *args, **kwargs):
    def __init__(self, *args, **kwargs):
    def clean(self):
ipp/relevamiento/models.py
class Comercio(models.Model):
    nombre = models.CharField(max_length=100)
    direccion = models.CharField("dirección", max_length=100)
    tipo = models.CharField("tipo de comercio", max_length=100)
    descripcion = models.CharField("descripción", max_length=256, blank=True)
    zona =  models.ForeignKey(Zona, related_name="comercios")

    def __str__(self):
        return self.nombre
ipp/relevamiento/models.py
class ProductoGenerico(models.Model):
    rubro = models.ForeignKey(Rubro)
    nombre = models.CharField(max_length=150)
    medida = models.CharField(max_length=20)

    def __str__(self):
        return "%s > %s (%s)" % (self.rubro, self.nombre, self.medida)
    
    class Meta:
        verbose_name_plural="productos genericos"
ipp/relevamiento/constants.py
COORD_GRAL = "coordinador_general"
ipp/relevamiento/models.py
class Region(models.Model):
    nombre = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.nombre

    class Meta:
        verbose_name = "región"
        verbose_name_plural = "regiones"
ipp/relevamiento/constants.py
PERMISO_COORD_JURISDICCIONAL = 3
ipp/relevamiento/models.py
class Jurisdiccion(models.Model):
    region = models.ForeignKey(Region, related_name="jurisdicciones")
    nombre = models.CharField(max_length=100)

    def __str__(self):
        return str(self.region) +" > "+ self.nombre

    class Meta:
        verbose_name = "jurisdicción"
        verbose_name_plural = "jurisdicciones"
        ordering = ['region__pk', 'nombre']
        unique_together = (("region", "nombre"))
ipp/relevamiento/constants.py
COORD_JURISDICCIONAL = "coordinador_jurisdiccional"
ipp/relevamiento/perms.py
class RequiereCoordRegional(RequiereRol):
    permiso_minimo = PERMISO_COORD_REGIONAL
ipp/relevamiento/models.py
class JerarquizacionMarca(models.Model):
    MARCA_CHOICES = (
        ("premium", "premium"),
        ("media", "media"),
        ("economica", "económica")
    )
    planilla_de_relevamiento = models.ForeignKey("PlanillaDeRelevamiento")
    producto_con_marca = models.ForeignKey(ProductoConMarca, related_name="jerarquizaciones", verbose_name="producto")
    tipo_marca = models.CharField(choices=MARCA_CHOICES, max_length=15)
    def __str__(self):
        return "%s (marca %s)" %\
            (str(self.producto_con_marca), self.tipo_marca)

    class Meta:
        unique_together = (("planilla_de_relevamiento", "producto_con_marca"),)
ipp/relevamiento/models.py
class Lectura(models.Model):
    producto_con_marca = models.ForeignKey(ProductoConMarca, verbose_name="producto")
    precio = models.FloatField()
    fecha = models.DateField(default=datetime.now)
    muestra = models.ForeignKey('Muestra', related_name="lecturas")
#    relevador = models.ForeignKey(Perfil)

    def __str__(self):
        return "%s $%s (%s)" % \
            (str(self.producto_con_marca), str(self.precio), str(self.fecha))

    class Meta:
        unique_together = (("producto_con_marca", "muestra"),)
ipp/relevamiento/models.py
class JerarquizacionMarca(models.Model):
    MARCA_CHOICES = (
        ("premium", "premium"),
        ("media", "media"),
        ("economica", "económica")
    )
    planilla_de_relevamiento = models.ForeignKey("PlanillaDeRelevamiento")
    producto_con_marca = models.ForeignKey(ProductoConMarca, related_name="jerarquizaciones", verbose_name="producto")
    tipo_marca = models.CharField(choices=MARCA_CHOICES, max_length=15)
    def __str__(self):
        return "%s (marca %s)" %\
            (str(self.producto_con_marca), self.tipo_marca)

    class Meta:
        unique_together = (("planilla_de_relevamiento", "producto_con_marca"),)
ipp/relevamiento/models.py
class Zona(models.Model):
    jurisdiccion = models.ForeignKey(Jurisdiccion, related_name="zonas")
    nombre = models.CharField(max_length=100)

    def __str__(self):
        return str(self.jurisdiccion) +" > "+ self.nombre

    class Meta:
        ordering = ['jurisdiccion__region__pk', 'jurisdiccion__nombre', 'nombre']
        unique_together = (("jurisdiccion", "nombre"))
ipp/relevamiento/constants.py
PERMISO_COORD_ZONAL = 2
ipp/relevamiento/models.py
class PlanillaDeRelevamiento(models.Model):
    """Basada en una Planilla Modelo, establece qué marcas se relevarán para un comercio específico"""
    planilla_modelo = models.ForeignKey(PlanillaModelo)
    zona = models.ForeignKey(Zona, related_name="planillas_de_relevamiento")
    comercio = models.ForeignKey(Comercio, related_name="planillas_de_relevamiento")
    productos = models.ManyToManyField(ProductoConMarca,
                                       through=JerarquizacionMarca, blank=True)
    habilitada = models.BooleanField(default=False)

    def __str__(self):
        return "%s (%s)" % \
            (str(self.comercio), str(self.zona))

    class Meta:
        unique_together = (("planilla_modelo", "zona", "comercio"),)
        verbose_name_plural = "planillas de relevamiento"
        ordering = ['planilla_modelo__nombre', 'zona']
ipp/relevamiento/perms.py
class RequiereCoordZonal(RequiereRol):
    permiso_minimo = PERMISO_COORD_ZONAL
ipp/relevamiento/constants.py
RELEVADOR = "relevador"
ipp/relevamiento/models.py
class Perfil(models.Model):
    ROLES_CHOICES = (
        (RELEVADOR, RELEVADOR),
        (COORD_ZONAL, COORD_ZONAL),
        (COORD_JURISDICCIONAL, COORD_JURISDICCIONAL),
        (COORD_REGIONAL, COORD_REGIONAL),
        (COORD_GRAL, COORD_GRAL)
    )
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    rol = models.CharField(choices=ROLES_CHOICES, default=RELEVADOR, max_length=40)
    telefono = models.CharField("teléfono", max_length=100, blank=True)
    celular = models.CharField(max_length=100, blank=True)
    enlace = models.URLField(blank=True)
    notas = models.TextField(blank=True)
    regiones = models.ManyToManyField(Region, blank=True)
    jurisdicciones = models.ManyToManyField(Jurisdiccion, blank=True)
    zonas = models.ManyToManyField(Zona, blank=True, related_name="perfiles")

    def __str__(self):
        return self.user.username

    @property
    def autorizacion(self):
        if self.rol == RELEVADOR: return PERMISO_RELEVADOR
        elif self.rol == COORD_ZONAL: return PERMISO_COORD_ZONAL
        elif self.rol == COORD_JURISDICCIONAL: return PERMISO_COORD_JURISDICCIONAL
        elif self.rol == COORD_REGIONAL: return PERMISO_COORD_REGIONAL
        elif self.rol == COORD_GRAL: return PERMISO_COORD_GRAL
        else: return 0

    @property
    def regiones_permitidas(self):
        if self.rol == COORD_REGIONAL:
            return self.regiones
        elif self.rol == COORD_GRAL:
            return Region.objects.all()
        else:
            return Region.objects.none()

    @property
    def jurisdicciones_permitidas(self):
        if self.rol == COORD_JURISDICCIONAL:
            return self.jurisdicciones
        elif self.rol == COORD_REGIONAL:
            return Jurisdiccion.objects.filter(region__in=self.regiones.all())
        elif self.rol == COORD_GRAL:
            return Jurisdiccion.objects.all()
        else:
            return Jurisdiccion.objects.none()

    @property
    def zonas_permitidas(self):
        if self.rol in [RELEVADOR, COORD_ZONAL]:
            return self.zonas
        elif self.rol == COORD_JURISDICCIONAL:
            return Zona.objects.filter(jurisdiccion__in=self.jurisdicciones.all())
        elif self.rol == COORD_REGIONAL:
            return Zona.objects.filter(jurisdiccion__region__in=self.regiones.all())
        elif self.rol == COORD_GRAL:
            return Zona.objects.all()
        else:
            return Zona.objects.none()
        
    class Meta:
        verbose_name_plural = "perfiles"
ipp/relevamiento/constants.py
PERMISO_COORD_GRAL = 5
ipp/relevamiento/constants.py
COORD_ZONAL = "coordinador_zonal"
ipp/relevamiento/models.py
class Muestra(models.Model):
    """Muestra de lecturas quincenales para un comercio"""
    planilla_de_relevamiento = models.ForeignKey(PlanillaDeRelevamiento, related_name="muestras")
    anio = models.IntegerField("año")
    mes = models.IntegerField(choices=MES_CHOICES)
    quincena = models.IntegerField(choices=((1, "primera"),(2, "segunda")))
    relevadores = models.ManyToManyField(Perfil, blank=True)
    completa = models.BooleanField(default=False)
    aprobada = models.BooleanField(default=False)
    
    def __str__(self):
        nombre = "%s (%s/%s, quincena %s)" %\
                 (str(self.planilla_de_relevamiento), self.mes, self.anio, self.quincena)
        return nombre

    class Meta:
        unique_together = (("planilla_de_relevamiento", "anio", "mes", "quincena"),)
        ordering = ['-anio', '-mes', '-quincena']
ipp/relevamiento/models.py
class ProductoConMarca(models.Model):
    producto_generico = models.ForeignKey(ProductoGenerico)
    marca = models.CharField(max_length=50, blank=True)

    def __str__(self):
        return "%s %s" %\
            (str(self.producto_generico), self.marca)

    class Meta:
        verbose_name="producto"
        verbose_name_plural="productos"
        unique_together = (("producto_generico", "marca"),)
ipp/relevamiento/models.py
class PlanillaDeRelevamiento(models.Model):
    """Basada en una Planilla Modelo, establece qué marcas se relevarán para un comercio específico"""
    planilla_modelo = models.ForeignKey(PlanillaModelo)
    zona = models.ForeignKey(Zona, related_name="planillas_de_relevamiento")
    comercio = models.ForeignKey(Comercio, related_name="planillas_de_relevamiento")
    productos = models.ManyToManyField(ProductoConMarca,
                                       through=JerarquizacionMarca, blank=True)
    habilitada = models.BooleanField(default=False)

    def __str__(self):
        return "%s (%s)" % \
            (str(self.comercio), str(self.zona))

    class Meta:
        unique_together = (("planilla_modelo", "zona", "comercio"),)
        verbose_name_plural = "planillas de relevamiento"
        ordering = ['planilla_modelo__nombre', 'zona']
ipp/relevamiento/constants.py
COORD_REGIONAL = "coordinador_regional"
ipp/relevamiento/models.py
class Comercio(models.Model):
    nombre = models.CharField(max_length=100)
    direccion = models.CharField("dirección", max_length=100)
    tipo = models.CharField("tipo de comercio", max_length=100)
    descripcion = models.CharField("descripción", max_length=256, blank=True)
    zona =  models.ForeignKey(Zona, related_name="comercios")

    def __str__(self):
        return self.nombre
ipp/relevamiento/constants.py
PERMISO_COORD_REGIONAL = 4
ipp/relevamiento/perms.py
class RequiereCoordJurisdiccional(RequiereRol):
    permiso_minimo = PERMISO_COORD_JURISDICCIONAL
ipp/relevamiento/models.py
class PlanillaModelo(models.Model):
    """Planilla que establece qué productos se relevarán en todo el sistema"""
    nombre = models.CharField(max_length=100)
    productos = models.ManyToManyField(ProductoGenerico,
                                       through=ProductoEnPlanilla, blank=True)
    habilitada = models.BooleanField(default=False)

    def __str__(self):
        return self.nombre

    class Meta:
        verbose_name_plural="planillas modelo"
ipp/relevamiento/constants.py
PERMISO_RELEVADOR = 1


Question: from collections import OrderedDict
from django.http import Http404
from django.http import HttpResponseRedirect
from django.shortcuts import render, HttpResponse, redirect
from django.forms.models import inlineformset_factory
from django.core.urlresolvers import reverse
from django.contrib import messages
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.list import ListView
from django.contrib.auth.models import User
from django.db.models import Q, F, Avg, Max, Min, Count
from django.db.models.functions import Concat
from django.utils.text import slugify
from .constants import PERMISO_RELEVADOR, PERMISO_COORD_ZONAL, PERMISO_COORD_JURISDICCIONAL,\
    PERMISO_COORD_REGIONAL, PERMISO_COORD_GRAL, RELEVADOR, COORD_ZONAL, COORD_JURISDICCIONAL,\
    COORD_REGIONAL, COORD_GRAL
from .forms import PlanillaDeRelevamientoForm, JerarquizacionMarcaForm, ProductoConMarcaForm,\
    MuestraForm, LecturaForm, UserFormCreacion, UserFormEdicion, PerfilFormSet, VariacionForm
from .models import PlanillaModelo, PlanillaDeRelevamiento, JerarquizacionMarca, ProductoGenerico,\
    ProductoConMarca, Lectura, Comercio, Perfil, Muestra, PlanillaDeRelevamiento, JerarquizacionMarca,\
    Zona, Comercio, Jurisdiccion, Region
from .perms import RequiereCoordZonal, RequiereCoordJurisdiccional, RequiereCoordRegional
import unicodecsv as csv
# -*- coding: utf-8 -*-

#    IPP, Plataforma web del Índice de Precios Popular
#    Copyright (c) 2016 Nicolás Echániz and contributors.
#
#    This file is part of IPP
#
#    IPP is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.

#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.

#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.







def crear_planilla_de_relevamiento(request):
    user=request.user
    if hasattr(user, "perfil") and \
       user.perfil.autorizacion >= PERMISO_COORD_ZONAL:
        if request.method == "POST":
            form = PlanillaDeRelevamientoForm(request.POST, user=user)
            if form.is_valid():
                form.save()
                messages.success(request, 'La planilla de relevamiento fue creada con éxito.')
                return render(request, 'relevamiento/mensaje.html')
            else:
                return render(request, 'relevamiento/crear_planilla_de_relevamiento.html',
                              {"form": form})
        else:
                planillas_modelo = PlanillaModelo.objects.all()
                initial = {}
                if len(planillas_modelo) == 1:
                    planilla_modelo = planillas_modelo[0]
                    initial = {"planilla_modelo": planilla_modelo}
                form = PlanillaDeRelevamientoForm(initial=initial, user=user)
                return render(request, 'relevamiento/crear_planilla_de_relevamiento.html',
                              {"form": form})
    else:
        messages.error(request, 'Permisos insuficientes.')
        return render(request, 'relevamiento/mensaje.html')

def json_opciones_zona(request):
# tiene que devolver las opciones de zona habilitadas para el usuario
    pass

def json_opciones_comercio(request):
# tiene que devolver las opciones de comercios para la zona elegida
    pass

def seleccionar_planilla_de_relevamiento(request):
    user = request.user
    if hasattr(request.user, "perfil") and \
       request.user.perfil.autorizacion >= PERMISO_RELEVADOR:

Answer:         if request.user.perfil.rol == RELEVADOR: