<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

##
# django-reuse: bin/manage.py
#
# An interface to django-admin.py which adds capability to manage reusable
# django applications, application dependencies, projects which use reusable
# applications, and the creation of a development environment that encourages
# and supports reusability.
#
# We do this by replacing existing commands and hooking in new ones using the
# django command extensions mechanism.
##

DJANGO_FOUND = False # A terrible hack
DJANGO_EXTENSIONS_FOUND = False
DJANGO_REUSE_FOUND = False
def try_execute_manager():
    global DJANGO_FOUND
    if DJANGO_FOUND == False:
        try:
            from django.core.management import execute_manager
            try:
                from project import settings
            except:
                from django.conf import settings
                settings.configure(INSTALLED_APPS=())
            DJANGO_FOUND = True
            if DJANGO_EXTENSIONS_FOUND == True:
                settings.INSTALLED_APPS += ('django_extensions',)
            if DJANGO_REUSE_FOUND == True:
                settings.INSTALLED_APPS += ('reuse',)
            execute_manager(settings)
        except:
            pass

##
# Guard against unintended imports
if __name__ == "__main__":

 import os
 script   = os.path.realpath(__file__)
 bin_dir  = os.path.dirname(script)
 dev_root = os.path.join(bin_dir,'..','..')

##
# Django command extensions are used to extend the capability of Django's
# built-in django-admin.py.  By default we use a suite of community provided
# extensions, as well as our own extensions targetted at reusable application
# development.

 import sys

 ext_path = os.path.join(dev_root,'django-extensions')
 if os.path.isdir(ext_path):
     sys.path.insert(0,ext_path)
     DJANGO_EXTENSIONS_FOUND = True

 ext_path = os.path.join(dev_root,'django-reuse')
 if os.path.isdir(ext_path):
     sys.path.insert(0,ext_path)
     DJANGO_REUSE_FOUND = True

##
# See if we're called from the context of a project, or if Django is installed
# on the default python path, and launch the command manager.

 if os.path.isfile(os.path.join('.','django','bin','django-admin.py')) and os.path.isfile(os.path.join('.','project','settings.py')):
     DIRNAME = os.path.abspath(os.path.dirname(__file__))
     sys.path.insert(0, DIRNAME)
     sys.path.insert(0, os.path.join(DIRNAME, 'apps'))
     sys.path.insert(0, os.path.join(DIRNAME, 'project'))

     from django.core.management import execute_manager
     from project import settings

     if DJANGO_EXTENSIONS_FOUND == True:
         settings.INSTALLED_APPS += ('django_extensions',)
     if DJANGO_REUSE_FOUND == True:
         settings.INSTALLED_APPS += ('reuse',)

     execute_manager(settings)
     sys.exit(0)

##
# Otherwise we'll try to find a stable version of Django under the assumption
# that this script is being called from a development environment that
# resembles one created by the bootstrap script.

 # temp is a bad name.. but it is a variable that has a lot of different uses
 # in the following code (maybe 'misc' would be better?).  By the time we get
 # to "if len(temp) > 0", temp is a list of potential Django installations.
 temp = []

 # If there is a django installation (or a symlink to one) by the name of
 # 'django' in the development directory, use that.
 if os.path.isfile(os.path.join(dev_root,'django','bin','django-admin.py')):
     temp = ['.']
 # Otherwise collect all potential Django installations in the current
 # directory (test by checking for the existance of django-admin.py) and
 # crudely sort by release type.
 else:
     # Build list of Django candidate installations.
     temp = [x for x in os.listdir(dev_root) if os.path.isdir(os.path.join(dev_root,x))]
     dirs = [x for x in temp if os.path.isfile(os.path.join(x,'django','bin','django-admin.py'))]
     # Sort that list by stability and version number.  The result is a list
     # sorted by stability ('final' first, 'trunk' last) and subsorted by
     # reverse alphabetic order, which *should* result in descending version
     # numbers.
     vers = ["final", "rc", "beta", "alpha", "trunk"]
     temp = map(lambda ver: [x for x in dirs if ver in x], vers)
     map(lambda dirs: dirs.sort(reverse=True), temp)
     temp = [x for y in temp for x in y]

 # If there's still no Django installation found... perhaps it's in the python
 # path?
 if not temp:
     try:
         import django
         # Give temp something to be put back on the python path.
         temp = [sys.path.pop(0)]
     except:
         pass

 # Use the highest version of the most stable category of release available.
 if len(temp) > 0:
     sys.path.insert(0,os.path.join(dev_root,temp.pop(0)))

     from django.core.management import execute_manager
     from django.conf import settings

     settings.configure(INSTALLED_APPS=())
     if DJANGO_EXTENSIONS_FOUND == True:
         settings.INSTALLED_APPS += ('django_extensions',)
     if DJANGO_REUSE_FOUND == True:
         settings.INSTALLED_APPS += ('reuse',)

     execute_manager(settings)
     sys.exit(0)

 # No Django installation... epic fail.
 else:
     sys.stderr.write("""
error: Could not find Django installation.  Are you sure that your development
error: environment is setup correctly?
""".lstrip())
     sys.exit(1)

##
# End of File
##
<commit_msg>no longer need try_execute_manager()<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

##
# django-reuse: bin/manage.py
#
# An interface to django-admin.py which adds capability to manage reusable
# django applications, application dependencies, projects which use reusable
# applications, and the creation of a development environment that encourages
# and supports reusability.
#
# We do this by replacing existing commands and hooking in new ones using the
# django command extensions mechanism.
##

##
# Guard against unintended imports
if __name__ == "__main__":

 import os
 script   = os.path.realpath(__file__)
 bin_dir  = os.path.dirname(script)
 dev_root = os.path.join(bin_dir,'..','..')

##
# Django command extensions are used to extend the capability of Django's
# built-in django-admin.py.  By default we use a suite of community provided
# extensions, as well as our own extensions targetted at reusable application
# development.

 import sys

 ext_path = os.path.join(dev_root,'django-extensions')
 if os.path.isdir(ext_path):
     sys.path.insert(0,ext_path)
     DJANGO_EXTENSIONS_FOUND = True

 ext_path = os.path.join(dev_root,'django-reuse')
 if os.path.isdir(ext_path):
     sys.path.insert(0,ext_path)
     DJANGO_REUSE_FOUND = True

##
# See if we're called from the context of a project, or if Django is installed
# on the default python path, and launch the command manager.

 if os.path.isfile(os.path.join('.','django','bin','django-admin.py')) and os.path.isfile(os.path.join('.','project','settings.py')):
     DIRNAME = os.path.abspath(os.path.dirname(__file__))
     sys.path.insert(0, DIRNAME)
     sys.path.insert(0, os.path.join(DIRNAME, 'apps'))
     sys.path.insert(0, os.path.join(DIRNAME, 'project'))

     from django.core.management import execute_manager
     from project import settings

     if DJANGO_EXTENSIONS_FOUND == True:
         settings.INSTALLED_APPS += ('django_extensions',)
     if DJANGO_REUSE_FOUND == True:
         settings.INSTALLED_APPS += ('reuse',)

     execute_manager(settings)
     sys.exit(0)

##
# Otherwise we'll try to find a stable version of Django under the assumption
# that this script is being called from a development environment that
# resembles one created by the bootstrap script.

 # temp is a bad name.. but it is a variable that has a lot of different uses
 # in the following code (maybe 'misc' would be better?).  By the time we get
 # to "if len(temp) > 0", temp is a list of potential Django installations.
 temp = []

 # If there is a django installation (or a symlink to one) by the name of
 # 'django' in the development directory, use that.
 if os.path.isfile(os.path.join(dev_root,'django','bin','django-admin.py')):
     temp = ['.']
 # Otherwise collect all potential Django installations in the current
 # directory (test by checking for the existance of django-admin.py) and
 # crudely sort by release type.
 else:
     # Build list of Django candidate installations.
     temp = [x for x in os.listdir(dev_root) if os.path.isdir(os.path.join(dev_root,x))]
     dirs = [x for x in temp if os.path.isfile(os.path.join(x,'django','bin','django-admin.py'))]
     # Sort that list by stability and version number.  The result is a list
     # sorted by stability ('final' first, 'trunk' last) and subsorted by
     # reverse alphabetic order, which *should* result in descending version
     # numbers.
     vers = ["final", "rc", "beta", "alpha", "trunk"]
     temp = map(lambda ver: [x for x in dirs if ver in x], vers)
     map(lambda dirs: dirs.sort(reverse=True), temp)
     temp = [x for y in temp for x in y]

 # If there's still no Django installation found... perhaps it's in the python
 # path?
 if not temp:
     try:
         import django
         # Give temp something to be put back on the python path.
         temp = [sys.path.pop(0)]
     except:
         pass

 # Use the highest version of the most stable category of release available.
 if len(temp) > 0:
     sys.path.insert(0,os.path.join(dev_root,temp.pop(0)))

     from django.core.management import execute_manager
     from django.conf import settings

     settings.configure(INSTALLED_APPS=())
     if DJANGO_EXTENSIONS_FOUND == True:
         settings.INSTALLED_APPS += ('django_extensions',)
     if DJANGO_REUSE_FOUND == True:
         settings.INSTALLED_APPS += ('reuse',)

     execute_manager(settings)
     sys.exit(0)

 # No Django installation... epic fail.
 else:
     sys.stderr.write("""
error: Could not find Django installation.  Are you sure that your development
error: environment is setup correctly?
""".lstrip())
     sys.exit(1)

##
# End of File
##
<|endoftext|>


<commit_before>from django.conf.urls import patterns, include, url
from django.contrib.auth.views import login, logout
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth.decorators import login_required
from django.views.generic.base import RedirectView
from django.views.generic import TemplateView
from decorator_include import decorator_include

from datapoints.api.meta_data import *
from datapoints.api.datapoint import DataPointResource, DataPointEntryResource
from datapoints.views import debug
from datapoints import views

from tastypie.api import Api

admin.autodiscover()

## tastypie endpoints - ##
v1_api = Api(api_name='v1')
v1_api.register(DataPointResource())
v1_api.register(DataPointEntryResource())
v1_api.register(GeoResource())
v1_api.register(CampaignResource())
v1_api.register(LocationResource())
v1_api.register(IndicatorResource())
v1_api.register(OfficeResource())
v1_api.register(CampaignTypeResource())
v1_api.register(LocationTypeResource())
v1_api.register(IndicatorTagResource())
v1_api.register(IndicatorToTagResource())
v1_api.register(DashboardResource())
v1_api.register(DocumentResource())
v1_api.register(GroupResource())
v1_api.register(UserGroupResource())
v1_api.register(LocationPermissionResource())
v1_api.register(GroupPermissionResource())
v1_api.register(DocumentReviewResource())
v1_api.register(SourceObjectMapResource())
v1_api.register(UserResource())
v1_api.register(SourceSubmissionResource())
v1_api.register(DocumentDetailResource())
v1_api.register(DocDataPointResource())
v1_api.register(ComputedDataPointResource())
v1_api.register(RefreshMasterResource())
v1_api.register(DocDetailTypeResource())
v1_api.register(DocTransFormResource())
v1_api.register(CalculatedIndicatorComponentResource())
v1_api.register(BaseIndicatorResource())
v1_api.register(CacheRefreshResource())

urlpatterns = patterns('',

    ## TASTYPIE API ##
    (r'^api/', include(v1_api.urls)),

    ## HOME PAGE
    url(r'^$', login_required(TemplateView.as_view(template_name="index.html")), name='index'),

    ## BASE DATPOINT FUNCTINOALITY ( see datapoints/urls )
    url(r'^datapoints/', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),

    ## DASHBOARD WITH URL PARAMS ##
    url(r'^datapoints/[-a-zA-Z]+/$', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),
    url(r'^datapoints/[-a-zA-Z]+/[^/]+/[0-9]{4}/[0-9]{2}/$', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),
    url(r'^datapoints/source-data/[-a-zA-Z]+/[0-9]{4}/[0-9]{2}/[-a-zA-Z]+/[0-9]+/', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),

    ## CORE SOURCE DATA FUNCTINOALITY
    url(r'^source_data/', decorator_include(login_required,'source_data.urls', namespace="source_data")),

    ## ADMIN, LOG IN AND LOGOUT
    url(r'^admin/', decorator_include(login_required,admin.site.urls)),
    url(r'^accounts/login/$', login, name='login'),
    url(r'^accounts/logout/$', logout, name='logout'),

    ## UFADMIN ##
    url(r'^ufadmin/', login_required(TemplateView.as_view(template_name='ufadmin.html')), name='ufadmin'),

    ## DOCUMENT_REVIEW ##
    url(r'^doc_review/', TemplateView.as_view(template_name="doc_review.html"), name='doc_review'),

    ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^debug/', debug),
    )
<commit_msg>remove source_data name space from URLs<commit_after>from django.conf.urls import patterns, include, url
from django.contrib.auth.views import login, logout
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth.decorators import login_required
from django.views.generic.base import RedirectView
from django.views.generic import TemplateView
from decorator_include import decorator_include

from datapoints.api.meta_data import *
from datapoints.api.datapoint import DataPointResource, DataPointEntryResource
from datapoints.views import debug
from datapoints import views

from tastypie.api import Api

admin.autodiscover()

## tastypie endpoints - ##
v1_api = Api(api_name='v1')
v1_api.register(DataPointResource())
v1_api.register(DataPointEntryResource())
v1_api.register(GeoResource())
v1_api.register(CampaignResource())
v1_api.register(LocationResource())
v1_api.register(IndicatorResource())
v1_api.register(OfficeResource())
v1_api.register(CampaignTypeResource())
v1_api.register(LocationTypeResource())
v1_api.register(IndicatorTagResource())
v1_api.register(IndicatorToTagResource())
v1_api.register(DashboardResource())
v1_api.register(DocumentResource())
v1_api.register(GroupResource())
v1_api.register(UserGroupResource())
v1_api.register(LocationPermissionResource())
v1_api.register(GroupPermissionResource())
v1_api.register(DocumentReviewResource())
v1_api.register(SourceObjectMapResource())
v1_api.register(UserResource())
v1_api.register(SourceSubmissionResource())
v1_api.register(DocumentDetailResource())
v1_api.register(DocDataPointResource())
v1_api.register(ComputedDataPointResource())
v1_api.register(RefreshMasterResource())
v1_api.register(DocDetailTypeResource())
v1_api.register(DocTransFormResource())
v1_api.register(CalculatedIndicatorComponentResource())
v1_api.register(BaseIndicatorResource())
v1_api.register(CacheRefreshResource())

urlpatterns = patterns('',

    ## TASTYPIE API ##
    (r'^api/', include(v1_api.urls)),

    ## HOME PAGE
    url(r'^$', login_required(TemplateView.as_view(template_name="index.html")), name='index'),

    ## BASE DATPOINT FUNCTINOALITY ( see datapoints/urls )
    url(r'^datapoints/', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),

    ## DASHBOARD WITH URL PARAMS ##
    url(r'^datapoints/[-a-zA-Z]+/$', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),
    url(r'^datapoints/[-a-zA-Z]+/[^/]+/[0-9]{4}/[0-9]{2}/$', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),
    url(r'^datapoints/source-data/[-a-zA-Z]+/[0-9]{4}/[0-9]{2}/[-a-zA-Z]+/[0-9]+/', decorator_include(login_required,'datapoints.urls', namespace="datapoints")),

    ## ADMIN, LOG IN AND LOGOUT
    url(r'^admin/', decorator_include(login_required,admin.site.urls)),
    url(r'^accounts/login/$', login, name='login'),
    url(r'^accounts/logout/$', logout, name='logout'),

    ## UFADMIN ##
    url(r'^ufadmin/', login_required(TemplateView.as_view(template_name='ufadmin.html')), name='ufadmin'),

    ## DOCUMENT_REVIEW ##
    url(r'^doc_review/', TemplateView.as_view(template_name="doc_review.html"), name='doc_review'),

    ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^debug/', debug),
    )
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright (C) 2008 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.com/license.html.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/.

import os.path
import sys

from genshi.builder import tag

from trac.admin import IAdminCommandProvider, IAdminPanelProvider
from trac.config import ListOption
from trac.core import *
from trac.perm import IPermissionRequestor
from trac.util import as_bool, is_path_below
from trac.util.compat import any
from trac.util.text import breakable_path, normalize_whitespace, print_table, \
                           printout
from trac.util.translation import _, ngettext, tag_
from trac.versioncontrol import DbRepositoryProvider, InvalidRepository, \
                                NoSuchChangeset, RepositoryManager, is_default
from trac.web.chrome import Chrome, add_notice, add_warning

class VersionControlAdmin(Component):
    """trac-admin command provider for version control administration."""

    implements(IAdminCommandProvider, IPermissionRequestor)

    # IAdminCommandProvider methods

    def get_admin_commands(self):
        yield ('changeset added', '<repos> <rev> [rev] [...]',
               """Notify trac about changesets added to a repository

               This command should be called from a post-commit hook. It will
               trigger a cache update and notify components about the addition.
               """,
               self._complete_repos, self._do_changeset_added)
        yield ('changeset modified', '<repos> <rev> [rev] [...]',
               """Notify trac about changesets modified in a repository

               This command should be called from a post-revprop hook after
               revision properties like the commit message, author or date
               have been changed. It will trigger a cache update for the given
               revisions and notify components about the change.
               """,
               self._complete_repos, self._do_changeset_modified)
        yield ('repository list', '',
               'List source repositories',
               None, self._do_list)
        yield ('repository resync', '<repos> [rev]',
               """Re-synchronize trac with repositories

               When [rev] is specified, only that revision is synchronized.
               Otherwise, the complete revision history is synchronized. Note
               that this operation can take a long time to complete.
               If synchronization gets interrupted, it can be resumed later
               using the `sync` command.

               To synchronize all repositories, specify "*" as the repository.
               """,
               self._complete_repos, self._do_resync)
        yield ('repository sync', '<repos> [rev]',
               """Resume synchronization of repositories

               It works like `resync`, except that it doesn't clear the already
               synchronized changesets, so it's a better way to resume an
               interrupted `resync`.

               See `resync` help for detailed usage.
               """,
               self._complete_repos, self._do_sync)

    def get_reponames(self):
        rm = RepositoryManager(self.env)
        return [reponame or '(default)' for reponame
                in rm.get_all_repositories()]

    def _complete_repos(self, args):
        if len(args) == 1:
            return self.get_reponames()

    def _do_changeset_added(self, reponame, *revs):
        if is_default(reponame):
            reponame = ''
        rm = RepositoryManager(self.env)
        errors = rm.notify('changeset_added', reponame, revs)
        for error in errors:
            printout(error)

    def _do_changeset_modified(self, reponame, *revs):
        if is_default(reponame):
            reponame = ''
        rm = RepositoryManager(self.env)
        errors = rm.notify('changeset_modified', reponame, revs)
        for error in errors:
            printout(error)

    def _do_list(self):
        rm = RepositoryManager(self.env)
        values = []
        for (reponame, info) in sorted(rm.get_all_repositories().iteritems()):
            alias = ''
            if 'alias' in info:
                alias = info['alias'] or '(default)'
            values.append((reponame or '(default)', info.get('type', ''),
                           alias, info.get('dir', '')))
        print_table(values, [_('Name'), _('Type'), _('Alias'), _('Directory')])

    def _sync(self, reponame, rev, clean):
        rm = RepositoryManager(self.env)
        if reponame == '*':
            if rev is not None:
                raise TracError(_('Cannot synchronize a single revision '
                                  'on multiple repositories'))
            repositories = rm.get_real_repositories()
        else:
            if is_default(reponame):
                reponame = ''
            repos = rm.get_repository(reponame)
            if repos is None:
                raise TracError(_("Repository '%(repo)s' not found",
                                  repo=reponame or '(default)'))
            if rev is not None:
                repos.sync_changeset(rev)
                printout(_('%(rev)s resynced on %(reponame)s.', rev=rev,
                           reponame=repos.reponame or '(default)'))
                return
            repositories = [repos]

        for repos in sorted(repositories, key=lambda r: r.reponame):
            printout(_('Resyncing repository history for %(reponame)s... ',
                       reponame=repos.reponame or '(default)'))
            repos.sync(self._sync_feedback, clean=clean)
            for cnt, in self.env.db_query(
                    "SELECT count(rev) FROM revision WHERE repos=%s",
                    (repos.id,)):
                printout(ngettext('%(num)s revision cached.',
                                  '%(num)s revisions cached.', num=cnt))
        printout(_('Done.'))

    def _sync_feedback(self, rev):
        sys.stdout.write(' [%s]\r' % rev)
        sys.stdout.flush()

    def _do_resync(self, reponame, rev=None):
        self._sync(reponame, rev, clean=True)

    def _do_sync(self, reponame, rev=None):
        self._sync(reponame, rev, clean=False)

    # IPermissionRequestor methods

    def get_permission_actions(self):
        return [('VERSIONCONTROL_ADMIN', ['BROWSER_VIEW', 'CHANGESET_VIEW',
                                          'FILE_VIEW', 'LOG_VIEW'])]

class RepositoryAdminPanel(Component):
    """Web admin panel for repository administration."""

    implements(IAdminPanelProvider)

    allowed_repository_dir_prefixes = ListOption('versioncontrol',
        'allowed_repository_dir_prefixes', '',
        doc="""Comma-separated list of allowed prefixes for repository
        directories when adding and editing repositories in the repository
        admin panel. If the list is empty, all repository directories are
        allowed. (''since 0.12.1'')""")

    # IAdminPanelProvider methods

    def get_admin_panels(self, req):
        if 'VERSIONCONTROL_ADMIN' in req.perm('admin', 'versioncontrol/repository'):
            yield ('versioncontrol', _('Version Control'), 'repository',
                   _('Repositories'))

    def render_admin_panel(self, req, category, page, path_info):
        # Retrieve info for all repositories
        rm = RepositoryManager(self.env)
        all_repos = rm.get_all_repositories()
        db_provider = self.env[DbRepositoryProvider]

        if path_info:
            # Detail view
            reponame = path_info if not is_default(path_info) else ''
            info = all_repos.get(reponame)
            if info is None:
                raise TracError(_("Repository '%(repo)s' not found",
                                  repo=path_info))
            if req.method == 'POST':
                if req.args.get('cancel'):
                    req.redirect(req.href.admin(category, page))

                elif db_provider and req.args.get('save'):
                    # Modify repository
                    changes = {}
                    valid = True
                    for field in db_provider.repository_attrs:
                        value = normalize_whitespace(req.args.get(field))
                        if (value is not None or field == 'hidden') \
                                and value != info.get(field):
                            changes[field] = value
                    if 'dir' in changes and not \
                            self._check_dir(req, changes['dir']):
                        valid = False
                    if valid and changes:
                        db_provider.modify_repository(reponame, changes)
                        add_notice(req, _('Your changes have been saved.'))
                        name = req.args.get('name')
                        resync = tag.tt('trac-admin %s repository resync '
                                        '"%s"' % (self.env.path,
                                                  name or '(default)'))
                        if 'dir' in changes:
                            msg = tag_('You should now run %(resync)s to '
                                       'synchronize Trac with the repository.',
                                       resync=resync)
                            add_notice(req, msg)
                        elif 'type' in changes:
                            msg = tag_('You may have to run %(resync)s to '
                                       'synchronize Trac with the repository.',
                                       resync=resync)
                            add_notice(req, msg)
                        if name and name != path_info and not 'alias' in info:
                            cset_added = tag.tt('trac-admin %s changeset '
                                                'added "%s" $REV'
                                                % (self.env.path,
                                                   name or '(default)'))
                            msg = tag_('You will need to update your '
                                       'post-commit hook to call '
                                       '%(cset_added)s with the new '
                                       'repository name.',
                                       cset_added=cset_added)
                            add_notice(req, msg)
                    if valid:
                        req.redirect(req.href.admin(category, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'reponame': reponame}

        else:
            # List view
            if req.method == 'POST':
                # Add a repository
                if db_provider and req.args.get('add_repos'):
                    name = req.args.get('name')
                    type_ = req.args.get('type')
                    # Avoid errors when copy/pasting paths
                    dir = normalize_whitespace(req.args.get('dir', ''))
                    if name is None or type_ is None or not dir:
                        add_warning(req, _('Missing arguments to add a '
                                           'repository.'))
                    elif self._check_dir(req, dir):
                        try:
                            db_provider.add_repository(name, dir, type_)
                        except self.env.db_exc.IntegrityError:
                            name = name or '(default)'
                            raise TracError(_('The repository "%(name)s" '
                                              'already exists.', name=name))
                        name = name or '(default)'
                        add_notice(req, _('The repository "%(name)s" has been '
                                          'added.', name=name))
                        resync = tag.tt('trac-admin %s repository resync '
                                        '"%s"' % (self.env.path, name))
                        msg = tag_('You should now run %(resync)s to '
                                   'synchronize Trac with the repository.',
                                   resync=resync)
                        add_notice(req, msg)
                        cset_added = tag.tt('trac-admin %s changeset '
                                            'added "%s" $REV'
                                            % (self.env.path, name))
                        doc = tag.a(_("documentation"),
                                    href=req.href.wiki('TracRepositoryAdmin')
                                         + '#Synchronization')
                        msg = tag_('You should also set up a post-commit hook '
                                   'on the repository to call %(cset_added)s '
                                   'for each committed changeset. See the '
                                   '%(doc)s for more information.',
                                   cset_added=cset_added, doc=doc)
                        add_notice(req, msg)
                        req.redirect(req.href.admin(category, page))

                # Add a repository alias
                elif db_provider and req.args.get('add_alias'):
                    name = req.args.get('name')
                    alias = req.args.get('alias')
                    if name is not None and alias is not None:
                        try:
                            db_provider.add_alias(name, alias)
                        except self.env.db_exc.IntegrityError:
                            raise TracError(_('The alias "%(name)s" already '
                                              'exists.',
                                              name=name or '(default)'))
                        add_notice(req, _('The alias "%(name)s" has been '
                                          'added.', name=name or '(default)'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('Missing arguments to add an '
                                       'alias.'))

                # Refresh the list of repositories
                elif req.args.get('refresh'):
                    req.redirect(req.href.admin(category, page))

                # Remove repositories
                elif db_provider and req.args.get('remove'):
                    sel = req.args.getlist('sel')
                    if sel:
                        for name in sel:
                            db_provider.remove_repository(name)
                        add_notice(req, _('The selected repositories have '
                                          'been removed.'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('No repositories were selected.'))

            data = {'view': 'list'}

        # Find repositories that are editable
        db_repos = {}
        if db_provider is not None:
            db_repos = dict(db_provider.get_repositories())

        # Prepare common rendering data
        repositories = dict((reponame, self._extend_info(reponame, info.copy(),
                                                         reponame in db_repos))
                            for (reponame, info) in all_repos.iteritems())
        types = sorted([''] + rm.get_supported_types())
        data.update({'types': types, 'default_type': rm.repository_type,
                     'repositories': repositories})

        return 'admin_repositories.html', data

    def _extend_info(self, reponame, info, editable):
        """Extend repository info for rendering."""
        info['name'] = reponame
        if info.get('dir') is not None:
            info['prettydir'] = breakable_path(info['dir']) or ''
        info['hidden'] = as_bool(info.get('hidden'))
        info['editable'] = editable
        if not info.get('alias'):
            try:
                repos = RepositoryManager(self.env).get_repository(reponame)
            except InvalidRepository, e:
                info['error'] = e
            except TracError:
                pass  # Probably "unsupported connector"
            else:
                youngest_rev = repos.get_youngest_rev()
                info['rev'] = youngest_rev
                try:
                    info['display_rev'] = repos.display_rev(youngest_rev)
                except NoSuchChangeset:
                    pass
        return info

    def _check_dir(self, req, dir):
        """Check that a repository directory is valid, and add a warning
        message if not.
        """
        if not os.path.isabs(dir):
            add_warning(req, _('The repository directory must be an absolute '
                               'path.'))
            return False
        prefixes = [os.path.join(self.env.path, prefix)
                    for prefix in self.allowed_repository_dir_prefixes]
        if prefixes and not any(is_path_below(dir, prefix)
                                for prefix in prefixes):
            add_warning(req, _('The repository directory must be located '
                               'below one of the following directories: '
                               '%(dirs)s', dirs=', '.join(prefixes)))
            return False
        return True
<commit_msg>1.0.5dev: Refactoring: `pretty_dir` is only relevant for non-alias repositories, so move inside conditional.<commit_after># -*- coding: utf-8 -*-
#
# Copyright (C) 2008 Edgewall Software
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.com/license.html.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/.

import os.path
import sys

from genshi.builder import tag

from trac.admin import IAdminCommandProvider, IAdminPanelProvider
from trac.config import ListOption
from trac.core import *
from trac.perm import IPermissionRequestor
from trac.util import as_bool, is_path_below
from trac.util.compat import any
from trac.util.text import breakable_path, normalize_whitespace, print_table, \
                           printout
from trac.util.translation import _, ngettext, tag_
from trac.versioncontrol import DbRepositoryProvider, InvalidRepository, \
                                NoSuchChangeset, RepositoryManager, is_default
from trac.web.chrome import Chrome, add_notice, add_warning

class VersionControlAdmin(Component):
    """trac-admin command provider for version control administration."""

    implements(IAdminCommandProvider, IPermissionRequestor)

    # IAdminCommandProvider methods

    def get_admin_commands(self):
        yield ('changeset added', '<repos> <rev> [rev] [...]',
               """Notify trac about changesets added to a repository

               This command should be called from a post-commit hook. It will
               trigger a cache update and notify components about the addition.
               """,
               self._complete_repos, self._do_changeset_added)
        yield ('changeset modified', '<repos> <rev> [rev] [...]',
               """Notify trac about changesets modified in a repository

               This command should be called from a post-revprop hook after
               revision properties like the commit message, author or date
               have been changed. It will trigger a cache update for the given
               revisions and notify components about the change.
               """,
               self._complete_repos, self._do_changeset_modified)
        yield ('repository list', '',
               'List source repositories',
               None, self._do_list)
        yield ('repository resync', '<repos> [rev]',
               """Re-synchronize trac with repositories

               When [rev] is specified, only that revision is synchronized.
               Otherwise, the complete revision history is synchronized. Note
               that this operation can take a long time to complete.
               If synchronization gets interrupted, it can be resumed later
               using the `sync` command.

               To synchronize all repositories, specify "*" as the repository.
               """,
               self._complete_repos, self._do_resync)
        yield ('repository sync', '<repos> [rev]',
               """Resume synchronization of repositories

               It works like `resync`, except that it doesn't clear the already
               synchronized changesets, so it's a better way to resume an
               interrupted `resync`.

               See `resync` help for detailed usage.
               """,
               self._complete_repos, self._do_sync)

    def get_reponames(self):
        rm = RepositoryManager(self.env)
        return [reponame or '(default)' for reponame
                in rm.get_all_repositories()]

    def _complete_repos(self, args):
        if len(args) == 1:
            return self.get_reponames()

    def _do_changeset_added(self, reponame, *revs):
        if is_default(reponame):
            reponame = ''
        rm = RepositoryManager(self.env)
        errors = rm.notify('changeset_added', reponame, revs)
        for error in errors:
            printout(error)

    def _do_changeset_modified(self, reponame, *revs):
        if is_default(reponame):
            reponame = ''
        rm = RepositoryManager(self.env)
        errors = rm.notify('changeset_modified', reponame, revs)
        for error in errors:
            printout(error)

    def _do_list(self):
        rm = RepositoryManager(self.env)
        values = []
        for (reponame, info) in sorted(rm.get_all_repositories().iteritems()):
            alias = ''
            if 'alias' in info:
                alias = info['alias'] or '(default)'
            values.append((reponame or '(default)', info.get('type', ''),
                           alias, info.get('dir', '')))
        print_table(values, [_('Name'), _('Type'), _('Alias'), _('Directory')])

    def _sync(self, reponame, rev, clean):
        rm = RepositoryManager(self.env)
        if reponame == '*':
            if rev is not None:
                raise TracError(_('Cannot synchronize a single revision '
                                  'on multiple repositories'))
            repositories = rm.get_real_repositories()
        else:
            if is_default(reponame):
                reponame = ''
            repos = rm.get_repository(reponame)
            if repos is None:
                raise TracError(_("Repository '%(repo)s' not found",
                                  repo=reponame or '(default)'))
            if rev is not None:
                repos.sync_changeset(rev)
                printout(_('%(rev)s resynced on %(reponame)s.', rev=rev,
                           reponame=repos.reponame or '(default)'))
                return
            repositories = [repos]

        for repos in sorted(repositories, key=lambda r: r.reponame):
            printout(_('Resyncing repository history for %(reponame)s... ',
                       reponame=repos.reponame or '(default)'))
            repos.sync(self._sync_feedback, clean=clean)
            for cnt, in self.env.db_query(
                    "SELECT count(rev) FROM revision WHERE repos=%s",
                    (repos.id,)):
                printout(ngettext('%(num)s revision cached.',
                                  '%(num)s revisions cached.', num=cnt))
        printout(_('Done.'))

    def _sync_feedback(self, rev):
        sys.stdout.write(' [%s]\r' % rev)
        sys.stdout.flush()

    def _do_resync(self, reponame, rev=None):
        self._sync(reponame, rev, clean=True)

    def _do_sync(self, reponame, rev=None):
        self._sync(reponame, rev, clean=False)

    # IPermissionRequestor methods

    def get_permission_actions(self):
        return [('VERSIONCONTROL_ADMIN', ['BROWSER_VIEW', 'CHANGESET_VIEW',
                                          'FILE_VIEW', 'LOG_VIEW'])]

class RepositoryAdminPanel(Component):
    """Web admin panel for repository administration."""

    implements(IAdminPanelProvider)

    allowed_repository_dir_prefixes = ListOption('versioncontrol',
        'allowed_repository_dir_prefixes', '',
        doc="""Comma-separated list of allowed prefixes for repository
        directories when adding and editing repositories in the repository
        admin panel. If the list is empty, all repository directories are
        allowed. (''since 0.12.1'')""")

    # IAdminPanelProvider methods

    def get_admin_panels(self, req):
        if 'VERSIONCONTROL_ADMIN' in req.perm('admin', 'versioncontrol/repository'):
            yield ('versioncontrol', _('Version Control'), 'repository',
                   _('Repositories'))

    def render_admin_panel(self, req, category, page, path_info):
        # Retrieve info for all repositories
        rm = RepositoryManager(self.env)
        all_repos = rm.get_all_repositories()
        db_provider = self.env[DbRepositoryProvider]

        if path_info:
            # Detail view
            reponame = path_info if not is_default(path_info) else ''
            info = all_repos.get(reponame)
            if info is None:
                raise TracError(_("Repository '%(repo)s' not found",
                                  repo=path_info))
            if req.method == 'POST':
                if req.args.get('cancel'):
                    req.redirect(req.href.admin(category, page))

                elif db_provider and req.args.get('save'):
                    # Modify repository
                    changes = {}
                    valid = True
                    for field in db_provider.repository_attrs:
                        value = normalize_whitespace(req.args.get(field))
                        if (value is not None or field == 'hidden') \
                                and value != info.get(field):
                            changes[field] = value
                    if 'dir' in changes and not \
                            self._check_dir(req, changes['dir']):
                        valid = False
                    if valid and changes:
                        db_provider.modify_repository(reponame, changes)
                        add_notice(req, _('Your changes have been saved.'))
                        name = req.args.get('name')
                        resync = tag.tt('trac-admin %s repository resync '
                                        '"%s"' % (self.env.path,
                                                  name or '(default)'))
                        if 'dir' in changes:
                            msg = tag_('You should now run %(resync)s to '
                                       'synchronize Trac with the repository.',
                                       resync=resync)
                            add_notice(req, msg)
                        elif 'type' in changes:
                            msg = tag_('You may have to run %(resync)s to '
                                       'synchronize Trac with the repository.',
                                       resync=resync)
                            add_notice(req, msg)
                        if name and name != path_info and not 'alias' in info:
                            cset_added = tag.tt('trac-admin %s changeset '
                                                'added "%s" $REV'
                                                % (self.env.path,
                                                   name or '(default)'))
                            msg = tag_('You will need to update your '
                                       'post-commit hook to call '
                                       '%(cset_added)s with the new '
                                       'repository name.',
                                       cset_added=cset_added)
                            add_notice(req, msg)
                    if valid:
                        req.redirect(req.href.admin(category, page))

            Chrome(self.env).add_wiki_toolbars(req)
            data = {'view': 'detail', 'reponame': reponame}

        else:
            # List view
            if req.method == 'POST':
                # Add a repository
                if db_provider and req.args.get('add_repos'):
                    name = req.args.get('name')
                    type_ = req.args.get('type')
                    # Avoid errors when copy/pasting paths
                    dir = normalize_whitespace(req.args.get('dir', ''))
                    if name is None or type_ is None or not dir:
                        add_warning(req, _('Missing arguments to add a '
                                           'repository.'))
                    elif self._check_dir(req, dir):
                        try:
                            db_provider.add_repository(name, dir, type_)
                        except self.env.db_exc.IntegrityError:
                            name = name or '(default)'
                            raise TracError(_('The repository "%(name)s" '
                                              'already exists.', name=name))
                        name = name or '(default)'
                        add_notice(req, _('The repository "%(name)s" has been '
                                          'added.', name=name))
                        resync = tag.tt('trac-admin %s repository resync '
                                        '"%s"' % (self.env.path, name))
                        msg = tag_('You should now run %(resync)s to '
                                   'synchronize Trac with the repository.',
                                   resync=resync)
                        add_notice(req, msg)
                        cset_added = tag.tt('trac-admin %s changeset '
                                            'added "%s" $REV'
                                            % (self.env.path, name))
                        doc = tag.a(_("documentation"),
                                    href=req.href.wiki('TracRepositoryAdmin')
                                         + '#Synchronization')
                        msg = tag_('You should also set up a post-commit hook '
                                   'on the repository to call %(cset_added)s '
                                   'for each committed changeset. See the '
                                   '%(doc)s for more information.',
                                   cset_added=cset_added, doc=doc)
                        add_notice(req, msg)
                        req.redirect(req.href.admin(category, page))

                # Add a repository alias
                elif db_provider and req.args.get('add_alias'):
                    name = req.args.get('name')
                    alias = req.args.get('alias')
                    if name is not None and alias is not None:
                        try:
                            db_provider.add_alias(name, alias)
                        except self.env.db_exc.IntegrityError:
                            raise TracError(_('The alias "%(name)s" already '
                                              'exists.',
                                              name=name or '(default)'))
                        add_notice(req, _('The alias "%(name)s" has been '
                                          'added.', name=name or '(default)'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('Missing arguments to add an '
                                       'alias.'))

                # Refresh the list of repositories
                elif req.args.get('refresh'):
                    req.redirect(req.href.admin(category, page))

                # Remove repositories
                elif db_provider and req.args.get('remove'):
                    sel = req.args.getlist('sel')
                    if sel:
                        for name in sel:
                            db_provider.remove_repository(name)
                        add_notice(req, _('The selected repositories have '
                                          'been removed.'))
                        req.redirect(req.href.admin(category, page))
                    add_warning(req, _('No repositories were selected.'))

            data = {'view': 'list'}

        # Find repositories that are editable
        db_repos = {}
        if db_provider is not None:
            db_repos = dict(db_provider.get_repositories())

        # Prepare common rendering data
        repositories = dict((reponame, self._extend_info(reponame, info.copy(),
                                                         reponame in db_repos))
                            for (reponame, info) in all_repos.iteritems())
        types = sorted([''] + rm.get_supported_types())
        data.update({'types': types, 'default_type': rm.repository_type,
                     'repositories': repositories})

        return 'admin_repositories.html', data

    def _extend_info(self, reponame, info, editable):
        """Extend repository info for rendering."""
        info['name'] = reponame
        info['hidden'] = as_bool(info.get('hidden'))
        info['editable'] = editable
        if not info.get('alias'):
            if info.get('dir') is not None:
                info['prettydir'] = breakable_path(info['dir']) or ''
            try:
                repos = RepositoryManager(self.env).get_repository(reponame)
            except InvalidRepository, e:
                info['error'] = e
            except TracError:
                pass  # Probably "unsupported connector"
            else:
                youngest_rev = repos.get_youngest_rev()
                info['rev'] = youngest_rev
                try:
                    info['display_rev'] = repos.display_rev(youngest_rev)
                except NoSuchChangeset:
                    pass
        return info

    def _check_dir(self, req, dir):
        """Check that a repository directory is valid, and add a warning
        message if not.
        """
        if not os.path.isabs(dir):
            add_warning(req, _('The repository directory must be an absolute '
                               'path.'))
            return False
        prefixes = [os.path.join(self.env.path, prefix)
                    for prefix in self.allowed_repository_dir_prefixes]
        if prefixes and not any(is_path_below(dir, prefix)
                                for prefix in prefixes):
            add_warning(req, _('The repository directory must be located '
                               'below one of the following directories: '
                               '%(dirs)s', dirs=', '.join(prefixes)))
            return False
        return True
<|endoftext|>


<commit_before>from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
from restclients.gws import GWS
import logging
from myuw_mobile.user import UserService
from myuw_mobile.logger.timer import Timer
from myuw_mobile.logger.util import log_invalid_netid_response, log_success_response

def support(request):
    timer = Timer()
    logger = logging.getLogger('myuw_mobile.views.support')

    user_service = UserService()
    user_service.get_user()
    # Do the group auth here.

    if not hasattr(settings, "MYUW_ADMIN_GROUP"):
        print "You must have a group in GWS defined as your admin group."
        print 'Configure that using MYUW_ADMIN_GROUP="u_foo_bar"'
        raise Exception("Missing MYUW_ADMIN_GROUP in settings")

    actual_user = user_service.get_original_user()
    if not actual_user:
        log_invalid_netid_response(logger, timer)
        return

    gws = GWS()
    members = gws.get_effective_members(settings.MYUW_ADMIN_GROUP)

    is_admin = False

    for member in members:
        if member.uwnetid == actual_user:
            is_admin = True
            break

    if is_admin == False:
        return  HttpResponseRedirect("/mobile")

    if "override_as" in request.POST:
        user_service.set_override_user(request.POST["override_as"])

    if "clear_override" in request.POST:
        user_service.clear_override()

    context = {
        'original_user': user_service.get_original_user(),
        'override_user': user_service.get_override_user(),
    }
    log_success_response(logger, timer)
    return render_to_response('support.html',
                              context,
                              context_instance=RequestContext(request))

<commit_msg>Moving to is_effective_member<commit_after>from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
from restclients.gws import GWS
import logging
from myuw_mobile.user import UserService
from myuw_mobile.logger.timer import Timer
from myuw_mobile.logger.util import log_invalid_netid_response, log_success_response

def support(request):
    timer = Timer()
    logger = logging.getLogger('myuw_mobile.views.support')

    user_service = UserService()
    user_service.get_user()
    # Do the group auth here.

    if not hasattr(settings, "MYUW_ADMIN_GROUP"):
        print "You must have a group in GWS defined as your admin group."
        print 'Configure that using MYUW_ADMIN_GROUP="u_foo_bar"'
        raise Exception("Missing MYUW_ADMIN_GROUP in settings")

    actual_user = user_service.get_original_user()
    if not actual_user:
        log_invalid_netid_response(logger, timer)
        return

    gws = GWS()
    is_admin = gws.is_effective_member(settings.MYUW_ADMIN_GROUP, actual_user)

    if is_admin == False:
        return  HttpResponseRedirect("/mobile")

    if "override_as" in request.POST:
        user_service.set_override_user(request.POST["override_as"])

    if "clear_override" in request.POST:
        user_service.clear_override()

    context = {
        'original_user': user_service.get_original_user(),
        'override_user': user_service.get_override_user(),
    }
    log_success_response(logger, timer)
    return render_to_response('support.html',
                              context,
                              context_instance=RequestContext(request))

<|endoftext|>


<commit_before>"""
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""
import logging
from decimal import Decimal

from rest_framework import serializers
from django.contrib.gis.geos import GEOSGeometry, Point

from gwells.utils import isPointInsideBC
from wells.models import Well
from aquifers.models.vertical_aquifer_extents import VerticalAquiferExtent

logger = logging.getLogger(__name__)

class WellLocationSerializerV2(serializers.ModelSerializer):
    """ serializes well locations """

    class Meta:
        model = Well
        fields = ("well_tag_number", "identification_plate_number",
                  "latitude", "longitude", "street_address", "city", "ems")

class WellVerticalAquiferExtentSerializerV2(serializers.ModelSerializer):
    # start = serializers.DecimalField(max_digits=7, decimal_places=2, required=True, allow_null=False)
    aquifer_id = serializers.IntegerField()
    aquifer_name = serializers.CharField(source='aquifer.aquifer_name', read_only=True)
    well_tag_number = serializers.IntegerField(write_only=True)

    class Meta:
        model = VerticalAquiferExtent
        fields = (
            'id',
            'aquifer_id',
            'aquifer_name',
            'well_tag_number',
            'start',
            'end',
            'geom'
        )

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        if instance.geom:
            ret['lat'] = Decimal(instance.geom.y)
            ret['lng'] = Decimal(instance.geom.x)
        del ret['geom']
        return ret

    def to_internal_value(self, data):
        latitude = data.pop('lat', None)
        longitude = data.pop('lng', None)
        well_tag_number = data.get('well_tag_number', None)

        errors = {}
        if well_tag_number:
            well = Well.objects.get(well_tag_number=well_tag_number)
            if well.geom:
                longitude = well.geom.x
                latitude = well.geom.y
        else:
            if latitude == '' or latitude is None:
                errors['lat'] = ['This field is required.']
            if longitude == '' or longitude is None:
                errors['lng'] = ['This field is required.']

        if len(errors) > 0:
            raise serializers.ValidationError(errors)

        point = Point(-abs(float(longitude)), float(latitude), srid=4326)

        data['geom'] = point
        return super(WellVerticalAquiferExtentSerializerV2, self).to_internal_value(data)

    def validate(self, attrs):
        errors = {}

        start_depth = attrs.get('start', None)
        end_depth = attrs.get('end', None)
        if start_depth is not None and end_depth is not None:
            if start_depth > end_depth:
                errors['end'] = 'To can not be above from'
            if abs(end_depth - start_depth) < Decimal('0.1'):
                errors['end'] = 'End must be more then 0.1m from start'

        point = attrs.get('geom')
        if point:
            isInside = isPointInsideBC(point.y, point.x)
            if not isInside:
                errors['lat'] = 'Latitude is not inside BC'
                errors['lng'] = 'Longitude is not inside BC'

        if len(errors) > 0:
            raise serializers.ValidationError(errors)

        return attrs

    def create(self, validated_data):
        well_tag_number = validated_data.pop('well_tag_number', None)
        well = Well.objects.get(well_tag_number=well_tag_number)
        validated_data['well'] = well
        return super().create(validated_data)
<commit_msg>Allow overwriting lat/lng even when a well is specified for a vertical aquifer extent<commit_after>"""
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
"""
import logging
from decimal import Decimal

from rest_framework import serializers
from django.contrib.gis.geos import GEOSGeometry, Point

from gwells.utils import isPointInsideBC
from wells.models import Well
from aquifers.models.vertical_aquifer_extents import VerticalAquiferExtent

logger = logging.getLogger(__name__)

class WellLocationSerializerV2(serializers.ModelSerializer):
    """ serializes well locations """

    class Meta:
        model = Well
        fields = ("well_tag_number", "identification_plate_number",
                  "latitude", "longitude", "street_address", "city", "ems")

class WellVerticalAquiferExtentSerializerV2(serializers.ModelSerializer):
    # start = serializers.DecimalField(max_digits=7, decimal_places=2, required=True, allow_null=False)
    aquifer_id = serializers.IntegerField()
    aquifer_name = serializers.CharField(source='aquifer.aquifer_name', read_only=True)
    well_tag_number = serializers.IntegerField(write_only=True)

    class Meta:
        model = VerticalAquiferExtent
        fields = (
            'id',
            'aquifer_id',
            'aquifer_name',
            'well_tag_number',
            'start',
            'end',
            'geom'
        )

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        if instance.geom:
            ret['lat'] = Decimal(instance.geom.y)
            ret['lng'] = Decimal(instance.geom.x)
        del ret['geom']
        return ret

    def to_internal_value(self, data):
        latitude = data.pop('lat', None)
        longitude = data.pop('lng', None)
        well_tag_number = data.get('well_tag_number', None)

        errors = {}
        # If lat and lng are not in the payload then we want to use the well's lat lng
        if latitude is None and longitude is None and well_tag_number:
            well = Well.objects.get(well_tag_number=well_tag_number)
            if well.geom:
                longitude = well.geom.x
                latitude = well.geom.y

        if latitude == '' or latitude is None:
            errors['lat'] = ['This field is required.']
        if longitude == '' or longitude is None:
            errors['lng'] = ['This field is required.']

        if len(errors) > 0:
            raise serializers.ValidationError(errors)

        point = Point(-abs(float(longitude)), float(latitude), srid=4326)

        data['geom'] = point
        return super(WellVerticalAquiferExtentSerializerV2, self).to_internal_value(data)

    def validate(self, attrs):
        errors = {}

        start_depth = attrs.get('start', None)
        end_depth = attrs.get('end', None)
        if start_depth is not None and end_depth is not None:
            if start_depth > end_depth:
                errors['end'] = 'To can not be above from'
            if abs(end_depth - start_depth) < Decimal('0.1'):
                errors['end'] = 'End must be more then 0.1m from start'

        point = attrs.get('geom')
        if point:
            isInside = isPointInsideBC(point.y, point.x)
            if not isInside:
                errors['lat'] = 'Latitude is not inside BC'
                errors['lng'] = 'Longitude is not inside BC'

        if len(errors) > 0:
            raise serializers.ValidationError(errors)

        return attrs

    def create(self, validated_data):
        well_tag_number = validated_data.pop('well_tag_number', None)
        well = Well.objects.get(well_tag_number=well_tag_number)
        validated_data['well'] = well
        return super().create(validated_data)
<|endoftext|>


<commit_before>import os
from functools import reduce
from urllib.parse import quote
from flask import Flask, request, Markup, session, redirect, url_for, flash, render_template
from flask_migrate import upgrade as database_upgrade
from flask_moment import Moment
from flask_uploads import configure_uploads
from flask_login import current_user
from flask_qrcode import QRcode
from flask_datepicker import datepicker
from flask_colorpicker import colorpicker
from flask_fontpicker import fontpicker
from flask_minify import minify
from sqlalchemy.exc import OperationalError

from app.middleware import db, login_manager, files, gtranslator, gTTs, migrate
from app.printer import get_printers_usb
from app.views.administrate import administrate
from app.views.core import core
from app.views.customize import cust_app
from app.views.manage import manage_app
from app.utils import absolute_path, log_error, create_default_records
from app.database import Settings, Serial, Office
from app.tasks import start_tasks
from app.api.setup import setup_api
from app.constants import (SUPPORTED_LANGUAGES, SUPPORTED_MEDIA_FILES, VERSION, MIGRATION_FOLDER,
                           DATABASE_FILE, SECRET_KEY)

def create_app(config={}):
    ''' Create the flask app and setup extensions and blueprints.

    Returns
    -------
        app: Flask app
            app with settings and blueprints loadeds.
    '''
    app = Flask(__name__, static_folder=absolute_path('static'), template_folder=absolute_path('templates'))
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URI',
                                                           (f'sqlite:///{absolute_path(DATABASE_FILE)}'
                                                            '?check_same_thread=False'))
    app.config['DB_NAME'] = DATABASE_FILE
    # Autoreload if templates change
    app.config['TEMPLATES_AUTO_RELOAD'] = True
    # flask_upload settings
    # app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024 # Remove Upload limit. FIX ISSUE
    app.config['UPLOADED_FILES_DEST'] = absolute_path('static/multimedia')
    app.config['UPLOADED_FILES_ALLOW'] = reduce(lambda sum, group: sum + group, SUPPORTED_MEDIA_FILES)
    app.config['SECRET_KEY'] = SECRET_KEY
    app.config['RESTX_VALIDATE'] = True
    app.config.update(config)

    # Initiating extensions before registering blueprints
    Moment(app)
    QRcode(app)
    configure_uploads(app, files)
    login_manager.init_app(app)
    db.init_app(app)
    migrate.init_app(app, db=db)
    datepicker(app, local=['static/css/jquery-ui.min.css', 'static/jquery-ui.min.js'])
    colorpicker(app, local=['static/css/spectrum.css', 'static/spectrum.min.js'])
    fontpicker(app, local=['static/jquery-ui.min.js', 'static/css/jquery-ui.min.css', 'static/webfont.min.js',
                           'static/webfont.select.min.js', 'static/css/webfont.select.css'])
    gTTs.init_app(app)
    gtranslator.init_app(app)

    if app.config.get('GUNICORN', False):
        gtranslator.readonly = True
    else:
        minify(app, js=True, cssless=True, caching_limit=3, fail_safe=True,
               bypass=['.min.*', 'restx_doc.static'])

    # Register blueprints
    app.register_blueprint(administrate)
    app.register_blueprint(core)
    app.register_blueprint(cust_app)
    app.register_blueprint(manage_app)
    app.register_blueprint(setup_api(), url_prefix='/api/v1')
    app.jinja_env.add_extension('jinja2.ext.loopcontrols')

    return app

def create_db(app, testing=False):
    ''' Creating all non-existing tables and load initial data.

    Parameters
    ----------
        app: Flask app
            app to use its context to create tables and load initial data.
        testing: bool
            flag to disable migrations, mainly used during integration testing.
    '''
    with app.app_context():
        if not os.path.isfile(absolute_path(app.config.get('DB_NAME'))):
            db.create_all()
        else:
            try:
                database_upgrade(directory=absolute_path(MIGRATION_FOLDER))
            except Exception as exception:
                if not isinstance(exception, OperationalError):
                    log_error(exception, quiet=os.name == 'nt')
        create_default_records()

def bundle_app(config={}):
    ''' Create a Flask app, set settings, load extensions, blueprints and create database. '''
    app = create_app(config)

    # NOTE: avoid creating or interacting with the database during migration
    if not app.config.get('MIGRATION', False):
        create_db(app)
        start_tasks(app)

    if os.name != 'nt':
        # !!! it did not work creates no back-end available error !!!
        # !!! strange bug , do not remove !!!
        if get_printers_usb():
            pass

    @app.route('/language_switch/<language>')
    def language_switch(language):
        ''' Endpoint to switch the default language.

        Parameters
        ----------
            language: str
                language short form to switch to.
        '''
        session['lang'] = language

        if current_user.is_authenticated:
            return redirect(str(request.referrer))

        return redirect(url_for('core.root'))

    @app.before_first_request
    def default_language():
        ''' Set the default language before the first request. '''
        if session.get('lang') not in list(SUPPORTED_LANGUAGES.keys()):
            session['lang'] = 'en'

    @app.errorhandler(404)
    @app.errorhandler(500)
    @app.errorhandler(413)
    def page_not_found(error):
        ''' Adding error handlers on main app instance. '''
        if getattr(error, 'code', None) == 413:
            flash('Error: file uploaded is too large ', 'danger')
            if current_user.is_authenticated:
                return redirect(url_for('cust_app.multimedia', nn=1))
            return redirect(url_for('core.root'))

        getattr(error, 'code', None) != 404 and log_error(error)
        flash('Error: something wrong , or the page is non-existing', 'danger')
        return redirect(url_for('core.root'))

    @app.route('/nojs/<int:enabled_js>')
    def nojs(enabled_js):
        ''' Handle JavaScript disabled or not supported. '''
        if enabled_js == 1:
            next_url = session.get('next_url', '/')

            if next_url != '/':
                return redirect(next_url)

            return redirect(url_for('core.root'))
        return render_template('nojs.html', page_title='Javascript is disabled')

    def moment_wrapper(moment):
        ''' Temproray moment wrapper to add `.toTime()` and `.toNow()`
            TODO: Remove and update Flask-Moment when PR's mereged.
        '''
        def toTime(*args, **kwargs):
            content = str(moment.fromTime(*args, **kwargs))

            return Markup(content.replace('from(', 'to('))

        def toNow(*args, **kwargs):
            content = str(moment.fromNow(*args, **kwargs))

            return Markup(content.replace('fromNow(', 'toNow('))

        setattr(moment, 'toTime', toTime)
        setattr(moment, 'toNow', toNow)
        return moment

    @app.context_processor
    def inject_vars():
        ''' Injecting default variables to all templates. '''
        ar = session.get('lang') == 'AR'  # adding language support var

        # modifying side bar spacing for specific paths
        path = request.path
        admin_routes = ['/users', '/user_a', '/admin_u', '/user_u', '/csv', '/settings']
        admin_route = any([path in admin_routes, path[:7] in admin_routes, path[:5] in admin_routes])

        return dict(path=path, adme=admin_route, brp=Markup('
'), ar=ar, version=VERSION, str=str,
                    defLang=session.get('lang'), getattr=getattr, settings=Settings.get(), Serial=Serial,
                    checkId=lambda id, records: id in [i.id for i in records], offices=Office.query.all(),
                    moment_wrapper=moment_wrapper, current_path=quote(request.path, safe=''),
                    windows=os.name == 'nt', unix=os.name != 'nt', next=next, it=iter,
                    setattr=lambda *args, **kwargs: setattr(*args, **kwargs) or '')

    return app
<commit_msg>Refactor template global vars.<commit_after>import os
from functools import reduce
from urllib.parse import quote
from flask import Flask, request, Markup, session, redirect, url_for, flash, render_template
from flask_migrate import upgrade as database_upgrade
from flask_moment import Moment
from flask_uploads import configure_uploads
from flask_login import current_user
from flask_qrcode import QRcode
from flask_datepicker import datepicker
from flask_colorpicker import colorpicker
from flask_fontpicker import fontpicker
from flask_minify import minify
from sqlalchemy.exc import OperationalError

from app.middleware import db, login_manager, files, gtranslator, gTTs, migrate
from app.printer import get_printers_usb
from app.views.administrate import administrate
from app.views.core import core
from app.views.customize import cust_app
from app.views.manage import manage_app
from app.utils import absolute_path, log_error, create_default_records, get_bp_endpoints
from app.database import Settings, Serial, Office
from app.tasks import start_tasks
from app.api.setup import setup_api
from app.constants import (SUPPORTED_LANGUAGES, SUPPORTED_MEDIA_FILES, VERSION, MIGRATION_FOLDER,
                           DATABASE_FILE, SECRET_KEY)

def create_app(config={}):
    ''' Create the flask app and setup extensions and blueprints.

    Returns
    -------
        app: Flask app
            app with settings and blueprints loadeds.
    '''
    app = Flask(__name__, static_folder=absolute_path('static'), template_folder=absolute_path('templates'))
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URI',
                                                           (f'sqlite:///{absolute_path(DATABASE_FILE)}'
                                                            '?check_same_thread=False'))
    app.config['DB_NAME'] = DATABASE_FILE
    # Autoreload if templates change
    app.config['TEMPLATES_AUTO_RELOAD'] = True
    # flask_upload settings
    # app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024 # Remove Upload limit. FIX ISSUE
    app.config['UPLOADED_FILES_DEST'] = absolute_path('static/multimedia')
    app.config['UPLOADED_FILES_ALLOW'] = reduce(lambda sum, group: sum + group, SUPPORTED_MEDIA_FILES)
    app.config['SECRET_KEY'] = SECRET_KEY
    app.config['RESTX_VALIDATE'] = False
    app.config.update(config)

    # Initiating extensions before registering blueprints
    Moment(app)
    QRcode(app)
    configure_uploads(app, files)
    login_manager.init_app(app)
    db.init_app(app)
    migrate.init_app(app, db=db)
    datepicker(app, local=['static/css/jquery-ui.min.css', 'static/jquery-ui.min.js'])
    colorpicker(app, local=['static/css/spectrum.css', 'static/spectrum.min.js'])
    fontpicker(app, local=['static/jquery-ui.min.js', 'static/css/jquery-ui.min.css', 'static/webfont.min.js',
                           'static/webfont.select.min.js', 'static/css/webfont.select.css'])
    gTTs.init_app(app)
    gtranslator.init_app(app)

    if app.config.get('GUNICORN', False):
        gtranslator.readonly = True
    else:
        minify(app, js=True, cssless=True, caching_limit=3, fail_safe=True,
               bypass=['.min.*', 'restx_doc.static'])

    # Register blueprints
    app.register_blueprint(administrate)
    app.register_blueprint(core)
    app.register_blueprint(cust_app)
    app.register_blueprint(manage_app)
    app.register_blueprint(setup_api(), url_prefix='/api/v1')
    app.jinja_env.add_extension('jinja2.ext.loopcontrols')

    return app

def create_db(app, testing=False):
    ''' Creating all non-existing tables and load initial data.

    Parameters
    ----------
        app: Flask app
            app to use its context to create tables and load initial data.
        testing: bool
            flag to disable migrations, mainly used during integration testing.
    '''
    with app.app_context():
        if not os.path.isfile(absolute_path(app.config.get('DB_NAME'))):
            db.create_all()
        else:
            try:
                database_upgrade(directory=absolute_path(MIGRATION_FOLDER))
            except Exception as exception:
                if not isinstance(exception, OperationalError):
                    log_error(exception, quiet=os.name == 'nt')
        create_default_records()

def bundle_app(config={}):
    ''' Create a Flask app, set settings, load extensions, blueprints and create database. '''
    app = create_app(config)

    # NOTE: avoid creating or interacting with the database during migration
    if not app.config.get('MIGRATION', False):
        create_db(app)
        start_tasks(app)

    if os.name != 'nt':
        # !!! it did not work creates no back-end available error !!!
        # !!! strange bug , do not remove !!!
        if get_printers_usb():
            pass

    @app.route('/language_switch/<language>')
    def language_switch(language):
        ''' Endpoint to switch the default language.

        Parameters
        ----------
            language: str
                language short form to switch to.
        '''
        session['lang'] = language

        if current_user.is_authenticated:
            return redirect(str(request.referrer))

        return redirect(url_for('core.root'))

    @app.before_first_request
    def default_language():
        ''' Set the default language before the first request. '''
        if session.get('lang') not in list(SUPPORTED_LANGUAGES.keys()):
            session['lang'] = 'en'

    @app.errorhandler(404)
    @app.errorhandler(500)
    @app.errorhandler(413)
    def page_not_found(error):
        ''' Adding error handlers on main app instance. '''
        if getattr(error, 'code', None) == 413:
            flash('Error: file uploaded is too large ', 'danger')
            if current_user.is_authenticated:
                return redirect(url_for('cust_app.multimedia', nn=1))
            return redirect(url_for('core.root'))

        getattr(error, 'code', None) != 404 and log_error(error)
        flash('Error: something wrong , or the page is non-existing', 'danger')
        return redirect(url_for('core.root'))

    @app.route('/nojs/<int:enabled_js>')
    def nojs(enabled_js):
        ''' Handle JavaScript disabled or not supported. '''
        if enabled_js == 1:
            next_url = session.get('next_url', '/')

            if next_url != '/':
                return redirect(next_url)

            return redirect(url_for('core.root'))
        return render_template('nojs.html', page_title='Javascript is disabled')

    def moment_wrapper(moment):
        ''' Temproray moment wrapper to add `.toTime()` and `.toNow()`
            TODO: Remove and update Flask-Moment when PR's mereged.
        '''
        def toTime(*args, **kwargs):
            content = str(moment.fromTime(*args, **kwargs))

            return Markup(content.replace('from(', 'to('))

        def toNow(*args, **kwargs):
            content = str(moment.fromNow(*args, **kwargs))

            return Markup(content.replace('fromNow(', 'toNow('))

        setattr(moment, 'toTime', toTime)
        setattr(moment, 'toNow', toNow)
        return moment

    @app.context_processor
    def inject_vars():
        ''' Injecting default variables to all templates. '''
        ar = session.get('lang') == 'AR'  # adding language support var
        path = request.path or ''

        return dict(brp=Markup('
'), ar=ar, version=VERSION, str=str, defLang=session.get('lang'),
                    getattr=getattr, settings=Settings.get(), Serial=Serial, next=next, it=iter,
                    checkId=lambda id, records: id in [i.id for i in records], offices=Office.query.all(),
                    moment_wrapper=moment_wrapper, current_path=quote(path, safe=''), windows=os.name == 'nt',
                    unix=os.name != 'nt', setattr=lambda *args, **kwargs: setattr(*args, **kwargs) or '',
                    adme=path in get_bp_endpoints(administrate))

    return app
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import netsvc
from osv import fields, osv
import ir

from tools.misc import currency
from tools.translate import _

class res_currency(osv.osv):
    def _current_rate(self, cr, uid, ids, name, arg, context={}):
        res={}
        if 'date' in context:
            date=context['date']
        else:
            date=time.strftime('%Y-%m-%d')
        date= date or time.strftime('%Y-%m-%d')
        for id in ids:
            cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %s AND name <= %s ORDER BY name desc LIMIT 1" ,(id, date))
            if cr.rowcount:
                id, rate=cr.fetchall()[0]
                res[id]=rate
            else:
                res[id]=0
        return res
    _name = "res.currency"
    _description = "Currency"
    _columns = {
        'name': fields.char('Currency', size=32, required=True),
        'code': fields.char('Code', size=3),
        'symbol': fields.char('Symbol', size=3),
        'rate': fields.function(_current_rate, method=True, string='Current Rate', digits=(12,6),
            help='The rate of the currency to the currency of rate 1'),
        'rate_ids': fields.one2many('res.currency.rate', 'currency_id', 'Rates'),
        'accuracy': fields.integer('Computational Accuracy'),
        'rounding': fields.float('Rounding factor', digits=(12,6)),
        'active': fields.boolean('Active'),
        'company_id':fields.many2one('res.company', 'Company'),
        'date': fields.date('Date'),
        'base': fields.boolean('Base')

    }
    _defaults = {
        'active': lambda *a: 1,
        'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'res.currency', context=c)
    }
    _order = "code"

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        res=super(osv.osv, self).read(cr, user, ids, fields, context, load)
        for r in res:
            if r.__contains__('rate_ids'):
                rates=r['rate_ids']
                if rates:
                    currency_rate_obj=self.pool.get('res.currency.rate')
                    currency_date=currency_rate_obj.read(cr,user,rates[0],['name'])['name']
                    r['date']=currency_date
        return res

    def round(self, cr, uid, currency, amount):
        if currency.rounding == 0:
            return 0.0
        else:
            # /!\ First member below must be rounded to full unit!
            # Do not pass a rounding digits value to round()
            return round(amount / currency.rounding) * currency.rounding

    def is_zero(self, cr, uid, currency, amount):
        return abs(self.round(cr, uid, currency, amount)) < currency.rounding

    def compute(self, cr, uid, from_currency_id, to_currency_id, from_amount, round=True, context={}, account=None, account_invert=False):
        if not from_currency_id:
            from_currency_id = to_currency_id
        if not to_currency_id:
            to_currency_id = from_currency_id
        xc = self.browse(cr, uid, [from_currency_id,to_currency_id], context=context)
        from_currency = (xc[0].id == from_currency_id and xc[0]) or xc[1]
        to_currency = (xc[0].id == to_currency_id and xc[0]) or xc[1]
        if from_currency['rate'] == 0 or to_currency['rate'] == 0:
            date = context.get('date', time.strftime('%Y-%m-%d'))
            if from_currency['rate'] == 0:
                code = from_currency.code
            else:
                code = to_currency.code
            raise osv.except_osv(_('Error'), _('No rate found \n' \
                    'for the currency: %s \n' \
                    'at the date: %s') % (code, date))
        rate = to_currency.rate/from_currency.rate
        if account and (account.currency_mode=='average') and account.currency_id:
            q = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
            cr.execute('select sum(debit-credit),sum(amount_currency) from account_move_line l ' \
              'where l.currency_id=%s and l.account_id=%s and '+q, (account.currency_id.id,account.id,))
            tot1,tot2 = cr.fetchone()
            if tot2 and not account_invert:
                rate = float(tot1)/float(tot2)
            elif tot1 and account_invert:
                rate = float(tot2)/float(tot1)
        if to_currency_id==from_currency_id:
            if round:
                return self.round(cr, uid, to_currency, from_amount)
            else:
                return from_amount
        else:
            if round:
                return self.round(cr, uid, to_currency, from_amount * rate)
            else:
                return (from_amount * rate)

    def name_search(self, cr, uid, name, args=[], operator='ilike', context={}, limit=100):
        args2 = args[:]
        if name:
            args += [('name', operator, name)]
            args2 += [('code', operator, name)]
        ids = self.search(cr, uid, args, limit=limit)
        ids += self.search(cr, uid, args2, limit=limit)
        res = self.name_get(cr, uid, ids, context)
        return res
res_currency()

class res_currency_rate(osv.osv):
    _name = "res.currency.rate"
    _description = "Currency Rate"
    _columns = {
        'name': fields.date('Date', required=True, select=True),
        'rate': fields.float('Rate', digits=(12,6), required=True,
            help='The rate of the currency to the currency of rate 1'),
        'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
    }
    _defaults = {
        'name': lambda *a: time.strftime('%Y-%m-%d'),
    }
    _order = "name desc"
res_currency_rate()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<commit_msg>[FIX] Currency :  better handling of context<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import netsvc
from osv import fields, osv
import ir

from tools.misc import currency
from tools.translate import _

class res_currency(osv.osv):
    def _current_rate(self, cr, uid, ids, name, arg, context=None):
        if context is None:
            context = {}
        res = {}
        if 'date' in context:
            date = context['date']
        else:
            date = time.strftime('%Y-%m-%d')
        date = date or time.strftime('%Y-%m-%d')
        for id in ids:
            cr.execute("SELECT currency_id, rate FROM res_currency_rate WHERE currency_id = %s AND name <= %s ORDER BY name desc LIMIT 1" ,(id, date))
            if cr.rowcount:
                id, rate = cr.fetchall()[0]
                res[id] = rate
            else:
                res[id] = 0
        return res
    _name = "res.currency"
    _description = "Currency"
    _columns = {
        'name': fields.char('Currency', size=32, required=True),
        'code': fields.char('Code', size=3),
        'symbol': fields.char('Symbol', size=3),
        'rate': fields.function(_current_rate, method=True, string='Current Rate', digits=(12,6),
            help='The rate of the currency to the currency of rate 1'),
        'rate_ids': fields.one2many('res.currency.rate', 'currency_id', 'Rates'),
        'accuracy': fields.integer('Computational Accuracy'),
        'rounding': fields.float('Rounding factor', digits=(12,6)),
        'active': fields.boolean('Active'),
        'company_id':fields.many2one('res.company', 'Company'),
        'date': fields.date('Date'),
        'base': fields.boolean('Base')

    }
    _defaults = {
        'active': lambda *a: 1,
        'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'res.currency', context=c)
    }
    _order = "code"

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        res=super(osv.osv, self).read(cr, user, ids, fields, context, load)
        for r in res:
            if r.__contains__('rate_ids'):
                rates=r['rate_ids']
                if rates:
                    currency_rate_obj=  self.pool.get('res.currency.rate')
                    currency_date = currency_rate_obj.read(cr,user,rates[0],['name'])['name']
                    r['date'] = currency_date
        return res

    def round(self, cr, uid, currency, amount):
        if currency.rounding == 0:
            return 0.0
        else:
            # /!\ First member below must be rounded to full unit!
            # Do not pass a rounding digits value to round()
            return round(amount / currency.rounding) * currency.rounding

    def is_zero(self, cr, uid, currency, amount):
        return abs(self.round(cr, uid, currency, amount)) < currency.rounding

    def compute(self, cr, uid, from_currency_id, to_currency_id, from_amount, round=True, context=None, account=None, account_invert=False):
        if context is None:
            context = {}
        if not from_currency_id:
            from_currency_id = to_currency_id
        if not to_currency_id:
            to_currency_id = from_currency_id
        xc = self.browse(cr, uid, [from_currency_id,to_currency_id], context=context)
        from_currency = (xc[0].id == from_currency_id and xc[0]) or xc[1]
        to_currency = (xc[0].id == to_currency_id and xc[0]) or xc[1]
        if from_currency['rate'] == 0 or to_currency['rate'] == 0:
            date = context.get('date', time.strftime('%Y-%m-%d'))
            if from_currency['rate'] == 0:
                code = from_currency.code
            else:
                code = to_currency.code
            raise osv.except_osv(_('Error'), _('No rate found \n' \
                    'for the currency: %s \n' \
                    'at the date: %s') % (code, date))
        rate = to_currency.rate/from_currency.rate
        if account and (account.currency_mode=='average') and account.currency_id:
            q = self.pool.get('account.move.line')._query_get(cr, uid, context=context)
            cr.execute('select sum(debit-credit),sum(amount_currency) from account_move_line l ' \
              'where l.currency_id=%s and l.account_id=%s and '+q, (account.currency_id.id,account.id,))
            tot1,tot2 = cr.fetchone()
            if tot2 and not account_invert:
                rate = float(tot1)/float(tot2)
            elif tot1 and account_invert:
                rate = float(tot2)/float(tot1)
        if to_currency_id==from_currency_id:
            if round:
                return self.round(cr, uid, to_currency, from_amount)
            else:
                return from_amount
        else:
            if round:
                return self.round(cr, uid, to_currency, from_amount * rate)
            else:
                return (from_amount * rate)

    def name_search(self, cr, uid, name, args=[], operator='ilike', context={}, limit=100):
        args2 = args[:]
        if name:
            args += [('name', operator, name)]
            args2 += [('code', operator, name)]
        ids = self.search(cr, uid, args, limit=limit)
        ids += self.search(cr, uid, args2, limit=limit)
        res = self.name_get(cr, uid, ids, context)
        return res
res_currency()

class res_currency_rate(osv.osv):
    _name = "res.currency.rate"
    _description = "Currency Rate"
    _columns = {
        'name': fields.date('Date', required=True, select=True),
        'rate': fields.float('Rate', digits=(12,6), required=True,
            help='The rate of the currency to the currency of rate 1'),
        'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
    }
    _defaults = {
        'name': lambda *a: time.strftime('%Y-%m-%d'),
    }
    _order = "name desc"
res_currency_rate()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<|endoftext|>