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')
|
---|