1 from django.db import models
2 from django.db.models import signals
3 from django.dispatch import dispatcher
6 INTERVAL_HELP_TEXT = _('examples: "1 hour", "14 days", "3 months", "DD:HH:MM:SS.ms"')
7 CHAR_MAXLEN=200 # just provide a sane default
10 """ --------------------------------------------------------------
12 -------------------------------------------------------------- """
15 class PermList(models.Model):
16 code = models.CharField(maxlength=100)
17 description = models.TextField(blank=True)
19 list_display = ('code','description')
20 search_fields = ['code']
22 db_table = 'perm_list'
24 verbose_name = _('Permission')
28 class GrpPermMap(models.Model):
29 grp_id = models.ForeignKey('GrpTree', db_column='grp')
30 perm_id = models.ForeignKey(PermList, db_column='perm')
31 depth_id = models.ForeignKey('OrgUnitType', to_field='depth', db_column='depth')
32 grantable = models.BooleanField()
34 list_filter = ['grp_id']
35 list_display = ('perm_id', 'grp_id', 'depth_id')
37 db_table = 'grp_perm_map'
38 ordering = ['perm_id', 'grp_id']
39 verbose_name = _('Permission Setting')
41 return str(self.grp_id)+' -> '+str(self.perm_id)
43 class GrpTree(models.Model):
44 name = models.CharField(maxlength=100)
45 parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent')
46 description = models.CharField(blank=True, maxlength=CHAR_MAXLEN)
47 perm_interval = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT)
48 application_perm = models.CharField(blank=True, maxlength=100)
49 usergroup = models.BooleanField()
51 list_display = ('name', 'description')
52 list_filter = ['parent_id']
53 search_fields = ['name', 'description']
57 verbose_name = _('User Group')
65 """ There's no way to do user-based mangling given the size of the data without custom handling.
66 When you try to create a new permission map, it tries to load all users into a dropdown selector :(
68 class User(models.Model):
69 card_id = models.ForeignKey('Card', db_column='card')
70 profile_id = models.ForeignKey(GrpTree, db_column='profile')
71 usrname = models.CharField(blank=False, null=False, maxlength=CHAR_MAXLEN)
73 return "%s (%s)" % ( str(self.card_id), str(self.usrname))
78 class UsrPermMap(models.Model):
79 usr_id = models.ForeignKey(User, db_column='usr')
80 perm_id = models.ForeignKey(PermList, db_column='perm')
81 depth_id = models.ForeignKey(OrgUnitType, to_field='depth', db_column='depth')
82 grantable = models.BooleanField()
84 search_fields = ['usr_id', 'perm_id'] # we need text fields to search...
86 db_table = 'usr_perm_map'
87 verbose_name = 'User Permission'
89 return "%s -> %s" % ( str(self.usr_id), str(self.perm_id) )
92 class Card(models.Model):
93 usr_id = models.ForeignKey(User, db_column='usr')
94 barcode = models.CharField(blank=False, null=False, maxlength=CHAR_MAXLEN)
95 active = models.BooleanField()
100 verbose_name = 'Card'
105 """ --------------------------------------------------------------
107 -------------------------------------------------------------- """
109 class OrgUnitType(models.Model):
110 name = models.CharField(maxlength=100)
111 opac_label = models.CharField(maxlength=100)
112 depth = models.IntegerField()
113 parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent')
114 can_have_vols = models.BooleanField()
115 can_have_users = models.BooleanField()
117 db_table = 'org_unit_type'
118 verbose_name = _('Organizational Unit Type')
120 list_display = ('name', 'depth')
121 list_filter = ['parent_id']
126 class OrgUnitSetting(models.Model):
127 org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit')
128 name = models.CharField(maxlength=CHAR_MAXLEN)
129 value = models.CharField(maxlength=CHAR_MAXLEN)
131 list_display = ('org_unit_id', 'name', 'value')
132 search_fields = ['name', 'value']
133 list_filter = ['name', 'org_unit_id']
135 db_table = 'org_unit_setting'
136 ordering = ['org_unit_id', 'name']
137 verbose_name = _('Organizational Unit Setting')
139 return "%s:%s=%s" % (self.org_unit_id.shortname, self.name, self.value)
142 class OrgAddress(models.Model):
143 valid = models.BooleanField()
144 org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit')
145 address_type = models.CharField(blank=False, maxlength=CHAR_MAXLEN, default=_('MAILING'))
146 street1 = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
147 street2 = models.CharField(maxlength=CHAR_MAXLEN)
148 city = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
149 county = models.CharField(maxlength=CHAR_MAXLEN)
150 state = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
151 country = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
152 post_code = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
154 search_fields = ['street1', 'city', 'post_code']
155 list_filter = ['org_unit_id']
156 list_display = ('street1', 'street2', 'city', 'county', 'state', 'post_code')
159 db_table = 'org_address'
160 verbose_name = _('Organizational Unit Address')
162 return self.street1+' '+self.city+', '+self.state+' '+self.post_code
164 class OrgUnit(models.Model):
165 parent_ou_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent_ou')
166 ou_type_id = models.ForeignKey(OrgUnitType, db_column='ou_type')
167 shortname = models.CharField(maxlength=CHAR_MAXLEN)
168 name = models.CharField(maxlength=CHAR_MAXLEN)
169 email = models.EmailField(null=True, blank=True)
170 phone = models.CharField(maxlength=CHAR_MAXLEN, null=True, blank=True)
171 opac_visible = models.BooleanField(blank=True)
172 ill_address_id = models.ForeignKey(OrgAddress,
173 db_column='ill_address', related_name='ill_addresses', null=True, blank=True)
174 holds_address_id = models.ForeignKey(OrgAddress,
175 db_column='holds_address', related_name='holds_addresses', null=True, blank=True)
176 mailing_address_id = models.ForeignKey(OrgAddress,
177 db_column='mailing_address', related_name='mailing_addresses', null=True, blank=True)
178 billing_address_id = models.ForeignKey(OrgAddress,
179 db_column='billing_address', related_name='billing_addresses', null=True, blank=True)
181 search_fields = ['name', 'shortname']
182 list_display = ('shortname', 'name')
184 db_table = 'org_unit'
185 ordering = ['shortname']
186 verbose_name = _('Organizational Unit')
188 return self.shortname
190 class HoursOfOperation(models.Model):
191 #choices = tuple([ (datetime.time(i), str(i)) for i in range(0,23) ])
192 org_unit = models.ForeignKey('OrgUnit', db_column='id')
193 # XXX add better time widget support
194 dow_0_open = models.TimeField(_('Monday Open'), null=False, blank=False, default=datetime.time(9))
195 dow_0_close = models.TimeField(_('Monday Close'), null=False, blank=False, default=datetime.time(17))
196 dow_1_open = models.TimeField(_('Tuesday Open'), null=False, blank=False, default=datetime.time(9))
197 dow_1_close = models.TimeField(_('Tuesday Close'), null=False, blank=False, default=datetime.time(17))
198 dow_2_open = models.TimeField(_('Wednesday Open'), null=False, blank=False, default=datetime.time(9))
199 dow_2_close = models.TimeField(_('Wednesday Close'), null=False, blank=False, default=datetime.time(17))
200 dow_3_open = models.TimeField(_('Thursday Open'), null=False, blank=False, default=datetime.time(9))
201 dow_3_close = models.TimeField(_('Thursday Close'), null=False, blank=False, default=datetime.time(17))
202 dow_4_open = models.TimeField(_('Friday Open'), null=False, blank=False, default=datetime.time(9))
203 dow_4_close = models.TimeField(_('Friday Close'), null=False, blank=False, default=datetime.time(17))
204 dow_5_open = models.TimeField(_('Saturday Open'), null=False, blank=False, default=datetime.time(9))
205 dow_5_close = models.TimeField(_('Saturday Close'), null=False, blank=False, default=datetime.time(17))
206 dow_6_open = models.TimeField(_('Sunday Open'), null=False, blank=False, default=datetime.time(9))
207 dow_6_close = models.TimeField(_('Sunday Close'), null=False, blank=False, default=datetime.time(17))
211 db_table = 'hours_of_operation'
212 verbose_name = _('Hours of Operation')
213 verbose_name_plural = verbose_name
215 return str(self.org_unit)
219 """ --------------------------------------------------------------
221 -------------------------------------------------------------- """
223 class CircModifier(models.Model):
224 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
225 name = models.CharField(maxlength=CHAR_MAXLEN)
226 description = models.CharField(maxlength=CHAR_MAXLEN);
227 sip2_media_type = models.CharField(maxlength=CHAR_MAXLEN);
228 magnetic_media = models.BooleanField()
230 search_fields = ['name','code']
231 list_display = ('code','name','description','sip2_media_type','magnetic_media')
233 db_table = 'circ_modifier'
235 verbose_name = _('Circulation Modifier')
240 class VideoRecordingFormat(models.Model):
241 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
242 value = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
244 search_fields = ['value','code']
245 list_display = ('value','code')
247 db_table = 'videorecording_format_map'
249 verbose_name = _('Video Recording Format')
253 class RuleCircDuration(models.Model):
254 name = models.CharField(maxlength=CHAR_MAXLEN)
255 extended = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
256 normal = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
257 shrt = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
258 max_renewals = models.IntegerField()
260 search_fields = ['name']
261 list_display = ('name','extended','normal','shrt','max_renewals')
263 db_table = 'rule_circ_duration'
265 verbose_name = _('Circ Duration Rule')
269 class CircMatrixMatchpoint(models.Model):
270 active = models.BooleanField(blank=False, default=True)
271 org_unit_id = models.ForeignKey(OrgUnit, db_column='org_unit', blank=False)
272 grp_id = models.ForeignKey(GrpTree, db_column='grp', blank=False)
273 circ_modifier_id = models.ForeignKey(CircModifier, db_column='circ_modifier', null=True)
274 marc_type_id = models.ForeignKey('ItemTypeMap', db_column='marc_type', null=True)
275 marc_form_id = models.ForeignKey('ItemFormMap', db_column='marc_form', null=True)
276 marc_vr_format_id = models.ForeignKey('VideoRecordingFormat', db_column='marc_vr_format', null=True)
277 ref_flag = models.BooleanField(null=True)
278 usr_age_lower_bound = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT, null=True)
279 usr_age_upper_bound = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT, null=True)
283 'fields': ('org_unit_id', 'circ_modifier_id', 'marc_type_id', 'marc_form_id','marc_vr_format_id','usr_age_lower_bound','usr_age_upper_bound')
286 'classes': 'collapse',
287 'fields' : ('circmatrixtest_set')
290 'classes': 'collapse',
291 'fields': ('circmatrixcircmodtest_set')
294 'classes': 'collapse',
295 'fields': ('circmatrixruleset_set')
298 search_fields = ['grp_id','org_unit_id','circ_modifier_id','marc_type_id','marc_form_id','marc_vr_format_id','usr_age_lower_bound','usr_age_upper_bound']
299 list_display = ('grp_id','org_unit_id','circ_modifier_id','marc_type_id','marc_form_id','marc_vr_format_id','ref_flag','usr_age_lower_bound','usr_age_upper_bound')
300 list_filter = ['grp_id','org_unit_id','circ_modifier_id','marc_type_id','marc_form_id','marc_vr_format_id']
302 db_table = 'circ_matrix_matchpoint'
304 verbose_name = _('Circulation Matrix Matchpoint')
306 return _("OrgUnit: %s, Group: %s, Circ Modifier: %s") % (self.org_unit_id, self.grp_id, self.circ_modifier_id)
308 class CircMatrixTest(models.Model):
309 matchpoint_id = models.ForeignKey(CircMatrixMatchpoint, db_column='matchpoint', blank=False, primary_key=True)
310 max_items_out = models.IntegerField(null=True)
311 max_overdue = models.IntegerField(null=True)
312 max_fines = models.FloatField(max_digits=8, decimal_places=2, null=True)
313 script_test = models.CharField(maxlength=CHAR_MAXLEN, null=True)
315 list_display = ('matchpoint_id','max_items_out','max_overdue','max_fines','script_test')
317 db_table = 'circ_matrix_test'
318 ordering = ['matchpoint_id']
319 verbose_name = _('Circ Matrix Test')
321 return self.matchpoint_id + _(", Max Items Out: %s, Max Overdue: %s, Max Fines: %s") % (self.max_items_out, self.max_overdue, self.max_fines)
323 class CircMatrixCircModTest(models.Model):
324 matchpoint_id = models.ForeignKey(CircMatrixMatchpoint, db_column='matchpoint', blank=False)
325 items_out = models.IntegerField(blank=False)
326 circ_mod_id = models.ForeignKey(CircModifier, db_column='circ_mod', blank=False)
328 search_fields = ['circ_mod_id']
329 list_display = ('matchpoint_id','circ_mod_id','items_out')
331 db_table = 'circ_matrix_circ_mod_test'
332 ordering = ['matchpoint_id']
333 verbose_name = _('Circ Matrix Items Out Cirulation Modifier Subtest')
335 return self.matchpoint_id + _(", Restriction: ") + self.circ_mod_id
337 class CircMatrixRuleSet(models.Model):
338 matchpoint_id = models.ForeignKey(CircMatrixMatchpoint, db_column='matchpoint', blank=False, primary_key=True)
339 duration_rule_id = models.ForeignKey(RuleCircDuration, db_column='duration_rule', blank=False)
340 recurring_fine_rule_id = models.ForeignKey('RuleRecurringFine', db_column='recurring_fine_rule', blank=False)
341 max_fine_rule_id = models.ForeignKey('RuleMaxFine', db_column='max_fine_rule', blank=False)
343 search_fields = ['matchoint_id']
344 list_display = ('matchpoint_id','duration_rule_id','recurring_fine_rule_id','max_fine_rule_id')
346 db_table = 'circ_matrix_ruleset'
347 ordering = ['matchpoint_id']
348 verbose_name = _('Circ Matrix Rule Set')
350 return _(", Duration: %s, Recurring Fine: %s, Max Fine: %s") % (self.duration_rule_id, self.recurring_fine_rule_id, self.max_fine_rule_id)
352 class RuleMaxFine(models.Model):
353 name = models.CharField(maxlength=CHAR_MAXLEN)
354 amount = models.FloatField(max_digits=6, decimal_places=2)
356 search_fields = ['name']
357 list_display = ('name','amount')
359 db_table = 'rule_max_fine'
361 verbose_name = _('Circ Max Fine Rule')
365 class RuleRecurringFine(models.Model):
366 name = models.CharField(maxlength=CHAR_MAXLEN)
367 high = models.FloatField(max_digits=6, decimal_places=2)
368 normal = models.FloatField(max_digits=6, decimal_places=2)
369 low = models.FloatField(max_digits=6, decimal_places=2)
371 search_fields = ['name']
372 list_display = ('name','high', 'normal', 'low')
374 db_table = 'rule_recuring_fine'
376 verbose_name = 'Circ Recurring Fine Rule'
380 class IdentificationType(models.Model):
381 name = models.CharField(maxlength=CHAR_MAXLEN)
383 search_fields = ['name']
385 db_table = 'identification_type'
387 verbose_name = _('Identification Type')
392 class RuleAgeHoldProtect(models.Model):
393 name = models.CharField(maxlength=CHAR_MAXLEN)
394 age = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT)
395 prox = models.IntegerField()
397 search_fields = ['name']
399 db_table = 'rule_age_hold_protect'
401 verbose_name = _('Hold Age Protection Rule')
407 class MetabibField(models.Model):
408 field_class_choices = (
410 ('author', 'Author'),
411 ('subject', 'Subject'),
412 ('series', 'Series'),
413 ('keyword', 'Keyword'),
415 field_class = models.CharField(maxlength=CHAR_MAXLEN, choices=field_class_choices, null=False, blank=False)
416 name = models.CharField(maxlength=CHAR_MAXLEN, null=False, blank=False)
417 xpath = models.TextField(null=False, blank=False)
418 weight = models.IntegerField(null=False, blank=False)
419 format_id = models.ForeignKey('XmlTransform', db_column='format')
421 search_fields = ['name', 'field_class', 'format_id']
422 list_display = ('field_class', 'name', 'format_id')
424 db_table = 'metabib_field'
425 ordering = ['field_class', 'name']
426 verbose_name = _('Metabib Field')
431 class CopyStatus(models.Model):
432 name = models.CharField(maxlength=CHAR_MAXLEN)
433 holdable = models.BooleanField()
435 search_fields = ['name']
436 list_display = ('name', 'holdable')
438 db_table = 'copy_status'
440 verbose_name= _('Copy Status')
441 verbose_name_plural= _('Copy Statuses')
446 class AudienceMap(models.Model):
447 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
448 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
449 description = models.CharField(maxlength=CHAR_MAXLEN)
451 search_fields = ['code', 'value', 'description']
452 list_display = ('code', 'value', 'description')
454 db_table = 'audience_map'
456 verbose_name = _('Audience Map')
461 class BibSource(models.Model):
462 quality = models.IntegerField()
463 source = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
464 transcendant = models.BooleanField()
466 search_fields = ['source']
467 list_display = ('source', 'quality', 'transcendant')
469 db_table = 'bib_source'
470 ordering = ['source']
471 verbose_name = _('Bib Source')
475 class ItemFormMap(models.Model):
476 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
477 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
479 search_fields = ['code', 'value']
480 list_display = ('code', 'value')
482 db_table = 'item_form_map'
484 verbose_name = _('Item Form Map')
488 class ItemTypeMap(models.Model):
489 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
490 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
492 search_fields = ['code', 'value']
493 list_display = ('code', 'value')
495 db_table = 'item_type_map'
497 verbose_name = _('Item Type Map')
503 class LanguageMap(models.Model):
504 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
505 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
507 search_fields = ['code', 'value']
508 list_display = ('code', 'value')
510 db_table = 'language_map'
512 verbose_name = _('Language Map')
517 class LitFormMap(models.Model):
518 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
519 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
520 description = models.CharField(maxlength=CHAR_MAXLEN)
522 search_fields = ['code', 'value', 'description']
523 list_display = ('code', 'value', 'description')
525 db_table = 'lit_form_map'
527 verbose_name = _('Lit Form Map')
531 class NetAccessLevel(models.Model):
532 name = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
534 search_fields = ['name']
536 db_table = 'net_access_level'
538 verbose_name = _('Net Access Level')
543 class XmlTransform(models.Model):
544 name = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
545 namespace_uri = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
546 prefix = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
547 xslt = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
549 search_fields = ['name', 'namespace_uri', 'prefix' ]
550 list_display = ('name', 'prefix', 'namespace_uri', 'xslt')
552 db_table = 'xml_transform'
554 verbose_name = _('XML Transform')