1 from django.db import models
2 from django.db.models import signals
3 from django.dispatch import dispatcher
5 from gettext import gettext as _
7 INTERVAL_HELP_TEXT = _('examples: "1 hour", "14 days", "3 months", "DD:HH:MM:SS.ms"')
8 CHAR_MAXLEN=200 # just provide a sane default
11 """ --------------------------------------------------------------
13 -------------------------------------------------------------- """
16 class PermList(models.Model):
17 code = models.CharField(maxlength=100)
18 description = models.TextField(blank=True)
20 list_display = ('code','description')
21 search_fields = ['code']
23 db_table = 'perm_list'
25 verbose_name = _('Permission')
29 class GrpPermMap(models.Model):
30 grp_id = models.ForeignKey('GrpTree', db_column='grp')
31 perm_id = models.ForeignKey(PermList, db_column='perm')
32 depth_id = models.ForeignKey('OrgUnitType', to_field='depth', db_column='depth')
33 grantable = models.BooleanField()
35 list_filter = ['grp_id']
36 list_display = ('perm_id', 'grp_id', 'depth_id')
38 db_table = 'grp_perm_map'
39 ordering = ['perm_id', 'grp_id']
40 verbose_name = _('Permission Setting')
42 return str(self.grp_id)+' -> '+str(self.perm_id)
44 class GrpTree(models.Model):
45 name = models.CharField(maxlength=100)
46 parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent')
47 description = models.CharField(blank=True, maxlength=CHAR_MAXLEN)
48 perm_interval = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT)
49 application_perm = models.CharField(blank=True, maxlength=100)
50 usergroup = models.BooleanField()
52 list_display = ('name', 'description')
53 list_filter = ['parent_id']
54 search_fields = ['name', 'description']
58 verbose_name = _('User Group')
66 """ There's no way to do user-based mangling given the size of the data without custom handling.
67 When you try to create a new permission map, it tries to load all users into a dropdown selector :(
69 class User(models.Model):
70 card_id = models.ForeignKey('Card', db_column='card')
71 profile_id = models.ForeignKey(GrpTree, db_column='profile')
72 usrname = models.CharField(blank=False, null=False, maxlength=CHAR_MAXLEN)
74 return "%s (%s)" % ( str(self.card_id), str(self.usrname))
79 class UsrPermMap(models.Model):
80 usr_id = models.ForeignKey(User, db_column='usr')
81 perm_id = models.ForeignKey(PermList, db_column='perm')
82 depth_id = models.ForeignKey(OrgUnitType, to_field='depth', db_column='depth')
83 grantable = models.BooleanField()
85 search_fields = ['usr_id', 'perm_id'] # we need text fields to search...
87 db_table = 'usr_perm_map'
88 verbose_name = 'User Permission'
90 return "%s -> %s" % ( str(self.usr_id), str(self.perm_id) )
93 class Card(models.Model):
94 usr_id = models.ForeignKey(User, db_column='usr')
95 barcode = models.CharField(blank=False, null=False, maxlength=CHAR_MAXLEN)
96 active = models.BooleanField()
101 verbose_name = 'Card'
106 """ --------------------------------------------------------------
108 -------------------------------------------------------------- """
110 class OrgUnitType(models.Model):
111 name = models.CharField(maxlength=100)
112 opac_label = models.CharField(maxlength=100)
113 depth = models.IntegerField()
114 parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent')
115 can_have_vols = models.BooleanField()
116 can_have_users = models.BooleanField()
118 db_table = 'org_unit_type'
119 verbose_name = _('Organizational Unit Type')
121 list_display = ('name', 'depth')
122 list_filter = ['parent_id']
127 class OrgUnitSetting(models.Model):
128 org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit')
129 name = models.CharField(maxlength=CHAR_MAXLEN)
130 value = models.CharField(maxlength=CHAR_MAXLEN)
132 list_display = ('org_unit_id', 'name', 'value')
133 search_fields = ['name', 'value']
134 list_filter = ['name', 'org_unit_id']
136 db_table = 'org_unit_setting'
137 ordering = ['org_unit_id', 'name']
138 verbose_name = _('Organizational Unit Setting')
140 return "%s:%s=%s" % (self.org_unit_id.shortname, self.name, self.value)
143 class OrgAddress(models.Model):
144 valid = models.BooleanField()
145 org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit')
146 address_type = models.CharField(blank=False, maxlength=CHAR_MAXLEN, default=_('MAILING'))
147 street1 = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
148 street2 = models.CharField(maxlength=CHAR_MAXLEN)
149 city = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
150 county = models.CharField(maxlength=CHAR_MAXLEN)
151 state = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
152 country = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
153 post_code = models.CharField(blank=False, maxlength=CHAR_MAXLEN)
155 search_fields = ['street1', 'city', 'post_code']
156 list_filter = ['org_unit_id']
157 list_display = ('street1', 'street2', 'city', 'county', 'state', 'post_code')
160 db_table = 'org_address'
161 verbose_name = _('Organizational Unit Address')
163 return self.street1+' '+self.city+', '+self.state+' '+self.post_code
165 class OrgUnit(models.Model):
166 parent_ou_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent_ou')
167 ou_type_id = models.ForeignKey(OrgUnitType, db_column='ou_type')
168 shortname = models.CharField(maxlength=CHAR_MAXLEN)
169 name = models.CharField(maxlength=CHAR_MAXLEN)
170 email = models.EmailField(null=True, blank=True)
171 phone = models.CharField(maxlength=CHAR_MAXLEN, null=True, blank=True)
172 opac_visible = models.BooleanField(blank=True)
173 ill_address_id = models.ForeignKey(OrgAddress,
174 db_column='ill_address', related_name='ill_addresses', null=True, blank=True)
175 holds_address_id = models.ForeignKey(OrgAddress,
176 db_column='holds_address', related_name='holds_addresses', null=True, blank=True)
177 mailing_address_id = models.ForeignKey(OrgAddress,
178 db_column='mailing_address', related_name='mailing_addresses', null=True, blank=True)
179 billing_address_id = models.ForeignKey(OrgAddress,
180 db_column='billing_address', related_name='billing_addresses', null=True, blank=True)
182 search_fields = ['name', 'shortname']
183 list_display = ('shortname', 'name')
185 db_table = 'org_unit'
186 ordering = ['shortname']
187 verbose_name = _('Organizational Unit')
189 return self.shortname
191 class HoursOfOperation(models.Model):
192 #choices = tuple([ (datetime.time(i), str(i)) for i in range(0,23) ])
193 org_unit = models.ForeignKey('OrgUnit', db_column='id')
194 # XXX add better time widget support
195 dow_0_open = models.TimeField(_('Monday Open'), null=False, blank=False, default=datetime.time(9))
196 dow_0_close = models.TimeField(_('Monday Close'), null=False, blank=False, default=datetime.time(17))
197 dow_1_open = models.TimeField(_('Tuesday Open'), null=False, blank=False, default=datetime.time(9))
198 dow_1_close = models.TimeField(_('Tuesday Close'), null=False, blank=False, default=datetime.time(17))
199 dow_2_open = models.TimeField(_('Wednesday Open'), null=False, blank=False, default=datetime.time(9))
200 dow_2_close = models.TimeField(_('Wednesday Close'), null=False, blank=False, default=datetime.time(17))
201 dow_3_open = models.TimeField(_('Thursday Open'), null=False, blank=False, default=datetime.time(9))
202 dow_3_close = models.TimeField(_('Thursday Close'), null=False, blank=False, default=datetime.time(17))
203 dow_4_open = models.TimeField(_('Friday Open'), null=False, blank=False, default=datetime.time(9))
204 dow_4_close = models.TimeField(_('Friday Close'), null=False, blank=False, default=datetime.time(17))
205 dow_5_open = models.TimeField(_('Saturday Open'), null=False, blank=False, default=datetime.time(9))
206 dow_5_close = models.TimeField(_('Saturday Close'), null=False, blank=False, default=datetime.time(17))
207 dow_6_open = models.TimeField(_('Sunday Open'), null=False, blank=False, default=datetime.time(9))
208 dow_6_close = models.TimeField(_('Sunday Close'), null=False, blank=False, default=datetime.time(17))
212 db_table = 'hours_of_operation'
213 verbose_name = _('Hours of Operation')
214 verbose_name_plural = verbose_name
216 return str(self.org_unit)
220 """ --------------------------------------------------------------
222 -------------------------------------------------------------- """
224 class CircModifier(models.Model):
225 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
226 name = models.CharField(maxlength=CHAR_MAXLEN)
227 description = models.CharField(maxlength=CHAR_MAXLEN);
228 sip2_media_type = models.CharField(maxlength=CHAR_MAXLEN);
229 magnetic_media = models.BooleanField()
231 search_fields = ['name','code']
232 list_display = ('code','name','description','sip2_media_type','magnetic_media')
234 db_table = 'circ_modifier'
236 verbose_name = _('Circulation Modifier')
241 class VideoRecordingFormat(models.Model):
242 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
243 value = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
245 search_fields = ['value','code']
246 list_display = ('value','code')
248 db_table = 'videorecording_format_map'
250 verbose_name = _('Video Recording Format')
254 class RuleCircDuration(models.Model):
255 name = models.CharField(maxlength=CHAR_MAXLEN)
256 extended = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
257 normal = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
258 shrt = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT);
259 max_renewals = models.IntegerField()
261 search_fields = ['name']
262 list_display = ('name','extended','normal','shrt','max_renewals')
264 db_table = 'rule_circ_duration'
266 verbose_name = _('Circ Duration Rule')
270 class CircMatrixMatchpoint(models.Model):
271 active = models.BooleanField(blank=False, default=True)
272 org_unit_id = models.ForeignKey(OrgUnit, db_column='org_unit', blank=False)
273 grp_id = models.ForeignKey(GrpTree, db_column='grp', blank=False, verbose_name=_("User Group"))
274 circ_modifier_id = models.ForeignKey(CircModifier, db_column='circ_modifier', null=True,blank=True)
275 marc_type_id = models.ForeignKey('ItemTypeMap', db_column='marc_type', null=True,blank=True)
276 marc_form_id = models.ForeignKey('ItemFormMap', db_column='marc_form', null=True,blank=True)
277 marc_vr_format_id = models.ForeignKey('VideoRecordingFormat', db_column='marc_vr_format', null=True,blank=True)
278 ref_flag = models.BooleanField(null=True)
279 usr_age_lower_bound = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT, null=True, blank=True)
280 usr_age_upper_bound = models.CharField(maxlength=CHAR_MAXLEN, help_text=INTERVAL_HELP_TEXT, null=True, blank=True)
283 ''' Override to force None-ness on the interval fields '''
284 if self.usr_age_lower_bound == "":
285 self.usr_age_lower_bound = None
286 if self.usr_age_upper_bound == "":
287 self.usr_age_upper_bound = None
288 return models.Model.save(self)
291 search_fields = ['grp_id','org_unit_id','circ_modifier_id','marc_type_id','marc_form_id',
292 'marc_vr_format_id','usr_age_lower_bound','usr_age_upper_bound']
294 list_display = ('grp_id','org_unit_id','circ_modifier_id','marc_type_id','marc_form_id',
295 'marc_vr_format_id','ref_flag','usr_age_lower_bound','usr_age_upper_bound')
297 list_filter = ['grp_id','org_unit_id','circ_modifier_id','marc_type_id','marc_form_id','marc_vr_format_id']
299 db_table = 'circ_matrix_matchpoint'
301 verbose_name = _('Circulation Matrix Matchpoint')
303 return _("OrgUnit: %(orgid)s, Group: %(grpid)s, Circ Modifier: %(modid)s") % {
304 'orgid':self.org_unit_id, 'grpid':self.grp_id, 'modid':self.circ_modifier_id}
306 class CircMatrixTest(models.Model):
307 matchpoint_id = models.ForeignKey(CircMatrixMatchpoint, db_column='matchpoint', blank=False, primary_key=True,
308 edit_inline=models.TABULAR, core=True, num_in_admin=1)
309 max_items_out = models.IntegerField(null=True, blank=True)
310 max_overdue = models.IntegerField(null=True, blank=True)
311 max_fines = models.FloatField(max_digits=8, decimal_places=2, null=True, blank=True)
312 script_test = models.CharField(maxlength=CHAR_MAXLEN, null=True, blank=True)
314 list_display = ('matchpoint_id','max_items_out','max_overdue','max_fines','script_test')
316 db_table = 'circ_matrix_test'
317 ordering = ['matchpoint_id']
318 verbose_name = _('Circ Matrix Test')
320 return _("%(mid)s, Max Items Out: %(iout)s, Max Overdue: %(odue)s, Max Fines: %(fines)s") % {
321 'mid': self.matchpoint_id, 'iout' : self.max_items_out, 'odue':self.max_overdue, 'fines':self.max_fines}
323 class CircMatrixCircModTest(models.Model):
324 matchpoint_id = models.ForeignKey(CircMatrixMatchpoint, db_column='matchpoint', blank=False, edit_inline=True,core=True, num_in_admin=1)
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 _("%(mid)s, Restriction: %(mod)s") % {'mid': self.matchpoint_id,'mod':self.circ_mod_id}
337 class CircMatrixRuleSet(models.Model):
338 matchpoint_id = models.ForeignKey(CircMatrixMatchpoint, db_column='matchpoint',
339 blank=False, primary_key=True, edit_inline=True,core=True, num_in_admin=1)
340 duration_rule_id = models.ForeignKey(RuleCircDuration, db_column='duration_rule', blank=False)
341 recurring_fine_rule_id = models.ForeignKey('RuleRecurringFine', db_column='recurring_fine_rule', blank=False)
342 max_fine_rule_id = models.ForeignKey('RuleMaxFine', db_column='max_fine_rule', blank=False)
344 search_fields = ['matchoint_id']
345 list_display = ('matchpoint_id','duration_rule_id','recurring_fine_rule_id','max_fine_rule_id')
347 db_table = 'circ_matrix_ruleset'
348 ordering = ['matchpoint_id']
349 verbose_name = _('Circ Matrix Rule Set')
351 return _("Duration: %(dur)s, Recurring Fine: %(rfine)s, Max Fine: %(mfine)s") % {
352 'dur':self.duration_rule_id, 'rfine':self.recurring_fine_rule_id, 'mfine':self.max_fine_rule_id}
354 class RuleMaxFine(models.Model):
355 name = models.CharField(maxlength=CHAR_MAXLEN)
356 amount = models.FloatField(max_digits=6, decimal_places=2)
358 search_fields = ['name']
359 list_display = ('name','amount')
361 db_table = 'rule_max_fine'
363 verbose_name = _('Circ Max Fine Rule')
367 class RuleRecurringFine(models.Model):
368 name = models.CharField(maxlength=CHAR_MAXLEN)
369 high = models.FloatField(max_digits=6, decimal_places=2)
370 normal = models.FloatField(max_digits=6, decimal_places=2)
371 low = models.FloatField(max_digits=6, decimal_places=2)
373 search_fields = ['name']
374 list_display = ('name','high', 'normal', 'low')
376 db_table = 'rule_recuring_fine'
378 verbose_name = 'Circ Recurring Fine Rule'
382 class IdentificationType(models.Model):
383 name = models.CharField(maxlength=CHAR_MAXLEN)
385 search_fields = ['name']
387 db_table = 'identification_type'
389 verbose_name = _('Identification Type')
394 class RuleAgeHoldProtect(models.Model):
395 name = models.CharField(maxlength=CHAR_MAXLEN)
396 age = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT)
397 prox = models.IntegerField()
399 search_fields = ['name']
401 db_table = 'rule_age_hold_protect'
403 verbose_name = _('Hold Age Protection Rule')
409 class MetabibField(models.Model):
410 field_class_choices = (
412 ('author', 'Author'),
413 ('subject', 'Subject'),
414 ('series', 'Series'),
415 ('keyword', 'Keyword'),
417 field_class = models.CharField(maxlength=CHAR_MAXLEN, choices=field_class_choices, null=False, blank=False)
418 name = models.CharField(maxlength=CHAR_MAXLEN, null=False, blank=False)
419 xpath = models.TextField(null=False, blank=False)
420 weight = models.IntegerField(null=False, blank=False)
421 format_id = models.ForeignKey('XmlTransform', db_column='format')
423 search_fields = ['name', 'field_class', 'format_id']
424 list_display = ('field_class', 'name', 'format_id')
426 db_table = 'metabib_field'
427 ordering = ['field_class', 'name']
428 verbose_name = _('Metabib Field')
433 class CopyStatus(models.Model):
434 name = models.CharField(maxlength=CHAR_MAXLEN)
435 holdable = models.BooleanField()
437 search_fields = ['name']
438 list_display = ('name', 'holdable')
440 db_table = 'copy_status'
442 verbose_name= _('Copy Status')
443 verbose_name_plural= _('Copy Statuses')
448 class AudienceMap(models.Model):
449 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
450 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
451 description = models.CharField(maxlength=CHAR_MAXLEN)
453 search_fields = ['code', 'value', 'description']
454 list_display = ('code', 'value', 'description')
456 db_table = 'audience_map'
458 verbose_name = _('Audience Map')
463 class BibSource(models.Model):
464 quality = models.IntegerField()
465 source = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
466 transcendant = models.BooleanField()
468 search_fields = ['source']
469 list_display = ('source', 'quality', 'transcendant')
471 db_table = 'bib_source'
472 ordering = ['source']
473 verbose_name = _('Bib Source')
477 class ItemFormMap(models.Model):
478 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
479 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
481 search_fields = ['code', 'value']
482 list_display = ('code', 'value')
484 db_table = 'item_form_map'
486 verbose_name = _('Item Form Map')
490 class ItemTypeMap(models.Model):
491 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
492 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
494 search_fields = ['code', 'value']
495 list_display = ('code', 'value')
497 db_table = 'item_type_map'
499 verbose_name = _('Item Type Map')
505 class LanguageMap(models.Model):
506 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
507 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
509 search_fields = ['code', 'value']
510 list_display = ('code', 'value')
512 db_table = 'language_map'
514 verbose_name = _('Language Map')
519 class LitFormMap(models.Model):
520 code = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
521 value = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
522 description = models.CharField(maxlength=CHAR_MAXLEN)
524 search_fields = ['code', 'value', 'description']
525 list_display = ('code', 'value', 'description')
527 db_table = 'lit_form_map'
529 verbose_name = _('Lit Form Map')
533 class NetAccessLevel(models.Model):
534 name = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
536 search_fields = ['name']
538 db_table = 'net_access_level'
540 verbose_name = _('Net Access Level')
545 class XmlTransform(models.Model):
546 name = models.CharField(maxlength=CHAR_MAXLEN, blank=False, primary_key=True)
547 namespace_uri = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
548 prefix = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
549 xslt = models.CharField(maxlength=CHAR_MAXLEN, blank=False)
551 search_fields = ['name', 'namespace_uri', 'prefix' ]
552 list_display = ('name', 'prefix', 'namespace_uri', 'xslt')
554 db_table = 'xml_transform'
556 verbose_name = _('XML Transform')