···11+UPV Car Share Project
22+=====================
33+44+Made with Python 3 and Django with :heart:.
55+66+Install Spatialite
77+------------------
88+99+Install SpatiaLite with brew on Mac OS X::
1010+1111+ brew update
1212+ brew install spatialite-tools
1313+ brew install gdal
1414+
+216
docs/Makefile
···11+# Makefile for Sphinx documentation
22+#
33+44+# You can set these variables from the command line.
55+SPHINXOPTS =
66+SPHINXBUILD = sphinx-build
77+PAPER =
88+BUILDDIR = _build
99+1010+# User-friendly check for sphinx-build
1111+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
1212+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
1313+endif
1414+1515+# Internal variables.
1616+PAPEROPT_a4 = -D latex_paper_size=a4
1717+PAPEROPT_letter = -D latex_paper_size=letter
1818+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
1919+# the i18n builder cannot share the environment and doctrees with the others
2020+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
2121+2222+.PHONY: help
2323+help:
2424+ @echo "Please use \`make <target>' where <target> is one of"
2525+ @echo " html to make standalone HTML files"
2626+ @echo " dirhtml to make HTML files named index.html in directories"
2727+ @echo " singlehtml to make a single large HTML file"
2828+ @echo " pickle to make pickle files"
2929+ @echo " json to make JSON files"
3030+ @echo " htmlhelp to make HTML files and a HTML help project"
3131+ @echo " qthelp to make HTML files and a qthelp project"
3232+ @echo " applehelp to make an Apple Help Book"
3333+ @echo " devhelp to make HTML files and a Devhelp project"
3434+ @echo " epub to make an epub"
3535+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
3636+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
3737+ @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
3838+ @echo " text to make text files"
3939+ @echo " man to make manual pages"
4040+ @echo " texinfo to make Texinfo files"
4141+ @echo " info to make Texinfo files and run them through makeinfo"
4242+ @echo " gettext to make PO message catalogs"
4343+ @echo " changes to make an overview of all changed/added/deprecated items"
4444+ @echo " xml to make Docutils-native XML files"
4545+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
4646+ @echo " linkcheck to check all external links for integrity"
4747+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
4848+ @echo " coverage to run coverage check of the documentation (if enabled)"
4949+5050+.PHONY: clean
5151+clean:
5252+ rm -rf $(BUILDDIR)/*
5353+5454+.PHONY: html
5555+html:
5656+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
5757+ @echo
5858+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
5959+6060+.PHONY: dirhtml
6161+dirhtml:
6262+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
6363+ @echo
6464+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
6565+6666+.PHONY: singlehtml
6767+singlehtml:
6868+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
6969+ @echo
7070+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
7171+7272+.PHONY: pickle
7373+pickle:
7474+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
7575+ @echo
7676+ @echo "Build finished; now you can process the pickle files."
7777+7878+.PHONY: json
7979+json:
8080+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
8181+ @echo
8282+ @echo "Build finished; now you can process the JSON files."
8383+8484+.PHONY: htmlhelp
8585+htmlhelp:
8686+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
8787+ @echo
8888+ @echo "Build finished; now you can run HTML Help Workshop with the" \
8989+ ".hhp project file in $(BUILDDIR)/htmlhelp."
9090+9191+.PHONY: qthelp
9292+qthelp:
9393+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
9494+ @echo
9595+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
9696+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
9797+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Chargy.qhcp"
9898+ @echo "To view the help file:"
9999+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Chargy.qhc"
100100+101101+.PHONY: applehelp
102102+applehelp:
103103+ $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
104104+ @echo
105105+ @echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
106106+ @echo "N.B. You won't be able to view it unless you put it in" \
107107+ "~/Library/Documentation/Help or install it in your application" \
108108+ "bundle."
109109+110110+.PHONY: devhelp
111111+devhelp:
112112+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
113113+ @echo
114114+ @echo "Build finished."
115115+ @echo "To view the help file:"
116116+ @echo "# mkdir -p $$HOME/.local/share/devhelp/Chargy"
117117+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Chargy"
118118+ @echo "# devhelp"
119119+120120+.PHONY: epub
121121+epub:
122122+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
123123+ @echo
124124+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
125125+126126+.PHONY: latex
127127+latex:
128128+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
129129+ @echo
130130+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
131131+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
132132+ "(use \`make latexpdf' here to do that automatically)."
133133+134134+.PHONY: latexpdf
135135+latexpdf:
136136+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
137137+ @echo "Running LaTeX files through pdflatex..."
138138+ $(MAKE) -C $(BUILDDIR)/latex all-pdf
139139+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
140140+141141+.PHONY: latexpdfja
142142+latexpdfja:
143143+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
144144+ @echo "Running LaTeX files through platex and dvipdfmx..."
145145+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
146146+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
147147+148148+.PHONY: text
149149+text:
150150+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
151151+ @echo
152152+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
153153+154154+.PHONY: man
155155+man:
156156+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
157157+ @echo
158158+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
159159+160160+.PHONY: texinfo
161161+texinfo:
162162+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
163163+ @echo
164164+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
165165+ @echo "Run \`make' in that directory to run these through makeinfo" \
166166+ "(use \`make info' here to do that automatically)."
167167+168168+.PHONY: info
169169+info:
170170+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
171171+ @echo "Running Texinfo files through makeinfo..."
172172+ make -C $(BUILDDIR)/texinfo info
173173+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
174174+175175+.PHONY: gettext
176176+gettext:
177177+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
178178+ @echo
179179+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
180180+181181+.PHONY: changes
182182+changes:
183183+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
184184+ @echo
185185+ @echo "The overview file is in $(BUILDDIR)/changes."
186186+187187+.PHONY: linkcheck
188188+linkcheck:
189189+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
190190+ @echo
191191+ @echo "Link check complete; look for any errors in the above output " \
192192+ "or in $(BUILDDIR)/linkcheck/output.txt."
193193+194194+.PHONY: doctest
195195+doctest:
196196+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
197197+ @echo "Testing of doctests in the sources finished, look at the " \
198198+ "results in $(BUILDDIR)/doctest/output.txt."
199199+200200+.PHONY: coverage
201201+coverage:
202202+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
203203+ @echo "Testing of coverage in the sources finished, look at the " \
204204+ "results in $(BUILDDIR)/coverage/python.txt."
205205+206206+.PHONY: xml
207207+xml:
208208+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
209209+ @echo
210210+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
211211+212212+.PHONY: pseudoxml
213213+pseudoxml:
214214+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
215215+ @echo
216216+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
+291
docs/conf.py
···11+#!/usr/bin/env python3
22+# -*- coding: utf-8 -*-
33+#
44+# UPV Car Share documentation build configuration file, created by
55+# sphinx-quickstart on Thu Mar 10 20:44:35 2016.
66+#
77+# This file is execfile()d with the current directory set to its
88+# containing dir.
99+#
1010+# Note that not all possible configuration values are present in this
1111+# autogenerated file.
1212+#
1313+# All configuration values have a default; values that are commented out
1414+# serve to show the default.
1515+1616+import sys
1717+import os
1818+1919+# If extensions (or modules to document with autodoc) are in another directory,
2020+# add these directories to sys.path here. If the directory is relative to the
2121+# documentation root, use os.path.abspath to make it absolute, like shown here.
2222+#sys.path.insert(0, os.path.abspath('.'))
2323+2424+# -- General configuration ------------------------------------------------
2525+2626+# If your documentation needs a minimal Sphinx version, state it here.
2727+#needs_sphinx = '1.0'
2828+2929+# Add any Sphinx extension module names here, as strings. They can be
3030+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
3131+# ones.
3232+extensions = ['sphinxcontrib.httpdomain']
3333+3434+# Add any paths that contain templates here, relative to this directory.
3535+templates_path = ['_templates']
3636+3737+# The suffix(es) of source filenames.
3838+# You can specify multiple suffix as a list of string:
3939+# source_suffix = ['.rst', '.md']
4040+source_suffix = '.rst'
4141+4242+# The encoding of source files.
4343+#source_encoding = 'utf-8-sig'
4444+4545+# The master toctree document.
4646+master_doc = 'index'
4747+4848+# General information about the project.
4949+project = 'UPV Car Share Project'
5050+copyright = '2016, Marcos Gabarda'
5151+author = 'Marcos Gabarda'
5252+5353+# The version info for the project you're documenting, acts as replacement for
5454+# |version| and |release|, also used in various other places throughout the
5555+# built documents.
5656+#
5757+# The short X.Y version.
5858+version = '0.1.0'
5959+# The full version, including alpha/beta/rc tags.
6060+release = '0.1.0'
6161+6262+# The language for content autogenerated by Sphinx. Refer to documentation
6363+# for a list of supported languages.
6464+#
6565+# This is also used if you do content translation via gettext catalogs.
6666+# Usually you set "language" from the command line for these cases.
6767+language = 'es'
6868+6969+# There are two options for replacing |today|: either, you set today to some
7070+# non-false value, then it is used:
7171+#today = ''
7272+# Else, today_fmt is used as the format for a strftime call.
7373+#today_fmt = '%B %d, %Y'
7474+7575+# List of patterns, relative to source directory, that match files and
7676+# directories to ignore when looking for source files.
7777+exclude_patterns = ['_build']
7878+7979+# The reST default role (used for this markup: `text`) to use for all
8080+# documents.
8181+#default_role = None
8282+8383+# If true, '()' will be appended to :func: etc. cross-reference text.
8484+#add_function_parentheses = True
8585+8686+# If true, the current module name will be prepended to all description
8787+# unit titles (such as .. function::).
8888+#add_module_names = True
8989+9090+# If true, sectionauthor and moduleauthor directives will be shown in the
9191+# output. They are ignored by default.
9292+#show_authors = False
9393+9494+# The name of the Pygments (syntax highlighting) style to use.
9595+pygments_style = 'sphinx'
9696+9797+# A list of ignored prefixes for module index sorting.
9898+#modindex_common_prefix = []
9999+100100+# If true, keep warnings as "system message" paragraphs in the built documents.
101101+#keep_warnings = False
102102+103103+# If true, `todo` and `todoList` produce output, else they produce nothing.
104104+todo_include_todos = False
105105+106106+107107+# -- Options for HTML output ----------------------------------------------
108108+109109+# The theme to use for HTML and HTML Help pages. See the documentation for
110110+# a list of builtin themes.
111111+html_theme = 'alabaster'
112112+113113+on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
114114+115115+if not on_rtd:
116116+ import sphinx_rtd_theme
117117+ html_theme = "sphinx_rtd_theme"
118118+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
119119+120120+# Theme options are theme-specific and customize the look and feel of a theme
121121+# further. For a list of options available for each theme, see the
122122+# documentation.
123123+#html_theme_options = {}
124124+125125+# Add any paths that contain custom themes here, relative to this directory.
126126+#html_theme_path = []
127127+128128+# The name for this set of Sphinx documents. If None, it defaults to
129129+# "<project> v<release> documentation".
130130+#html_title = None
131131+132132+# A shorter title for the navigation bar. Default is the same as html_title.
133133+#html_short_title = None
134134+135135+# The name of an image file (relative to this directory) to place at the top
136136+# of the sidebar.
137137+#html_logo = None
138138+139139+# The name of an image file (relative to this directory) to use as a favicon of
140140+# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
141141+# pixels large.
142142+#html_favicon = None
143143+144144+# Add any paths that contain custom static files (such as style sheets) here,
145145+# relative to this directory. They are copied after the builtin static files,
146146+# so a file named "default.css" will overwrite the builtin "default.css".
147147+html_static_path = ['_static']
148148+149149+# Add any extra paths that contain custom files (such as robots.txt or
150150+# .htaccess) here, relative to this directory. These files are copied
151151+# directly to the root of the documentation.
152152+#html_extra_path = []
153153+154154+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
155155+# using the given strftime format.
156156+#html_last_updated_fmt = '%b %d, %Y'
157157+158158+# If true, SmartyPants will be used to convert quotes and dashes to
159159+# typographically correct entities.
160160+#html_use_smartypants = True
161161+162162+# Custom sidebar templates, maps document names to template names.
163163+#html_sidebars = {}
164164+165165+# Additional templates that should be rendered to pages, maps page names to
166166+# template names.
167167+#html_additional_pages = {}
168168+169169+# If false, no module index is generated.
170170+#html_domain_indices = True
171171+172172+# If false, no index is generated.
173173+#html_use_index = True
174174+175175+# If true, the index is split into individual pages for each letter.
176176+#html_split_index = False
177177+178178+# If true, links to the reST sources are added to the pages.
179179+#html_show_sourcelink = True
180180+181181+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
182182+#html_show_sphinx = True
183183+184184+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
185185+#html_show_copyright = True
186186+187187+# If true, an OpenSearch description file will be output, and all pages will
188188+# contain a <link> tag referring to it. The value of this option must be the
189189+# base URL from which the finished HTML is served.
190190+#html_use_opensearch = ''
191191+192192+# This is the file name suffix for HTML files (e.g. ".xhtml").
193193+#html_file_suffix = None
194194+195195+# Language to be used for generating the HTML full-text search index.
196196+# Sphinx supports the following languages:
197197+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
198198+# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
199199+#html_search_language = 'en'
200200+201201+# A dictionary with options for the search language support, empty by default.
202202+# Now only 'ja' uses this config value
203203+#html_search_options = {'type': 'default'}
204204+205205+# The name of a javascript file (relative to the configuration directory) that
206206+# implements a search results scorer. If empty, the default will be used.
207207+#html_search_scorer = 'scorer.js'
208208+209209+# Output file base name for HTML help builder.
210210+htmlhelp_basename = 'Upvcarsharedoc'
211211+212212+# -- Options for LaTeX output ---------------------------------------------
213213+214214+latex_elements = {
215215+# The paper size ('letterpaper' or 'a4paper').
216216+#'papersize': 'letterpaper',
217217+218218+# The font size ('10pt', '11pt' or '12pt').
219219+#'pointsize': '10pt',
220220+221221+# Additional stuff for the LaTeX preamble.
222222+#'preamble': '',
223223+224224+# Latex figure (float) alignment
225225+#'figure_align': 'htbp',
226226+}
227227+228228+# Grouping the document tree into LaTeX files. List of tuples
229229+# (source start file, target name, title,
230230+# author, documentclass [howto, manual, or own class]).
231231+latex_documents = [
232232+ (master_doc, 'UPVCarShare.tex', 'UPV Car Share Documentation',
233233+ 'Marcos Gabarda', 'manual'),
234234+]
235235+236236+# The name of an image file (relative to this directory) to place at the top of
237237+# the title page.
238238+#latex_logo = None
239239+240240+# For "manual" documents, if this is true, then toplevel headings are parts,
241241+# not chapters.
242242+#latex_use_parts = False
243243+244244+# If true, show page references after internal links.
245245+#latex_show_pagerefs = False
246246+247247+# If true, show URL addresses after external links.
248248+#latex_show_urls = False
249249+250250+# Documents to append as an appendix to all manuals.
251251+#latex_appendices = []
252252+253253+# If false, no module index is generated.
254254+#latex_domain_indices = True
255255+256256+257257+# -- Options for manual page output ---------------------------------------
258258+259259+# One entry per manual page. List of tuples
260260+# (source start file, name, description, authors, manual section).
261261+man_pages = [
262262+ (master_doc, 'upvcarshare', 'UPV Car Share Documentation',
263263+ [author], 1)
264264+]
265265+266266+# If true, show URL addresses after external links.
267267+#man_show_urls = False
268268+269269+270270+# -- Options for Texinfo output -------------------------------------------
271271+272272+# Grouping the document tree into Texinfo files. List of tuples
273273+# (source start file, target name, title, author,
274274+# dir menu entry, description, category)
275275+texinfo_documents = [
276276+ (master_doc, 'UPVCarShare', 'UPV Car Share Documentation',
277277+ author, 'UPVCarShare', 'One line description of project.',
278278+ 'Miscellaneous'),
279279+]
280280+281281+# Documents to append as an appendix to all manuals.
282282+#texinfo_appendices = []
283283+284284+# If false, no module index is generated.
285285+#texinfo_domain_indices = True
286286+287287+# How to display URL addresses: 'footnote', 'no', or 'inline'.
288288+#texinfo_show_urls = 'footnote'
289289+290290+# If true, do not generate a @detailmenu in the "Top" node's menu.
291291+#texinfo_no_detailmenu = False
+20
docs/index.rst
···11+.. Chargy documentation master file, created by
22+ sphinx-quickstart on Thu Mar 10 20:44:35 2016.
33+ You can adapt this file completely to your liking, but it should at least
44+ contain the root `toctree` directive.
55+66+Documentación de UPV Car Share Project
77+======================================
88+99+Content:
1010+1111+.. toctree::
1212+ :maxdepth: 2
1313+1414+1515+Indices and tables
1616+==================
1717+1818+* :ref:`genindex`
1919+* :ref:`modindex`
2020+* :ref:`search`
···11+"""
22+WSGI config for upvcarshare project.
33+44+It exposes the WSGI callable as a module-level variable named ``application``.
55+66+For more information on this file, see
77+https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
88+"""
99+1010+import os
1111+1212+from django.core.wsgi import get_wsgi_application
1313+1414+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "upvcarshare.settings")
1515+1616+application = get_wsgi_application()
···11+# -*- coding: utf-8 -*-
22+from __future__ import unicode_literals, print_function, absolute_import
33+44+55+class NoFreePlaces(Exception):
66+ msg = "No free places for this journey."
77+88+99+class AlreadyAPassenger(Exception):
1010+ msg = "User is already a passenger."
1111+1212+1313+class NotAPassenger(Exception):
1414+ msg = "The user is not a passenger of this journey."
+111
upvcarshare/journeys/managers.py
···11+# -*- coding: utf-8 -*-
22+from __future__ import unicode_literals, print_function, absolute_import
33+44+from functools import reduce
55+from django.contrib.gis.db import models
66+from django.contrib.gis.measure import D
77+from django.db.models import Count, F, Q
88+from django.utils import timezone
99+1010+from journeys import GOING, RETURN
1111+1212+1313+def recommended_condition(journey):
1414+ """Creates a condition to mark a journey as recommended, based on kind and a
1515+ needed journey.
1616+ :param kind:
1717+ :param journey:
1818+ """
1919+ key = "residence{}" if journey.kind == GOING else "campus{}"
2020+ return {
2121+ key.format("__position__distance_lte"): (
2222+ getattr(journey, key.format("")).position,
2323+ D(m=getattr(journey, key.format("")).distance)
2424+ )
2525+ }
2626+2727+2828+class ResidenceManager(models.GeoManager):
2929+3030+ def smart_create(self, user):
3131+ """Smart create using data from user."""
3232+ return self.create(
3333+ address=user.default_address,
3434+ position=user.default_position,
3535+ )
3636+3737+3838+class JourneyManager(models.GeoManager):
3939+ """Manager for Journeys."""
4040+4141+ def smart_create(self, user, origin, destination, departure, transport=None):
4242+ """Enhanced method to create journeys"""
4343+ assert origin.__class__.__name__.lower() == "residence" or \
4444+ origin.__class__.__name__.lower() == "campus"
4545+ assert destination.__class__.__name__.lower() == "residence" or \
4646+ destination.__class__.__name__.lower() == "campus"
4747+ assert destination.__class__ != origin.__class__
4848+ kind = GOING if origin.__class__.__name__.lower() == "residence" else RETURN
4949+ data = {
5050+ "user": user,
5151+ "kind": kind,
5252+ "departure": departure,
5353+ origin.__class__.__name__.lower(): origin,
5454+ destination.__class__.__name__.lower(): destination,
5555+ }
5656+ if transport is not None:
5757+ data["driver"] = user
5858+ data["free_places"] = transport.default_places
5959+ return self.create(**data)
6060+6161+ def available(self, kind=None):
6262+ """Gets all available journeys.
6363+ :param kind: GOING, RETURN
6464+ """
6565+ now = timezone.now()
6666+ queryset = self.filter(driver__isnull=False, departure__gt=now)
6767+ if kind is not None:
6868+ queryset = queryset.filter(kind=kind)
6969+ return queryset.\
7070+ annotate(total_passengers=Count("passengers")).\
7171+ filter(total_passengers__lt=F("free_places"))
7272+7373+ def nearby(self, geometry, distance, kind=None):
7474+ """Gets available nearby journeys.
7575+ :param distance: django.contrib.gis.measure.D
7676+ :param geometry: django.contrib.gis.geos.GEOSGeometry
7777+ :param kind: GOING, RETURN
7878+ """
7979+8080+ nearby = self.available(kind)
8181+ if kind is not None:
8282+ key = "residence{}" if kind == GOING else "campus{}"
8383+ key = key.format("__position__distance_lte")
8484+ nearby = nearby.filter(**{key: (geometry, distance)})
8585+ else:
8686+ nearby = nearby.filter(
8787+ Q(residence__position__distance_lte=(geometry, distance)) |
8888+ Q(campus__position__distance_lte=(geometry, distance))
8989+ )
9090+ return nearby
9191+9292+ def needed(self, user, kind=None):
9393+ """Journeys that given user needs a driver.
9494+ :param kind:
9595+ :param user:
9696+ """
9797+ now = timezone.now()
9898+ queryset = self.filter(user=user, driver__isnull=True, departure__gt=now)
9999+ if kind is not None:
100100+ queryset = queryset.filter(kind=kind)
101101+ return queryset
102102+103103+ def recommended(self, user, kind=None):
104104+ """Gets the journeys recommended for an user needs.
105105+ :param user:
106106+ :param kind:
107107+ """
108108+ # Gets journeys needed by the user...
109109+ needed_journeys = self.needed(user=user, kind=kind)
110110+ conditions = [Q(**recommended_condition(journey=journey)) for journey in needed_journeys]
111111+ return self.available(kind=kind).exclude(user=user).filter(reduce(lambda x, y: x | y, conditions))