Example #1
0
class Tag(TimestampMixin, db.Model):
    """
    represent the tag of a disruption
    """
    __tablename__ = 'tag'
    id = db.Column(UUID, primary_key=True)
    name = db.Column(db.Text, unique=False, nullable=False)
    is_visible = db.Column(db.Boolean, unique=False, nullable=False, default=True)
    client_id = db.Column(UUID, db.ForeignKey(Client.id), nullable=False)
    client = db.relationship('Client', backref='tags', lazy='joined')
    __table_args__ = (db.UniqueConstraint('name', 'client_id', name='tag_name_client_id_key'),)

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<Tag %r>' % self.id

    @classmethod
    def all(cls, client_id):
        return cls.query.filter_by(client_id=client_id,is_visible=True).all()

    @classmethod
    def get(cls, id, client_id):
        return cls.query.filter_by(id=id, client_id=client_id, is_visible=True).first_or_404()

    @classmethod
    def get_archived_by_name(cls, name, client_id):
        return cls.query.filter_by(name=name, client_id=client_id, is_visible=False).first()
Example #2
0
class AssociateDisruptionProperty(db.Model):
    """
    links disruptions to properties
    """
    __tablename__ = 'associate_disruption_property'
    value = db.Column(db.Text, primary_key=True)
    disruption_id = db.Column(UUID,
                              db.ForeignKey('disruption.id'),
                              primary_key=True)
    property_id = db.Column(UUID,
                            db.ForeignKey('property.id'),
                            primary_key=True)
    property = db.relationship('Property', back_populates='disruptions')
    disruption = db.relationship('Disruption', back_populates='properties')

    @classmethod
    def get(cls, property_id, disruption_id, value):
        return cls.query.filter_by(property_id=property_id,
                                   disruption_id=disruption_id,
                                   value=value).first()

    @classmethod
    def get_by_disruption(cls, disruption_id):
        return cls.query.filter_by(disruption_id=disruption_id).all()

    def __repr__(self):
        return '<%s: %s %s %s>' % (self.__class__.__name__, self.property_id,
                                   self.disruption_id, self.value)
Example #3
0
class TimestampMixin(object):
    created_at = db.Column(db.DateTime(),
                           default=get_current_time,
                           nullable=False)
    updated_at = db.Column(db.DateTime(),
                           default=None,
                           onupdate=get_current_time)
Example #4
0
class TimestampMixin(object):
    created_at = db.Column(db.DateTime(),
                           default=datetime.utcnow,
                           nullable=False)
    updated_at = db.Column(db.DateTime(),
                           default=None,
                           onupdate=datetime.utcnow)
Example #5
0
class PTobject(TimestampMixin, db.Model):
    __tablename__ = 'pt_object'
    id = db.Column(UUID, primary_key=True)
    type = db.Column(PtObjectType,
                     nullable=False,
                     default='network',
                     index=True)
    uri = db.Column(db.Text, primary_key=True)
    line_section = db.relationship('LineSection',
                                   foreign_keys='LineSection.object_id',
                                   backref='pt_object',
                                   uselist=False)

    def __repr__(self):
        return '<PTobject %r>' % self.id

    def __init__(self, type=None, code=None):
        self.id = str(uuid.uuid1())
        self.type = type
        self.uri = code

    def insert_line_section(self, line_section):
        """
        Adds a line_section in an object.
        """
        self.line_section = line_section
        db.session.add(line_section)

    @classmethod
    def get(cls, id):
        return cls.query.filter_by(id=id).first_or_404()

    @classmethod
    def get_pt_object_by_uri(cls, uri):
        return cls.query.filter_by(uri=uri).first()
Example #6
0
class Pattern(TimestampMixin, db.Model):
    """
    represents the patterns of application periods of an impact
    """
    __tablename__ = 'pattern'
    id = db.Column(UUID, primary_key=True)
    start_date = db.Column(db.Date(), nullable=True)
    end_date = db.Column(db.Date(), nullable=True)
    weekly_pattern = db.Column(BIT(7), unique=False, nullable=False)
    impact_id = db.Column(UUID, db.ForeignKey(Impact.id), index=True)
    time_slots = db.relationship('TimeSlot',
                                 backref='pattern',
                                 lazy='joined',
                                 cascade='delete')

    def __init__(self, impact_id=None):
        self.id = str(uuid.uuid1())
        self.impact_id = impact_id

    def __repr__(self):
        return '<Pattern %r>' % self.id

    def delete_time_slots(self):
        for time_slot in self.time_slots:
            db.session.delete(time_slot)

    def insert_time_slot(self, time_slot):
        """
        Adds a time slot in the pattern
        """
        self.time_slots.append(time_slot)
        db.session.add(time_slot)
Example #7
0
class Property(TimestampMixin, db.Model):
    """
    represents the types of properties
    """
    __tablename__ = 'property'
    __table_args__ = (
        db.UniqueConstraint(
            'type',
            'key',
            'client_id',
            name='property_type_key_client_id_uc'
        ),
    )
    id = db.Column(UUID, primary_key=True)
    client_id = db.Column(UUID, db.ForeignKey(Client.id), nullable=False)
    client = db.relationship('Client', backref='properties', lazy='joined')
    key = db.Column(db.Text, nullable=False)
    type = db.Column(db.Text, nullable=False)
    disruptions = db.relationship(
        'AssociateDisruptionProperty',
        lazy='dynamic',
        back_populates='property',
        cascade='delete'
    )

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<%s: %s %s %s>' % (
            self.__class__.__name__, self.id, self.type, self.key
        )

    @classmethod
    def prepare_request(cls, client_id, key=None, type=None, id=None):
        request = {'client_id': client_id}
        if id:
            request['id'] = id
        if key:
            request['key'] = key
        if type:
            request['type'] = type

        return request

    @classmethod
    def all(cls, client_id, key=None, type=None):
        kargs = cls.prepare_request(client_id, key, type)

        return cls.query.filter_by(**kargs).all()

    @classmethod
    def get(cls, client_id, id=None, key=None, type=None):
        kargs = cls.prepare_request(client_id, key, type, id)

        return cls.query.filter_by(**kargs).first()
Example #8
0
class Meta(db.Model):
    """
    represent the channel for the message of an impact
    """
    id = db.Column(UUID, primary_key=True)
    key = db.Column(db.Text, unique=False, nullable=False)
    value = db.Column(db.Text, unique=False, nullable=False)

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<Meta %r>' % self.id
Example #9
0
class Wording(TimestampMixin, db.Model):
    """
    represent the Wording of a cause
    """
    id = db.Column(UUID, primary_key=True)
    key = db.Column(db.Text, unique=False, nullable=False)
    value = db.Column(db.Text, unique=False, nullable=False)

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<Wording %r>' % self.id
Example #10
0
class ApplicationPeriods(TimestampMixin, db.Model):
    """
    represents the application periods of an impact
    """
    id = db.Column(UUID, primary_key=True)
    start_date = db.Column(db.DateTime(), nullable=True)
    end_date = db.Column(db.DateTime(), nullable=True)
    impact_id = db.Column(UUID, db.ForeignKey(Impact.id), index=True)

    def __init__(self, impact_id=None):
        self.id = str(uuid.uuid1())
        self.impact_id = impact_id

    def __repr__(self):
        return '<ApplicationPeriods %r>' % self.id
Example #11
0
class ChannelType(TimestampMixin, db.Model):
    """
    represents the types of a channel
    """
    __tablename__ = 'channel_type'
    id = db.Column(UUID, primary_key=True)
    channel_id = db.Column(UUID, db.ForeignKey(Channel.id), index=True)
    name = db.Column(ChannelTypeEnum, nullable=False, default='web')

    def __init__(self, channel_id=None):
        self.id = str(uuid.uuid1())
        self.channel_id = channel_id

    def __repr__(self):
        return '<ChannelType %r>' % self.id
Example #12
0
class TimeSlot(TimestampMixin, db.Model):
    """
    represents the time slots of a pattern
    """
    __tablename__ = 'time_slot'
    id = db.Column(UUID, primary_key=True)
    begin = db.Column(db.Time(), nullable=True)
    end = db.Column(db.Time(), nullable=True)
    pattern_id = db.Column(UUID, db.ForeignKey(Pattern.id), index=True)

    def __init__(self, pattern_id=None):
        self.id = str(uuid.uuid1())
        self.pattern_id = pattern_id

    def __repr__(self):
        return '<TimeSlot %r>' % self.id
Example #13
0
class Cause(TimestampMixin, db.Model):
    """
    represent the cause of a disruption
    """
    id = db.Column(UUID, primary_key=True)
    # TODO A supprimer plus tard
    wording = db.Column(db.Text, unique=False, nullable=False)
    is_visible = db.Column(db.Boolean,
                           unique=False,
                           nullable=False,
                           default=True)
    client_id = db.Column(UUID, db.ForeignKey(Client.id), nullable=False)
    client = db.relationship('Client', backref='causes')
    category_id = db.Column(UUID, db.ForeignKey(Category.id), nullable=True)
    category = db.relationship('Category', backref='causes', lazy='joined')
    wordings = db.relationship("Wording",
                               secondary=associate_wording_cause,
                               backref="causes")

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<Cause %r>' % self.id

    @classmethod
    def all(cls, client_id, category_id=None):
        kargs = {"client_id": client_id, "is_visible": True}
        if category_id:
            kargs["category_id"] = category_id
        return cls.query.filter_by(**kargs).all()

    @classmethod
    def get(cls, id, client_id, category_id=None):
        kargs = {"client_id": client_id, "is_visible": True, "id": id}
        if category_id:
            kargs["category_id"] = category_id
        return cls.query.filter_by(**kargs).first_or_404()

    def delete_wordings(self):
        index = len(self.wordings) - 1
        while index >= 0:
            wording = self.wordings[index]
            self.wordings.remove(wording)
            db.session.delete(wording)
            index -= 1
Example #14
0
class Client(TimestampMixin, db.Model):
    __tablename__ = 'client'
    id = db.Column(UUID, primary_key=True)
    client_code = db.Column(db.Text, unique=True, nullable=False)

    def __init__(self, code=None):
        self.id = str(uuid.uuid1())
        self.client_code = code

    @classmethod
    def get_by_code(cls, code):
        return cls.query.filter_by(client_code=code).first()

    @classmethod
    def get_or_create(cls, code):
        client = cls.query.filter_by(client_code=code).first()
        if not client:
            client = Client(code)
        return client
Example #15
0
class Message(TimestampMixin, db.Model):
    """
    represent the message of an impact
    """
    id = db.Column(UUID, primary_key=True)
    text = db.Column(db.Text, unique=False, nullable=False)
    impact_id = db.Column(UUID, db.ForeignKey(Impact.id))
    channel_id = db.Column(UUID, db.ForeignKey(Channel.id))
    channel = db.relationship('Channel', backref='message', lazy='select')
    meta = db.relationship("Meta",
                           secondary=associate_message_meta,
                           lazy="joined")

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<Message %r>' % self.id

    @classmethod
    def all(cls):
        return cls.query.all()

    @classmethod
    def get(cls, id):
        return cls.query.filter_by(id=id).first_or_404()

    def insert_meta(self, meta):
        """
        Adds an meta in a message.
        """
        self.meta.append(meta)
        db.session.add(meta)

    def delete_meta(self, meta):
        """
        delete a meta in a message.
        """
        self.meta.remove(meta)
        db.session.delete(meta)
Example #16
0
class Message(TimestampMixin, db.Model):
    """
    represent the message of an impact
    """
    id = db.Column(UUID, primary_key=True)
    text = db.Column(db.Text, unique=False, nullable=False)
    impact_id = db.Column(UUID, db.ForeignKey(Impact.id))
    channel_id = db.Column(UUID, db.ForeignKey(Channel.id))
    channel = db.relationship('Channel', backref='message', lazy='select')

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<Message %r>' % self.id

    @classmethod
    def all(cls):
        return cls.query.all()

    @classmethod
    def get(cls, id):
        return cls.query.filter_by(id=id).first_or_404()
Example #17
0
class Severity(TimestampMixin, db.Model):
    """
    represent the severity of an impact
    """
    id = db.Column(UUID, primary_key=True)
    wording = db.Column(db.Text, unique=False, nullable=False)
    color = db.Column(db.Text, unique=False, nullable=True)
    is_visible = db.Column(db.Boolean,
                           unique=False,
                           nullable=False,
                           default=True)
    priority = db.Column(db.Integer, unique=False, nullable=True)
    effect = db.Column(SeverityEffect, nullable=True)
    client_id = db.Column(UUID, db.ForeignKey(Client.id), nullable=False)
    client = db.relationship('Client', backref='severity')
    wordings = db.relationship("Wording",
                               secondary=associate_wording_severity,
                               backref="severities")

    def delete_wordings(self):
        index = len(self.wordings) - 1
        while index >= 0:
            wording = self.wordings[index]
            self.wordings.remove(wording)
            db.session.delete(wording)
            index -= 1

    def __init__(self):
        self.id = str(uuid.uuid1())
        self.effect = 'unknown_effect'

    def __repr__(self):
        return '<Severity %r>' % self.id

    @classmethod
    def all(cls, client_id):
        return cls.query.filter_by(
            client_id=client_id, is_visible=True).order_by(cls.priority).all()

    @classmethod
    def get(cls, id, client_id):
        severity = cls.query.filter_by(id=id,
                                       client_id=client_id,
                                       is_visible=True).first()

        if severity is None:
            raise exceptions.ObjectUnknown(
                'The severty with id {} does not exist for this client'.format(
                    id))

        return severity
Example #18
0
class LineSection(TimestampMixin, db.Model):
    __tablename__ = 'line_section'
    id = db.Column(UUID, primary_key=True)
    line_object_id = db.Column(UUID,
                               db.ForeignKey(PTobject.id),
                               nullable=False)
    start_object_id = db.Column(UUID,
                                db.ForeignKey(PTobject.id),
                                nullable=False)
    end_object_id = db.Column(UUID, db.ForeignKey(PTobject.id), nullable=False)
    sens = db.Column(db.Integer, unique=False, nullable=True)
    object_id = db.Column(UUID, db.ForeignKey(PTobject.id))
    line = db.relationship('PTobject', foreign_keys=line_object_id)
    start_point = db.relationship('PTobject',
                                  foreign_keys=start_object_id,
                                  lazy="joined")
    end_point = db.relationship('PTobject',
                                foreign_keys=end_object_id,
                                lazy="joined")
    routes = db.relationship("PTobject",
                             secondary=associate_line_section_route_object,
                             lazy="joined")
    via = db.relationship("PTobject",
                          secondary=associate_line_section_via_object,
                          lazy="joined")
    wordings = db.relationship("Wording",
                               secondary=associate_wording_line_section,
                               backref="linesections",
                               lazy="joined")

    def delete_wordings(self):
        index = len(self.wordings) - 1
        while index >= 0:
            wording = self.wordings[index]
            self.wordings.remove(wording)
            db.session.delete(wording)
            index -= 1

    def __repr__(self):
        return '<LineSection %r>' % self.id

    def __init__(self, object_id=None):
        self.id = str(uuid.uuid1())
        self.object_id = object_id

    @classmethod
    def get(cls, id):
        return cls.query.filter_by(id=id).first_or_404()

    @classmethod
    def get_by_object_id(cls, object_id):
        return cls.query.filter_by(object_id=object_id).first()

    @classmethod
    def get_by_ids(cls, ids):
        return cls.query.filter(cls.object_id.in_(ids)).all()
Example #19
0
class Channel(TimestampMixin, db.Model):
    """
    represent the channel for the message of an impact
    """
    id = db.Column(UUID, primary_key=True)
    name = db.Column(db.Text, unique=False, nullable=False)
    max_size = db.Column(db.Integer, unique=False, nullable=True)
    content_type = db.Column(db.Text, unique=False, nullable=True)
    is_visible = db.Column(db.Boolean,
                           unique=False,
                           nullable=False,
                           default=True)
    client_id = db.Column(UUID, db.ForeignKey(Client.id), nullable=False)
    client = db.relationship('Client', backref='channels', lazy='joined')
    channel_types = db.relationship('ChannelType',
                                    backref='channel',
                                    lazy='joined')

    def __init__(self):
        self.id = str(uuid.uuid1())

    def __repr__(self):
        return '<Channel %r>' % self.id

    def delete_channel_types(self):
        """
        Deletes a channel_type in the channel
        """
        index = len(self.channel_types) - 1
        while index >= 0:
            type = self.channel_types[index]
            self.channel_types.remove(type)
            db.session.delete(type)
            index -= 1

    def insert_channel_type(self, channel_type):
        """
        Adds a channel_type in the channel
        """
        self.channel_types.append(channel_type)
        db.session.add(channel_type)

    @classmethod
    def all(cls, client_id):
        return cls.query.filter_by(client_id=client_id,
                                   is_visible=True).order_by(cls.name).all()

    @classmethod
    def get(cls, id, client_id):
        return cls.query.filter_by(id=id, client_id=client_id,
                                   is_visible=True).first_or_404()
Example #20
0
class Disruption(TimestampMixin, db.Model):
    __tablename__ = 'disruption'
    id = db.Column(UUID, primary_key=True)
    reference = db.Column(db.Text, unique=False, nullable=True)
    note = db.Column(db.Text, unique=False, nullable=True)
    status = db.Column(DisruptionStatus,
                       nullable=False,
                       default='published',
                       index=True)
    start_publication_date = db.Column(db.DateTime(), nullable=True)
    end_publication_date = db.Column(db.DateTime(), nullable=True)
    impacts = db.relationship('Impact',
                              backref='disruption',
                              lazy='dynamic',
                              cascade='delete')
    cause_id = db.Column(UUID, db.ForeignKey(Cause.id))
    cause = db.relationship('Cause', backref='disruption', lazy='joined')
    tags = db.relationship("Tag",
                           secondary=associate_disruption_tag,
                           backref="disruptions")
    client_id = db.Column(UUID, db.ForeignKey(Client.id), nullable=False)
    client = db.relationship('Client', backref='disruptions', lazy='joined')
    contributor_id = db.Column(UUID,
                               db.ForeignKey(Contributor.id),
                               nullable=False)
    contributor = db.relationship('Contributor',
                                  backref='disruptions',
                                  lazy='joined')
    version = db.Column(db.Integer, nullable=False, default=1)
    localizations = db.relationship("PTobject",
                                    secondary=associate_disruption_pt_object,
                                    backref="disruptions")
    properties = db.relationship('AssociateDisruptionProperty',
                                 lazy='joined',
                                 back_populates='disruption',
                                 cascade='delete')

    def __repr__(self):
        return '<Disruption %r>' % self.id

    def __init__(self):
        self.id = str(uuid.uuid1())

    def upgrade_version(self):
        self.version = self.version + 1

    def archive(self):
        """
        archive the disruption, it will not be visible on any media
        """
        self.status = 'archived'
        for impact in self.impacts:
            impact.archive()

    def is_published(self):
        return self.status == 'published'

    def is_draft(self):
        return self.status == 'draft'

    @classmethod
    def get(cls, id, contributor_id):
        return cls.query.filter((cls.id == id)
                                and (cls.contributor == contributor_id)
                                and (cls.status != 'archived')).first_or_404()

    @classmethod
    @paginate()
    def all_with_filter(cls, contributor_id, publication_status, tags, uri,
                        statuses):
        availlable_filters = {
            'past':
            and_(cls.end_publication_date != None,
                 cls.end_publication_date < get_current_time()),
            'ongoing':
            and_(
                cls.start_publication_date <= get_current_time(),
                or_(cls.end_publication_date == None,
                    cls.end_publication_date >= get_current_time())),
            'coming':
            Disruption.start_publication_date > get_current_time()
        }
        query = cls.query.filter(
            and_(cls.contributor_id == contributor_id,
                 cls.status.in_(statuses)))

        if tags:
            query = query.filter(cls.tags.any(Tag.id.in_(tags)))

        if uri:
            query = query.join(cls.impacts)
            query = query.filter(Impact.status == 'published')
            query = query.join(Impact.objects)

            #Here add a new query to find impacts with line =_section having uri as line, start_point or end_point
            filters = []
            alias_line = aliased(PTobject)
            alias_start_point = aliased(PTobject)
            alias_end_point = aliased(PTobject)
            alias_route = aliased(PTobject)
            alias_via = aliased(PTobject)
            query_line_section = query
            query_line_section = query_line_section.join(PTobject.line_section)
            query_line_section = query_line_section.join(
                alias_line, LineSection.line_object_id == alias_line.id)
            filters.append(alias_line.uri == uri)
            query_line_section = query_line_section.join(
                PTobject, LineSection.object_id == PTobject.id)
            query_line_section = query_line_section.join(
                alias_start_point,
                LineSection.start_object_id == alias_start_point.id)
            filters.append(alias_start_point.uri == uri)
            query_line_section = query_line_section.join(
                alias_end_point,
                LineSection.end_object_id == alias_end_point.id)
            filters.append(alias_end_point.uri == uri)
            query_line_section = query_line_section.join(
                alias_route, LineSection.routes)
            filters.append(alias_route.uri == uri)
            query_line_section = query_line_section.join(
                alias_via, LineSection.via)
            filters.append(alias_via.uri == uri)
            query_line_section = query_line_section.filter(or_(*filters))

            query = query.filter(PTobject.uri == uri)

        publication_status = set(publication_status)
        if len(publication_status) == len(publication_status_values):
            #For a query by uri use union with the query for line_section
            if uri:
                query = query.union_all(query_line_section)

        else:
            filters = [
                availlable_filters[status] for status in publication_status
            ]
            query = query.filter(or_(*filters))
            #For a query by uri use union with the query for line_section
            if uri:
                query_line_section = query_line_section.filter(or_(*filters))
                query = query.union_all(query_line_section)

        return query.order_by(cls.end_publication_date, cls.id)

    @property
    def publication_status(self):
        current_time = utils.get_current_time()
        # Past
        if (self.end_publication_date != None) and (self.end_publication_date <
                                                    current_time):
            return "past"
        # ongoing
        if self.start_publication_date <= current_time\
            and (self.end_publication_date == None or self.end_publication_date >= current_time):
            return "ongoing"
        # Coming
        if self.start_publication_date > current_time:
            return "coming"
Example #21
0
class Impact(TimestampMixin, db.Model):
    id = db.Column(UUID, primary_key=True)
    status = db.Column(ImpactStatus,
                       nullable=False,
                       default='published',
                       index=True)
    disruption_id = db.Column(UUID, db.ForeignKey(Disruption.id))
    severity_id = db.Column(UUID, db.ForeignKey(Severity.id))
    messages = db.relationship('Message',
                               backref='impact',
                               lazy='joined',
                               cascade='delete')
    application_periods = db.relationship('ApplicationPeriods',
                                          backref='impact',
                                          lazy='joined',
                                          cascade='delete')
    severity = db.relationship('Severity', backref='impacts', lazy='joined')
    objects = db.relationship("PTobject",
                              secondary=associate_impact_pt_object,
                              lazy='joined',
                              order_by="PTobject.type, PTobject.uri")
    patterns = db.relationship('Pattern',
                               backref='impact',
                               lazy='joined',
                               cascade='delete')
    send_notifications = db.Column(db.Boolean,
                                   unique=False,
                                   nullable=False,
                                   default=True)
    version = db.Column(db.Integer, nullable=False, default=1)
    notification_date = db.Column(db.DateTime(), default=None, nullable=True)

    def __repr__(self):
        return '<Impact %r>' % self.id

    def __marshallable__(self):
        '''
        This method is added to solve the problem of impact without instance during creation of response json for Post..
        API post cannot fill url for impact and disruption in impact_fields
        When we have either one of them present in impact_fields, it works.
        '''
        d = {}
        d['id'] = self.id
        d['status'] = self.status
        d['disruption_id'] = self.disruption_id
        d['severity_id'] = self.severity_id
        d['objects'] = self.objects
        d['application_periods'] = self.application_periods
        d['severity'] = self.severity
        d['messages'] = self.messages
        d['application_period_patterns'] = self.patterns
        d['send_notifications'] = self.send_notifications
        d['notification_date'] = self.notification_date
        return d

    def __init__(self, objects=None):
        self.id = str(uuid.uuid1())

    def archive(self):
        """
        archive the impact, it will not be visible on any media
        """
        self.status = 'archived'

    def insert_object(self, object):
        """
        Adds an objectTC in a imapct.
        """
        self.objects.append(object)
        db.session.add(object)

    def upgrade_version(self):
        self.version = self.version + 1

    def insert_message(self, message):
        """
        Adds an message in a imapct.
        """
        self.messages.append(message)
        db.session.add(message)

    def delete_message(self, message):
        """
        delete a message in an impact.
        """
        self.messages.remove(message)
        db.session.delete(message)

    def delete_app_periods(self):
        for app_per in self.application_periods:
            db.session.delete(app_per)

    def delete_line_section(self):
        for pt_object in self.objects:
            if pt_object.type == 'line_section':
                line_section = LineSection.get_by_object_id(pt_object.id)
                if line_section:
                    db.session.delete(line_section)
                self.delete(pt_object)
                db.session.delete(pt_object)

    def insert_app_period(self, application_period):
        """
        Adds an ApplicationPeriods in a impact.
        """
        self.application_periods.append(application_period)
        db.session.add(application_period)

    def delete_patterns(self):
        for i in range(len(self.patterns), 0, -1):
            pattern = self.patterns[i - 1]
            pattern.delete_time_slots()
            self.patterns.remove(pattern)
            db.session.delete(pattern)

    def insert_pattern(self, pattern):
        """
        Adds a pattern of ApplicationPeriods in a impact.
        """
        self.patterns.append(pattern)
        db.session.add(pattern)

    @classmethod
    def get(cls, id, contributor_id):
        query = cls.query.filter_by(id=id, status='published')
        query = query.join(Disruption)
        query = query.filter(Disruption.contributor_id == contributor_id)
        return query.first_or_404()

    @classmethod
    @paginate()
    def all(cls, disruption_id, contributor_id):
        alias = aliased(Severity)
        query = cls.query.filter_by(status='published')
        query = query.filter(and_(cls.disruption_id == disruption_id))
        query = query.join(Disruption)
        query = query.filter(Disruption.contributor_id == contributor_id)
        return query.join(alias, Impact.severity).order_by(alias.priority)

    @classmethod
    def all_with_filter(cls, start_date, end_date, pt_object_type, uris,
                        contributor_id):
        filter_with_line_section = True
        pt_object_alias = aliased(PTobject)
        query = cls.query.filter(cls.status == 'published')
        query = query.join(Disruption)
        query = query.join(ApplicationPeriods)
        query = query.join(pt_object_alias, cls.objects)
        query = query.filter(Disruption.contributor_id == contributor_id)
        query = query.filter(
            and_(ApplicationPeriods.start_date <= end_date,
                 ApplicationPeriods.end_date >= start_date))
        query_line_section = query
        if pt_object_type or uris:
            alias_line = aliased(PTobject)
            alias_start_point = aliased(PTobject)
            alias_end_point = aliased(PTobject)
            alias_route = aliased(PTobject)
            alias_via = aliased(PTobject)

            query_line_section = query_line_section.filter(
                pt_object_alias.type == 'line_section')
            query_line_section = query_line_section.join(
                pt_object_alias.line_section)
            query_line_section = query_line_section.join(
                alias_line, LineSection.line_object_id == alias_line.id)
            query_line_section = query_line_section.join(
                alias_start_point,
                LineSection.start_object_id == alias_start_point.id)
            query_line_section = query_line_section.join(
                alias_end_point,
                LineSection.end_object_id == alias_end_point.id)
            query_line_section = query_line_section.outerjoin(
                alias_route, LineSection.routes)
            query_line_section = query_line_section.outerjoin(
                alias_via, LineSection.via)
        else:
            filter_with_line_section = False

        if pt_object_type:
            query = query.filter(pt_object_alias.type == pt_object_type)
            if pt_object_type == 'route':
                query_line_section = query_line_section.filter(
                    alias_route.type == pt_object_type)
            elif pt_object_type not in ['line_section', 'line', 'stop_area']:
                filter_with_line_section = False

        if uris:
            query = query.filter(pt_object_alias.uri.in_(uris))
            uri_filters = []
            uri_filters.append(alias_line.uri.in_(uris))
            uri_filters.append(alias_start_point.uri.in_(uris))
            uri_filters.append(alias_end_point.uri.in_(uris))
            uri_filters.append(alias_route.uri.in_(uris))
            uri_filters.append(alias_via.uri.in_(uris))
            query_line_section = query_line_section.filter(or_(*uri_filters))

        if filter_with_line_section:
            query = query.union_all(query_line_section)
        query = query.order_by("application_periods_1.start_date")
        return query.all()
Example #22
0
class Disruption(TimestampMixin, db.Model):
    __tablename__ = 'disruption'
    id = db.Column(UUID, primary_key=True)
    reference = db.Column(db.Text, unique=False, nullable=True)
    note = db.Column(db.Text, unique=False, nullable=True)
    status = db.Column(DisruptionStatus,
                       nullable=False,
                       default='published',
                       index=True)
    start_publication_date = db.Column(db.DateTime(), nullable=True)
    end_publication_date = db.Column(db.DateTime(), nullable=True)
    impacts = db.relationship('Impact',
                              backref='disruption',
                              lazy='joined',
                              cascade='delete')
    cause_id = db.Column(UUID, db.ForeignKey(Cause.id))
    cause = db.relationship('Cause', backref='disruption', lazy='joined')
    tags = db.relationship("Tag",
                           secondary=associate_disruption_tag,
                           backref="disruptions",
                           lazy='joined')
    client_id = db.Column(UUID, db.ForeignKey(Client.id), nullable=False)
    client = db.relationship('Client', backref='disruptions')
    contributor_id = db.Column(UUID,
                               db.ForeignKey(Contributor.id),
                               nullable=False)
    contributor = db.relationship('Contributor',
                                  backref='disruptions',
                                  lazy='joined')
    version = db.Column(db.Integer, nullable=False, default=1)
    localizations = db.relationship("PTobject",
                                    secondary=associate_disruption_pt_object,
                                    backref="disruptions",
                                    lazy='joined')
    properties = db.relationship('AssociateDisruptionProperty',
                                 lazy='joined',
                                 back_populates='disruption',
                                 cascade='delete')

    def __repr__(self):
        return '<Disruption %r>' % self.id

    def __init__(self):
        self.id = str(uuid.uuid1())

    def upgrade_version(self):
        self.version = self.version + 1

    def archive(self):
        """
        archive the disruption, it will not be visible on any media
        """
        self.status = 'archived'
        for impact in self.impacts:
            impact.archive()

    def is_published(self):
        return self.status == 'published'

    def is_draft(self):
        return self.status == 'draft'

    def is_last_impact(self, impact_id):
        nb_impacts = list(
            filter(lambda x: x.status != 'archived', self.impacts))
        return len(nb_impacts) == 1 and nb_impacts[0].id == impact_id

    @classmethod
    def get(cls, id, contributor_id):
        return cls.query.filter((cls.id == id)
                                and (cls.contributor == contributor_id)
                                and (cls.status != 'archived')).first_or_404()

    @classmethod
    def get_query_with_args(cls,
                            contributor_id,
                            publication_status,
                            ends_after_date,
                            ends_before_date,
                            tags,
                            uri,
                            line_section,
                            statuses,
                            application_status=application_status_values,
                            query=None,
                            cause_category_id=None,
                            current_time=None):
        if current_time is None: current_time = get_current_time()
        if (query is None):
            query = cls.query

        query = query.filter(
            and_(cls.contributor_id == contributor_id,
                 cls.status.in_(statuses)))

        if cause_category_id:
            query = query.join(cls.cause)
            query = query.filter(Cause.category_id == cause_category_id)

        if ends_after_date:
            query = query.filter(cls.end_publication_date >= ends_after_date)

        if ends_before_date:
            query = query.filter(cls.end_publication_date <= ends_before_date)

        if tags:
            query = query.filter(cls.tags.any(Tag.id.in_(tags)))

        if uri:
            query = query.join(cls.impacts)
            query = query.filter(Impact.status == 'published')
            query = query.join(Impact.objects)

            # Here add a new query to find impacts with line_section having uri as line
            if line_section:
                query_line_section = query
                query_line_section = query_line_section.filter(
                    and_(PTobject.type == "line_section",
                         PTobject.uri.like(uri + ":%")))

            query = query.filter(PTobject.uri == uri)

        publication_availlable_filters = {
            'past':
            and_(cls.end_publication_date != None,
                 cls.end_publication_date < current_time),
            'ongoing':
            and_(
                cls.start_publication_date <= current_time,
                or_(cls.end_publication_date == None,
                    cls.end_publication_date >= current_time)),
            'coming':
            Disruption.start_publication_date > current_time
        }
        publication_status = set(publication_status)
        if len(publication_status) == len(publication_status_values):
            # For a query by uri use union with the query for line_section
            if uri and line_section:
                query = query.union(query_line_section)

        else:
            filters = [
                publication_availlable_filters[status]
                for status in publication_status
            ]
            query = query.filter(or_(*filters))

            # For a query by uri use union with the query for line_section
            if uri and line_section:
                query_line_section = query_line_section.filter(or_(*filters))
                query = query.union(query_line_section)

        application_status = set(application_status)
        if len(application_status) != len(application_status_values):
            query = query.join(cls.impacts)
            query = query.filter(Impact.status == 'published')
            query = query.join(Impact.application_periods)
            application_availlable_filters = {
                'past':
                ApplicationPeriods.end_date < current_time,
                'ongoing':
                and_(ApplicationPeriods.start_date <= current_time,
                     ApplicationPeriods.end_date >= current_time),
                'coming':
                ApplicationPeriods.start_date > current_time
            }
            filters = [
                application_availlable_filters[status]
                for status in application_status
            ]
            query = query.filter(or_(*filters))
        return query.order_by(cls.end_publication_date, cls.id)

    @classmethod
    @paginate()
    def all_with_post_filter(cls,
                             contributor_id,
                             application_status,
                             publication_status,
                             ends_after_date,
                             ends_before_date,
                             tags,
                             uri,
                             line_section,
                             statuses,
                             ptObjectFilter,
                             cause_category_id,
                             application_period,
                             current_time=None):
        if current_time is None: current_time = get_current_time()
        query = cls.query
        object_types = []
        uris = []
        line_section_uris = []
        if uri_is_not_in_pt_object_filter(uri=uri,
                                          pt_object_filter=ptObjectFilter):
            return cls.query.filter('1=0')
        if ptObjectFilter is not None:
            for key, objectIds in ptObjectFilter.iteritems():
                object_type = key[:-1]
                object_types.append(object_type)
                uris = uris + objectIds
                if object_type == 'line':
                    line_section_uris = [
                        objectId + ':%' for objectId in objectIds
                    ]
                    line_section = False

            uris_filter = and_(
                cls.impacts.any(
                    Impact.objects.any(PTobject.type.in_(object_types))),
                cls.impacts.any(Impact.objects.any(PTobject.uri.in_(uris))))
            if len(line_section_uris):
                query = cls.query.filter(
                    or_(
                        uris_filter,
                        cls.impacts.any(
                            Impact.objects.any(
                                or_(*[
                                    PTobject.uri.like(objectId)
                                    for objectId in line_section_uris
                                ])))))
            else:
                query = cls.query.filter(uris_filter)
        if application_period is not None:
            query = cls.query.filter(
                cls.impacts.any(
                    Impact.application_periods.any(
                        or_(
                            and_(
                                ApplicationPeriods.start_date >=
                                application_period['begin'],
                                ApplicationPeriods.start_date <=
                                application_period['end']),
                            and_(
                                ApplicationPeriods.end_date >=
                                application_period['begin'],
                                ApplicationPeriods.end_date <=
                                application_period['end']),
                            and_(
                                ApplicationPeriods.start_date <=
                                application_period['begin'],
                                ApplicationPeriods.end_date >=
                                application_period['end'])))))
        return cls.get_query_with_args(contributor_id=contributor_id,
                                       application_status=application_status,
                                       publication_status=publication_status,
                                       ends_after_date=ends_after_date,
                                       ends_before_date=ends_before_date,
                                       tags=tags,
                                       uri=uri,
                                       line_section=line_section,
                                       statuses=statuses,
                                       query=query,
                                       cause_category_id=cause_category_id,
                                       current_time=current_time)

    @classmethod
    @paginate()
    def all_with_filter(cls, contributor_id, publication_status,
                        ends_after_date, ends_before_date, tags, uri,
                        line_section, statuses):

        return cls.get_query_with_args(contributor_id=contributor_id,
                                       publication_status=publication_status,
                                       ends_after_date=ends_after_date,
                                       ends_before_date=ends_before_date,
                                       tags=tags,
                                       uri=uri,
                                       line_section=line_section,
                                       statuses=statuses)

    @property
    def publication_status(self):
        current_time = utils.get_current_time()
        # Past
        if (self.end_publication_date != None) and (self.end_publication_date <
                                                    current_time):
            return "past"
        # ongoing
        if self.start_publication_date <= current_time\
                and (self.end_publication_date == None or self.end_publication_date >= current_time):
            return "ongoing"
        # Coming
        if self.start_publication_date > current_time:
            return "coming"

    @classmethod
    def traffic_report_filter(cls, contributor_id):
        query = cls.query.filter(cls.status == 'published')
        query = query.filter(cls.contributor_id == contributor_id)
        query = query.filter(
            between(get_current_time(), cls.start_publication_date,
                    cls.end_publication_date))
        return query.all()
Example #23
0
    @classmethod
    def get_by_code(cls, code):
        return cls.query.filter_by(contributor_code=code).first()

    @classmethod
    def get_or_create(cls, code):
        contributor = cls.query.filter_by(contributor_code=code).first()
        if not contributor:
            contributor = Contributor(code)
        return contributor


associate_wording_severity = db.Table(
    'associate_wording_severity', db.metadata,
    db.Column('wording_id', UUID, db.ForeignKey('wording.id')),
    db.Column('severity_id', UUID, db.ForeignKey('severity.id')),
    db.PrimaryKeyConstraint('wording_id',
                            'severity_id',
                            name='wording_severity_pk'))


class Severity(TimestampMixin, db.Model):
    """
    represent the severity of an impact
    """
    id = db.Column(UUID, primary_key=True)
    wording = db.Column(db.Text, unique=False, nullable=False)
    color = db.Column(db.Text, unique=False, nullable=True)
    is_visible = db.Column(db.Boolean,
                           unique=False,