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