models
main.models
¤
Models module for main app.
Classes¤
AnalysisCode
¤
Capacity
¤
Bases: Model
Proportion of working time that team members are able to work on projects.
Classes¤
Meta
¤
Meta class for the model.
Methods:¤
__str__()
¤
String representation of the Capacity object.
Source code in main/models.py
910 911 912 | |
DailyRate
¤
Bases: Model
Historical record of the standard daily rate used for funding.
Rather than storing a single mutable value, each change to the standard rate is recorded as a new entry, effective from a given date. This keeps an audit trail of how the standard rate has changed over time, and lets a new rate be scheduled ahead of its effective date if needed.
This only supplies the default value proposed when a new Funding
record is created (see get_current_daily_rate). Each Funding.daily_rate
remains independently editable, so funding sources that use a bespoke rate
(different from the standard one at that point in time) can simply have
their rate set accordingly, and it won't be affected by later additions
here.
Department
¤
Bases: Model
Model to manage the departments.
You can find the faculties and potential departments in:
https://www.imperial.ac.uk/faculties-and-departments/
FullTimeEquivalent
¤
Bases: Model
Full-time-equivalent model for user and projects.
Attributes¤
days
property
¤
Convert FTE to days using the working days in a year in the settings.
Classes¤
Meta
¤
Model metadata.
Methods:¤
clean()
¤
Ensure start date comes before end date and that value 0 or positive.
Source code in main/models.py
1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 | |
from_days(days, start_date, end_date, **kwargs)
classmethod
¤
Creates an FTE object given a number of days time period.
Source code in main/models.py
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 | |
trace(timerange=None)
¤
Convert the FTE to a dataframe.
If timerange is provided, those dates are used, otherwise a datetime index is created using the start and end dates of the FTE object.
Source code in main/models.py
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 | |
Funding
¤
Bases: Model
Funding associated with a project.
Attributes¤
effort
property
¤
Provide the effort in days, calculated based on the budget and daily rate.
Returns:
| Type | Description |
|---|---|
float
|
The total number of days of effort provided by the funding. |
effort_left
property
¤
Provide the effort left in days.
Returns:
| Type | Description |
|---|---|
float
|
The number of days worth of effort left. |
funding_left
property
¤
Provide the funding left in currency.
Funding left is calculated based on 'Confirmed' monthly charges.
Returns:
| Type | Description |
|---|---|
float
|
The amount of funding left. |
project_code
property
¤
Provide the project code, containing the cost centre and activity code.
Returns:
| Type | Description |
|---|---|
str
|
The designated project code. |
Classes¤
Meta
¤
Meta class for the model.
Methods:¤
__str__()
¤
String representation of the Funding object.
Source code in main/models.py
746 747 748 | |
clean()
¤
Ensure that the activity code has a valid value.
Source code in main/models.py
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 | |
is_complete()
¤
Checks if funding record is complete.
This is only relevant to funding where source is external.
Source code in main/models.py
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 | |
monthly_pro_rata_charge(date)
¤
Calculate the charge per month if the project has Pro-rata charging.
Calculates the number of months between project start and end date regardless of the day of the month so the monthly charge will be the same regardless of the number of days in the month.
The last month of the project is not charged, so the charge applies from the month of the start date until the month before the end date, to ensure that no charges are made outside of the project period. For example, if a project starts on 15th January and ends on 10th April, the charge will apply for January, February and March, but not April.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
date
|
date
|
The date for which to calculate the monthly charge, used to check if the project has started and hasn't ended yet. |
required |
Returns:
| Type | Description |
|---|---|
float | None
|
The monthly charge amount, or None if the project doesn't have Pro-rata |
float | None
|
charging or the date is outside the project period. |
Source code in main/models.py
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 | |
MonthlyCharge
¤
Bases: Model
Monthly charge for a specific project, account and analysis code.
Methods:¤
__str__()
¤
String representation of the MonthlyCharge object.
Source code in main/models.py
972 973 974 | |
clean()
¤
Ensure the charge has valid funding attached and description if Manual.
Source code in main/models.py
976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 | |
Project
¤
Bases: Warning, Model
Software project details.
Attributes¤
days_left
property
¤
Provide the days worth of effort left.
Returns:
| Type | Description |
|---|---|
tuple[float, float] | None
|
The number of days and percentage worth of effort left, or None if there is |
tuple[float, float] | None
|
no funding information. |
percent_effort_left
property
¤
Provide the percentage of effort left.
Returns:
| Type | Description |
|---|---|
float | None
|
The percentage of effort left, or None if there is no funding information. |
total_effort
property
¤
Provide the total days worth of effort available.
For projects in Maintenance status, the total effort is the one associated to
the maintenance phase. For projects in Active status, the total effort is the
sum of the days associated to all non-maintenance phases (this deliberately
excludes a maintenance phase that may already have been set up in
preparation for a future transition to Maintenance status). If an Active
project has no phases defined yet, funding is used instead: this preserves the
prior behaviour for projects that don't use the phases feature, and avoids a
circular dependency when creating the very first phase for a project (since
total_effort may be used to seed the initial phase created for a project).
For all other statuses, the total effort is derived from the funding sources,
as before.
Returns:
| Type | Description |
|---|---|
float | None
|
The total number of days effort, or None if there is no relevant |
float | None
|
information (funding or phases, depending on status) to derive it from. |
total_funding_left
property
¤
Provide the total funding left after deducting confirmed charges.
In maintenance mode or if the project is finished, this is not relevant, despite having a funding source. For all other statuses, if there's funding information, it should be calculated out of it.
Returns:
| Type | Description |
|---|---|
float | None
|
The total monetary amount of funding left, or none if there is no funding |
float | None
|
information. |
total_working_days
property
¤
Provide the total number of working days given the funding.
Returns:
| Type | Description |
|---|---|
float | None
|
Number of working days given the funding available. |
weeks_to_deadline
property
¤
Provide the number of weeks left until project deadline.
Only relevant for projects in Active, Confirmed, and Maintenance statuses.
Returns:
| Type | Description |
|---|---|
tuple[float, float] | None
|
The number of weeks left or None if the project is Tentative or Not done. |
Methods:¤
__str__()
¤
String representation of the Project object.
Source code in main/models.py
209 210 211 | |
check_and_notify_status()
¤
Check the project status and notify accordingly.
Source code in main/models.py
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | |
clean()
¤
Ensure all fields have a value unless status is 'Tentative' or 'Not done'.
It also checks that, if present, the end date is after the start date. In addition, a project that was not yet 'Active' or 'Maintenance', but wants to, cannot have warnings; the project must start clean
Source code in main/models.py
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | |
fte(timerange=None)
¤
Calculate the FTE trace for the project over a given timerange.
This is calculated by summing the trace of all the phases of the project, which are assumed to be sequential and non-overlapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timerange
|
DatetimeIndex | None
|
The timerange to calculate the FTE trace over. |
None
|
Returns:
| Type | Description |
|---|---|
Series
|
A pandas Series with the FTE trace over the timerange, or a trace of 0 if |
Series
|
there are no phases. |
Source code in main/models.py
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | |
maintenance_phase()
¤
Provide the phase flagged as the maintenance phase of the project, if any.
This is not restricted to projects currently in Maintenance status: an Active project may already have a phase flagged in preparation for a future transition to Maintenance.
Returns:
| Type | Description |
|---|---|
ProjectPhase | None
|
The maintenance phase, or None if there is no maintenance phase. |
Source code in main/models.py
451 452 453 454 455 456 457 458 459 460 461 | |
ProjectPhase
¤
Bases: FullTimeEquivalent
Phases associated with a project.
Attributes¤
expected_days_left
property
¤
Expected number of days left in the phase.
If the days were to be used homogeneously over the phase length, this function calculates how many days of effort are left from today. In phases that have not started (today < start date), the days left will be the total number of days, and phases that are gone (today > end date) the total number of days will be zero.
Methods:¤
__str__()
¤
String representation of the ProjectPhase object.
Source code in main/models.py
1168 1169 1170 | |
check_only_one_maintenance_phase(siblings=None)
¤
Ensure only one maintenance phase exists for the project.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
siblings
|
Iterable[ProjectPhase] | None
|
See |
None
|
Source code in main/models.py
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 | |
check_overlapping_phases(siblings=None)
¤
Check the phase doesn't overlap with another phase (by 1 day).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
siblings
|
Iterable[ProjectPhase] | None
|
The other phases of the same project to check against. If
not given (the default), the project's other phases are fetched
from the database, which is the correct behaviour when
validating a single phase on its own (e.g. from the admin, the
API, or a direct |
None
|
Source code in main/models.py
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 | |
check_phase_alignment(siblings=None)
¤
Ensures phases are aligned but separated by 1 day.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
siblings
|
Iterable[ProjectPhase] | None
|
See |
None
|
Source code in main/models.py
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 | |
check_phase_in_project()
¤
Ensure the start phase dates are within the project dates.
Source code in main/models.py
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 | |
clean()
¤
Ensures that phase dates are sensible.
Ensures start is before the end date (from FTE clean). Ensures phase within project period. Ensures the phase isn't covered by any other phases. Ensures at least phase start or end date aligns with other phases or project dates.
The sibling-dependent checks (overlap, alignment, single maintenance
phase) are skipped here if _validated_by_formset has been set on this
instance: in that case, ProjectPhaseInlineFormSet.clean() (see
forms.py) performs them itself, once, against the complete in-memory
set of phases being submitted together, rather than one at a time
against the database.
Source code in main/models.py
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 | |
save(**kwargs)
¤
Saves the object to the database.
This overwrites models.Model.save() to keep the days constant if the start or
end date changes, modifying the FTE value. Except if value has also changed in
the same modification.
Source code in main/models.py
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 | |
TimeEntry
¤
Bases: Model
Time entry for a user.
User
¤
Functions:¤
get_current_daily_rate()
¤
Provide the currently applicable standard daily rate.
Used as the default value for new Funding records. Existing records are
unaffected by later changes to the standard rate, since daily_rate is
stored on each Funding individually rather than looked up live.
Returns:
| Type | Description |
|---|---|
float
|
The rate of the most recent |
float
|
in the future, or |
Source code in main/models.py
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 | |