~dricottone/fmg-timesheets

ref: 7326d28027df088781be5bf0cb673109a1cc0d13 fmg-timesheets/parser/timeentry.py -rw-r--r-- 2.9 KiB
7326d280Dominic Ricottone Started implementing time entry extraction. 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/usr/bin/env python3

from re import compile as re_compile

ENTRY_PATTERNS = (
    re_compile("[1-9][0-9]?"),
    re_compile("(ST|VAC|HOL)"),
    re_compile("(OHORG\.(MTG|ONB)\.0[0-5]\.00[0-5]|UNALW\.EMW\.0[0-5]\.00[0-5]|[0-9]{5}\.[0-9]{3}\.[0-9]{2}\.[0-9]{3})"),
    re_compile("[0-9]{3,5}"),
    re_compile("."),
    re_compile("Notes"),
    re_compile("[ADFJMNOS][aceopu][bcglnprtvy] [1-9][0-9]?, 20[12][89012]"),
    re_compile("- [ADFJMNOS][aceopu][bcglnprtvy] [1-9][0-9]?, 20[12][89012]"),
    re_compile("."),
)

class TimeEntry(object):
    def __init__(self, semistructured_data, timesheet_name, entry_number):
        self._issues = []
        self._timesheet = timesheet_name
        self._entry = entry_number
        self._data = self.beat_data_with_a_stick(semistructured_data)
        self.assert_entry()

    def __str__(self):
        return f"entry #{self._entry} in the timesheet for {self._timesheet}"

    def __len__(self):
        return len(self._data)

    def report_issues(self):
        if self._issues:
            print(f"There are some issues in {self}...")
            for issue in self._issues:
                print(issue)
            for index, line in enumerate(self._data):
                print(index, line)

    def log_issue(self, *parts):
        self._issues.append(''.join(parts))

    def beat_data_with_a_stick(self, data):
        # Project and TimeType fields can get merged
        if " " in data[2][0]:
            project_timetype = data[2][0].split(" ", 1)
            shared = [n for n in data[2][1:]]
            split = [
                (project_timetype[0], *shared, ),
                (project_timetype[1], *shared, ),
            ]
            data = data[:2] + split + data[3:]

        # Holiday and Vacation time entries skip the Project and TimeType fields
        if data[1][0] in ("HOL", "VAC", ):
            data = data[0:1] + [("", 0, ), ("", 0, )] + data[1:]

        return data

    def assert_entry_item(self, index, should_be_at):
        if not ENTRY_PATTERNS[index].match(self._data[index][0]):
            self.log_issue(
                "assert_entry: ",
                f"item {index} does not look right ",
                f"({self._data[index][0]})",
            )
        if self._data[index][1] != should_be_at:
            self.log_issue(
                "assert_entry: ",
                f"item {index} is not at {should_be_at}px left ",
                f"(is at {self._data[index][1]}px)",
            )

    def assert_entry(self):
        self.assert_entry_item(1, 40)
        self.assert_entry_item(2, 120)
        self.assert_entry_item(3, 201)
        print(self._data)
        self.assert_entry_item(4, 39)
        if len(self)>5 and self._data[5] == "Notes":
            self.assert_entry_item(5, 40)
            self.assert_entry_item(6, 40)
            self.assert_entry_item(7, 99)
            self.assert_entry_item(8, 220)