diff --git a/sigi/admin/filterspecs.py b/sigi/admin/filterspecs.py index 73c2878..f0a5bb7 100644 --- a/sigi/admin/filterspecs.py +++ b/sigi/admin/filterspecs.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec, BooleanFieldFilterSpec from django.utils.encoding import smart_unicode from django.utils.safestring import mark_safe @@ -345,3 +346,68 @@ class CasaProjetoFilterSpec(ChoicesFilterSpec): # registering the filter FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'projeto_filter', False), CasaProjetoFilterSpec)) + +# Filterspec para ocorrencias + +class OcorrenciaFilterspec(ChoicesFilterSpec): + def __init__(self, f, request, params, model, model_admin): + super(OcorrenciaFilterspec, self).__init__(f, request, params, model, model_admin) + self.lookup_kwarg = 'grupo' + self.lookup_val = request.GET.get(self.lookup_kwarg, None) + self.lookup_choices = (('S', u'Atribuídos ao meu setor'), ('M', u'Registrados por mim'),) + + def choices(self, cl): + yield {'selected': self.lookup_val is None, + 'query_string': cl.get_query_string({}, [self.lookup_kwarg]), + 'display': _('All')} + for value, label in self.lookup_choices: + yield {'selected': smart_unicode(value) == self.lookup_val, + 'query_string': cl.get_query_string({self.lookup_kwarg: value}), + 'display': label} + def title(self): + return u"grupos de ocorrência" + +# registering the filter +FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'grupo_filter', False), + OcorrenciaFilterspec)) + +# Multichoices filterspec + +class MultichoicesFilterSpec(ChoicesFilterSpec): + """ + my_model_field.multichoices_filter = True + """ + + def __init__(self, f, request, params, model, model_admin): + super(MultichoicesFilterSpec, self).__init__(f, request, params, model, + model_admin) + self.lookup_kwarg = '%s__in' % f.name + self.lookup_val = request.GET.get(self.lookup_kwarg, None) + + def choices(self, cl): + lookup_values = map(int, self.lookup_val.split(',')) if self.lookup_val is not None else [] + is_all = (self.lookup_val is None) or (lookup_values == [k for k,v in self.field.flatchoices]) + if is_all: + lookup_values = [] + yield {'selected': is_all, + 'query_string': cl.get_query_string({}, [self.lookup_kwarg]), + 'display': _('All')} + for k, v in self.field.flatchoices: + selected = k in lookup_values + new_values = list(lookup_values) + if selected: + new_values.remove(k) + else: + new_values.append(k) + new_values.sort() + yield {'selected': selected, + 'query_string': cl.get_query_string({self.lookup_kwarg: u",".join(map(str, new_values))}), + 'display': v} + + def title(self): + return _('%(field_name)s in') % \ + {'field_name': self.field.verbose_name} + +# registering the filter +FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'multichoice_filter', False), + MultichoicesFilterSpec)) diff --git a/sigi/apps/casas/admin.py b/sigi/apps/casas/admin.py index f966d91..0ea0e78 100644 --- a/sigi/apps/casas/admin.py +++ b/sigi/apps/casas/admin.py @@ -17,6 +17,7 @@ from sigi.apps.diagnosticos.models import Diagnostico from sigi.apps.inventario.models import Bem from sigi.apps.servicos.models import Servico from sigi.apps.metas.models import PlanoDiretor +from sigi.apps.ocorrencias.models import Ocorrencia class TelefonesInline(generic.GenericTabularInline): model = Telefone @@ -136,6 +137,14 @@ class ServicoInline(admin.TabularInline): class PlanoDiretorInline(admin.TabularInline): model = PlanoDiretor + +class OcorrenciaInline(admin.TabularInline): + model = Ocorrencia + fields = ('data_criacao', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel',) + readonly_fields = ('data_criacao', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel',) + extra = 0 + max_num = 0 + can_delete = False class CasaLegislativaAdmin(admin.ModelAdmin): form = CasaLegislativaForm @@ -143,7 +152,7 @@ class CasaLegislativaAdmin(admin.ModelAdmin): change_list_template = 'casas/change_list.html' actions = ['adicionar_casas',] inlines = (TelefonesInline, PresidenteInline, FuncionariosInline, ConveniosInline, LegislaturaInline, - DiagnosticoInline, BemInline, ServicoInline, PlanoDiretorInline) + DiagnosticoInline, BemInline, ServicoInline, PlanoDiretorInline, OcorrenciaInline, ) list_display = ('nome','municipio','logradouro', 'ult_alt_endereco', 'get_convenios') list_display_links = ('nome',) list_filter = ('tipo', 'municipio', 'search_text') diff --git a/sigi/apps/ocorrencias/admin.py b/sigi/apps/ocorrencias/admin.py index 5308ca3..79549bb 100644 --- a/sigi/apps/ocorrencias/admin.py +++ b/sigi/apps/ocorrencias/admin.py @@ -1,29 +1,114 @@ # -*- coding: utf-8 -*- +from django.core.urlresolvers import reverse +from django.http import HttpResponseRedirect from django.contrib import admin +from django.contrib.admin.views.main import ChangeList from eav.admin import BaseEntityAdmin, BaseSchemaAdmin +from sigi.apps.servidores.models import Servidor from sigi.apps.ocorrencias.models import Ocorrencia, Comentario, Anexo, Categoria + +class ComentarioViewInline(admin.TabularInline): + model = Comentario + extra = 0 + max_num=0 + can_delete = False + verbose_name, verbose_name_plural = u"Comentário anterior", u"Comentários anteriores" + fields = ('usuario', 'data_criacao', 'novo_status', 'encaminhar_setor', 'descricao', ) + readonly_fields = ('novo_status', 'encaminhar_setor', 'descricao', 'data_criacao', 'usuario',) -class ComentarioInline(admin.TabularInline): +class ComentarioInline(admin.StackedInline): model = Comentario - extra = 1 + extra = 3 + verbose_name, verbose_name_plural = u"Comentário novo", u"Comentários novos" + fieldsets = ((None, {'fields': (('novo_status', 'encaminhar_setor',), 'descricao', )}),) + def queryset(self, request): + return self.model.objects.get_empty_query_set() class AnexosInline(admin.TabularInline): model = Anexo extra = 2 - exclude = ['data_pub',] + readonly_fields = ['data_pub',] + +class OcorrenciaChangeList(ChangeList): + request = None + def __init__(self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, + list_select_related, list_per_page, list_editable, model_admin): + self.request = request + super(OcorrenciaChangeList, self).__init__(request, model, list_display, list_display_links, list_filter, + date_hierarchy, search_fields, list_select_related, list_per_page, + list_editable, model_admin) + def get_query_set(self): + tmp_params = self.params.copy() + grupo = None + if 'grupo' in self.params: + grupo = self.params['grupo'] + del self.params['grupo'] + qs = super(OcorrenciaChangeList, self).get_query_set() + self.params = tmp_params.copy() + if grupo: + servidor = Servidor.objects.get(user=self.request.user) + if grupo == 'S': # Apenas do meu setor + qs = qs.filter(setor_responsavel=servidor.servico) + elif grupo == 'M': # Apenas criados por mim + qs = qs.filter(servidor_registro=servidor) + return qs -class AnexoAdmin(admin.ModelAdmin): - date_hierarchy = 'data_pub' - exclude = ['data_pub',] - list_display = ('arquivo', 'descricao', 'data_pub', 'ocorrencia') - raw_id_fields = ('ocorrencia',) - search_fields = ('descricao', 'ocorrencia__id', 'arquivo', - 'ocorrencia__casa_legislativa__nome') +class OcorrenciaAdmin(admin.ModelAdmin): + list_display = ('data_criacao', 'casa_legislativa', 'assunto', 'prioridade', 'status', 'data_modificacao', 'setor_responsavel',) + list_filter = ('assunto', 'status', 'prioridade', 'categoria', 'setor_responsavel', ) + search_fields = ('casa_legislativa__search_text', 'assunto', 'servidor_registro__nome', ) + date_hierarchy = 'data_criacao' + fields = ('casa_legislativa', 'categoria', 'assunto', 'status', 'prioridade', 'descricao', 'servidor_registro', + 'setor_responsavel', 'resolucao', ) + readonly_fields = ('servidor_registro', 'setor_responsavel', ) + inlines = (ComentarioViewInline, ComentarioInline, AnexosInline, ) + raw_id_fields = ('casa_legislativa', ) + + def get_changelist(self, request, **kwargs): + return OcorrenciaChangeList + + def get_readonly_fields(self, request, obj=None): + fields = list(self.readonly_fields) + if obj is not None: + fields.extend(['casa_legislativa', 'categoria', 'assunto', 'status', 'descricao', ]) + if obj.status in [3, 4, 5]: #Fechados + fields.append('prioridade') + return fields + + def get_fieldsets(self, request, obj=None): + if obj is None: + self.fields = ('casa_legislativa', 'categoria', 'assunto', 'prioridade', 'descricao', 'resolucao', ) + return super(OcorrenciaAdmin, self).get_fieldsets(request, obj) + + def changelist_view(self, request, *args, **kwargs): + try: + if len(request.GET) == 0: + url = reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.module_name)) + return HttpResponseRedirect("%s?grupo=S&status__in=1,2" % url) + except: + pass + return super(OcorrenciaAdmin, self).changelist_view(request, *args, **kwargs) -class OcorrenciaAdmin(BaseEntityAdmin): - inlines = (ComentarioInline, AnexosInline) - raw_id_fields = ('casa_legislativa',) + def save_model(self, request, obj, form, change): + if not change: + obj.servidor_registro = Servidor.objects.get(user=request.user) + obj.setor_responsavel = obj.categoria.setor_responsavel + obj.save() + + def save_formset(self, request, form, formset, change): + servidor = Servidor.objects.get(user=request.user) + instances = formset.save(commit=False) + for instance in instances: + instance.usuario = servidor + instance.save() + if instance.encaminhar_setor and (instance.encaminhar_setor != instance.ocorrencia.setor_responsavel): + instance.ocorrencia.setor_responsavel = instance.encaminhar_setor + instance.ocorrencia.save() + if instance.novo_status and (instance.novo_status != instance.ocorrencia.status): + instance.ocorrencia.status = instance.novo_status + instance.ocorrencia.save() + + formset.save_m2m() admin.site.register(Ocorrencia, OcorrenciaAdmin) -admin.site.register(Anexo, AnexoAdmin) admin.site.register(Categoria) diff --git a/sigi/apps/ocorrencias/models.py b/sigi/apps/ocorrencias/models.py index c9865b1..e977ea5 100644 --- a/sigi/apps/ocorrencias/models.py +++ b/sigi/apps/ocorrencias/models.py @@ -3,81 +3,77 @@ from django.db import models from datetime import datetime from django.db import models from sigi.apps.utils import SearchField -from eav.models import BaseChoice, BaseEntity, BaseSchema, BaseAttribute +#from eav.models import BaseChoice, BaseEntity, BaseSchema, BaseAttribute class Categoria(models.Model): nome= models.CharField(max_length=50) descricao = models.TextField('descrição', blank=True, null=True) + setor_responsavel = models.ForeignKey('servidores.Servico', verbose_name=u"Setor responsável") + + class Meta: + verbose_name, verbose_name_plural = u'Categoria', u'Categorias' def __unicode__(self): return str(self.nome) class Ocorrencia(models.Model): - casa_legislativa = models.ForeignKey( - 'casas.CasaLegislativa', - verbose_name='Casa Legislativa' - ) - search_text = SearchField(field_names=['casa_legislativa']) - casa_legislativa.convenio_uf_filter = True - casa_legislativa.convenio_cl_tipo_filter = True - data_criacao = models.DateField( - 'data de criacao', - null=True, - blank=True, - ) - - data_modificacao = models.DateField( - u'data de modificação', - null=True, - blank=True, - ) - - STATUS_CHOICES = ( - (1, 'Aberto'), - (2, 'Reaberto'), - (3, 'Resolvido'), - (4, 'Fechado'), - (5, 'Duplicado'), + (1, u'Aberto'), + (2, u'Reaberto'), + (3, u'Resolvido'), + (4, u'Fechado'), + (5, u'Duplicado'), ) PRIORITY_CHOICES = ( (1, u'Altíssimo'), - (2, 'Alto'), - (3, 'Normal'), - (4, 'Baixo'), + (2, u'Alto'), + (3, u'Normal'), + (4, u'Baixo'), (5, u'Baixíssimo'), ) - categoria = models.ForeignKey(Categoria) - assunto = models.CharField(max_length=200) - status = models.IntegerField(choices=STATUS_CHOICES, default=1, blank=1) - prioridade = models.IntegerField(choices=PRIORITY_CHOICES, default=3, blank=3) - descricao = models.TextField(u'descirção', blank=True, null=True) - resolucao = models.TextField(u'resolução', blank=True, null=True) - responsavel = models.ForeignKey('servidores.Servidor', blank=True, null=True, verbose_name=u'responsável') + casa_legislativa = models.ForeignKey('casas.CasaLegislativa', verbose_name=u'Casa Legislativa') + casa_legislativa.convenio_uf_filter = True + casa_legislativa.convenio_cl_tipo_filter = True + data_criacao = models.DateField(u'Data de criação', null=True, blank=True, auto_now_add=True) + data_modificacao = models.DateField(u'Data de modificação', null=True, blank=True, auto_now=True) + categoria = models.ForeignKey(Categoria, verbose_name=u'Categoria') + assunto = models.CharField(u'Assunto', max_length=200) + assunto.grupo_filter = True + status = models.IntegerField(u'Status', choices=STATUS_CHOICES, default=1,) + status.multichoice_filter = True + prioridade = models.IntegerField(u'Prioridade', choices=PRIORITY_CHOICES, default=3, ) + descricao = models.TextField(u'descrição', blank=True,) + resolucao = models.TextField(u'resolução', blank=True,) + servidor_registro = models.ForeignKey('servidores.Servidor', verbose_name=u"Servidor que registrou a ocorrência") + setor_responsavel = models.ForeignKey('servidores.Servico', verbose_name=u"Setor responsável") class Meta: verbose_name, verbose_name_plural = u'ocorrência', u'ocorrências' + ordering = ['prioridade', 'data_modificacao', 'data_criacao', ] + + def __unicode__(self): + return u"%(casa_legislativa)s: %(assunto)s" % {'assunto': self.assunto, 'casa_legislativa': str(self.casa_legislativa)} class Comentario(models.Model): - ocorrencia = models.ForeignKey(Ocorrencia, verbose_name=u'ocorrência') - data_criacao = models.DateTimeField(u'data de criação', default = datetime.now()) - descricao = models.TextField(u'descirção', blank=True, null=True) - usuario = models.ForeignKey('servidores.Servidor', blank=True, null=True, verbose_name=u'usuário') + ocorrencia = models.ForeignKey(Ocorrencia, verbose_name=u'Ocorrência') + data_criacao = models.DateTimeField(u'Data de criação', null=True, blank=True, auto_now_add=True) + descricao = models.TextField(u'Descrição', blank=True, null=True) + usuario = models.ForeignKey('servidores.Servidor', verbose_name=u'Usuário') + novo_status = models.IntegerField(u'Novo status', choices=Ocorrencia.STATUS_CHOICES, blank=True, null=True) + encaminhar_setor = models.ForeignKey('servidores.Servico', verbose_name=u'Encaminhar para setor', blank=True, null=True) class Anexo(models.Model): ocorrencia = models.ForeignKey(Ocorrencia, verbose_name=u'ocorrência') - arquivo = models.FileField(upload_to='apps/ocorrencia/anexo/arquivo',) - descricao = models.CharField('descrição', max_length='70') - data_pub = models.DateTimeField( - 'data da publicação do anexo', - default=datetime.now - ) + arquivo = models.FileField(u'Arquivo anexado', upload_to='apps/ocorrencia/anexo/arquivo',) + descricao = models.CharField(u'descrição do anexo', max_length='70') + data_pub = models.DateTimeField( u'data da publicação do anexo', null=True, blank=True, auto_now_add=True) class Meta: ordering = ('-data_pub',) + verbose_name, verbose_name_plural = u'Anexo', u'Anexos' def __unicode__(self): - return unicode(self.arquivo.name) + return u"%(arquivo_name)s: %(descricao)s" % {'arquivo_name': self.arquivo.name, 'descricao': self.descricao}