diff --git a/controllers/default.py b/controllers/default.py index 66906edfe5..95fefb951d 100755 --- a/controllers/default.py +++ b/controllers/default.py @@ -64,7 +64,7 @@ def register_validation(form): # ============================================================================= def index(): """ Main Home Page """ - + auth.settings.register_onvalidation = register_validation auth.configure_user_fields() diff --git a/controllers/inv.py b/controllers/inv.py index 3721db8d8d..e43c2ca823 100644 --- a/controllers/inv.py +++ b/controllers/inv.py @@ -1378,7 +1378,7 @@ def track_item(): #"send_id", #"req_item_id", (T("Date Released"), "send_id$date"), - (T("Beneficiary"), "send_id$site_id"), + (T("Beneficiary"), "send_id$to_site_id"), (settings.get_inv_send_shortname(), "send_id$send_ref"), (settings.get_req_shortname(), "send_id$req_ref"), (T("Items/Description"), "item_id"), @@ -1460,6 +1460,33 @@ def track_item(): ] ) s3.filter = (FS("expiry_date") != None) + elif report == "dist": + # Summary of Releases + s3.crud_strings["inv_track_item"] = Storage(title_list = T("Distribution Report")) + + level_fields = ["send_id$to_site_id$location_id$%s" % level for + level in current.gis.get_relevant_hierarchy_levels()] + + s3db.configure("inv_track_item", + list_fields = ["id", + #"send_id", + #"req_item_id", + (T("Date Sent"), "send_id$date"), + (s3db.inv_send.to_site_id.label, "send_id$to_site_id")] + + level_fields + + [(settings.get_inv_send_shortname(), "send_id$send_ref"), + (settings.get_req_shortname(), "send_id$req_ref"), + (T("Items"), "item_id"), + (T("Source"), "supply_org_id"), + (T("Unit"), "item_pack_id"), + (T("Quantity"), "quantity"), + (T("Unit Cost"), "pack_value"), + (T("Total Cost"), "total_value"), + ], + orderby = "inv_send.date dsc", + sort = True + ) + s3.filter = (FS("send_id$type") == 21) output = s3_rest_controller(rheader = s3db.inv_rheader) return output diff --git a/modules/s3/s3codecs/xls.py b/modules/s3/s3codecs/xls.py index e6b836b9a5..3b33dfb314 100644 --- a/modules/s3/s3codecs/xls.py +++ b/modules/s3/s3codecs/xls.py @@ -171,6 +171,9 @@ def encode(self, data_source, **attr): list_fields = attr.get("list_fields") if not list_fields: list_fields = data_source.list_fields() + # Always export comments field + if "comments" in data_source.fields and "comments" not in list_fields: + list_fields.append("comments") group = attr.get("dt_group") use_colour = attr.get("use_colour", False) diff --git a/modules/s3/s3gis.py b/modules/s3/s3gis.py index 8e4ab20bca..def036cd98 100644 --- a/modules/s3/s3gis.py +++ b/modules/s3/s3gis.py @@ -1527,6 +1527,7 @@ def get_location_hierarchy(self, level=None, location=None): db = current.db s3db = current.s3db table = s3db.gis_hierarchy + ltable = s3db.gis_location fields = (table.uuid, table.L1, @@ -1536,7 +1537,15 @@ def get_location_hierarchy(self, level=None, location=None): table.L5, ) - query = (table.uuid == "SITE_DEFAULT") + countries = current.deployment_settings.get_gis_countries() + if len(countries) == 1: + #If the site is only configed for one country, use the hierarchy for that country + query = (table.location_id == ltable.id) & \ + (ltable.level == "L0") & \ + (ltable.name == self.get_country(countries[0],key_type="code")) + else: + query = (table.uuid == "SITE_DEFAULT") + if not location: config = GIS.get_config() location = config.region_location_id diff --git a/modules/s3/s3query.py b/modules/s3/s3query.py index b2cdc7fd9f..333529f1be 100644 --- a/modules/s3/s3query.py +++ b/modules/s3/s3query.py @@ -676,7 +676,7 @@ def __init__(self, resource, selector, label=None): # Fall back to the field label if label is None: fname = self.fname - if fname in ["L1", "L2", "L3", "L3", "L4", "L5"]: + if fname in ("L1", "L2", "L3", "L3", "L4", "L5"): try: label = current.gis.get_location_hierarchy(fname) except: diff --git a/modules/s3/s3widgets.py b/modules/s3/s3widgets.py index 18d2f873b6..b03886e1e8 100644 --- a/modules/s3/s3widgets.py +++ b/modules/s3/s3widgets.py @@ -7911,75 +7911,74 @@ class ICON(I): "zoomin": "icon-zoomin", "zoomout": "icon-zoomout", }, - # @todo: integrate - #"font-awesome4": { - #"_base": "fa", - #"active": "fa-check", - #"activity": "fa-tag", - #"add": "fa-plus", - #"arrow-down": "fa-arrow-down", - #"attachment": "fa-paper-clip", - #"bar-chart": "fa-bar-chart", - #"book": "fa-book", - #"bookmark": "fa-bookmark", - #"bookmark-empty": "fa-bookmark-empty", - #"briefcase": "fa-briefcase", - #"calendar": "fa-calendar", - #"certificate": "fa-certificate", - #"comment-alt": "fa-comment-o", - #"commit": "fa-truck", - #"delete": "fa-trash", - #"deploy": "fa-plus", - #"deployed": "fa-check", - #"down": "fa-caret-down", - #"edit": "fa-edit", - #"exclamation": "fa-exclamation", - #"facebook": "fa-facebook", - #"facility": "fa-home", - #"file": "fa-file", - #"file-alt": "fa-file-alt", - #"folder-open-alt": "fa-folder-open-o", - #"fullscreen": "fa-fullscreen", - #"globe": "fa-globe", - #"group": "fa-group", - #"home": "fa-home", - #"inactive": "fa-check-empty", - #"link": "fa-external-link", - #"list": "fa-list", - #"location": "fa-globe", - #"mail": "fa-envelope-o", - #"map-marker": "fa-map-marker", - #"offer": "fa-truck", - #"organisation": "fa-institution", - #"org-network": "fa-umbrella", - #"other": "fa-circle", - #"paper-clip": "fa-paper-clip", - #"phone": "fa-phone", - #"plus": "fa-plus", - #"plus-sign": "fa-plus-sign", - #"radio": "fa-microphone", - #"remove": "fa-remove", - #"request": "fa-flag", - #"responsibility": "fa-briefcase", - #"rss": "fa-rss", - #"sent": "fa-check", - #"site": "fa-home", - #"skype": "fa-skype", - #"star": "fa-star", - #"table": "fa-table", - #"tag": "fa-tag", - #"tags": "fa-tags", - #"tasks": "fa-tasks", - #"time": "fa-time", - #"truck": "fa-truck", - #"twitter": "fa-twitter", - #"unsent": "fa-times", - #"up": "fa-caret-up", - #"upload": "fa-upload", - #"user": "fa-user", - #"zoomin": "fa-zoomin", - #"zoomout": "fa-zoomout", - #}, + "font-awesome4": { + "_base": "fa", + "active": "fa-check", + "activity": "fa-tag", + "add": "fa-plus", + "arrow-down": "fa-arrow-down", + "attachment": "fa-paper-clip", + "bar-chart": "fa-bar-chart", + "book": "fa-book", + "bookmark": "fa-bookmark", + "bookmark-empty": "fa-bookmark-empty", + "briefcase": "fa-briefcase", + "calendar": "fa-calendar", + "certificate": "fa-certificate", + "comment-alt": "fa-comment-o", + "commit": "fa-truck", + "delete": "fa-trash", + "deploy": "fa-plus", + "deployed": "fa-check", + "down": "fa-caret-down", + "edit": "fa-edit", + "exclamation": "fa-exclamation", + "facebook": "fa-facebook", + "facility": "fa-home", + "file": "fa-file", + "file-alt": "fa-file-alt", + "folder-open-alt": "fa-folder-open-o", + "fullscreen": "fa-fullscreen", + "globe": "fa-globe", + "group": "fa-group", + "home": "fa-home", + "inactive": "fa-check-empty", + "link": "fa-external-link", + "list": "fa-list", + "location": "fa-globe", + "mail": "fa-envelope-o", + "map-marker": "fa-map-marker", + "offer": "fa-truck", + "organisation": "fa-sitemap", + "org-network": "fa-umbrella", + "other": "fa-circle", + "paper-clip": "fa-paper-clip", + "phone": "fa-phone", + "plus": "fa-plus", + "plus-sign": "fa-plus-sign", + "radio": "fa-microphone", + "remove": "fa-remove", + "request": "fa-flag", + "responsibility": "fa-briefcase", + "rss": "fa-rss", + "sent": "fa-check", + "site": "fa-home", + "skype": "fa-skype", + "star": "fa-star", + "table": "fa-table", + "tag": "fa-tag", + "tags": "fa-tags", + "tasks": "fa-tasks", + "time": "fa-time", + "truck": "fa-truck", + "twitter": "fa-twitter", + "unsent": "fa-times", + "up": "fa-caret-up", + "upload": "fa-upload", + "warehouse":"fa-th", + "zoomin": "fa-zoomin", + "zoomout": "fa-zoomout", + }, "foundation": { "active": "fi-check", "activity": "fi-price-tag", diff --git a/modules/s3cfg.py b/modules/s3cfg.py index f888dbfa95..906412d765 100644 --- a/modules/s3cfg.py +++ b/modules/s3cfg.py @@ -3511,6 +3511,11 @@ def get_req_restrict_on_complete(self): # ------------------------------------------------------------------------- # Supply # + def get_supply_autocomplete(self): + """ + Whether supply fields should use an Autocomplete instead of a dropdown + """ + return self.supply.get("autocomplete", False) def get_supply_catalog_default(self): return self.inv.get("catalog_default", "Default") diff --git a/modules/s3db/hrm.py b/modules/s3db/hrm.py index 1de73d62e4..d27e500e26 100644 --- a/modules/s3db/hrm.py +++ b/modules/s3db/hrm.py @@ -5165,7 +5165,7 @@ def hrm_human_resource_onaccept(form): ltable.insert(human_resource_id=id, job_title_id=job_title_id, main=True, - start_date=request.utcnow, + date=request.utcnow, ) data = Storage() diff --git a/modules/s3db/inv.py b/modules/s3db/inv.py index 11aa3b55ed..f16fe06128 100644 --- a/modules/s3db/inv.py +++ b/modules/s3db/inv.py @@ -1050,6 +1050,8 @@ def model(self): #send_type_opts.update(self.inv_item_status_opts) send_type_opts.update(settings.get_inv_send_types()) + ADD_FACILITY = T("Create Facility") + site_types = auth.org_site_types tablename = "inv_send" define_table(tablename, @@ -1094,6 +1096,10 @@ def model(self): not_filterby = "obsolete", not_filter_opts = (True,), )), + comment = S3AddResourceLink(c="org", + f="facility", + label=ADD_FACILITY, + title=ADD_FACILITY) ), organisation_id( label = T("To Organization"), @@ -1183,6 +1189,8 @@ def model(self): s3_comments(), *s3_meta_fields()) + levels = current.gis.get_relevant_hierarchy_levels() + # Filter Widgets filter_widgets = [ S3TextFilter(["sender_id$first_name", @@ -1194,7 +1202,7 @@ def model(self): "recipient_id$first_name", "recipient_id$middle_name", "recipient_id$last_name", - ], + ] + ["to_site_id$location_id$%s" % level for level in levels], label = T("Search"), comment = T("Search for an item by text."), ), @@ -1204,6 +1212,9 @@ def model(self): cols = 2, hidden = True, ), + S3LocationFilter("to_site_id$location_id", + levels=levels, + ), S3TextFilter("type", label = T("Shipment Type"), hidden = True, @@ -1875,6 +1886,12 @@ def model(self): label = T("Search"), #comment = recv_search_comment, ), + S3OptionsFilter("send_id$site_id"), + S3LocationFilter("send_id$to_site_id$location_id", + #hidden=True, + label=T("Sent to Location"), + levels=levels, + ), S3DateFilter("send_id$date", label = T("Sent date"), hidden = True, @@ -2142,7 +2159,8 @@ def inv_send_controller(cls): s3 = response.s3 # Limit site_id to sites the user has permissions for - error_msg = T("You do not have permission for any facility to send a shipment.") + error_msg = T("You do not have permission for any %s to send a shipment.") % \ + current.deployment_settings.get_inv_facility_label() current.auth.permitted_facilities(table=sendtable, error_msg=error_msg) # Set Validator for checking against the number of items in the warehouse @@ -2534,7 +2552,7 @@ def inv_send_process(): site_id = send_record.to_site_id, comments = send_record.comments, status = SHIP_STATUS_SENT, - type = 1, # 1:"Another Inventory" + type = 11, # 11:"Another Inventory" ) # Change the status for all track items in this shipment to In transit diff --git a/modules/s3db/org.py b/modules/s3db/org.py index 0797f20c45..c8b14f5480 100644 --- a/modules/s3db/org.py +++ b/modules/s3db/org.py @@ -322,7 +322,7 @@ def model(self): label = T("Name"), ), # http://hxl.humanitarianresponse.info/#abbreviation - Field("acronym", length=16, + Field("acronym", length=20, label = T("Acronym"), represent = lambda val: val or "", comment = DIV(_class="tooltip", @@ -1898,11 +1898,11 @@ def model(self): crud_strings[tablename] = Storage( label_create = T("Create Resource"), title_display = T("Resource Details"), - title_list = T("Resource Inventory"), + title_list = T("Resources"), title_update = T("Edit Resource"), title_map = T("Map of Resources"), title_upload = T("Import Resources"), - label_list_button = T("Resource Inventory"), + label_list_button = T("Resources"), label_delete_button = T("Delete Resource"), msg_record_created = T("Resource added"), msg_record_modified = T("Resource updated"), diff --git a/modules/s3db/supply.py b/modules/s3db/supply.py index 8c4f6faebd..9a1bd5b403 100644 --- a/modules/s3db/supply.py +++ b/modules/s3db/supply.py @@ -425,6 +425,10 @@ def model(self): supply_item_represent = supply_ItemRepresent(show_link=True) # Reusable Field + if settings.get_supply_autocomplete(): + default_widget = S3AutocompleteWidget("supply", "item") + else: + default_widget = None supply_item_id = S3ReusableField("item_id", "reference %s" % tablename, # 'item_id' for backwards-compatibility label = T("Item"), @@ -434,7 +438,7 @@ def model(self): supply_item_represent, sort=True), sortby = "name", - widget = S3AutocompleteWidget("supply", "item"), + widget = default_widget, comment=S3AddResourceLink(c="supply", f="item", label=ADD_ITEM, diff --git a/modules/s3db/vol.py b/modules/s3db/vol.py index 27d9cbec42..80141a20c1 100644 --- a/modules/s3db/vol.py +++ b/modules/s3db/vol.py @@ -742,6 +742,8 @@ def prep(r): list_fields.append((T("Trainings"),"person_id$training.course_id")) if settings.get_hrm_use_certificates(): list_fields.append((T("Certificates"),"person_id$certification.certificate_id")) + if r.representation == "xls": + list_fields.append("person_id$comments") # Volunteer Programme and Active-status report_options = get_config("report_options") @@ -1148,7 +1150,7 @@ def prep(r): resource = r.resource if mode is not None: - r.resource.build_query(id=s3_logged_in_person()) + r.resource.build_query(id=current.auth.s3_logged_in_person()) elif r.method not in ("deduplicate", "search_ac"): if not r.id and not hr_id: # pre-action redirect => must retain prior errors diff --git a/modules/s3layouts.py b/modules/s3layouts.py index 38167fb216..2f5c6870b3 100644 --- a/modules/s3layouts.py +++ b/modules/s3layouts.py @@ -254,8 +254,7 @@ def layout(item): _class = "active" section = [LI(A(item.label, - **attr - ), + **attr), _class="heading %s" % _class, ), ] @@ -273,8 +272,7 @@ def layout(item): _class = "" return LI(A(item.label, - **attr - ), + **attr), _class=_class, ) else: diff --git a/modules/s3menus.py b/modules/s3menus.py index 00e773a066..b19830275a 100644 --- a/modules/s3menus.py +++ b/modules/s3menus.py @@ -1196,6 +1196,8 @@ def inv(): vars=dict(report="inc")), M("Summary of Releases", c="inv", f="track_item", vars=dict(report="rel")), + M("Distribution Report", c="inv", f="track_item", + vars=dict(report="dist")), ), M(inv_recv_list, c="inv", f="recv", translate=False)( # Already T() M("Create", m="create"), @@ -1468,11 +1470,7 @@ def org(): M("Create", m="create"), M("Import", m="import"), ), - M("Resource Inventory", f="resource")( - M("Create", m="create"), - M("Import", m="import") - ), - M("Resources", f="resource", m="summary")( + M("Resources", f="resource")( M("Create", m="create"), M("Import", m="import") ), diff --git a/modules/templates/IFRC/config.py b/modules/templates/IFRC/config.py index 0bfd5017df..b05228970b 100644 --- a/modules/templates/IFRC/config.py +++ b/modules/templates/IFRC/config.py @@ -483,78 +483,8 @@ def currency_default(default): settings.hrm.activity_types = {"rdrt": "RDRT Mission"} # ----------------------------------------------------------------------------- - # Projects - # Uncomment this to use settings suitable for a global/regional organisation (e.g. DRR) - settings.project.mode_3w = True - # Uncomment this to use DRR (Disaster Risk Reduction) extensions - settings.project.mode_drr = True - # Uncomment this to use Activity Types for Activities & Projects - settings.project.activity_types = True - # Uncomment this to use Codes for projects - settings.project.codes = True - # Uncomment this to call project locations 'Communities' - settings.project.community = True - # Uncomment this to enable Hazards in 3W projects - settings.project.hazards = True - # Uncomment this to use multiple Budgets per project - settings.project.multiple_budgets = True - # Uncomment this to use multiple Organisations per project - settings.project.multiple_organisations = True - # Uncomment this to enable Programmes in projects - settings.project.programmes = True - # Uncomment this to enable Themes in 3W projects - settings.project.themes = True - # Uncomment this to customise - # Links to Filtered Components for Donors & Partners - settings.project.organisation_roles = { - 1: T("Host National Society"), - 2: T("Partner"), - 3: T("Donor"), - #4: T("Customer"), # T("Beneficiary")? - #5: T("Supplier"), - 9: T("Partner National Society"), - } - - # ----------------------------------------------------------------------------- - # Inventory Management - settings.inv.show_mode_of_transport = True - settings.inv.send_show_time_in = True - #settings.inv.collapse_tabs = True - # Uncomment if you need a simpler (but less accountable) process for managing stock levels - settings.inv.direct_stock_edits = True - settings.inv.org_dependent_warehouse_types = True - # Settings for HNRC: - #settings.inv.stock_count = False - #settings.inv.item_status = {#0: current.messages["NONE"], # Not defined yet - # 0: T("Good"), - # 1: T("Damaged"), - # #1: T("Dump"), - # #2: T("Sale"), - # #3: T("Reject"), - # #4: T("Surplus") - # } - #settings.inv.recv_types = {#0: current.messages["NONE"], In Shipment Types - # #11: T("Internal Shipment"), In Shipment Types - # 32: T("Donation"), - # 34: T("Purchase"), - # 36: T("Consignment"), # Borrowed - # 37: T("In Transit"), # Loaning warehouse space to another agency - # } - - # ----------------------------------------------------------------------------- - # Request Management - # Uncomment to disable Inline Forms in Requests module - settings.req.inline_forms = False - settings.req.req_type = ["Stock"] - settings.req.use_commit = False - # Should Requests ask whether Transportation is required? - settings.req.ask_transport = True - settings.req.pack_values = False - # Disable Request Matching as we don't want users making requests to see what stock is available - #settings.req.prompt_match = False # HNRC - # Uncomment to disable Recurring Request - #settings.req.recurring = False # HNRC - + # Supply / Inventory / Warehouse + settings.supply.autocomplete = True # ============================================================================= # Template Modules # Comment/uncomment modules here to disable/enable them diff --git a/modules/templates/Nepal/config.py b/modules/templates/Nepal/config.py index d5754b9175..795e3862dc 100644 --- a/modules/templates/Nepal/config.py +++ b/modules/templates/Nepal/config.py @@ -8,7 +8,10 @@ from gluon.contrib.simplejson.ordered_dict import OrderedDict from gluon import current +from gluon.html import * from gluon.storage import Storage +from s3 import S3CustomController +from layouts import IndexMenuLayOut def config(settings): """ @@ -23,7 +26,7 @@ def config(settings): T = current.T settings.base.system_name = T("Nepal Sahana Disaster Management Platform") - #settings.base.system_name_short = T("Sahana") + settings.base.system_name_short = T("Sahana") # PrePopulate data settings.base.prepopulate = ("Nepal", "default/users") @@ -39,6 +42,7 @@ def config(settings): # Do new users need to be approved by an administrator prior to being able to login? #settings.auth.registration_requires_approval = True settings.auth.registration_requests_organisation = True + settings.auth.registration_requests_site = True # Approval emails get sent to all admins settings.mail.approver = "ADMIN" @@ -101,13 +105,20 @@ def config(settings): #settings.L10n.translate_gis_location = True # Uncomment this to Translate Organisation Names/Acronyms #settings.L10n.translate_org_organisation = True + # Finance settings - #settings.fin.currencies = { - # "EUR" : T("Euros"), - # "GBP" : T("Great British Pounds"), - # "USD" : T("United States Dollars"), - #} - #settings.fin.currency_default = "USD" + settings.fin.currencies = { + "NPR" : T("Nepalese Rupee"), + "AUD" : T("Australian Dollar"), + "EUR" : T("Euro"), + "GBP" : T("British Pound"), + "INR" : T("Indian Rupee"), + "KRW" : T("South-Korean Won"), + "JPY" : T("Japanese Yen"), + "NZD" : T("New Zealand Dollar"), + "USD" : T("United States Dollars"), + } + settings.fin.currency_default = "NPR" # Security Policy # http://eden.sahanafoundation.org/wiki/S3AAA#System-widePolicy @@ -122,12 +133,120 @@ def config(settings): # settings.security.policy = 6 # Organisation-ACLs + # User Interface + settings.ui.icons = "font-awesome4" + settings.ui.custom_icons = { + "ambulance": "fa fa-ambulance", + "create":"fa fa-plus", + "hospital":"fa fa-hospital-o", + "receive": "fa fa-sign-in", + "recv_shipments": "fa fa-indent", + "resource": "fa fa-cube", + "send": "fa fa-sign-out", + "sent_shipments": "fa fa-outdent", + "shelter": "fa fa-home", + "site-current": "fa fa-square", + "sites-all": "fa fa-th", + "stock": "fa fa-cubes", + "user": "fa fa-user", + "volunteer": "fa fa-user", + "volunteers": "fa fa-users", + } # ------------------------------------------------------------------------- + # Module Settings + settings.org.sector = True + settings.ui.cluster = True + # Simple Requests settings.req.req_type = ("Other",) # Uncomment to disable the Commit step in the workflow & simply move direct to Ship settings.req.use_commit = False + # Doesn't appear to work... Need inline field and/or component tab? + settings.hrm.multi_job_titles = True + + # ========================================================================= + def customise_inv_index(): + """ Custom Inventory Index Page""" + response = current.response + response.title = T("Sahana : Warehouse Management") + s3 = response.s3 + s3db = current.s3db + s3.stylesheets.append("../themes/Nepal/index.css") + s3.stylesheets.append("../styles/font-awesome.css") + S3CustomController._view("Nepal","inv_index.html") + + response.title + + site_id = current.auth.user.site_id + if site_id: + current_site = DIV(XML(T("You are currently managing stock for: %(site)s") % \ + {"site":s3db.org_site_represent(site_id, + show_link = True)}), + _title = T("Contact Administrator to change your default facility."), + ) + else: + current_site = "" + is_current_site = lambda i: site_id + + IM = IndexMenuLayOut + index_menu = IM()(IM("Receive", c="inv", f="recv", args="create", + vars={"recv.status":2}, + icon="receive", + description=T("Receive a New shipment or an Existing shipment at your site."), + )(IM("Existing", args="summary", icon="list",vars={"recv.status":2}), + IM("New",args="create",icon="create")), + IM("Send", c="inv", f="send", + description=T("Send a shipment from your site."), + )(IM("Create",args="create",icon="create")), + IM("Stock", c="inv", f="inv_item", + icon="stock", + description=T("List of stock at sites."), + )(IM("Your Site",icon="your-site", check = is_current_site), + IM("All Sites",icon="all-sites")), + IM("Recvd. Shipments", c="inv", f="recv", args="summary", + vars={"recv.status__ne":2}, + icon="recv_shipments", + description=T("List of received shipments."), + )(IM("Your Site",icon="your-site", check = is_current_site), + IM("All Sites",icon="all-sites")), + IM("Sent Shipments", c="inv", f="sent", args="summary", + icon="sent_shipments", + description=T("List of sent shipments."), + )(IM("Your Site",icon="your-site", check = is_current_site), + IM("All Sites",icon="all-sites")), + IM("Warehouse", c="inv", f="warehouse", args="summary", + icon="warehouse", + description=T("List of Warehouses."), + )(IM("View",args="summary",icon="list"), + IM("Create",args="create",icon="create")) + ) + + return dict(current_site = current_site, + index_menu = index_menu) + settings.customise_inv_home = customise_inv_index + # ------------------------------------------------------------------------- + def customise_inv_recv_controller(**attr): + s3 = current.response.s3 + # Custom PreP + standard_prep = s3.prep + def custom_prep(r): + # Call standard prep + if callable(standard_prep): + result = standard_prep(r) + if not result: + return False + + # Customise titles + if r.vars.get("recv.status") == "2": + s3.crud_strings.inv_recv.title_list = T("Existing Shipments to Received") + if r.vars.get("recv.status__ne") == "2": + s3.crud_strings.inv_recv.title_list = T("Received Shipments") + return True + s3.prep = custom_prep + return attr + settings.customise_inv_recv_controller = customise_inv_recv_controller + # ------------------------------------------------------------------------- # Comment/uncomment modules here to disable/enable them # Modules menu is defined in modules/eden/menu.py @@ -185,7 +304,7 @@ def config(settings): #description = "Central point to record details on People", restricted = True, access = "|1|", # Only Administrators can see this module in the default menu (access to controller is possible to all still) - module_type = 10 + module_type = None )), ("org", Storage( name_nice = T("Organizations"), @@ -197,7 +316,7 @@ def config(settings): name_nice = T("Staff"), #description = "Human Resources Management", restricted = True, - module_type = 2, + module_type = 10, )), ("vol", Storage( name_nice = T("Volunteers"), @@ -209,7 +328,7 @@ def config(settings): name_nice = T("Content Management"), #description = "Content Management System", restricted = True, - module_type = 10, + module_type = None, )), #("doc", Storage( # name_nice = T("Documents"), @@ -231,12 +350,12 @@ def config(settings): restricted = True, module_type = None, # Not displayed )), - #("inv", Storage( - # name_nice = T("Warehouses"), - # #description = "Receiving and Sending Items", - # restricted = True, - # module_type = 4 - #)), + ("inv", Storage( + name_nice = T("Warehouses"), + #description = "Receiving and Sending Items", + restricted = True, + module_type = 4 + )), #("asset", Storage( # name_nice = T("Assets"), # #description = "Recording and Assigning Assets", @@ -256,12 +375,12 @@ def config(settings): restricted = True, module_type = 10, )), - #("project", Storage( - # name_nice = T("Projects"), - # #description = "Tracking of Projects, Activities and Tasks", - # restricted = True, - # module_type = 2 - #)), + ("project", Storage( + name_nice = T("Projects"), + #description = "Tracking of Projects, Activities and Tasks", + restricted = True, + module_type = 10 + )), ("cr", Storage( name_nice = T("Shelters"), #description = "Tracks the location, capacity and breakdown of victims in Shelters", @@ -272,10 +391,10 @@ def config(settings): name_nice = T("Hospitals"), #description = "Helps to monitor status of hospitals", restricted = True, - module_type = 10 + module_type = 3 )), ("patient", Storage( - name_nice = T("Patient Tracking"), + name_nice = T("Patients"), #description = "Tracking of Patients", restricted = True, module_type = 10 @@ -286,12 +405,12 @@ def config(settings): # restricted = True, # module_type = 10, #)), - #("event", Storage( - # name_nice = T("Events"), - # #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).", - # restricted = True, - # module_type = 10, - #)), + ("event", Storage( + name_nice = T("Events"), + #description = "Activate Events (e.g. from Scenario templates) for allocation of appropriate Resources (Human, Assets & Facilities).", + restricted = True, + module_type = 10, + )), #("transport", Storage( # name_nice = T("Transport"), # restricted = True, diff --git a/modules/templates/Nepal/controllers.py b/modules/templates/Nepal/controllers.py index c7f83c6a9e..f5968bdbc7 100644 --- a/modules/templates/Nepal/controllers.py +++ b/modules/templates/Nepal/controllers.py @@ -2,6 +2,7 @@ from gluon import * from s3 import S3CustomController +from layouts import IndexMenuLayOut THEME = "Nepal" @@ -10,13 +11,14 @@ class index(S3CustomController): """ Custom Home Page """ def __call__(self): - output = {} T = current.T response = current.response s3 = response.s3 - s3.stylesheets.append("../themes/CERT/homepage.css") + s3.stylesheets.append("../themes/Nepal/index.css") + s3.stylesheets.append("../styles/font-awesome.css") + self._view(THEME, "index.html") settings = current.deployment_settings output["title"] = response.title = settings.get_system_name() @@ -64,96 +66,46 @@ def __call__(self): item = "" output["item"] = item - menus = [{"title": T("Volunteers"), - "icon": "user", - "description": T("Manage people who have volunteered for your organization, their contact details, certicates and trainings."), - "module": "vol", - "function": "volunteer", - "buttons": [{"args": "summary", - "icon": "list", - "label": T("View"), - }, - {"args": "create", - "icon": "plus-sign", - "label": T("Create"), - }] - }, - {"title": T("Shelters"), - "icon": "home", - "description": T("List of Shelters."), - "module": "cr", - "function": "shelter", - "buttons": [{"args": "summary", - "icon": "list", - "label": T("View"), - }, - {"args": "create", - "icon": "plus-sign", - "label": T("Create"), - }] - }, - {"title": T("Hospitals"), - "icon": "h-sign", - "description": T("List of Hospitals."), - "module": "hms", - "function": "hospital", - "buttons": [{"args": "summary", - "icon": "list", - "label": T("View"), - }, - {"args": "create", - "icon": "plus-sign", - "label": T("Create"), - }] - }, - {"title": T("Patients"), - "icon": "ambulance", - "description": T("List of Patients."), - "module": "patient", - "function": "patient", - "buttons": [{"args": "summary", - "icon": "list", - "label": T("View"), - }, - {"args": "create", - "icon": "plus-sign", - "label": T("Create"), - }] - }, - {"title": T("Requests"), - "icon": "truck", - "description": T("Requests for goods or services."), - "module": "req", - "function": "req", - "args": None, - "buttons": [{"args": "summary", - "icon": "list", - "label": T("View"), - }, - {"args": "create", - "icon": "plus-sign", - "label": T("Create"), - }] - }, - {"title": T("Resources"), - "icon": "wrench", - "description": T("Resources that organizations have that are useful for response."), - "module": "org", - "function": "resource", - "args": None, - "buttons": [{"args": "summary", - "icon": "list", - "label": T("View"), - }, - {"args": "create", - "icon": "plus-sign", - "label": T("Create"), - }] - }, - ] - output["menus"] = menus - - self._view(THEME, "index.html") + IM = IndexMenuLayOut + index_menu = IM()(IM("Organizations", c="org", f="organisation", args="summary", + icon="organisation", + description=T("List of Organizations responding with contact details and their activities to provide 3W (Who's Doing What Where)."), + )(IM("View", args="summary", icon="list"), + IM("Create", args="create", icon="create")), + IM("Volunteers", c="vol", f="volunteer", args="summary", + icon="volunteers", + description=T("Manage people volunteering for your organization, their contact details, certificates and trainings."), + )(IM("View", args="summary", icon="list"), + IM("Create", args="create", icon="create")), + IM("Hospitals", c="hms", f="hospital", args="summary", + description=T("List of Hospitals and other Health Facilities."), + )(IM("View", args="summary", icon="list"), + IM("Create", args="create", icon="create")), + IM("Warehouses", c="inv", f="index", args="summary", + description=T("Manage Warehouses, their stock and shipments."), + icon="warehouse", + )(IM("View", f="warehouse", args="summary", icon="list"), + IM("Create", f="warehouse", args="create", icon="create")), + IM("Resources", c="org", f="resource", args="summary", + description=T("Resources that organizations have that are useful for response."), + )(IM("View", args="summary", icon="list"), + IM("Create", args="create", icon="create")), + IM("Shelters", c="cr", f="shelter", args="summary", + description=T("List of Shelters for displaced people."), + )(IM("View", args="summary", icon="list"), + IM("Create", args="create", icon="create")), + IM("Patients", c="patient", f="patient", args="summary", + icon="ambulance", + description=T("Register and track Patients."), + )(IM("View", args="summary", icon="list"), + IM("Create", args="create", icon="create")), + IM("Requests", c="req", f="req", args="summary", + icon="truck", + description=T("Requests for resources or services."), + )(IM("View", args="summary", icon="list"), + IM("Create", args="create", icon="create")), + ) + output["index_menu"] = index_menu return output # END ========================================================================= diff --git a/modules/templates/Nepal/css.cfg b/modules/templates/Nepal/css.cfg deleted file mode 100644 index 0bcec78d39..0000000000 --- a/modules/templates/Nepal/css.cfg +++ /dev/null @@ -1,43 +0,0 @@ -../themes/default/layout.css -../themes/default/xtheme-gray.css -../themes/default/footer.css -../themes/default/widgets.css -../themes/default/shortcut.css -../themes/default/homepage.css -bootstrap/font-awesome.css -plugins/jquery.cluetip.css -plugins/jquery.dataTables.css -plugins/jquery.dataTables.responsive.css -#ui/accordion.css -ui/core.css -ui/autocomplete.css -ui/button.css -ui/datepicker.css -ui/dialog.css -# Needed for Delphi -#ui/draggable.css -ui/menu.css -#ui/progressbar.css -ui/resizable.css -ui/selectmenu.css -ui/slider.css -#ui/sortable.css -#ui/spinner.css -ui/tabs.css -#ui/tooltip.css -ui/fgtimepicker.css -ui/multiselect.css -ui/timepicker-addon.css -foundation/jquery-ui.theme.css -gis/style.css -zocial/zocial.css -../themes/default/gis.css -../themes/foundation/map.css -../themes/default/mobile.css -../themes/default/print.css -d3/nv.d3.css -../themes/default/report.css -../themes/default/survey.css -../themes/default/style.css -#../themes/MY_THEME/style.css -# Final line required for parsing diff --git a/modules/templates/Nepal/layouts.py b/modules/templates/Nepal/layouts.py new file mode 100644 index 0000000000..f6cd750b44 --- /dev/null +++ b/modules/templates/Nepal/layouts.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +from gluon import * +from s3 import * + +# ============================================================================= +class IndexMenuLayOut(S3NavigationItem): + @staticmethod + def layout(item): + """ Layout Method (Item Renderer) """ + + # Manage flags: hide any disabled/unauthorized items + #if not item.authorized: + # enabled = False + # visible = False + #elif item.enabled is None or item.enabled: + # enabled = True + # visible = True + + #if enabled and visible: + if item.parent is None: + # Return Menu + items = item.render_components() + return UL(items, _id="index-menu", + _class="small-block-grid-1 medium-block-grid-2 large-block-grid-4") + else: + if item.enabled:# and item.authorized: + attr = dict(_id = item.attr._id, + _href = item.url()) + + if item.components: + # Menu Icon + section = [A(H2(ICON(item.opts.get("icon",item.function)), + BR(), + item.label), + **attr), + ] + items = item.render_components() + if items: + section.append(DIV(items)) + section.append(P(item.opts.description)) + return LI(section) + else: + # Menu Icon Buttons + return A(ICON(item.opts.icon), + " ", + item.label, + _class="button small secondary", + **attr) +# END ========================================================================= diff --git a/modules/templates/Nepal/menus.py b/modules/templates/Nepal/menus.py new file mode 100644 index 0000000000..600937447b --- /dev/null +++ b/modules/templates/Nepal/menus.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- + +from gluon import current +from s3 import * +from s3layouts import * +try: + from .layouts import * +except ImportError: + pass +import s3menus as default + +# ============================================================================= +class S3OptionsMenu(default.S3OptionsMenu): + """ + Custom Application Options Menu + + Define one function per controller with the controller prefix as + function name and with "self" as its only argument (must be an + instance method!), and let it return the controller menu + definition as an instance of the layout (=an S3NavigationItem + subclass, standard: M). + + In the standard layout, the main item in a controller menu does + not have a label. If you want to re-use a menu for multiple + controllers, do *not* define a controller setting (c="xxx") in + the main item. + """ + + def __init__(self, name): + """ Constructor """ + + try: + self.menu = getattr(self, name)() + except: + self.menu = None + + # ------------------------------------------------------------------------- + @staticmethod + def inv(): + """ INV / Inventory """ + + ADMIN = current.session.s3.system_roles.ADMIN + + current.s3db.inv_recv_crud_strings() + inv_recv_list = current.response.s3.crud_strings.inv_recv.title_list + + settings = current.deployment_settings + use_adjust = lambda i: not settings.get_inv_direct_stock_edits() + use_commit = lambda i: settings.get_req_use_commit() + + return M()( + M("Receive", c="inv", f="recv")( + M("New", m="create"), + M("Exiting", vars = {"a":1}), # + M("Timeline", args="timeline"), + ), + M("Send", c="inv", f="send")( + M("New", m="create"), + M("Exiting", vars = {"a":1}), # + M("Sent Shipments", m="summary"), # + M("Search Shipped Items", f="track_item"), + M("Timeline", args="timeline"), + ), + M("Stock", c="inv", f="inv_item", m="summary")( + M("Adjust Stock Levels", f="adj", check=use_adjust), + M("Kitting", f="kitting"), + M("Import", f="inv_item", m="import", p="create"), + ), + M("Warehouses", c="inv", f="warehouse")( + M("Create", m="create"), + M("Import", m="import", p="create"), + ), + M("Requests", c="req", f="req")( + M("Create", m="create"), + M("Requested Items", f="req_item"), + ), + M("Commitments", c="req", f="commit", check=use_commit)( + ), + M("Reports", c="inv", f="inv_item")( + M("Stock Matrix", f="inv_item", m="report"), + M("Distribution Report", c="inv", f="track_item", + vars=dict(report="dist")), + ), + M("Administration", restrict=[ADMIN])( + M("Items", c="supply", f="item", m="summary"), + M("Catalogs", c="supply", f="catalog"), + M("Item Categories", c="supply", f="item_category", + restrict=[ADMIN]), + M("Suppliers", c="inv", f="supplier"), + M("Facilities", c="inv", f="facility"), + M("Facility Types", c="inv", f="facility_type", + restrict=[ADMIN]), + M("Warehouse Types", c="inv", f="warehouse_type", + restrict=[ADMIN]), + ) + ) diff --git a/modules/templates/Nepal/tasks.cfg b/modules/templates/Nepal/tasks.cfg index 9aefce6c21..90dcc44a57 100644 --- a/modules/templates/Nepal/tasks.cfg +++ b/modules/templates/Nepal/tasks.cfg @@ -43,3 +43,14 @@ org,office_type,default/office_type.csv,office_type.xsl # ----------------------------------------------------------------------------- cms,post,cms_post.csv,post.xsl # ============================================================================= +# DEMO Data Only +# Inventory +# inv,inv_item,inv_item.csv,inv_item.xsl +# Requests +#req,req,test/inv-mngt/req_req.csv,req.xsl +#req,req_item,test/inv-mngt/req_item.csv,req_item.xsl +# The order in which the items are shipped is important +# so do not try to change the order or merge the following track_item files +#inv,track_item,test/inv-mngt/track_item1.csv,track_item.xsl +#inv,track_item,test/inv-mngt/track_item2.csv,track_item.xsl +#inv,track_item,test/inv-mngt/track_item3.csv,track_item.xsl diff --git a/modules/templates/Nepal/views/index.html b/modules/templates/Nepal/views/index.html index a4d7585d4d..b9f305fb83 100644 --- a/modules/templates/Nepal/views/index.html +++ b/modules/templates/Nepal/views/index.html @@ -1,5 +1,5 @@ {{extend "layout.html"}} -