Revision f243d667 snf-astakos-app/astakos/im/models.py
b/snf-astakos-app/astakos/im/models.py | ||
---|---|---|
1316 | 1316 |
|
1317 | 1317 |
|
1318 | 1318 |
class ProjectApplicationManager(ForUpdateManager): |
1319 |
|
|
1320 |
def user_visible_projects(self, *filters, **kw_filters): |
|
1321 |
model = self.model |
|
1322 |
return self.filter(model.Q_PENDING | model.Q_APPROVED) |
|
1323 |
|
|
1324 |
def user_visible_by_chain(self, flt): |
|
1325 |
model = self.model |
|
1326 |
pending = self.filter( |
|
1327 |
model.Q_PENDING | model.Q_DENIED).values_list('chain') |
|
1328 |
approved = self.filter(model.Q_APPROVED).values_list('chain') |
|
1329 |
by_chain = dict(pending.annotate(models.Max('id'))) |
|
1330 |
by_chain.update(approved.annotate(models.Max('id'))) |
|
1331 |
return self.filter(flt, id__in=by_chain.values()) |
|
1332 |
|
|
1333 |
def user_accessible_projects(self, user): |
|
1334 |
""" |
|
1335 |
Return projects accessed by specified user. |
|
1336 |
""" |
|
1337 |
if user.is_project_admin(): |
|
1338 |
participates_filters = Q() |
|
1339 |
else: |
|
1340 |
participates_filters = Q(owner=user) | Q(applicant=user) | \ |
|
1341 |
Q(project__projectmembership__person=user) |
|
1342 |
|
|
1343 |
return self.user_visible_by_chain( |
|
1344 |
participates_filters).order_by('issue_date').distinct() |
|
1345 |
|
|
1346 |
def search_by_name(self, *search_strings): |
|
1347 |
q = Q() |
|
1348 |
for s in search_strings: |
|
1349 |
q = q | Q(name__icontains=s) |
|
1350 |
return self.filter(q) |
|
1351 |
|
|
1352 |
def latest_of_chain(self, chain_id): |
|
1353 |
try: |
|
1354 |
return self.filter(chain=chain_id).order_by('-id')[0] |
|
1355 |
except IndexError: |
|
1356 |
return None |
|
1319 |
pass |
|
1357 | 1320 |
|
1358 | 1321 |
|
1359 | 1322 |
class ProjectApplication(models.Model): |
... | ... | |
1428 | 1391 |
def state_display(self): |
1429 | 1392 |
return self.APPLICATION_STATE_DISPLAY.get(self.state, _('Unknown')) |
1430 | 1393 |
|
1431 |
def project_state_display(self): |
|
1432 |
try: |
|
1433 |
project = self.project |
|
1434 |
return project.state_display() |
|
1435 |
except Project.DoesNotExist: |
|
1436 |
return self.state_display() |
|
1437 |
|
|
1438 | 1394 |
def add_resource_policy(self, resource, uplimit): |
1439 | 1395 |
"""Raises ObjectDoesNotExist, IntegrityError""" |
1440 | 1396 |
q = self.projectresourcegrant_set |
1441 | 1397 |
resource = Resource.objects.get(name=resource) |
1442 | 1398 |
q.create(resource=resource, member_capacity=uplimit) |
1443 | 1399 |
|
1444 |
def members_count(self): |
|
1445 |
return self.project.approved_memberships.count() |
|
1446 |
|
|
1447 | 1400 |
@property |
1448 | 1401 |
def grants(self): |
1449 | 1402 |
return self.projectresourcegrant_set.values('member_capacity', |
... | ... | |
1457 | 1410 |
for resource, uplimit in policies: |
1458 | 1411 |
self.add_resource_policy(resource, uplimit) |
1459 | 1412 |
|
1460 |
def pending_modifications_incl_me(self): |
|
1461 |
q = self.chained_applications() |
|
1462 |
q = q.filter(Q(state=self.PENDING)) |
|
1463 |
return q |
|
1464 |
|
|
1465 |
def last_pending_incl_me(self): |
|
1466 |
try: |
|
1467 |
return self.pending_modifications_incl_me().order_by('-id')[0] |
|
1468 |
except IndexError: |
|
1469 |
return None |
|
1470 |
|
|
1471 |
def pending_modifications(self): |
|
1472 |
return self.pending_modifications_incl_me().filter(~Q(id=self.id)) |
|
1473 |
|
|
1474 |
def last_pending(self): |
|
1475 |
try: |
|
1476 |
return self.pending_modifications().order_by('-id')[0] |
|
1477 |
except IndexError: |
|
1478 |
return None |
|
1479 |
|
|
1480 | 1413 |
def is_modification(self): |
1481 | 1414 |
# if self.state != self.PENDING: |
1482 | 1415 |
# return False |
... | ... | |
1487 | 1420 |
def chained_applications(self): |
1488 | 1421 |
return ProjectApplication.objects.filter(chain=self.chain) |
1489 | 1422 |
|
1490 |
def is_latest(self): |
|
1491 |
return self.chained_applications().order_by('-id')[0] == self |
|
1492 |
|
|
1493 |
def has_pending_modifications(self): |
|
1494 |
return bool(self.last_pending()) |
|
1495 |
|
|
1496 | 1423 |
def denied_modifications(self): |
1497 | 1424 |
q = self.chained_applications() |
1498 | 1425 |
q = q.filter(Q(state=self.DENIED)) |
... | ... | |
1508 | 1435 |
def has_denied_modifications(self): |
1509 | 1436 |
return bool(self.last_denied()) |
1510 | 1437 |
|
1511 |
def is_applied(self): |
|
1512 |
try: |
|
1513 |
self.project |
|
1514 |
return True |
|
1515 |
except Project.DoesNotExist: |
|
1516 |
return False |
|
1517 |
|
|
1518 | 1438 |
def can_cancel(self): |
1519 | 1439 |
return self.state == self.PENDING |
1520 | 1440 |
|
... | ... | |
1670 | 1590 |
Q(application__end_date__lt=datetime.now())) |
1671 | 1591 |
return self.filter(q) |
1672 | 1592 |
|
1593 |
def user_accessible_projects(self, user): |
|
1594 |
""" |
|
1595 |
Return projects accessible by specified user. |
|
1596 |
""" |
|
1597 |
model = self.model |
|
1598 |
if user.is_project_admin(): |
|
1599 |
flt = Q() |
|
1600 |
else: |
|
1601 |
membs = user.projectmembership_set.associated() |
|
1602 |
memb_projects = membs.values_list("project", flat=True) |
|
1603 |
flt = (Q(application__owner=user) | |
|
1604 |
Q(application__applicant=user) | |
|
1605 |
Q(id__in=memb_projects)) |
|
1606 |
|
|
1607 |
relevant = model.o_states_q(model.RELEVANT_STATES) |
|
1608 |
return self.filter(flt, relevant).order_by( |
|
1609 |
'application__issue_date').select_related( |
|
1610 |
'application', 'application__owner', 'application__applicant') |
|
1611 |
|
|
1612 |
def search_by_name(self, *search_strings): |
|
1613 |
q = Q() |
|
1614 |
for s in search_strings: |
|
1615 |
q = q | Q(name__icontains=s) |
|
1616 |
return self.filter(q) |
|
1617 |
|
|
1673 | 1618 |
|
1674 | 1619 |
class Project(models.Model): |
1675 | 1620 |
|
... | ... | |
1747 | 1692 |
p_state, a_state = cls.OVERALL_STATE_INV[o_state] |
1748 | 1693 |
return Q(state=p_state, application__state=a_state) |
1749 | 1694 |
|
1695 |
@classmethod |
|
1696 |
def o_states_q(cls, o_states): |
|
1697 |
return reduce(lambda x, y: x | y, map(cls.o_state_q, o_states), Q()) |
|
1698 |
|
|
1750 | 1699 |
INITIALIZED_STATES = [O_ACTIVE, |
1751 | 1700 |
O_SUSPENDED, |
1752 | 1701 |
O_TERMINATED, |
... | ... | |
1778 | 1727 |
return apps[0] |
1779 | 1728 |
return None |
1780 | 1729 |
|
1730 |
def last_pending_modification(self): |
|
1731 |
last_pending = self.last_pending_application() |
|
1732 |
if last_pending == self.application: |
|
1733 |
return None |
|
1734 |
return last_pending |
|
1735 |
|
|
1736 |
def has_pending_modifications(self): |
|
1737 |
last_pending = self.last_pending_modification() |
|
1738 |
return last_pending is not None |
|
1739 |
|
|
1781 | 1740 |
def state_display(self): |
1782 | 1741 |
return self.O_STATE_DISPLAY.get(self.overall_state(), _('Unknown')) |
1783 | 1742 |
|
... | ... | |
1880 | 1839 |
def suspended(self): |
1881 | 1840 |
return self.filter(state=ProjectMembership.USER_SUSPENDED) |
1882 | 1841 |
|
1842 |
def associated(self): |
|
1843 |
return self.filter(state__in=ProjectMembership.ASSOCIATED_STATES) |
|
1844 |
|
|
1883 | 1845 |
|
1884 | 1846 |
class ProjectMembership(models.Model): |
1885 | 1847 |
|
Also available in: Unified diff