Example #1
0
 def parse_item(self, item):
     ep = Storage()
     title_and_size = re.search(r'alt="([^"]*)" class="epinfo"',item)
     if not title_and_size:
         return None
     title_and_size = title_and_size.group(1)
     size = re.search(r'\(([^)]*)\)$', title_and_size)
     if size:
         size = size.group(0).replace('(', '').replace(')', '').strip()
         if 'MB' in size:
             size = size.replace('MB', '')
             multiplier = 1024
         elif 'GB' in size:
             size = size.replace('GB', '')
             multiplier = 1024*1024
         try:
             size = float(size.strip())*multiplier
         except:
             size = 300*1024*1024
     else:
         size = 300*1024*1024
     ep.title = title_and_size.rsplit('(', 1)[0]
     info = self.parse_title(ep.title)
     ep.update(info)
     magnet = re.search(r'href="magnet:\?xt([^"]*)"', item)
     if magnet:
         ep.magnet = 'magnet:?xt%s' % magnet.groups(1)
     ep.filename = ep.title
     ep.pubdate = datetime.datetime.utcnow()
     ep.filterwith = ep.title
     ep.size = size * 1024
     ep.guid = ep.magnet
     return ep
Example #2
0
def index():
    C = Storage()
    C.escuela = db.escuela(1)
    menu_migas.append(T("Tipos de pagos"))

    C.titulo = T("Registro de tipos de pago")

    # permisos
    puede_editar = auth.has_membership(role=myconf.take('roles.admin'))
#     puede_borrar = auth.has_membership(role=myconf.take('roles.admin'))
    puede_crear = auth.has_membership(role=myconf.take('roles.admin'))

    tbl = db.tipo_pago

    query = (tbl.id > 0)
    tbl.id.readable = False

    if 'edit' in request.args:
        tbl.nombre.writable = False

    text_lengths = {'tipo_pago.nombre': 50}

    C.grid = grid_simple(query,
                         maxtextlengths=text_lengths,
                         create=puede_crear,
                         editable=puede_editar)

    return dict(C=C)
Example #3
0
def show_responsibles():
    oprofesor = obies.Profesor(db, session)
    profesores = oprofesor.dame_profesores_curso()
    responsables = []
        
    for profesor in profesores:
        #comprobemos si el usuario existe en la tabla auth_user
        usuario = db(db.auth_user.username == profesor.profesor.usuario_rayuela).select(db.auth_user.ALL).first()
        if usuario:
            db(db.auth_user.id==usuario.id).select().first().update_record(first_name=profesor.profesor.nombre, last_name=profesor.profesor.apellidos)
            if auth.has_membership(role = 'Responsables', user_id = usuario.id):
                usu = Storage(usuario.as_dict())
                usua = db(usuario.username == db.profesor.usuario_rayuela).select(db.profesor.ALL).first()
                usu.idprofesor = usua.id
                responsables.append(usu)    
        else:
            #no existe usuario autentificación asociado al profesor
            id = db.auth_user.insert(username=profesor.profesor.usuario_rayuela, first_name=profesor.profesor.nombre, last_name=profesor.profesor.apellidos)
            auth.add_membership(role = 'Profesores', user_id = id)           
                  
    form = FORM(TABLE(TR(T('Teacher')+':', SELECT(_name='profe', *[OPTION(p.profesor.apellidos+', '+p.profesor.nombre, _value=p.profesor.usuario_rayuela) for p in profesores])),
                      TR("", INPUT(_type="submit",_value=T("Add responsible")))))
                      
    if form.accepts(request.vars, session):
        #debemos insertar al profesor en el grupo responsables
        usuario = db(db.auth_user.username==form.vars.profe).select(db.auth_user.id).first()
        if auth.has_membership(user_id=usuario, role='Responsables'):
            session.flash = T('Responsible already defined')
        else:
            auth.add_membership(role='Responsables', user_id=usuario)        
            session.flash = T('new responsible inserted')
        redirect(URL('show_responsibles'))                        
    return dict(form=form, responsables=responsables)
def phylogramConfig( session ):
    """
    This function returns the 'phylogram' renderType default config.  'phylogram' is a little of a misnomer,
    its simply the initial way this application rendered a tree using svg and raphael.js
    """

    config = Storage( verticalTipBuffer = 20,
                      branchLength = 20,
                      branchLengthStyle = 'smooth',
                      scaledBranchMultiplier = 0,
                      maxTips = 50,
                      verticalPadding = 50,
                      horizontalPadding = 50,
                      tipLabelBuffer = 5,
                      treeColor = 'black',
                      pathWidth = 3,
                      collapsedCladeColor = 'grey',
                      nonTipLabelBuffer = -5,
                      nodeSelectorRadius = 5,
                      nodeSelectorColor = 'blue' )

    if( session.TreeViewer.type == 'grafted' ):

        config.primaryShowEditColor = 'red'
        config.secondaryShowEditColor = 'blue'
        config.tertiaryShowEditColor = 'yellow'

    return config
Example #5
0
def index():
    """Carga la UI para la realización de los pagos"""
    C = Storage()
    C.evento = db.evento(request.args(0))
    C.persona = db.persona(request.args(1))

    return dict(C=C)
Example #6
0
    def url(self, extension=None, **kwargs):
        """
            Return the target URL for this item, doesn't check permissions

            @param extension: override the format extension
            @param kwargs: override URL query vars
        """

        if not self.link:
            return None

        args = self.args
        if self.vars:
            vars = Storage(self.vars)
            vars.update(kwargs)
        else:
            vars = Storage(kwargs)
        if extension is None:
            extension = self.extension
        a = self.get("application")
        if a is None:
            a = current.request.application
        c = self.get("controller")
        if c is None:
            c = "default"
        f = self.get("function")
        if f is None:
            f = "index"
        f, args = self.__format(f, args, extension)
        return URL(a=a, c=c, f=f, args=args, vars=vars)
Example #7
0
def wiki():

    wiki = auth.shotwiki()
    wiki_ctrl = Storage()

    if str(request.args(0)).startswith('_'):
        wiki_ctrl.cmd    = request.args(0)
        wiki_ctrl.slug   = request.args(1)
        wiki_ctrl.render = auth.get_wiki_rendering(wiki_ctrl.slug )
        response.flash_custom_display = True # hide default wiki flash messages
    else:
        wiki_ctrl.slug = request.args(0)

        if wiki_ctrl.slug == 'start':
            if config.display_flash_schedule:
                response.flash = auth.get_shotwiki_page(slug_base = 'market-schedule')

    if str(request.args(0)) != '_preview':
        wiki['wiki_ctrl'] = wiki_ctrl

    if wiki_ctrl.slug and str.lower(wiki_ctrl.slug) == 'zwillingsmarkt':
        #response.b_noindex = True
        redirect(URL('main','wiki', args = ['start']))

    return wiki
Example #8
0
File: pr.py Project: mauld/eden
    def testMobilePhoneNumberValidationInternational(self):
        """ Test that validator for mobile phone number is applied """

        current.deployment_settings \
               .msg.require_international_phone_numbers = True

        from s3db.pr import PRContactModel
        onvalidation = PRContactModel.pr_contact_onvalidation

        form = Storage(
            vars = Storage(
                contact_method = "SMS",
            )
        )

        # valid
        form.errors = Storage()
        form.vars.value = "+46-73-3847589"
        onvalidation(form)
        self.assertEqual(form.vars.value, "+46733847589")
        self.assertFalse("value" in form.errors)

        # invalid
        form.errors = Storage()
        form.vars.value = "0368172634"
        onvalidation(form)
        self.assertEqual(form.vars.value, "0368172634")
        self.assertTrue("value" in form.errors)
Example #9
0
    def accessible_url(self, extension=None, **kwargs):
        """
            Return the target URL for this item if accessible by the
            current user, otherwise False

            @param extension: override the format extension
            @param kwargs: override URL query vars
        """

        auth = current.auth
        aURL = auth.permission.accessible_url

        if not self.link:
            return None

        args = self.args
        if self.vars:
            vars = Storage(self.vars)
            vars.update(kwargs)
        else:
            vars = Storage(kwargs)
        if extension is None:
            extension = self.extension
        a = self.get("application")
        if a is None:
            a = current.request.application
        c = self.get("controller")
        if c is None:
            c = "default"
        f = self.get("function")
        if f is None:
            f = "index"
        p = self.p
        f, args = self.__format(f, args, extension)
        return aURL(p=p, a=a, c=c, f=f, args=args, vars=vars)
Example #10
0
    def draw(self, output="xml"):
        """
            Output the chart as a PNG embedded in an IMG tag
                - used by the Delphi module
        """

        fig = self.fig
        if not fig:
            return "Matplotlib not installed"

        # For interactive shell tests
        #plt.show()
        # For web response
        #savefig(response.body)
        chart = Storage()
        chart.body = StringIO()
        chart.headers = Storage()
        chart.headers["Content-Type"] = "image/png"

        canvas = self.FigureCanvas(fig)
        canvas.print_figure(chart.body)
        #return response.body.getvalue()
        image = chart.body.getvalue()
        if output == "xml":
            base64Img = base64.b64encode(image)
            image = IMG(_src="data:image/png;base64,%s" % base64Img)
        else:
            current.response.headers["Content-Type"] = "image/png"
        return image
Example #11
0
 def select(self):
     if self.op == 'eq' and self.field == 'id' and self.value:
         #means that someone wants to retrieve the key self.value
         rtn = self.db.hgetall("%s:%s" % (self.keyprefix, self.value))
         if rtn == dict():
             #return an empty resultset for non existing key
             return []
         else:
             return [Storage(rtn)]
     elif self.op == 'ge' and self.field == 'id' and self.value == 0:
         #means that someone wants the complete list
         rtn = []
         id_idx = "%s:id_idx" % self.keyprefix
         #find all session keys of this app
         allkeys = self.db.smembers(id_idx)
         for sess in allkeys:
             val = self.db.hgetall(sess)
             if val == dict():
                 if self.session_expiry:
                     #clean up the idx, because the key expired
                     self.db.srem(id_idx, sess)
                     continue
                 else:
                     continue
             val = Storage(val)
             #add a delete_record method (necessary for sessions2trash.py)
             val.delete_record = RecordDeleter(
                 self.db, sess, self.keyprefix)
             rtn.append(val)
         return rtn
     else:
         raise Exception("Operation not supported")
Example #12
0
 def select(self):
     if self.op == 'eq' and self.field == 'id' and self.value:
         #means that someone wants to retrieve the key self.value
         key = self.keyprefix + ':' + str(self.value)
         if self.with_lock:
             acquire_lock(self.db, key + ':lock', self.value)
         rtn = self.db.hgetall(key)
         rtn['update_record'] = self.update  # update record support
         return [Storage(rtn)] if rtn else []
     elif self.op == 'ge' and self.field == 'id' and self.value == 0:
         #means that someone wants the complete list
         rtn = []
         id_idx = "%s:id_idx" % self.keyprefix
         #find all session keys of this app
         allkeys = self.db.smembers(id_idx)
         for sess in allkeys:
             val = self.db.hgetall(sess)
             if not val:
                 if self.session_expiry:
                     #clean up the idx, because the key expired
                     self.db.srem(id_idx, sess)
                 continue
             val = Storage(val)
             #add a delete_record method (necessary for sessions2trash.py)
             val.delete_record = RecordDeleter(
                 self.db, sess, self.keyprefix)
             rtn.append(val)
         return rtn
     else:
         raise Exception("Operation not supported")
Example #13
0
    def __call__(self, name=None, **attr):

        if not name:
            name = self.name

        ia = Storage(self.attr)

        if attr:
            if not attr.get("empty", True):
                requires = ia.requires
                if requires:
                    if not isinstance(requires, (list, tuple)):
                        requires = [requires]
                    if requires:
                        r = requires[0]
                        if isinstance(r, IS_EMPTY_OR):
                            requires = r.other
                            ia.update(requires=requires)
            if "empty" in attr:
                del attr["empty"]
            ia.update(**attr)

        if ia.sortby is not None:
            return FieldS3(name, self.__type, **ia)
        else:
            return Field(name, self.__type, **ia)
Example #14
0
def s3_lx_update(table, record_id):
    """
        Write the Lx fields from the Location
        - used by hrm_human_resource & pr_address

        @ToDo: Allow the reverse operation.
        If these fields are populated then create/update the location
    """

    if "location_id" in table:

        db = current.db
        ltable = current.s3db.gis_location
        query = (table.id == record_id) & (ltable.id == table.location_id)
        location = (
            db(query).select(ltable.id, ltable.name, ltable.level, ltable.parent, ltable.path, limitby=(0, 1)).first()
        )
        if location:
            vars = Storage()
            if location.level == "L0":
                vars.L0 = location.name
            elif location.level == "L1":
                vars.L1 = location.name
                if location.parent:
                    query = ltable.id == location.parent
                    country = db(query).select(ltable.name, limitby=(0, 1)).first()
                    if country:
                        vars.L0 = country.name
            else:
                # Get Names of ancestors at each level
                vars = current.gis.get_parent_per_level(vars, location.id, feature=location, ids=False, names=True)
            # Update record
            db(table.id == record_id).update(**vars)
Example #15
0
    def job_data(self):
        """Return the data representing job to be queued.

        Returns:
            Storage: representing job (equivalent to db.job Row.as_dict())
        """
        db = current.app.db
        attributes = Storage(dict(self.default_job_options))
        if self.job_options:
            attributes.update(self.job_options)
        for k in sorted(attributes.keys()):
            if k not in self.tbl.fields:
                raise InvalidJobOptionError(
                    'Invalid job option: {opt}'.format(opt=k))
        now = datetime.datetime.now()

        job_queuer = None
        if self.class_factory_id:
            query = (db.job_queuer.code == self.class_factory_id)
            job_queuer = db(query).select().first()

        attributes['job_queuer_id'] = job_queuer.id if job_queuer else 0

        if 'command' not in attributes:
            attributes['command'] = self.command()
        if 'start' not in attributes:
            attributes['start'] = now
        if self.delay_seconds:
            attributes['start'] = attributes['start'] + \
                datetime.timedelta(seconds=self.delay_seconds)
        attributes['queued_time'] = now
        return attributes
Example #16
0
def info():
    if not have_uwsgi:
        return "you aren't running web2py with uwsgi"
    info = Storage()
    info.masterpid = uwsgi.masterpid()
    info.version = uwsgi.version
    info.started_on = time.ctime(uwsgi.started_on)
    info.buffer_size = uwsgi.buffer_size
    info.total_requests = uwsgi.total_requests()
    info.logsize = uwsgi.logsize()
    info.numproc = uwsgi.numproc
    try:
        info.mode = uwsgi.mode
    except:
        pass
    try:
        info.pidfile = uwsgi.pidfile
    except:
        pass
    
    workers = uwsgi.workers()
    total_load = time.time() - uwsgi.started_on
    for w in workers:
        w['load'] = (100 * (w['running_time']/1000))/total_load
        w['last_spawn_str'] = time.ctime(w['last_spawn'])
        w['vsz_str'] = do_filesizeformat(w['vsz'])
        w['rss_str'] = do_filesizeformat(w['rss'])
    
    context = dict(info=info, workers=workers)
    template = template_view('info')
    return response.render(template, context)
Example #17
0
    def testTypeConversionFeature(self):
        """ Check that values get converted into the field type during validation """

        s3db = current.s3db

        # Create a fake request
        resource = s3db.resource("project_organisation")
        request = Storage(prefix="project",
                          name="organisation",
                          resource=resource,
                          table=resource.table,
                          tablename=resource.tablename,
                          method="validate",
                          get_vars=Storage(),
                          representation="json",
                          http="GET")

        crud = resource.crud

        jsonstr = """{"organisation_id":"1", "role":"1"}"""
        request.body = StringIO(jsonstr)

        output = crud.validate(request)
        self.assertTrue(isinstance(output, basestring))
        from gluon.contrib import simplejson as json
        data = json.loads(output)
        self.assertTrue(isinstance(data, dict))
        self.assertEqual(len(data), 2)

        self.assertTrue("role" in data)
        role = data["role"]
        self.assertTrue(isinstance(role, dict))
        self.assertTrue("value" in role)
        self.assertTrue(isinstance(role["value"], int))
Example #18
0
    def test__set_port(self):
        port_1 = '1111'
        port_2 = '2222'
        port_3 = '3333'
        local_mysql = LocalMySQL(port=port_1)
        self.assertTrue(local_mysql.port, port_1)  # Provided port is used

        save_env_port = os.environ.get('MYSQL_TCP_PORT')

        del os.environ['MYSQL_TCP_PORT']
        local_mysql = LocalMySQL()
        # No port, no http env var, no uses env var, not set
        self.assertFalse(local_mysql.port)

        os.environ['MYSQL_TCP_PORT'] = port_2
        local_mysql = LocalMySQL()
        # No port, no http env var, uses env var
        self.assertTrue(local_mysql.port, port_2)

        request = Storage()
        request.env = Storage()
        request.env.web2py_mysql_tcp_port = port_3

        local_mysql = LocalMySQL()
        self.assertTrue(local_mysql.port, port_3)  # No port, uses http env var

        os.environ['MYSQL_TCP_PORT'] = save_env_port
        return
Example #19
0
def carreras_me():
    C = Storage()
    C.escuela = db.escuela(1)
    menu_migas.append(T("Descripciones de carreras"))

    tbl = db.descripcion_carrera
    query = (tbl.id > 0)

    tbl.id.readable = False
    text_lengths = {'descripcion_carrera.nombre': 50}

    C.titulo = T("Registro de carreras del Ministerio de Educación")

    puede_editar = auth.has_membership(role=myconf.take('roles.admin'))
#     puede_borrar = auth.has_membership(role=myconf.take('roles.admin'))
    puede_crear = auth.has_membership(role=myconf.take('roles.admin'))

    C.grid = grid_simple(query,
                         editable=puede_editar,
                         create=puede_crear,
                         maxtextlengths=text_lengths,
                         orderby=[tbl.nombre],
                         args=request.args[:1])

    return dict(C=C)
Example #20
0
def historial():
    C = Storage()
    C.escuela = db.escuela(1)
    menu_migas.append(T("Control de cambios"))

    tbl_n = request.args(0)
    r_id = int(request.args(1))

    C.titulo = T("Historial de cambios TABLA: {} REGISTRO ID: {}").format(tbl_n, r_id)

    tbl = db["{}_archive".format(tbl_n)]
    query = (tbl.current_record == r_id)

    for f in tbl:
        f.readable = True
    tbl.current_record.readable = False

    C.current_record = SQLTABLE(db(db[tbl_n].id == r_id).select(),
                                headers="labels",
                                _class="table")
    C.grid = SQLFORM.grid(query, args=request.args[:2],
                          orderby=[~tbl.modified_on],
                          create=False,
                          searchable=False,
                          editable=False,
                          deletable=False,
                          details=False,
                          csv=False)

    return dict(C=C)
Example #21
0
def asignaturas():
    '''registro general de asigaturas'''
    C = Storage()
    C.escuela = db.escuela(1)

    menu_migas.append(T("Registro de asignaturas"))

    # -- construir el grid
    tbl = db.asignatura
    query = (tbl.id > 0)

    # permisos
    puede_crear = auth.has_membership(role=myconf.take('roles.admin'))
    puede_editar, puede_borrar = (puede_crear, puede_crear)

    tbl.id.readable = False
    text_lengths = {'asignatura.nombre': 50}

    C.grid = grid_simple(query,
                         create=puede_crear,
                         editable=puede_editar,
                         maxtextlengths=text_lengths,
                         deletable=puede_borrar)

    return dict(C=C)
Example #22
0
def labels():
    """
        args: [items]
        vars: [id_purchase, id_layout]
    """
    expiration_redirect()

    from_purchase = False

    page_layout = None
    if request.vars.id_layout:
        page_layout = db.labels_page_layout(request.vars.id_layout)
    else:
        page_layout = db(db.labels_page_layout).select().first()
    if not page_layout:
        redirect(URL('labels_page_layout', 'index'))
    layout = Storage({
        'id': page_layout.id,
        'width': page_layout.id_paper_size.width,
        'height': page_layout.id_paper_size.height,
        'margin_top': page_layout.margin_top,
        'margin_right': page_layout.margin_right,
        'margin_bottom': page_layout.margin_bottom,
        'margin_left': page_layout.margin_left,
        'space_x': page_layout.space_x or 0,
        'space_y': page_layout.space_y or 0,
        'cols': page_layout.label_cols,
        'rows': page_layout.label_rows,
        'show_item_name': page_layout.show_name,
        'show_price': page_layout.show_price
    })

    layout.label_width = (layout.width - (layout.margin_left + layout.margin_right + layout.space_x * (layout.cols - 1))) / layout.cols
    layout.label_height = (layout.height - (layout.margin_top + layout.margin_bottom + layout.space_y * (layout.rows - 1))) / layout.rows

    if request.vars.id_purchase and request.vars.id_purchase != 'None':
        from_purchase = True
        purchase = db((db.purchase.id == request.vars.id_purchase) & (db.purchase.is_done == True)).select().first()
        if not purchase:
            raise HTTP(404)
        purchase_items = db(
            db.stock_item.id_purchase == purchase.id
        ).iterselect()
        if not purchase_items:
            raise HTTP(404)
        return dict(items=purchase_items, layout=layout)

    if request.args:
        items_ids = request.args(0).split('_')
        query = (db.item.id < 0)
        for item_id in items_ids:
            query |= (db.item.id == int(item_id))
        items = db(
            (query) & (db.item.is_active == True)
        ).select()

        return dict(items=items, layout=layout)

    redirect(URL('default', 'index'))
Example #23
0
    def test_URL(self):
        self.assertEqual(URL('a', 'c', 'f', args='1'), '/a/c/f/1')
        self.assertEqual(URL('a', 'c', 'f', args=('1', '2')), '/a/c/f/1/2')
        self.assertEqual(URL('a', 'c', 'f', args=['1', '2']), '/a/c/f/1/2')
        self.assertEqual(URL('a', 'c', '/f'), '/a/c/f')
        self.assertEqual(URL('a', 'c', 'f.json'), '/a/c/f.json')
        from gluon.globals import current
        current.request = None
        self.assertRaises(SyntaxError, URL, *['a'])

        request = Storage()
        request.application = 'a'
        request.controller = 'c'
        request.function = 'f'
        request.env = {}

        from gluon.globals import current  # Can't be moved with other import
        current.request = request

        must_return = '/a/c/f'
        self.assertEqual(URL(), must_return)
        self.assertEqual(URL('f'), must_return)
        self.assertEqual(URL('c', 'f'), must_return)
        self.assertEqual(URL('a', 'c', 'f'), must_return)
        self.assertEqual(URL('a', 'c', 'f', extension='json'), '/a/c/f.json')

        def weird():
            pass
        self.assertEqual(URL('a', 'c', weird), '/a/c/weird')
        self.assertRaises(SyntaxError, URL, *['a', 'c', 1])
        # test signature
        rtn = URL(a='a', c='c', f='f', args=['x', 'y', 'z'],
                  vars={'p': (1, 3), 'q': 2}, anchor='1', hmac_key='key')
        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f#1')
        # test _signature exclusion
        rtn = URL(a='a', c='c', f='f', args=['x', 'y', 'z'],
                  vars={'p': (1, 3), 'q': 2, '_signature': 'abc'},
                  anchor='1', hmac_key='key')
        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f#1')
        # emulate user_signature
        current.session = Storage(auth=Storage(hmac_key='key'))
        self.assertEqual(URL(user_signature=True), '/a/c/f?_signature=c4aed53c08cff08f369dbf8b5ba51889430cf2c2')
        # hash_vars combination
        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key')
        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f')
        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars=True)
        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=a32530f0d0caa80964bb92aad2bedf8a4486a31f')
        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars=False)
        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=0b5a0702039992aad23c82794b8496e5dcd59a5b')
        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars=['p'])
        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=5d01b982fd72b39674b012e0288071034e156d7a')
        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'p': (1, 3), 'q': 2}, hmac_key='key', hash_vars='p')
        self.assertEqual(rtn, '/a/c/f/x/y/z?p=1&p=3&q=2&_signature=5d01b982fd72b39674b012e0288071034e156d7a')
        # test CRLF detection
        self.assertRaises(SyntaxError, URL, *['a\n', 'c', 'f'])
        self.assertRaises(SyntaxError, URL, *['a\r', 'c', 'f'])
        # test url_encode
        rtn = URL('a', 'c', 'f', args=['x', 'y', 'z'], vars={'maï': (1, 3), 'lié': 2}, url_encode=True)
        self.assertEqual(rtn, '/a/c/f/x/y/z?li%C3%A9=2&ma%C3%AF=1&ma%C3%AF=3')
Example #24
0
def s3_popup_comment(c=None,
                     f=None,
                     t=None,
                     vars=None,
                     label=None,
                     info=None,
                     title=None,
                     tooltip=None):

    """
        Generate a ADD-popup comment, return an empty DIV if the user
        is not permitted to add records to the referenced table

        @param c: the target controller
        @param f: the target function
        @param t: the target table (defaults to c_f)
        @param vars: the request vars (format="popup" will be added automatically)
        @param label: the link label
        @param info: hover-title for the label
        @param title: the tooltip title
        @param tooltip: the tooltip text

        @todo: replace by S3NavigationItem
    """

    auth = current.auth

    if title is None:
        return None

    if label is None:
        label = title
    if info is None:
        info = title

    if vars is not None:
        _vars = Storage(vars)
    else:
        _vars = Storage()
    _vars.update(format="popup")

    popup = ""
    ttip = ""
    if c and f and auth is not None:
        _href = auth.permission.accessible_url(c=c, f=f, t=t,
                                               p="create",
                                               args="create", vars=_vars)
        if _href is not False:
            popup = A(label,
                      _class="colorbox",
                      _href=_href,
                      _target="top",
                      _title=info)
            if tooltip is not None:
                ttip = DIV(_class="tooltip",
                           _title="%s|%s" % (title, tooltip))

    comment = DIV(popup, ttip)
    return comment
Example #25
0
File: doc.py Project: flavour/aidiq
    def document_onvalidation(form, document=True):
        """ Form validation for both, documents and images """

        form_vars = form.vars
        doc = form_vars.file

        if doc is None:
            # If this is a prepop, then file not in form
            # Interactive forms with empty doc has this as "" not None
            return

        if not document:
            encoded_file = form_vars.get("imagecrop-data", None)
            if encoded_file:
                # S3ImageCropWidget
                import base64
                import uuid
                metadata, encoded_file = encoded_file.split(",")
                #filename, datatype, enctype = metadata.split(";")
                filename = metadata.split(";", 1)[0]
                f = Storage()
                f.filename = uuid.uuid4().hex + filename
                import cStringIO
                f.file = cStringIO.StringIO(base64.decodestring(encoded_file))
                doc = form_vars.file = f
                if not form_vars.name:
                    form_vars.name = filename

        if not hasattr(doc, "file"):
            # Record update without new file upload => keep existing
            record_id = current.request.post_vars.id
            if record_id:
                db = current.db
                if document:
                    tablename = "doc_document"
                else:
                    tablename = "doc_image"
                table = db[tablename]
                record = db(table.id == record_id).select(table.file,
                                                          limitby = (0, 1),
                                                          ).first()
                if record:
                    doc = record.file

        if not hasattr(doc, "file") and not doc and not form_vars.url:
            if document:
                msg = current.T("Either file upload or document URL required.")
            else:
                msg = current.T("Either file upload or image URL required.")
            if "file" in form_vars:
                form.errors.file = msg
            if "url" in form_vars:
                form.errors.url = msg

        if hasattr(doc, "file"):
            name = form_vars.name
            if not name:
                # Use filename as document/image title
                form_vars.name = doc.filename
Example #26
0
 def __init__(
     self,
     db=None,
     tablename='web2py_ticket'
 ):
     Storage.__init__(self)
     self.db = db
     self.tablename = tablename
Example #27
0
 def test_getlist(self):
     # usually used with request.vars
     a = Storage()
     a.x = 'abc'
     a.y = ['abc', 'def']
     self.assertEqual(a.getlist('x'), ['abc'])
     self.assertEqual(a.getlist('y'), ['abc', 'def'])
     self.assertEqual(a.getlist('z'), [])
Example #28
0
 def test_getlast(self):
     # usually with request.vars
     a = Storage()
     a.x = 'abc'
     a.y = ['abc', 'def']
     self.assertEqual(a.getlast('x'), 'abc')
     self.assertEqual(a.getlast('y'), 'def')
     self.assertEqual(a.getlast('z'), None)
Example #29
0
    def member_onaccept(form):
        """ On-accept for Member records """

        db = current.db
        s3db = current.s3db

        utable = current.auth.settings.table_user
        ptable = s3db.pr_person
        ltable = s3db.pr_person_user
        mtable = s3db.member_membership

        # Get the full record
        id = form.vars.id
        if id:
            query = (mtable.id == id)
            record = db(query).select(mtable.id,
                                      mtable.person_id,
                                      mtable.organisation_id,
                                      mtable.deleted,
                                      limitby=(0, 1)).first()
        else:
            return

        data = Storage()

        # Affiliation
        s3db.pr_update_affiliations(mtable, record)

        # Update the location ID from the Home Address
        atable = s3db.pr_address
        query = (atable.pe_id == ptable.pe_id) & \
                (ptable.id == record.person_id) & \
                (atable.type == 1) & \
                (atable.deleted == False)
        address = db(query).select(atable.location_id,
                                   limitby=(0, 1)).first()
        if address:
            data.location_id = address.location_id

        # Add record owner (user)
        query = (ptable.id == record.person_id) & \
                (ltable.pe_id == ptable.pe_id) & \
                (utable.id == ltable.user_id)
        user = db(query).select(utable.id,
                                utable.organisation_id,
                                utable.site_id,
                                limitby=(0, 1)).first()
        if user:
            user_id = user.id
            data.owned_by_user = user.id

        if not data:
            return
        record.update_record(**data)

        if data.location_id:
            # Populate the Lx fields
            current.response.s3.lx_update(mtable, record.id)
Example #30
0
def user():
    from gluon.storage import Storage
    objects = Storage()
    if request.args(0) in ['register', 'login']:
        objects.login = auth.login()
        objects.register = auth.register()
    else:
        objects.form = auth()
    return dict(objects=objects)
Example #31
0
def config(settings):
    """
        Template settings: 'Skeleton' designed to be copied to quickly create
                           custom templates

        All settings which are to configure a specific template are located
        here. Deployers should ideally not need to edit any other files outside
        of their template folder.
    """

    T = current.T

    #settings.base.system_name = T("Sahana Skeleton")
    #settings.base.system_name_short = T("Sahana")

    # PrePopulate data
    settings.base.prepopulate = ("skeleton", "default/users")

    # Theme (folder to use for views/layout.html)
    settings.base.theme = "skeleton"

    # Authentication settings
    # Should users be allowed to register themselves?
    #settings.security.self_registration = False
    # Do new users need to verify their email address?
    #settings.auth.registration_requires_verification = True
    # 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

    # Approval emails get sent to all admins
    settings.mail.approver = "ADMIN"

    # Restrict the Location Selector to just certain countries
    # NB This can also be over-ridden for specific contexts later
    # e.g. Activities filtered to those of parent Project
    #settings.gis.countries = ("US",)
    # Uncomment to display the Map Legend as a floating DIV
    settings.gis.legend = "float"
    # Uncomment to Disable the Postcode selector in the LocationSelector
    #settings.gis.postcode_selector = False # @ToDo: Vary by country (include in the gis_config!)
    # Uncomment to show the Print control:
    # http://eden.sahanafoundation.org/wiki/UserGuidelines/Admin/MapPrinting
    #settings.gis.print_button = True

    # L10n settings
    # Languages used in the deployment (used for Language Toolbar & GIS Locations)
    # http://www.loc.gov/standards/iso639-2/php/code_list.php
    #settings.L10n.languages = OrderedDict([
    #    ("ar", "العربية"),
    #    ("bs", "Bosanski"),
    #    ("en", "English"),
    #    ("fr", "Français"),
    #    ("de", "Deutsch"),
    #    ("el", "ελληνικά"),
    #    ("es", "Español"),
    #    ("it", "Italiano"),
    #    ("ja", "日本語"),
    #    ("km", "ភាសាខ្មែរ"),
    #    ("ko", "한국어"),
    #    ("ne", "नेपाली"),          # Nepali
    #    ("prs", "دری"), # Dari
    #    ("ps", "پښتو"), # Pashto
    #    ("pt", "Português"),
    #    ("pt-br", "Português (Brasil)"),
    #    ("ru", "русский"),
    #    ("tet", "Tetum"),
    #    ("tl", "Tagalog"),
    #    ("tr", "Türkçe"),
    #    ("ur", "اردو"),
    #    ("vi", "Tiếng Việt"),
    #    ("zh-cn", "中文 (简体)"),
    #    ("zh-tw", "中文 (繁體)"),
    #])
    # Default language for Language Toolbar (& GIS Locations in future)
    #settings.L10n.default_language = "en"
    # Uncomment to Hide the language toolbar
    #settings.L10n.display_toolbar = False
    # Default timezone for users
    #settings.L10n.utc_offset = "UTC +0100"
    # Number formats (defaults to ISO 31-0)
    # Decimal separator for numbers (defaults to ,)
    settings.L10n.decimal_separator = "."
    # Thousands separator for numbers (defaults to space)
    settings.L10n.thousands_separator = ","
    # Uncomment this to Translate Layer Names
    #settings.L10n.translate_gis_layer = True
    # Uncomment this to Translate Location Names
    #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"

    # Security Policy
    # http://eden.sahanafoundation.org/wiki/S3AAA#System-widePolicy
    # 1: Simple (default): Global as Reader, Authenticated as Editor
    # 2: Editor role required for Update/Delete, unless record owned by session
    # 3: Apply Controller ACLs
    # 4: Apply both Controller & Function ACLs
    # 5: Apply Controller, Function & Table ACLs
    # 6: Apply Controller, Function, Table ACLs and Entity Realm
    # 7: Apply Controller, Function, Table ACLs and Entity Realm + Hierarchy
    # 8: Apply Controller, Function, Table ACLs, Entity Realm + Hierarchy and Delegations
    #
    #settings.security.policy = 7 # Organisation-ACLs

    # RSS feeds
    #settings.frontpage.rss = [
    #    {"title": "Eden",
    #     # Trac timeline
    #     "url": "http://eden.sahanafoundation.org/timeline?ticket=on&changeset=on&milestone=on&wiki=on&max=50&daysback=90&format=rss"
    #    },
    #    {"title": "Twitter",
    #     # @SahanaFOSS
    #     #"url": "https://search.twitter.com/search.rss?q=from%3ASahanaFOSS" # API v1 deprecated, so doesn't work, need to use 3rd-party service, like:
    #     "url": "http://www.rssitfor.me/getrss?name=@SahanaFOSS"
    #     # Hashtag
    #     #url: "http://search.twitter.com/search.atom?q=%23eqnz" # API v1 deprecated, so doesn't work, need to use 3rd-party service, like:
    #     #url: "http://api2.socialmention.com/search?q=%23eqnz&t=all&f=rss"
    #    }
    #]


    # -------------------------------------------------------------------------
    # Comment/uncomment modules here to disable/enable them
    # Modules menu is defined in modules/eden/menu.py
    settings.modules = OrderedDict([
        # Core modules which shouldn't be disabled
        ("default", Storage(
            name_nice = T("Home"),
            restricted = False, # Use ACLs to control access to this module
            access = None,      # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type = None  # This item is not shown in the menu
        )),
        ("admin", Storage(
            name_nice = T("Administration"),
            #description = "Site Administration",
            restricted = True,
            access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
            module_type = None  # This item is handled separately for the menu
        )),
        ("appadmin", Storage(
            name_nice = T("Administration"),
            #description = "Site Administration",
            restricted = True,
            module_type = None  # No Menu
        )),
        ("errors", Storage(
            name_nice = T("Ticket Viewer"),
            #description = "Needed for Breadcrumbs",
            restricted = False,
            module_type = None  # No Menu
        )),
        #("sync", Storage(
        #    name_nice = T("Synchronization"),
        #    #description = "Synchronization",
        #    restricted = True,
        #    access = "|1|",     # Only Administrators can see this module in the default menu & access the controller
        #    module_type = None  # This item is handled separately for the menu
        #)),
        #("tour", Storage(
        #    name_nice = T("Guided Tour Functionality"),
        #    module_type = None,
        #)),
        #("translate", Storage(
        #    name_nice = T("Translation Functionality"),
        #    #description = "Selective translation of strings based on module.",
        #    module_type = None,
        #)),
        ("gis", Storage(
            name_nice = T("Map"),
            #description = "Situation Awareness & Geospatial Analysis",
            restricted = True,
            module_type = 6,     # 6th item in the menu
        )),
        ("pr", Storage(
            name_nice = T("Person Registry"),
            #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
        )),
        ("org", Storage(
            name_nice = T("Organizations"),
            #description = 'Lists "who is doing what & where". Allows relief agencies to coordinate their activities',
            restricted = True,
            module_type = 1
        )),
        #("hrm", Storage(
        #    name_nice = T("Staff"),
        #    #description = "Human Resources Management",
        #    restricted = True,
        #    module_type = 2,
        #)),
        #("vol", Storage(
        #    name_nice = T("Volunteers"),
        #    #description = "Human Resources Management",
        #    restricted = True,
        #    module_type = 2,
        #)),
        #("cms", Storage(
        #  name_nice = T("Content Management"),
        #  #description = "Content Management System",
        #  restricted = True,
        #  module_type = 10,
        #)),
        #("doc", Storage(
        #    name_nice = T("Documents"),
        #    #description = "A library of digital resources, such as photos, documents and reports",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("msg", Storage(
        #    name_nice = T("Messaging"),
        #    #description = "Sends & Receives Alerts via Email & SMS",
        #    restricted = True,
        #    # The user-visible functionality of this module isn't normally required. Rather it's main purpose is to be accessed from other modules.
        #    module_type = None,
        #)),
        #("supply", Storage(
        #    name_nice = T("Supply Chain Management"),
        #    #description = "Used within Inventory Management, Request Management and Asset Management",
        #    restricted = True,
        #    module_type = None, # Not displayed
        #)),
        #("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",
        #    restricted = True,
        #    module_type = 5,
        #)),
        # Vehicle depends on Assets
        #("vehicle", Storage(
        #    name_nice = T("Vehicles"),
        #    #description = "Manage Vehicles",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("req", Storage(
        #    name_nice = T("Requests"),
        #    #description = "Manage requests for supplies, assets, staff or other resources. Matches against Inventories where supplies are requested.",
        #    restricted = True,
        #    module_type = 10,
        #)),
        #("project", Storage(
        #    name_nice = T("Projects"),
        #    #description = "Tracking of Projects, Activities and Tasks",
        #    restricted = True,
        #    module_type = 2
        #)),
        #("cr", Storage(
        #    name_nice = T("Shelters"),
        #    #description = "Tracks the location, capacity and breakdown of victims in Shelters",
        #    restricted = True,
        #    module_type = 10
        #)),
        #("hms", Storage(
        #    name_nice = T("Hospitals"),
        #    #description = "Helps to monitor status of hospitals",
        #    restricted = True,
        #    module_type = 10
        #)),
        #("dvr", Storage(
        #   name_nice = T("Disaster Victim Registry"),
        #   #description = "Allow affected individuals & households to register to receive compensation and distributions",
        #   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,
        #   module_type = 10,
        #)),
        #("stats", Storage(
        #    name_nice = T("Statistics"),
        #    #description = "Manages statistics",
        #    restricted = True,
        #    module_type = None,
        #)),
    ])

# END =========================================================================
Example #32
0
    table.purchase_price.readable = table.purchase_price.writable = False
    table.purchase_currency.readable = table.purchase_currency.writable = False


settings.customise_asset_asset_resource = customise_asset_asset_resource
# -----------------------------------------------------------------------------
# Comment/uncomment modules here to disable/enable them
# Modules menu is defined in modules/eden/menu.py
settings.modules = OrderedDict([
    # Core modules which shouldn't be disabled
    (
        "default",
        Storage(
            name_nice=T("Home"),
            restricted=False,  # Use ACLs to control access to this module
            access=
            None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type=None  # This item is not shown in the menu
        )),
    (
        "admin",
        Storage(
            name_nice=T("Administration"),
            #description = "Site Administration",
            restricted=True,
            access=
            "|1|",  # Only Administrators can see this module in the default menu & access the controller
            module_type=None  # This item is handled separately for the menu
        )),
    (
        "appadmin",
Example #33
0
__author__ = 'smrutim'
import socket
from gluon.storage import Storage
settings = Storage()

settings.migrate = True
settings.title = 'RIP'
settings.subtitle = 'Rest In Peak'
settings.author = 'Smruti Mohanty'
settings.author_email = '*****@*****.**'
settings.app_uri = socket.gethostname()
settings.keywords = ''
settings.description = ''
settings.layout_theme = 'Default'
#settings.database_uri = 'postgres://*****:*****@localhost:5432/mydb'
settings.database_uri = 'sqlite://storage.sqlite'
settings.security_key = 'bb05dd73-42f2-4ad2-a1f7-589476f6a904'
settings.email_server = 'smtp.vmware.com'
settings.email_sender = '*****@*****.**'
settings.email_login = ''
settings.login_method = ''
settings.login_config = ''
settings.plugins = []
Example #34
0
    def model(self):

        T = current.T
        db = current.db
        request = current.request
        s3 = current.response.s3

        messages = current.messages
        UNKNOWN_OPT = messages.UNKNOWN_OPT
        NONE = messages["NONE"]

        crud_strings = s3.crud_strings
        define_table = self.define_table

        add_components = self.add_components
        configure = self.configure
        set_method = self.set_method

        s3_datetime_represent = lambda dt: \
                                S3DateTime.datetime_represent(dt, utc=True)

        # -------------------------------------------------------------------------
        # Configuration
        # -------------------------------------------------------------------------
        tablename = "sync_config"
        define_table(tablename,
                     Field("proxy",
                           label=T("Proxy Server URL"),
                           requires=IS_EMPTY_OR(IS_URL(mode="generic"))),
                     *s3_meta_fields())

        # Field configuration
        # @todo: make in-line
        table = db[tablename]
        table.uuid.readable = True
        table.uuid.label = "UUID"

        table.uuid.comment = DIV(_class="tooltip",
                                 _title="%s|%s" % (
                                    T("UUID"),
                                    T("Unique identifier which THIS repository identifies itself with when sending synchronization requests.")))
        table.proxy.comment = DIV(_class="tooltip",
                                  _title="%s|%s" % (
                                    T("Proxy Server URL"),
                                    T("URL of the default proxy server to connect to remote repositories (if required). If only some of the repositories require the use of a proxy server, you can configure this in the respective repository configurations.")))

        # CRUD Strings
        crud_strings[tablename] = Storage(
            title_display = T("Synchronization Settings"),
            title_update = T("Edit Synchronization Settings"),
            msg_record_modified = T("Synchronization settings updated"))

        # Resource Configuration
        configure(tablename,
                  insertable=False,
                  deletable=False,
                  update_next=URL(c="sync", f="config", args=["1", "update"]))

        # -------------------------------------------------------------------------
        # Status
        # -------------------------------------------------------------------------
        tablename = "sync_status"
        define_table(tablename,
                     Field("running", "boolean",
                           default=False,
                           readable=False,
                           writable=False),
                     Field("manual", "boolean",
                           default=False,
                           readable=False,
                           writable=False),
                     Field("timestmp", "datetime",
                           readable=False,
                           writable=False))

        # -------------------------------------------------------------------------
        # Repository
        # -------------------------------------------------------------------------
        sync_repository_types = {
            "eden": "Sahana Eden",
            "ccrm": "CiviCRM",
            "wrike": "Wrike",
            "mcb": "Mariner CommandBridge",
        }
        password_widget = S3PasswordWidget()
        tablename = "sync_repository"
        define_table(tablename,
                     Field("name", length=64, notnull=True,
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Repository Name"),
                                                T("Name of the repository (for you own reference)"))),
                           ),
                     Field("apitype",
                           label=T("Repository Type"),
                           requires = IS_IN_SET(sync_repository_types),
                           default = "eden",
                           represent = lambda opt: \
                                       NONE if not opt else \
                                       sync_repository_types.get(opt, NONE),
                           ),
                     Field("url",
                           label="URL",
                           requires = IS_EMPTY_OR(
                                      IS_NOT_IN_DB(db, "sync_repository.url")),
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Repository Base URL"),
                                                T("Base URL of the remote Sahana Eden instance including application path, e.g. http://www.example.org/eden"))),
                           ),
                     Field("username",
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Username"),
                                                T("Username to use for authentication at the remote site."))),
                           ),
                     Field("password", "password",
                           widget = password_widget,
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Password"),
                                                T("Password to use for authentication at the remote site."))),
                           ),
                     Field("client_id",
                           label = T("Client ID"),
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Client ID"),
                                                T("The client ID to use for authentication at the remote site (if required for this type of repository)."))),
                           ),
                     Field("client_secret", "password",
                           widget = password_widget,
                           label = T("Client Secret"),
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Client Secret"),
                                                T("The client secret to use for authentication at the remote site (if required for this type of repository)."))),
                           ),
                     Field("site_key",
                           label = T("Site Key"),
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Site Key"),
                                                T("Site Key which this site uses to authenticate at the remote site (if required for this type of repository)."))),
                           ),
                     Field("refresh_token",
                           readable = False,
                           writable = False,
                           ),
                     Field("proxy",
                           label=T("Proxy Server URL"),
                           requires=IS_EMPTY_OR(IS_URL(mode="generic")),
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Proxy Server URL"),
                                                T("URL of the proxy server to connect to the repository (leave empty for default proxy)"))),
                           ),
                     Field("last_status",
                           readable=False,
                           writable=False,
                           label=T("Last status"),
                           ),
                     Field("accept_push", "boolean",
                           represent = s3_yes_no_represent,
                           default=False,
                           label=T("Accept Push"),
                           comment = DIV(_class="tooltip",
                                         _title="%s|%s" % (
                                                T("Accept Push"),
                                                T("Accept unsolicited data transmissions from the repository."))),
                           ),
                     Field.Method("last_pull_time",
                                  self.sync_repository_last_pull_time),
                     Field.Method("last_push_time",
                                  self.sync_repository_last_push_time),
                     *s3_meta_fields())

        # CRUD Strings
        ADD_REPOSITORY = T("Create Repository")
        crud_strings[tablename] = Storage(
            label_create = ADD_REPOSITORY,
            title_display = T("Repository Configuration"),
            title_list = T("Repositories"),
            title_update = T("Edit Repository Configuration"),
            label_list_button = T("List Repositories"),
            msg_record_created = T("Repository configured"),
            msg_record_modified = T("Repository configuration updated"),
            msg_record_deleted = T("Repository configuration deleted"),
            msg_list_empty = T("No repositories configured"))

        # Resource Configuration
        configure(tablename,
                  list_fields=["name",
                               "uuid",
                               "accept_push",
                               (T("Last Pull"), "last_pull_time"),
                               (T("Last Push"), "last_push_time"),
                               ],
                  onaccept=self.sync_repository_onaccept,
                  ondelete=self.sync_repository_ondelete,
                  create_next=URL(c="sync",
                                  f="repository",
                                  args=["[id]", "task"],
                                  ),
                  update_next=URL(c="sync",
                                  f="repository",
                                  args=["[id]"],
                                  )
                  )

        set_method("sync", "repository", method="now", action=sync_now)

        # Reusable Fields
        repository_id = S3ReusableField("repository_id", "reference %s" % tablename,
                                        requires = IS_ONE_OF(db,
                                                            "sync_repository.id",
                                                            "%(name)s"),
                                        represent = self.sync_repository_represent,
                                        label = T("Repository"))

        # Components
        add_components(tablename,
                       sync_task="repository_id",
                       sync_log="repository_id",
                       #sync_conflict="repository_id",
                       
                       **{# Scheduler Jobs
                          S3Task.TASK_TABLENAME: {"name": "job",
                                                  "joinby": "repository_id",
                                                  "link": "sync_job",
                                                  "key": "scheduler_task_id",
                                                  "actuate": "replace",
                                                 },
                         }
                      )

        # -------------------------------------------------------------------------
        # Task
        # -------------------------------------------------------------------------
        # Synchronization mode
        sync_mode = {
            1: T("pull"),           # pull only
            2: T("push"),           # push only
            3: T("pull and push"),  # pull & push
            4: T("none")            # do not synchronize this resource
        }

        # Strategy (allowed import methods)
        sync_strategy = S3ImportItem.METHOD

        sync_strategy_represent = lambda opt: opt and \
                                    ", ".join([o for o in sync_strategy.values()
                                            if o in opt]) or NONE

        # Update method
        sync_update_method = {
            1: T("update"),         # update the existing record
            2: T("replace"),        # replace the existing record
        }

        # Update/conflict resolution policy
        sync_policies = S3ImportItem.POLICY
        sync_policy = {
            sync_policies.OTHER: T("always update"),
            sync_policies.NEWER: T("update if newer"),
            sync_policies.MASTER: T("update if master"),
            sync_policies.THIS: T("never update")
        }

        sync_policy_represent = lambda opt: \
                                opt and sync_policy.get(opt, UNKNOWN_OPT) or NONE

        tablename = "sync_task"
        define_table(tablename,
                     repository_id(),
                     Field("resource_name",
                           notnull=True),
                     Field("last_pull", "datetime",
                           readable=True,
                           writable=False,
                           label=T("Last pull on")),
                     Field("last_push", "datetime",
                           readable=True,
                           writable=False,
                           label=T("Last push on")),
                     Field("mode", "integer",
                           requires = IS_IN_SET(sync_mode,
                                                zero=None),
                           default = 3,
                           label = T("Mode"),
                           represent = lambda opt: \
                                       sync_mode.get(opt, NONE)),
                     Field("strategy", "list:string",
                           requires = IS_IN_SET(sync_strategy.values(),
                                                multiple=True,
                                                zero=None),
                           default = sync_strategy.values(),
                           label = T("Strategy"),
                           represent = sync_strategy_represent,
                           widget = CheckboxesWidgetS3.widget),
                     Field("update_method", "integer",
                           # hide while not implemented
                           readable=False,
                           writable=False,
                           requires = IS_IN_SET(sync_update_method,
                                                zero=None),
                           default = 1,
                           label = T("Update Method"),
                           represent = lambda opt: \
                                       sync_update_method.get(opt,
                                                              NONE)),
                     Field("update_policy",
                           requires = IS_IN_SET(sync_policies,
                                                zero=None),
                           default = sync_policies.NEWER,
                           label = T("Update Policy"),
                           represent = sync_policy_represent),
                     Field("conflict_policy",
                           requires = IS_IN_SET(sync_policies,
                                                zero=None),
                           default = sync_policies.NEWER,
                           label = T("Conflict Policy"),
                           represent = sync_policy_represent),
                     *s3_meta_fields())

        # Field configuration
        # @todo: make in-line
        table = db[tablename]
        table.resource_name.comment = DIV(_class="tooltip",
                                          _title="%s|%s" % (
                                            T("Resource Name"),
                                            T("Table name of the resource to synchronize")))

        table.mode.comment = DIV(_class="tooltip",
                                 _title="%s|%s" % (
                                    T("Synchronization mode"),
                                    T("How data shall be transferred")))
        table.strategy.comment = DIV(_class="tooltip",
                                     _title="%s|%s" % (
                                        T("Strategy"),
                                        T("Which methods to apply when importing data to the local repository")))
        table.update_method.comment = DIV(_class="tooltip",
                                          _title="%s|%s" % (
                                            T("Update Method"),
                                            T("How local records shall be updated")))
        table.update_policy.comment = DIV(_class="tooltip",
                                          _title="%s|%s" % (
                                            T("Update Policy"),
                                            T("Under which conditions local records shall be updated")))
        table.conflict_policy.comment = DIV(_class="tooltip",
                                            _title="%s|%s" % (
                                                T("Conflict Policy"),
                                                T("Under which condition a local record shall be updated if it also has been modified locally since the last synchronization")))

        # CRUD Strings
        ADD_TASK = T("Create Resource")
        crud_strings[tablename] = Storage(
            label_create = ADD_TASK,
            title_display = T("Resource Configuration"),
            title_list = T("Resources"),
            title_update = T("Edit Resource Configuration"),
            label_list_button = T("List Resources"),
            msg_record_created = T("Resource configured"),
            msg_record_modified = T("Resource configuration updated"),
            msg_record_deleted = T("Resource configuration deleted"),
            msg_list_empty = T("No resources configured yet"))

        # Resource Configuration
        configure(tablename,
                  create_onvalidation=self.sync_task_onvalidation)

        # Reusable Field
        task_represent = self.sync_task_represent
        task_id = S3ReusableField("task_id", "reference %s" % tablename,
                                  requires = IS_ONE_OF(db,
                                                       "sync_task.id",
                                                       task_represent),
                                  represent = task_represent,
                                  label = T("Task"))

        # Components
        add_components(tablename,
                       sync_resource_filter="task_id",
                      )
                      
        # -------------------------------------------------------------------------
        # Filters
        # -------------------------------------------------------------------------
        tablename = "sync_resource_filter"
        define_table(tablename,
                     task_id(),
                     Field("tablename",
                           label = T("Table"),
                           requires = IS_NOT_EMPTY()),
                     Field("filter_string",
                           label = T("Filter"),
                           requires = IS_NOT_EMPTY()),
                     *s3_meta_fields())

        onaccept = self.sync_resource_filter_onaccept
        configure(tablename,
                  list_fields = ["id",
                                 "task_id$repository_id",
                                 "task_id$resource_name",
                                 "tablename",
                                 "filter_string"],
                  onaccept = onaccept,
                  ondelete = onaccept)
                             
        # -------------------------------------------------------------------------
        # Job
        # -------------------------------------------------------------------------
        tablename = "sync_job"
        define_table(tablename,
                     repository_id(),
                     s3.scheduler_task_id(),
                     *s3_meta_fields())

        # CRUD Strings
        ADD_JOB = T("Create Job")
        crud_strings[tablename] = Storage(
            label_create = ADD_JOB,
            title_display = T("Synchronization Job"),
            title_list = T("Synchronization Schedule"),
            title_update = T("Edit Job"),
            label_list_button = T("List Jobs"),
            msg_record_created = T("Job added"),
            msg_record_modified = T("Job updated"),
            msg_record_deleted = T("Job deleted"),
            msg_list_empty = T("No jobs configured yet"),
            msg_no_match = T("No jobs configured"))

        # Resource Configuration
        set_method("sync", "repository",
                   component_name="job",
                   method="reset",
                   action=sync_job_reset)

        # -------------------------------------------------------------------------
        # Log
        # -------------------------------------------------------------------------
        tablename = "sync_log"
        define_table(tablename,
                     Field("timestmp", "datetime",
                           represent=s3_datetime_represent,
                           label=T("Date/Time")),
                     repository_id(),
                     Field("resource_name"),
                     # Synchronization mode: PULL/PUSH, IN/OUT
                     Field("mode"),
                     Field("action"),
                     Field("result"),
                     Field("remote", "boolean",
                           default=False,
                           label=T("Remote Error"),
                           represent=lambda opt: opt and T("yes") or ("no")),
                     Field("message", "text",
                           represent=s3_strip_markup),
                     *s3_meta_fields())

        # CRUD Strings
        crud_strings[tablename] = Storage(
            title_display = T("Log Entry"),
            title_list = T("Synchronization Log"),
            label_list_button = T("List All Entries"),
            msg_record_deleted = T("Log Entry Deleted"),
            msg_list_empty = T("No entries found"),
            msg_no_match = T("No entries found"))

        # Resource Configuration
        configure(tablename,
                  editable=False,
                  insertable=False,
                  deletable=True,
                  orderby="sync_log.timestmp desc")

        # ---------------------------------------------------------------------
        # Return global names to s3.*
        #
        return Storage()
Example #35
0
    def model(self):

        T = current.T
        db = current.db
        auth = current.auth
        s3 = current.response.s3
        settings = current.deployment_settings

        organisation_id = self.org_organisation_id

        ADMIN = current.session.s3.system_roles.ADMIN
        is_admin = auth.s3_has_role(ADMIN)

        add_components = self.add_components
        configure = self.configure
        crud_strings = s3.crud_strings
        define_table = self.define_table

        root_org = auth.root_org()
        if is_admin:
            filter_opts = ()
        elif root_org:
            filter_opts = (root_org, None)
        else:
            filter_opts = (None, )

        types = settings.get_member_membership_types()

        # ---------------------------------------------------------------------
        # Membership Types
        #
        tablename = "member_membership_type"
        define_table(
            tablename,
            Field(
                "name",
                notnull=True,
                length=64,
                label=T("Name"),
                requires=[
                    IS_NOT_EMPTY(),
                    IS_LENGTH(64),
                ],
            ),
            # Only included in order to be able to set
            # realm_entity to filter appropriately
            organisation_id(
                default=root_org,
                readable=is_admin,
                writable=is_admin,
            ),
            s3_comments(
                label=T("Description"),
                comment=None,
            ),
            *s3_meta_fields())

        ADD_MEMBERSHIP_TYPE = T("Create Membership Type")
        crud_strings[tablename] = Storage(
            label_create=ADD_MEMBERSHIP_TYPE,
            title_display=T("Membership Type Details"),
            title_list=T("Membership Types"),
            title_update=T("Edit Membership Type"),
            title_upload=T("Import Membership Types"),
            label_list_button=T("List Membership Types"),
            label_delete_button=T("Delete Membership Type"),
            msg_record_created=T("Membership Type added"),
            msg_record_modified=T("Membership Type updated"),
            msg_record_deleted=T("Membership Type deleted"),
            msg_list_empty=T("No membership types currently registered"))

        represent = S3Represent(lookup=tablename, translate=True)
        membership_type_id = S3ReusableField(
            "membership_type_id",
            "reference %s" % tablename,
            label=T("Type"),
            ondelete="SET NULL",
            readable=types,
            represent=represent,
            requires=IS_EMPTY_OR(
                IS_ONE_OF(db,
                          "member_membership_type.id",
                          represent,
                          filterby="organisation_id",
                          filter_opts=filter_opts)),
            sortby="name",
            writable=types,
            comment=S3PopupLink(
                f="membership_type",
                label=ADD_MEMBERSHIP_TYPE,
                title=ADD_MEMBERSHIP_TYPE,
                tooltip=T("Add a new membership type to the catalog."),
            ),
        )

        configure(
            tablename,
            deduplicate=S3Duplicate(
                primary=(
                    "name",
                    "organisation_id",
                ),
                ignore_deleted=True,
            ),
        )

        # ---------------------------------------------------------------------
        # Members
        #
        tablename = "member_membership"
        define_table(tablename,
                     organisation_id(
                        empty = False,
                        requires = self.org_organisation_requires(
                                        updateable = True,
                                        ),
                        ),
                      Field("code",
                            label = T("Member ID"),
                            #readable = False,
                            #writable = False,
                            ),
                      self.pr_person_id(
                        comment = None,
                        ondelete = "CASCADE",
                        widget = S3AddPersonWidget(controller="member"),
                        empty = False,
                      ),
                      membership_type_id(),
                      # History
                      s3_date("start_date",
                              label = T("Date Joined"),
                              set_min = "#member_membership_end_date",
                              ),
                      s3_date("end_date",
                              label = T("Date Resigned"),
                              set_max = "#member_membership_start_date",
                              start_field = "member_membership_start_date",
                              default_interval = 12,
                              ),
                      Field("leaving_reason",
                            label = T("Reason for Leaving"),
                            # Enable in template as-required
                            readable = False,
                            writable = False,
                            ),
                      s3_date("restart_date",
                              label = T("Date Rejoined"),
                              # Enable in template as-required
                              readable = False,
                              set_max = "#member_membership_end_date",
                              writable = False,
                              ),
                      Field("membership_fee", "double",
                            label = T("Membership Fee"),
                            represent = lambda v: \
                                IS_FLOAT_AMOUNT.represent(v, precision=2),
                            requires = IS_EMPTY_OR(
                                        IS_FLOAT_AMOUNT(minimum=0.0)
                                        ),
                            ),
                      s3_date("membership_paid",
                              label = T("Membership Paid"),
                              ),
                      s3_date("membership_due",
                              label = T("Membership Fee Due Date"),
                              ),
                      Field("fee_exemption", "boolean",
                            label = T("Exempted from Membership Fee"),
                            default = False,
                            # Expose in templates as needed:
                            readable = False,
                            writable = False,
                            ),
                      Field("election",
                            label = T("Participation in the Election as a"),
                            # Expose in templates as needed:
                            readable = False,
                            writable = False,
                            ),
                      Field("trainings",
                            label = T("Trainings"),
                            # Expose in templates as needed:
                            readable = False,
                            writable = False,
                            ),
                      s3_comments(),
                      # Location (from pr_address component)
                      self.gis_location_id(readable = False,
                                           writable = False,
                                           ),
                      Field.Method("paid",
                                   self.member_membership_paid),
                      *s3_meta_fields())

        crud_strings[tablename] = Storage(
            label_create=T("Create Member"),
            title_display=T("Member Details"),
            title_list=T("Members"),
            title_update=T("Edit Member"),
            title_upload=T("Import Members"),
            label_list_button=T("List Members"),
            label_delete_button=T("Delete Member"),
            msg_record_created=T("Member added"),
            msg_record_modified=T("Member updated"),
            msg_record_deleted=T("Member deleted"),
            msg_list_empty=T("No Members currently registered"))

        # Which levels of Hierarchy are we using?
        levels = current.gis.get_relevant_hierarchy_levels()

        list_fields = [
            "person_id",
            "organisation_id",
        ]
        if types:
            list_fields.append("membership_type_id")
        list_fields += [
            "start_date",
            #"membership_paid",
            (T("Paid"), "paid"),
            (T("Email"), "email.value"),
            (T("Phone"), "phone.value"),
        ]

        report_fields = [
            "organisation_id",
            "person_id",
        ]
        if types:
            report_fields.append("membership_type_id")
            default_col = "membership.membership_type_id"
        else:
            default_col = "membership.paid"
        report_fields.append((T("Paid"), "paid"))

        text_fields = [
            "organisation_id$name",
            "organisation_id$acronym",
            "person_id$first_name",
            "person_id$middle_name",
            "person_id$last_name",
        ]
        if types:
            text_fields.append("membership_type_id")

        for level in levels:
            lfield = "location_id$%s" % level
            list_fields.append(lfield)
            report_fields.append(lfield)
            text_fields.append(lfield)

        if settings.get_org_branches():
            org_filter = S3HierarchyFilter(
                "organisation_id",
                # Can be unhidden in customise_xx_resource if there is a need to use a default_filter
                hidden=True,
                leafonly=False,
            )
            report_fields.insert(1,
                                 (settings.get_hrm_root_organisation_label(),
                                  "organisation_id$root_organisation"))
        else:
            org_filter = S3OptionsFilter(
                "organisation_id",
                search=True,
                header="",
                # Can be unhidden in customise_xx_resource if there is a need to use a default_filter
                hidden=True,
            )

        filter_widgets = [
            S3TextFilter(
                text_fields,
                label=T("Search"),
            ),
            org_filter,
        ]
        if types:
            filter_widgets.append(
                S3OptionsFilter(
                    "membership_type_id",
                    cols=3,
                    hidden=True,
                ))
        filter_widgets += [
            S3OptionsFilter(
                "paid",
                cols=3,
                label=T("Paid"),
                options={
                    T("paid"): T("paid"),
                    T("overdue"): T("overdue"),
                    T("expired"): T("expired"),
                    #T("exempted"): T("exempted"),
                },
                hidden=True,
            ),
            S3LocationFilter(
                "location_id",
                label=T("Location"),
                levels=levels,
                hidden=True,
            ),
        ]

        report_options = Storage(rows=report_fields,
                                 cols=report_fields,
                                 facts=report_fields,
                                 defaults=Storage(
                                     cols=default_col,
                                     rows="membership.organisation_id",
                                     fact="count(membership.person_id)",
                                     totals=True,
                                 ))

        configure(
            tablename,
            create_next=URL(f="person",
                            args="address",
                            vars={"membership.id": "[id]"}),
            deduplicate=S3Duplicate(
                primary=(
                    "person_id",
                    "organisation_id",
                ),
                ignore_deleted=True,
            ),
            extra_fields=(
                "start_date",
                "membership_paid",
                "fee_exemption",
            ),
            filter_widgets=filter_widgets,
            list_fields=list_fields,
            onaccept=self.member_onaccept,
            report_options=report_options,
            # Default summary
            summary=[
                {
                    "name": "addform",
                    "common": True,
                    "widgets": [{
                        "method": "create"
                    }],
                },
                {
                    "name": "table",
                    "label": "Table",
                    "widgets": [{
                        "method": "datatable"
                    }]
                },
                {
                    "name": "report",
                    "label": "Report",
                    "widgets": [{
                        "method": "report",
                        "ajax_init": True
                    }]
                },
                {
                    "name": "map",
                    "label": "Map",
                    "widgets": [{
                        "method": "map",
                        "ajax_init": True
                    }],
                },
            ],
            update_realm=True,
        )

        # Components
        self.add_components(
            tablename,
            # Contact Information
            pr_contact=(  # Email
                {
                    "name": "email",
                    "link": "pr_person",
                    "joinby": "id",
                    "key": "pe_id",
                    "fkey": "pe_id",
                    "pkey": "person_id",
                    "filterby": {
                        "contact_method": "EMAIL",
                    },
                },
                # Phone
                {
                    "name": "phone",
                    "link": "pr_person",
                    "joinby": "id",
                    "key": "pe_id",
                    "fkey": "pe_id",
                    "pkey": "person_id",
                    "filterby": {
                        "contact_method": (
                            "SMS",
                            "HOME_PHONE",
                            "WORK_PHONE",
                        ),
                    },
                },
            ),
            hrm_programme={
                "link": "member_membership_programme",
                "joinby": "membership_id",
                "key": "programme_id",
            },
        )

        represent = S3Represent(lookup=tablename, fields=["code"])
        membership_id = S3ReusableField(
            "membership_id",
            "reference %s" % tablename,
            label=T("Member"),
            ondelete="CASCADE",
            represent=represent,
            requires=IS_ONE_OF(
                db,
                "member_membership.id",
                represent,
            ),
        )

        # ---------------------------------------------------------------------
        # Pass names back to global scope (s3.*)
        #
        return dict(member_membership_id=membership_id)
Example #36
0
    def configure_tasktable_crud(self,
                                 task=None,
                                 function=None,
                                 args=[],
                                 vars={}):
        """
            Configure the task table for interactive CRUD,
            setting defaults, widgets and hiding unnecessary fields

            @param task: the task name (will use a UUID if omitted)
            @param function: the function name (won't hide if omitted)
            @param args: the function position arguments
            @param vars: the function named arguments
        """

        T = current.T

        db = current.db
        tablename = self.TASK_TABLENAME
        table = db[tablename]

        if not task:
            import uuid
            task = str(uuid.uuid4())
        table.task_name.default = task
        table.task_name.readable = False
        table.task_name.writable = False

        if function:
            table.function_name.default = function
            table.function_name.readable = False
            table.function_name.writable = False

        table.args.default = json.dumps(args)
        table.args.readable = False
        table.args.writable = False

        table.repeats.label = T("Repeat")
        table.repeats.comment = T("times (0 = unlimited)")
        table.repeats.default = 0
        table.repeats.represent = lambda opt: opt and "%s %s" % (opt, T("times")) or \
                                              opt == 0 and T("unlimited") or \
                                              "-"

        table.period.label = T("Run every")
        table.period.widget = S3TimeIntervalWidget.widget
        table.period.requires = IS_TIME_INTERVAL_WIDGET(table.period)
        table.period.represent = S3TimeIntervalWidget.represent
        table.period.comment = None

        table.timeout.default = 600
        table.timeout.represent = lambda opt: opt and "%s %s" % (opt, T("seconds")) or \
                                              opt == 0 and T("unlimited") or \
                                              "-"

        table.vars.default = json.dumps(vars)
        table.vars.readable = False
        table.vars.writable = False

        table.application_name.readable = False
        table.application_name.writable = False

        table.group_name.readable = False
        table.group_name.writable = False

        table.status.readable = False
        table.status.writable = False

        table.next_run_time.readable = False
        table.next_run_time.writable = False

        table.times_run.readable = False
        table.times_run.writable = False

        table.assigned_worker_name.readable = False
        table.assigned_worker_name.writable = False

        current.s3db.configure(tablename,
                               list_fields=[
                                   "id", "enabled", "start_time", "repeats",
                                   "period", (T("Last run"), "last_run_time"),
                                   (T("Last status"), "status"),
                                   (T("Next run"), "next_run_time"),
                                   "stop_time"
                               ])

        response = current.response
        if response:
            response.s3.crud_strings[tablename] = Storage(
                title_create=T("Add Job"),
                title_display=T("Scheduled Jobs"),
                title_list=T("Job Schedule"),
                title_update=T("Edit Job"),
                title_search=T("Search for Job"),
                subtitle_create=T("Add Job"),
                label_list_button=T("List Jobs"),
                label_create_button=T("Add Job"),
                msg_record_created=T("Job added"),
                msg_record_modified=T("Job updated updated"),
                msg_record_deleted=T("Job deleted"),
                msg_list_empty=T("No jobs configured yet"),
                msg_no_match=T("No jobs configured"))

        return
Example #37
0
    def model(self):

        T = current.T
        db = current.db
        request = current.request
        s3 = current.response.s3
        settings = current.deployment_settings

        currency_type = s3.currency_type
        person_id = self.pr_person_id
        location_id = self.gis_location_id
        organisation_id = self.org_organisation_id
        human_resource_id = self.hrm_human_resource_id

        UNKNOWN_OPT = current.messages.UNKNOWN_OPT

        s3_date_format = settings.get_L10n_date_format()
        s3_datetime_represent = lambda dt: S3DateTime.datetime_represent(dt, utc=True)
        s3_date_represent = lambda dt: S3DateTime.date_represent(dt, utc=True)

        super_link = self.super_link
        define_table = self.define_table
        configure = self.configure
        add_component = self.add_component

        # ---------------------------------------------------------------------
        # Hospitals
        #

        # Use government-assigned UUIDs instead of internal UUIDs
        HMS_HOSPITAL_USE_GOVUUID = True

        hms_facility_type_opts = {
            1: T("Hospital"),
            2: T("Field Hospital"),
            3: T("Specialized Hospital"),
            11: T("Health center"),
            12: T("Health center with beds"),
            13: T("Health center without beds"),
            21: T("Dispensary"),
            98: T("Other"),
            99: T("Unknown type of facility"),
        } #: Facility Type Options

        hms_facility_status_opts = {
            1: T("Normal"),
            2: T("Compromised"),
            3: T("Evacuating"),
            4: T("Closed")
        } #: Facility Status Options

        hms_clinical_status_opts = {
            1: T("Normal"),
            2: T("Full"),
            3: T("Closed")
        } #: Clinical Status Options

        hms_morgue_status_opts = {
            1: T("Open"),
            2: T("Full"),
            3: T("Exceeded"),
            4: T("Closed")
        } #: Morgue Status Options

        hms_security_status_opts = {
            1: T("Normal"),
            2: T("Elevated"),
            3: T("Restricted Access"),
            4: T("Lockdown"),
            5: T("Quarantine"),
            6: T("Closed")
        } #: Security Status Options

        hms_resource_status_opts = {
            1: T("Adequate"),
            2: T("Insufficient")
        } #: Resource Status Options

        hms_ems_traffic_opts = {
            1: T("Normal"),
            2: T("Advisory"),
            3: T("Closed"),
            4: T("Not Applicable")
        } #: EMS Traffic Options

        hms_or_status_opts = {
            1: T("Normal"),
            #2: T("Advisory"),
            3: T("Closed"),
            4: T("Not Applicable")
        } #: Operating Room Status Options

        tablename = "hms_hospital"
        table = define_table(tablename,
                             super_link("doc_id", "doc_entity"),
                             super_link("pe_id", "pr_pentity"),
                             super_link("site_id", "org_site"),
                             Field("paho_uuid",
                                   unique=True,
                                   length=128,
                                   requires = IS_NULL_OR(IS_NOT_ONE_OF(db,
                                                "%s.paho_uuid" % tablename)),
                                   label = T("PAHO UID")),

                             # UID assigned by Local Government
                             Field("gov_uuid",
                                   unique=True,
                                   length=128,
                                   requires = IS_NULL_OR(IS_NOT_ONE_OF(db,
                                                "%s.gov_uuid" % tablename)),
                                   label = T("Government UID")),

                             # Alternate ids found in data feeds
                             Field("other_ids",
                                   length=128),

                             # Mayon compatibility
                             #Field("code",
                             #      length=10,
                             #      notnull=True,
                             #      unique=True, label=T("Code")),

                             # Name of the facility
                             Field("name",
                                   notnull=True,
                                   length=64, # Mayon compatibility
                                   label = T("Name")),

                             # Alternate name, or name in local language
                             Field("aka1", label = T("Other Name")),

                             # Alternate name, or name in local language
                             Field("aka2",label = T("Other Name")),

                             Field("facility_type", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                hms_facility_type_opts)),
                                   default = 1,
                                   label = T("Facility Type"),
                                   represent = lambda opt: \
                                               hms_facility_type_opts.get(opt,
                                                        T("not specified"))),
                             organisation_id(),
                             location_id(),

                             # Address fields:
                             # @todo: Deprecate these & use location_id in HAVE export
                             Field("address",
                                   label = T("Address")),
                             Field("postcode",
                                   label = settings.get_ui_label_postcode()),
                             Field("city"),

                             Field("phone_exchange",
                                   label = T("Phone/Exchange (Switchboard)"),
                                   requires = IS_NULL_OR(s3_phone_requires)),

                             Field("phone_business",
                                   label = T("Phone/Business"),
                                   requires = IS_NULL_OR(s3_phone_requires)),
                             Field("phone_emergency",
                                   label = T("Phone/Emergency"),
                                   requires = IS_NULL_OR(s3_phone_requires)),
                             Field("website",
                                   label=T("Website"),
                                   requires = IS_NULL_OR(IS_URL()),
                                   represent = s3_url_represent),
                             Field("email",
                                   label = T("Email"),
                                   requires = IS_NULL_OR(IS_EMAIL())),
                             Field("fax",
                                   label = T("Fax"),
                                   requires = IS_NULL_OR(s3_phone_requires)),
                             Field("total_beds", "integer",
                                   readable = False,
                                   writable = False,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   label = T("Total Beds")),
                             Field("available_beds", "integer",
                                   readable = False,
                                   writable = False,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   label = T("Available Beds")),

                             # Emergency Room Status
                             Field("ems_status", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_ems_traffic_opts)),
                                   label = T("ER Status"),
                                   represent = lambda opt: \
                                               hms_ems_traffic_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             # Reason for EMS Status
                             Field("ems_reason",
                                   length=128,
                                   label = T("ER Status Reason")),
                             # Operating Room Status
                             Field("or_status", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                        hms_or_status_opts)),
                                   label = T("OR Status"),
                                   represent = lambda opt: \
                                               hms_or_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             # Reason for OR Status
                             Field("or_reason",
                                   length=128,
                                   label = T("OR Status Reason")),

                             Field("facility_status", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_facility_status_opts)),
                                   label = T("Facility Status"),
                                   represent = lambda opt: \
                                               hms_facility_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             Field("clinical_status", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_clinical_status_opts)),
                                   label = T("Clinical Status"),
                                   represent = lambda opt: \
                                               hms_clinical_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             Field("morgue_status", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_morgue_status_opts)),
                                   label = T("Morgue Status"),
                                   represent = lambda opt: \
                                               hms_clinical_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             # Number of available/vacant morgue units
                             Field("morgue_units", "integer",
                                   requires = IS_NULL_OR(
                                                IS_INT_IN_RANGE(0, 9999)),
                                   label = T("Morgue Units Available"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("security_status", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_security_status_opts)),
                                   label = T("Security Status"),
                                   represent = lambda opt: \
                                               hms_security_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             Field("doctors", "integer",
                                   label = T("Number of doctors"),
                                   requires = IS_NULL_OR(
                                                IS_INT_IN_RANGE(0, 9999)),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("nurses", "integer",
                                   label = T("Number of nurses"),
                                   requires = IS_NULL_OR(
                                                IS_INT_IN_RANGE(0, 9999)),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("non_medical_staff", "integer",
                                   requires = IS_NULL_OR(
                                                IS_INT_IN_RANGE(0, 9999)),
                                   label = T("Number of non-medical staff"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             # Staffing status
                             Field("staffing", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_resource_status_opts)),
                                   label = T("Staffing"),
                                   represent = lambda opt: \
                                               hms_resource_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             # Facility Operations Status
                             Field("facility_operations", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_resource_status_opts)),
                                   label = T("Facility Operations"),
                                   represent = lambda opt: \
                                               hms_resource_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             # Clinical Operations Status
                             Field("clinical_operations", "integer",
                                   requires = IS_NULL_OR(IS_IN_SET(
                                                    hms_resource_status_opts)),
                                   label = T("Clinical Operations"),
                                   represent = lambda opt: \
                                               hms_resource_status_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             Field("access_status",
                                   label = T("Road Conditions")),

                             s3.comments(),
                             *s3.meta_fields())

        # CRUD Strings
        ADD_HOSPITAL = T("Add Hospital")
        s3.crud_strings[tablename] = Storage(
            title_create = ADD_HOSPITAL,
            title_display = T("Hospital Details"),
            title_list = T("Hospitals"),
            title_update = T("Edit Hospital"),
            title_search = T("Find Hospital"),
            title_map = T("Map of Hospitals"),
            subtitle_create = T("Add New Hospital"),
            label_list_button = T("List Hospitals"),
            label_create_button = ADD_HOSPITAL,
            label_delete_button = T("Delete Hospital"),
            msg_record_created = T("Hospital information added"),
            msg_record_modified = T("Hospital information updated"),
            msg_record_deleted = T("Hospital information deleted"),
            msg_list_empty = T("No Hospitals currently registered"))

        # Search method
        hms_hospital_search = S3Search(
            #name="hospital_search_simple",
            #label=T("Name and/or ID"),
            #comment=T("To search for a hospital, enter any of the names or IDs of the hospital, separated by spaces. You may use % as wildcard. Press 'Search' without input to list all hospitals."),
            #field=["gov_uuid", "name", "aka1", "aka2"],
            advanced=(S3SearchSimpleWidget(
                        name="hospital_search_advanced",
                        label=T("Name, Org and/or ID"),
                        comment=T("To search for a hospital, enter any of the names or IDs of the hospital, or the organisation name or acronym, separated by spaces. You may use % as wildcard. Press 'Search' without input to list all hospitals."),
                        field=["gov_uuid", "name", "aka1", "aka2",
                            "organisation_id$name", "organisation_id$acronym"]
                      ),
                      # for testing:
                      S3SearchOptionsWidget(
                        name="hospital_facility_type",
                        label=T("Facility Type"),
                        field="facility_type"
                      ),
                      # for testing:
                      S3SearchMinMaxWidget(
                        name="hospital_search_bedcount",
                        method="range",
                        label=T("Total Beds"),
                        comment=T("Select a range for the number of total beds"),
                        field="total_beds"
                      ),
                    ))

        # Resource configuration
        configure(tablename,
                  super_entity=("org_site", "doc_entity", "pr_pentity"),
                  search_method=hms_hospital_search,
                  list_fields=["id",
                               "gov_uuid",
                               "name",
                               "facility_type",
                               "organisation_id",
                               "location_id",
                               "phone_exchange",
                               "ems_status",
                               "facility_status",
                               "clinical_status",
                               "security_status",
                               "total_beds",
                               "available_beds"])

        # Reusable field
        hms_hospital_id_comment = S3AddResourceLink(c="hms",
                                                    f="hospital",
                                                    label=ADD_HOSPITAL,
                                                    title=T("Hospital"),
                                                    tooltip=T("If you don't see the Hospital in the list, you can add a new one by clicking link 'Add Hospital'."))

        hospital_id = S3ReusableField("hospital_id", db.hms_hospital,
                                      sortby="name",
                                      requires = IS_NULL_OR(IS_ONE_OF(db, "hms_hospital.id", "%(name)s")),
                                      represent = lambda id: \
                                                  (id and [db(db.hms_hospital.id == id).select(db.hms_hospital.name,
                                                                                               limitby=(0, 1)).first().name] or ["None"])[0],
                                      label = T("Hospital"),
                                      comment = hms_hospital_id_comment,
                                      ondelete = "RESTRICT")

        # Components
        single = dict(joinby="hospital_id", multiple=False)
        multiple = "hospital_id"

        add_component("hms_contact", hms_hospital=multiple)
        add_component("hms_bed_capacity", hms_hospital=multiple)
        add_component("hms_activity", hms_hospital=multiple)
        add_component("hms_services", hms_hospital=single)
        add_component("hms_ctc_capability", hms_hospital=single)
        add_component("hms_resources", hms_hospital=multiple)

        # ---------------------------------------------------------------------
        # Contacts
        #
        tablename = "hms_contact"
        table = define_table(tablename,
                             hospital_id(ondelete="CASCADE"),
                             person_id(label = T("Contact"),
                                       requires = IS_ONE_OF(db, "pr_person.id",
                                                            self.pr_person_represent,
                                                            orderby="pr_person.first_name",
                                                            sort=True)),
                              Field("title", label = T("Job Title")),
                              Field("phone", label = T("Phone"),
                                    requires = IS_NULL_OR(s3_phone_requires)),
                              Field("mobile", label = T("Mobile"),
                                    requires = IS_NULL_OR(s3_phone_requires)),
                              Field("email", label = T("Email"),
                                    requires = IS_NULL_OR(IS_EMAIL())),
                              Field("fax", label = T("Fax"),
                                    requires = IS_NULL_OR(s3_phone_requires)),
                              Field("skype", label = T("Skype ID")),
                              Field("website", label=T("Website")),
                              *s3.meta_fields())

        # CRUD Strings
        s3.crud_strings[tablename] = Storage(
            title_create = T("Add Contact"),
            title_display = T("Contact Details"),
            title_list = T("Contacts"),
            title_update = T("Edit Contact"),
            title_search = T("Search Contacts"),
            subtitle_create = T("Add New Contact"),
            label_list_button = T("List Contacts"),
            label_create_button = T("Add Contact"),
            msg_record_created = T("Contact information added"),
            msg_record_modified = T("Contact information updated"),
            msg_record_deleted = T("Contact information deleted"),
            msg_list_empty = T("No contacts currently registered"))

        # Resource configuration
        configure(tablename,
                  mark_required = ["person_id"],
                  list_fields=["id",
                               "person_id",
                               "title",
                               "phone",
                               "mobile",
                               "email",
                               "fax",
                               "skype"],
                  main="person_id",
                  extra="title")

        # ---------------------------------------------------------------------
        # Activity
        #
        tablename = "hms_activity"
        table = define_table(tablename,
                             hospital_id(ondelete="CASCADE"),
                             Field("date", "datetime", unique=True,  # Date&Time the entry applies to
                                   requires = IS_UTC_DATETIME(allow_future=False),
                                   represent = s3_datetime_represent,
                                   widget = S3DateTimeWidget(future=0),
                                   label = T("Date & Time")),
                             Field("patients", "integer",            # Current Number of Patients
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   default = 0,
                                   label = T("Number of Patients"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("admissions24", "integer",        # Admissions in the past 24 hours
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   default = 0,
                                   label = T("Admissions/24hrs"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("discharges24", "integer",        # Discharges in the past 24 hours
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   default = 0,
                                   label = T("Discharges/24hrs"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("deaths24", "integer",            # Deaths in the past 24 hours
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   default = 0,
                                   label = T("Deaths/24hrs"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("comment", length=128),
                             *s3.meta_fields())

        # CRUD Strings
        s3.crud_strings[tablename] = Storage(
            title_create = T("Add Activity Report"),
            title_display = T("Activity Report"),
            title_list = T("Activity Reports"),
            title_update = T("Update Activity Report"),
            title_search = T("Search Activity Report"),
            subtitle_create = T("Add Activity Report"),
            label_list_button = T("List Activity Reports"),
            label_create_button = T("Add Report"),
            label_delete_button = T("Delete Report"),
            msg_record_created = T("Report added"),
            msg_record_modified = T("Report updated"),
            msg_record_deleted = T("Report deleted"),
            msg_list_empty = T("No reports currently available"))

        # Resource configuration
        configure(tablename,
                  onaccept = self.hms_activity_onaccept,
                  list_fields=["id",
                               "date",
                               "patients",
                               "admissions24",
                               "discharges24",
                               "deaths24",
                               "comment"],
                  main="hospital_id",
                  extra="id")

        # ---------------------------------------------------------------------
        # Bed Capacity
        #
        hms_bed_type_opts = {
            1: T("Adult ICU"),
            2: T("Pediatric ICU"),
            3: T("Neonatal ICU"),
            4: T("Emergency Department"),
            5: T("Nursery Beds"),
            6: T("General Medical/Surgical"),
            7: T("Rehabilitation/Long Term Care"),
            8: T("Burn ICU"),
            9: T("Pediatrics"),
            10: T("Adult Psychiatric"),
            11: T("Pediatric Psychiatric"),
            12: T("Negative Flow Isolation"),
            13: T("Other Isolation"),
            14: T("Operating Rooms"),
            15: T("Cholera Treatment"),
            99: T("Other")
        }

        tablename = "hms_bed_capacity"
        table = define_table(tablename,
                             hospital_id(ondelete="CASCADE"),
                             Field("unit_id", length=128, unique=True,
                                   readable=False,
                                   writable=False),
                             Field("bed_type", "integer",
                                   requires = IS_IN_SET(hms_bed_type_opts,
                                                        zero=None),
                                   default = 6,
                                   label = T("Bed Type"),
                                   represent = lambda opt: \
                                               hms_bed_type_opts.get(opt,
                                                                UNKNOWN_OPT)),
                             Field("date", "datetime",
                                   requires = IS_UTC_DATETIME(allow_future=False),
                                   represent = s3_datetime_represent,
                                   widget = S3DateTimeWidget(future=0),
                                   label = T("Date of Report")),
                             Field("beds_baseline", "integer",
                                   default = 0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   label = T("Baseline Number of Beds"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("beds_available", "integer",
                                   default = 0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   label = T("Available Beds"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("beds_add24", "integer",
                                   default = 0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 9999)),
                                   label = T("Additional Beds / 24hrs"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             s3.comments(),
                             *s3.meta_fields())

        # Field configuration
        # CRUD Strings
        s3.crud_strings[tablename] = Storage(
            title_create = T("Add Bed Type"),
            title_display = T("Bed Capacity"),
            title_list = T("Bed Capacity"),
            title_update = T("Update Unit"),
            title_search = T("Search Units"),
            subtitle_create = T("Add Unit"),
            label_list_button = T("List Units"),
            label_create_button = T("Add Unit"),
            label_delete_button = T("Delete Unit"),
            msg_record_created = T("Unit added"),
            msg_record_modified = T("Unit updated"),
            msg_record_deleted = T("Unit deleted"),
            msg_list_empty = T("No units currently registered"))

        # Resource configuration
        configure(tablename,
                  onvalidation = self.hms_bed_capacity_onvalidation,
                  onaccept = self.hms_bed_capacity_onaccept,
                  ondelete = self.hms_bed_capacity_onaccept,
                  list_fields=["id",
                               "unit_name",
                               "bed_type",
                               "date",
                               "beds_baseline",
                               "beds_available",
                               "beds_add24"],
                  main="hospital_id",
                  extra="id")

        # ---------------------------------------------------------------------
        # Services
        #
        tablename = "hms_services"
        table = define_table(tablename,
                             hospital_id(ondelete="CASCADE"),
                             Field("burn", "boolean", default=False,
                                   label = T("Burn")),
                             Field("card", "boolean", default=False,
                                   label = T("Cardiology")),
                             Field("dial", "boolean", default=False,
                                   label = T("Dialysis")),
                             Field("emsd", "boolean", default=False,
                                   label = T("Emergency Department")),
                             Field("infd", "boolean", default=False,
                                   label = T("Infectious Diseases")),
                             Field("neon", "boolean", default=False,
                                   label = T("Neonatology")),
                             Field("neur", "boolean", default=False,
                                   label = T("Neurology")),
                             Field("pedi", "boolean", default=False,
                                   label = T("Pediatrics")),
                             Field("surg", "boolean", default=False,
                                   label = T("Surgery")),
                             Field("labs", "boolean", default=False,
                                   label = T("Clinical Laboratory")),
                             Field("tran", "boolean", default=False,
                                   label = T("Ambulance Service")),
                             Field("tair", "boolean", default=False,
                                   label = T("Air Transport Service")),
                             Field("trac", "boolean", default=False,
                                   label = T("Trauma Center")),
                             Field("psya", "boolean", default=False,
                                   label = T("Psychiatrics/Adult")),
                             Field("psyp", "boolean", default=False,
                                   label = T("Psychiatrics/Pediatric")),
                             Field("obgy", "boolean", default=False,
                                   label = T("Obstetrics/Gynecology")),
                             *s3.meta_fields())

        # CRUD Strings
        s3.crud_strings[tablename] = Storage(
            title_create = T("Add Service Profile"),
            title_display = T("Services Available"),
            title_list = T("Services Available"),
            title_update = T("Update Service Profile"),
            title_search = T("Search Service Profiles"),
            subtitle_create = T("Add Service Profile"),
            label_list_button = T("List Service Profiles"),
            label_create_button = T("Add Service Profile"),
            label_delete_button = T("Delete Service Profile"),
            msg_record_created = T("Service profile added"),
            msg_record_modified = T("Service profile updated"),
            msg_record_deleted = T("Service profile deleted"),
            msg_list_empty = T("No service profile available"))

        # Resource configuration
        configure(tablename,
                  list_fields = ["id"],
                  main="hospital_id",
                  extra="id")

        # ---------------------------------------------------------------------
        # Cholera Treatment Capability
        #
        hms_problem_types = {
            1: T("Security problems"),
            2: T("Hygiene problems"),
            3: T("Sanitation problems"),
            4: T("Improper handling of dead bodies"),
            5: T("Improper decontamination"),
            6: T("Understaffed"),
            7: T("Lack of material"),
            8: T("Communication problems"),
            9: T("Information gaps")
        }

        tablename = "hms_ctc_capability"
        table = define_table(tablename,
                             hospital_id(ondelete="CASCADE"),
                             Field("ctc", "boolean", default=False,
                                   represent = lambda opt: \
                                               opt and T("yes") or T("no"),
                                   label = T("Cholera-Treatment-Center")),
                             Field("number_of_patients", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 999999)),
                                   label = T("Current number of patients"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("cases_24", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 999999)),
                                   label = T("New cases in the past 24h"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("deaths_24", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 999999)),
                                   label = T("Deaths in the past 24h"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             #Field("staff_total", "integer", default=0),
                             Field("icaths_available", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 99999999)),
                                   label = T("Infusion catheters available"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("icaths_needed_24", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 99999999)),
                                   label = T("Infusion catheters needed per 24h"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("infusions_available", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 99999999)),
                                   label = T("Infusions available"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("infusions_needed_24", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 99999999)),
                                   label = T("Infusions needed per 24h"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             #Field("infset_available", "integer", default=0),
                             #Field("infset_needed_24", "integer", default=0),
                             Field("antibiotics_available", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 99999999)),
                                   label = T("Antibiotics available"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("antibiotics_needed_24", "integer", default=0,
                                   requires = IS_NULL_OR(IS_INT_IN_RANGE(0, 99999999)),
                                   label = T("Antibiotics needed per 24h"),
                                   represent = lambda v, row=None: IS_INT_AMOUNT.represent(v)),
                             Field("problem_types", "list:integer",
                                   requires = IS_EMPTY_OR(IS_IN_SET(hms_problem_types,
                                                                    zero=None,
                                                                    multiple=True)),
                                   represent = lambda optlist: \
                                               optlist and ", ".join(map(str,optlist)) or T("N/A"),
                                   label = T("Current problems, categories")),
                             Field("problem_details", "text",
                                   label = T("Current problems, details")),
                             s3.comments(),
                             *s3.meta_fields())

        # Field configuration
        table.modified_on.label = T("Last updated on")
        table.modified_on.readable = True
        table.modified_by.label = T("Last updated by")
        table.modified_by.readable = True

        # CRUD Strings
        s3.crud_strings[tablename] = Storage(
            title_create = T("Add Cholera Treatment Capability Information"),
            title_display = T("Cholera Treatment Capability"),
            title_list = T("Cholera Treatment Capability"),
            title_update = T("Update Cholera Treatment Capability Information"),
            title_search = T("Search Status"),
            subtitle_create = T("Add Status"),
            label_list_button = T("List Statuses"),
            label_create_button = T("Add Status"),
            label_delete_button = T("Delete Status"),
            msg_record_created = T("Status added"),
            msg_record_modified = T("Status updated"),
            msg_record_deleted = T("Status deleted"),
            msg_list_empty = T("No status information available"))

        # Resource configuration
        configure(tablename,
                  list_fields = ["id"],
                  subheadings = {
                        "Activities": "ctc",
                        "Medical Supplies Availability": "icaths_available",
                        "Current Problems": "problem_types",
                        "Comments": "comments"
                  })

        # ---------------------------------------------------------------------
        # Resources (multiple) - @todo: to be completed!
        #
        tablename = "hms_resources"
        table = define_table(tablename,
                             hospital_id(ondelete="CASCADE"),
                             Field("type"),
                             Field("description"),
                             Field("quantity"),
                             s3.comments(),
                             *s3.meta_fields())

        # CRUD Strings
        s3.crud_strings[tablename] = Storage(
            title_create = T("Report Resource"),
            title_display = T("Resource Details"),
            title_list = T("Resources"),
            title_update = T("Edit Resource"),
            title_search = T("Search Resources"),
            subtitle_create = T("Add New Resource"),
            label_list_button = T("List Resources"),
            label_create_button = T("Add Resource"),
            label_delete_button = T("Delete Resource"),
            msg_record_created = T("Resource added"),
            msg_record_modified = T("Resource updated"),
            msg_record_deleted = T("Resource deleted"),
            msg_list_empty = T("No resources currently reported"))

        # Resource configuration
        configure(tablename,
                  list_fields=["id"],
                  main="hospital_id",
                  extra="id")

        # ---------------------------------------------------------------------
        # Return global names to s3db
        #
        return Storage(hms_hospital_id=hospital_id)
Example #38
0
    def defaults(self):
        """ Safe defaults if the module is disabled """

        return Storage()
Example #39
0
# Uncomment this to enable `auto-reloading
# <http://web2py.com/books/default/chapter/29/04/the-core?search=import+module#Sharing-the-global-scope-with-modules-using-the-current-object>`_
# of code in the ``modules/`` subdirectory. This is helpful when doing
# development; otherwise, the web2py server must be restarted to reload any
# changes made to ``modules/``.
#from gluon.custom_import import track_changes; track_changes(True)

from gluon.storage import Storage
import logging
from os import environ

settings = Storage()

settings.migrate = True
settings.migprefix = 'runestonebeta_'
settings.title = 'Runestone Interactive'
settings.subtitle = 'eBooks for Python'
settings.author = 'Brad Miller'
settings.author_email = '*****@*****.**'
settings.keywords = ''
settings.description = ''
settings.layout_theme = 'Default'
settings.security_key = '0b734ebc-7a50-4167-99b1-2df09062fde8'
settings.email_server = 'smtp.webfaction.com'
settings.email_sender = '*****@*****.**'
settings.email_login = '******'
settings.login_method = 'local'
settings.login_config = ''
settings.course_id = 'devcourse'
settings.plugins = []
settings.server_type = "http://"
Example #40
0
##--------------------------------------#
"""

import socket
import platform
import os

try:
    import yaml
    from yaml.parser import ParserError
except ImportError:
    raise ImportError('PyYAML required. Please install it before continuing')

from gluon.storage import Storage

settings = Storage()

settings.kvasir_config = {}
kv_cfg_filename = os.path.join(os.environ.get('HOME'), '.kvasir',
                               'kvasir.yaml')
try:
    settings.kvasir_config = yaml.load(open(kv_cfg_filename, 'r'))
except IOError as e:
    kv_cfg_filename = os.environ.get('KVASIR_CONFIG', 'kvasir.yaml')
    try:
        settings.kvasir_config = yaml.load(open(kv_cfg_filename, 'r'))
    except IOError as e:
        kv_cfg_filename = os.path.join('applications', request.application,
                                       'kvasir.yaml')
        try:
            settings.kvasir_config = yaml.load(open(kv_cfg_filename, 'r'))
Example #41
0
                                           use_username=True,
                                           reset_password=False,
                                           register=True)
if db(db.auth_user.id > 0).count() > 0:
    auth.settings.actions_disabled.append('register')

response.ns_menu = create_menu()
ui.control.create_cmd(response, T, "b")

_editable = True
if session.auth:
    if session.auth.user.has_key("username"):
        if session.auth.user.username == "demo":
            _editable = False
            if request.post_vars:
                request.post_vars = Storage()
                response.flash = T("Demo user: This action is not allowed!")
    else:
        _editable = True


@auth.requires(session.alias == 'nas_admin', requires_login=True)
def index():
    response.view = 'nas/index.html'
    response.subtitle = T("Home")
    gform = DIV(
        P("Nervatura NAS Admin", _style="font-weight: bold;"),
        P(SPAN(T("Username: "******"font-weight: bold;"),
          session.auth.user.username),
        P(SPAN("Ver.No: " + response.verNo, _class="vernum")),
        TABLE(
Example #42
0
    def __call__(self):

        T = current.T
        response = current.response

        response.title = current.deployment_settings.get_system_name()
        view = path.join(current.request.folder, "private", "templates",
                         "IFRC", "views", "index.html")
        try:
            # Pass view as file not str to work in compiled mode
            response.view = open(view, "rb")
        except IOError:
            from gluon.http import HTTP
            raise HTTP(404, "Unable to open Custom View: %s" % view)

        script = '''
$('.marker').mouseover(function(){$(this).children('.marker-window').show()})
$('.marker').mouseout(function(){$(this).children('.marker-window').hide()})
$('#single-col').css('padding', 0)'''
        response.s3.jquery_ready.append(script)

        markers = [
            Storage(name="Afghan Red Crescent Society",
                    direction="right",
                    top=109,
                    left=271),
            Storage(name="Australian Red Cross",
                    direction="right",
                    top=349,
                    left=478),
            Storage(name="Bangladesh Red Crescent Society",
                    direction="right",
                    top=142,
                    left=326),
            Storage(name="Brunei Darussalam Red Crescent Society",
                    direction="right",
                    top=205,
                    left=402),
            Storage(name="Cambodian Red Cross Society",
                    direction="right",
                    top=181,
                    left=374),
            Storage(name="Cook Islands Red Cross",
                    direction="right",
                    top=291,
                    left=652),
            Storage(name="Fiji Red Cross Society",
                    direction="right",
                    top=278,
                    left=590),
            Storage(name="Hong Kong Red Cross Society",
                    direction="right",
                    top=146,
                    left=398),
            Storage(name="Indian Red Cross Society",
                    direction="right",
                    top=129,
                    left=287),
            Storage(name="Indonesian Red Cross Society",
                    direction="right",
                    top=235,
                    left=378),
            Storage(name="Japanese Red Cross Society",
                    direction="right",
                    top=94,
                    left=463),
            Storage(name="Kiribati Red Cross Society",
                    direction="left",
                    top=214,
                    left=564),
            Storage(name="Lao Red Cross Society",
                    direction="right",
                    top=159,
                    left=366),
            Storage(name="Malaysian Red Crescent Society",
                    direction="right",
                    top=207,
                    left=367),
            Storage(name="Maldivian Red Crescent",
                    direction="right",
                    top=205,
                    left=278),
            Storage(name="Marshall Islands Red Cross Society",
                    direction="left",
                    top=200,
                    left=561),
            Storage(name="Micronesia Red Cross Society",
                    direction="left",
                    top=200,
                    left=532),
            Storage(name="Mongolian Red Cross Society",
                    direction="right",
                    top=54,
                    left=372),
            Storage(name="Myanmar Red Cross Society",
                    direction="right",
                    top=165,
                    left=349),
            Storage(name="Nepal Red Cross Society",
                    direction="right",
                    top=133,
                    left=308),
            Storage(name="New Zealand Red Cross",
                    direction="right",
                    top=368,
                    left=562),
            Storage(name="Pakistan Red Crescent Society",
                    direction="right",
                    top=115,
                    left=278),
            Storage(name="Palau Red Cross Society",
                    direction="right",
                    top=197,
                    left=463),
            Storage(name="Papua New Guinea Red Cross Society",
                    direction="right",
                    top=247,
                    left=504),
            Storage(name="Philippine National Red Cross",
                    direction="right",
                    top=170,
                    left=421),
            Storage(name="Red Cross of Viet Nam",
                    direction="right",
                    top=150,
                    left=373),
            Storage(name="Red Cross Society of China",
                    direction="right",
                    top=81,
                    left=399),
            Storage(
                name=
                "Red Cross Society of the Democratic People's Republic of Korea",
                direction="right",
                top=82,
                left=423),
            Storage(name="Republic of Korea National Red Cross",
                    direction="right",
                    top=87,
                    left=426),
            Storage(name="Samoa Red Cross Society",
                    direction="left",
                    top=261,
                    left=621),
            Storage(name="Singapore Red Cross Society",
                    direction="right",
                    top=214,
                    left=376),
            Storage(name="Solomon Islands Red Cross",
                    direction="right",
                    top=247,
                    left=537),
            Storage(name="Sri Lanka Red Cross Society",
                    direction="right",
                    top=197,
                    left=303),
            Storage(name="Thai Red Cross Society",
                    direction="right",
                    top=172,
                    left=360),
            Storage(name="Timor-Leste Red Cross Society",
                    direction="right",
                    top=245,
                    left=435),
            Storage(name="Tonga Red Cross Society",
                    direction="right",
                    top=291,
                    left=563),
            Storage(name="Tuvalu Red Cross Society",
                    direction="right",
                    top=245,
                    left=591),
            Storage(name="Vanuatu Red Cross Society",
                    direction="right",
                    top=276,
                    left=559),
        ]

        map = DIV(A(T("Go to Functional Map"),
                    _href=URL(c="gis", f="index"),
                    _class="map-click"),
                  _id="map-home")

        append = map.append
        for marker in markers:
            append(
                DIV(A("",
                      _href=URL(c="org",
                                f="organisation",
                                args="read",
                                vars={"organisation.name": marker.name})),
                    DIV(SPAN(marker.name),
                        SPAN(_class="marker-plus"),
                        _class="marker-window %s" % marker.direction),
                    _class="marker",
                    _style="top:%ipx;left:%ipx;" % (marker.top, marker.left)))
        append(
            DIV(SPAN(T("Click anywhere on the map for full functionality")),
                _class="map-tip"))

        current.menu.breadcrumbs = None

        return dict(map=map)
Example #43
0
    from reportlab.platypus.frames import Frame
    from reportlab.platypus import Spacer, PageBreak, FrameBreak, Paragraph
    from reportlab.platypus import Table, TableStyle
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.lib.units import inch
    from reportlab.lib.units import cm
    from reportlab.lib import colors
    from reportlab.lib.colors import Color
    from reportlab.lib.pagesizes import A4, LETTER, landscape, portrait
    from reportlab.platypus.flowables import Flowable
    reportLabImported = True
except ImportError:
    reportLabImported = False
    BaseDocTemplate = object
    inch = 72.0
    canvas = Storage()
    canvas.Canvas = None

PDF_WIDTH = 0
PDF_HEIGHT = 1


# =============================================================================
class S3RL_PDF(S3Codec):
    """
        Simple Report Labs PDF format codec
    """
    def __init__(self):
        """
            Constructor
        """
Example #44
0
response.static_version = '1.3.16'

db = DAL("sqlite://storage.db",
         migrate=MIGRATE,
         attempts=10,
         lazy_tables=LAZY_TABLES,
         driver_args={'timeout': 30})
db2 = DAL("sqlite://storage_scheduler.db",
          migrate=MIGRATE,
          attempts=10,
          lazy_tables=LAZY_TABLES,
          driver_args={'timeout': 30})

from gluon.storage import Storage
from gluon import current
current.w2p_tvseries = Storage(database=db, database2=db2)

from gluon.tools import Auth, Crud, Service, PluginManager, prettydate
crud, service, plugins = Crud(db), Service(), PluginManager()

STATIC_FOLDER = os.path.join(request.folder, 'static', 'deposit')

#from gluon.custom_import import track_changes; track_changes(True)

db.define_table("series",
                Field("seriesid", "integer"),
                Field("language", length=3),
                Field("overview", 'text'),
                Field("name"),
                Field("genre", "list:string"),
                Field("status"),
Example #45
0
# -*- coding: utf-8 -*-
'''
Copyright (c) 2015 Heidelberg University Library
Distributed under the GNU GPL v3. For full terms see the file
LICENSE.md
'''
from gluon.storage import Storage
from gluon.custom_import import track_changes
settings = Storage()

settings.migrate = True
settings.title = 'Heidelberg University Publishing - heiUP'
settings.subtitle = ''
settings.author_email = '*****@*****.**'
settings.keywords = 'heiUP, Heidelberg University Publishing, Universitätsverlag Heidelberg, Universitätsbibliothek Heidelberg, Universität Heidelberg, digitales Publizieren, Open Access, omp, python, mysql, knv, onix'
settings.description = 'Heidelberg University Publishing ist ein Open-Access-Verlag für wissenschaftliche Publikationen - qualitätsgeprüft und in mehreren Formaten.'
settings.layout_theme = 'Default'
# settings.database_uri = 'sqlite://storage.sqlite'
# settings.database_uri = 'mysql://*****:*****@localhost:3306/omptest'
settings.security_key = '1228409b-a1fc-4868-92b1-a973a607d3f1'
settings.email_server = 'login'
settings.email_sender = 'login'
settings.email_login = ''
settings.login_method = 'local'
settings.login_config = ''
settings.plugins = []

track_changes(True)
Example #46
0
    def __send(self, r, **attr):
        """
            Respond to an incoming pull

            @param r: the S3Request
            @param attr: the controller attributes
        """

        mixed = attr.get("mixed", False)
        get_vars = r.get_vars

        resource = r.resource

        # Identify the requesting repository
        repository_uuid = get_vars.get("repository")
        connector = None

        if repository_uuid:

            rtable = current.s3db.sync_repository
            query = rtable.uuid == repository_uuid
            row = current.db(query).select(limitby=(0, 1)).first()
            if row:
                connector = S3SyncRepository(row)

        if connector is None:
            # Use a dummy repository with Eden API
            connector = S3SyncRepository(
                Storage(
                    id=None,
                    name="unknown",
                    apitype="eden",
                ))

        current.log.debug("S3Sync PULL from %s (%s)" %
                          (connector.name, connector.apitype))

        # Additional export parameters
        start = get_vars.get("start", None)
        if start is not None:
            try:
                start = int(start)
            except ValueError:
                start = None
        limit = get_vars.get("limit", None)
        if limit is not None:
            try:
                limit = int(limit)
            except ValueError:
                limit = None
        msince = get_vars.get("msince", None)
        if msince is not None:
            msince = s3_parse_datetime(msince)

        # Sync filters from peer
        filters = {}
        for k, v in get_vars.items():
            if k[0] == "[" and "]" in k:
                tablename, urlvar = k[1:].split("]", 1)
                if urlvar:
                    if not tablename or tablename == "~":
                        tablename = resource.tablename
                    f = filters.get(tablename, {})
                    u = f.get(urlvar, None)
                    if u:
                        u = "%s&%s" % (u, v)
                    else:
                        u = v
                    f[urlvar] = u
                    filters[tablename] = f
        if not filters:
            filters = None

        try:
            result = connector.send(
                resource,
                start=start,
                limit=limit,
                msince=msince,
                filters=filters,
                mixed=mixed,
            )
        except NotImplementedError:
            r.error(405, "Synchronization method not supported for repository")

        log = self.log
        log.write(
            repository_id=connector.id,
            resource_name="mixed" if mixed else resource.tablename,
            transmission=log.IN,
            mode=log.PULL,
            action="send",
            remote=result.get("remote", False),
            result=result.get("status", log.NONE),
            message=result.get("message", ""),
        )

        return result.get("response")
Example #47
0
    def member_onaccept(form):
        """ On-accept for Member records """

        db = current.db
        s3db = current.s3db
        auth = current.auth
        settings = current.deployment_settings

        utable = current.auth.settings.table_user
        ptable = s3db.pr_person
        ltable = s3db.pr_person_user
        mtable = db.member_membership

        # Get the full record
        _id = form.vars.id
        if _id:
            query = (mtable.id == _id)
            record = db(query).select(mtable.id,
                                      mtable.person_id,
                                      mtable.organisation_id,
                                      mtable.deleted,
                                      limitby=(0, 1)).first()
        else:
            return

        data = Storage()

        # Affiliation, record ownership and component ownership
        # @ToDo
        #s3db.pr_update_affiliations(mtable, record)

        # realm_entity for the pr_person record
        person_id = record.person_id
        person = Storage(id=person_id)
        if settings.get_auth_person_realm_member_org():
            # Set pr_person.realm_entity to the human_resource's organisation pe_id
            organisation_id = record.organisation_id
            entity = s3db.pr_get_pe_id("org_organisation", organisation_id)
            if entity:
                auth.set_realm_entity(ptable,
                                      person,
                                      entity=entity,
                                      force_update=True)

        # Update the location ID from the Home Address
        atable = s3db.pr_address
        query = (atable.pe_id == ptable.pe_id) & \
                (ptable.id == record.person_id) & \
                (atable.type == 1) & \
                (atable.deleted == False)
        address = db(query).select(atable.location_id, limitby=(0, 1)).first()
        if address:
            data.location_id = address.location_id

        # Add record owner (user)
        query = (ptable.id == record.person_id) & \
                (ltable.pe_id == ptable.pe_id) & \
                (utable.id == ltable.user_id)
        user = db(query).select(utable.id,
                                utable.organisation_id,
                                utable.site_id,
                                limitby=(0, 1)).first()
        if user:
            data.owned_by_user = user.id

        if not data:
            return
        record.update_record(**data)
Example #48
0
    "CAD": T("Canadian Dollars"),
    "EUR": T("Euros"),
    "GBP": T("Great British Pounds"),
    "CHF": T("Swiss Francs"),
    "USD": T("United States Dollars"),
}

# Comment/uncomment modules here to disable/enable them
settings.modules = OrderedDict([
    # Core modules which shouldn't be disabled
    (
        "default",
        Storage(
            name_nice=T("Home"),
            restricted=False,  # Use ACLs to control access to this module
            access=
            None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type=None  # This item is not shown in the menu
        )),
    (
        "admin",
        Storage(
            name_nice=T("Administration"),
            #description = "Site Administration",
            restricted=True,
            access=
            "|1|",  # Only Administrators can see this module in the default menu & access the controller
            module_type=None  # This item is handled separately for the menu
        )),
    (
        "appadmin",
Example #49
0
import logging
from gluon.contrib.appconfig import AppConfig
from gluon.storage import Storage

from tbox_interface import TBoxInterface
from abox_interface import ABoxInterface

# Doesn't work well anyway even for dev/testing
# from gluon.custom_import import track_changes
# track_changes(True)

SETTINGS = Storage()
MYCONF = AppConfig(reload=False)

# read values from private/config.ini
SETTINGS.app_view_name = MYCONF.take('app.view_name', cast=str)
SETTINGS.app_name = MYCONF.take('app.app_name', cast=str)
SETTINGS.maintainer_eml = MYCONF.take('app.maintainer_eml', cast=str)
SETTINGS.base_url = MYCONF.take('app.base_url', cast=str)

SETTINGS.document_endpoint = MYCONF.take('app.document_endpoint', cast=str)
SETTINGS.id_gen_endpoint = MYCONF.take('app.id_gen_endpoint', cast=str)
SETTINGS.inheritance_query_endpoint = MYCONF.take(
    'app.inheritance_query_endpoint', cast=str)
SETTINGS.create_activity_endpoint = MYCONF.take('app.create_activity_endpoint',
                                                cast=str)

SETTINGS.db_url_login = MYCONF.take('auth_db.db_url_login', cast=str)
SETTINGS.migrate = MYCONF.take('auth_db.migrate', cast=bool)
SETTINGS.fake_migrate_all = MYCONF.take('auth_db.fake_migrate_all', cast=bool)
SETTINGS.admn_grp = MYCONF.take('auth_db.admn_grp', cast=str)
Example #50
0
from gluon.storage import Storage
settings = Storage()

settings.migrate = True
settings.title = 'FFlock Distributed Cluster Transcoding'
settings.subtitle = ''
settings.author = 'Eric Griffin'
settings.author_email = '*****@*****.**'
settings.keywords = 'fflock, transcoding, cluster'
settings.description = ''
settings.layout_theme = 'Default'
settings.database_uri = 'sqlite://storage.sqlite'
settings.security_key = '89465294-76ab-4323-90d7-f157bd412ffc'
settings.email_server = 'localhost'
settings.email_sender = '*****@*****.**'
settings.email_login = ''
settings.login_method = 'local'
settings.login_config = ''
settings.plugins = []
Example #51
0
from unittest.case import SkipTest, _ExpectedFailure, _UnexpectedSuccess

from dateutil.relativedelta import relativedelta
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.support.ui import Select, WebDriverWait

from gluon import current
from gluon.storage import Storage

from s3.s3resource import S3FieldSelector
from s3.s3utils import s3_unicode
from s3.s3widgets import *

from tests.core import *

current.data = Storage()
current.data["auth"] = {
    "normal": {
        "email": "*****@*****.**",
        "password": "******",
        "first_name": "Test",
        "last_name": "User",
    },
    "admin": {
        "email": "*****@*****.**",
        "password": "******",
        "first_name": "Admin",
        "last_name": "User",
    },
}
Example #52
0
    def html(self, widget_id=None, formkey=None):
        """
            Render the organizer container and instantiate the UI widget

            @param widget_id: the container's DOM ID
        """

        T = current.T
        settings = current.deployment_settings

        if not widget_id:
            widget_id = "organizer"

        # Parse resource configuration
        resources = self.resources
        if not isinstance(resources, (list, tuple)):
            resources = [resources]
        resource_configs = []
        use_time = False
        for resource_config in resources:
            resource_use_time = resource_config.get("useTime")
            if resource_use_time:
                use_time = True
            resource_configs.append(resource_config)

        # Inject script and widget instantiation
        script_opts = {"resources": resource_configs,
                       "useTime": use_time,
                       "labelEdit": s3_str(T("Edit")),
                       "labelDelete": s3_str(T("Delete")),
                       "deleteConfirmation": s3_str(T("Do you want to delete this entry?")),
                       "firstDay": settings.get_L10n_firstDOW(),
                       }
        # Options from settings
        bhours = settings.get_ui_organizer_business_hours()
        if bhours:
            script_opts["businessHours"] = bhours
        tformat = settings.get_ui_organizer_time_format()
        if tformat:
            script_opts["timeFormat"] = tformat
        snap_duration = settings.get_ui_organizer_snap_duration()
        if snap_duration:
            script_opts["snapDuration"] = snap_duration

        self.inject_script(widget_id, script_opts)

        # Add a datepicker to navigate to arbitrary dates
        picker = S3DateWidget()(Storage(name="date_select"),
                                None,
                                _type="hidden",
                                _id="%s-date-picker" % widget_id,
                                )

        # Generate and return the HTML for the widget container
        return DIV(INPUT(_name = "_formkey",
                         _type = "hidden",
                         _value = str(formkey) if formkey else "",
                         ),
                   picker,
                   _id = widget_id,
                   _class = "s3-organizer",
                   )
Example #53
0
    def _create_popup(r, widget, list_id, resource, context, numrows):
        """
            Render an action link for a create-popup (used in data lists
            and data tables).

            @param r: the S3Request instance
            @param widget: the widget definition as dict
            @param list_id: the list ID
            @param resource: the target resource
            @param context: the context filter
            @param numrows: the total number of rows in the list/table
        """

        create = ""

        widget_get = widget.get

        insert = widget_get("insert", True)
        if not insert:
            return create

        table = resource.table
        tablename = resource.tablename

        # Default to primary REST controller for the resource being added
        c, f = tablename.split("_", 1)
        create_controller = widget_get("create_controller")
        if create_controller:
            c = create_controller
        create_function = widget_get("create_function")
        if create_function:
            f = create_function

        permit = current.auth.s3_has_permission
        create_ok = permit("create", table, c=c, f=f)
        if create_ok:
            if not create_controller or not create_function:
                # Assume not component context
                create_ok = permit("update", r.table, record_id=r.id, c=c, f=f)
        if create_ok:
            #if tablename = "org_organisation":
            # @ToDo: Special check for creating resources on Organisation profile

            # URL-serialize the widget filter
            widget_filter = widget_get("filter")
            if widget_filter:
                url_vars = widget_filter.serialize_url(resource)
            else:
                url_vars = Storage()

            # URL-serialize the context filter
            if context:
                filters = context.serialize_url(resource)
                for selector in filters:
                    url_vars[selector] = filters[selector]

            # URL-serialize the widget default
            default = widget_get("default")
            if default:
                k, v = default.split("=", 1)
                url_vars[k] = v

            # URL-serialize the list ID (refresh-target of the popup)
            url_vars.refresh = list_id

            # Indicate that popup comes from profile (and which)
            url_vars.profile = r.tablename

            # CRUD string
            label_create = widget_get("label_create", None)
            # Activate if-required
            #if label_create and isinstance(label_create, basestring):
            if label_create:
                label_create = current.T(label_create)
            else:
                label_create = S3CRUD.crud_string(tablename, "label_create")

            # Popup URL
            component = widget_get("create_component", None)
            if component:
                args = [r.id, component, "create.popup"]
            else:
                args = ["create.popup"]
            add_url = URL(c=c, f=f, args=args, vars=url_vars)

            if callable(insert):
                # Custom widget
                create = insert(r, list_id, label_create, add_url)

            elif current.deployment_settings.ui.formstyle == "bootstrap":
                # Bootstrap-style action icon
                create = A(
                    ICON("plus-sign", _class="small-add"),
                    _href=add_url,
                    _class="s3_modal",
                    _title=label_create,
                )
            else:
                # Standard action button
                create = A(
                    label_create,
                    _href=add_url,
                    _class="action-btn profile-add-btn s3_modal",
                )

            if widget_get("type") == "datalist":

                # If this is a multiple=False widget and we already
                # have a record, we hide the create-button
                multiple = widget_get("multiple", True)
                if not multiple and hasattr(create, "update"):
                    if numrows:
                        create.update(_style="display:none")
                    else:
                        create.update(_style="display:block")
                    # Script to hide/unhide the create-button on Ajax
                    # list updates
                    createid = create["_id"]
                    if not createid:
                        createid = "%s-add-button" % list_id
                        create.update(_id=createid)
                    script = \
'''$('#%(list_id)s').on('listUpdate',function(){
$('#%(createid)s').css({display:$(this).datalist('getTotalItems')?'none':'block'})
})''' % dict(list_id=list_id, createid=createid)
                    current.response.s3.jquery_ready.append(script)

        return create
Example #54
0
    def model(self):

        T = current.T
        db = current.db

        crud_strings = current.response.s3.crud_strings
        define_table = self.define_table
        location_id = self.gis_location_id

        # -----------------------------------------------------------
        # Security Levels
        # - according to the UN Security Level System (SLS)
        # http://ictemergency.wfp.org/c/document_library/get_file?uuid=c025cb98-2297-4208-bcc6-76ba02719c02&groupId=10844
        # http://geonode.wfp.org/layers/geonode:wld_bnd_securitylevel_wfp
        #

        level_opts = {
            1: T("Minimal"),
            2: T("Low"),
            3: T("Moderate"),
            4: T("Substantial"),
            5: T("High"),
            6: T("Extreme"),
        }

        tablename = "security_level"
        define_table(
            tablename,
            location_id(
                #label = T("Security Level Area"),
                widget=S3LocationSelector(show_map=False), ),
            # Overall Level
            Field(
                "level",
                "integer",
                label=T("Security Level"),
                represent=lambda v: level_opts.get(
                    v, current.messages.UNKNOWN_OPT),
                requires=IS_IN_SET(level_opts),
            ),
            # Categories
            Field(
                "armed_conflict",
                "integer",
                label=T("Armed Conflict"),
                represent=lambda v: level_opts.get(
                    v, current.messages.UNKNOWN_OPT),
                requires=IS_IN_SET(level_opts),
            ),
            Field(
                "terrorism",
                "integer",
                label=T("Terrorism"),
                represent=lambda v: level_opts.get(
                    v, current.messages.UNKNOWN_OPT),
                requires=IS_IN_SET(level_opts),
            ),
            Field(
                "crime",
                "integer",
                label=T("Crime"),
                represent=lambda v: level_opts.get(
                    v, current.messages.UNKNOWN_OPT),
                requires=IS_IN_SET(level_opts),
            ),
            Field(
                "civil_unrest",
                "integer",
                label=T("Civil Unrest"),
                represent=lambda v: level_opts.get(
                    v, current.messages.UNKNOWN_OPT),
                requires=IS_IN_SET(level_opts),
            ),
            Field(
                "hazards",
                "integer",
                label=T("Hazards"),
                represent=lambda v: level_opts.get(
                    v, current.messages.UNKNOWN_OPT),
                requires=IS_IN_SET(level_opts),
                comment=T("e.g. earthquakes or floods"),
            ),
            s3_comments(),
            *s3_meta_fields())

        # CRUD strings
        crud_strings[tablename] = Storage(
            label_create=T("Classify Area"),
            title_display=T("Security Level Details"),
            title_list=T("Security Levels"),
            title_update=T("Edit Security Level"),
            title_upload=T("Import Security Levels"),
            label_list_button=T("List Security Levels"),
            label_delete_button=T("Delete Security Level"),
            msg_record_created=T("Security Area classified"),
            msg_record_modified=T("Security Level updated"),
            msg_record_deleted=T("Security Level deleted"),
            msg_list_empty=T("No Security Areas currently classified"))

        # -----------------------------------------------------------
        # Security Zone Types
        #
        tablename = "security_zone_type"
        define_table(tablename, Field(
            "name",
            label=T("Name"),
        ), s3_comments(), *s3_meta_fields())

        # CRUD strings
        ADD_ZONE_TYPE = T("Create Zone Type")
        crud_strings[tablename] = Storage(
            label_create=ADD_ZONE_TYPE,
            title_display=T("Zone Type Details"),
            title_list=T("Zone Types"),
            title_update=T("Edit Zone Type"),
            title_upload=T("Import Zone Types"),
            label_list_button=T("List Zone Types"),
            label_delete_button=T("Delete Zone Type"),
            msg_record_created=T("Zone Type added"),
            msg_record_modified=T("Zone Type updated"),
            msg_record_deleted=T("Zone Type deleted"),
            msg_list_empty=T("No Zone Types currently registered"))

        zone_type_represent = S3Represent(lookup=tablename)

        self.configure(
            tablename,
            deduplicate=self.security_zone_type_duplicate,
        )

        # -----------------------------------------------------------
        # Security Zones
        #
        tablename = "security_zone"
        define_table(
            tablename, Field(
                "name",
                label=T("Name"),
            ),
            Field(
                "zone_type_id",
                db.security_zone_type,
                label=T("Type"),
                represent=zone_type_represent,
                requires=IS_EMPTY_OR(
                    IS_ONE_OF(db,
                              "security_zone_type.id",
                              zone_type_represent,
                              sort=True)),
                comment=S3AddResourceLink(
                    c="security",
                    f="zone_type",
                    label=ADD_ZONE_TYPE,
                    tooltip=
                    T("Select a Zone Type from the list or click 'Add Zone Type'"
                      )),
            ),
            location_id(widget=S3LocationSelector(
                catalog_layers=True,
                points=False,
                polygons=True,
            ), ), s3_comments(), *s3_meta_fields())

        # CRUD strings
        ADD_ZONE = T("Create Zone")
        crud_strings[tablename] = Storage(
            label_create=ADD_ZONE,
            title_display=T("Zone Details"),
            title_list=T("Zones"),
            title_update=T("Edit Zone"),
            title_upload=T("Import Zones"),
            label_list_button=T("List Zones"),
            label_delete_button=T("Delete Zone"),
            msg_record_created=T("Zone added"),
            msg_record_modified=T("Zone updated"),
            msg_record_deleted=T("Zone deleted"),
            msg_list_empty=T("No Zones currently registered"))

        zone_represent = S3Represent(lookup=tablename)

        # -----------------------------------------------------------
        # Security Staff Types
        #
        tablename = "security_staff_type"
        define_table(tablename, Field("name", label=T("Name")), s3_comments(),
                     *s3_meta_fields())

        # CRUD strings
        ADD_STAFF = T("Add Staff Type")
        crud_strings[tablename] = Storage(
            label_create=ADD_STAFF,
            title_display=T("Staff Type Details"),
            title_list=T("Staff Types"),
            title_update=T("Edit Staff Type"),
            title_upload=T("Import Staff Types"),
            label_list_button=T("List Staff Types"),
            label_delete_button=T("Delete Staff Type"),
            msg_record_created=T("Staff Type added"),
            msg_record_modified=T("Staff Type updated"),
            msg_record_deleted=T("Staff Type deleted"),
            msg_list_empty=T("No Staff Types currently registered"))

        staff_type_represent = S3Represent(lookup=tablename)

        # -----------------------------------------------------------
        # Security Staff
        #
        tablename = "security_staff"
        define_table(
            tablename, self.hrm_human_resource_id(),
            Field(
                "staff_type_id",
                "list:reference security_staff_type",
                label=T("Type"),
                represent=self.security_staff_type_multirepresent,
                requires=IS_EMPTY_OR(
                    IS_ONE_OF(db,
                              "security_staff_type.id",
                              staff_type_represent,
                              sort=True,
                              multiple=True)),
                comment=S3AddResourceLink(
                    c="security",
                    f="staff_type",
                    label=ADD_STAFF,
                    tooltip=
                    T("Select a Staff Type from the list or click 'Add Staff Type'"
                      )),
            ),
            Field(
                "zone_id",
                db.security_zone,
                label=T("Zone"),
                represent=zone_represent,
                requires=IS_EMPTY_OR(
                    IS_ONE_OF(db,
                              "security_zone.id",
                              zone_represent,
                              sort=True)),
                comment=S3AddResourceLink(
                    c="security",
                    f="zone",
                    label=ADD_ZONE,
                    tooltip=
                    T("For wardens, select a Zone from the list or click 'Add Zone'"
                      )),
            ),
            self.super_link(
                "site_id",
                "org_site",
                label=T("Facility"),
                represent=self.org_site_represent,
                readable=True,
                writable=True,
            ), s3_comments(), *s3_meta_fields())

        # CRUD strings
        crud_strings[tablename] = Storage(
            label_create=T("Add Security-Related Staff"),
            title_display=T("Security-Related Staff Details"),
            title_list=T("Security-Related Staff"),
            title_update=T("Edit Security-Related Staff"),
            title_upload=T("Import Security-Related Staff"),
            label_list_button=T("List Security-Related Staff"),
            label_delete_button=T("Delete Security-Related Staff"),
            msg_record_created=T("Security-Related Staff added"),
            msg_record_modified=T("Security-Related Staff updated"),
            msg_record_deleted=T("Security-Related Staff deleted"),
            msg_list_empty=T("No Security-Related Staff currently registered"))

        # ---------------------------------------------------------------------
        # Pass names back to global scope (s3.*)
        #
        return dict()
Example #55
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
| This file is part of the web2py Web Framework
| Copyrighted by Massimo Di Pierro <*****@*****.**>
| License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
"""

import os
import sys
import platform
from gluon.storage import Storage
from pydal._compat import PY2

global_settings = Storage()
settings = global_settings  # legacy compatibility

if not hasattr(os, 'mkdir'):
    global_settings.db_sessions = True

if global_settings.db_sessions is not True:
    global_settings.db_sessions = set()

global_settings.gluon_parent = \
    os.environ.get('web2py_path', os.getcwd())

global_settings.applications_parent = global_settings.gluon_parent

global_settings.app_folders = set()

global_settings.debugging = False
Example #56
0
class LoginRadiusAccount(object):
    """
    from gluon.contrib.login_methods.loginradius_account import LoginRadiusAccount
    auth.settings.actions_disabled=['register','change_password',
        'request_reset_password']
    auth.settings.login_form = LoginRadiusAccount(request,
              api_key="...",
              api_secret="...",
              url = "http://localhost:8000/%s/default/user/login" % request.application)
    """
    def __init__(self,
                 request,
                 api_key="",
                 api_secret="",
                 url=None,
                 on_login_failure=None):

        self.request = request
        self.api_key = api_key
        self.api_secret = api_secret
        self.url = url
        self.auth_base_url = "https://hub.loginradius.com/UserProfile.ashx/"
        self.profile = None
        self.on_login_failure = on_login_failure
        self.mappings = Storage()

        def defaultmapping(profile):
            first_name = profile.get('FirstName')
            last_name = profile.get('LastName')
            email = profile.get('Email', [{}])[0].get('Value')
            reg_id = profile.get('ID', '')
            username = profile.get('ProfileName', email)

            return dict(registration_id=reg_id,
                        username=username,
                        email=email,
                        first_name=first_name,
                        last_name=last_name)

        self.mappings.default = defaultmapping

    def get_user(self):
        request = self.request
        user = None
        if request.vars.token:
            try:
                auth_url = self.auth_base_url + self.api_secret + "/" + request.vars.token
                json_data = fetch(
                    auth_url,
                    headers={'User-Agent': "LoginRadius - Python - SDK"})
                self.profile = json.loads(json_data)
                provider = self.profile['Provider']
                mapping = self.mappings.get(provider, self.mappings['default'])
                user = mapping(self.profile)
            except (JSONDecodeError, KeyError):
                pass
            if user is None and self.on_login_failure:
                redirect(self.on_login_failure)
        return user

    def login_form(self):
        loginradius_url = "https://hub.loginradius.com/include/js/LoginRadius.js"
        loginradius_lib = SCRIPT(_src=loginradius_url, _type='text/javascript')
        container = DIV(_id="interfacecontainerdiv",
                        _class='interfacecontainerdiv')
        widget = SCRIPT("""var options={}; options.login=true;
        LoginRadius_SocialLogin.util.ready(function () {
        $ui = LoginRadius_SocialLogin.lr_login_settings;
        $ui.interfacesize = "";$ui.apikey = "%s";
        $ui.callback=""; $ui.lrinterfacecontainer ="interfacecontainerdiv";
        LoginRadius_SocialLogin.init(options); });""" % self.api_key)
        form = DIV(container, loginradius_lib, widget)
        return form
Example #57
0
# This script is designed to be run as a Web2Py application:
# python web2py.py -S eden -M -R applications/eden/modules/tests/suite.py
# or
# python web2py.py -S eden -M -R applications/eden/modules/tests/suite.py -A testscript

import argparse
import unittest

from gluon import current
from gluon.storage import Storage

current.data = Storage()

# @ToDo: Load these only when running Selenium tests
# (shouldn't be required for Smoke tests)
# (means removing the *)
from selenium import webdriver
from tests.asset import *
from tests.inv import *
from tests.member import *
from tests.org import *
from tests.project import *
from tests.staff import *
from tests.volunteer import *


def loadAllTests():

    # Create Organisation
    loadTests = unittest.TestLoader().loadTestsFromTestCase
    suite = loadTests(CreateOrganisation)
Example #58
0
    def model(self):

        T = current.T

        UNKNOWN_OPT = current.messages.UNKNOWN_OPT

        # ---------------------------------------------------------------------
        # Case
        #
        dvr_damage_opts = {
            1: T("Very High"),
            2: T("High"),
            3: T("Medium"),
            4: T("Low"),
        }

        dvr_status_opts = {
            1: T("Open"),
            2: T("Accepted"),
            3: T("Rejected"),
        }

        tablename = "dvr_case"
        self.define_table(tablename,
                          # @ToDo: Option to autogenerate these, like Waybills, et al
                          Field("reference",
                                label = T("Case Number")),
                          self.pr_person_id(
                            # @ToDo: Modify this to update location_id if the selected person has a Home Address already
                            comment=None,
                            requires=IS_ADD_PERSON_WIDGET2(),
                            widget=S3AddPersonWidget2(controller="pr"),
                          ),
                          self.gis_location_id(label = T("Home Address")),
                          Field("damage", "integer",
                                requires = IS_EMPTY_OR(IS_IN_SET(dvr_damage_opts)),
                                represent = lambda opt: \
                                    dvr_damage_opts.get(opt, UNKNOWN_OPT),
                                label= T("Damage Assessment")),
                          Field("insurance", "boolean",
                                represent = s3_yes_no_represent,
                                label = T("Insurance")),
                          Field("status", "integer",
                                default = 1,
                                requires = IS_EMPTY_OR(IS_IN_SET(dvr_status_opts)),
                                represent = lambda opt: \
                                    dvr_status_opts.get(opt, UNKNOWN_OPT),
                                label= T("Status")),
                          s3_comments(),
                          *s3_meta_fields())

        # CRUD Strings
        ADD_CASE = T("Create Case")
        current.response.s3.crud_strings[tablename] = Storage(
            label_create=ADD_CASE,
            title_display=T("Case Details"),
            title_list=T("Cases"),
            title_update=T("Edit Case"),
            label_list_button=T("List Cases"),
            label_delete_button=T("Delete Case"),
            msg_record_created=T("Case added"),
            msg_record_modified=T("Case updated"),
            msg_record_deleted=T("Case deleted"),
            msg_list_empty=T("No Cases found"))

        self.configure(
            tablename,
            onaccept=self.dvr_case_onaccept,
        )

        # ---------------------------------------------------------------------
        # Pass names back to global scope (s3.*)
        #
        return Storage()
Example #59
0
    return form


settings.ui.formstyle_row = formstyle_row
settings.ui.formstyle = formstyle_row

# -----------------------------------------------------------------------------
# Comment/uncomment modules here to disable/enable them
settings.modules = OrderedDict([
    # Core modules which shouldn't be disabled
    (
        "default",
        Storage(
            name_nice=T("Home"),
            restricted=False,  # Use ACLs to control access to this module
            access=
            None,  # All Users (inc Anonymous) can see this module in the default menu & access the controller
            module_type=None  # This item is not shown in the menu
        )),
    (
        "admin",
        Storage(
            name_nice=T("Administration"),
            #description = "Site Administration",
            restricted=True,
            access=
            "|1|",  # Only Administrators can see this module in the default menu & access the controller
            module_type=None  # This item is handled separately for the menu
        )),
    (
        "appadmin",
Example #60
0
    def model(self):

        T = current.T
        db = current.db
        s3 = current.response.s3

        person_comment = self.pr_person_comment
        person_id = self.pr_person_id
        location_id = self.gis_location_id
        organisation_id = self.org_organisation_id

        messages = current.messages
        NONE = messages.NONE
        UNKNOWN_OPT = messages.UNKNOWN_OPT

        # Shortcuts
        add_component = self.add_component
        configure = self.configure
        crud_strings = s3.crud_strings
        define_table = self.define_table
        super_key = self.super_key
        super_link = self.super_link

        # ---------------------------------------------------------------------
        # Document-referencing entities
        #
        entity_types = Storage(
            asset_asset=T("Asset"),
            irs_ireport=T("Incident Report"),
            project_project=T("Project"),
            project_activity=T("Project Activity"),
            project_task=T("Task"),
            hms_hospital=T("Hospital"),
        )

        tablename = "doc_entity"
        doc_entity = self.super_entity(tablename, "doc_id", entity_types)

        # Components
        add_component("doc_document", doc_entity=super_key(doc_entity))
        add_component("doc_image", doc_entity=super_key(doc_entity))

        # ---------------------------------------------------------------------
        # Documents
        #
        tablename = "doc_document"
        table = define_table(tablename,
                             # Instance
                             super_link("source_id", "stats_source"),
                             # Component not instance
                             super_link("site_id", "org_site"),
                             super_link("doc_id", doc_entity),
                             Field("file", "upload", autodelete=True),
                             Field("name", length=128,
                                   # Allow Name to be added onvalidation
                                   requires = IS_NULL_OR(IS_LENGTH(128)),
                                   label=T("Name")),
                             Field("url", label=T("URL"),
                                   requires = IS_NULL_OR(IS_URL()),
                                   represent = lambda url: \
                                               url and A(url,_href=url) or NONE),
                             person_id(label=T("Author"),
                                       comment=person_comment(T("Author"),
                                                              T("The Author of this Document (optional)"))),
                             organisation_id(
                                widget = S3OrganisationAutocompleteWidget(default_from_profile=True)
                                ),
                             s3_date(label = T("Date Published")),
                             location_id(),
                             self.stats_group_type_id(),
                             s3_comments(),
                             #Field("entered", "boolean", label=T("Entered")),
                             Field("checksum", readable=False, writable=False),
                             *s3_meta_fields())

        # Field configuration
        table.file.represent = lambda file, table=table: \
                               self.doc_file_represent(file, table)
        #table.location_id.readable = False
        #table.location_id.writable = False
        #table.entered.comment = DIV(_class="tooltip",
        #                            _title="%s|%s" % (T("Entered"),
        #                                              T("Has data from this Reference Document been entered into Sahana?")))

        # CRUD Strings
        ADD_DOCUMENT = T("Add Reference Document")
        crud_strings[tablename] = Storage(
            title_create=ADD_DOCUMENT,
            title_display=T("Document Details"),
            title_list=T("Documents"),
            title_update=T("Edit Document"),
            title_search=T("Search Documents"),
            subtitle_create=T("Add New Document"),
            label_list_button=T("List Documents"),
            label_create_button=ADD_DOCUMENT,
            label_delete_button=T("Delete Document"),
            msg_record_created=T("Document added"),
            msg_record_modified=T("Document updated"),
            msg_record_deleted=T("Document deleted"),
            msg_list_empty=T("No Documents found"))

        # Search Method

        # Resource Configuration
        configure(tablename,
                  super_entity="stats_source",
                  deduplicate=self.document_duplicate,
                  onvalidation=self.document_onvalidation)

        # ---------------------------------------------------------------------
        # Images
        #
        # @ToDo: Field to determine which is the default image to use for
        #        e.g. a Map popup (like the profile picture)
        #        readable/writable=False except in the cases where-needed
        #
        doc_image_type_opts = {
            1: T("Photograph"),
            2: T("Map"),
            3: T("Document Scan"),
            99: T("other")
        }

        tablename = "doc_image"
        table = define_table(
            tablename,
            # Instance
            super_link("source_id", "stats_source"),
            # Component not instance
            super_link("site_id", "org_site"),
            super_link("pe_id", "pr_pentity"),
            super_link("doc_id", doc_entity),
            Field(
                "file",
                "upload",
                autodelete=True,
                requires=IS_NULL_OR(
                    IS_IMAGE(extensions=(s3.IMAGE_EXTENSIONS))),
                # upload folder needs to be visible to the download() function as well as the upload
                uploadfolder=os.path.join(current.request.folder, "uploads",
                                          "images")),
            Field(
                "name",
                length=128,
                # Allow Name to be added onvalidation
                requires=IS_NULL_OR(IS_LENGTH(128)),
                label=T("Name")),
            Field("url", label=T("URL"), requires=IS_NULL_OR(IS_URL())),
            Field("type",
                  "integer",
                  requires=IS_IN_SET(doc_image_type_opts, zero=None),
                  default=1,
                  label=T("Image Type"),
                  represent=lambda opt: doc_image_type_opts.get(
                      opt, UNKNOWN_OPT)),
            person_id(label=T("Author")),
            organisation_id(widget=S3OrganisationAutocompleteWidget(
                default_from_profile=True)),
            s3_date(label=T("Date Taken")),
            location_id(),
            self.stats_group_type_id(),
            s3_comments(),
            Field("checksum", readable=False, writable=False),
            *s3_meta_fields())

        # Field configuration
        table.file.represent = doc_image_represent

        # CRUD Strings
        ADD_IMAGE = T("Add Photo")
        crud_strings[tablename] = Storage(
            title_create=ADD_IMAGE,
            title_display=T("Photo Details"),
            title_list=T("Photos"),
            title_update=T("Edit Photo"),
            title_search=T("Search Photos"),
            subtitle_create=T("Add New Photo"),
            label_list_button=T("List Photos"),
            label_create_button=ADD_IMAGE,
            label_delete_button=T("Delete Photo"),
            msg_record_created=T("Photo added"),
            msg_record_modified=T("Photo updated"),
            msg_record_deleted=T("Photo deleted"),
            msg_list_empty=T("No Photos found"))

        # Search Method

        # Resource Configuration
        configure(tablename,
                  super_entity = "stats_source",
                  deduplicate=self.document_duplicate,
                  onvalidation=lambda form: \
                                self.document_onvalidation(form, document=False))
        # ---------------------------------------------------------------------
        # Pass model-global names to response.s3
        #
        return Storage()