def test_details_view(self):
     """Details page displays all the fields Title, Date, Time Spent, What You Learned, Resources to Remember."""
     journal_entry_data = {
         'title':
         'testing new journal entries',
         'date':
         datetime.datetime.now().strftime('%Y-%m-%d'),
         'time_spent':
         '2',
         'what_i_learned':
         'how to test flask views',
         'resources_to_remember':
         'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
     }
     with test_database(TEST_DB, (User, JournalEntry)):
         UserModelTestCase.create_users(1)
         journal_entry_data['user'] = User.select().get()
         JournalEntry.create(**journal_entry_data)
         self.app.post('/login', data=USER_DATA)
         rv = self.app.get('/details/{}'.format(JournalEntry.get().id))
         self.assertIn(journal_entry_data['title'],
                       rv.get_data(as_text=True))
         self.assertIn(journal_entry_data['date'],
                       rv.get_data(as_text=True))
         self.assertIn(journal_entry_data['time_spent'],
                       rv.get_data(as_text=True))
         self.assertIn(journal_entry_data['what_i_learned'],
                       rv.get_data(as_text=True))
         self.assertIn(journal_entry_data['resources_to_remember'],
                       rv.get_data(as_text=True))
Beispiel #2
0
class TestJournalEntry(TestCase):
    """
    JournalEntry model tests
    """

    def setUp(self):
        self.journalEntry = JournalEntry()
        self.journalEntry.title = "Test title"
        self.journalEntry.author = testUser
        self.journalEntry.show_on_main = False

    def test_import(self):
        """
        Should import module
        """
        self.assertIsNotNone(JournalEntry)
        self.assertIsNotNone(get_group_journals)

    def test_unicode(self):
        """
        Should return unicode value
        """
        self.assertIsNotNone(unicode(self.journalEntry))
        self.assertTrue(unicode(self.journalEntry).endswith(
            self.journalEntry.title))

    @skip
    def test_save_and_retrieve(self):
        """
        Should save and retrieve
        """
        self.assertEqual(
            0, JournalEntry.objects.all().count(), "Should be empty")
        self.journalEntry.save()

        allEntries = JournalEntry.objects.all()
        self.assertEqual(1, allEntries.count(), "Should have 1 entry")

        entry = allEntries[0]
        self.assertIsInstance(entry, JournalEntry,
                              "Should be an instance of JournalEntry")

        # Make sure the correct values have been saved
        self.assertEqual(entry.title, self.journalEntry.title,
                         "Should have same title")
        self.assertEqual(entry.author.name,
                         self.journalEntry.author.name,
                         "Should have same authors")

        self.assertEqual(entry.show_on_main, False)

    @skip
    def test_get_absolute_url(self):
        self.assertIsNotNone(self.journalEntry.get_absolute_url())

    def test_has_plural(self):
        self.assertIsNotNone(JournalEntry._meta.verbose_name_plural)
Beispiel #3
0
def get_entry_by_id(user):
    entries = JournalEntry.select().where(JournalEntry.author == user)
    if not entries:
        print("there are no journals")
    elif entries:
        entry_id = int(input("choose any entry id"))
        entry = JournalEntry.select().where(JournalEntry.id == entry_id).get()
        print("-" * 20)
        print(entry.content)
        print("-" * 20)
Beispiel #4
0
class TestJournalEntry(TestCase):
    """
    JournalEntry model tests
    """
    def setUp(self):
        self.journalEntry = JournalEntry()
        self.journalEntry.title = "Test title"
        self.journalEntry.author = testUser
        self.journalEntry.show_on_main = False

    def test_import(self):
        """
        Should import module
        """
        self.assertIsNotNone(JournalEntry)
        self.assertIsNotNone(get_group_journals)


    def test_unicode(self):
        """
        Should return unicode value
        """
        self.assertIsNotNone(unicode(self.journalEntry))
        self.assertTrue(unicode(self.journalEntry).endswith(self.journalEntry.title))

    @skip("TODO: Fix this test")
    def test_save_and_retrieve(self):
        """
        Should save and retrieve
        """
        self.assertEqual(0, JournalEntry.objects.all().count(), "Should be empty")
        self.journalEntry.save()

        allEntries = JournalEntry.objects.all()
        self.assertEqual(1, allEntries.count(), "Should have 1 entry")

        entry = allEntries[0]
        self.assertIsInstance(entry, JournalEntry, "Should be an instance of JournalEntry")

        # Make sure the correct values have been saved
        self.assertEqual(entry.title, self.journalEntry.title, "Should have same title")
        self.assertEqual(entry.author.name,
                         self.journalEntry.author.name,
                         "Should have same authors")

        self.assertEqual(entry.show_on_main, False)

    @skip("TODO")
    def test_get_absolute_url(self):
        self.assertIsNotNone(self.journalEntry.get_absolute_url())

    def test_has_plural(self):
        self.assertIsNotNone(JournalEntry._meta.verbose_name_plural)
 def test_journal_entry_creation(self):
     """Test creating a JournalEntry"""
     with test_database(TEST_DB, (User, JournalEntry)):
         UserModelTestCase.create_users()
         user = User.select().get()
         JournalEntry.create(
             user=user,
             title='Testing Journal Entries',
             date=datetime.datetime.now().strftime('%Y-%m-%d'),
             time_spent='22',
             what_i_learned='Hopefully, I learn if this works or not!',
             resources_to_remember='teamtreehouse.com')
         self.assertEqual(JournalEntry.select().count(), 1)
         self.assertEqual(JournalEntry.user, user)
Beispiel #6
0
def make_entry(user, content):
    entry = JournalEntry.create(content=content,
                                author=user,
                                timestamp=datetime.now())

    if entry == 1:
        print("Entry Saved Successfully!\n")
Beispiel #7
0
def get_all_entries(user):
    entries = JournalEntry.select().where(JournalEntry.author == user)

    print("-" * 20)
    for entry in entries:
        print(entry.id, entry.timestamp, entry.content[:20], "...")
    print("-" * 20)
    def test_list_view(self):
        """The list view contains a list of journal entries, which displays Title and Date for Entry."""
        journal_entry_data_1 = {
            'title':
            'testing 1',
            'date':
            datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent':
            '4',
            'what_i_learned':
            'how to test flask views',
            'resources_to_remember':
            'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
        }
        journal_entry_data_2 = {
            'title':
            'testing 123',
            'date':
            datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent':
            '8',
            'what_i_learned':
            'how to test flask views',
            'resources_to_remember':
            'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
        }
        with test_database(TEST_DB, (User, JournalEntry)):
            UserModelTestCase.create_users(1)
            user = User.select().get()
            journal_entry_data_1['user'] = user
            journal_entry_data_2['user'] = user
            JournalEntry.create(**journal_entry_data_1)
            JournalEntry.create(**journal_entry_data_2)

            self.app.post('/login', data=USER_DATA)
            rv = self.app.get('/entries')
            self.assertNotIn('No Entries...', rv.get_data(as_text=True))
            self.assertIn(journal_entry_data_1['title'],
                          rv.get_data(as_text=True))
            self.assertIn(journal_entry_data_1['date'],
                          rv.get_data(as_text=True))
            self.assertIn(journal_entry_data_2['title'],
                          rv.get_data(as_text=True))
            self.assertIn(journal_entry_data_2['date'],
                          rv.get_data(as_text=True))
Beispiel #9
0
def delete_journal(user, id):
    entry = JournalEntry.select().where(JournalEntry.id == id).get()
    print("Delete the journal--", id)
    a = input("(y/n)-->")
    if a == "y":
        entry.delete_instance()
        print("Entry deleted")
    elif a == "n":
        print("Journal not deleted")
        return user.get()
 def test_details_link_to_edit(self):
     """Details page includes a link to edit the entry"""
     journal_entry_data = {
         'title':
         'testing new journal entries',
         'date':
         datetime.datetime.now().strftime('%Y-%m-%d'),
         'time_spent':
         '2',
         'what_i_learned':
         'how to test flask views',
         'resources_to_remember':
         'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
     }
     with test_database(TEST_DB, (User, JournalEntry)):
         UserModelTestCase.create_users(1)
         journal_entry_data['user'] = User.select().get()
         JournalEntry.create(**journal_entry_data)
         self.app.post('/login', data=USER_DATA)
         rv = self.app.get('/details/{}'.format(JournalEntry.get().id))
         self.assertIn('href="/entry/', rv.get_data(as_text=True))
Beispiel #11
0
def new(request, year):
	year = int(year)

	# Default the date to the same date as the last entry for this year,
	# provided one exists. Otherwise, just the start of the year.
	try:
		lastentry = JournalEntry.objects.filter(year=year).order_by('-date')[0]
		d = lastentry.date
	except IndexError:
		d = date(year,1,1)

	year = get_object_or_404(Year, year=year)
	highseq = JournalEntry.objects.filter(year=year).aggregate(Max('seq'))['seq__max']
	if highseq is None:
		highseq = 0
	entry = JournalEntry(year=year, seq=highseq+1, date=d, closed=False)
	entry.save()

	# Disable any search query to make sure we can actually see
	# the record we've just created.
	_setup_search(request, '')

	return HttpResponseRedirect('/accounting/e/%s/' % entry.pk)
    def test_journal_entry_list(self):
        """Test new Journal Entries display on the home page, and the 'no entries' message does not."""
        journal_entry_data = {
            'title':
            'testing new journal entries',
            'date':
            datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent':
            '2',
            'what_i_learned':
            'how to test flask views',
            'resources_to_remember':
            'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
        }
        with test_database(TEST_DB, (User, JournalEntry)):
            UserModelTestCase.create_users(1)
            journal_entry_data['user'] = User.select().get()
            JournalEntry.create(**journal_entry_data)
            self.app.post('/login', data=USER_DATA)

            rv = self.app.get('/')
            self.assertNotIn('No Entries...', rv.get_data(as_text=True))
            self.assertIn(journal_entry_data['title'],
                          rv.get_data(as_text=True))
    def test_more_entries_button(self):
        """If there's more than 5 entries, the home page should display a More Entries button"""
        journal_entry_data = {
            'title':
            'testing more entries',
            'date':
            datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent':
            '4',
            'what_i_learned':
            'how to test flask views',
            'resources_to_remember':
            'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
        }
        with test_database(TEST_DB, (User, JournalEntry)):
            UserModelTestCase.create_users(1)
            user = User.select().get()
            journal_entry_data['user'] = user
            for _ in range(6):
                JournalEntry.create(**journal_entry_data)

            self.app.post('/login', data=USER_DATA)
            rv = self.app.get('/')
            self.assertIn('More Entries', rv.get_data(as_text=True))
    def test_list_view_hyperlink(self):
        """The list view Title should be hyperlinked to the detail page for each journal entry."""
        journal_entry_data = {
            'title':
            'testing hyperlink',
            'date':
            datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent':
            '4',
            'what_i_learned':
            'how to test flask views',
            'resources_to_remember':
            'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
        }
        with test_database(TEST_DB, (User, JournalEntry)):
            UserModelTestCase.create_users(1)
            user = User.select().get()
            journal_entry_data['user'] = user
            JournalEntry.create(**journal_entry_data)

            self.app.post('/login', data=USER_DATA)
            hyperlink = 'href="/details/{}"'.format(JournalEntry.get().id)
            rv = self.app.get('/entries')
            self.assertIn(hyperlink, rv.get_data(as_text=True))
    def test_journal_entry_create(self):
        """Test can create new JournalEntry, redirects to homepage, and adds to the database."""
        journal_entry_data = {
            'title':
            'testing new journal entries',
            'date':
            datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent':
            '2',
            'what_i_learned':
            'how to test flask views',
            'resources_to_remember':
            'teamtreehouse.com, stackoverflow.com, flask.pocoo.org'
        }
        with test_database(TEST_DB, (User, JournalEntry)):
            UserModelTestCase.create_users(1)
            self.app.post('/login', data=USER_DATA)

            journal_entry_data['user'] = User.select().get()
            rv = self.app.post('/entry', data=journal_entry_data)
            self.assertEqual(rv.status_code, 302)
            self.assertEqual(rv.location, 'http://localhost/')
            self.assertEqual(JournalEntry.select().count(), 1)
Beispiel #16
0
def title_exists(form, field):
    if JournalEntry.select().where(JournalEntry.title**field.data).exists():
        raise ValidationError('An entry with that title already exists.')
Beispiel #17
0
 def setUp(self):
     self.journalEntry = JournalEntry()
     self.journalEntry.title = "Test title"
     self.journalEntry.author = testUser
     self.journalEntry.show_on_main = False
def webpay_run(name, payment_pk, *args, **kwargs):
    """Runs a Webpay binary within a preconfigured environment.

    Before running the binary, this context manager recreates the
    directories and files in /tmp that the binary needs to run correctly,
    as if it were sitting in an standalone web server.

    Yields a subprocess.Popen instance with an open pipe to stdin and stdout.

    After running the binary, log and journal entries are captured and
    then temporary files are removed.

    Args:
        name: A string, basename of the binary as is found in assets_dir.
        payment_pk: An integer, primary key for the related payment. This
            is needed to associate the logs with their payment.
        *args: Extra positional arguments are appended to the command line
            before execution.

    Example:
        >>> webpay_run('tbk_bp_resultado.cgi', 3958) as cgi:
                output, _ = cgi.communicate("TBK_MONTO=384800&...\n")
                do_something_with(output)

    WARNING: Always use Popen with communicate() method when using PIPE
        or there will be deadlocks.
    """

    from pprint import pprint

    # prepare the configuration files
    assets_dir = PaymentProcessor.get_backend_setting('ASSETS_DIR')
    tbk_config = PaymentProcessor.get_tbk_config(payment_pk, 'CLP')  # FIXME
    tbk_param = PaymentProcessor.get_tbk_param()
    tbk_trace = PaymentProcessor.get_tbk_trace()

    temp_dir = mkdtemp()
    cgi_path = os.path.join(assets_dir, name)
    temp_cgi_path = os.path.join(temp_dir, name)
    datos_path = os.path.join(temp_dir, 'datos')

    os.mkdir(datos_path)
    with open(os.path.join(datos_path, 'tbk_config.dat'), 'w') as f:
        pprint("TBK_CONFIG: %s" % tbk_config)
        pprint('------------------------------------------')
        f.write(tbk_config)
    with open(os.path.join(datos_path, 'tbk_param.txt'), 'w') as f:
        f.write(tbk_param)
    with open(os.path.join(datos_path, 'tbk_trace.dat'), 'w') as f:
        f.write(tbk_trace)

    # prepare the public and private keys
    maestros_path = os.path.join(temp_dir, 'maestros')
    public_key, private_key = PaymentProcessor.get_keys()

    os.mkdir(maestros_path)
    with open(os.path.join(maestros_path, 'tbk_public_key.pem'), 'w') as f:
        f.write(public_key)
    with open(os.path.join(maestros_path, 'privada.pem'), 'w') as f:
        f.write(private_key)

    # prepare the log directory
    log_path = os.path.join(temp_dir, 'log')
    os.mkdir(log_path)

    # copy the binary to the temp dir and make it executable
    copyfile(cgi_path, temp_cgi_path)
    os.chmod(temp_cgi_path, S_IEXEC)

    yield Popen([temp_cgi_path] + list(args), stdin=PIPE, stdout=PIPE)

    # capture the logs
    try:
        from getpaid.models import Payment

        payment = Payment.objects.get(pk=payment_pk)

        for event_log in glob.glob(os.path.join(log_path, 'TBK_EVN*')):
            with open(event_log, 'r') as f:
                for line in map(str.strip, f.readlines()):
                    pprint("TBK_ENV: %s" % line)
                    from models import LogEntry

                    entry = LogEntry.from_line(line=line, payment=payment)
                    entry.save()
                pprint('------------------------------------------')

        for journal_log in glob.glob(os.path.join(log_path, 'tbk_bitacora_TR_NORMAL*')):
            st = os.stat(journal_log)
            date = datetime.date.fromtimestamp(st.st_mtime)
            with open(journal_log, 'r') as f:
                for line in map(str.strip, f.readlines()):
                    pprint("TBK_BITACORA: %s" % line)
                    from models import JournalEntry
                    entry = JournalEntry(date=date, body=line, payment=payment)
                    entry.save()
                pprint('------------------------------------------')
    except Payment.DoesNotExist:
        pass

    # clean up
    rmtree(temp_dir)
Beispiel #19
0
def webpay_run(name, payment_pk, *args, **kwargs):
    """Runs a Webpay binary within a preconfigured environment.
    Before running the binary, this context manager recreates the
    directories and files in /tmp that the binary needs to run correctly,
    as if it were sitting in an standalone web server.
    Yields a subprocess.Popen instance with an open pipe to stdin and stdout.
    After running the binary, log and journal entries are captured and
    then temporary files are removed.
    Args:
        name: A string, basename of the binary as is found in assets_dir.
        payment_pk: An integer, primary key for the related payment. This
            is needed to associate the logs with their payment.
        *args: Extra positional arguments are appended to the command line
            before execution.
    Example:
        >>> webpay_run('tbk_bp_resultado.cgi', 3958) as cgi:
                output, _ = cgi.communicate("TBK_MONTO=384800&...\n")
                do_something_with(output)
    WARNING: Always use Popen with communicate() method when using PIPE
        or there will be deadlocks.
    """

    from pprint import pprint

    # prepare the configuration files
    assets_dir = PaymentProcessor.get_backend_setting('WEBPAY_DOCS')
    tbk_config = PaymentProcessor.get_tbk_config(kwargs.get('request'),
                                                 payment_pk, 'CLP')  # FIXME
    tbk_param = PaymentProcessor.get_tbk_param()
    tbk_trace = PaymentProcessor.get_tbk_trace()

    # temp_dir = mkdtemp()
    cgi_path = os.path.join(assets_dir, name)
    # temp_cgi_path = os.path.join(assets_dir, name)
    datos_path = os.path.join(assets_dir, 'datos')

    # os.mkdir(datos_path)
    # with open(os.path.join(datos_path, 'tbk_config.dat'), 'w') as f:
    #     pprint("TBK_CONFIG: %s" % tbk_config)
    #     pprint('------------------------------------------')
    #     f.write(tbk_config)
    # with open(os.path.join(datos_path, 'tbk_param.txt'), 'w') as f:
    #     f.write(tbk_param)
    # with open(os.path.join(datos_path, 'tbk_trace.dat'), 'w') as f:
    #     f.write(tbk_trace)

    # prepare the public and private keys
    maestros_path = os.path.join(assets_dir, 'maestros')
    public_key, private_key = PaymentProcessor.get_keys()

    # os.mkdir(maestros_path)
    # with open(os.path.join(maestros_path, 'tbk_public_key.pem'), 'w') as f:
    #     f.write(public_key)
    # with open(os.path.join(maestros_path, 'privada.pem'), 'w') as f:
    #     f.write(private_key)

    # prepare the log directory
    log_path = os.path.join(assets_dir, 'log')
    # os.mkdir(log_path)

    # copy the binary to the temp dir and make it executable
    # copyfile(cgi_path, temp_cgi_path)
    # os.chmod(cgi_path, S_IEXEC)

    yield Popen([sys.executable, cgi_path] + list(args),
                stdin=PIPE,
                stdout=PIPE)

    # capture the logs
    try:
        from getpaid.models import Payment

        payment = Payment.objects.get(pk=payment_pk)

        for event_log in glob.glob(os.path.join(log_path, 'TBK_EVN*')):
            with open(event_log, 'r') as f:
                for line in map(str.strip, f.readlines()):
                    pprint("TBK_ENV: %s" % line)
                    from models import LogEntry

                    entry = LogEntry.from_line(line=line, payment=payment)
                    entry.save()
                pprint('------------------------------------------')

        for journal_log in glob.glob(
                os.path.join(log_path, 'tbk_bitacora_TR_NORMAL*')):
            st = os.stat(journal_log)
            date = datetime.date.fromtimestamp(st.st_mtime)
            with open(journal_log, 'r') as f:
                for line in map(str.strip, f.readlines()):
                    pprint("TBK_BITACORA: %s" % line)
                    from models import JournalEntry
                    entry = JournalEntry(date=date, body=line, payment=payment)
                    entry.save()
                pprint('------------------------------------------')
    except Payment.DoesNotExist:
        pass
    def test_many_to_many_relationships(self):
        """Make sure JournalEntries and Tags can have many to many relationships"""
        journal_entry_data_1 = {
            'title': 'entry 1',
            'date': datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent': '111',
            'what_i_learned': 'many to many relationships',
            'resources_to_remember': 'docs.peewee-orm.com'
        }
        journal_entry_data_2 = {
            'title': 'entry 2',
            'date': datetime.datetime.now().strftime('%Y-%m-%d'),
            'time_spent': '222',
            'what_i_learned': 'many to many relationships',
            'resources_to_remember': 'docs.peewee-orm.com'
        }
        with test_database(TEST_DB,
                           (User, JournalEntry, Tag, JournalEntryTag)):
            # create the user
            UserModelTestCase.create_users(1)

            # create the journal entries
            journal_entry_data_1['user'] = User.select().get()
            journal_entry_data_2['user'] = User.select().get()
            JournalEntry.create(**journal_entry_data_1)
            JournalEntry.create(**journal_entry_data_2)
            entry1 = JournalEntry.get(JournalEntry.title == 'entry 1')
            entry2 = JournalEntry.get(JournalEntry.title == 'entry 2')

            # create the tags
            Tag.create_tag(tag='first')
            Tag.create_tag(tag='both')
            Tag.create_tag(tag='second')
            tag1 = Tag.get(Tag.tag == 'first')
            tag2 = Tag.get(Tag.tag == 'both')
            tag3 = Tag.get(Tag.tag == 'second')

            # tie tags to entries
            entry1.tags.add(
                [Tag.get(Tag.tag == 'first'),
                 Tag.get(Tag.tag == 'both')])

            entry2.tags.add(
                [Tag.get(Tag.tag == 'second'),
                 Tag.get(Tag.tag == 'both')])

            # assertions
            self.assertIn(tag1, entry1.tags)
            self.assertIn(tag2, entry1.tags)
            self.assertNotIn(tag3, entry1.tags)

            self.assertNotIn(tag1, entry2.tags)
            self.assertIn(tag2, entry2.tags)
            self.assertIn(tag3, entry2.tags)

            self.assertIn(entry1, tag1.journal_entries)
            self.assertNotIn(entry2, tag1.journal_entries)

            self.assertIn(entry1, tag2.journal_entries)
            self.assertIn(entry2, tag2.journal_entries)

            self.assertNotIn(entry1, tag3.journal_entries)
            self.assertIn(entry2, tag3.journal_entries)
Beispiel #21
0
def make_entry(user, content):
    entry = JournalEntry.create(content=content,
                                author=user,
                                timestamp=datetime.now())
    if entry == 1:
        print("entry saved")
Beispiel #22
0
def get_entry_by_id(id):
    entry = JournalEntry.select().where(JournalEntry.id == id).get()
    print("-" * 20)
    print(entry.content)
    print("-" * 20)
Beispiel #23
0
 def setUp(self):
     self.journalEntry = JournalEntry()
     self.journalEntry.title = "Test title"
     self.journalEntry.author = testUser
     self.journalEntry.show_on_main = False
Beispiel #24
0
def create_accounting_entry(date,
							items,
							leaveopen=False,
							urllist=None):
	# items must be an array of tuples in the format:
	# (accountnumber, descriptiontext, amount, objectname)
	# Positive amounts indicate debit, negative amounts indicate credit.
	# objects are referenced by *named* and looked up internally here.
	# Entries must be balanced unless leaveopen is set to True
	# Any urls listed in urllist must exist and be correct, no verification
	# is done.

	if not settings.ENABLE_AUTO_ACCOUNTING:
		return

	sid = transaction.savepoint()
	try:
		# Start by some simple validation
		for r in items:
			if r[2] == 0:
				raise AccountingException("Submitted accounting journal entry has a zero sum entry!")
			if Decimal(r[2]).as_tuple().exponent < -2:
				raise AccountingException("Submitted accounting journal entry has items that are not rounded off to two decimal points!")

		debitsum = sum([r[2] for r in items if r[2] > 0])
		creditsum = -sum([r[2] for r in items if r[2] < 0])
		if debitsum != creditsum and not leaveopen:
			raise AccountingException("Submitted accounting journal entry is not balanced!")

		try:
			year = Year.objects.get(year=date.year)
		except Year.DoesNotExist:
			raise AccountingException("Year %s does not exist in the accounting system!" % date.year)
		if not year.isopen:
			raise AccountingException("Year %s is not open for new entries!" % date.year)
		seq = JournalEntry.objects.filter(year=year).aggregate(Max('seq'))['seq__max']
		if seq is None: seq = 0

		# We assume the rest is correct and start building the db entries,
		# since we'll just roll it back if referenced data is missing.

		entry = JournalEntry(year=year, seq=seq+1, date=date, closed=False)
		entry.save()

		for accountnum, description, amount, objectname in items:
			try:
				account = Account.objects.get(num=accountnum)
				if objectname:
					obj = Object.objects.get(name=objectname)
				else:
					obj = None
				JournalItem(journal=entry,
							account=account,
							amount=amount,
							object=obj,
							description=description).save()
			except Account.DoesNotExist:
				raise AccountingException("Account %s does not exist!" % accountnum)
			except Object.DoesNotExist:
				raise AccountingException("Object %s does not exist!" % objectname)

		# If there are any URLs to attach, do so now
		if urllist:
			for url in urllist:
				JournalUrl(journal=entry, url=url).save()

		# All items saved correct. Close the entry if we have to. We verified
		# above that it's valid...
		if not leaveopen:
			entry.closed = True
			entry.save()

		# Ok, it seems it worked...
		transaction.savepoint_commit(sid)
	except:
		transaction.savepoint_rollback(sid)
		raise