Python3 compatibility
[vagrant-mail.git] / database / platal / models.py
CommitLineData
f497e0a9
NI
1# -*- coding: utf-8 -*-
2#***************************************************************************
3#* Copyright (C) 2015 Polytechnique.org *
4#* http://opensource.polytechnique.org/ *
5#* *
6#* This program is free software; you can redistribute it and/or modify *
7#* it under the terms of the GNU General Public License as published by *
8#* the Free Software Foundation; either version 2 of the License, or *
9#* (at your option) any later version. *
10#* *
11#* This program is distributed in the hope that it will be useful, *
12#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14#* GNU General Public License for more details. *
15#* *
16#* You should have received a copy of the GNU General Public License *
17#* along with this program; if not, write to the Free Software *
18#* Foundation, Inc., *
19#* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20#***************************************************************************/
21"""Django models which fit the latest version of Plat/al database
22
23Latest version synced: Plat/al 1.1.15
24https://github.com/Polytechnique-org/platal/tree/xorg/maint/upgrade
25
26This requires Django to work.
27"""
27b0b59f 28from __future__ import unicode_literals
f497e0a9
NI
29import collections
30from django.db import models
27b0b59f 31from django.utils.encoding import python_2_unicode_compatible
f497e0a9
NI
32
33
34def is_ax_visible(field):
35 return field in ('public', 'ax')
36
37
38# Misc for Account/Profile
39# ========================
40
41
27b0b59f 42@python_2_unicode_compatible
f497e0a9
NI
43class Skin(models.Model):
44 #id = models.IntegerField(primary_key=True)
45 name = models.CharField(max_length=96)
46 date = models.DateField()
47 comment = models.CharField(max_length=765)
48 auteur = models.CharField(max_length=90)
49 skin_tpl = models.CharField(max_length=96)
50 ext = models.CharField(max_length=9)
51 class Meta:
27b0b59f 52 db_table = 'skins'
f497e0a9 53
27b0b59f 54 def __str__(self):
f497e0a9
NI
55 return self.name
56
57
27b0b59f 58@python_2_unicode_compatible
f497e0a9
NI
59class EmailVirtualDomain(models.Model):
60 #id = models.IntegerField(primary_key=True)
61 name = models.CharField(max_length=765)
62 aliasing = models.ForeignKey('self', db_column='aliasing')
63 class Meta:
27b0b59f 64 db_table = 'email_virtual_domains'
f497e0a9 65
27b0b59f 66 def __str__(self):
f497e0a9
NI
67 return self.name
68
69
27b0b59f 70@python_2_unicode_compatible
f497e0a9
NI
71class ProfileSectionEnum(models.Model):
72 #id = models.IntegerField(primary_key=True)
73 text = models.CharField(max_length=150, unique=True)
74 class Meta:
27b0b59f 75 db_table = 'profile_section_enum'
f497e0a9 76
27b0b59f 77 def __str__(self):
f497e0a9
NI
78 return self.text
79
80
27b0b59f 81@python_2_unicode_compatible
f497e0a9
NI
82class GeolocCountry(models.Model):
83 iso_3166_1_a2 = models.CharField(max_length=6, primary_key=True)
84 iso_3166_1_a3 = models.CharField(max_length=9, unique=True)
85 iso_3166_1_num = models.IntegerField(unique=True)
86 worldregion = models.CharField(max_length=6, db_column='worldRegion', blank=True) # Field name made lowercase.
87 country = models.CharField(max_length=765, blank=True)
88 countryen = models.CharField(max_length=765, db_column='countryEn', blank=True) # Field name made lowercase.
89 capital = models.CharField(max_length=765)
90 nationality = models.CharField(max_length=765, blank=True)
91 nationalityen = models.CharField(max_length=765, db_column='nationalityEn', blank=True) # Field name made lowercase.
92 phoneprefix = models.IntegerField(null=True, db_column='phonePrefix', blank=True) # Field name made lowercase.
93 phoneformat = models.CharField(max_length=765, db_column='phoneFormat') # Field name made lowercase.
94 licenseplate = models.CharField(max_length=12, db_column='licensePlate', blank=True) # Field name made lowercase.
95 belongsto = models.ForeignKey('self', null=True, db_column='belongsTo', blank=True) # Field name made lowercase.
96 countryplain = models.CharField(max_length=765, db_column='countryPlain', blank=True) # Field name made lowercase.
97 class Meta:
27b0b59f 98 db_table = 'geoloc_countries'
f497e0a9 99
27b0b59f 100 def __str__(self):
f497e0a9
NI
101 return self.iso_3166_1_a2
102
103
104# Account/Profile
105# ===============
106
107
27b0b59f 108@python_2_unicode_compatible
f497e0a9
NI
109class AccountType(models.Model):
110 type = models.CharField(max_length=48, primary_key=True)
111 perms = models.CharField(max_length=321)
112 description = models.TextField(blank=True)
113 class Meta:
27b0b59f 114 db_table = 'account_types'
f497e0a9 115
27b0b59f 116 def __str__(self):
f497e0a9
NI
117 return self.type
118
119
27b0b59f 120@python_2_unicode_compatible
f497e0a9
NI
121class Account(models.Model):
122 uid = models.AutoField(primary_key=True)
123 hruid = models.CharField(max_length=255, unique=True)
124 type = models.ForeignKey(AccountType, null=True, db_column='type', blank=True)
125 user_perms = models.CharField(max_length=288, blank=True)
126 is_admin = models.BooleanField()
127 state = models.CharField(max_length=24)
128 password = models.CharField(max_length=120, blank=True)
129 token = models.CharField(max_length=96, blank=True)
130 weak_password = models.CharField(max_length=768, blank=True)
131 registration_date = models.DateTimeField()
132 flags = models.CharField(max_length=15)
133 comment = models.CharField(max_length=765, blank=True)
134 email = models.CharField(max_length=765, blank=True)
135 firstname = models.CharField(max_length=765, blank=True)
136 lastname = models.CharField(max_length=765, blank=True)
137 full_name = models.CharField(max_length=765, blank=True)
138 directory_name = models.CharField(max_length=765, blank=True)
139 sort_name = models.CharField(max_length=765, blank=True)
140 display_name = models.CharField(max_length=765, blank=True)
141 sex = models.CharField(max_length=18)
142 email_format = models.CharField(max_length=12)
143 skin = models.ForeignKey(Skin, null=True, db_column='skin', blank=True)
144 last_version = models.CharField(max_length=48)
145 best_domain = models.ForeignKey(EmailVirtualDomain, null=True, db_column='best_domain', blank=True)
146 from_email = models.CharField(max_length=765)
147 from_format = models.CharField(max_length=12)
148 class Meta:
27b0b59f 149 db_table = 'accounts'
f497e0a9 150
27b0b59f
NI
151 def __str__(self):
152 return '%s (%s)' % (self.hruid, self.full_name)
f497e0a9
NI
153
154 @property
155 def profile(self):
156 return self.profiles.filter(perms='owner').get().profile
157
158
27b0b59f 159@python_2_unicode_compatible
f497e0a9
NI
160class ProfileAlias(object):
161 def __init__(self, alias_of, kind, lastname, firstname=None):
162 self.alias_of = alias_of
163 self.kind = kind
164 self.lastname = lastname
165 self.firstname = alias_of.firstname if firstname is None else firstname
166
167 ALT_MARITAL = 'marital'
168 ALT_PSEUDO = 'pseudo'
169 ALT_ORDINARY = 'ordinary'
170
171 @property
172 def is_pseudo(self):
173 return self.kind == self.ALT_PSEUDO
174
175 def get_kind_display(self):
176 if self.kind == self.ALT_MARITAL:
177 if self.female:
27b0b59f 178 return "Mme"
f497e0a9 179 else:
27b0b59f 180 return "M."
f497e0a9 181 elif self.kind == self.ALT_PSEUDO:
27b0b59f 182 return "Pseudonyme"
f497e0a9 183 else:
27b0b59f 184 return ""
f497e0a9
NI
185
186 def __getattr__(self, attr):
187 return getattr(self.alias_of, attr)
188
189 def __repr__(self):
190 return '<ProfileAlias %s of %r>' % (self.kind, self.alias_of)
191
192
27b0b59f 193@python_2_unicode_compatible
f497e0a9
NI
194class Profile(models.Model):
195
196 alias_of = None
197
198 def __init__(self, *args, **kwargs):
199 super(Profile, self).__init__(*args, **kwargs)
200 self._aliases = None
201
202 pid = models.AutoField(primary_key=True)
203 hrpid = models.CharField(max_length=255, unique=True)
204 xorg_id = models.IntegerField()
205 ax_id = models.CharField(max_length=24, blank=True)
206 birthdate = models.DateField(null=True, blank=True)
207 birthdate_ref = models.DateField(null=True, blank=True)
208 next_birthday = models.DateField(null=True, blank=True)
209 deathdate = models.DateField(null=True, blank=True)
210 deathdate_rec = models.DateField(null=True, blank=True)
211 sex = models.CharField(max_length=18)
212 section = models.ForeignKey(ProfileSectionEnum, null=True, db_column='section', blank=True)
213 cv = models.TextField(blank=True)
214 freetext = models.TextField(blank=True)
215 freetext_pub = models.CharField(max_length=21)
216 medals_pub = models.CharField(max_length=21)
217 alias_pub = models.CharField(max_length=21)
218 nationality1 = models.ForeignKey(GeolocCountry, null=True, db_column='nationality1', blank=True, related_name='natives')
219 nationality2 = models.ForeignKey(GeolocCountry, null=True, db_column='nationality2', blank=True, related_name='second_natives')
220 nationality3 = models.ForeignKey(GeolocCountry, null=True, db_column='nationality3', blank=True, related_name='third_natives')
221 email_directory = models.CharField(max_length=765, blank=True)
222 last_change = models.DateField()
223 title = models.CharField(max_length=12)
224
225 class Meta:
27b0b59f 226 db_table = 'profiles'
f497e0a9 227
27b0b59f 228 def __str__(self):
f497e0a9
NI
229 return self.hrpid
230
231 @property
232 def is_alive(self):
233 return self.deathdate is None
234
235 @property
236 def account(self):
237 return self.accounts.filter(perms='owner').get().account
238
239 @property
240 def firstname(self):
241 return self.public_name.firstname_ordinary or self.public_name.firstname_main or self.public_name.firstname_initial
242
243 @property
244 def lastname(self):
245 return self.public_name.lastname_main or self.public_name.lastname_initial
246
247 @property
248 def lastname_display(self):
249 return self.public_name.lastname_ordinary or self.public_name.lastname_marital or self.public_name.lastname_main or self.public_name.lastname_initial
250
251 @property
252 def lastname_marital(self):
253 return self.public_name.lastname_marital
254
255 @property
256 def lastname_ordinary(self):
257 return self.public_name.lastname_ordinary
258
259 @property
260 def pseudonym(self):
261 return self.public_name.pseudonym
262
263 @property
264 def promo(self):
265 return self.profiledisplay.promo
266
267 @property
268 def female(self):
269 return self.sex == 'female'
270
271 @property
272 def nationality(self):
273 return self.nationality1 or self.nationality2 or self.nationality3
274
275 @property
276 def country_code(self):
277 nat = self.nationality
278 if nat is None:
279 return 'FR'
280 return nat.iso_3166_1_a2
281
282 @property
283 def country_name(self):
284 nat = self.nationality
285 if nat is None:
27b0b59f 286 return "France"
f497e0a9
NI
287 return nat.country
288
289 @property
290 def current_corps(self):
291 try:
292 return self.profilecorps.current
293 except ProfileCorps.DoesNotExist:
294 return None
295
296 def get_aliases(self, include_deviations=True):
297 if self._aliases is None:
298 self._aliases = []
299
300 alt_names = set([self.lastname])
301 if self.lastname_marital and self.lastname_marital not in alt_names:
302 alt_names.add(self.lastname_marital)
303 self._aliases.append(
304 ProfileAlias(self, ProfileAlias.ALT_MARITAL, self.lastname_marital))
305
306 if self.lastname_ordinary and self.lastname_ordinary not in alt_names:
307 # Some people filled 'ordinary' instead of 'marital'
308 alt_names.add(self.lastname_ordinary)
309 self._aliases.append(
310 ProfileAlias(self, ProfileAlias.ALT_ORDINARY, self.lastname_ordinary))
311
312 if self.pseudonym and self.pseudonym not in alt_names:
313 alt_names.add(self.pseudonym)
314 self._aliases.append(
315 ProfileAlias(self, ProfileAlias.ALT_PSEUDO, self.pseudonym, firstname=''))
316
317 if include_deviations:
318 return self._aliases
319 else:
320 return [a for a in self._aliases
321 if not a.lastname.startswith(self.lastname)
322 and not self.lastname.startswith(a.lastname)
323 ]
324
325 @property
326 def mobile_line(self):
327 if not hasattr(self, '_mobiles'):
328 mobiles = [phone
329 for phone in self.phones.all()
330 if phone.link_type == phone.LINK_USER and phone.tel_type == phone.KIND_MOBILE
331 ]
332 self._mobiles = sorted(mobiles, key=lambda p: p.tel_id)
333 if self._mobiles:
334 return self._mobiles[0]
335 return None
336
337 def sorted_addresses(self, for_ax=False):
338 personal_addresses = [addr
339 for addr in self.addresses.all()
340 if addr.is_home and (addr.ax_visible or not for_ax)
341 ]
342
343 address_phones = collections.defaultdict(lambda: collections.defaultdict(list))
344
345 for phone in self.phones.all():
346 if phone.is_address and (phone.ax_visible or not for_ax):
347 address_phones[phone.link_id][phone.tel_type].append(phone)
348
349 for address in personal_addresses:
350 addr_phones = {}
351 for kind, phones in address_phones[address.subid].items():
352 if phones:
353 addr_phones[kind] = sorted(phones, key=lambda p: p.tel_id)[0]
354 else:
355 addr_phones[kind] = None
356 address.phones = addr_phones
357
358 current = [addr for addr in personal_addresses if addr.current]
359 secondary = [addr for addr in personal_addresses if addr.secondary and not addr.current]
360 if not current:
361 current, secondary = secondary, []
362
363 return [(a, True) for a in current] + [(a, False) for a in secondary]
364
365 def sorted_educations(self):
366 edus = [edu for edu in self.educations.all() if edu.school and edu.school.abbreviation != 'X']
367 return sorted(edus, key=lambda edu: edu.entry_year)
368
369 def sorted_jobs(self):
370 jobs = sorted(self.jobs.all(), key=lambda j: (j.id, j.entry_year))
371 job_addresses = {}
372 for addr in self.addresses.all():
373 if addr.is_job:
374 job_addresses[addr.job_id] = addr
375
376 job_phones = collections.defaultdict(lambda: collections.defaultdict(list))
377 for phone in self.phones.all():
378 if phone.is_job:
379 job_phones[phone.link_id][phone.tel_type].append(phone)
380
381 for job in jobs:
382 job.address = job_addresses.get(job.id)
383 j_phones = {}
384 for kind, phones in job_phones[job.id].items():
385 if phones:
386 j_phones[kind] = sorted(phones, key=lambda p: p.tel_id)[0]
387 else:
388 j_phones[kind] = None
389 job.phones = j_phones
390
391 return jobs
392
393
27b0b59f 394@python_2_unicode_compatible
f497e0a9
NI
395class AccountProfile(models.Model):
396 account = models.ForeignKey(Account, db_column='uid', related_name='profiles')
397 profile = models.ForeignKey(Profile, db_column='pid', related_name='accounts')
398 pkey = models.CompositeField(account, profile, primary_key=True)
399 perms = models.CharField(max_length=15)
400 class Meta:
27b0b59f 401 db_table = 'account_profiles'
f497e0a9 402
27b0b59f
NI
403 def __str__(self):
404 return '%s -> %s' % (self.account.hruid, self.profile.hrpid)
f497e0a9
NI
405
406
407# Account-related
408# ===============
409
410
27b0b59f 411@python_2_unicode_compatible
f497e0a9
NI
412class AccountAuthOpenid(models.Model):
413 #id = models.IntegerField(primary_key=True)
414 account = models.ForeignKey(Account, unique=True, null=True, db_column='uid', blank=True)
415 url = models.CharField(max_length=255, unique=True)
416 class Meta:
27b0b59f 417 db_table = 'account_auth_openid'
f497e0a9 418
27b0b59f
NI
419 def __str__(self):
420 return "%s at %s" % (self.account, self.url)
f497e0a9 421
27b0b59f 422@python_2_unicode_compatible
f497e0a9
NI
423class AccountLostPassword(models.Model):
424 certificat = models.CharField(max_length=96, primary_key=True)
425 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
426 created = models.DateTimeField(null=True, blank=True)
427 class Meta:
27b0b59f 428 db_table = 'account_lost_passwords'
f497e0a9 429
27b0b59f
NI
430 def __str__(self):
431 return "%s on %s" % (self.account.hruid, self.created)
f497e0a9
NI
432
433
27b0b59f 434@python_2_unicode_compatible
f497e0a9
NI
435class AccountXnetLostPassword(models.Model):
436 account = models.ForeignKey(Account, primary_key=True, db_column='uid')
437 date = models.DateTimeField(null=True, blank=True)
438 hash = models.CharField(max_length=96)
439 class Meta:
27b0b59f 440 db_table = 'account_xnet_lost_passwords'
f497e0a9 441
27b0b59f
NI
442 def __str__(self):
443 return "%s on %s" % (self.account.hruid, self.date)
f497e0a9
NI
444
445
446# Announces
447# =========
448
449
27b0b59f 450@python_2_unicode_compatible
f497e0a9
NI
451class Announce(models.Model):
452 #id = models.IntegerField(primary_key=True)
453 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
454 creation_date = models.DateTimeField()
455 titre = models.CharField(max_length=765)
456 texte = models.TextField()
457 expiration = models.DateField()
458 promo_min = models.IntegerField()
459 promo_max = models.IntegerField()
460 flags = models.CharField(max_length=87)
461 noinvite = models.IntegerField()
462 post_id = models.IntegerField(null=True, blank=True, editable=False,
463 help_text=u"NNTP post identifier")
464 class Meta:
27b0b59f 465 db_table = 'announces'
f497e0a9 466
27b0b59f
NI
467 def __str__(self):
468 return "%s: %s" % (self.id, self.titre)
f497e0a9
NI
469
470
27b0b59f 471@python_2_unicode_compatible
f497e0a9
NI
472class AnnouncePhoto(models.Model):
473 eid = models.ForeignKey(Announce, primary_key=True, db_column='eid')
474 attachmime = models.CharField(max_length=12)
475 attach = models.TextField()
476 x = models.IntegerField()
477 y = models.IntegerField()
478 class Meta:
27b0b59f 479 db_table = 'announce_photos'
f497e0a9 480
27b0b59f
NI
481 def __str__(self):
482 return "%s (%s, %d x %d)" % (self.eid, self.attachmime, self.x, self.y)
f497e0a9
NI
483
484
27b0b59f 485@python_2_unicode_compatible
f497e0a9
NI
486class AnnounceRead(models.Model):
487 evt = models.ForeignKey(Announce)
488 account = models.ForeignKey(Account, db_column='uid')
489 pkey = models.CompositeField(evt, account, primary_key=True)
490 class Meta:
27b0b59f 491 db_table = 'announce_read'
f497e0a9 492
27b0b59f
NI
493 def __str__(self):
494 return "%s: %s" % (self.account, self.evt)
f497e0a9
NI
495
496
497# Email routing
498# =============
499
500
27b0b59f 501@python_2_unicode_compatible
f497e0a9
NI
502class EmailVirtual(models.Model):
503 email = models.CharField(max_length=255)
504 domain = models.ForeignKey(EmailVirtualDomain, db_column='domain')
505 pkey = models.CompositeField(email, domain, primary_key=True)
506 redirect = models.CharField(max_length=765)
507 type = models.CharField(max_length=21, blank=True)
508 expire = models.DateField()
509 class Meta:
27b0b59f 510 db_table = 'email_virtual'
f497e0a9 511
27b0b59f
NI
512 def __str__(self):
513 return "%s@%s (%s)" % (self.email, self.domain, self.type)
f497e0a9
NI
514
515
27b0b59f 516@python_2_unicode_compatible
f497e0a9
NI
517class EmailRedirectAccount(models.Model):
518 account = models.ForeignKey(Account, db_column='uid')
519 redirect = models.CharField(max_length=765)
520 pkey = models.CompositeField(account, redirect, primary_key=True)
521 rewrite = models.CharField(max_length=765)
522 type = models.CharField(max_length=30)
523 action = models.CharField(max_length=54)
524 broken_date = models.DateField()
525 broken_level = models.IntegerField()
526 last = models.DateField()
527 flags = models.CharField(max_length=24)
528 hash = models.CharField(max_length=96, blank=True)
529 allow_rewrite = models.BooleanField()
530 class Meta:
27b0b59f 531 db_table = 'email_redirect_account'
f497e0a9 532
27b0b59f
NI
533 def __str__(self):
534 return "%s for %s (%s)" % (self.redirect, self.account.hruid, self.type)
f497e0a9
NI
535
536
27b0b59f 537@python_2_unicode_compatible
f497e0a9
NI
538class EmailSourceAccount(models.Model):
539 email = models.CharField(max_length=255)
540 domain = models.ForeignKey(EmailVirtualDomain, db_column='domain')
541 pkey = models.CompositeField(email, domain, primary_key=True)
542
543 account = models.ForeignKey(Account, db_column='uid')
544 type = models.CharField(max_length=27)
545 flags = models.CharField(max_length=69)
546 expire = models.DateField(null=True, blank=True)
547 class Meta:
27b0b59f 548 db_table = 'email_source_account'
f497e0a9 549
27b0b59f
NI
550 def __str__(self):
551 return "%s@%s (%s)" % (self.email, self.domain, self.type)
f497e0a9
NI
552
553
27b0b59f 554@python_2_unicode_compatible
f497e0a9
NI
555class EmailSourceOther(models.Model):
556 email = models.CharField(max_length=255)
557 domain = models.ForeignKey(EmailVirtualDomain, db_column='domain')
558 pkey = models.CompositeField(email, domain, primary_key=True)
559
560 hrmid = models.CharField(max_length=765)
561 type = models.CharField(max_length=24, blank=True)
562 expire = models.DateField(null=True, blank=True)
563 class Meta:
27b0b59f 564 db_table = 'email_source_other'
f497e0a9 565
27b0b59f
NI
566 def __str__(self):
567 return "%s@%s (%s)" % (self.email, self.domain, self.type)
f497e0a9
NI
568
569
27b0b59f 570@python_2_unicode_compatible
f497e0a9
NI
571class EmailRedirectOther(models.Model):
572 hrmid = models.ForeignKey(EmailSourceOther, db_column='hrmid')
573 redirect = models.CharField(max_length=765)
574 pkey = models.CompositeField(hrmid, redirect, primary_key=True)
575 type = models.CharField(max_length=30)
576 action = models.CharField(max_length=54)
577 class Meta:
27b0b59f 578 db_table = 'email_redirect_other'
f497e0a9 579
27b0b59f
NI
580 def __str__(self):
581 return "%s -> %s (%s)" % (self.hrmid, self.redirect, self.type)
f497e0a9
NI
582
583
584# innd-related
585# ============
586
587
27b0b59f 588@python_2_unicode_compatible
f497e0a9
NI
589class InndForum(models.Model):
590 """ACLs for innd"""
591 id_innd = models.AutoField(primary_key=True)
592 ipmin = models.IntegerField(null=True, blank=True)
593 ipmax = models.IntegerField(null=True, blank=True)
594 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
595 read_perm = models.CharField(max_length=300, blank=True)
596 write_perm = models.CharField(max_length=300, blank=True)
597 priority = models.IntegerField(null=True, blank=True)
598 comment = models.TextField(blank=True)
599 class Meta:
27b0b59f 600 db_table = 'forum_innd'
f497e0a9 601
27b0b59f 602 def __str__(self):
f497e0a9
NI
603 return "%d: %s" % (self.id_innd, self.account.hruid)
604
605
27b0b59f 606@python_2_unicode_compatible
f497e0a9
NI
607class ForumProfile(models.Model):
608 account = models.ForeignKey(Account, primary_key=True, db_column='uid')
609 name = models.CharField(max_length=192)
610 mail = models.CharField(max_length=210)
611 sig = models.TextField()
612 flags = models.CharField(max_length=63)
613 tree_unread = models.CharField(max_length=24)
614 tree_read = models.CharField(max_length=24)
615 last_seen = models.DateTimeField()
616 class Meta:
27b0b59f 617 db_table = 'forum_profiles'
f497e0a9 618
27b0b59f
NI
619 def __str__(self):
620 return "%s: %s" % (self.account.hruid, self.name)
f497e0a9
NI
621
622
27b0b59f 623@python_2_unicode_compatible
f497e0a9
NI
624class Forum(models.Model):
625 fid = models.IntegerField(primary_key=True)
626 name = models.CharField(max_length=192)
627 class Meta:
27b0b59f 628 db_table = 'forums'
f497e0a9 629
27b0b59f 630 def __str__(self):
f497e0a9
NI
631 return self.name
632
633
27b0b59f 634@python_2_unicode_compatible
f497e0a9
NI
635class ForumSubs(models.Model):
636 forum = models.ForeignKey(Forum, db_column='fid')
637 account = models.ForeignKey(Account, db_column='uid')
638 pkey = models.CompositeField(forum, account, primary_key=True)
639 class Meta:
27b0b59f 640 db_table = 'forum_subs'
f497e0a9 641
27b0b59f
NI
642 def __str__(self):
643 return "%s by %s" % (self.forum.name, self.account.hruid)
f497e0a9
NI
644
645
646# Payments
647# ========
648
649
27b0b59f 650@python_2_unicode_compatible
f497e0a9
NI
651class PaymentBankAccount(models.Model):
652 #id = models.IntegerField(primary_key=True)
653 asso = models.ForeignKey('Group', blank=True, null=True)
654 iban = models.CharField(max_length=33)
655 owner = models.CharField(max_length=300)
656 status = models.CharField(max_length=36)
657 bic = models.CharField(max_length=11)
658 class Meta:
27b0b59f 659 db_table = 'payment_bankaccounts'
f497e0a9 660
27b0b59f
NI
661 def __str__(self):
662 return '%s: %s' % (self.asso.name, self.account)
f497e0a9
NI
663
664
27b0b59f 665@python_2_unicode_compatible
f497e0a9
NI
666class Payment(models.Model):
667 #id = models.IntegerField(primary_key=True)
668 text = models.CharField(max_length=765)
669 url = models.CharField(max_length=384)
670 flags = models.CharField(max_length=51)
671 amount_def = models.DecimalField(max_digits=12, decimal_places=2)
672 amount_min = models.DecimalField(max_digits=12, decimal_places=2)
673 amount_max = models.DecimalField(max_digits=12, decimal_places=2)
674 mail = models.CharField(max_length=192)
675 confirmation = models.TextField()
676 asso = models.ForeignKey('Group', null=True, blank=True)
677 rib = models.ForeignKey(PaymentBankAccount)
678 class Meta:
27b0b59f 679 db_table = 'payments'
f497e0a9 680
27b0b59f
NI
681 def __str__(self):
682 return "%s: %s" % (self.id, self.text)
f497e0a9
NI
683
684
27b0b59f 685@python_2_unicode_compatible
f497e0a9
NI
686class PaymentCodeC(models.Model):
687 id = models.IntegerField(primary_key=True)
688 text = models.CharField(max_length=192)
689 class Meta:
27b0b59f 690 db_table = 'payment_codeC'
f497e0a9 691
27b0b59f 692 def __str__(self):
f497e0a9
NI
693 return self.text
694
695
27b0b59f 696@python_2_unicode_compatible
f497e0a9
NI
697class PaymentCodeRCB(models.Model):
698 id = models.IntegerField(primary_key=True)
699 text = models.CharField(max_length=192)
700 codec = models.IntegerField(db_column='codeC') # Field name made lowercase.
701 class Meta:
27b0b59f 702 db_table = 'payment_codeRCB'
f497e0a9 703
27b0b59f 704 def __str__(self):
f497e0a9
NI
705 return self.text
706
707
27b0b59f 708@python_2_unicode_compatible
f497e0a9
NI
709class PaymentMethod(models.Model):
710 id = models.IntegerField(primary_key=True)
711 text = models.CharField(max_length=96)
712 include = models.CharField(max_length=96)
713 short_name = models.CharField(max_length=30)
714 flags = models.CharField(max_length=36, blank=True)
715 class Meta:
27b0b59f 716 db_table = 'payment_methods'
f497e0a9 717
27b0b59f 718 def __str__(self):
f497e0a9
NI
719 return self.short_name
720
721
27b0b59f 722@python_2_unicode_compatible
f497e0a9
NI
723class PaymentReconcilation(models.Model):
724 #id = models.IntegerField(primary_key=True)
725 method = models.ForeignKey(PaymentMethod)
726 period_start = models.DateField()
727 period_end = models.DateField()
728 status = models.CharField(max_length=33)
729 payment_count = models.IntegerField()
730 sum_amounts = models.DecimalField(max_digits=11, decimal_places=2)
731 sum_commissions = models.DecimalField(max_digits=11, decimal_places=2)
732 comments = models.TextField()
733 recongroup_id = models.IntegerField(null=True, blank=True)
734 class Meta:
27b0b59f 735 db_table = 'payment_reconcilations'
f497e0a9 736
27b0b59f
NI
737 def __str__(self):
738 return "%s: %s" % (self.method, self.status)
f497e0a9
NI
739
740
27b0b59f 741@python_2_unicode_compatible
f497e0a9
NI
742class PaymentTransaction(models.Model):
743 id = models.CharField(max_length=192, primary_key=True)
744 method = models.ForeignKey(PaymentMethod, null=True, blank=True)
745 account = models.ForeignKey(Account, db_column='uid')
746 ref = models.IntegerField()
747 fullref = models.CharField(max_length=45)
748 ts_confirmed = models.DateTimeField(null=True, blank=True)
749 ts_initiated = models.DateTimeField(null=True, blank=True)
750 amount = models.DecimalField(max_digits=11, decimal_places=2)
751 commission = models.DecimalField(null=True, max_digits=11, decimal_places=2, blank=True)
752 pkey = models.CharField(max_length=15)
753 comment = models.CharField(max_length=765)
754 status = models.CharField(max_length=27)
755 recon = models.ForeignKey(PaymentReconcilation, null=True, blank=True)
756 display = models.IntegerField()
757 class Meta:
27b0b59f 758 db_table = 'payment_transactions'
f497e0a9 759
27b0b59f
NI
760 def __str__(self):
761 return "%s (%s)" % (self.fullref, self.ref)
f497e0a9
NI
762
763
27b0b59f 764@python_2_unicode_compatible
f497e0a9
NI
765class PaymentTransfer(models.Model):
766 #id = models.IntegerField(primary_key=True)
767 recongroup_id = models.IntegerField()
768 payment = models.ForeignKey(Payment)
769 amount = models.DecimalField(max_digits=11, decimal_places=2)
770 account = models.ForeignKey(Account, null=True, blank=True)
771 message = models.CharField(max_length=765)
772 date = models.DateField(null=True, blank=True)
773 class Meta:
27b0b59f 774 db_table = 'payment_transfers'
f497e0a9 775
27b0b59f
NI
776 def __str__(self):
777 return "%s: %s" % (self.id, self.amount)
f497e0a9
NI
778
779
780# Groups
781# ======
782
783
27b0b59f 784@python_2_unicode_compatible
f497e0a9
NI
785class GroupDom(models.Model):
786 #id = models.IntegerField(primary_key=True)
787 name = models.TextField(db_column='nom')
788 cat = models.CharField(max_length=117)
789 class Meta:
27b0b59f 790 db_table = 'group_dom'
f497e0a9 791
27b0b59f
NI
792 def __str__(self):
793 return "%s :: %s" % (self.cat, self.name)
f497e0a9
NI
794
795
27b0b59f 796@python_2_unicode_compatible
f497e0a9
NI
797class Group(models.Model):
798 #id = models.IntegerField(primary_key=True)
799 name = models.CharField(max_length=765, db_column='nom')
800 diminutif = models.CharField(max_length=192, unique=True)
801 cat = models.CharField(max_length=117)
802 dom = models.ForeignKey(GroupDom, null=True, db_column='dom', blank=True)
803 descr = models.TextField()
804 logo = models.TextField(blank=True)
805 logo_mime = models.TextField(blank=True)
806 site = models.CharField(max_length=765)
807 mail = models.CharField(max_length=765)
808 resp = models.CharField(max_length=765)
809 forum = models.CharField(max_length=765)
810 mail_domain = models.CharField(max_length=765)
811 ax = models.IntegerField()
812 pub = models.CharField(max_length=21)
813 sub_url = models.CharField(max_length=765)
814 inscriptible = models.IntegerField()
815 unsub_url = models.CharField(max_length=765)
816 flags = models.CharField(max_length=117)
817 axdate = models.DateField(null=True, db_column='axDate', blank=True) # Field name made lowercase.
818 welcome_msg = models.TextField(blank=True)
819 event_order = models.CharField(max_length=8)
820 disable_mails = models.BooleanField()
821 status = models.CharField(max_length=117)
822 class Meta:
27b0b59f 823 db_table = 'groups'
f497e0a9 824
27b0b59f 825 def __str__(self):
f497e0a9
NI
826 return self.name
827
828
829# Group::membership
830# -----------------
831
832
27b0b59f 833@python_2_unicode_compatible
f497e0a9
NI
834class GroupMember(models.Model):
835 asso = models.ForeignKey(Group)
836 account = models.ForeignKey(Account, db_column='uid')
837 pkey = models.CompositeField(asso, account, primary_key=True)
838
839 perms = models.CharField(max_length=18)
840 comm = models.CharField(max_length=765, blank=True)
841 position = models.CharField(max_length=54, blank=True)
842 flags = models.CharField(max_length=18)
843 class Meta:
27b0b59f 844 db_table = 'group_members'
f497e0a9 845
27b0b59f
NI
846 def __str__(self):
847 return "%s to %s" % (self.account.hruid, self.asso.name)
f497e0a9
NI
848
849
27b0b59f 850@python_2_unicode_compatible
f497e0a9
NI
851class GroupMemberSubRequest(models.Model):
852 asso = models.ForeignKey(Group)
853 account = models.ForeignKey(Account, db_column='uid')
854 pkey = models.CompositeField(asso, account, primary_key=True)
855
856 ts = models.DateTimeField()
857 reason = models.TextField(blank=True)
858 class Meta:
27b0b59f 859 db_table = 'group_member_sub_requests'
f497e0a9 860
27b0b59f
NI
861 def __str__(self):
862 return "%s to %s" % (self.account.hruid, self.asso.name)
f497e0a9
NI
863
864
27b0b59f 865@python_2_unicode_compatible
f497e0a9
NI
866class GroupFormerMember(models.Model):
867 asso = models.ForeignKey(Group)
868 account = models.ForeignKey(Account, db_column='uid')
869 pkey = models.CompositeField(asso, account, primary_key=True)
870
871 remember = models.IntegerField()
872 unsubsciption_date = models.DateField()
873 class Meta:
27b0b59f 874 db_table = 'group_former_members'
f497e0a9 875
27b0b59f
NI
876 def __str__(self):
877 return "%s to %s" % (self.account.hruid, self.asso.name)
f497e0a9
NI
878
879
880# Group::Announces
881# ----------------
882
883
27b0b59f 884@python_2_unicode_compatible
f497e0a9
NI
885class GroupAnnounce(models.Model):
886 #id = models.IntegerField(primary_key=True)
887 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
888 asso = models.ForeignKey(Group)
889 create_date = models.DateTimeField()
890 titre = models.CharField(max_length=765)
891 texte = models.TextField()
892 contacts = models.TextField()
893 expiration = models.DateField()
894 promo_min = models.IntegerField()
895 promo_max = models.IntegerField()
896 flags = models.CharField(max_length=36)
897 post_id = models.IntegerField(null=True, blank=True,
898 help_text=u"NNTP post ID")
899 class Meta:
27b0b59f 900 db_table = 'group_announces'
f497e0a9 901
27b0b59f
NI
902 def __str__(self):
903 return "%s: %s" % (self.asso.name, self.titre)
f497e0a9
NI
904
905
27b0b59f 906@python_2_unicode_compatible
f497e0a9
NI
907class GroupAnnouncePhoto(models.Model):
908 eid = models.ForeignKey(GroupAnnounce, primary_key=True, db_column='eid')
909 attachmime = models.CharField(max_length=12)
910 attach = models.TextField()
911 x = models.IntegerField()
912 y = models.IntegerField()
913 class Meta:
27b0b59f 914 db_table = 'group_announces_photo'
f497e0a9 915
27b0b59f
NI
916 def __str__(self):
917 return "%s (%s, %d x %d)" % (self.eid, self.attachmime, self.x, self.y)
f497e0a9
NI
918
919
27b0b59f 920@python_2_unicode_compatible
f497e0a9
NI
921class GroupAnnounceRead(models.Model):
922 announce = models.ForeignKey(GroupAnnounce)
923 account = models.ForeignKey(Account, db_column='uid')
924 pkey = models.CompositeField(announce, account, primary_key=True)
925 class Meta:
27b0b59f 926 db_table = 'group_announces_read'
f497e0a9 927
27b0b59f
NI
928 def __str__(self):
929 return "%s: %s" % (self.account.hruid, self.announce_id)
f497e0a9
NI
930
931
932# Group::Event
933# ------------
934
935
27b0b59f 936@python_2_unicode_compatible
f497e0a9
NI
937class GroupEvent(models.Model):
938 eid = models.IntegerField(primary_key=True)
939 asso = models.ForeignKey(Group, null=True, blank=True)
940 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
941 intitule = models.CharField(max_length=300)
942 short_name = models.CharField(max_length=90)
943 paiement = models.ForeignKey(Payment, null=True, blank=True)
944 descriptif = models.TextField()
945 debut = models.DateTimeField()
946 fin = models.DateTimeField(null=True, blank=True)
947 show_participants = models.BooleanField()
948 deadline_inscription = models.DateField(null=True, blank=True)
949 noinvite = models.IntegerField()
950 accept_nonmembre = models.BooleanField()
951 archive = models.BooleanField()
952 subscription_notification = models.CharField(max_length=24)
953 class Meta:
27b0b59f 954 db_table = 'group_events'
f497e0a9 955
27b0b59f
NI
956 def __str__(self):
957 return "%s: %s" % (self.asso.name, self.intitule)
f497e0a9
NI
958
959
27b0b59f 960@python_2_unicode_compatible
f497e0a9
NI
961class GroupEventItem(models.Model):
962 event = models.ForeignKey(GroupEvent, db_column='eid')
963 item_id = models.IntegerField()
964 pkey = models.CompositeField(event, item_id, primary_key=True)
965
966 titre = models.CharField(max_length=300)
967 details = models.TextField()
968 montant = models.DecimalField(max_digits=12, decimal_places=2)
969 class Meta:
27b0b59f 970 db_table = 'group_event_items'
f497e0a9 971
27b0b59f
NI
972 def __str__(self):
973 return "%s - %s" % (self.event, self.item_id)
f497e0a9
NI
974
975
27b0b59f 976@python_2_unicode_compatible
f497e0a9
NI
977class GroupEventParticipant(models.Model):
978 event = models.ForeignKey(GroupEvent, db_column='eid')
979 item_id = models.IntegerField()
980 account = models.ForeignKey(Account, db_column='uid')
981 item = models.ForeignKey(GroupEventItem, to_field='pkey')
982 pkey = models.CompositeField(event, account, item, primary_key=True)
983
984 nb = models.IntegerField()
985 flags = models.CharField(max_length=42)
986 paid = models.FloatField()
987 class Meta:
27b0b59f 988 db_table = 'group_event_participants'
f497e0a9 989
27b0b59f
NI
990 def __str__(self):
991 return "%s to %s" % (self.account.hruid, self.item)
f497e0a9
NI
992
993
994# Group::misc
995# -----------
996
997
27b0b59f 998@python_2_unicode_compatible
f497e0a9
NI
999class GroupAuth(models.Model):
1000 #id = models.IntegerField(primary_key=True)
1001 privkey = models.CharField(max_length=120, unique=True)
1002 name = models.CharField(max_length=96)
1003 datafields = models.CharField(max_length=765)
1004 returnurls = models.CharField(max_length=765)
1005 last_used = models.DateField(null=True, blank=True)
1006 group = models.ForeignKey(Group, null=True, blank=True)
1007 flags = models.CharField(max_length=63, blank=True)
1008 class Meta:
27b0b59f 1009 db_table = 'group_auth'
f497e0a9 1010
27b0b59f 1011 def __str__(self):
f497e0a9
NI
1012 return self.name
1013
1014
1015# Logging
1016# =======
1017
1018
27b0b59f 1019@python_2_unicode_compatible
f497e0a9
NI
1020class IpWatch(models.Model):
1021 state = models.CharField(max_length=27)
1022 detection = models.DateField(null=True, blank=True)
1023 last = models.DateTimeField()
1024 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
1025 description = models.TextField()
1026 ip = models.IntegerField(primary_key=True)
1027 mask = models.IntegerField()
1028 class Meta:
27b0b59f 1029 db_table = 'ip_watch'
f497e0a9 1030
27b0b59f 1031 def __str__(self):
f497e0a9
NI
1032 return self.ip
1033
1034
27b0b59f 1035@python_2_unicode_compatible
f497e0a9
NI
1036class LogAction(models.Model):
1037 #id = models.IntegerField(primary_key=True)
1038 text = models.CharField(max_length=96)
1039 description = models.CharField(max_length=765)
1040 class Meta:
27b0b59f 1041 db_table = 'log_actions'
f497e0a9 1042
27b0b59f 1043 def __str__(self):
f497e0a9
NI
1044 return self.text
1045
1046
27b0b59f 1047@python_2_unicode_compatible
f497e0a9
NI
1048class LogSession(models.Model):
1049 #id = models.IntegerField(primary_key=True)
1050 auth = models.CharField(max_length=18)
1051 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True, related_name='sessions')
1052 start = models.DateTimeField()
1053 host = models.CharField(max_length=384)
1054 sauth = models.CharField(max_length=18)
1055 suid = models.ForeignKey(Account, null=True, db_column='suid', blank=True, related_name='su_sessions')
1056 browser = models.CharField(max_length=765)
1057 forward_host = models.CharField(max_length=384, blank=True)
1058 flags = models.CharField(max_length=15)
1059 ip = models.IntegerField()
1060 forward_ip = models.IntegerField(null=True, blank=True)
1061 class Meta:
27b0b59f 1062 db_table = 'log_sessions'
f497e0a9 1063
27b0b59f
NI
1064 def __str__(self):
1065 return "%s: %s@%s" % (self.id, self.account.hruid, self.host)
f497e0a9
NI
1066
1067
27b0b59f 1068@python_2_unicode_compatible
f497e0a9
NI
1069class LogLastSession(models.Model):
1070 account = models.ForeignKey(Account, primary_key=True, db_column='uid')
1071 id = models.ForeignKey(LogSession, db_column='id')
1072 class Meta:
27b0b59f 1073 db_table = 'log_last_sessions'
f497e0a9 1074
27b0b59f 1075 def __str__(self):
f497e0a9
NI
1076 return self.account.hruid
1077
1078
27b0b59f 1079@python_2_unicode_compatible
f497e0a9
NI
1080class LogEvent(models.Model):
1081 stamp = models.DateTimeField(primary_key=True)
1082 session = models.ForeignKey(LogSession, db_column='session')
1083 action = models.ForeignKey(LogAction, db_column='action')
1084 data = models.TextField(blank=True)
1085 class Meta:
27b0b59f 1086 db_table = 'log_events'
f497e0a9 1087
27b0b59f
NI
1088 def __str__(self):
1089 return "%s@%s: %s" % (self.session_id, self.stamp, self.action.text)
f497e0a9
NI
1090
1091
1092# Newsletters
1093# ===========
1094
1095
27b0b59f 1096@python_2_unicode_compatible
f497e0a9
NI
1097class Newsletter(models.Model):
1098 #id = models.IntegerField(primary_key=True)
1099 group = models.ForeignKey(Group, unique=True)
1100 name = models.CharField(max_length=765)
1101 criteria = models.CharField(max_length=42, blank=True)
1102 class Meta:
27b0b59f 1103 db_table = 'newsletters'
f497e0a9 1104
27b0b59f 1105 def __str__(self):
f497e0a9
NI
1106 return self.name
1107
1108
27b0b59f 1109@python_2_unicode_compatible
f497e0a9
NI
1110class NewsletterIssue(models.Model):
1111 nlid = models.ForeignKey(Newsletter, unique=True, db_column='nlid')
1112 #id = models.IntegerField(primary_key=True)
1113 date = models.DateField()
1114 send_before = models.DateTimeField(null=True, blank=True)
1115 state = models.CharField(max_length=21)
1116 sufb_json = models.TextField(blank=True)
1117 title = models.CharField(max_length=765)
1118 head = models.TextField()
1119 signature = models.TextField()
1120 short_name = models.CharField(max_length=48, unique=True, blank=True)
1121 mail_title = models.CharField(max_length=765)
1122 unsubscribe = models.IntegerField()
1123 reply_to = models.CharField(max_length=765)
1124 class Meta:
27b0b59f 1125 db_table = 'newsletter_issues'
f497e0a9 1126
27b0b59f 1127 def __str__(self):
f497e0a9
NI
1128 return self.title
1129
1130
27b0b59f 1131@python_2_unicode_compatible
f497e0a9
NI
1132class NewsletterCat(models.Model):
1133 cid = models.AutoField(primary_key=True)
1134 nlid = models.ForeignKey(Newsletter, db_column='nlid')
1135 pos = models.IntegerField()
1136 title = models.CharField(max_length=384)
1137 class Meta:
27b0b59f 1138 db_table = 'newsletter_cat'
f497e0a9 1139
27b0b59f 1140 def __str__(self):
f497e0a9
NI
1141 return self.title
1142
1143
27b0b59f 1144@python_2_unicode_compatible
f497e0a9
NI
1145class NewsletterArt(models.Model):
1146 issue = models.ForeignKey(NewsletterIssue, db_column='id')
1147 aid = models.IntegerField()
1148 pkey = models.CompositeField(issue, aid, primary_key=True)
1149 cid = models.ForeignKey(NewsletterCat, null=True, db_column='cid', blank=True)
1150 pos = models.IntegerField()
1151 title = models.TextField()
1152 body = models.TextField()
1153 append = models.TextField()
1154 class Meta:
27b0b59f 1155 db_table = 'newsletter_art'
f497e0a9 1156
27b0b59f
NI
1157 def __str__(self):
1158 return "%s: %s" % (self.issue_id, self.title)
f497e0a9
NI
1159
1160
27b0b59f 1161@python_2_unicode_compatible
f497e0a9
NI
1162class NewsletterIns(models.Model):
1163 account = models.ForeignKey(Account, db_column='uid')
1164 nl = models.ForeignKey(Newsletter, db_column='nlid')
1165 pkey = models.CompositeField(account, nl, primary_key=True)
1166 last = models.ForeignKey(NewsletterIssue, null=True, db_column='last', blank=True)
1167 hash = models.CharField(max_length=96, blank=True)
1168 class Meta:
27b0b59f 1169 db_table = 'newsletter_ins'
f497e0a9 1170
27b0b59f
NI
1171 def __str__(self):
1172 return "%s to %s" % (self.account.hruid, self.nl.title)
f497e0a9
NI
1173
1174
1175# Profile
1176# =======
1177
1178
27b0b59f 1179@python_2_unicode_compatible
f497e0a9
NI
1180class ProfileDisplay(models.Model):
1181 profile = models.OneToOneField(Profile, primary_key=True, db_column='pid')
1182 yourself = models.CharField(max_length=765)
1183 public_name = models.CharField(max_length=765)
1184 private_name = models.CharField(max_length=765)
1185 directory_name = models.CharField(max_length=765)
1186 short_name = models.CharField(max_length=765)
1187 sort_name = models.CharField(max_length=765)
1188 promo = models.CharField(max_length=765)
1189 class Meta:
27b0b59f 1190 db_table = 'profile_display'
f497e0a9 1191
27b0b59f 1192 def __str__(self):
f497e0a9
NI
1193 return self.profile.hrpid
1194
1195
27b0b59f 1196@python_2_unicode_compatible
f497e0a9
NI
1197class ProfilePhone(models.Model):
1198 LINK_ADDRESS = 'address'
1199 LINK_PRO = 'pro'
1200 LINK_USER = 'user'
1201 LINK_HQ = 'hq'
1202 LINK_GROUP = 'group'
1203 LINK_CHOICES = (
1204 (LINK_ADDRESS, u"Address"),
1205 (LINK_PRO, u"Pro"),
1206 (LINK_USER, u"User"),
1207 (LINK_HQ, u"HQ"),
1208 (LINK_GROUP, u"Group"),
1209 )
1210
1211 KIND_FIXED = 'fixed'
1212 KIND_MOBILE = 'mobile'
1213 KIND_FAX = 'fax'
1214 KIND_CHOICES = (
1215 (KIND_FIXED, u"Fixed"),
1216 (KIND_MOBILE, u"Mobile"),
1217 (KIND_FAX, u"Fax"),
1218 )
1219
1220 profile = models.ForeignKey(Profile, db_column='pid', related_name='phones')
1221 link_type = models.CharField(max_length=21, choices=LINK_CHOICES)
1222 link_id = models.IntegerField()
1223 tel_id = models.IntegerField()
1224 pkey = models.CompositeField(profile, link_type, link_id, tel_id, primary_key=True)
1225
1226 tel_type = models.CharField(max_length=18, choices=KIND_CHOICES)
1227 search_tel = models.CharField(max_length=75)
1228 display_tel = models.CharField(max_length=90)
1229 pub = models.CharField(max_length=21)
1230 comment = models.CharField(max_length=240)
1231
1232 class Meta:
27b0b59f 1233 db_table = 'profile_phones'
f497e0a9 1234
27b0b59f
NI
1235 def __str__(self):
1236 return "%s: %s (%s)" % (self.profile.hrpid, self.display_tel, self.tel_type)
f497e0a9
NI
1237
1238 @property
1239 def is_address(self):
1240 return self.link_type == self.LINK_ADDRESS
1241
1242 @property
1243 def is_job(self):
1244 return self.link_type == self.LINK_PRO
1245
1246 @property
1247 def ax_visible(self):
1248 return is_ax_visible(self.pub)
1249
1250
27b0b59f 1251@python_2_unicode_compatible
f497e0a9
NI
1252class ProfilePhoto(models.Model):
1253 profile = models.OneToOneField(Profile, primary_key=True, db_column='pid', related_name='photo')
1254 attachmime = models.CharField(max_length=12)
1255 attach = models.TextField()
1256 x = models.IntegerField()
1257 y = models.IntegerField()
1258 pub = models.CharField(max_length=21)
1259 last_update = models.DateTimeField()
1260 class Meta:
27b0b59f 1261 db_table = 'profile_photos'
f497e0a9 1262
27b0b59f 1263 def __str__(self):
f497e0a9
NI
1264 return self.profile.hrpid
1265
1266
27b0b59f 1267@python_2_unicode_compatible
f497e0a9
NI
1268class ProfilePrivateName(models.Model):
1269 profile = models.ForeignKey(Profile, db_column='pid', related_name='private_name')
1270 type = models.CharField(max_length=27)
1271 id = models.IntegerField()
1272 pkey = models.CompositeField(profile, type, id, primary_key=True)
1273 name = models.CharField(max_length=765)
1274 class Meta:
27b0b59f 1275 db_table = 'profile_private_names'
f497e0a9 1276
27b0b59f
NI
1277 def __str__(self):
1278 return "%s: %s" % (self.profile.hrpid, self.type)
f497e0a9
NI
1279
1280
27b0b59f 1281@python_2_unicode_compatible
f497e0a9
NI
1282class ProfilePublicName(models.Model):
1283 profile = models.OneToOneField(Profile, primary_key=True, db_column='pid', related_name='public_name')
1284 lastname_initial = models.CharField(max_length=765)
1285 lastname_main = models.CharField(max_length=765)
1286 lastname_marital = models.CharField(max_length=765)
1287 lastname_ordinary = models.CharField(max_length=765)
1288 firstname_initial = models.CharField(max_length=765)
1289 firstname_main = models.CharField(max_length=765)
1290 firstname_ordinary = models.CharField(max_length=765)
1291 pseudonym = models.CharField(max_length=765)
1292 class Meta:
27b0b59f 1293 db_table = 'profile_public_names'
f497e0a9 1294
27b0b59f 1295 def __str__(self):
f497e0a9
NI
1296 return self.profile.hrpid
1297
1298
1299# Profile::addresses
1300# ------------------
1301
1302
27b0b59f 1303@python_2_unicode_compatible
f497e0a9
NI
1304class ProfileAddress(models.Model):
1305
1306 KIND_HOME = 'home'
1307 KIND_HQ = 'hq'
1308 KIND_JOB = 'job'
1309 KIND_GROUP = 'group'
1310
1311 KIND_CHOICES = (
1312 (KIND_HOME, u"Home"),
1313 (KIND_HQ, u"Headquarters"),
1314 (KIND_JOB, u"Job"),
1315 (KIND_GROUP, u"Group"),
1316 )
1317
1318 profile = models.ForeignKey(Profile, db_column='pid', related_name='addresses')
1319 job = models.ForeignKey('ProfileJobEnum', db_column='jobid', blank=True, null=True,
1320 related_name='addresses')
1321 #job = models.IntegerField(db_column='jobid')
1322 group = models.ForeignKey('Group', db_column='groupid', blank=True, null=True)
1323 #groupid = models.IntegerField()
1324 addr_type = models.CharField(max_length=15, db_column='type', choices=KIND_CHOICES)
1325 subid = models.IntegerField(db_column='id')
1326 pkey = models.CompositeField(profile, job, group, addr_type, subid, primary_key=True)
1327 pjob_key = models.CompositeField(profile, subid)
1328 pjob = models.ForeignKey('ProfileJob', aux_field='pjob_key')
1329
1330 flags = models.CharField(max_length=180, blank=True)
1331 text = models.TextField()
1332 postaltext = models.TextField(db_column='postalText') # Field name made lowercase.
1333 formatted_address = models.TextField()
1334 types = models.CharField(max_length=891)
1335 latitude = models.FloatField(null=True, blank=True)
1336 longitude = models.FloatField(null=True, blank=True)
1337 southwest_latitude = models.FloatField(null=True, blank=True)
1338 southwest_longitude = models.FloatField(null=True, blank=True)
1339 northeast_latitude = models.FloatField(null=True, blank=True)
1340 northeast_longitude = models.FloatField(null=True, blank=True)
1341 location_type = models.CharField(max_length=54, blank=True)
1342 partial_match = models.IntegerField()
1343 pub = models.CharField(max_length=21)
1344 comment = models.CharField(max_length=765, blank=True)
1345 geocoding_date = models.DateField(null=True, blank=True)
1346 geocoding_calls = models.IntegerField()
1347 postal_code_fr = models.CharField(max_length=15, blank=True)
1348
1349 components = models.ManyToManyField('ProfileAddressComponentEnum',
1350 through='ProfileAddressComponent', related_name='addresses')
1351
1352 class Meta:
27b0b59f 1353 db_table = 'profile_addresses'
f497e0a9 1354
27b0b59f 1355 def __str__(self):
f497e0a9
NI
1356 if self.addr_type == self.KIND_HOME:
1357 rel = self.profile.hrpid
1358 elif self.addr_type == self.KIND_HQ:
1359 if self.jobid:
1360 rel = unicode(self.job)
1361 else:
1362 rel = u"[BADJOB]"
1363 elif self.addr_type == self.KIND_GROUP:
1364 rel = unicode(self.group)
1365 else:
1366 rel = u"%s at %s" % (self.profile.hrpid, self.pjob.company)
27b0b59f 1367 return "%s address %d for %s" % (
f497e0a9
NI
1368 self.get_addr_type_display(), self.subid, rel)
1369
1370 @property
1371 def ax_visible(self):
1372 return is_ax_visible(self.pub)
1373
1374 def get_components_by_type(self):
1375 flags = collections.defaultdict(list)
1376 for component in self.components.all():
1377 for cp_type in component.types.split(','):
1378 flags[cp_type].append(component)
1379 return flags
1380
1381 @property
1382 def flag_list(self):
1383 return self.flags.split(',')
1384
1385 FLAG_CURRENT = 'current'
1386 FLAG_MAIL = 'mail'
1387 FLAG_SECONDARY = 'secondary'
1388
1389 @property
1390 def current(self):
1391 return self.FLAG_CURRENT in self.flag_list
1392
1393 @property
1394 def mail(self):
1395 return self.FLAG_MAIL in self.flag_list
1396
1397 @property
1398 def secondary(self):
1399 return self.FLAG_SECONDARY in self.flag_list
1400
1401 @property
1402 def is_home(self):
1403 return self.addr_type == self.KIND_HOME
1404
1405 @property
1406 def is_job(self):
1407 return self.addr_type == self.KIND_JOB
1408
1409
27b0b59f 1410@python_2_unicode_compatible
f497e0a9
NI
1411class ProfileAddressComponentEnum(models.Model):
1412 #id = models.BigIntegerField(primary_key=True)
1413 short_name = models.CharField(max_length=765)
1414 long_name = models.CharField(max_length=765)
1415 types = models.CharField(max_length=891)
1416 class Meta:
27b0b59f 1417 db_table = 'profile_addresses_components_enum'
f497e0a9 1418
27b0b59f
NI
1419 def __str__(self):
1420 return '%s (%s)' % (self.short_name, self.types)
f497e0a9
NI
1421
1422
27b0b59f 1423@python_2_unicode_compatible
f497e0a9
NI
1424class ProfileAddressComponent(models.Model):
1425 profile = models.ForeignKey(Profile, db_column='pid')
1426 job = models.ForeignKey('ProfileJobEnum', db_column='jobid')
1427 group = models.ForeignKey(Group, db_column='groupid', blank=True, null=True)
1428 addr_type = models.CharField(max_length=15, db_column='type')
1429 subid = models.IntegerField(db_column='id')
1430 pkey = models.CompositeField(profile, job, group, addr_type, subid, primary_key=True)
1431
1432 component = models.ForeignKey(ProfileAddressComponentEnum, related_name='component_links')
1433 address = models.ForeignKey(ProfileAddress, related_name='component_links',
1434 aux_field='pkey')
1435 class Meta:
27b0b59f 1436 db_table = 'profile_addresses_components'
f497e0a9 1437
27b0b59f
NI
1438 def __str__(self):
1439 return "%s (%s) for %s" % (
f497e0a9
NI
1440 self.component.long_name,
1441 self.component.types,
1442 self.address,
1443 )
1444
1445
1446# Profile::networking
1447# -------------------
1448
1449
1450class ProfileBinetEnum(models.Model):
1451 #id = models.IntegerField(primary_key=True)
1452 text = models.CharField(max_length=150)
1453 url = models.CharField(max_length=765)
1454 class Meta:
27b0b59f 1455 db_table = 'profile_binet_enum'
f497e0a9
NI
1456
1457
1458class ProfileBinet(models.Model):
1459 profile = models.ForeignKey(Profile, db_column='pid')
1460 binet = models.ForeignKey(ProfileBinetEnum)
1461 pkey = models.CompositeField(profile, binet, primary_key=True)
1462 class Meta:
27b0b59f 1463 db_table = 'profile_binets'
f497e0a9
NI
1464
1465
1466class ProfileHobby(models.Model):
1467 profile = models.ForeignKey(Profile, db_column='pid')
1468 id = models.IntegerField()
1469 pkey = models.CompositeField(profile, id, primary_key=True)
1470 type = models.CharField(max_length=18)
1471 text = models.CharField(max_length=765)
1472 pub = models.CharField(max_length=21)
1473 class Meta:
27b0b59f 1474 db_table = 'profile_hobby'
f497e0a9
NI
1475
1476
1477class ProfileNetworkingEnum(models.Model):
1478 nwid = models.IntegerField(primary_key=True)
1479 name = models.CharField(max_length=90)
1480 icon = models.CharField(max_length=150)
1481 filter = models.CharField(max_length=18)
1482 network_type = models.CharField(max_length=18)
1483 link = models.CharField(max_length=765)
1484 class Meta:
27b0b59f 1485 db_table = 'profile_networking_enum'
f497e0a9
NI
1486
1487
1488class ProfileNetworking(models.Model):
1489 profile = models.ForeignKey(Profile, db_column='pid')
1490 id = models.IntegerField()
1491 nwid = models.ForeignKey(ProfileNetworkingEnum, db_column='nwid')
1492 pkey = models.CompositeField(id, nwid, primary_key=True)
1493 address = models.CharField(max_length=765)
1494 pub = models.CharField(max_length=21)
1495 class Meta:
27b0b59f 1496 db_table = 'profile_networking'
f497e0a9
NI
1497
1498
1499# Profile::corps
1500# --------------
1501
1502
27b0b59f 1503@python_2_unicode_compatible
f497e0a9
NI
1504class ProfileCorpsEnum(models.Model):
1505 #id = models.IntegerField(primary_key=True)
1506 name = models.CharField(max_length=255, unique=True)
1507 abbreviation = models.CharField(max_length=15, unique=True)
1508 still_exists = models.IntegerField()
1509 class Meta:
27b0b59f 1510 db_table = 'profile_corps_enum'
f497e0a9 1511
27b0b59f 1512 def __str__(self):
f497e0a9
NI
1513 return self.name
1514
1515
27b0b59f 1516@python_2_unicode_compatible
f497e0a9
NI
1517class ProfileCorpsRankEnum(models.Model):
1518 #id = models.IntegerField(primary_key=True)
1519 name = models.CharField(max_length=255, unique=True)
1520 abbreviation = models.CharField(max_length=15, unique=True)
1521 class Meta:
27b0b59f 1522 db_table = 'profile_corps_rank_enum'
f497e0a9 1523
27b0b59f 1524 def __str__(self):
f497e0a9
NI
1525 return self.name
1526
1527
27b0b59f 1528@python_2_unicode_compatible
f497e0a9
NI
1529class ProfileCorps(models.Model):
1530 profile = models.OneToOneField(Profile, primary_key=True, db_column='pid')
1531 original = models.ForeignKey(ProfileCorpsEnum, db_column='original_corpsid', related_name='original_members')
1532 current = models.ForeignKey(ProfileCorpsEnum, db_column='current_corpsid', related_name='current_members')
1533 rank = models.ForeignKey(ProfileCorpsRankEnum, db_column='rankid')
1534 # Ignored: corps is public information anyway.
1535 corps_pub = models.CharField(max_length=21)
1536 class Meta:
27b0b59f 1537 db_table = 'profile_corps'
f497e0a9 1538
27b0b59f
NI
1539 def __str__(self):
1540 return "%s: %s" % (self.profile.hrpid, self.current.name)
f497e0a9
NI
1541
1542
1543# Profile::edu
1544# ------------
1545
1546
27b0b59f 1547@python_2_unicode_compatible
f497e0a9
NI
1548class ProfileEducationEnum(models.Model):
1549 #id = models.IntegerField(primary_key=True)
1550 name = models.CharField(max_length=255, unique=True, blank=True)
1551 abbreviation = models.CharField(max_length=765)
1552 url = models.CharField(max_length=765, blank=True)
1553 country = models.ForeignKey(GeolocCountry, null=True, db_column='country', blank=True)
1554 class Meta:
27b0b59f 1555 db_table = 'profile_education_enum'
f497e0a9 1556
27b0b59f 1557 def __str__(self):
f497e0a9
NI
1558 return self.name
1559
1560 @property
1561 def short(self):
1562 return self.abbreviation or self.name
1563
1564
27b0b59f 1565@python_2_unicode_compatible
f497e0a9
NI
1566class ProfileEducationDegreeEnum(models.Model):
1567 #id = models.IntegerField(primary_key=True)
1568 degree = models.CharField(max_length=255, unique=True, blank=True)
1569 abbreviation = models.CharField(max_length=765)
1570 level = models.IntegerField()
1571 class Meta:
27b0b59f 1572 db_table = 'profile_education_degree_enum'
f497e0a9 1573
27b0b59f 1574 def __str__(self):
f497e0a9
NI
1575 return self.degree
1576
1577
27b0b59f 1578@python_2_unicode_compatible
f497e0a9
NI
1579class ProfileEducationFieldEnum(models.Model):
1580 #id = models.IntegerField(primary_key=True)
1581 field = models.CharField(max_length=255, unique=True, blank=True)
1582 class Meta:
27b0b59f 1583 db_table = 'profile_education_field_enum'
f497e0a9 1584
27b0b59f 1585 def __str__(self):
f497e0a9
NI
1586 return self.field
1587
1588
27b0b59f 1589@python_2_unicode_compatible
f497e0a9
NI
1590class ProfileEducation(models.Model):
1591 id = models.IntegerField()
1592 profile = models.ForeignKey(Profile, db_column='pid', related_name='educations')
1593 pkey = models.CompositeField(id, profile, primary_key=True)
1594
1595 school = models.ForeignKey(ProfileEducationEnum, null=True, db_column='eduid', blank=True)
1596 degree = models.ForeignKey(ProfileEducationDegreeEnum, null=True, db_column='degreeid', blank=True)
1597 field = models.ForeignKey(ProfileEducationFieldEnum, null=True, db_column='fieldid', blank=True)
1598 entry_year = models.IntegerField(null=True, blank=True)
1599 grad_year = models.IntegerField(null=True, blank=True)
1600 promo_year = models.IntegerField(null=True, blank=True)
1601 program = models.CharField(max_length=765, blank=True)
1602 flags = models.CharField(max_length=81)
1603 class Meta:
27b0b59f 1604 db_table = 'profile_education'
f497e0a9 1605
27b0b59f
NI
1606 def __str__(self):
1607 return "%s: %s" % (self.profile.hrpid, self.edu.name)
f497e0a9
NI
1608
1609
27b0b59f 1610@python_2_unicode_compatible
f497e0a9
NI
1611class ProfileEducationDegree(models.Model):
1612 edu = models.ForeignKey(ProfileEducationEnum, db_column='eduid')
1613 degree = models.ForeignKey(ProfileEducationDegreeEnum, db_column='degreeid')
1614 pkey = models.CompositeField(edu, degree, primary_key=True)
1615 class Meta:
27b0b59f 1616 db_table = 'profile_education_degree'
f497e0a9 1617
27b0b59f
NI
1618 def __str__(self):
1619 return "%s - %s" % (self.edu, self.degree)
f497e0a9
NI
1620
1621
1622# Profile::jobs
1623# -------------
1624
1625
27b0b59f 1626@python_2_unicode_compatible
f497e0a9
NI
1627class ProfileJobEnum(models.Model):
1628 #id = models.IntegerField(primary_key=True)
1629 name = models.CharField(max_length=255, unique=True)
1630 acronym = models.CharField(max_length=765, blank=True)
1631 url = models.CharField(max_length=765, blank=True)
1632 email = models.CharField(max_length=765, blank=True)
1633 holding = models.ForeignKey('self', null=True, db_column='holdingid', blank=True)
1634 naf_code = models.CharField(max_length=15, db_column='NAF_code', blank=True) # Field name made lowercase.
1635 ax_code = models.BigIntegerField(null=True, db_column='AX_code', blank=True) # Field name made lowercase.
1636 siren_code = models.CharField(max_length=9, null=True, db_column='SIREN_code', blank=True) # Field name made lowercase.
1637 class Meta:
27b0b59f 1638 db_table = 'profile_job_enum'
f497e0a9 1639
27b0b59f 1640 def __str__(self):
f497e0a9
NI
1641 return self.name
1642
1643 @property
1644 def address(self):
1645 if not hasattr(self, '_address'):
1646
1647 self._address = None
1648 for address in self.addresses.all():
1649 if address.addr_type == address.KIND_HQ:
1650 self._address = address
1651 break
1652 return self._address
1653
1654
27b0b59f 1655@python_2_unicode_compatible
f497e0a9
NI
1656class ProfileJob(models.Model):
1657 id = models.IntegerField()
1658 profile = models.ForeignKey(Profile, db_column='pid', related_name='jobs')
1659 pkey = models.CompositeField(profile, id, primary_key=True)
1660
1661 company = models.ForeignKey(ProfileJobEnum, null=True, db_column='jobid', blank=True)
1662 description = models.CharField(max_length=765)
1663 url = models.CharField(max_length=765)
1664 email = models.CharField(max_length=765)
1665 pub = models.CharField(max_length=21)
1666 email_pub = models.CharField(max_length=21)
1667 entry_year = models.CharField(max_length=12, blank=True)
1668 class Meta:
27b0b59f 1669 db_table = 'profile_job'
f497e0a9
NI
1670
1671 @property
1672 def ax_visible(self):
1673 return is_ax_visible(self.pub)
1674
1675 @property
1676 def ax_visible_email(self):
1677 return is_ax_visible(self.email_pub)
1678
27b0b59f
NI
1679 def __str__(self):
1680 return "%s at %s" % (self.profile.hrpid, self.company.name if self.company else '<NONE>')
f497e0a9
NI
1681
1682
1683# Profile::job::terms
1684# -------------------
1685
1686
27b0b59f 1687@python_2_unicode_compatible
f497e0a9
NI
1688class ProfileJobTermEnum(models.Model):
1689 jtid = models.AutoField(primary_key=True)
1690 name = models.CharField(max_length=765)
1691 full_name = models.CharField(max_length=765)
1692 class Meta:
27b0b59f 1693 db_table = 'profile_job_term_enum'
f497e0a9 1694
27b0b59f 1695 def __str__(self):
f497e0a9
NI
1696 return self.name
1697
1698
27b0b59f 1699@python_2_unicode_compatible
f497e0a9
NI
1700class ProfileJobTermRelation(models.Model):
1701 jtid_1 = models.ForeignKey(ProfileJobTermEnum, db_column='jtid_1', related_name='relations_from')
1702 jtid_2 = models.ForeignKey(ProfileJobTermEnum, db_column='jtid_2', related_name='relations_to')
1703 rel = models.CharField(max_length=24)
1704 computed = models.CharField(max_length=24)
1705 pkey = models.CompositeField(jtid_1, jtid_2, computed, primary_key=True)
1706 class Meta:
27b0b59f 1707 db_table = 'profile_job_term_relation'
f497e0a9 1708
27b0b59f
NI
1709 def __str__(self):
1710 return "%s <-> %s" % (self.jtid_1.name, self.jtid_2.name)
f497e0a9
NI
1711
1712
27b0b59f 1713@python_2_unicode_compatible
f497e0a9
NI
1714class ProfileJobTermSearch(models.Model):
1715 search = models.CharField(max_length=150)
1716 job_term = models.ForeignKey(ProfileJobTermEnum, db_column='jtid')
1717 pkey = models.CompositeField(search, job_term, primary_key=True)
1718 class Meta:
27b0b59f 1719 db_table = 'profile_job_term_search'
f497e0a9 1720
27b0b59f
NI
1721 def __str__(self):
1722 return "%s => %s" % (self.search, self.job_term.name)
f497e0a9
NI
1723
1724
27b0b59f 1725@python_2_unicode_compatible
f497e0a9
NI
1726class ProfileJobTerm(models.Model):
1727 profile = models.ForeignKey(Profile, db_column='pid')
1728 company = models.ForeignKey(ProfileJobEnum, db_column='jid')
1729 job = models.ForeignKey(ProfileJob, to_field='pkey')
1730 job_term = models.ForeignKey(ProfileJobTermEnum, db_column='jtid')
1731 computed = models.CharField(max_length=24)
1732 pkey = models.CompositeField(profile, company, job_term, primary_key=True)
1733 class Meta:
27b0b59f 1734 db_table = 'profile_job_term'
f497e0a9 1735
27b0b59f
NI
1736 def __str__(self):
1737 return "%s at %s: %s" % (self.profile.hrpid, self.company.name, self.job_term.name)
f497e0a9
NI
1738
1739
27b0b59f 1740@python_2_unicode_compatible
f497e0a9
NI
1741class ProfileJobEntrepriseTerm(models.Model):
1742 job = models.ForeignKey(ProfileJobEnum, db_column='eid')
1743 job_term = models.ForeignKey(ProfileJobTermEnum, db_column='jtid')
1744 pkey = models.CompositeField(job, job_term, primary_key=True)
1745 class Meta:
27b0b59f 1746 db_table = 'profile_job_entreprise_term'
f497e0a9 1747
27b0b59f
NI
1748 def __str__(self):
1749 return "%s: %s" % (self.job.name, self.job_term.name)
f497e0a9
NI
1750
1751
1752# Profile::skills
1753# ---------------
1754
1755
27b0b59f 1756@python_2_unicode_compatible
f497e0a9
NI
1757class ProfileLangSkillEnum(models.Model):
1758 iso_639_2b = models.CharField(max_length=9, primary_key=True)
1759 language = models.CharField(max_length=765)
1760 language_en = models.CharField(max_length=765)
1761 iso_639_2t = models.CharField(max_length=9)
1762 iso_639_1 = models.CharField(max_length=6, blank=True)
1763 class Meta:
27b0b59f 1764 db_table = 'profile_langskill_enum'
f497e0a9 1765
27b0b59f 1766 def __str__(self):
f497e0a9
NI
1767 return self.iso_639_2b
1768
1769
27b0b59f 1770@python_2_unicode_compatible
f497e0a9
NI
1771class ProfileLangSkill(models.Model):
1772 profile = models.ForeignKey(Profile, db_column='pid')
1773 lang = models.ForeignKey(ProfileLangSkillEnum, db_column='lid')
1774 pkey = models.CompositeField(profile, lang, primary_key=True)
1775 level = models.IntegerField(null=True, blank=True)
1776 class Meta:
27b0b59f 1777 db_table = 'profile_langskills'
f497e0a9 1778
27b0b59f
NI
1779 def __str__(self):
1780 return "%s: %s" % (self.profile.hrpid, self.lang.iso_639_2b)
f497e0a9
NI
1781
1782
27b0b59f 1783@python_2_unicode_compatible
f497e0a9
NI
1784class ProfileSkillEnum(models.Model):
1785 id = models.CharField(max_length=9, primary_key=True)
1786 text_fr = models.CharField(max_length=330)
1787 text_en = models.CharField(max_length=330)
1788 flags = models.CharField(max_length=15)
1789 axfreetext = models.TextField()
1790 class Meta:
27b0b59f 1791 db_table = 'profile_skill_enum'
f497e0a9 1792
27b0b59f 1793 def __str__(self):
f497e0a9
NI
1794 return self.text_en
1795
1796
27b0b59f 1797@python_2_unicode_compatible
f497e0a9
NI
1798class ProfileSkill(models.Model):
1799 profile = models.ForeignKey(Profile, db_column='pid')
1800 skill = models.ForeignKey(ProfileSkillEnum, db_column='cid')
1801 pkey = models.CompositeField(profile, skill, primary_key=True)
1802 level = models.CharField(max_length=54)
1803 class Meta:
27b0b59f 1804 db_table = 'profile_skills'
f497e0a9 1805
27b0b59f
NI
1806 def __str__(self):
1807 return "%s: %s" % (self.profile.hrpid, self.skill.text_en)
f497e0a9
NI
1808
1809
1810# Profile::medals
1811# ---------------
1812
1813
1814class ProfileMedalEnum(models.Model):
1815 #id = models.IntegerField(primary_key=True)
1816 type = models.CharField(max_length=30)
1817 text = models.CharField(max_length=765, blank=True)
1818 img = models.CharField(max_length=765, blank=True)
1819 flags = models.CharField(max_length=63)
1820 class Meta:
27b0b59f 1821 db_table = 'profile_medal_enum'
f497e0a9
NI
1822
1823
1824class ProfileMedalGradeEnum(models.Model):
1825 medal = models.ForeignKey(ProfileMedalEnum, db_column='mid')
1826 gid = models.IntegerField()
1827 pkey = models.CompositeField(medal, gid, primary_key=True)
1828 text = models.CharField(max_length=765, blank=True)
1829 pos = models.IntegerField()
1830 class Meta:
27b0b59f 1831 db_table = 'profile_medal_grade_enum'
f497e0a9
NI
1832
1833
1834class ProfileMedal(models.Model):
1835 profile = models.ForeignKey(Profile, db_column='pid')
1836 medal = models.ForeignKey(ProfileMedalEnum)
1837 gid = models.IntegerField()
1838 grade = models.ForeignKey(ProfileMedalGradeEnum, to_field='pkey')
1839 pkey = models.CompositeField(profile, medal, gid, primary_key=True)
1840 level = models.CharField(max_length=18)
1841 class Meta:
27b0b59f 1842 db_table = 'profile_medals'
f497e0a9
NI
1843
1844
1845# Profile::mentor
1846# ---------------
1847
1848
1849class ProfileMentor(models.Model):
1850 profile = models.OneToOneField(Profile, primary_key=True, db_column='pid')
1851 expertise = models.TextField()
1852 class Meta:
27b0b59f 1853 db_table = 'profile_mentor'
f497e0a9
NI
1854
1855
1856class ProfileMentorCountry(models.Model):
1857 profile = models.ForeignKey(Profile, db_column='pid')
1858 country = models.ForeignKey(GeolocCountry, db_column='country')
1859 pkey = models.CompositeField(profile, country, primary_key=True)
1860 class Meta:
27b0b59f 1861 db_table = 'profile_mentor_country'
f497e0a9
NI
1862
1863
1864class ProfileMentorTerm(models.Model):
1865 profile = models.ForeignKey(Profile, db_column='pid')
1866 job_term = models.ForeignKey(ProfileJobTermEnum, db_column='jtid')
1867 pkey = models.CompositeField(profile, job_term, primary_key=True)
1868 class Meta:
27b0b59f 1869 db_table = 'profile_mentor_term'
f497e0a9
NI
1870
1871
1872# Profile::partner
1873# ----------------
1874
1875
1876class ProfilePartnersharingEnum(models.Model):
1877 #id = models.IntegerField(primary_key=True)
1878 api_account = models.ForeignKey(Account, null=True, db_column='api_uid', blank=True)
1879 shortname = models.CharField(max_length=192)
1880 name = models.CharField(max_length=765)
1881 url = models.CharField(max_length=765)
1882 default_sharing_level = models.CharField(max_length=21, blank=True)
1883 has_directory = models.IntegerField()
1884 has_bulkmail = models.IntegerField()
1885 class Meta:
27b0b59f 1886 db_table = 'profile_partnersharing_enum'
f497e0a9
NI
1887
1888
1889class ProfilePartnersharingSetting(models.Model):
1890 profile = models.ForeignKey(Profile, db_column='pid')
1891 partner = models.ForeignKey(ProfilePartnersharingEnum)
1892 pkey = models.CompositeField(profile, partner, primary_key=True)
1893 exposed_uid = models.CharField(max_length=765)
1894 sharing_level = models.CharField(max_length=21, blank=True)
1895 allow_email = models.CharField(max_length=18, blank=True)
1896 last_connection = models.DateTimeField(null=True, blank=True)
1897 class Meta:
27b0b59f 1898 db_table = 'profile_partnersharing_settings'
f497e0a9
NI
1899
1900
1901class ProfilePhotoToken(models.Model):
1902 profile = models.ForeignKey(Profile, primary_key=True, db_column='pid')
1903 token = models.CharField(max_length=765)
1904 expires = models.DateTimeField()
1905 class Meta:
27b0b59f 1906 db_table = 'profile_photo_tokens'
f497e0a9
NI
1907
1908
1909# Profile::misc
1910# -------------
1911
1912
1913class ProfileMergeIssue(models.Model):
1914 profile = models.ForeignKey(Profile, primary_key=True, db_column='pid')
1915 issues = models.CharField(max_length=144, blank=True)
1916 entry_year_ax = models.IntegerField(null=True, blank=True)
1917 deathdate_ax = models.DateField(null=True, blank=True)
1918 name = models.CharField(max_length=765, blank=True)
1919 name_type = models.IntegerField(null=True, blank=True)
1920 class Meta:
27b0b59f 1921 db_table = 'profile_merge_issues'
f497e0a9
NI
1922
1923
1924class ProfileModification(models.Model):
1925 profile = models.ForeignKey(Profile, db_column='pid')
1926 account = models.ForeignKey(Account, db_column='uid')
1927 field = models.CharField(max_length=180)
1928 pkey = models.CompositeField(profile, field, primary_key=True)
1929 oldtext = models.TextField(db_column='oldText')
1930 newtext = models.TextField(db_column='newText')
1931 type = models.CharField(max_length=33)
1932 timestamp = models.DateTimeField()
1933 class Meta:
27b0b59f 1934 db_table = 'profile_modifications'
f497e0a9
NI
1935
1936
1937class ProfileVisibilityEnum(models.Model):
1938 access_level = models.CharField(max_length=21, blank=True, primary_key=True)
1939 best_display_level = models.CharField(max_length=21, blank=True)
1940 display_levels = models.CharField(max_length=72, blank=True)
1941 class Meta:
27b0b59f 1942 db_table = 'profile_visibility_enum'
f497e0a9
NI
1943
1944
1945
1946class ProfileDeltaten(models.Model):
1947 profile = models.OneToOneField(Profile, primary_key=True, db_column='pid')
1948 message = models.TextField()
1949 class Meta:
27b0b59f 1950 db_table = 'profile_deltaten'
f497e0a9
NI
1951
1952
1953# Reminders
1954# =========
1955
1956
1957class ReminderType(models.Model):
1958 #type_id = models.IntegerField(primary_key=True)
1959 name = models.CharField(max_length=255, unique=True)
1960 weight = models.IntegerField()
1961 remind_delay_yes = models.IntegerField()
1962 remind_delay_no = models.IntegerField()
1963 remind_delay_dismiss = models.IntegerField()
1964 class Meta:
27b0b59f 1965 db_table = 'reminder_type'
f497e0a9
NI
1966
1967
1968class Reminder(models.Model):
1969 account = models.ForeignKey(Account, db_column='uid')
1970 type = models.ForeignKey(ReminderType)
1971 pkey = models.CompositeField(account, type, primary_key=True)
1972 status = models.CharField(max_length=21)
1973 remind_last = models.DateTimeField()
1974 remind_next = models.DateTimeField(null=True, blank=True)
1975 class Meta:
27b0b59f 1976 db_table = 'reminder'
f497e0a9
NI
1977
1978
1979class ReminderTip(models.Model):
1980 #id = models.IntegerField(primary_key=True)
1981 title = models.CharField(max_length=192)
1982 text = models.TextField()
1983 priority = models.IntegerField()
1984 expiration = models.DateField()
1985 promo_min = models.IntegerField()
1986 promo_max = models.IntegerField()
1987 state = models.CharField(max_length=18)
1988 class Meta:
27b0b59f 1989 db_table = 'reminder_tips'
f497e0a9
NI
1990
1991
1992# Surveys
1993# =======
1994
1995
1996class Survey(models.Model):
1997 #id = models.IntegerField(primary_key=True)
1998 questions = models.TextField()
1999 title = models.CharField(max_length=765)
2000 description = models.TextField()
2001 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
2002 end = models.DateField()
2003 mode = models.IntegerField()
2004 promos = models.CharField(max_length=765)
2005 class Meta:
27b0b59f 2006 db_table = 'surveys'
f497e0a9
NI
2007
2008
2009class SurveyVote(models.Model):
2010 #id = models.IntegerField(primary_key=True)
2011 survey = models.ForeignKey(Survey)
2012 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
2013 class Meta:
27b0b59f 2014 db_table = 'survey_votes'
f497e0a9
NI
2015
2016
2017class SurveyAnswer(models.Model):
2018 #id = models.IntegerField(primary_key=True)
2019 vote = models.ForeignKey(SurveyVote)
2020 question_id = models.IntegerField()
2021 answer = models.TextField()
2022 class Meta:
27b0b59f 2023 db_table = 'survey_answers'
f497e0a9
NI
2024
2025
2026# GApps
2027# =====
2028
2029
2030class GappsAccount(models.Model):
2031 l_userid = models.ForeignKey(Account, null=True, db_column='l_userid', blank=True)
2032 l_sync_password = models.BooleanField(default=True)
2033 l_activate_mail_redirection = models.BooleanField(default=True)
2034 g_account_id = models.CharField(max_length=48, blank=True)
2035 g_account_name = models.CharField(max_length=255, primary_key=True)
2036 g_domain = models.CharField(max_length=120, blank=True)
2037 g_first_name = models.CharField(max_length=120)
2038 g_last_name = models.CharField(max_length=120)
2039 g_status = models.CharField(max_length=39, blank=True)
2040 g_admin = models.BooleanField()
2041 g_suspension = models.CharField(max_length=768, blank=True)
2042 r_disk_usage = models.BigIntegerField(null=True, blank=True)
2043 r_creation = models.DateField(null=True, blank=True)
2044 r_last_login = models.DateField(null=True, blank=True)
2045 r_last_webmail = models.DateField(null=True, blank=True)
2046 class Meta:
27b0b59f 2047 db_table = 'gapps_accounts'
f497e0a9
NI
2048
2049
2050class GappsNickname(models.Model):
2051 l_userid = models.ForeignKey(Account, null=True, db_column='l_userid', blank=True)
2052 g_account_name = models.CharField(max_length=768)
2053 g_nickname = models.CharField(max_length=255, primary_key=True)
2054 class Meta:
27b0b59f 2055 db_table = 'gapps_nicknames'
f497e0a9
NI
2056
2057
2058class GappsQueue(models.Model):
2059 q_id = models.AutoField(primary_key=True)
2060 q_owner = models.ForeignKey(Account, null=True, blank=True, related_name='owned_gapps_jobs')
2061 q_recipient = models.ForeignKey(Account, null=True, blank=True, related_name='received_gapps_jobs')
2062 p_entry_date = models.DateTimeField()
2063 p_notbefore_date = models.DateTimeField()
2064 p_start_date = models.DateTimeField(null=True, blank=True)
2065 p_end_date = models.DateTimeField(null=True, blank=True)
2066 p_status = models.CharField(max_length=24)
2067 p_priority = models.CharField(max_length=27)
2068 p_admin_request = models.BooleanField()
2069 j_type = models.CharField(max_length=30)
2070 j_parameters = models.TextField(blank=True)
2071 r_softfail_date = models.DateTimeField(null=True, blank=True)
2072 r_softfail_count = models.IntegerField()
2073 r_result = models.CharField(max_length=768, blank=True)
2074 class Meta:
27b0b59f 2075 db_table = 'gapps_queue'
f497e0a9
NI
2076
2077
2078class GappsReporting(models.Model):
2079 date = models.DateField(primary_key=True)
2080 num_accounts = models.IntegerField(null=True, blank=True)
2081 count_1_day_actives = models.IntegerField(null=True, blank=True)
2082 count_7_day_actives = models.IntegerField(null=True, blank=True)
2083 count_14_day_actives = models.IntegerField(null=True, blank=True)
2084 count_30_day_actives = models.IntegerField(null=True, blank=True)
2085 count_30_day_idle = models.IntegerField(null=True, blank=True)
2086 count_60_day_idle = models.IntegerField(null=True, blank=True)
2087 count_90_day_idle = models.IntegerField(null=True, blank=True)
2088 usage_in_bytes = models.BigIntegerField(null=True, blank=True)
2089 quota_in_mb = models.IntegerField(null=True, blank=True)
2090 class Meta:
27b0b59f 2091 db_table = 'gapps_reporting'
f497e0a9
NI
2092
2093
2094
2095# Watch
2096# =====
2097
2098
2099class Watch(models.Model):
2100 account = models.ForeignKey(Account, primary_key=True, db_column='uid')
2101 flags = models.CharField(max_length=39)
2102 actions = models.CharField(max_length=105)
2103 last = models.DateTimeField()
2104 class Meta:
27b0b59f 2105 db_table = 'watch'
f497e0a9
NI
2106
2107
2108class WatchGroup(models.Model):
2109 account = models.ForeignKey(Account, db_column='uid')
2110 group = models.ForeignKey(Group, db_column='groupid')
2111 pkey = models.CompositeField(account, group, primary_key=True)
2112 class Meta:
27b0b59f 2113 db_table = 'watch_group'
f497e0a9
NI
2114
2115
2116class WatchNonins(models.Model):
2117 account = models.ForeignKey(Account, db_column='uid', related_name='watching')
2118 watched = models.ForeignKey(Account, db_column='ni', related_name='watched_by')
2119 pkey = models.CompositeField(account, watched, primary_key=True)
2120 class Meta:
27b0b59f 2121 db_table = 'watch_nonins'
f497e0a9
NI
2122
2123
2124class WatchProfile(models.Model):
2125 profile = models.ForeignKey(Profile, db_column='pid')
2126 ts = models.DateTimeField()
2127 field = models.CharField(max_length=36)
2128 pkey = models.CompositeField(profile, field, primary_key=True)
2129 class Meta:
27b0b59f 2130 db_table = 'watch_profile'
f497e0a9
NI
2131
2132
2133class WatchPromo(models.Model):
2134 account = models.ForeignKey(Account, db_column='uid')
2135 promo = models.IntegerField()
2136 pkey = models.CompositeField(account, promo, primary_key=True)
2137 class Meta:
27b0b59f 2138 db_table = 'watch_promo'
f497e0a9
NI
2139
2140
2141# Postfix
2142# =======
2143
2144
2145class MxWatch(models.Model):
2146 host = models.CharField(max_length=192, primary_key=True)
2147 state = models.CharField(max_length=21, blank=True)
2148 text = models.TextField()
2149 class Meta:
27b0b59f 2150 db_table = 'mx_watch'
f497e0a9
NI
2151
2152
2153class PostfixBlacklist(models.Model):
2154 email = models.CharField(max_length=255, primary_key=True)
2155 reject_text = models.CharField(max_length=192)
2156 class Meta:
27b0b59f 2157 db_table = 'postfix_blacklist'
f497e0a9
NI
2158
2159
2160class PostfixMailseen(models.Model):
2161 crc = models.CharField(max_length=24, primary_key=True)
2162 nb = models.IntegerField()
2163 update_time = models.DateTimeField()
2164 create_time = models.DateTimeField()
2165 release = models.CharField(max_length=18)
2166 class Meta:
27b0b59f 2167 db_table = 'postfix_mailseen'
f497e0a9
NI
2168
2169
2170class PostfixWhitelist(models.Model):
2171 email = models.CharField(max_length=255, primary_key=True)
2172 class Meta:
27b0b59f 2173 db_table = 'postfix_whitelist'
f497e0a9
NI
2174
2175
2176# Register
2177# ========
2178
2179
2180class RegisterMarketing(models.Model):
2181 account = models.ForeignKey(Account, db_column='uid', related_name='received_marketings')
2182 sender = models.ForeignKey(Account, null=True, db_column='sender', blank=True, related_name='sent_marketings')
2183 email = models.CharField(max_length=765)
2184 pkey = models.CompositeField(account, email, primary_key=True)
2185
2186 date = models.DateField()
2187 last = models.DateField()
2188 nb = models.IntegerField()
2189 type = models.CharField(max_length=15, blank=True)
2190 hash = models.CharField(max_length=96)
2191 message = models.CharField(max_length=48)
2192 message_data = models.CharField(max_length=192, blank=True)
2193 personal_notes = models.TextField(blank=True)
2194 class Meta:
27b0b59f 2195 db_table = 'register_marketing'
f497e0a9
NI
2196
2197
2198class RegisterMstat(models.Model):
2199 account = models.OneToOneField(Account, primary_key=True, db_column='uid', related_name='received_marketings_stats')
2200 sender = models.ForeignKey(Account, null=True, db_column='sender', blank=True, related_name='sent_marketings_stats')
2201 success = models.DateField()
2202 class Meta:
27b0b59f 2203 db_table = 'register_mstats'
f497e0a9
NI
2204
2205
2206class RegisterPending(models.Model):
2207 account = models.OneToOneField(Account, primary_key=True, db_column='uid')
2208 forlife = models.CharField(max_length=255, unique=True)
2209 bestalias = models.CharField(max_length=255, unique=True)
2210 mailorg2 = models.CharField(max_length=765, blank=True)
2211 password = models.CharField(max_length=120)
2212 email = models.CharField(max_length=765)
2213 date = models.DateField()
2214 relance = models.DateField()
2215 naissance = models.DateField()
2216 hash = models.CharField(max_length=36)
2217 services = models.CharField(max_length=78)
2218 class Meta:
27b0b59f 2219 db_table = 'register_pending'
f497e0a9
NI
2220
2221
2222class RegisterPendingXnet(models.Model):
2223 account = models.ForeignKey(Account, primary_key=True, db_column='uid', related_name='pending_xnet_register')
2224 hruid = models.ForeignKey(Account, unique=True, db_column='hruid', related_name='pending_xnet_register_by_hruid')
2225 email = models.CharField(max_length=765)
2226 date = models.DateField()
2227 last_date = models.DateField(null=True, blank=True)
2228 hash = models.CharField(max_length=36)
2229 sender_name = models.CharField(max_length=765)
2230 group_name = models.CharField(max_length=765)
2231 class Meta:
27b0b59f 2232 db_table = 'register_pending_xnet'
f497e0a9
NI
2233
2234
2235class RegisterSubs(models.Model):
2236 account = models.ForeignKey(Account, db_column='uid')
2237 type = models.CharField(max_length=15)
2238 sub = models.CharField(max_length=96)
2239 domain = models.CharField(max_length=192)
2240 pkey = models.CompositeField(account, type, sub, domain, primary_key=True)
2241 class Meta:
27b0b59f 2242 db_table = 'register_subs'
f497e0a9
NI
2243
2244
2245# Search
2246# ======
2247
2248
2249class SearchAutocomplete(models.Model):
2250 name = models.CharField(max_length=60)
2251 query = models.CharField(max_length=300)
2252 pkey = models.CompositeField(name, query, primary_key=True)
2253 result = models.TextField()
2254 generated = models.DateTimeField()
2255 class Meta:
27b0b59f 2256 db_table = 'search_autocomplete'
f497e0a9
NI
2257
2258
2259class SearchName(models.Model):
2260 profile = models.ForeignKey(Profile, db_column='pid')
2261 token = models.CharField(max_length=765)
2262 pkey = models.CompositeField(profile, token, primary_key=True)
2263 score = models.IntegerField()
2264 soundex = models.CharField(max_length=12)
2265 flags = models.CharField(max_length=18)
2266 general_type = models.CharField(max_length=27)
2267 class Meta:
27b0b59f 2268 db_table = 'search_name'
f497e0a9
NI
2269
2270
2271# Requests
2272# ========
2273
2274
2275class Request(models.Model):
2276 account = models.ForeignKey(Account, db_column='uid')
2277 type = models.CharField(max_length=48)
2278 data = models.TextField()
2279 stamp = models.DateTimeField()
2280 profile = models.ForeignKey(Profile, null=True, db_column='pid', blank=True)
2281 pkey = models.CompositeField(account, stamp, type, primary_key=True)
2282 class Meta:
27b0b59f 2283 db_table = 'requests'
f497e0a9
NI
2284
2285
2286class RequestAnswer(models.Model):
2287 #id = models.IntegerField(primary_key=True)
2288 category = models.CharField(max_length=45)
2289 title = models.CharField(max_length=150)
2290 answer = models.TextField()
2291 class Meta:
27b0b59f 2292 db_table = 'requests_answers'
f497e0a9
NI
2293
2294
2295class RequestHidden(models.Model):
2296 account = models.ForeignKey(Account, primary_key=True, db_column='uid')
2297 hidden_requests = models.TextField()
2298 class Meta:
27b0b59f 2299 db_table = 'requests_hidden'
f497e0a9
NI
2300
2301
2302# Misc
2303# ====
2304
2305
2306class AXLetter(models.Model):
2307 #id = models.IntegerField(primary_key=True)
2308 short_name = models.CharField(max_length=48, unique=True, blank=True)
2309 subject = models.CharField(max_length=765)
2310 title = models.CharField(max_length=765)
2311 body = models.TextField()
2312 signature = models.TextField()
2313 promo_min = models.IntegerField()
2314 promo_max = models.IntegerField()
2315 subset = models.TextField(blank=True)
2316 subset_rm = models.IntegerField(null=True, blank=True)
2317 echeance = models.DateTimeField()
2318 date = models.DateField()
2319 bits = models.CharField(max_length=48)
2320 class Meta:
27b0b59f 2321 db_table = 'axletter'
f497e0a9
NI
2322
2323
2324class Carva(models.Model):
2325 account = models.ForeignKey(Account, primary_key=True, db_column='uid')
2326 url = models.CharField(max_length=765)
2327 class Meta:
27b0b59f 2328 db_table = 'carvas'
f497e0a9
NI
2329
2330
2331class Contact(models.Model):
2332 account = models.ForeignKey(Account, db_column='uid')
2333 contact = models.ForeignKey(Profile, db_column='contact')
2334 pkey = models.CompositeField(account, contact, primary_key=True)
2335 class Meta:
27b0b59f 2336 db_table = 'contacts'
f497e0a9
NI
2337
2338
2339class Downtime(models.Model):
2340 debut = models.DateTimeField()
2341 duree = models.TimeField() # This field type is a guess.
2342 resume = models.CharField(max_length=765)
2343 description = models.TextField()
2344 services = models.CharField(max_length=54)
2345 class Meta:
27b0b59f 2346 db_table = 'downtimes'
f497e0a9
NI
2347
2348
2349class EmailListModerate(models.Model):
2350 ml = models.CharField(max_length=192)
2351 domain = models.CharField(max_length=192)
2352 mid = models.IntegerField()
2353 pkey = models.CompositeField(ml, domain, mid, primary_key=True)
2354 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
2355 action = models.CharField(max_length=18)
2356 ts = models.DateTimeField()
2357 message = models.TextField(blank=True)
2358 handler = models.IntegerField(null=True, blank=True)
2359 class Meta:
27b0b59f 2360 db_table = 'email_list_moderate'
f497e0a9
NI
2361
2362
2363class EmailSendSave(models.Model):
2364 account = models.OneToOneField(Account, primary_key=True, db_column='uid')
2365 data = models.TextField()
2366 class Meta:
27b0b59f 2367 db_table = 'email_send_save'
f497e0a9
NI
2368
2369
2370class EmailWatch(models.Model):
2371 email = models.CharField(max_length=180, primary_key=True)
2372 state = models.CharField(max_length=27)
2373 detection = models.DateField(null=True, blank=True)
2374 last = models.DateTimeField()
2375 account = models.ForeignKey(Account, null=True, db_column='uid', blank=True)
2376 description = models.TextField()
2377 class Meta:
27b0b59f 2378 db_table = 'email_watch'
f497e0a9
NI
2379
2380
2381class GeolocLanguage(models.Model):
2382 iso_3166_1_a2 = models.ForeignKey(GeolocCountry, db_column='iso_3166_1_a2')
2383 language = models.CharField(max_length=15)
2384 pkey = models.CompositeField(iso_3166_1_a2, language, primary_key=True)
2385 country = models.CharField(max_length=765, blank=True)
2386 countryplain = models.CharField(max_length=765, db_column='countryPlain', blank=True) # Field name made lowercase.
2387 class Meta:
27b0b59f 2388 db_table = 'geoloc_languages'
f497e0a9
NI
2389
2390
2391class HomonymList(models.Model):
2392 hrmid = models.CharField(max_length=765)
2393 account = models.ForeignKey(Account, db_column='uid')
2394 pkey = models.CompositeField(hrmid, account, primary_key=True)
2395 class Meta:
27b0b59f 2396 db_table = 'homonyms_list'
f497e0a9
NI
2397
2398
2399class UrlShortener(models.Model):
2400 alias = models.CharField(max_length=255, primary_key=True)
2401 url = models.TextField()
2402 class Meta:
27b0b59f 2403 db_table = 'url_shortener'