Blame view

app/db_mgr.py 8.3 KB
432b6596   hitier   Sql sum is 0 if None
1
from app.models import db, Period
1aeda847   hitier   Two db request wr...
2

0a8a3ec6   hitier   Convert charge fr...
3
4
5
6
7
8
9
# TODO: make this configurable, and choose another place to use it,
#       in 'routes.py' maybe
# Charge as stored on a 100% basis, percent of total worked time;
# Here it is possible to convert to an ETP basis, dividing by 100
# or we set it to '1' if we want to keep the percent basis
charge_unit = 100

1aeda847   hitier   Two db request wr...
10

f8e1465a   hitier   New projects list...
11
12
def projects():
    """
8ffdad81   hitier   Show current peri...
13
    Build the list of all agents, with their charges for the current period
f8e1465a   hitier   New projects list...
14
15
    :return:
    """
8ffdad81   hitier   Show current peri...
16
    current_period_id = get_current_period()
f8e1465a   hitier   New projects list...
17
    sql_txt = """
432b6596   hitier   Sql sum is 0 if None
18
            select p.id, p.name, IFNULL(sum(tc.charge_rate), 0) as total_charge
f8e1465a   hitier   New projects list...
19
            from project as p left join
8ffdad81   hitier   Show current peri...
20
               ( select c.project_id, c.charge_rate from charge c where c.period_id = {})
f8e1465a   hitier   New projects list...
21
22
23
24
            tc
            on p.id = tc.project_id
            group by p.id
            order by total_charge desc;
8ffdad81   hitier   Show current peri...
25
            """.format(current_period_id)
f8e1465a   hitier   New projects list...
26
27
28
    all_projects = db.session.execute(sql_txt).fetchall()
    return all_projects

0d6506cb   hitier   New project_charg...
29

1aeda847   hitier   Two db request wr...
30
def agents():
64515ad9   hitier   New agent charges...
31
    """
8ffdad81   hitier   Show current peri...
32
    Build the list of all agents, with their charges for the current period
64515ad9   hitier   New agent charges...
33
34
    :return:
    """
8ffdad81   hitier   Show current peri...
35
    current_period_id = get_current_period()
e5449e3e   hitier   Fix wrong agents ...
36
    sql_txt = """
432b6596   hitier   Sql sum is 0 if None
37
            select a.id, a.firstname, a.secondname, IFNULL (sum(tc.charge_rate), 0) as total_charge
e5449e3e   hitier   Fix wrong agents ...
38
            from agent as a left join
8ffdad81   hitier   Show current peri...
39
               ( select c.agent_id, c.charge_rate from charge c where c.period_id = {})
e5449e3e   hitier   Fix wrong agents ...
40
41
42
43
            tc
            on a.id = tc.agent_id
            group by a.id
            order by total_charge desc;
8ffdad81   hitier   Show current peri...
44
            """.format(current_period_id)
2cb0a345   hitier   Add 2 columns in ...
45
46
    all_agents = db.session.execute(sql_txt).fetchall()

1aeda847   hitier   Two db request wr...
47
48
49
    return all_agents


0d6506cb   hitier   New project_charg...
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def charges_by_project(project_id):
    """
    Build the flatten list of charges for one project, period by period
    :param project_id:
    :return:
    """

    req_sql = f"""
            select p.name as period_name,
                   a.firstname ||" "|| a.secondname as agent_name,
                   s.name as service_name,
                   c2.name as capacity_name,
                   c.charge_rate as charge_rate
            from charge as c
                     join period p on c.period_id = p.id
                     join project p2 on c.project_id = p2.id
                     join service s on c.service_id = s.id
                     join agent a on a.id = c.agent_id
                     join capacity c2 on c2.id = c.capacity_id
            where project_id = {project_id}
            order by c.period_id
            """
0d6506cb   hitier   New project_charg...
72
73
74
75
76
77
78
    req_res = db.session.execute(req_sql)
    results = list(req_res)
    # Remove comma
    nocomma_results = []
    for line in results:
        nocomma_line = [str(cell) for cell in line]
        nocomma_results.append(nocomma_line)
b9d90810   hitier   Tweak charges tab...
79
    headers = ["Periode", "Agent", "Service", "Fonction", "Charge"]
0d6506cb   hitier   New project_charg...
80
81
82
83
    nocomma_results.insert(0, headers)
    return nocomma_results


90b18951   hitier   New db method: ch...
84
85
86
87
88
89
90
def charges_by_project_stacked(project_id, category="service"):
    """
    Build the list of charges for one project, period by period
    :param project_id: the project's id we want to return data for
    :param category: what dict to build for each period, 'service' or 'capacity' ?
    :return: a 2 dim table with header as first line and datas next, of the form
            period, category_0, category_1, ....., category_n,
9705f04b   hitier   Fix project charg...
91
92
            per_0, value_00, value_01, ....., value_0n,
            per_1, value_10, value_11, ....., value_1n,
90b18951   hitier   New db method: ch...
93
94
                .
                .
9705f04b   hitier   Fix project charg...
95
            per_n, value_n0, value_n1, ....., value_nn,
0a8a3ec6   hitier   Convert charge fr...
96
97

    TODO: common with charges_by_agent_stacked(agent_id): code to extrat
90b18951   hitier   New db method: ch...
98
    """
cf88ff52   hitier   Fix head data sel...
99
    if category == 'capacity':
40302c4f   hitier   Fix category tabl...
100
        category_table = 'capacity'
90b18951   hitier   New db method: ch...
101
        sql_req = """
9705f04b   hitier   Fix project charg...
102
        select sum(c.charge_rate)
90b18951   hitier   New db method: ch...
103
104
        from capacity c1 left join
            charge c on c1.id = c.capacity_id and project_id = {} and period_id={}
9705f04b   hitier   Fix project charg...
105
            group by c1.id
90b18951   hitier   New db method: ch...
106
107
        order by c1.id
        """
cf88ff52   hitier   Fix head data sel...
108
    elif category == 'service':
40302c4f   hitier   Fix category tabl...
109
        category_table = 'service'
90b18951   hitier   New db method: ch...
110
        sql_req = """
9705f04b   hitier   Fix project charg...
111
        select sum(c.charge_rate)
90b18951   hitier   New db method: ch...
112
113
        from service s left join
            charge c on s.id = c.service_id and project_id = {} and period_id={}
9705f04b   hitier   Fix project charg...
114
            group by s.id
90b18951   hitier   New db method: ch...
115
116
117
118
        order by s.id
        """
    else:
        raise ValueError("Waiting for 'service' or 'capacity'")
40302c4f   hitier   Fix category tabl...
119
    categories_req = "select name from {} order by id".format(category_table)
90b18951   hitier   New db method: ch...
120
    categories = [c for (c,) in db.session.execute(categories_req)]
b48d8e69   hitier   Changed charges_b...
121
    headers = ['period'] + categories
90b18951   hitier   New db method: ch...
122
123
124
125
126
127
128
    all_charges = [headers]
    for (period_id, period_name) in db.session.execute("select id, name from period order by id"):
        # build the request from the string previously set
        charge_by_categorie_req = sql_req.format(project_id, period_id)
        # build the charges line for the current period
        category_charges = [period_name]
        for (category_rate,) in db.session.execute(charge_by_categorie_req):
0a8a3ec6   hitier   Convert charge fr...
129
            category_rate = str(round(category_rate / charge_unit, 2)) if category_rate else '0'
90b18951   hitier   New db method: ch...
130
131
132
133
134
135
            category_charges.append(category_rate)
        all_charges.append(category_charges)

    return all_charges


b48d8e69   hitier   Changed charges_b...
136
137
138
def charges_by_agent_stacked(agent_id):
    """
    Build the list of charges for all projects of one agent, period by period
0a8a3ec6   hitier   Convert charge fr...
139
    TODO: common with charges_by_project_stacked(project_id, ..) code to extrat
b48d8e69   hitier   Changed charges_b...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
    :param agent_id:
    :return:
    """
    categories_req = "select name from project order by id"
    categories = [c for (c,) in db.session.execute(categories_req)]
    headers = ['period'] + categories
    all_charges = [headers]
    for (period_id, period_name) in db.session.execute("select id, name from period order by id"):
        charge_by_project_req = """
                               select sum(c.charge_rate)
                                from project p
                                         left join
                                     charge c on p.id = c.project_id and agent_id = {} and period_id = {}
                                group by p.id
                                order by p.id 
                            """.format(agent_id, period_id)
b48d8e69   hitier   Changed charges_b...
156
157
        category_charges = [period_name]
        for (category_rate,) in db.session.execute(charge_by_project_req):
0a8a3ec6   hitier   Convert charge fr...
158
            category_rate = str(round(category_rate / charge_unit, 2)) if category_rate else '0'
b48d8e69   hitier   Changed charges_b...
159
160
161
162
163
            category_charges.append(category_rate)
        all_charges.append(category_charges)
    return all_charges


64515ad9   hitier   New agent charges...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
def charges_by_agent_tabled(agent_id):
    """
    Build the flatten list of charges for one agent, period by period
    :param agent_id:
    :return:
    """
    req_sql = f"""
            select p.name as period_name,
                   p2.name as project_name,
                   s.name as service_name,
                   c2.name as capacity_name,
                   c.charge_rate as charge_rate
            from charge as c
                     join period p on c.period_id = p.id
                     join project p2 on c.project_id = p2.id
                     join service s on c.service_id = s.id
                     join agent a on a.id = c.agent_id
                     join capacity c2 on c2.id = c.capacity_id
            where agent_id = {agent_id}
            order by c.period_id
            """
    req_res = db.session.execute(req_sql)
    results = list(req_res)
    # Remove comma
    nocomma_results = []
    for line in results:
70da5dd5   hitier   Insert charges ta...
190
        nocomma_line = [str(cell) for cell in line]
64515ad9   hitier   New agent charges...
191
        nocomma_results.append(nocomma_line)
b9d90810   hitier   Tweak charges tab...
192
    headers = ["Periode", "Projet", "Service", "Fonction", "Charge"]
64515ad9   hitier   New agent charges...
193
194
195
196
    nocomma_results.insert(0, headers)
    return nocomma_results


1aeda847   hitier   Two db request wr...
197
def charges_by_agent(agent_id):
8b3ab81d   hitier   All charges now i...
198
199
    periods = db.session.execute("select name from period")
    sql_txt = "select p.name, sum(charge_rate)  from charge inner join period p on charge.period_id = p.id\
71b91c22   hitier   New json route fo...
200
201
                where agent_id={} group by period_id order by p.name" \
        .format(agent_id)
1aeda847   hitier   Two db request wr...
202
    request = db.session.execute(sql_txt)
8b3ab81d   hitier   All charges now i...
203
204
205
206
207
208
209
210
    all_charges = []
    charges_list = [(period, charge) for (period, charge) in request.fetchall()]
    charges_dict = dict(charges_list)
    for (p,) in periods:
        if p in charges_dict.keys():
            all_charges.append([p, charges_dict[p]])
        else:
            all_charges.append([p, 0])
71b91c22   hitier   New json route fo...
211
    return all_charges
aec65e04   hitier   New cli command g...
212
213
214
215
216
217
218


def get_current_period():
    """
    :return:  the id of the period of current day
    """
    # TODO: request on dates as soon as periods are dated
083ac872   hitier   Return period id ...
219
220
    p = Period.query.filter((Period.name == '2021') | (Period.name == '2021_S1')).one()
    return p.id