| 1 | # -*- coding: utf-8 -*-
|
|---|
| 2 | """ Este módulo é responsável por toda a parte cadastral básica do controle
|
|---|
| 3 | interno.
|
|---|
| 4 |
|
|---|
| 5 | Durante o uso do sistema, este módulo pode ser considerado o "ponto de entrada"
|
|---|
| 6 | pois é aqui que são cadastradas todas as informações essenciais usadas pelos
|
|---|
| 7 | outros módulos/aplicações.
|
|---|
| 8 |
|
|---|
| 9 | .. moduleauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 10 | .. moduleauthor:: Fernando José Loureiro <nando_al@msn.com>
|
|---|
| 11 | """
|
|---|
| 12 |
|
|---|
| 13 | from __future__ import unicode_literals
|
|---|
| 14 |
|
|---|
| 15 | import os
|
|---|
| 16 | import shutil
|
|---|
| 17 |
|
|---|
| 18 | from django.conf import settings
|
|---|
| 19 | from django.db import models
|
|---|
| 20 | from django.db.models import signals
|
|---|
| 21 | from django.db.models.loading import get_models
|
|---|
| 22 |
|
|---|
| 23 | from ci.fields import CharTitleField
|
|---|
| 24 | from ci.fields import CharLowerCaseField
|
|---|
| 25 |
|
|---|
| 26 | from ..models import Base
|
|---|
| 27 | from ..utils.utils import mkdir
|
|---|
| 28 | from ..utils.utils import execute_sql
|
|---|
| 29 | from ..utils.utils import to_ascii
|
|---|
| 30 |
|
|---|
| 31 | from .consts import VERBOSE_ANO
|
|---|
| 32 | from .consts import VERBOSE_ANO_PLURAL
|
|---|
| 33 | from .consts import VERBOSE_EMAIL
|
|---|
| 34 | from .consts import VERBOSE_EMAIL_PLURAL
|
|---|
| 35 | from .consts import VERBOSE_MES
|
|---|
| 36 | from .consts import VERBOSE_MES_PLURAL
|
|---|
| 37 | from .consts import VERBOSE_MES_CODIGO
|
|---|
| 38 | from .consts import VERBOSE_MES_ESPECIAL
|
|---|
| 39 | from .consts import VERBOSE_OPERADORA_TELEFONIA
|
|---|
| 40 | from .consts import VERBOSE_OPERADORA_TELEFONIA_PLURAL
|
|---|
| 41 | from .consts import VERBOSE_TELEFONE
|
|---|
| 42 | from .consts import VERBOSE_TELEFONE_PLURAL
|
|---|
| 43 | from ci.download.models import DownloadSemCategoria
|
|---|
| 44 | from ci.cadastro.consts import VERBOSE_SISTEMA, VERBOSE_SISTEMA_PLURAL
|
|---|
| 45 | from ci.cadastro.tipo.models import TipoHierarquiaBase
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 | class Ano(Base):
|
|---|
| 49 | """ Cadastro de anos.
|
|---|
| 50 |
|
|---|
| 51 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 52 | .. codeauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 53 | """
|
|---|
| 54 | nome = models.IntegerField(unique = True,
|
|---|
| 55 | verbose_name = 'ConfigurationField.objects.get(config_name="verbose_name")',)
|
|---|
| 56 |
|
|---|
| 57 | # def __init__(self, *args, **kwargs):
|
|---|
| 58 | # super(Ano, self).__init__(*args, **kwargs)
|
|---|
| 59 | # for field in self._meta.fields:
|
|---|
| 60 | # print(field.verbose_name)
|
|---|
| 61 | # field.verbose_name = "Teste"
|
|---|
| 62 |
|
|---|
| 63 | class Meta:
|
|---|
| 64 | ordering = ['nome',]
|
|---|
| 65 | verbose_name = VERBOSE_ANO
|
|---|
| 66 | verbose_name_plural = VERBOSE_ANO_PLURAL
|
|---|
| 67 | db_table = "cadastro_ano"
|
|---|
| 68 |
|
|---|
| 69 | def __unicode__(self):
|
|---|
| 70 | return unicode(self.nome)
|
|---|
| 71 |
|
|---|
| 72 |
|
|---|
| 73 | class Mes(Base):
|
|---|
| 74 | """ Cadastro de meses.
|
|---|
| 75 |
|
|---|
| 76 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 77 | .. codeauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 78 | """
|
|---|
| 79 | nome = CharTitleField(max_length = 32,
|
|---|
| 80 | unique = True,
|
|---|
| 81 | verbose_name = VERBOSE_MES,)
|
|---|
| 82 | codigo = models.IntegerField(unique = True,
|
|---|
| 83 | verbose_name = VERBOSE_MES_CODIGO,)
|
|---|
| 84 | mes_especial = models.BooleanField(default = False,
|
|---|
| 85 | verbose_name = VERBOSE_MES_ESPECIAL,)
|
|---|
| 86 |
|
|---|
| 87 | class Meta:
|
|---|
| 88 | ordering = ['codigo']
|
|---|
| 89 | verbose_name = VERBOSE_MES
|
|---|
| 90 | verbose_name_plural = VERBOSE_MES_PLURAL
|
|---|
| 91 | db_table = "cadastro_mes"
|
|---|
| 92 |
|
|---|
| 93 | def __unicode__(self):
|
|---|
| 94 | return self.nome
|
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 | class OperadoraTelefonia(Base):
|
|---|
| 98 | """ Cadastro de operadoras telefônicas.
|
|---|
| 99 |
|
|---|
| 100 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 101 | .. codeauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 102 | """
|
|---|
| 103 | nome = CharTitleField(max_length = 64,
|
|---|
| 104 | unique = True,
|
|---|
| 105 | verbose_name = VERBOSE_OPERADORA_TELEFONIA,)
|
|---|
| 106 |
|
|---|
| 107 | class Meta:
|
|---|
| 108 | ordering = ['nome',]
|
|---|
| 109 | verbose_name = VERBOSE_OPERADORA_TELEFONIA
|
|---|
| 110 | verbose_name_plural = VERBOSE_OPERADORA_TELEFONIA_PLURAL
|
|---|
| 111 | db_table = "cadastro_operadora_telefonia"
|
|---|
| 112 |
|
|---|
| 113 | def __unicode__(self):
|
|---|
| 114 | return self.nome
|
|---|
| 115 |
|
|---|
| 116 |
|
|---|
| 117 | class Email(Base):
|
|---|
| 118 | """ Cadastro de e-mails.
|
|---|
| 119 |
|
|---|
| 120 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 121 | .. codeauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 122 | """
|
|---|
| 123 | endereco = CharLowerCaseField(db_index = True,
|
|---|
| 124 | max_length = 64,
|
|---|
| 125 | verbose_name = VERBOSE_EMAIL,)
|
|---|
| 126 |
|
|---|
| 127 | class Meta:
|
|---|
| 128 | abstract = True
|
|---|
| 129 | verbose_name = VERBOSE_EMAIL
|
|---|
| 130 | verbose_name_plural = VERBOSE_EMAIL_PLURAL
|
|---|
| 131 |
|
|---|
| 132 | def __unicode__(self):
|
|---|
| 133 | return self.endereco
|
|---|
| 134 |
|
|---|
| 135 |
|
|---|
| 136 | class Telefone(Base):
|
|---|
| 137 | """ Cadastro de números telefônicos.
|
|---|
| 138 |
|
|---|
| 139 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 140 | .. codeauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 141 | """
|
|---|
| 142 | numero = models.CharField(db_index = True,
|
|---|
| 143 | max_length = 9,
|
|---|
| 144 | verbose_name = VERBOSE_TELEFONE,)
|
|---|
| 145 |
|
|---|
| 146 | class Meta:
|
|---|
| 147 | abstract = True
|
|---|
| 148 | verbose_name = VERBOSE_TELEFONE
|
|---|
| 149 | verbose_name_plural = VERBOSE_TELEFONE_PLURAL
|
|---|
| 150 |
|
|---|
| 151 |
|
|---|
| 152 | class SistemaCategoria(TipoHierarquiaBase):
|
|---|
| 153 | class Meta:
|
|---|
| 154 | db_table = "cadastro_sistema_categoria"
|
|---|
| 155 |
|
|---|
| 156 |
|
|---|
| 157 | class Sistema(DownloadSemCategoria):
|
|---|
| 158 | """ Cadastro de sistemas.
|
|---|
| 159 |
|
|---|
| 160 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 161 | .. codeauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 162 |
|
|---|
| 163 | Esta classe representa um software que a Tavares & Souza pode alugar para
|
|---|
| 164 | um cliente, como por exemplo um sistema de controle tributário.
|
|---|
| 165 |
|
|---|
| 166 | Qualquer local do controle interno que precise fazer refência a um
|
|---|
| 167 | sistema(e não a qualquer arquivo disponível para download) deve criar uma
|
|---|
| 168 | referência para esta classe.
|
|---|
| 169 |
|
|---|
| 170 | Poderia ter sido usada a classe DownloadSemCategoria para esta função, porém foi
|
|---|
| 171 | decidido criar esta classe especializada para aumentar a flexibilidade do
|
|---|
| 172 | sistema caso seja necessário incluir novas informações para um sistema.
|
|---|
| 173 |
|
|---|
| 174 | """
|
|---|
| 175 | categoria = models.ForeignKey(SistemaCategoria)
|
|---|
| 176 |
|
|---|
| 177 | class Meta:
|
|---|
| 178 | verbose_name = VERBOSE_SISTEMA
|
|---|
| 179 | verbose_name_plural = VERBOSE_SISTEMA_PLURAL
|
|---|
| 180 | db_table = "cadastro_sistema"
|
|---|
| 181 |
|
|---|
| 182 |
|
|---|
| 183 | def mes_pre_save(signal, instance, sender, **kwargs):
|
|---|
| 184 | """ Mantém a consistência dos arquivos no sistema de arquivos.
|
|---|
| 185 |
|
|---|
| 186 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 187 | .. codeauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 188 | .. codeauthor:: Fernando José Loureiro <nando_al@msn.com>
|
|---|
| 189 |
|
|---|
| 190 | Este método garante que caso o nome ou o código de um mês seja alteração
|
|---|
| 191 | os arquivos vínculados a ele sejam movidos para uma nova localização que
|
|---|
| 192 | seja condizente com o nome/código do mês. Isso é feito para manter a
|
|---|
| 193 | consistência do sistema de arquivos, já que o path dos arquivos é montado
|
|---|
| 194 | com base no nome do mês e do código(além de outros dados).
|
|---|
| 195 | """
|
|---|
| 196 | if instance.id:
|
|---|
| 197 | protocolos_arquivo = instance.protocolorelatorio_set.all()
|
|---|
| 198 | old_full_path = None
|
|---|
| 199 |
|
|---|
| 200 | if len(unicode(instance.codigo)) == 1:
|
|---|
| 201 | mes = '0' + unicode(instance.codigo)
|
|---|
| 202 | else:
|
|---|
| 203 | mes = unicode(instance.codigo)
|
|---|
| 204 |
|
|---|
| 205 | mes = mes + '_' + instance.nome
|
|---|
| 206 |
|
|---|
| 207 | for protocolo_relatorio in protocolos_arquivo:
|
|---|
| 208 | for protocolo_relatorio_arquivo in protocolo_relatorio.protocolorelatorioarquivo_set.all():
|
|---|
| 209 | old_full_path = protocolo_relatorio_arquivo.protocolo_relatorio_arquivo.path
|
|---|
| 210 |
|
|---|
| 211 | old_relative_path = protocolo_relatorio_arquivo.protocolo_relatorio_arquivo.name
|
|---|
| 212 |
|
|---|
| 213 | novo_dst = os.path.join(old_relative_path.rsplit('/', 2)[0],
|
|---|
| 214 | mes,
|
|---|
| 215 | old_relative_path.rsplit('/', 1)[-1]
|
|---|
| 216 | )
|
|---|
| 217 |
|
|---|
| 218 | sql = 'update ' + protocolo_relatorio_arquivo._meta.db_table +\
|
|---|
| 219 | ' set ' + protocolo_relatorio_arquivo.protocolo_relatorio_arquivo.field.column + '=\'' +\
|
|---|
| 220 | novo_dst + '\' where id=' + unicode(protocolo_relatorio_arquivo.id)
|
|---|
| 221 |
|
|---|
| 222 | execute_sql(sql.lower())
|
|---|
| 223 |
|
|---|
| 224 | src = old_full_path.rsplit('/', 1)[0]
|
|---|
| 225 | dst = os.path.join(old_full_path.rsplit('/', 2)[0], mes)
|
|---|
| 226 | dst = to_ascii(dst)
|
|---|
| 227 |
|
|---|
| 228 | shutil.move(src.lower(), dst.lower())
|
|---|
| 229 |
|
|---|
| 230 |
|
|---|
| 231 | def generate_custom_sql(**kwargs):
|
|---|
| 232 | """ Cria um arquivo sql para criar esquemas no postgres.
|
|---|
| 233 |
|
|---|
| 234 | .. sectionauthor:: Elton Pereira de Lima <eltonplima@gmail.com>
|
|---|
| 235 | .. codeauthor:: Fernando José Loureiro <nando_al@msn.com>
|
|---|
| 236 |
|
|---|
| 237 | Este método é invocado após a execução do syncdb. Ele gera um arquivo com o
|
|---|
| 238 | nome que foi setado em settings.FIXTURE_FILE_NAME, dentro do diretório:
|
|---|
| 239 | project_name/app_name/sql/nome_do_arquivo.
|
|---|
| 240 | """
|
|---|
| 241 | database_engine = settings.DATABASES['default']['ENGINE']
|
|---|
| 242 |
|
|---|
| 243 | if database_engine.find('postgresql') != 0:
|
|---|
| 244 | pass
|
|---|
| 245 |
|
|---|
| 246 | app = kwargs['app']
|
|---|
| 247 | package = app.__package__
|
|---|
| 248 |
|
|---|
| 249 | if package is not None:
|
|---|
| 250 | PROJECT_APPS = list(settings.PROJECT_APPS)
|
|---|
| 251 | EXTERNAL_APPS = list(settings.EXTERNAL_APPS)
|
|---|
| 252 | try:
|
|---|
| 253 | app_name = package.split('.')[1]
|
|---|
| 254 | package = package.split('.')[-1]
|
|---|
| 255 | FIXTURE_PATH = os.path.join(settings.PROJECT_ROOT_PATH, app_name, 'sql')
|
|---|
| 256 | FIXTURE_FILE = os.path.join(FIXTURE_PATH, settings.FIXTURE_FILE_NAME)
|
|---|
| 257 | PRE_FIXTURE_FILE = os.path.join(FIXTURE_PATH, "pre_fixtures.sql")
|
|---|
| 258 | POS_FIXTURE_FILE = os.path.join(FIXTURE_PATH, "pos_fixtures.sql")
|
|---|
| 259 | PROJECT_APPS = [p.split('.')[-1] for p in PROJECT_APPS]
|
|---|
| 260 | query_external_apps_move = None
|
|---|
| 261 |
|
|---|
| 262 | if EXTERNAL_APPS.index(package) >= 0:
|
|---|
| 263 | query_external_apps_move = "select func_movetablestoschema('%s');" % package
|
|---|
| 264 | except ValueError:
|
|---|
| 265 | pass
|
|---|
| 266 | except IndexError:
|
|---|
| 267 | pass
|
|---|
| 268 |
|
|---|
| 269 | try:
|
|---|
| 270 | if PROJECT_APPS.index(package) >= 0:
|
|---|
| 271 |
|
|---|
| 272 | master_apps = []
|
|---|
| 273 | for p in list(settings.PROJECT_APPS):
|
|---|
| 274 | #coloca apenas as apps que tenham models
|
|---|
| 275 | modelos = get_models()
|
|---|
| 276 | for modelo in modelos:
|
|---|
| 277 | if modelo.__module__.startswith(p):
|
|---|
| 278 | p = p.split('.')[1]
|
|---|
| 279 | if p not in master_apps:
|
|---|
| 280 | master_apps.append(p)
|
|---|
| 281 |
|
|---|
| 282 | apps = ', '.join(master_apps)
|
|---|
| 283 | apps_audit = ''
|
|---|
| 284 |
|
|---|
| 285 | for app in master_apps:
|
|---|
| 286 | apps_audit += app + '_audit, '
|
|---|
| 287 |
|
|---|
| 288 | apps_audit = apps_audit.rsplit(',', 1)[0]
|
|---|
| 289 | query_search_path = 'alter user %s set search_path to public, django, %s, %s;' % (settings.DATABASES['default']['USER'], apps_audit, apps)
|
|---|
| 290 |
|
|---|
| 291 | mkdir(FIXTURE_PATH)
|
|---|
| 292 | query = "select func_movetablestoschema('%s');\n" % app_name
|
|---|
| 293 | query += 'select func_movetablestoschema(\'audit\' ,\'%s\', \'audit\');' % (app_name)
|
|---|
| 294 | fixture_file = open(FIXTURE_FILE,"w")
|
|---|
| 295 |
|
|---|
| 296 | # Envia o conteúdo do arquivo pre_fixtures.sql para o inicio
|
|---|
| 297 | if os.path.isfile(PRE_FIXTURE_FILE):
|
|---|
| 298 | pre_fixture_file = open(PRE_FIXTURE_FILE,"r")
|
|---|
| 299 |
|
|---|
| 300 | for line in pre_fixture_file.readlines():
|
|---|
| 301 | fixture_file.write(line)
|
|---|
| 302 |
|
|---|
| 303 | pre_fixture_file.close()
|
|---|
| 304 |
|
|---|
| 305 | fixture_file.write(query+'\n')
|
|---|
| 306 |
|
|---|
| 307 | # Envia o conteúdo do arquivo pos_fixtures.sql para o final
|
|---|
| 308 | if os.path.isfile(POS_FIXTURE_FILE):
|
|---|
| 309 | pos_fixture_file = open(POS_FIXTURE_FILE,"r")
|
|---|
| 310 |
|
|---|
| 311 | for line in pos_fixture_file.readlines():
|
|---|
| 312 | fixture_file.write(line)
|
|---|
| 313 |
|
|---|
| 314 | pos_fixture_file.close()
|
|---|
| 315 |
|
|---|
| 316 | if query_external_apps_move is not None:
|
|---|
| 317 | fixture_file.write(query_external_apps_move + '\n')
|
|---|
| 318 |
|
|---|
| 319 | fixture_file.write('select func_movetablestoschema(\'django\');\n')
|
|---|
| 320 | fixture_file.write('select func_movetablestoschema(\'auth\' ,\'django\');\n')
|
|---|
| 321 | fixture_file.write('select func_delete_foreignkey_audit();\n')
|
|---|
| 322 | fixture_file.write(query_search_path + '\n')
|
|---|
| 323 | fixture_file.close()
|
|---|
| 324 | except ValueError:
|
|---|
| 325 | pass
|
|---|
| 326 |
|
|---|
| 327 | signals.post_syncdb.connect(generate_custom_sql)
|
|---|
| 328 | #signals.pre_save.connect(mes_pre_save, sender=Mes, dispatch_uid='mes_pre_save')
|
|---|