Exemplo n.º 1
0
    def setUp(self):
        super(BaseClassIO, self).setUp()

        self.invoice = Invoice([
            TimeEntry(1, _dt(2010, 1, 1), '1st entry', 'Company1', 'job1'),
            TimeEntry(2.5, _dt(2010, 1, 2), '2nd entry', 'Company1', 'job1')
        ], _dt(2010, 1, 14), (_dt(2010, 1, 1), _dt(2010, 1, 13)),
                               CompanyJobs('Company1', {'job1': 'Job One'},
                                           20))
Exemplo n.º 2
0
    def testSumEntryHours(self):
        entry1 = TimeEntry(1, None, None, None, None)
        entry2 = TimeEntry(2, None, None, None, None)
        entry3 = TimeEntry(2.5, None, None, None, None)
        entry4 = TimeEntry(3.0, None, None, None, None)

        _total = TimeEntry.get_hours_total
        self.assertEqual(_total([entry1, entry2]), 3.0)
        self.assertEqual(_total([entry1, entry2, entry3]), 5.5)
        self.assertEqual(_total([entry1, entry2, entry3, entry4]), 8.5)
Exemplo n.º 3
0
    def testFilterEntries(self):
        comp1_entries = [
            TimeEntry(None, None, None, 'Company1', None) for i in range(100)
            ]
        comp2_entries = [
            TimeEntry(None, None, None, 'Company2', None) for i in range(100)
            ]
        comp3_entries = [
            TimeEntry(None, None, None, 'Company3', None) for i in range(100)
            ]

        all_entries = comp1_entries + comp2_entries + comp3_entries

        for entry in TimeEntry.query(all_entries, 'Company1'):
            self.assertEqual(entry.company, 'Company1')
        for entry in TimeEntry.query(all_entries, 'Company2'):
            self.assertEqual(entry.company, 'Company2')
        for entry in TimeEntry.query(all_entries, 'Company3'):
            self.assertEqual(entry.company, 'Company3')

        import random
        random.shuffle(all_entries)

        for entry in TimeEntry.query(all_entries, 'Company1'):
            self.assertEqual(entry.company, 'Company1')
        for entry in TimeEntry.query(all_entries, 'Company2'):
            self.assertEqual(entry.company, 'Company2')
        for entry in TimeEntry.query(all_entries, 'Company3'):
            self.assertEqual(entry.company, 'Company3')
Exemplo n.º 4
0
    def testCreateInvoice(self):
        filtered_entries = TimeEntry.query(self.entries, 'Company1')
        invoice = Invoice(filtered_entries, None, (None, None), self.company1_jobs)
        self.assertEqual(invoice.hours_total, 3)

        filtered_entries = TimeEntry.query(self.entries, 'Company2')
        invoice = Invoice(filtered_entries, None, (None, None), self.company2_jobs)
        self.assertEqual(invoice.hours_total, 4.9)

        filtered_entry_ids = [e.id for e in filtered_entries]
        self.assertEqual(sorted(invoice.entry_ids), sorted(filtered_entry_ids))
Exemplo n.º 5
0
    def __init__(self, entries, payment_dt, pay_period, jobs):
        self.company = jobs.company

        for i in range(len(entries) - 1, -1, -1):
            if entries[i].company != self.company:
                raise ValueError('Entry with different company: %s and %s' %
                                 (repr(entries[i]), self.company))

            if not entries[i].can_be_invoiced():
                del (entries[i])

        self.entries = sorted(entries, key=lambda x: x.dt)

        self.entry_ids = []
        self.job_ids = defaultdict(list)
        for entry in self.entries:
            self.entry_ids.append(entry.id)
            self.job_ids[entry.job].append(entry)

        self.hours_total = TimeEntry.get_hours_total(self.entries)
        self.invoiced_dt = None
        self.payment_dt = payment_dt
        self.paid_dt = None
        self.sent = False

        self.payperiod_start = pay_period[0]
        self.payperiod_end = pay_period[1]
        self.jobs = jobs
        self.id = uuid.uuid1().hex
Exemplo n.º 6
0
    def testSendInvoice(self):
        """Asserting the invoiced_dt value is weird, like what am I
           trying to prove?  So far, it's only use is being printed in
           text; of interest for future record keeping?  I don't
           really have a personal need for send(), so it's just this
           kinda-academic thing I thought an invoice should have.  And
           I think that uncertainty shows in this lame test.

        """
        
        filtered_entries = TimeEntry.query(self.entries, 'Company1')
        invoice = Invoice(filtered_entries, None, (None, None), self.company1_jobs)

        send_start = _dt.now()
        invoice.send()
        send_end = _dt.now()

        self.assertLess(send_start, invoice.invoiced_dt)
        self.assertGreater(send_end, invoice.invoiced_dt)

        for entry in invoice.entries:
            self.assertFalse(entry.can_be_invoiced())
            self.assertEqual(entry.invoiced_dt, invoice.invoiced_dt)

        self.assertTrue(invoice.sent)
Exemplo n.º 7
0
    def testOpenEntry(self):
        entry = TimeEntry(1, _dt(2010, 1, 1), '1st entry', 'Company1', 'job1')
        entry_path = io_txt.get_entry_path(entry)
        io_txt.write_entry(entry)
        read_entry = io_txt.open_entry(entry_path)
        self.assertEqual(read_entry.id, entry.id)

        del_path(entry_path)
Exemplo n.º 8
0
    def testCreateTimeEntry(self):
        entry = TimeEntry(1, _dt(2010,1,1), '1st entry', 'Company1', 'job1')

        self.assertEqual(entry.hours, 1.0)
        self.assertEqual(entry.dt, _dt(2010,1,1))
        self.assertEqual(entry.message, '1st entry')
        self.assertEqual(entry.company, 'Company1')
        self.assertEqual(entry.job, 'job1')
Exemplo n.º 9
0
    def testWriteReport(self):
        self.invoice.send()

        report_path = io_txt.get_report_path(self.invoice)
        io_txt.write_report(self.invoice)

        with open(report_path, 'r') as f:
            written_txt = f.read()
            _entries = self.invoice.entries
            self.assertIn(_entries[0].message, written_txt)
            self.assertIn(str(TimeEntry.get_hours_total(_entries)),
                          written_txt)

        del_path(report_path)
Exemplo n.º 10
0
    def testIdCollisions(self):
        """Using something other than self(id), right now uuid1().

           I was using self.id = id(self) for ID, which would make for
           a collison in about 10 iterations of the following loop.
           Noticed this problem as an intermittent
           already-exists-error in:

             test_io:TestGenInvoice.testRealRun()

        """
        ids = []
        for i in range(100):
            invoice = Invoice(
            [
                TimeEntry(1, _dt(2010,1,1), '1st entry', 'Company1', 'job1'),
                TimeEntry(2.5, _dt(2010,1,2), '2nd entry', 'Company1', 'job1')
            ],
            _dt(2010,1,14),
            (_dt(2010,1,1), _dt(2010,1,13)),
            CompanyJobs('Company1', {'job1': 'Job One'}, 20)
            )
            self.assertNotIn(invoice.id, ids)
            ids.append(invoice.id)
Exemplo n.º 11
0
    def testFilterEntriesByDate(self):
        e1 = TimeEntry(1, _dt(2010,1,1), '1st entry', 'Company1', 'job1')
        e2 = TimeEntry(1, _dt(2010,1,2), '2nd entry', 'Company1', 'job1')
        e3 = TimeEntry(1, _dt(2010,1,3), '3rd entry', 'Company1', 'job1')

        self.assertEqual(
            TimeEntry.filter_by_date([e1], _dt(2010,1,1), _dt(2010,1,1)),
            [e1]
            )

        self.assertEqual(
            TimeEntry.filter_by_date([e1, e2, e3], _dt(2010,1,1), _dt(2010,1,1)),
            [e1]
            )

        # With date range in February, all January entries are filtered out
        self.assertEqual(
            TimeEntry.filter_by_date([e1, e2, e3], _dt(2010,2,1), _dt(2010,2,3)),
            []
            )
Exemplo n.º 12
0
def parse_entries_from_note(note_data, jobs):
    from time_entry import TimeEntry

    def _assert_field_count(row, field_count):
        assert len(row) == field_count, \
            'Expected %s field(s) in row, got %d: %s' % (field_count, len(row), row)

    def cast_date(s):
        if not s:
            return None

        mo, day, yr = map(int, s.split('/'))
        return datetime.datetime(2000 + yr, mo, day)

    def cast_float(s):
        if not s:
            return None
        return float(s)

    def cast_int(s):
        if not s:
            return None
        return int(s)

    def _unicode(s):
        if not s:
            return None

        return unicode(s, 'utf-8')

    def _job_id(s):
        if not s:
            return None

        id_or_name = _unicode(s)

        if jobs.get_name_by_id(id_or_name):
            return id_or_name

        job_id = jobs.get_id_by_name(id_or_name)
        if job_id:
            return job_id

        return None

    import csv
    import datetime

    if not note_data.read().strip():
        raise ValueError('no data in note_data')
    note_data.seek(0)

    note_data = replace_in_file(note_data)

    reader = csv.reader(note_data, delimiter=',', quotechar='"')
    entries = []
    for row in reader:
        if not row:
            continue

        _assert_field_count(row, 5)

        entries.append(
            TimeEntry(cast_float(row[0]), cast_date(row[1]), _unicode(row[2]),
                      _unicode(row[3]), _job_id(row[4])))

    return entries