Ticket #19845: models.py

File models.py, 12.1 KB (added by eltonplima@…, 11 years ago)

The models.py

Line 
1# -*- coding: utf-8 -*-
2""" Este módulo é responsável por toda a parte cadastral básica do controle
3interno.
4
5Durante o uso do sistema, este módulo pode ser considerado o "ponto de entrada"
6pois é aqui que são cadastradas todas as informações essenciais usadas pelos
7outros 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
13from __future__ import unicode_literals
14
15import os
16import shutil
17
18from django.conf import settings
19from django.db import models
20from django.db.models import signals
21from django.db.models.loading import get_models
22
23from ci.fields import CharTitleField
24from ci.fields import CharLowerCaseField
25
26from ..models import Base
27from ..utils.utils import mkdir
28from ..utils.utils import execute_sql
29from ..utils.utils import to_ascii
30
31from .consts import VERBOSE_ANO
32from .consts import VERBOSE_ANO_PLURAL
33from .consts import VERBOSE_EMAIL
34from .consts import VERBOSE_EMAIL_PLURAL
35from .consts import VERBOSE_MES
36from .consts import VERBOSE_MES_PLURAL
37from .consts import VERBOSE_MES_CODIGO
38from .consts import VERBOSE_MES_ESPECIAL
39from .consts import VERBOSE_OPERADORA_TELEFONIA
40from .consts import VERBOSE_OPERADORA_TELEFONIA_PLURAL
41from .consts import VERBOSE_TELEFONE
42from .consts import VERBOSE_TELEFONE_PLURAL
43from ci.download.models import DownloadSemCategoria
44from ci.cadastro.consts import VERBOSE_SISTEMA, VERBOSE_SISTEMA_PLURAL
45from ci.cadastro.tipo.models import TipoHierarquiaBase
46
47
48class 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
73class 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
97class 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
117class 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
136class 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
152class SistemaCategoria(TipoHierarquiaBase):
153 class Meta:
154 db_table = "cadastro_sistema_categoria"
155
156
157class 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
183def 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
231def 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
327signals.post_syncdb.connect(generate_custom_sql)
328#signals.pre_save.connect(mes_pre_save, sender=Mes, dispatch_uid='mes_pre_save')
Back to Top