Revision 123be68a snf-astakos-app/astakos/im/models.py

b/snf-astakos-app/astakos/im/models.py
1392 1392
        unique_together = ("resource", "project_application")
1393 1393

  
1394 1394

  
1395
class ProjectManager(ForUpdateManager):
1396

  
1397
    def deactivating_projects(self):
1398
        return self.filter(state__gt=Project.ACTIVE)
1399

  
1400
    def _q_terminated(self):
1401
        return Q(state=Project.TERMINATED) | Q(state=Project.TERMINATING)
1402

  
1403
    def terminated_projects(self):
1404
        q = self._q_terminated()
1405
        return self.filter(q)
1406

  
1407
    def not_terminated_projects(self):
1408
        q = ~self._q_terminated()
1409
        return self.filter(q)
1410

  
1395 1411
class Project(models.Model):
1396 1412

  
1397 1413
    application                 =   models.OneToOneField(
......
1404 1420
                                            through='ProjectMembership')
1405 1421

  
1406 1422
    deactivation_reason         =   models.CharField(max_length=255, null=True)
1407
    deactivation_start_date     =   models.DateTimeField(null=True)
1408 1423
    deactivation_date           =   models.DateTimeField(null=True)
1409 1424

  
1410 1425
    creation_date               =   models.DateTimeField()
......
1413 1428
                                            db_index=True,
1414 1429
                                            unique=True)
1415 1430

  
1416
    TERMINATED  =   'TERMINATED'
1417
    SUSPENDED   =   'SUSPENDED'
1431
    ACTIVE      = 1 << 8
1432
    TERMINATED  = 1
1433
    SUSPENDED   = 2
1418 1434

  
1419
    objects     =   ForUpdateManager()
1435
    INACTIVE    = 0
1436
    TERMINATING = TERMINATED | ACTIVE
1437
    SUSPENDING  = SUSPENDED | ACTIVE
1438

  
1439
    state                       =   models.IntegerField(default=ACTIVE,
1440
                                                        db_index=True)
1441

  
1442
    objects     =   ProjectManager()
1420 1443

  
1421 1444
    def __str__(self):
1422 1445
        return _("<project %s '%s'>") % (self.id, self.application.name)
1423 1446

  
1424 1447
    __repr__ = __str__
1425 1448

  
1426
    def is_deactivating(self):
1427
        return bool(self.deactivation_start_date)
1428 1449

  
1429
    def is_deactivated_synced(self):
1430
        return bool(self.deactivation_date)
1450
    ### Internal state manipulation
1431 1451

  
1432
    def is_deactivated(self):
1433
        return self.is_deactivated_synced() or self.is_deactivating()
1452
    def _active_bit(self):
1453
        return self.state & self.ACTIVE
1434 1454

  
1435
    def is_still_approved(self):
1436
        return bool(self.last_approval_date)
1455
    def is_active_bit(self):
1456
        return self._active_bit() == self.ACTIVE
1437 1457

  
1438
    def is_active(self):
1439
        return not(self.is_deactivated())
1458
    def is_active_strict(self):
1459
        return self.state == self.ACTIVE
1460

  
1461
    def is_modulo_active(self, s):
1462
        return self.state & (~self.ACTIVE) == s
1463

  
1464
    def set_modulo_active(self, s):
1465
        self.state = s | self._active_bit()
1466

  
1467
    def set_inactive(self):
1468
        self.state &= (~self.ACTIVE)
1469

  
1470
    def is_deactivating(self, reason=None):
1471
        return (self.is_active_bit() and
1472
                (self.is_modulo_active(reason) if reason
1473
                 else not self.is_active_strict()))
1474

  
1475
    def is_deactivated_synced(self, reason=None):
1476
        if reason:
1477
            return self.state == reason
1478
        return not self.is_active_bit()
1479

  
1480
    def is_deactivated(self, reason=None):
1481
        return (self.is_deactivated_synced(reason) or
1482
                self.is_deactivating(reason))
1483

  
1484

  
1485
    ### Deactivation calls
1486

  
1487
    def set_deactivation_date(self):
1488
        self.deactivation_date = datetime.now()
1489

  
1490
    def deactivate(self):
1491
        self.set_deactivation_date()
1492
        self.set_inactive()
1493

  
1494
    def terminate(self):
1495
        self.deactivation_reason = 'TERMINATED'
1496
        self.set_modulo_active(self.TERMINATED)
1497
        self.save()
1498

  
1499

  
1500
    ### Logical checks
1440 1501

  
1441 1502
    def is_inconsistent(self):
1442 1503
        now = datetime.now()
1443 1504
        dates = [self.creation_date,
1444 1505
                 self.last_approval_date,
1445
                 self.deactivation_start_date,
1446 1506
                 self.deactivation_date]
1447 1507
        return any([date > now for date in dates])
1448 1508

  
1449
    def set_deactivation_start_date(self):
1450
        self.deactivation_start_date = datetime.now()
1509
    def is_active(self):
1510
        return self.is_active_strict()
1451 1511

  
1452
    def set_deactivation_date(self):
1453
        self.deactivation_start_date = None
1454
        self.deactivation_date = datetime.now()
1512
    @property
1513
    def is_alive(self):
1514
        return self.is_active()
1515

  
1516
    @property
1517
    def is_terminated(self):
1518
        return self.is_deactivated(self.TERMINATED)
1519

  
1520
    @property
1521
    def is_suspended(self):
1522
        return False
1455 1523

  
1456 1524
    def violates_resource_grants(self):
1457 1525
        return False
......
1461 1529
        return (len(self.approved_members) + adding >
1462 1530
                application.limit_on_members_number)
1463 1531

  
1464
    @property
1465
    def is_alive(self):
1466
        return self.is_active()
1532

  
1533
    ### Other
1467 1534

  
1468 1535
    @property
1469 1536
    def approved_memberships(self):
......
1510 1577
        m = ProjectMembership.objects.get(person=user, project=self)
1511 1578
        m.remove()
1512 1579

  
1513
    def terminate(self):
1514
        self.set_deactivation_start_date()
1515
        self.deactivation_reason = self.TERMINATED
1516
        self.save()
1517

  
1518
    @property
1519
    def is_terminated(self):
1520
        return (self.is_deactivated() and
1521
                self.deactivation_reason == self.TERMINATED)
1522

  
1523
    @property
1524
    def is_suspended(self):
1525
        return False
1526

  
1527 1580
class ProjectMembership(models.Model):
1528 1581

  
1529 1582
    person              =   models.ForeignKey(AstakosUser)
......
1793 1846
    REMOVING = ProjectMembership.REMOVING
1794 1847

  
1795 1848
    psfu = Project.objects.select_for_update()
1796
    projects = psfu.filter(deactivation_start_date__isnull=False)
1849
    projects = psfu.deactivating_projects()
1797 1850

  
1798 1851
    if not projects:
1799 1852
        return
......
1835 1888
    sync_finish_serials([serial])
1836 1889

  
1837 1890
    # finalize deactivating projects
1838
    deactivating_projects = psfu.filter(deactivation_start_date__isnull=False)
1891
    deactivating_projects = psfu.deactivating_projects()
1839 1892
    for project in deactivating_projects:
1840 1893
        objects = project.projectmembership_set.select_for_update()
1841 1894
        memberships = list(objects.filter(Q(state=ACCEPTED) |

Also available in: Unified diff