1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 """Set of classes to store persons, organizations, relationships and
28 permissions
29
30 These structures are modeled like described in 'The Data Model Resource Book'
31 by Len Silverston, Chapter 2
32 """
33
34 import camelot
35 import camelot.types
36
37 from camelot.model import *
38 from camelot.model.synchronization import *
39
40 __metadata__ = metadata
41
42 from camelot.view.elixir_admin import EntityAdmin
43 from camelot.view.forms import Form, TabForm, VBoxForm, HBoxForm, WidgetOnlyForm
44 import datetime
45
46 _current_person_ = None
49 return datetime.date(year=2400, month=12, day=31)
50
58
65
72
74 """Relation from employer to employee"""
75 using_options(tablename='party_relationship_empl', inheritance='multi')
76 established_from = ManyToOne('Organization', required=True, ondelete='cascade', onupdate='cascade')
77 established_to = ManyToOne('Person', required=True, ondelete='cascade', onupdate='cascade')
78
80 name = 'Employees'
81 list_display = ['established_to', 'from_date', 'thru_date']
82 fields = ['established_to', 'comment', 'from_date', 'thru_date']
83 field_attributes = {'established_to':{'name':'Name'}}
84
86 name = 'Employers'
87 list_display = ['established_from', 'from_date', 'thru_date']
88 fields = ['established_from', 'comment', 'from_date', 'thru_date']
89 field_attributes = {'established_from':{'name':'Name'}}
90
92 """Relation from a directed organization to a director"""
93 using_options(tablename='party_relationship_dir', inheritance='multi')
94 established_from = ManyToOne('Organization', required=True, ondelete='cascade', onupdate='cascade')
95 established_to = ManyToOne('Person', required=True, ondelete='cascade', onupdate='cascade')
96 title = Field(Unicode(256))
97 representing = OneToMany('RepresentedRepresentor', inverse='established_to')
98
100 name = 'Directors'
101 list_display = ['established_to', 'from_date', 'thru_date']
102 fields = ['established_to', 'title', 'from_date', 'thru_date', 'representing', 'comment']
103 field_attributes = {'established_to':{'name':'Name'}}
104
106 name = 'Directed organizations'
107 list_display = ['established_from', 'from_date', 'thru_date']
108 fields = ['established_from', 'from_date', 'thru_date', 'representing', 'comment']
109 field_attributes = {'established_from':{'name':'Name'}}
110
112 """Relation from a represented party to the director representing the party"""
113 using_options(tablename='party_representor')
114 from_date = Field(Date(), default=datetime.date.today, required=True, index=True)
115 thru_date = Field(Date(), default=end_of_times, required=True, index=True)
116 comment = Field(Text)
117 established_from = ManyToOne('Party', required=True, ondelete='cascade', onupdate='cascade')
118 established_to = ManyToOne('DirectedDirector', required=True, ondelete='cascade', onupdate='cascade')
119
120 - class Admin(EntityAdmin):
121 name = 'Representing'
122 list_display = ['established_from', 'from_date', 'thru_date', 'comment']
123 field_attributes = {'established_from':{'name':'Name'}}
124
126 """Relation from supplier to customer"""
127 using_options(tablename='party_relationship_suppl', inheritance='multi')
128 established_from = ManyToOne('Party', required=True, ondelete='cascade', onupdate='cascade')
129 established_to = ManyToOne('Party', required=True, ondelete='cascade', onupdate='cascade')
130
136
138 name = 'Suppliers'
139 list_display = ['established_from',]
140 fields = ['established_from', 'comment', 'from_date', 'thru_date']
141 field_attributes = {'established_from':{'name':'Name'}}
142
144 """Relation from a shared organization to a shareholder"""
145 using_options(tablename='party_relationship_shares', inheritance='multi')
146 established_from = ManyToOne('Organization', required=True, ondelete='cascade', onupdate='cascade')
147 established_to = ManyToOne('Party', required=True, ondelete='cascade', onupdate='cascade')
148 shares = Field(Integer())
149
151 name = 'Shareholders'
152 list_display = ['established_to', 'shares', 'from_date', 'thru_date']
153 fields = ['established_to', 'shares', 'from_date', 'thru_date', 'comment']
154 field_attributes = {'established_to':{'name':'Shareholder name'}}
155
157 name = 'Shares'
158 list_display = ['established_from', 'shares', 'from_date', 'thru_date']
159 fields = ['established_from', 'shares', 'from_date', 'thru_date', 'comment']
160 field_attributes = {'established_from':{'name':'Name'}}
161
163 """Base class for persons and organizations. Use this base class to refer to either persons or
164 organisations in building authentication systems, contact management or CRM"""
165 using_options(tablename='party')
166 is_synchronized('synchronized', lazy=True)
167 addresses = OneToMany('PartyAddress', lazy=True)
168 contact_mechanisms = OneToMany('PartyContactMechanism', lazy=True)
169
170 @property
173
174 - class Admin(EntityAdmin):
175 name = 'Parties'
176 list_display = ['name']
177 fields = ['suppliers', 'customers', 'addresses']
178 field_attributes = dict(suppliers={'admin':SupplierCustomer.SupplierAdmin},
179 customers={'admin':SupplierCustomer.CustomerAdmin},
180 employers={'admin':EmployerEmployee.EmployerAdmin},
181 employees={'admin':EmployerEmployee.EmployeeAdmin},
182 directed_organizations={'admin':DirectedDirector.DirectedAdmin},
183 directors={'admin':DirectedDirector.DirectorAdmin},
184 shares={'admin':SharedShareholder.SharedAdmin},
185 shareholders={'admin':SharedShareholder.ShareholderAdmin},
186 sex=dict(choices=lambda obj:[(u'M',u'Male'), (u'F',u'Female')],),
187 )
188
190 """An organization represents any internal or external organization. Organizations can include
191 businesses and groups of individuals"""
192 using_options(tablename='organization', inheritance='multi')
193 name = Field(Unicode(50), required=True, index=True)
194 logo = Field(camelot.types.Image(upload_to='organization-logo'), deferred=True)
195 tax_id = Field(Unicode(20))
196 directors = OneToMany('DirectedDirector', inverse='established_from')
197 employees = OneToMany('EmployerEmployee', inverse='established_from')
198 suppliers = OneToMany('SupplierCustomer', inverse='established_to')
199 customers = OneToMany('SupplierCustomer', inverse='established_from')
200 shareholders = OneToMany('SharedShareholder', inverse='established_from')
201 shares = OneToMany('SharedShareholder', inverse='established_to')
202
205
206 @property
209
210 - class Admin(Party.Admin):
211 name = 'Organizations'
212 section = 'relations'
213 list_display = ['name', 'tax_id',]
214 form = TabForm([('Basic', Form(['name', 'tax_id', 'addresses', 'contact_mechanisms'])),
215 ('Employment', Form(['employees'])),
216 ('Customers', Form(['customers'])),
217 ('Suppliers', Form(['suppliers'])),
218 ('Corporate', Form(['directors', 'shareholders', 'shares'])),
219 ('Branding', Form(['logo'])), ])
220
222 """Person represents natural persons, these can be given access to the system
223 and as such require a username.
224
225 Username is required, other fields are optional, there is no password because
226 authentication is supposed to happen through the operating system services or
227 other.
228 """
229 using_options(tablename='person', inheritance='multi')
230 username = Field(Unicode(40), required=True, index=True, unique=True)
231 first_name = Field(Unicode(40))
232 last_name = Field(Unicode(40))
233 middle_name = Field(Unicode(40))
234 personal_title = Field(Unicode(10))
235 suffix = Field(Unicode(3))
236 sex = Field(Unicode(1), default=u'M')
237 birthdate = Field(Date())
238 martial_status = Field(Unicode(1))
239 social_security_number = Field(Unicode(12))
240 passport_number = Field(Unicode(20))
241 passport_expiry_date = Field(Date())
242 is_staff = Field(Boolean, default=False, index=True)
243 is_active = Field(Boolean, default=True, index=True)
244 is_superuser = Field(Boolean, default=False, index=True)
245 last_login = Field(DateTime(), default=datetime.datetime.now)
246 date_joined = Field(DateTime(), default=datetime.datetime.now)
247 picture = Field(camelot.types.Image(upload_to='person-pictures'), deferred=True)
248 comment = Field(Text)
249 employers = OneToMany('EmployerEmployee', inverse='established_to')
250 directed_organizations = OneToMany('DirectedDirector', inverse='established_to')
251 shares = OneToMany('SharedShareholder', inverse='established_to')
252
253 @property
259
262
263 @classmethod
271
272 - class Admin(Party.Admin):
273 name = 'Persons'
274 section = 'relations'
275 list_display = ['username', 'first_name', 'last_name', ]
276 list_filter = ['is_active', 'is_staff', 'is_superuser']
277 form = TabForm([('Basic', Form([HBoxForm([Form(['username', 'first_name', 'last_name', 'sex']),
278 Form(['is_staff', 'is_active', 'is_superuser',]),
279 Form(['picture',]),
280 ]),
281 'contact_mechanisms', 'comment',], scrollbars=True)),
282 ('Official', Form(['birthdate', 'social_security_number', 'passport_number','passport_expiry_date','addresses',], scrollbars=True)),
283 ('Work', Form(['employers', 'directed_organizations', 'shares'], scrollbars=True))
284 ])
285
287 using_options(tablename='geographic_boundary')
288 code = Field(Unicode(10))
289 name = Field(Unicode(40), required=True)
290
292 return u'%s %s'%(self.code, self.name)
293
295 using_options(tablename='geographic_boundary_country', inheritance='multi')
296
297 @classmethod
305
306 - class Admin(EntityAdmin):
309
310 -class City(GeographicBoundary):
311 using_options(tablename='geographic_boundary_city', inheritance='multi')
312 country = ManyToOne('Country', required=True, ondelete='cascade', onupdate='cascade')
313
314 @classmethod
322
323 - class Admin(EntityAdmin):
326
328 using_options(tablename='address')
329 street1 = Field(Unicode(128), required=True)
330 street2 = Field(Unicode(128))
331 city = ManyToOne('City', required=True, ondelete='cascade', onupdate='cascade')
332 is_synchronized('synchronized', lazy=True)
333
336
338 from PyQt4 import QtGui, QtCore
339 QtGui.QDesktopServices.openUrl (QtCore.QUrl('http://www.google.be/maps?f=q&source=s_q&geocode=%s&q=%s+%s'%(self.city.country.code, self.street1, self.city.name)))
340
341 - class Admin(EntityAdmin):
345
347 using_options(tablename='party_address_role_type')
348 code = Field(Unicode(10))
349 description = Field(Unicode(40))
350
351 - class Admin(EntityAdmin):
354
356 using_options(tablename='party_address')
357 party = ManyToOne('Party', required=True, ondelete='cascade', onupdate='cascade')
358 address = ManyToOne('Address', required=True, ondelete='cascade', onupdate='cascade')
359 from_date = Field(Date(), default=datetime.date.today, required=True, index=True)
360 thru_date = Field(Date(), default=end_of_times, required=True, index=True)
361 comment = Field(Unicode(256))
362
364 return '%s : %s'%(unicode(self.party), unicode(self.address))
365
369
370 - class Admin(EntityAdmin):
375
388
404