<commit_before>#!/usr/bin/env python3

# Toolbox Importer
#
# default config.json:
# {
#   "tier_types": {
#     "\\t": "words",
#     "\\m": "morphemes",
#     "\\g": "glosses",
#     "\\p": "pos",
#     "\\f": "translations",
#   },
#   "alignments": {
#     "\\m": "\\t",
#     "\\g": "\\m",
#     "\\p": "\\m"
#   },
#   "record_markers": [
#     "\\id",
#     "\\ref"
#   ],
#   "attribute_map": {
#     "\\id": "corpus-id"
#   }
#   "error_recovery_method": "ratio"
# }

from collections import OrderedDict
import logging
import warnings
try:
    from itertools import chain, zip_longest
except ImportError:
    from itertools import chain, izip_longest as zip_longest

from xigt import (XigtCorpus, Igt, Tier, Item, Metadata, Meta)
from xigt.codecs import xigtxml
from xigt.errors import XigtImportError

try:
    import toolbox
except ImportError:
    raise ImportError(
        'Could not import Toolbox module. Get it from here:\n'
        '  https://github.com/goodmami/toolbox'
    )

default_tier_types = {
    '\\t': 'words',
    '\\m': 'morphemes',
    '\\g': 'glosses',
    '\\p': 'pos',
    '\\f': 'translations'
}

default_alignments = {
    '\\m': '\\t',
    '\\g': '\\m',
    '\\p': '\\m'
}

default_record_markers = [
    '\\id',
    '\\ref'
]

default_attribute_map = {
    '\\id': 'corpus-id'
}

default_error_recovery_method = 'ratio'

def xigt_import(infile, outfile, options=None):

    if options is None:
        options = {}
    options.setdefault('tier_types', default_tier_types)
    options.setdefault('alignments', default_alignments)
    options.setdefault('record_markers', default_record_markers)
    options.setdefault('attribute_map', default_attribute_map)
    options.setdefault('error_recovery_method', default_error_recovery_method)

    with open(infile, 'r') as in_fh, open(outfile, 'w') as out_fh:
        tb = toolbox.read_toolbox_file(in_fh)
        igts = toolbox_igts(tb, options)
        xc = XigtCorpus(igts=igts, mode='transient')
        xigtxml.dump(out_fh, xc)

def toolbox_igts(tb, options):
    record_markers = options['record_markers']
    assert len(record_markers) > 0
    mkrPriKey = record_markers[-1]
    for context, data in toolbox.records(tb, record_markers):
        data = list(data)  # run the generator
        if context.get(mkrPriKey) is None:
            continue  # header info
        igt = make_igt(
            context[mkrPriKey], data, context, options
        )
        if igt is not None:
            yield igt

def make_igt(key, data, context, options):
    # IDs cannot start with a digit
    assert key
    if key[0].isdigit():
        key = 'igt{}'.format(key)
    if context is None:
        context = {}
    attrs = {}
    attmap = options['attribute_map']
    for (mkr, val) in chain(data, context.items()):
        if val is None:  # will be None if mkr not encountered
            continue
        if mkr in attmap:
            attrs[attmap[mkr]] = val
    metadata = None

    w = None
    with warnings.catch_warnings(record=True) as ws:
        warnings.simplefilter('always')

        try:
            tiers = make_all_tiers(data, options)
            igt = Igt(
                id=key,
                attributes=attrs,
                metadata=metadata,
                tiers=tiers
            )
        except (toolbox.ToolboxError, XigtImportError) as ex:
            logging.error('Error during import of item {}:\n  {}'
                          .format(key, str(ex)))
            igt = None
        if len(ws) > 0:
            w = ws[0]

    if w is not None:
        if issubclass(w.category, toolbox.ToolboxWarning):
            warnings.warn('{}: {}'.format(key, w.message), w.category)
        else:
            warnings.warn_explicit(w.message, w.category, w.filename, w.lineno)

    return igt

def make_all_tiers(item_data, options):
    tier_types = options['tier_types']
    alignments = options['alignments']
    aligned_tiers = set(alignments.keys()).union(alignments.values())
    # use strip=False because we want same-length strings
    tier_data = toolbox.normalize_record(item_data, aligned_tiers, strip=False)
    prev = {}
    aligned_fields = toolbox.align_fields(
        tier_data, alignments, errors=options['error_recovery_method']
    )
    for mkr, aligned_tokens in aligned_fields:
        tier_type = tier_types.get(mkr)
        tier_id = mkr.lstrip('\\')
        algn_tier = prev.get(alignments.get(mkr))  # could be None
        try:
            tier = make_tier(tier_type, tier_id, aligned_tokens, algn_tier)
        except (AttributeError, AssertionError):
            raise XigtImportError('Error making {} tier (marker: {}).'
                                  .format(tier_type, mkr))
        prev[mkr] = tier
        yield tier

def make_tier(tier_type, tier_id, aligned_tokens, algn_tier):
    attrs = OrderedDict()
    items = list()
    i = 1  # start indices at 1
    if aligned_tokens == [(None, None)]:
        pass  # nothing to do
    elif algn_tier is not None:
        attrs['alignment'] = algn_tier.id
        algn_data = zip_longest(algn_tier.items, aligned_tokens)
        for tgt_item, src_data in algn_data:
            tgt_tok, src_toks = src_data
            assert tgt_tok == tgt_item.text  # FIXME is this necessary?
            for s in src_toks:
                items.append(
                    Item(id='{}{}'.format(tier_id, i),
                         text=s,
                         attributes={'alignment':tgt_item.id})
                )
                i += 1
    else:
        for tgt, src in aligned_tokens:
            for s in src:
                items.append(Item(id='{}{}'.format(tier_id, i), text=s))
                i += 1
    return Tier(id=tier_id, type=tier_type, items=items, attributes=attrs)<commit_msg>Require tier_id specification in config for toolbox importer.<commit_after>#!/usr/bin/env python3

# Toolbox Importer
#
# default config.json:
# {
#   "tier_types": {
#     "\\t": ["words", "w"],
#     "\\m": ["morphemes", "m"],
#     "\\g": ["glosses", "g"],
#     "\\p": ["pos", "pos"],
#     "\\f": ["translations", "t"],
#   },
#   "alignments": {
#     "\\m": "\\t",
#     "\\g": "\\m",
#     "\\p": "\\m"
#   },
#   "record_markers": [
#     "\\id",
#     "\\ref"
#   ],
#   "attribute_map": {
#     "\\id": "corpus-id"
#   },
#   "error_recovery_method": "ratio"
# }

from collections import OrderedDict
import logging
import warnings
try:
    from itertools import chain, zip_longest
except ImportError:
    from itertools import chain, izip_longest as zip_longest

from xigt import (XigtCorpus, Igt, Tier, Item, Metadata, Meta)
from xigt.codecs import xigtxml
from xigt.errors import XigtImportError

try:
    import toolbox
except ImportError:
    raise ImportError(
        'Could not import Toolbox module. Get it from here:\n'
        '  https://github.com/goodmami/toolbox'
    )

default_tier_types = {
    '\\t': ['words', 'w'],
    '\\m': ['morphemes', 'm'],
    '\\g': ['glosses', 'g'],
    '\\p': ['pos', 'pos'],
    '\\f': ['translations', 't'],
}

default_alignments = {
    '\\m': '\\t',
    '\\g': '\\m',
    '\\p': '\\m'
}

default_record_markers = [
    '\\id',
    '\\ref'
]

default_attribute_map = {
    '\\id': 'corpus-id'
}

default_error_recovery_method = 'ratio'

def xigt_import(infile, outfile, options=None):

    if options is None:
        options = {}
    options.setdefault('tier_types', default_tier_types)
    options.setdefault('alignments', default_alignments)
    options.setdefault('record_markers', default_record_markers)
    options.setdefault('attribute_map', default_attribute_map)
    options.setdefault('error_recovery_method', default_error_recovery_method)

    with open(infile, 'r') as in_fh, open(outfile, 'w') as out_fh:
        tb = toolbox.read_toolbox_file(in_fh)
        igts = toolbox_igts(tb, options)
        xc = XigtCorpus(igts=igts, mode='transient')
        xigtxml.dump(out_fh, xc)

def toolbox_igts(tb, options):
    record_markers = options['record_markers']
    assert len(record_markers) > 0
    mkrPriKey = record_markers[-1]
    for context, data in toolbox.records(tb, record_markers):
        data = list(data)  # run the generator
        if context.get(mkrPriKey) is None:
            continue  # header info
        igt = make_igt(
            context[mkrPriKey], data, context, options
        )
        if igt is not None:
            yield igt

def make_igt(key, data, context, options):
    # IDs cannot start with a digit
    assert key
    if key[0].isdigit():
        key = 'igt{}'.format(key)
    if context is None:
        context = {}
    attrs = {}
    attmap = options['attribute_map']
    for (mkr, val) in chain(data, context.items()):
        if val is None:  # will be None if mkr not encountered
            continue
        if mkr in attmap:
            attrs[attmap[mkr]] = val
    metadata = None

    w = None
    with warnings.catch_warnings(record=True) as ws:
        warnings.simplefilter('always')

        try:
            tiers = make_all_tiers(data, options)
            igt = Igt(
                id=key,
                attributes=attrs,
                metadata=metadata,
                tiers=tiers
            )
        except (toolbox.ToolboxError, XigtImportError) as ex:
            logging.error('Error during import of item {}:\n  {}'
                          .format(key, str(ex)))
            igt = None
        if len(ws) > 0:
            w = ws[0]

    if w is not None:
        if issubclass(w.category, toolbox.ToolboxWarning):
            warnings.warn('{}: {}'.format(key, w.message), w.category)
        else:
            warnings.warn_explicit(w.message, w.category, w.filename, w.lineno)

    return igt

def make_all_tiers(item_data, options):
    tier_types = options['tier_types']
    alignments = options['alignments']
    aligned_tiers = set(alignments.keys()).union(alignments.values())
    # use strip=False because we want same-length strings
    tier_data = toolbox.normalize_record(item_data, aligned_tiers, strip=False)
    prev = {}
    aligned_fields = toolbox.align_fields(
        tier_data, alignments, errors=options['error_recovery_method']
    )
    for mkr, aligned_tokens in aligned_fields:
        tier_type, tier_id = tier_types.get(mkr)
        algn_tier = prev.get(alignments.get(mkr))  # could be None
        try:
            tier = make_tier(tier_type, tier_id, aligned_tokens, algn_tier)
        except (AttributeError, AssertionError):
            raise XigtImportError('Error making {} tier (marker: {}).'
                                  .format(tier_type, mkr))
        prev[mkr] = tier
        yield tier

def make_tier(tier_type, tier_id, aligned_tokens, algn_tier):
    attrs = OrderedDict()
    items = list()
    i = 1  # start indices at 1
    if aligned_tokens == [(None, None)]:
        pass  # nothing to do
    elif algn_tier is not None:
        attrs['alignment'] = algn_tier.id
        algn_data = zip_longest(algn_tier.items, aligned_tokens)
        for tgt_item, src_data in algn_data:
            tgt_tok, src_toks = src_data
            assert tgt_tok == tgt_item.text  # FIXME is this necessary?
            for s in src_toks:
                items.append(
                    Item(id='{}{}'.format(tier_id, i),
                         text=s,
                         attributes={'alignment':tgt_item.id})
                )
                i += 1
    else:
        for tgt, src in aligned_tokens:
            for s in src:
                items.append(Item(id='{}{}'.format(tier_id, i), text=s))
                i += 1
    return Tier(id=tier_id, type=tier_type, items=items, attributes=attrs)
<|endoftext|>


<commit_before>#!/usr/bin/env python
from argparse import ArgumentParser
from xml.etree.cElementTree import ElementTree
from reportlab.pdfgen import canvas
from reportlab.lib.colors import toColor, Color
from reportlab.pdfbase._fontdata import standardFonts
from reportlab.lib.utils import ImageReader
from base64 import b64decode
from PyPDF2 import PdfFileReader, PdfFileWriter
from io import BytesIO
import gzip, sys, os.path, click

def main():
    # fetch path
    parser = ArgumentParser()
    parser.add_argument('src')
    args = parser.parse_args()

    # extract xml in zip archive
    with gzip.open(args.src, 'rb') as fp:
        xml = ElementTree(file=fp)

    # render PDF
    dest = BytesIO()
    c = canvas.Canvas(dest, bottomup=0)
    warnings = []
    pdf_background_filename = None
    pdf_background_pages = {}
    for pageno, page in enumerate(xml.getroot().iter('page')):
        # set page size
        c.setPageSize(
            (float(page.attrib['width']), float(page.attrib['height'])))

        # fill with background color
        background = page.find('background')
        if background.attrib['type'] == 'solid':
            background_color = background.attrib['color']
            if background.attrib['style'] == 'plain':
                c.setFillColor(background_color)
                c.rect(
                    0,
                    0,
                    float(page.attrib['width']),
                    float(page.attrib['height']),
                    stroke=0,
                    fill=1)
            else:
                warnings.append(
                    "Do not know how to handle background style '%s'" %
                    background.attrib['style'])
        elif background.attrib['type'] == 'pdf':
            if 'domain' in background.attrib:
                # determine filename according to Xournal rules
                domain = background.attrib['domain']
                if domain == 'absolute':
                    pdf_background_filename = background.attrib['filename']
                elif domain == 'attach':
                    pdf_background_filename = "%s.%s" % (
                        args.src, background.attrib['filename'])
                else:
                    warnings.append(
                        "Do not know how to handle PDF background domain '%s'"
                        % domain)

            # add page number mapping
            pdf_background_pages[pageno] = int(background.attrib['pageno']) - 1
        else:
            warnings.append("Do not know how to handle background type '%s'" %
                            background.attrib['type'])

        # render layers
        for layer in page.iter('layer'):
            for item in layer:
                # render stroke?
                if item.tag == 'stroke':
                    # configure pen
                    if item.attrib["tool"] not in ["pen", "highlighter"]:
                        warnings.append(
                            "Do not know how to handle stroke tool '%s'" %
                            item.attrib['tool'])
                    color = toColor(item.attrib["color"])
                    if item.attrib["tool"] == "highlighter":
                        color.alpha = 0.5
                    c.setStrokeColor(color)
                    c.setLineWidth(float(item.attrib["width"]))

                    # draw path
                    coords = item.text.split()
                    p = c.beginPath()
                    p.moveTo(float(coords[0]), float(coords[1]))
                    for i in range(0, len(coords), 2):
                        fn = p.moveTo if i == 0 else p.lineTo
                        fn(float(coords[i]), float(coords[i + 1]))
                    c.drawPath(p)

                # render text?
                elif item.tag == 'text':
                    font = item.attrib["font"]
                    if font not in standardFonts:
                        warnings.append(
                            "Unknown font '%s', falling back to Helvetica." %
                            font)
                        font = "Helvetica"
                    font_size = float(item.attrib["size"])
                    c.setFont(font, font_size)
                    c.setFillColor(item.attrib["color"])
                    dy = 0
                    for line in item.text.split("\n"):
                        c.drawString(item.attrib["x"], dy +
                                     float(item.attrib["y"]) + font_size, line)
                        dy += float(item.attrib["size"])

                # render image?
                elif item.tag == 'image':
                    # png image base 64 encoded
                    png_data = b64decode(item.text)
                    #png = Image.open(BytesIO(png_data))
                    png = ImageReader(BytesIO(png_data))
                    x = float(item.attrib["left"])
                    y = float(item.attrib["top"])
                    width = float(item.attrib["right"]) - float(item.attrib[
                        "left"])
                    height = float(item.attrib["bottom"]) - float(item.attrib[
                        "top"])
                    c.saveState()
                    c.translate(x, y + height / 2)
                    c.scale(1, -1)
                    c.drawImage(
                        png, 0, -height / 2, width, height, anchor='nw')
                    c.restoreState()

                # !?
                else:
                    warnings.append("Unknown item '%s'" % item.tag)

        c.showPage()

    # save PDF in the BytesIO object (`dest`)
    c.save()

    # PDF file not found? Attempt to guess better if Xournal filename is of the form 'filename.pdf.xoj'.
    if pdf_background_filename and not os.path.exists(pdf_background_filename):
        if args.src.endswith('.pdf.xoj'):
            warnings.append(
                "File not found '%s', attempting to use '%s' instead." %
                (pdf_background_filename, args.src[:-4]))
            pdf_background_filename = args.src[:-4]

    pdf_writer = None
    if pdf_background_filename:
        if not os.path.exists(pdf_background_filename):
            warnings.append("File not found '%s'." % pdf_background_filename)
        else:
            # open PDF background
            dest.seek(0)
            pdf_journal = PdfFileReader(dest)
            pdf_background = PdfFileReader(file(pdf_background_filename, 'rb'))

            # merge journal and background
            pdf_writer = PdfFileWriter()
            for pageno, _ in enumerate(xml.getroot().iter('page')):
                # page has PDF background?
                if pageno in pdf_background_pages:
                    pdf_pageno = pdf_background_pages[pageno]

                    page = pdf_background.getPage(pdf_pageno)
                    page.mergePage(pdf_journal.getPage(pageno))
                else:
                    page = pdf_journal.getPage(pageno)
                pdf_writer.addPage(page)

    # print warnings
    if warnings:
        sys.stderr.write( "WARNINGS:\n" )
        for line in warnings:
            sys.stderr.write(" -"+line+"\n")

    # print PDF
    stdout = click.get_binary_stream('stdout')
    if pdf_writer:
        pdf_writer.write(stdout)
    else:
        stdout.write(dest.getvalue())

if __name__ == '__main__':
    main()
<commit_msg>Fixed formatting.<commit_after>#!/usr/bin/env python
from argparse import ArgumentParser
from xml.etree.cElementTree import ElementTree
from reportlab.pdfgen import canvas
from reportlab.lib.colors import toColor, Color
from reportlab.pdfbase._fontdata import standardFonts
from reportlab.lib.utils import ImageReader
from base64 import b64decode
from PyPDF2 import PdfFileReader, PdfFileWriter
from io import BytesIO
import gzip, sys, os.path, click

def main():
    # fetch path
    parser = ArgumentParser()
    parser.add_argument('src')
    args = parser.parse_args()

    # extract xml in zip archive
    with gzip.open(args.src, 'rb') as fp:
        xml = ElementTree(file=fp)

    # render PDF
    dest = BytesIO()
    c = canvas.Canvas(dest, bottomup=0)
    warnings = []
    pdf_background_filename = None
    pdf_background_pages = {}
    for pageno, page in enumerate(xml.getroot().iter('page')):
        # set page size
        c.setPageSize((float(page.attrib['width']),
                       float(page.attrib['height'])))

        # fill with background color
        background = page.find('background')
        if background.attrib['type'] == 'solid':
            background_color = background.attrib['color']
            if background.attrib['style'] == 'plain':
                c.setFillColor(background_color)
                c.rect(
                    0,
                    0,
                    float(page.attrib['width']),
                    float(page.attrib['height']),
                    stroke=0,
                    fill=1)
            else:
                warnings.append(
                    "Do not know how to handle background style '%s'" %
                    background.attrib['style'])
        elif background.attrib['type'] == 'pdf':
            if 'domain' in background.attrib:
                # determine filename according to Xournal rules
                domain = background.attrib['domain']
                if domain == 'absolute':
                    pdf_background_filename = background.attrib['filename']
                elif domain == 'attach':
                    pdf_background_filename = "%s.%s" % (
                        args.src, background.attrib['filename'])
                else:
                    warnings.append(
                        "Do not know how to handle PDF background domain '%s'"
                        % domain)

            # add page number mapping
            pdf_background_pages[pageno] = int(background.attrib['pageno']) - 1
        else:
            warnings.append("Do not know how to handle background type '%s'" %
                            background.attrib['type'])

        # render layers
        for layer in page.iter('layer'):
            for item in layer:
                # render stroke?
                if item.tag == 'stroke':
                    # configure pen
                    if item.attrib["tool"] not in ["pen", "highlighter"]:
                        warnings.append(
                            "Do not know how to handle stroke tool '%s'" %
                            item.attrib['tool'])
                    color = toColor(item.attrib["color"])
                    if item.attrib["tool"] == "highlighter":
                        color.alpha = 0.5
                    c.setStrokeColor(color)
                    c.setLineWidth(float(item.attrib["width"]))

                    # draw path
                    coords = item.text.split()
                    p = c.beginPath()
                    p.moveTo(float(coords[0]), float(coords[1]))
                    for i in range(0, len(coords), 2):
                        fn = p.moveTo if i == 0 else p.lineTo
                        fn(float(coords[i]), float(coords[i + 1]))
                    c.drawPath(p)

                # render text?
                elif item.tag == 'text':
                    font = item.attrib["font"]
                    if font not in standardFonts:
                        warnings.append(
                            "Unknown font '%s', falling back to Helvetica." %
                            font)
                        font = "Helvetica"
                    font_size = float(item.attrib["size"])
                    c.setFont(font, font_size)
                    c.setFillColor(item.attrib["color"])
                    dy = 0
                    for line in item.text.split("\n"):
                        c.drawString(item.attrib["x"],
                                     dy + float(item.attrib["y"]) + font_size,
                                     line)
                        dy += float(item.attrib["size"])

                # render image?
                elif item.tag == 'image':
                    # png image base 64 encoded
                    png_data = b64decode(item.text)
                    #png = Image.open(BytesIO(png_data))
                    png = ImageReader(BytesIO(png_data))
                    x = float(item.attrib["left"])
                    y = float(item.attrib["top"])
                    width = float(item.attrib["right"]) - float(
                        item.attrib["left"])
                    height = float(item.attrib["bottom"]) - float(
                        item.attrib["top"])
                    c.saveState()
                    c.translate(x, y + height / 2)
                    c.scale(1, -1)
                    c.drawImage(
                        png, 0, -height / 2, width, height, anchor='nw')
                    c.restoreState()

                # !?
                else:
                    warnings.append("Unknown item '%s'" % item.tag)

        c.showPage()

    # save PDF in the BytesIO object (`dest`)
    c.save()

    # PDF file not found? Attempt to guess better if Xournal filename is of the form 'filename.pdf.xoj'.
    if pdf_background_filename and not os.path.exists(pdf_background_filename):
        if args.src.endswith('.pdf.xoj'):
            warnings.append(
                "File not found '%s', attempting to use '%s' instead." %
                (pdf_background_filename, args.src[:-4]))
            pdf_background_filename = args.src[:-4]

    pdf_writer = None
    if pdf_background_filename:
        if not os.path.exists(pdf_background_filename):
            warnings.append("File not found '%s'." % pdf_background_filename)
        else:
            # open PDF background
            dest.seek(0)
            pdf_journal = PdfFileReader(dest)
            pdf_background = PdfFileReader(file(pdf_background_filename, 'rb'))

            # merge journal and background
            pdf_writer = PdfFileWriter()
            for pageno, _ in enumerate(xml.getroot().iter('page')):
                # page has PDF background?
                if pageno in pdf_background_pages:
                    pdf_pageno = pdf_background_pages[pageno]

                    page = pdf_background.getPage(pdf_pageno)
                    page.mergePage(pdf_journal.getPage(pageno))
                else:
                    page = pdf_journal.getPage(pageno)
                pdf_writer.addPage(page)

    # print warnings
    if warnings:
        sys.stderr.write("WARNINGS:\n")
        for line in warnings:
            sys.stderr.write(" -" + line + "\n")

    # print PDF
    stdout = click.get_binary_stream('stdout')
    if pdf_writer:
        pdf_writer.write(stdout)
    else:
        stdout.write(dest.getvalue())

if __name__ == '__main__':
    main()
<|endoftext|>


<commit_before># -*- coding:utf-8 -*-
from django.db import models
from django.core.urlresolvers import reverse
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _

class Location(models.Model):
    class Meta:
        verbose_name = _(u'Local')
        verbose_name_plural = _(u'Locais')

    description = models.CharField(_(u'Descrição'), max_length=100)
    street = models.CharField(_(u'Rua'), max_length=255)
    number = models.CharField(_(u'Número'), max_length=15)
    district = models.CharField(_(u'Bairro'), max_length=255)
    postal_code = models.CharField(_(u'CEP'), max_length=50)
    city = models.CharField(_(u'Cidade'), max_length=50)
    state = models.CharField(_(u'Estado'), max_length=50)
    country = models.CharField(_(u'País'), max_length=50)

    reference = models.CharField(u'Referência', max_length=100)

    map = models.URLField(
        _(u'Mapa'), max_length=255, null=True, blank=True,
        help_text=u'Caso preenchido, sobrescreve o mapa gerado '
        u'automaticamente',
    )

    def __unicode__(self):
        return self.description

    @property
    def address(self):
        address = (self.street, self.number, self.district)
        return u'{0} nº{1} {2}'.format(*address)

    def get_map(self):
        if self.map:
            return self.map

        base_url = 'http://maps.google.com.br/maps?q={0}'

        qs = u'{0},{1},{2},{3},{4}'
        qs = qs.format(
            self.street, self.number, self.district, self.city, self.state,
        )

        return base_url.format(qs)

class EventLecture(models.Model):
    class Meta:
        verbose_name = _(u'Palestra do Evento')
        verbose_name_plural = _(u'Palestras do Evento')

    event = models.ForeignKey('event_generator.Event',
                              verbose_name=_(u'Evento'))
    lecture = models.ForeignKey('palestra.Lecture',
                                verbose_name=_(u'Palestra'))
    start = models.TimeField(u'Início')
    end = models.TimeField(_(u'Fim'))

    def __unicode__(self):
        return smart_unicode(self.lecture)

class Event(models.Model):
    class Meta:
        verbose_name = _(u'Evento')
        verbose_name_plural = _(u'Eventos')

    description = models.CharField(_(u'Descrição'), max_length=100)
    full_description = models.TextField(_(u'Descrição Completa'))
    date = models.DateTimeField(_(u'Data'))
    location = models.ForeignKey(
        'event_generator.Location', verbose_name=_(u'Local'),
    )

    slug = models.SlugField()

    def __unicode__(self):
        return self.description

    def get_absolute_url(self):
        return reverse('event', kwargs={'slug': self.slug})
<commit_msg>Refatorando models<commit_after># -*- coding:utf-8 -*-
from django.db import models
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _

class Event(models.Model):
    class Meta:
        verbose_name = _(u'Evento')
        verbose_name_plural = _(u'Eventos')

    description = models.CharField(_(u'Descrição'), max_length=100)
    full_description = models.TextField(_(u'Descrição Completa'))
    date = models.DateTimeField(_(u'Data'))
    slug = models.SlugField()

    def __unicode__(self):
        return self.description

    def get_absolute_url(self):
        return reverse('event', kwargs={'slug': self.slug})
<|endoftext|>


<commit_before>#-*- coding: utf-8 -*-
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.utils.translation import ugettext as _
from django.http import HttpResponse
from django.views.decorators.http import require_http_methods
import json
from apps.genfors.forms import LoginForm, MeetingForm, QuestionForm, RegisterVoterForm, AlternativeFormSet
from apps.genfors.models import Meeting, Question, RegisteredVoter, Alternative, BooleanVote, MultipleChoice
from apps.genfors.models import BOOLEAN_VOTE, MULTIPLE_CHOICE
import datetime

@login_required
def genfors(request):
    context = {}
    meeting = get_active_meeting()

    # Check for session token
    if request.session.get('registered_voter') == True:
        # Check for active meeting
        if meeting:
            context['meeting'] = meeting

            # If there is an active question
            if meeting.get_active_question():
                aq = meeting.get_active_question()
                total_votes = aq.get_votes().count()
                alternatives = aq.get_alternatives()

                context['active_question'] = {}
                context['active_question']['total_votes'] = total_votes
                context['active_question']['alternatives'] = alternatives

                reg_voter = RegisteredVoter.objects.filter(user=request.user, meeting=meeting)
                if reg_voter:
                    reg_voter = reg_voter[0]
                else:
                    reg_voter = None
                context['registered_voter'] = reg_voter

                context['already_voted'] = aq.already_voted(reg_voter)

                res = aq.get_results()

                if aq.question_type is BOOLEAN_VOTE and total_votes != 0:
                    context['active_question']['yes_percent'] = res['JA'] * 100 / total_votes
                    context['active_question']['no_percent'] = res['NEI'] * 100 / total_votes
                    context['active_question']['blank_percent'] = res['BLANKT'] * 100 / total_votes

                elif aq.question_type is MULTIPLE_CHOICE and total_votes != 0:
                    context['active_question']['multiple_choice'] = {a.description : [0, 0] for a in alternatives}
                    context['active_question']['multiple_choice']['Blankt'] = [0, 0]
                    for k,v in res.items():
                        context['active_question']['multiple_choice'][k] = [v, v * 100 / total_votes]

        return render(request, "genfors/index.html", context)

    # If user is not logged in
    else:

        # Process stuff from the login form
        if request.method == 'POST' and not meeting.registration_locked:
            form = RegisterVoterForm(request.POST)
            context['form'] = form
            if form.is_valid():

                # Create a registered voter object if it does not already exis
                reg_voter = RegisteredVoter.objects.filter(meeting=meeting, user=request.user)
                if not reg_voter:
                    reg_voter = RegisteredVoter(user=request.user, meeting=meeting, can_vote=True)
                    reg_voter.save()

                request.session['registered_voter'] = True
                return redirect('genfors_index')

        # Set registration_locked context and create login form
        else:
            context['form'] = RegisterVoterForm()
            if meeting:
                context['registration_locked'] = meeting.registration_locked
            else:
                context['registration_locked'] = True

    return render(request, "genfors/index_login.html", context)

@login_required
def registered_voters(request):
    context = {}
    if request.session.get('genfors_admin') is True:
        meeting = get_active_meeting()
        if meeting:
            context['registered_voters'] = meeting.get_attendee_list()
    return render(request, "genfors/registered_voters.html", context)

@login_required
def admin(request):
    context = {}
    # Check if user is logged in as genfors admin
    if request.session.get('genfors_admin') is True:
        meeting = get_next_meeting()
        if meeting:
            context['meeting'] = meeting
            question = meeting.get_active_question()
            if question:
                context['question'] = question
            else:
                if request.method == 'POST':
                    form = QuestionForm(request.POST)
                    if form.is_valid():
                        data = form.cleaned_data
                        question = Question(meeting=meeting, anonymous=data['anonymous'],
                                            question_type=data['anonymous'], description=data['description'],
                                            number_of_alternatives=data['number_of_alternatives'])
                        question.save()
                        messages.success(request, _(u'Nytt spørsmål lagt til'))
                        return redirect('genfors_admin')
                else:
                    form = QuestionForm()
                    formset = AlternativeFormSet()
                context['form'] = form
                context['formset'] = formset
        elif request.method == 'POST':
            form = MeetingForm(request.POST)
            context['form'] = form
            if form.is_valid():
                meeting = Meeting(title=form.cleaned_data['title'],
                                  start_date=form.cleaned_data['start_date'])
                meeting.save()
                messages.success(request, _(u'Generalforsamling lagt til'))
                return redirect('genfors_admin')
        else:
            # Create meeting view
            form = MeetingForm()
            context['form'] = form
        return render(request, "genfors/admin.html", context)
    else:
        if request.method == 'POST':
            form = LoginForm(request.POST)
            context['form'] = form
            if form.is_valid():
                request.session['genfors_admin'] = True
                return redirect('genfors_admin')
        else:
            context['form'] = LoginForm()
    return render(request, "genfors/admin_login.html", context)

def admin_logout(request):
    if 'genfors_admin' in request.session:
        del request.session['genfors_admin']
    return redirect('genfors_index')

# Handle votes
@require_http_methods(["POST"])
def vote(request):
    m = get_active_meeting()
    if m:

        # If user is logged in..
        if request.session.get('registered_voter') == True:
            q = m.get_active_question()
            r = RegisteredVoter.objects.filter(user=request.user, meeting=m)
            if r:
                r = r[0]
            else:
                messages.error(request, 'Du er ikke registrert som oppmøtt, og kan derfor ikke avlegge stemme.')
                return redirect('genfors_index')

            if q.already_voted(r):
                messages.error(request, 'Du har allerede avlagt en stemme i denne saken.')
                return redirect('genfors_index')
            # If user is registered and has not cast a vote on the active question
            else:
                if 'choice' in request.POST:
                    alt = int(request.POST['choice'])
                    if q.question_type is BOOLEAN_VOTE:
                        valid = [0, 1, 2]
                        if alt in valid:
                            vote = None
                            if alt == 0:
                                vote = BooleanVote(voter=r, question=q, answer=None)
                            elif alt == 1:
                                vote = BooleanVote(voter=r, question=q, answer=True)
                            elif alt == 2:
                                vote = BooleanVote(voter=r, question=q, answer=False)
                            vote.save()
                            messages.success(request, 'Din stemme ble registrert!')
                            return redirect('genfors_index')

                    elif q.question_type is MULTIPLE_CHOICE:
                        alternatives = Alternative.objects.filter(question=q)
                        valid = [a.alt_id for a in alternatives]
                        valid.append(0)
                        if alt in valid:
                            vote = None
                            if alt == 0:
                                vote = MultipleChoice(voter=r, question=q, answer=None)
                                vote.save()
                                messages.success(request, 'Din stemme ble registrert!')
                                return redirect('genfors_index')
                            else:
                                choice = Alternative.objects.filter(id=alt)
                                if choice:
                                    vote = MultipleChoice(voter=r, question=q, answer=choice[0])
                                    vote.save()
                                    messages.success(request, 'Din stemme ble registrert!')
                                    return redirect('genfors_index')

                messages.error(request, 'Det ble forsøkt å stemme på et ugyldig alternativ, stemmen ble ikke registrert.')
                return redirect('genfors_index')

        # Else forbid
        return HttpResponse(status_code=403, reason_phrase='Forbidden')
    else:
        return HttpResponse(status_code=403, reason_phrase='Forbidden')

def get_active_meeting():
    today = datetime.date.today()
    meetings = Meeting.objects.filter(start_date__range=[today, today + datetime.timedelta(hours=24)]).order_by('-start_date')
    if meetings:
        return meetings[0]

def get_next_meeting():
    today = datetime.date.today()
    meetings = Meeting.objects.filter(registration_locked=False, start_date__gt=today).order_by('-start_date')
    if meetings:
        return meetings[0]
<commit_msg>Removed old question field<commit_after>#-*- coding: utf-8 -*-
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.utils.translation import ugettext as _
from django.http import HttpResponse
from django.views.decorators.http import require_http_methods
import json
from apps.genfors.forms import LoginForm, MeetingForm, QuestionForm, RegisterVoterForm, AlternativeFormSet
from apps.genfors.models import Meeting, Question, RegisteredVoter, Alternative, BooleanVote, MultipleChoice
from apps.genfors.models import BOOLEAN_VOTE, MULTIPLE_CHOICE
import datetime

@login_required
def genfors(request):
    context = {}
    meeting = get_active_meeting()

    # Check for session token
    if request.session.get('registered_voter') == True:
        # Check for active meeting
        if meeting:
            context['meeting'] = meeting

            # If there is an active question
            if meeting.get_active_question():
                aq = meeting.get_active_question()
                total_votes = aq.get_votes().count()
                alternatives = aq.get_alternatives()

                context['active_question'] = {}
                context['active_question']['total_votes'] = total_votes
                context['active_question']['alternatives'] = alternatives

                reg_voter = RegisteredVoter.objects.filter(user=request.user, meeting=meeting)
                if reg_voter:
                    reg_voter = reg_voter[0]
                else:
                    reg_voter = None
                context['registered_voter'] = reg_voter

                context['already_voted'] = aq.already_voted(reg_voter)

                res = aq.get_results()

                if aq.question_type is BOOLEAN_VOTE and total_votes != 0:
                    context['active_question']['yes_percent'] = res['JA'] * 100 / total_votes
                    context['active_question']['no_percent'] = res['NEI'] * 100 / total_votes
                    context['active_question']['blank_percent'] = res['BLANKT'] * 100 / total_votes

                elif aq.question_type is MULTIPLE_CHOICE and total_votes != 0:
                    context['active_question']['multiple_choice'] = {a.description : [0, 0] for a in alternatives}
                    context['active_question']['multiple_choice']['Blankt'] = [0, 0]
                    for k,v in res.items():
                        context['active_question']['multiple_choice'][k] = [v, v * 100 / total_votes]

        return render(request, "genfors/index.html", context)

    # If user is not logged in
    else:

        # Process stuff from the login form
        if request.method == 'POST' and not meeting.registration_locked:
            form = RegisterVoterForm(request.POST)
            context['form'] = form
            if form.is_valid():

                # Create a registered voter object if it does not already exis
                reg_voter = RegisteredVoter.objects.filter(meeting=meeting, user=request.user)
                if not reg_voter:
                    reg_voter = RegisteredVoter(user=request.user, meeting=meeting, can_vote=True)
                    reg_voter.save()

                request.session['registered_voter'] = True
                return redirect('genfors_index')

        # Set registration_locked context and create login form
        else:
            context['form'] = RegisterVoterForm()
            if meeting:
                context['registration_locked'] = meeting.registration_locked
            else:
                context['registration_locked'] = True

    return render(request, "genfors/index_login.html", context)

@login_required
def registered_voters(request):
    context = {}
    if request.session.get('genfors_admin') is True:
        meeting = get_active_meeting()
        if meeting:
            context['registered_voters'] = meeting.get_attendee_list()
    return render(request, "genfors/registered_voters.html", context)

@login_required
def admin(request):
    context = {}
    # Check if user is logged in as genfors admin
    if request.session.get('genfors_admin') is True:
        meeting = get_next_meeting()
        if meeting:
            context['meeting'] = meeting
            question = meeting.get_active_question()
            if question:
                context['question'] = question
            else:
                if request.method == 'POST':
                    form = QuestionForm(request.POST)
                    if form.is_valid():
                        data = form.cleaned_data
                        question = Question(meeting=meeting, anonymous=data['anonymous'],
                                            question_type=data['anonymous'], description=data['description'])
                        question.save()
                        messages.success(request, _(u'Nytt spørsmål lagt til'))
                        return redirect('genfors_admin')
                else:
                    form = QuestionForm()
                    formset = AlternativeFormSet()
                context['form'] = form
                context['formset'] = formset
        elif request.method == 'POST':
            form = MeetingForm(request.POST)
            context['form'] = form
            if form.is_valid():
                meeting = Meeting(title=form.cleaned_data['title'],
                                  start_date=form.cleaned_data['start_date'])
                meeting.save()
                messages.success(request, _(u'Generalforsamling lagt til'))
                return redirect('genfors_admin')
        else:
            # Create meeting view
            form = MeetingForm()
            context['form'] = form
        return render(request, "genfors/admin.html", context)
    else:
        if request.method == 'POST':
            form = LoginForm(request.POST)
            context['form'] = form
            if form.is_valid():
                request.session['genfors_admin'] = True
                return redirect('genfors_admin')
        else:
            context['form'] = LoginForm()
    return render(request, "genfors/admin_login.html", context)

def admin_logout(request):
    if 'genfors_admin' in request.session:
        del request.session['genfors_admin']
    return redirect('genfors_index')

# Handle votes
@require_http_methods(["POST"])
def vote(request):
    m = get_active_meeting()
    if m:

        # If user is logged in..
        if request.session.get('registered_voter') == True:
            q = m.get_active_question()
            r = RegisteredVoter.objects.filter(user=request.user, meeting=m)
            if r:
                r = r[0]
            else:
                messages.error(request, 'Du er ikke registrert som oppmøtt, og kan derfor ikke avlegge stemme.')
                return redirect('genfors_index')

            if q.already_voted(r):
                messages.error(request, 'Du har allerede avlagt en stemme i denne saken.')
                return redirect('genfors_index')
            # If user is registered and has not cast a vote on the active question
            else:
                if 'choice' in request.POST:
                    alt = int(request.POST['choice'])
                    if q.question_type is BOOLEAN_VOTE:
                        valid = [0, 1, 2]
                        if alt in valid:
                            vote = None
                            if alt == 0:
                                vote = BooleanVote(voter=r, question=q, answer=None)
                            elif alt == 1:
                                vote = BooleanVote(voter=r, question=q, answer=True)
                            elif alt == 2:
                                vote = BooleanVote(voter=r, question=q, answer=False)
                            vote.save()
                            messages.success(request, 'Din stemme ble registrert!')
                            return redirect('genfors_index')

                    elif q.question_type is MULTIPLE_CHOICE:
                        alternatives = Alternative.objects.filter(question=q)
                        valid = [a.alt_id for a in alternatives]
                        valid.append(0)
                        if alt in valid:
                            vote = None
                            if alt == 0:
                                vote = MultipleChoice(voter=r, question=q, answer=None)
                                vote.save()
                                messages.success(request, 'Din stemme ble registrert!')
                                return redirect('genfors_index')
                            else:
                                choice = Alternative.objects.filter(id=alt)
                                if choice:
                                    vote = MultipleChoice(voter=r, question=q, answer=choice[0])
                                    vote.save()
                                    messages.success(request, 'Din stemme ble registrert!')
                                    return redirect('genfors_index')

                messages.error(request, 'Det ble forsøkt å stemme på et ugyldig alternativ, stemmen ble ikke registrert.')
                return redirect('genfors_index')

        # Else forbid
        return HttpResponse(status_code=403, reason_phrase='Forbidden')
    else:
        return HttpResponse(status_code=403, reason_phrase='Forbidden')

def get_active_meeting():
    today = datetime.date.today()
    meetings = Meeting.objects.filter(start_date__range=[today, today + datetime.timedelta(hours=24)]).order_by('-start_date')
    if meetings:
        return meetings[0]

def get_next_meeting():
    today = datetime.date.today()
    meetings = Meeting.objects.filter(registration_locked=False, start_date__gt=today).order_by('-start_date')
    if meetings:
        return meetings[0]
<|endoftext|>


<commit_before>import logging
from os import remove
from django_dynamic_fixture import G
from django.test import TestCase
from apps.offline.models import IMAGE_FOLDER, Issue

class OfflineTest(TestCase):

    def setUp(self):
        self.logger = logging.getLogger(__name__)
        self.issue = G(Issue, issue=IMAGE_FOLDER + '/offline-test-pdf.pdf')

    def testThumbnailExists(self):
        self.assertTrue(self.issue.thumbnail_exists)

    def tearDown(self):
        remove(self.issue.thumbnail)
<commit_msg>Now checks for imagemagick<commit_after>import logging
from os import remove
from subprocess import check_call, CalledProcessError
from django_dynamic_fixture import G
from django.test import TestCase
from apps.offline.models import IMAGE_FOLDER, Issue

class OfflineTest(TestCase):

    def setUp(self):
        self.logger = logging.getLogger(__name__)
        self.issue = G(Issue, issue=IMAGE_FOLDER + '/offline-test-pdf.pdf')

    def _runImagemagick(self):
        try:
            check_call(['which', 'convert'])
            return True
        except (OSError, CalledProcessError) as e:
            self.logger.error('Missing dependency imagemagick.')
            return False

    def testImagemagickExists(self):
        self.assertTrue(self._runImagemagick())

    def testThumbnailExists(self):
        self.assertTrue(self.issue.thumbnail_exists)

    def tearDown(self):
        remove(self.issue.thumbnail)
<|endoftext|>


<commit_before>import logging
import os

from flask import Flask, send_from_directory, render_template

from community_share import config, store
from community_share.routes.user_routes import register_user_routes
from community_share.routes.search_routes import register_search_routes
from community_share.routes.conversation_routes import register_conversation_routes
from community_share.routes.share_routes import register_share_routes
from community_share.routes.survey_routes import register_survey_routes
from community_share.routes.email_routes import register_email_routes
from community_share.routes.statistics_routes import register_statistics_routes

logger = logging.getLogger(__name__)

def make_app():
    logger.debug('COMMIT_HASH is {0}'.format(config.COMMIT_HASH))
    app = Flask(__name__, template_folder='../static/')
    app.config['SQLALCHEMY_DATABASE_URI'] = config.DB_CONNECTION

    register_user_routes(app)
    register_search_routes(app)
    register_conversation_routes(app)
    register_share_routes(app)
    register_survey_routes(app)
    register_email_routes(app)
    register_statistics_routes(app)

    @app.teardown_appcontext
    def close_db_connection(exception):
        store.session.remove()

    @app.route('/static/js/<path:filename>')
    def js_static(filename):
        return send_from_directory(app.root_path + '/../static/js/', filename)

    @app.route('/static/fonts/<path:filename>')
    def fonts_static(filename):
        return send_from_directory(app.root_path + '/../static/fonts/', filename)

    @app.route('/static/css/<path:filename>')
    def css_static(filename):
        return send_from_directory(app.root_path + '/../static/css/', filename)

    @app.route('/static/templates/<path:filename>')
    def templates_static(filename):
        return send_from_directory(app.root_path + '/../static/templates/', filename)

    @app.route('/')
    def index():
        logger.debug('rendering index')
        return render_template('index.html', COMMIT_HASH=config.COMMIT_HASH,
                               config=config
        )

    return app

if __name__ == '__main__':
    logger.info('Loading settings from environment')
    config.load_from_environment()
    logger.info('Making application')
    app = make_app()
    app.debug = True
    logger.info('Running application - debug={0}'.format(app.debug))
    app.run()
<commit_msg>Fix links in footer.<commit_after>import logging
import os

from flask import Flask, send_from_directory, render_template

from community_share import config, store
from community_share.routes.user_routes import register_user_routes
from community_share.routes.search_routes import register_search_routes
from community_share.routes.conversation_routes import register_conversation_routes
from community_share.routes.share_routes import register_share_routes
from community_share.routes.survey_routes import register_survey_routes
from community_share.routes.email_routes import register_email_routes
from community_share.routes.statistics_routes import register_statistics_routes

logger = logging.getLogger(__name__)

def make_app():
    logger.debug('COMMIT_HASH is {0}'.format(config.COMMIT_HASH))
    app = Flask(__name__, template_folder='../static/')
    app.config['SQLALCHEMY_DATABASE_URI'] = config.DB_CONNECTION

    register_user_routes(app)
    register_search_routes(app)
    register_conversation_routes(app)
    register_share_routes(app)
    register_survey_routes(app)
    register_email_routes(app)
    register_statistics_routes(app)

    @app.teardown_appcontext
    def close_db_connection(exception):
        store.session.remove()

    @app.route('/static/js/<path:filename>')
    def js_static(filename):
        return send_from_directory(app.root_path + '/../static/js/', filename)

    @app.route('/static/fonts/<path:filename>')
    def fonts_static(filename):
        return send_from_directory(app.root_path + '/../static/fonts/', filename)

    @app.route('/static/css/<path:filename>')
    def css_static(filename):
        return send_from_directory(app.root_path + '/../static/css/', filename)

    @app.route('/static/templates/footer.html')
    def footer_template():
        return render_template('templates/footer.html', config=config)

    @app.route('/static/templates/<path:filename>')
    def templates_static(filename):
        return send_from_directory(app.root_path + '/../static/templates/', filename)

    @app.route('/')
    def index():
        logger.debug('rendering index')
        return render_template('index.html', COMMIT_HASH=config.COMMIT_HASH,
                               config=config
        )

    return app

if __name__ == '__main__':
    logger.info('Loading settings from environment')
    config.load_from_environment()
    logger.info('Making application')
    app = make_app()
    app.debug = True
    logger.info('Running application - debug={0}'.format(app.debug))
    app.run()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import json
import logging

import stripe
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.mail import EmailMessage, send_mail
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from pytz import timezone as tz

from apps.payment.models import Payment, PaymentPrice, PaymentRelation, PaymentTransaction, ReceiptEmail
from apps.webshop.models import OrderLine

@login_required
def payment(request):

    if request.is_ajax():
        if request.method == "POST":

            # Get the credit card details submitted by the form
            token = request.POST.get("stripeToken")
            payment_id = request.POST.get("paymentId")
            price_id = request.POST.get("priceId")

            payment_object = Payment.objects.get(id=payment_id)
            payment_price = PaymentPrice.objects.get(id=price_id)

            if payment_object:
                try:
                    stripe.api_key = settings.STRIPE_PRIVATE_KEYS[payment_object.stripe_key]

                    charge = stripe.Charge.create(
                        amount=payment_price.price * 100,  # Price is multiplied with 100 because the amount is in øre
                        currency="nok",
                        card=token,
                        description=payment_object.description() + " - " + request.user.email
                    )

                    payment_relation = PaymentRelation.objects.create(
                        payment=payment_object,
                        payment_price=payment_price,
                        user=request.user,
                        stripe_id=charge.id
                    )

                    payment_object.handle_payment(request.user)

                    _send_payment_confirmation_mail(payment_relation)

                    messages.success(request, _("Betaling utført."))
                    return HttpResponse("Betaling utført.", content_type="text/plain", status=200)
                except stripe.CardError as e:
                    messages.error(request, str(e))
                    return HttpResponse(str(e), content_type="text/plain", status=500)

    raise Http404("Request not supported")

@login_required
def payment_info(request):

    if request.is_ajax():
        if 'payment_id' in request.session:

            data = dict()

            payment_object = Payment.objects.get(id=request.session['payment_id'])

            if payment_object:
                data['stripe_public_key'] = settings.STRIPE_PUBLIC_KEYS[payment_object.stripe_key]
                data['email'] = request.user.email
                data['description'] = payment_object.description()
                data['payment_id'] = request.session['payment_id']
                data['price_ids'] = [price.id for price in payment_object.prices()]

                for payment_price in payment_object.prices():
                    data[payment_price.id] = dict()
                    data[payment_price.id]['price'] = payment_price.price
                    # The price is in øre so it needs to be multiplied with 100
                    data[payment_price.id]['stripe_price'] = payment_price.price * 100

                return HttpResponse(json.dumps(data), content_type="application/json")

    raise Http404("Request not supported")

@login_required
def webshop_info(request):
    if request.is_ajax():
        data = dict()

        # TODO fix get order_line
        order_line = OrderLine.objects.filter(user=request.user, paid=False).first()

        if order_line:
            data['stripe_public_key'] = settings.STRIPE_PUBLIC_KEYS["prokom"]
            data['email'] = request.user.email
            data['order_line_id'] = order_line.pk
            data['price'] = int(order_line.subtotal() * 100)

            return HttpResponse(json.dumps(data), content_type="application/json")

    raise Http404("Request not supported")

@login_required
def webshop_pay(request):

    if request.is_ajax():
        if request.method == "POST":

            # Get the credit card details submitted by the form
            token = request.POST.get("stripeToken")
            amount = int(request.POST.get("amount"))
            order_line_id = request.POST.get("order_line_id")

            order_line = OrderLine.objects.get(pk=order_line_id)

            # Check if the user has added or removed items since reloading the checkout page
            if int(order_line.subtotal() * 100) != amount:
                messages.error(request, "Det har skjedd endringer på bestillingen. Prøv igjen")
                return HttpResponse("Invalid input", content_type="text/plain", status=500)

            try:
                stripe.api_key = settings.STRIPE_PRIVATE_KEYS["prokom"]

                if not order_line.is_valid():
                    error = "Ordren er ikke gyldig."
                    messages.error(request, error)
                    return HttpResponse(error, content_type="text/plain", status=400)

                charge = stripe.Charge.create(
                    amount=amount,
                    currency="nok",
                    card=token,
                    description="Web shop purchase - " + request.user.email
                )

                order_line.pay()
                order_line.stripe_id = charge.id
                order_line.save()
                _send_webshop_mail(order_line)

                messages.success(request, "Betaling utført")

                return HttpResponse("Betaling utført.", content_type="text/plain", status=200)
            except stripe.CardError as e:
                messages.error(request, str(e))
                return HttpResponse(str(e), content_type="text/plain", status=500)

    raise Http404("Request not supported")

@login_required
def payment_refund(request, payment_relation_id):

    payment_relation = get_object_or_404(PaymentRelation, pk=payment_relation_id)

    # Prevents users from refunding others
    if request.user != payment_relation.user:
        return HttpResponse("Unauthorized user", content_type="text/plain", status=403)

    status = payment_relation.payment.check_refund(payment_relation)

    if not status[0]:
        messages.error(request, status[1])
        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

    try:
        stripe.api_key = settings.STRIPE_PRIVATE_KEYS[payment_relation.payment.stripe_key]
        ch = stripe.Charge.retrieve(payment_relation.stripe_id)
        ch.refunds.create()

        payment_relation.payment.handle_refund(request.META['HTTP_HOST'], payment_relation)
        messages.success(request, _("Betalingen har blitt refundert."))
    except stripe.InvalidRequestError as e:
        messages.error(request, str(e))

    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

def _send_payment_confirmation_mail(payment_relation):
    subject = _("kvittering") + ": " + payment_relation.payment.description()
    from_mail = payment_relation.payment.responsible_mail()
    to_mails = [payment_relation.user.email]

    context = {
        'payment_date': payment_relation.datetime.astimezone(tz('Europe/Oslo')).strftime("%-d %B %Y kl. %H:%M"),
        'description': payment_relation.payment.description,
        'payment_id': payment_relation.unique_id,
        'amount': payment_relation.payment_price.price,
        'to_mail': to_mails,
        'from_mail': from_mail
    }

    email_message = render_to_string('payment/email/confirmation_mail.txt', context)
    send_mail(subject, email_message, from_mail, to_mails)

@login_required
def saldo_info(request):

    if request.is_ajax():

        data = dict()

        data['stripe_public_key'] = settings.STRIPE_PUBLIC_KEYS["trikom"]
        data['email'] = request.user.email
        return HttpResponse(json.dumps(data), content_type="application/json")

    raise Http404("Request not supported")

@login_required
def saldo(request):

    if request.is_ajax():
        if request.method == "POST":

            # Get the credit card details submitted by the form
            token = request.POST.get("stripeToken")
            amount = int(request.POST.get("amount"))

            if amount not in (100, 200, 500):
                messages.error(request, "Invalid input")
                return HttpResponse("Invalid input", content_type="text/plain", status=500)

            try:
                stripe.api_key = settings.STRIPE_PRIVATE_KEYS["trikom"]

                stripe.Charge.create(
                    amount=amount * 100,  # Price is multiplied with 100 because the amount is in øre
                    currency="nok",
                    card=token,
                    description="Saldo deposit - " + request.user.email
                )

                payment_transaction = PaymentTransaction.objects.create(user=request.user, amount=amount,
                                                                        used_stripe=True)

                _send_confirmation_mail(payment_transaction)

                messages.success(request, _("Inskudd utført."))
                return HttpResponse("Inskudd utført.", content_type="text/plain", status=200)
            except stripe.CardError as e:
                messages.error(request, str(e))
                return HttpResponse(str(e), content_type="text/plain", status=500)

    raise Http404("Request not supported")

def _send_confirmation_mail(payment_transaction):
    subject = _("kvittering saldo inskudd")
    from_mail = settings.EMAIL_TRIKOM
    to_mails = [payment_transaction.user.email]

    context = {
        'payment_date': payment_transaction.datetime,
        'description': "påfyll av saldo",
        'payment_id': payment_transaction.unique_id,
        'amount': payment_transaction.amount,
        'to_mail': to_mails,
        'from_mail': from_mail
    }

    email_message = render_to_string('payment/email/confirmation_mail.txt', context)
    send_mail(subject, email_message, from_mail, to_mails)

def _send_webshop_mail(order_line):
    subject = _("Kvittering Webshop Online")
    from_mail = settings.EMAIL_PROKOM
    to_mails = [order_line.user.email]

    message = _(
        "Hei, du har bestilt ting i Online sin webshop. Ordren din kom på totalt %.2f kroner."
        % order_line.subtotal()
    )

    logging.getLogger(__name__).debug("Logging for send webshop mail")
    logging.getLogger(__name__).info("%s (#%s)" % (str(order_line), order_line.id))

    message += "\nDine produkter:"
    products = ""
    for o in order_line.orders.all():
        products += "\n " + str(o)
    message += products
    message += "\n\nDin betalingsreferanse er " + order_line.stripe_id
    message += "\n\n"
    message += _("Dersom du har problemer eller spørsmål, send mail til") + ": " + settings.EMAIL_PROKOM

    EmailMessage(subject, str(message), from_mail, to_mails).send()
<commit_msg>Move _send_payment_confirmation_mail function down to the other mail functions<commit_after># -*- coding: utf-8 -*-

import json
import logging

import stripe
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.mail import EmailMessage, send_mail
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from pytz import timezone as tz

from apps.payment.models import Payment, PaymentPrice, PaymentRelation, PaymentTransaction
from apps.webshop.models import OrderLine

@login_required
def payment(request):

    if request.is_ajax():
        if request.method == "POST":

            # Get the credit card details submitted by the form
            token = request.POST.get("stripeToken")
            payment_id = request.POST.get("paymentId")
            price_id = request.POST.get("priceId")

            payment_object = Payment.objects.get(id=payment_id)
            payment_price = PaymentPrice.objects.get(id=price_id)

            if payment_object:
                try:
                    stripe.api_key = settings.STRIPE_PRIVATE_KEYS[payment_object.stripe_key]

                    charge = stripe.Charge.create(
                        amount=payment_price.price * 100,  # Price is multiplied with 100 because the amount is in øre
                        currency="nok",
                        card=token,
                        description=payment_object.description() + " - " + request.user.email
                    )

                    payment_relation = PaymentRelation.objects.create(
                        payment=payment_object,
                        payment_price=payment_price,
                        user=request.user,
                        stripe_id=charge.id
                    )

                    payment_object.handle_payment(request.user)

                    _send_payment_confirmation_mail(payment_relation)

                    messages.success(request, _("Betaling utført."))
                    return HttpResponse("Betaling utført.", content_type="text/plain", status=200)
                except stripe.CardError as e:
                    messages.error(request, str(e))
                    return HttpResponse(str(e), content_type="text/plain", status=500)

    raise Http404("Request not supported")

@login_required
def payment_info(request):

    if request.is_ajax():
        if 'payment_id' in request.session:

            data = dict()

            payment_object = Payment.objects.get(id=request.session['payment_id'])

            if payment_object:
                data['stripe_public_key'] = settings.STRIPE_PUBLIC_KEYS[payment_object.stripe_key]
                data['email'] = request.user.email
                data['description'] = payment_object.description()
                data['payment_id'] = request.session['payment_id']
                data['price_ids'] = [price.id for price in payment_object.prices()]

                for payment_price in payment_object.prices():
                    data[payment_price.id] = dict()
                    data[payment_price.id]['price'] = payment_price.price
                    # The price is in øre so it needs to be multiplied with 100
                    data[payment_price.id]['stripe_price'] = payment_price.price * 100

                return HttpResponse(json.dumps(data), content_type="application/json")

    raise Http404("Request not supported")

@login_required
def webshop_info(request):
    if request.is_ajax():
        data = dict()

        # TODO fix get order_line
        order_line = OrderLine.objects.filter(user=request.user, paid=False).first()

        if order_line:
            data['stripe_public_key'] = settings.STRIPE_PUBLIC_KEYS["prokom"]
            data['email'] = request.user.email
            data['order_line_id'] = order_line.pk
            data['price'] = int(order_line.subtotal() * 100)

            return HttpResponse(json.dumps(data), content_type="application/json")

    raise Http404("Request not supported")

@login_required
def webshop_pay(request):

    if request.is_ajax():
        if request.method == "POST":

            # Get the credit card details submitted by the form
            token = request.POST.get("stripeToken")
            amount = int(request.POST.get("amount"))
            order_line_id = request.POST.get("order_line_id")

            order_line = OrderLine.objects.get(pk=order_line_id)

            # Check if the user has added or removed items since reloading the checkout page
            if int(order_line.subtotal() * 100) != amount:
                messages.error(request, "Det har skjedd endringer på bestillingen. Prøv igjen")
                return HttpResponse("Invalid input", content_type="text/plain", status=500)

            try:
                stripe.api_key = settings.STRIPE_PRIVATE_KEYS["prokom"]

                if not order_line.is_valid():
                    error = "Ordren er ikke gyldig."
                    messages.error(request, error)
                    return HttpResponse(error, content_type="text/plain", status=400)

                charge = stripe.Charge.create(
                    amount=amount,
                    currency="nok",
                    card=token,
                    description="Web shop purchase - " + request.user.email
                )

                order_line.pay()
                order_line.stripe_id = charge.id
                order_line.save()
                _send_webshop_mail(order_line)

                messages.success(request, "Betaling utført")

                return HttpResponse("Betaling utført.", content_type="text/plain", status=200)
            except stripe.CardError as e:
                messages.error(request, str(e))
                return HttpResponse(str(e), content_type="text/plain", status=500)

    raise Http404("Request not supported")

@login_required
def payment_refund(request, payment_relation_id):

    payment_relation = get_object_or_404(PaymentRelation, pk=payment_relation_id)

    # Prevents users from refunding others
    if request.user != payment_relation.user:
        return HttpResponse("Unauthorized user", content_type="text/plain", status=403)

    status = payment_relation.payment.check_refund(payment_relation)

    if not status[0]:
        messages.error(request, status[1])
        return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

    try:
        stripe.api_key = settings.STRIPE_PRIVATE_KEYS[payment_relation.payment.stripe_key]
        ch = stripe.Charge.retrieve(payment_relation.stripe_id)
        ch.refunds.create()

        payment_relation.payment.handle_refund(request.META['HTTP_HOST'], payment_relation)
        messages.success(request, _("Betalingen har blitt refundert."))
    except stripe.InvalidRequestError as e:
        messages.error(request, str(e))

    return HttpResponseRedirect(request.META.get('HTTP_REFERER'))

@login_required
def saldo_info(request):

    if request.is_ajax():

        data = dict()

        data['stripe_public_key'] = settings.STRIPE_PUBLIC_KEYS["trikom"]
        data['email'] = request.user.email
        return HttpResponse(json.dumps(data), content_type="application/json")

    raise Http404("Request not supported")

@login_required
def saldo(request):

    if request.is_ajax():
        if request.method == "POST":

            # Get the credit card details submitted by the form
            token = request.POST.get("stripeToken")
            amount = int(request.POST.get("amount"))

            if amount not in (100, 200, 500):
                messages.error(request, "Invalid input")
                return HttpResponse("Invalid input", content_type="text/plain", status=500)

            try:
                stripe.api_key = settings.STRIPE_PRIVATE_KEYS["trikom"]

                stripe.Charge.create(
                    amount=amount * 100,  # Price is multiplied with 100 because the amount is in øre
                    currency="nok",
                    card=token,
                    description="Saldo deposit - " + request.user.email
                )

                payment_transaction = PaymentTransaction.objects.create(user=request.user, amount=amount,
                                                                        used_stripe=True)

                _send_confirmation_mail(payment_transaction)

                messages.success(request, _("Inskudd utført."))
                return HttpResponse("Inskudd utført.", content_type="text/plain", status=200)
            except stripe.CardError as e:
                messages.error(request, str(e))
                return HttpResponse(str(e), content_type="text/plain", status=500)

    raise Http404("Request not supported")

# Confirmation Mails
def _send_payment_confirmation_mail(payment_relation):
    subject = _("kvittering") + ": " + payment_relation.payment.description()
    from_mail = payment_relation.payment.responsible_mail()
    to_mails = [payment_relation.user.email]

    context = {
        'payment_date': payment_relation.datetime.astimezone(tz('Europe/Oslo')).strftime("%-d %B %Y kl. %H:%M"),
        'description': payment_relation.payment.description,
        'payment_id': payment_relation.unique_id,
        'amount': payment_relation.payment_price.price,
        'to_mail': to_mails,
        'from_mail': from_mail
    }

    email_message = render_to_string('payment/email/confirmation_mail.txt', context)
    send_mail(subject, email_message, from_mail, to_mails)

def _send_confirmation_mail(payment_transaction):
    subject = _("kvittering saldo inskudd")
    from_mail = settings.EMAIL_TRIKOM
    to_mails = [payment_transaction.user.email]

    context = {
        'payment_date': payment_transaction.datetime,
        'description': "påfyll av saldo",
        'payment_id': payment_transaction.unique_id,
        'amount': payment_transaction.amount,
        'to_mail': to_mails,
        'from_mail': from_mail
    }

    email_message = render_to_string('payment/email/confirmation_mail.txt', context)
    send_mail(subject, email_message, from_mail, to_mails)

def _send_webshop_mail(order_line):
    subject = _("Kvittering Webshop Online")
    from_mail = settings.EMAIL_PROKOM
    to_mails = [order_line.user.email]

    message = _(
        "Hei, du har bestilt ting i Online sin webshop. Ordren din kom på totalt %.2f kroner."
        % order_line.subtotal()
    )

    logging.getLogger(__name__).debug("Logging for send webshop mail")
    logging.getLogger(__name__).info("%s (#%s)" % (str(order_line), order_line.id))

    message += "\nDine produkter:"
    products = ""
    for o in order_line.orders.all():
        products += "\n " + str(o)
    message += products
    message += "\n\nDin betalingsreferanse er " + order_line.stripe_id
    message += "\n\n"
    message += _("Dersom du har problemer eller spørsmål, send mail til") + ": " + settings.EMAIL_PROKOM

    EmailMessage(subject, str(message), from_mail, to_mails).send()
<|endoftext|>


<commit_before>from django.db import models
from django.forms import ModelForm, TextInput, Textarea, SelectMultiple, CheckboxSelectMultiple

# --- Competency System Hierarchy ---

class School(models.Model):
    name = models.CharField(max_length=500)

    def __unicode__(self):
        return self.name

class SubjectArea(models.Model):
    subject_area = models.CharField(max_length=500)
    school = models.ForeignKey(School)

    def __unicode__(self):
        return self.subject_area

class SubdisciplineArea(models.Model):
    subdiscipline_area = models.CharField(max_length=500)
    subject_area = models.ForeignKey(SubjectArea)

    def __unicode__(self):
        return self.subdiscipline_area

class CompetencyArea(models.Model):
    competency_area = models.CharField(max_length=500)
    subject_area = models.ForeignKey(SubjectArea)
    subdiscipline_area = models.ForeignKey(SubdisciplineArea, blank=True, null=True)

    def __unicode__(self):
        return self.competency_area

class Level(models.Model):
    APPRENTICE = 'Apprentice'
    TECHNICIAN = 'Technician'
    MASTER = 'Master'
    PROFESSIONAL = 'Professional'
    LEVEL_TYPE_CHOICES = ( (APPRENTICE, 'Apprentice'), (TECHNICIAN, 'Technician'),
                           (MASTER, 'Master'), (PROFESSIONAL, 'Professional') )
    level_type = models.CharField(max_length=500, choices=LEVEL_TYPE_CHOICES)
    level_description = models.CharField(max_length=5000)
    competency_area = models.ForeignKey(CompetencyArea)

    def __unicode__(self):
        return self.level_description

    class Meta:
        unique_together = ('competency_area', 'level_type',)
        order_with_respect_to = 'competency_area'

class EssentialUnderstanding(models.Model):
    essential_understanding = models.CharField(max_length=2000)
    competency_area = models.ForeignKey(CompetencyArea)

    def __unicode__(self):
        return self.essential_understanding

class LearningTarget(models.Model):
    learning_target = models.CharField(max_length=2000)
    essential_understanding = models.ForeignKey(EssentialUnderstanding)

    def __unicode__(self):
        return self.learning_target

# --- Pathways ---
from django.db.models import Q
class Pathway(models.Model):
    name = models.CharField(max_length=500)
    school = models.ForeignKey(School)
    subject_areas = models.ManyToManyField(SubjectArea)
    subdiscipline_areas = models.ManyToManyField(SubdisciplineArea, blank=True, null=True)
    competency_areas = models.ManyToManyField(CompetencyArea, blank=True, null=True)
    essential_understandings = models.ManyToManyField(EssentialUnderstanding, blank=True, null=True)
    learning_targets = models.ManyToManyField(LearningTarget, blank=True, null=True)

    def __unicode__(self):
        return self.name

# --- ModelForms ---
class CompetencyAreaForm(ModelForm):
    class Meta:
        model = CompetencyArea
        fields = ('competency_area',)
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'competency_area': Textarea(attrs={'rows': 3, 'class': 'span8'}) }

class EssentialUnderstandingForm(ModelForm):
    class Meta:
        model = EssentialUnderstanding
        fields = ('essential_understanding',)
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'essential_understanding': Textarea(attrs={'rows': 3, 'class': 'span8'}) }

class LevelForm(ModelForm):
    class Meta:
        model = Level
        fields = ('level_type', 'level_description',)
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'level_description': Textarea(attrs={'rows': 3, 'class': 'span8'}) }

class LearningTargetForm(ModelForm):
    class Meta:
        model = LearningTarget
        fields = ('learning_target', )
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'learning_target': Textarea(attrs={'rows': 3, 'class': 'span8'}) }

class PathwayForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(PathwayForm, self).__init__(*args, **kwargs)
        pathway = self.instance

        # sas
        self.fields['subject_areas'].queryset = pathway.school.subjectarea_set.all()

        # sdas
        if pathway.subject_areas.all():
            sda_queryset = SubdisciplineArea.objects.none()
            for sa in pathway.subject_areas.all():
                sda_queryset = sda_queryset | sa.subdisciplinearea_set.all()
            self.fields['subdiscipline_areas'].queryset = sda_queryset

        # cas
        if pathway.subject_areas.all():
            ca_queryset = CompetencyArea.objects.none()
            # General subject area competencies:
            for sa in pathway.subject_areas.all():
                ca_queryset = ca_queryset | sa.competencyarea_set.all().filter(subdiscipline_area=None)
            # Subdiscipline area competencies:
            if pathway.subdiscipline_areas.all():
                for sda in pathway.subdiscipline_areas.all():
                    ca_queryset = ca_queryset | sda.competencyarea_set.all()
            self.fields['competency_areas'].queryset = ca_queryset

        # eus
        if pathway.competency_areas.all():
            eu_queryset = EssentialUnderstanding.objects.none()
            for ca in pathway.competency_areas.all():
                eu_queryset |= ca.essentialunderstanding_set.all()
            self.fields['essential_understandings'].queryset = eu_queryset

        # lts
        if pathway.essential_understandings.all():
            lt_queryset = LearningTarget.objects.none()
            for eu in pathway.essential_understandings.all():
                lt_queryset |= eu.learningtarget_set.all()
            self.fields['learning_targets'].queryset = lt_queryset

    class Meta:
        model = Pathway
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        #  Consider CheckboxSelectMultiple for some of these, especially eus and lts
        # number of items to show in longer dropdown lists:
        widgets = {
            'name': TextInput(attrs={'class': 'span4'}),
            'subject_areas': SelectMultiple(attrs={'class': 'span4', 'size': 5}),
            'subdiscipline_areas': SelectMultiple(attrs={'class': 'span4', 'size': 5}),
            'competency_areas': SelectMultiple(attrs={'class': 'span4', 'size': 15}),
            'essential_understandings': SelectMultiple(attrs={'class': 'span8', 'size': 20}),
            'learning_targets': SelectMultiple(attrs={'class': 'span8', 'size': 20}),
            }
<commit_msg>Some edit forms have 5-row text boxes.<commit_after>from django.db import models
from django.forms import ModelForm, TextInput, Textarea, SelectMultiple, CheckboxSelectMultiple

# --- Competency System Hierarchy ---

class School(models.Model):
    name = models.CharField(max_length=500)

    def __unicode__(self):
        return self.name

class SubjectArea(models.Model):
    subject_area = models.CharField(max_length=500)
    school = models.ForeignKey(School)

    def __unicode__(self):
        return self.subject_area

class SubdisciplineArea(models.Model):
    subdiscipline_area = models.CharField(max_length=500)
    subject_area = models.ForeignKey(SubjectArea)

    def __unicode__(self):
        return self.subdiscipline_area

class CompetencyArea(models.Model):
    competency_area = models.CharField(max_length=500)
    subject_area = models.ForeignKey(SubjectArea)
    subdiscipline_area = models.ForeignKey(SubdisciplineArea, blank=True, null=True)

    def __unicode__(self):
        return self.competency_area

class Level(models.Model):
    APPRENTICE = 'Apprentice'
    TECHNICIAN = 'Technician'
    MASTER = 'Master'
    PROFESSIONAL = 'Professional'
    LEVEL_TYPE_CHOICES = ( (APPRENTICE, 'Apprentice'), (TECHNICIAN, 'Technician'),
                           (MASTER, 'Master'), (PROFESSIONAL, 'Professional') )
    level_type = models.CharField(max_length=500, choices=LEVEL_TYPE_CHOICES)
    level_description = models.CharField(max_length=5000)
    competency_area = models.ForeignKey(CompetencyArea)

    def __unicode__(self):
        return self.level_description

    class Meta:
        unique_together = ('competency_area', 'level_type',)
        order_with_respect_to = 'competency_area'

class EssentialUnderstanding(models.Model):
    essential_understanding = models.CharField(max_length=2000)
    competency_area = models.ForeignKey(CompetencyArea)

    def __unicode__(self):
        return self.essential_understanding

class LearningTarget(models.Model):
    learning_target = models.CharField(max_length=2000)
    essential_understanding = models.ForeignKey(EssentialUnderstanding)

    def __unicode__(self):
        return self.learning_target

# --- Pathways ---
from django.db.models import Q
class Pathway(models.Model):
    name = models.CharField(max_length=500)
    school = models.ForeignKey(School)
    subject_areas = models.ManyToManyField(SubjectArea)
    subdiscipline_areas = models.ManyToManyField(SubdisciplineArea, blank=True, null=True)
    competency_areas = models.ManyToManyField(CompetencyArea, blank=True, null=True)
    essential_understandings = models.ManyToManyField(EssentialUnderstanding, blank=True, null=True)
    learning_targets = models.ManyToManyField(LearningTarget, blank=True, null=True)

    def __unicode__(self):
        return self.name

# --- ModelForms ---
class CompetencyAreaForm(ModelForm):
    class Meta:
        model = CompetencyArea
        fields = ('competency_area',)
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'competency_area': Textarea(attrs={'rows': 5, 'class': 'span8'}) }

class EssentialUnderstandingForm(ModelForm):
    class Meta:
        model = EssentialUnderstanding
        fields = ('essential_understanding',)
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'essential_understanding': Textarea(attrs={'rows': 5, 'class': 'span8'}) }

class LevelForm(ModelForm):
    class Meta:
        model = Level
        fields = ('level_type', 'level_description',)
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'level_description': Textarea(attrs={'rows': 5, 'class': 'span8'}) }

class LearningTargetForm(ModelForm):
    class Meta:
        model = LearningTarget
        fields = ('learning_target', )
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        widgets = {'learning_target': Textarea(attrs={'rows': 5, 'class': 'span8'}) }

class PathwayForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(PathwayForm, self).__init__(*args, **kwargs)
        pathway = self.instance

        # sas
        self.fields['subject_areas'].queryset = pathway.school.subjectarea_set.all()

        # sdas
        if pathway.subject_areas.all():
            sda_queryset = SubdisciplineArea.objects.none()
            for sa in pathway.subject_areas.all():
                sda_queryset = sda_queryset | sa.subdisciplinearea_set.all()
            self.fields['subdiscipline_areas'].queryset = sda_queryset

        # cas
        if pathway.subject_areas.all():
            ca_queryset = CompetencyArea.objects.none()
            # General subject area competencies:
            for sa in pathway.subject_areas.all():
                ca_queryset = ca_queryset | sa.competencyarea_set.all().filter(subdiscipline_area=None)
            # Subdiscipline area competencies:
            if pathway.subdiscipline_areas.all():
                for sda in pathway.subdiscipline_areas.all():
                    ca_queryset = ca_queryset | sda.competencyarea_set.all()
            self.fields['competency_areas'].queryset = ca_queryset

        # eus
        if pathway.competency_areas.all():
            eu_queryset = EssentialUnderstanding.objects.none()
            for ca in pathway.competency_areas.all():
                eu_queryset |= ca.essentialunderstanding_set.all()
            self.fields['essential_understandings'].queryset = eu_queryset

        # lts
        if pathway.essential_understandings.all():
            lt_queryset = LearningTarget.objects.none()
            for eu in pathway.essential_understandings.all():
                lt_queryset |= eu.learningtarget_set.all()
            self.fields['learning_targets'].queryset = lt_queryset

    class Meta:
        model = Pathway
        # Bootstrap controls width of Textarea, ignoring the 'cols' setting. Can also use 'class': 'input-block-level'
        #  Consider CheckboxSelectMultiple for some of these, especially eus and lts
        # number of items to show in longer dropdown lists:
        widgets = {
            'name': TextInput(attrs={'class': 'span4'}),
            'subject_areas': SelectMultiple(attrs={'class': 'span4', 'size': 5}),
            'subdiscipline_areas': SelectMultiple(attrs={'class': 'span4', 'size': 5}),
            'competency_areas': SelectMultiple(attrs={'class': 'span4', 'size': 15}),
            'essential_understandings': SelectMultiple(attrs={'class': 'span8', 'size': 20}),
            'learning_targets': SelectMultiple(attrs={'class': 'span8', 'size': 20}),
            }
<|endoftext|>


<commit_before>import unittest

from cloudshell.api import cloudshell_api

from cloudshell.workflow.orchestration.sandbox import Sandbox

import sys

if (sys.version_info >= (3,0)):
    from unittest.mock import MagicMock
    from unittest import TestCase, mock, patch
else:
    from mock import MagicMock, patch
    import mock
    from unittest import TestCase

class TestSandbox(unittest.TestCase):
    def setUp(self):
        patcher = patch.dict('os.environ', {
            'qualiConnectivityContext': '{"tsAPIPort": "8028","adminPass": "admin", "adminUser": "admin", "serverAddress":"localhost"}',
            'reservationLifecycleContext': '{"reservationId":"be015364-9640-4ac5-b6ca-f26e1c6d44c8", "savedSandboxName":"empty", "savedSandboxDescription":"","currentUserName":"admin"}',
            'reservationContext': '{"environmentName":"","runningUser":"admin", "environmentPath":"Global Topologies/empty","domain":"Global", "description":"","parameters":{"resourceRequirements":[],"globalInputs":[{"parameterName": "in1", "value": "222"},{"parameterName": "in2", "value": "0"}],"resourceAdditionalInfo":[]},"ownerUser":"admin","ownerPass":"admin","id":"be015364-9640-4ac5-b6ca-f26e1c6d44c8","permittedUsers":[{"userName":"admin", "email":"None"}]}',
            'MY_PARAM': 'PARAM-VALUE'})
        patcher.start()

    def tearDown(self):
        patch.stopall()

    @patch('cloudshell.helpers.scripts.cloudshell_scripts_helpers.get_api_session')
    @patch.object(cloudshell_api, 'GetReservationDescriptionResponseInfo')
    def test_sandbox_inputs(self, automation_api, details):
        #automation_api.return_value = 'test-val-1'
        #details.ReservationDescription.Id = 'be015364-9640-4ac5-b6ca-f26e1c6d44c8'
       # automation_api.GetReservationDetails.return_value = details
        sandbox = Sandbox()
        param = sandbox.get_user_param('MY_PARAM')
        self.assertEqual(param, "PARAM-VALUE")<commit_msg>handle Error in atexit._run_exitfuncs<commit_after>import logging
import unittest

from cloudshell.api import cloudshell_api
from cloudshell.core.logger import qs_logger, interprocess_logger
from cloudshell.core.logger.qs_logger import get_qs_logger
import multiprocessing
from cloudshell.workflow.orchestration.sandbox import Sandbox

import sys

if (sys.version_info >= (3,0)):
    from unittest.mock import MagicMock, patch
    from unittest import TestCase, mock
else:
    from mock import MagicMock, patch
    import mock
    from unittest import TestCase

class TestSandbox(unittest.TestCase):
    def setUp(self):
        patcher = patch.dict('os.environ', {
            'qualiConnectivityContext': '{"tsAPIPort": "8028","adminPass": "admin", "adminUser": "admin", "serverAddress":"localhost"}',
            'reservationLifecycleContext': '{"reservationId":"be015364-9640-4ac5-b6ca-f26e1c6d44c8", "savedSandboxName":"empty", "savedSandboxDescription":"","currentUserName":"admin"}',
            'reservationContext': '{"environmentName":"","runningUser":"admin", "environmentPath":"Global Topologies/empty","domain":"Global", "description":"","parameters":{"resourceRequirements":[],"globalInputs":[{"parameterName": "in1", "value": "222"},{"parameterName": "in2", "value": "0"}],"resourceAdditionalInfo":[]},"ownerUser":"admin","ownerPass":"admin","id":"be015364-9640-4ac5-b6ca-f26e1c6d44c8","permittedUsers":[{"userName":"admin", "email":"None"}]}',
            'MY_PARAM': 'PARAM-VALUE'})
        patcher.start()

    def tearDown(self):
        patch.stopall()

    @patch('cloudshell.helpers.scripts.cloudshell_scripts_helpers.get_api_session')
    @patch.object(interprocess_logger, 'MultiProcessingLog') #without it getting errors like: Error in atexit._run_exitfuncs
    @patch.object(cloudshell_api, 'GetReservationDescriptionResponseInfo')
    def test_sandbox_inputs(self, automation_api, logger, details):
        # automation_api.return_value = 'test-val-1'
        # details.ReservationDescription.Id = 'be015364-9640-4ac5-b6ca-f26e1c6d44c8'
        # automation_api.GetReservationDetails.return_value = details
        sandbox = Sandbox()
        param = sandbox.get_user_param('MY_PARAM')
        self.assertEqual(param, "PARAM-VALUE")<|endoftext|>