1
# -*- coding: utf-8 -*-
9
# -----------------------------------------------------------------------------
13
tablename = "%s_%s" % (module, resource)
14
table = db.define_table(tablename,
15
Field("audit_read", "boolean"),
16
Field("audit_write", "boolean"),
19
# -----------------------------------------------------------------------------
20
# Sectors (to be renamed as Clusters)
23
tablename = "%s_%s" % (module, resource)
24
table = db.define_table(tablename, timestamp, uuidstamp, deletion_status,
25
Field("name", length=128, notnull=True, unique=True),
29
table.uuid.requires = IS_NOT_IN_DB(db, "%s.uuid" % tablename)
30
table.name.requires = [IS_NOT_EMPTY(), IS_NOT_IN_DB(db, "%s.name" % tablename)]
31
table.name.label = T("Name")
32
table.name.comment = SPAN("*", _class="req")
35
def shn_sector_represent(sector_ids):
38
elif "|" in str(sector_ids):
39
sectors = [db(db.org_sector.id == id).select(db.org_sector.name, limitby=(0, 1)).first().name for id in sector_ids.split("|") if id]
40
return ", ".join(sectors)
42
return db(db.org_sector.id == sector_ids).select(db.org_sector.name, limitby=(0, 1)).first().name
45
ADD_SECTOR = T("Add Sector")
46
sector_id = db.Table(None, "sector_id",
47
FieldS3("sector_id", sortby="name",
48
requires = IS_NULL_OR(IS_ONE_OF(db, "org_sector.id", "%(name)s", multiple=True)),
49
represent = shn_sector_represent,
51
comment = DIV(A(ADD_SECTOR, _class="colorbox", _href=URL(r=request, c="org", f="sector", args="create", vars=dict(format="popup")), _target="top", _title=ADD_SECTOR),
52
DIV( _class="tooltip", _title=Tstr("Add Sector") + "|" + Tstr("The Sector(s) this organization works in. Multiple values can be selected by holding down the 'Control' key."))),
56
# -----------------------------------------------------------------------------
59
org_organisation_type_opts = {
62
3:T("International NGO"),
63
4:T("Donor"), # Don't change this number without changing organisation_popup.html
66
8:T("International Organization"),
69
#12:T("MINUSTAH") Haiti-specific
72
resource = "organisation"
73
tablename = module + "_" + resource
74
table = db.define_table(tablename, timestamp, uuidstamp, deletion_status,
75
pr_pe_fieldset, # Person Entity Field Set
76
#Field("privacy", "integer", default=0),
77
#Field("archived", "boolean", default=False),
78
Field("name", length=128, notnull=True, unique=True),
79
Field("acronym", length=8),
80
Field("type", "integer"),
82
#Field("registration", label=T("Registration")), # Registration Number
83
Field("country", "integer"),
85
Field("twitter"), # deprecated by pe_contact component
86
Field("donation_phone"),
92
table.uuid.requires = IS_NOT_IN_DB(db, "%s.uuid" % tablename)
93
table.pr_pe_label.readable = False
94
table.pr_pe_label.writable = False
95
table.name.requires = [IS_NOT_EMPTY(), IS_NOT_IN_DB(db, "%s.name" % tablename)]
96
table.type.requires = IS_NULL_OR(IS_IN_SET(org_organisation_type_opts))
97
table.type.represent = lambda opt: org_organisation_type_opts.get(opt, UNKNOWN_OPT)
98
table.country.requires = IS_NULL_OR(IS_IN_SET(shn_list_of_nations))
99
table.country.represent = lambda opt: shn_list_of_nations.get(opt, UNKNOWN_OPT)
100
table.website.requires = IS_NULL_OR(IS_URL())
101
table.donation_phone.requires = shn_phone_requires
102
table.name.label = T("Name")
103
table.name.comment = SPAN("*", _class="req")
104
table.acronym.label = T("Acronym")
105
table.type.label = T("Type")
106
table.donation_phone.label = T("Donation Phone #")
107
table.donation_phone.comment = DIV( _class="tooltip", _title=Tstr("Donation Phone #") + "|" + Tstr("Phone number to donate to this organization's relief efforts."))
108
table.country.label = T("Home Country")
109
table.website.label = T("Website")
110
# Should be visible to the Dashboard
111
table.website.represent = shn_url_represent
112
table.twitter.label = T("Twitter")
113
table.twitter.comment = DIV( _class="tooltip", _title=Tstr("Twitter") + "|" + Tstr("Twitter ID or #hashtag"))
115
ADD_ORGANIZATION = Tstr("Add Organization")
116
LIST_ORGANIZATIONS = T("List Organizations")
117
s3.crud_strings[tablename] = Storage(
118
title_create = ADD_ORGANIZATION,
119
title_display = T("Organization Details"),
120
title_list = LIST_ORGANIZATIONS,
121
title_update = T("Edit Organization"),
122
title_search = T("Search Organizations"),
123
subtitle_create = T("Add New Organization"),
124
subtitle_list = T("Organizations"),
125
label_list_button = LIST_ORGANIZATIONS,
126
label_create_button = ADD_ORGANIZATION,
127
label_delete_button = T("Delete Organization"),
128
msg_record_created = T("Organization added"),
129
msg_record_modified = T("Organization updated"),
130
msg_record_deleted = T("Organization deleted"),
131
msg_list_empty = T("No Organizations currently registered"))
134
organisation_popup_url = URL(r=request, c="org", f="organisation", args="create", vars=dict(format="popup"))
135
shn_organisation_comment = DIV(A(ADD_ORGANIZATION,
137
_href=organisation_popup_url,
139
_title=ADD_ORGANIZATION),
140
DIV(DIV(_class="tooltip",
141
_title=ADD_ORGANIZATION + "|" + Tstr("The Organization this record is associated with."))))
142
organisation_id = db.Table(None, "organisation_id",
143
FieldS3("organisation_id", db.org_organisation, sortby="name",
144
requires = IS_NULL_OR(IS_ONE_OF(db, "org_organisation.id", "%(name)s")),
145
represent = lambda id: (id and [db(db.org_organisation.id == id).select(db.org_organisation.name, limitby=(0, 1)).first().name] or ["None"])[0],
146
label = T("Organization"),
147
comment = shn_organisation_comment,
148
ondelete = "RESTRICT"
151
# Orgs as component of Clusters
152
s3xrc.model.add_component(module, resource,
154
joinby=dict(org_sector="sector_id"),
158
s3xrc.model.configure(table,
159
# Ensure that table is substituted when lambda defined not evaluated by using the default value
160
onaccept=lambda form, tab=table: shn_pentity_onaccept(form, table=tab, entity_type=5),
161
delete_onaccept=lambda form: shn_pentity_ondelete(form),
169
# -----------------------------------------------------------------------------
172
org_office_type_opts = {
173
1:T("Satellite Office"),
180
tablename = module + "_" + resource
181
table = db.define_table(tablename, timestamp, uuidstamp, deletion_status,
182
pr_pe_fieldset, # Person Entity Field Set
183
Field("name", notnull=True),
185
Field("type", "integer"),
187
Field("parent", "reference org_office"), # This form of hierarchy may not work on all Databases
188
Field("address", "text"),
194
Field("national_staff", "integer"),
195
Field("international_staff", "integer"),
196
Field("number_of_vehicles", "integer"),
197
Field("vehicle_types"),
204
table.uuid.requires = IS_NOT_IN_DB(db, "%s.uuid" % tablename)
205
table.pr_pe_label.readable = False
206
table.pr_pe_label.writable = False
207
#db[table].name.requires = IS_NOT_EMPTY() # Office names don't have to be unique
208
table.name.requires = [IS_NOT_EMPTY(), IS_NOT_IN_DB(db, "%s.name" % tablename)]
209
table.type.requires = IS_NULL_OR(IS_IN_SET(org_office_type_opts))
210
table.type.represent = lambda opt: org_office_type_opts.get(opt, UNKNOWN_OPT)
211
table.parent.requires = IS_NULL_OR(IS_ONE_OF(db, "org_office.id", "%(name)s"))
212
table.parent.represent = lambda id: (id and [db(db.org_office.id == id).select(db.org_office.name, limitby=(0, 1)).first().name] or ["None"])[0]
213
table.phone1.requires = shn_phone_requires
214
table.phone2.requires = shn_phone_requires
215
table.fax.requires = shn_phone_requires
216
table.email.requires = IS_NULL_OR(IS_EMAIL())
217
table.national_staff.requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 99999))
218
table.international_staff.requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999))
219
table.number_of_vehicles.requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999))
220
table.name.label = T("Name")
221
table.name.comment = SPAN("*", _class="req")
222
table.parent.label = T("Parent")
223
table.type.label = T("Type")
224
table.address.label = T("Address")
225
table.postcode.label = T("Postcode")
226
table.phone1.label = T("Phone 1")
227
table.phone2.label = T("Phone 2")
228
table.email.label = T("Email")
229
table.fax.label = T("FAX")
230
table.national_staff.label = T("National Staff")
231
table.international_staff.label = T("International Staff")
232
table.number_of_vehicles.label = T("Number of Vehicles")
233
table.vehicle_types.label = T("Vehicle Types")
234
table.equipment.label = T("Equipment")
236
ADD_OFFICE = Tstr("Add Office")
237
LIST_OFFICES = T("List Offices")
238
s3.crud_strings[tablename] = Storage(
239
title_create = ADD_OFFICE,
240
title_display = T("Office Details"),
241
title_list = LIST_OFFICES,
242
title_update = T("Edit Office"),
243
title_search = T("Search Offices"),
244
subtitle_create = T("Add New Office"),
245
subtitle_list = T("Offices"),
246
label_list_button = LIST_OFFICES,
247
label_create_button = ADD_OFFICE,
248
label_delete_button = T("Delete Office"),
249
msg_record_created = T("Office added"),
250
msg_record_modified = T("Office updated"),
251
msg_record_deleted = T("Office deleted"),
252
msg_list_empty = T("No Offices currently registered"))
254
# Reusable field for other tables to reference
255
office_id = db.Table(None, "office_id",
256
FieldS3("office_id", db.org_office, sortby="name",
257
requires = IS_NULL_OR(IS_ONE_OF(db, "org_office.id", "%(name)s")),
258
represent = lambda id: (id and [db(db.org_office.id == id).select(db.org_office.name, limitby=(0, 1)).first().name] or ["None"])[0],
260
comment = DIV(A(ADD_OFFICE, _class="colorbox", _href=URL(r=request, c="org", f="office", args="create", vars=dict(format="popup")), _target="top", _title=ADD_OFFICE),
261
DIV( _class="tooltip", _title=ADD_OFFICE + "|" + Tstr("The Office this record is associated with."))),
262
ondelete = "RESTRICT"
265
# Offices as component of Orgs & Locations
266
s3xrc.model.add_component(module, resource,
268
joinby=dict(org_organisation="organisation_id", gis_location="location_id"),
272
s3xrc.model.configure(table,
273
# Ensure that table is substituted when lambda defined not evaluated by using the default value
274
onaccept=lambda form, tab=table: shn_pentity_onaccept(form, table=tab, entity_type=6),
275
delete_onaccept=lambda form: shn_pentity_ondelete(form),
278
"organisation_id", # Filtered in Component views
283
# Donors are a type of Organisation
284
def shn_donor_represent(donor_ids):
287
elif "|" in str(donor_ids):
288
donors = [db(db.org_donor.id == id).select(db.org_donor.name, limitby=(0, 1)).first().name for id in donor_ids.split("|") if id]
289
return ", ".join(donors)
291
return db(db.org_donor.id == donor_ids).select(db.org_donor.name, limitby=(0, 1)).first().name
293
ADD_DONOR = Tstr("Add Donor")
294
donor_id = db.Table(None, "donor_id",
295
FieldS3("donor_id", db.org_organisation, sortby="name",
296
requires = IS_NULL_OR(IS_ONE_OF(db, "org_organisation.id", "%(name)s", multiple=True, filterby="type", filter_opts=[4])),
297
represent = shn_donor_represent,
299
comment = DIV(A(ADD_DONOR, _class="colorbox", _href=URL(r=request, c="org", f="organisation", args="create", vars=dict(format="popup", child="donor_id")), _target="top", _title=ADD_DONOR),
300
DIV( _class="tooltip", _title=ADD_DONOR + "|" + Tstr("The Donor(s) for this project. Multiple values can be selected by holding down the 'Control' key."))),
301
ondelete = "RESTRICT"
304
# -----------------------------------------------------------------------------
306
# the projects which each organization is engaged in
308
org_project_status_opts = {
314
tablename = module + "_" + resource
315
table = db.define_table(tablename, timestamp, deletion_status,
321
Field('status', 'integer',
322
requires = IS_IN_SET(org_project_status_opts, zero=None),
324
label = T('Project Status'),
325
represent = lambda opt: org_project_status_opts.get(opt, UNKNOWN_OPT)),
326
Field("description", "text"),
327
Field("beneficiaries", "integer"),
328
Field("start_date", "date"),
329
Field("end_date", "date"),
330
Field("funded", "boolean"),
332
Field("budgeted_cost", "double"),
336
table.code.requires = [IS_NOT_EMPTY(error_message=T("Please fill this!")),
337
IS_NOT_IN_DB(db, "org_project.code")]
338
table.start_date.requires = IS_NULL_OR(IS_DATE())
339
table.end_date.requires = IS_NULL_OR(IS_DATE())
340
table.budgeted_cost.requires = IS_NULL_OR(IS_FLOAT_IN_RANGE(0, 999999999))
342
# Project Resource called from multiple controllers
343
# - so we define strings in the model
344
table.code.label = T("Code")
345
table.code.comment = SPAN("*", _class="req")
346
table.name.label = T("Title")
347
table.start_date.label = T("Start date")
348
table.end_date.label = T("End date")
349
table.description.label = T("Description")
350
#table.description.comment = SPAN("*", _class="req")
351
table.status.label = T("Status")
352
table.status.comment = SPAN("*", _class="req")
354
ADD_PROJECT = Tstr("Add Project")
355
s3.crud_strings[tablename] = Storage(
356
title_create = ADD_PROJECT,
357
title_display = T("Project Details"),
358
title_list = T("List Projects"),
359
title_update = T("Edit Project"),
360
title_search = T("Search Projects"),
361
subtitle_create = T("Add New Project"),
362
subtitle_list = T("Projects"),
363
label_list_button = T("List Projects"),
364
label_create_button = ADD_PROJECT,
365
label_delete_button = T("Delete Project"),
366
msg_record_created = T("Project added"),
367
msg_record_modified = T("Project updated"),
368
msg_record_deleted = T("Project deleted"),
369
msg_list_empty = T("No Projects currently registered"))
372
project_id = db.Table(None, "project_id",
373
FieldS3("project_id", db.org_project, sortby="name",
374
requires = IS_NULL_OR(IS_ONE_OF(db, "org_project.id", "%(code)s")),
375
represent = lambda id: (id and [db.org_project[id].code] or ["None"])[0],
376
comment = DIV(A(ADD_PROJECT, _class="colorbox", _href=URL(r=request, c="org", f="project", args="create", vars=dict(format="popup")), _target="top", _title=ADD_PROJECT),
377
DIV( _class="tooltip", _title=ADD_PROJECT + "|" + Tstr("Add new project."))),
379
ondelete = "RESTRICT"
382
# Projects as component of Orgs & Locations
383
s3xrc.model.add_component(module, resource,
385
joinby=dict(org_organisation="organisation_id", gis_location="location_id"),
389
s3xrc.model.configure(table,
401
# -----------------------------------------------------------------------------
403
# Many-to-Many Persons to Offices & Projects with also the Title & Manager that the person has in this context
404
# ToDo: Build an Organigram out of this data?
407
tablename = module + "_" + resource
408
table = db.define_table(tablename, timestamp, deletion_status,
414
Field("manager_id", db.pr_person),
415
Field("focal_point", "boolean"),
416
#Field("slots", "integer", default=1),
417
#Field("payrate", "double", default=0.0), # Wait for Bugeting integration
422
# Over-ride the default IS_NULL_OR as Staff doesn't make sense without an associated Organisation
423
table.organisation_id.requires = IS_ONE_OF(db, "org_organisation.id", "%(name)s")
424
table.manager_id.requires = IS_NULL_OR(IS_ONE_OF(db, "pr_person.id", shn_pr_person_represent))
425
table.manager_id.represent = lambda id: (id and [shn_pr_person_represent(id)] or ["None"])[0]
427
# Staff Resource called from multiple controllers
428
# - so we define strings in the model
429
table.person_id.label = T("Person")
430
#table.person_id.comment = DIV(SPAN("*", _class="req"), shn_person_comment)
431
table.organisation_id.comment = DIV(SPAN("*", _class="req"), shn_organisation_comment)
432
table.title.label = T("Job Title")
433
table.title.comment = DIV( _class="tooltip", _title=Tstr("Title") + "|" + Tstr("The Role this person plays within this Office/Project."))
434
table.manager_id.label = T("Manager")
435
table.manager_id.comment = DIV( _class="tooltip", _title=Tstr("Manager") + "|" + Tstr("The person's manager within this Office/Project."))
436
table.focal_point.comment = DIV( _class="tooltip", _title=Tstr("Focal Point") + "|" + Tstr("The contact person for this organization."))
438
ADD_STAFF = T("Add Staff")
439
LIST_STAFF = T("List Staff")
440
s3.crud_strings[tablename] = Storage(
441
title_create = ADD_STAFF,
442
title_display = T("Staff Details"),
443
title_list = LIST_STAFF,
444
title_update = T("Edit Staff"),
445
title_search = T("Search Staff"),
446
subtitle_create = T("Add New Staff"),
447
subtitle_list = T("Staff"),
448
label_list_button = LIST_STAFF,
449
label_create_button = ADD_STAFF,
450
msg_record_created = T("Staff added"),
451
msg_record_modified = T("Staff updated"),
452
msg_record_deleted = T("Staff deleted"),
453
msg_list_empty = T("No Staff currently registered"))
456
def represent_focal_point(is_focal_point):
462
def shn_org_staff_represent(staff_id):
463
person = db((db.org_staff.id == staff_id) &
464
(db.pr_person.id == db.org_staff.person_id)).select(db.pr_person.ALL)
466
return vita.fullname(person[0])
470
table.focal_point.represent = lambda focal_point: represent_focal_point(focal_point)
472
def shn_orgs_to_person(person_id):
475
staff = db((db.org_staff.person_id == person_id) &
476
(db.org_staff.deleted == False)).select(db.org_staff.organisation_id)
479
orgs.append(s.organisation_id)
482
# Staff as component of Orgs, Offices & Projects
483
s3xrc.model.add_component(module, resource,
485
joinby=dict(org_organisation="organisation_id", org_office="office_id", org_project="project_id"),
489
# May wish to over-ride this in controllers
490
s3xrc.model.configure(table,
504
# org_position (component of org_project)
505
# describes a position in a project
507
# Deprecated - replaced by staff
509
#org_position_type_opts = {
510
# 1: T("Site Manager"),
511
# 2: T("Team Leader"),
515
#resource = "position"
516
#tablename = module + "_" + resource
517
#table = db.define_table(tablename, timestamp, uuidstamp, deletion_status,
519
# Field("type", "integer",
520
# requires = IS_IN_SET(org_position_type_opts, zero=None),
522
# label = T("Position type"),
523
# represent = lambda opt: org_position_type_opts.get(opt, UNKNOWN_OPT)),
524
# Field("title", length=30),
525
# Field("description", "text"),
526
# Field("slots", "integer", default=1),
527
# Field("payrate", "double", default=0.0),
532
#ADD_POSITION = Tstr("Add Position")
533
#POSITIONS = T("Positions")
534
#s3.crud_strings[tablename] = Storage(
535
# title_create = ADD_POSITION,
536
# title_display = T("Position Details"),
537
# title_list = POSITIONS,
538
# title_update = T("Edit Position"),
539
# title_search = T("Search Positions"),
540
# subtitle_create = T("Add New Position"),
541
# subtitle_list = POSITIONS,
542
# label_list_button = T("List Positions"),
543
# label_create_button = ADD_POSITION,
544
# msg_record_created = T("Position added"),
545
# msg_record_modified = T("Position updated"),
546
# msg_record_deleted = T("Position deleted"),
547
# msg_list_empty = T("No positions currently registered"))
550
#org_position_id = db.Table(None, "org_position_id",
551
# FieldS3("org_position_id", db.org_position, sortby="title",
552
# requires = IS_NULL_OR(IS_ONE_OF(db, "org_position.id", "%(title)s")),
553
# represent = lambda id: lambda id: (id and [db.org_position[id].title] or ["None"])[0],
554
# comment = DIV(A(ADD_POSITION, _class="colorbox", _href=URL(r=request, c="org", f="project", args="create", vars=dict(format="popup")), _target="top", _title=ADD_POSITION),
555
# DIV( _class="tooltip", _title=ADD_POSITION + "|" + Tstr("Add new position."))),
556
# ondelete = "RESTRICT"
559
# -----------------------------------------------------------------------------
561
# a task within a project
563
org_task_status_opts = {
573
org_task_priority_opts = {
582
tablename = module + "_" + resource
583
table = db.define_table(tablename, timestamp, uuidstamp, deletion_status,
586
Field("priority", "integer",
587
requires = IS_IN_SET(org_task_priority_opts, zero=None),
589
label = T("Priority"),
590
represent = lambda opt: org_task_priority_opts.get(opt, UNKNOWN_OPT)),
591
Field("subject", length=80),
592
Field("description", "text"),
594
Field("status", "integer",
595
requires = IS_IN_SET(org_task_status_opts, zero=None),
598
represent = lambda opt: org_task_status_opts.get(opt, UNKNOWN_OPT)),
601
# Task Resource called from multiple controllers
602
# - so we define strings in the model
603
table.person_id.label = T("Assigned to")
605
ADD_TASK = T("Add Task")
606
LIST_TASKS = T("List Tasks")
607
s3.crud_strings[tablename] = Storage(
608
title_create = ADD_TASK,
609
title_display = T("Task Details"),
610
title_list = LIST_TASKS,
611
title_update = T("Edit Task"),
612
title_search = T("Search Tasks"),
613
subtitle_create = T("Add New Task"),
614
subtitle_list = T("Tasks"),
615
label_list_button = LIST_TASKS,
616
label_create_button = ADD_TASK,
617
msg_record_created = T("Task added"),
618
msg_record_modified = T("Task updated"),
619
msg_record_deleted = T("Task deleted"),
620
msg_list_empty = T("No tasks currently registered"))
622
# Task as Component of Project, Office, (Organisation to come? via Project? Can't rely on that as multi-Org projects)
623
s3xrc.model.add_component(module, resource,
625
joinby=dict(org_project="project_id", org_office="office_id"),
628
main="subject", extra="description")
630
s3xrc.model.configure(table,
639
# -----------------------------------------------------------------------------
640
# shn_project_search_location:
641
# form function to search projects by location
643
def shn_project_search_location(xrequest, **attr):
648
if not shn_has_permission("read", db.org_project):
649
session.error = UNAUTHORISED
650
redirect(URL(r=request, c="default", f="user", args="login", vars={"_next":URL(r=request, args="search_location", vars=request.vars)}))
652
if xrequest.representation == "html":
653
# Check for redirection
654
if request.vars._next:
655
next = str.lower(request.vars._next)
657
next = str.lower(URL(r=request, c="org", f="project", args="[id]"))
660
response.view = "%s/project_search.html" % xrequest.prefix
663
title = T("Search for a Project")
664
subtitle = T("Matching Records")
667
l_opts = [OPTION(_value="")]
668
l_opts += [OPTION(location.name, _value=location.id)
669
for location in db(db.gis_location.deleted == False).select(db.gis_location.ALL, cache=(cache.ram, 3600))]
672
SELECT(_name="location", *l_opts, **dict(name="location", requires=IS_NULL_OR(IS_IN_DB(db, "gis_location.id"))))),
673
TR("", INPUT(_type="submit", _value="Search"))
676
output = dict(title=title, subtitle=subtitle, form=form, vars=form.vars)
680
if form.accepts(request.vars, session):
682
table = db.org_project
683
query = (table.deleted == False)
685
if form.vars.location is None:
686
results = db(query).select(table.ALL)
688
query = query & (table.location_id == form.vars.location)
689
results = db(query).select(table.ALL)
691
if results and len(results):
693
for result in results:
694
href = next.replace("%5bid%5d", "%s" % result.id)
696
A(result.name, _href=href),
697
result.start_date or "None",
698
result.end_date or "None",
699
result.description or "None",
700
result.status and org_project_status_opts[result.status] or "unknown",
702
items=DIV(TABLE(THEAD(TR(
712
TH("Budgeted Cost"))),
713
TBODY(records), _id="list", _class="display"))
718
label_create_button = s3.crud_strings["org_project"].label_create_button
720
label_create_button = s3.crud_strings.label_create_button
722
add_btn = A(label_create_button, _href=URL(r=request, f="project", args="create"), _class="action-btn")
724
output.update(dict(items=items, add_btn=add_btn))
729
session.error = BADFORMAT
730
redirect(URL(r=request))
732
# Plug into REST controller
733
s3xrc.model.set_method(module, "project", method="search_location", action=shn_project_search_location )
735
# -----------------------------------------------------------------------------
736
def shn_project_rheader(jr, tabs=[]):
738
if jr.representation == "html":
740
rheader_tabs = shn_rheader_tabs(jr, tabs)
742
if jr.name == "project":
750
if project.sector_id:
751
_sectors = re.split("\|", project.sector_id)[1:-1]
752
for sector in _sectors:
753
sectors.append(TR(db(db.org_sector.id == sector).select(db.org_sector.name, limitby=(0, 1)).first().name))
760
TH(A(T("Clear Selection"),
761
_href=URL(r=request, f="project", args="clear", vars={"_next": _same})))
767
location_id.location_id.represent(project.location_id),
771
"%s" % org_project_status_opts[project.status],
772
TH(T("Sector(s): ")),
774
#TH(A(T("Edit Project"),
775
# _href=URL(r=request, f="project", args=[jr.id, "update"], vars={"_next": _next})))
782
# -----------------------------------------------------------------------------