Ejemplo n.º 1
0
class Role(CacheableMixin, db.Model, RoleMixin, MarshalMixin):
    cache_label = 'users'
    query_class = query_callable()

    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))
Ejemplo n.º 2
0
class ZUPC(db.Model, MarshalMixin, CacheableMixin):
    cache_label = 'zupc'
    query_class = query_callable()

    id = Column(db.Integer, primary_key=True)
    departement_id = Column(db.Integer, db.ForeignKey('departement.id'))
    nom = Column(db.String(255), label='Nom')
    insee = Column(db.String(), nullable=True)
    shape = Column(Geography(geometry_type='MULTIPOLYGON', srid=4326,
        spatial_index=False), label='Geography of the shape')
    departement = db.relationship('Departement',
            backref=db.backref('departements'), lazy='joined')
    parent_id = Column(db.Integer, db.ForeignKey('ZUPC.id'))
    parent = db.relationship('ZUPC', remote_side=[id], lazy='joined')
    active = Column(db.Boolean, default=False)
    __geom = None
    __preped_geom = None
    __bounds = None

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

    def __str__(self):
        return self.nom

    @property
    def geom(self):
        if self.__geom is None:
            self.__geom = to_shape(self.shape)
        return self.__geom

    @property
    def preped_geom(self):
        if self.__preped_geom is None:
            self.__preped_geom = prep(self.geom)
        return self.__preped_geom

    @property
    def bounds(self):
        if not self.__bounds:
            self.__bounds = self.geom.bounds
        return self.__bounds

    @property
    def bottom(self):
        return self.bounds[1]

    @property
    def left(self):
        return self.bounds[0]

    @property
    def top(self):
        return self.bounds[3]

    @property
    def right(self):
        return self.bounds[2]
Ejemplo n.º 3
0
class VehicleDescription(HistoryMixin, CacheableMixin, db.Model, AsDictMixin):
    @declared_attr
    def added_by(cls):
        return Column(db.Integer, db.ForeignKey('user.id'))

    cache_label = 'taxis'
    query_class = query_callable()

    def __init__(self, vehicle_id, added_by):
        db.Model.__init__(self)
        HistoryMixin.__init__(self)
        self.vehicle_id = vehicle_id
        self.added_by = added_by

    id = Column(db.Integer, primary_key=True)
    model_id = Column(db.Integer, db.ForeignKey("model.id"))
    __model = db.relationship('Model', lazy='joined')
    constructor_id = Column(db.Integer, db.ForeignKey("constructor.id"))
    __constructor = db.relationship('Constructor', lazy='joined')
    model_year = Column(db.Integer,
                        label=u'Année',
                        nullable=True,
                        description=u'Année de mise en production du véhicule')
    engine = Column(db.String(80),
                    label=u'Motorisation',
                    nullable=True,
                    description=u'Motorisation du véhicule, champ P3')
    horse_power = Column(
        db.Float(),
        label=u'Puissance',
        nullable=True,
        description=u'Puissance du véhicule en chevaux fiscaux')
    relais = Column(db.Boolean,
                    label=u'Relais',
                    default=False,
                    nullable=True,
                    description=u'Est-ce un véhicule relais')
    horodateur = Column(db.String(255),
                        label=u'Horodateur',
                        nullable=True,
                        description=u'Modèle de l\'horodateur')
    taximetre = Column(db.String(255),
                       label=u'Taximètre',
                       nullable=True,
                       description=u'Modèle du taximètre')
    date_dernier_ct = Column(
        db.Date(),
        label=u'Date du dernier CT (format année-mois-jour)',
        description=u'Date du dernier contrôle technique')
    date_validite_ct = Column(
        db.Date(),
        label=u'Date de la fin de validité du CT (format année-mois-jour)',
        description=u'Date de fin de validité du contrôle technique')
    special_need_vehicle = Column(
        db.Boolean,
        name='special_need_vehicle',
        label=u'Véhicule spécialement aménagé pour PMR ',
        nullable=True)
    type_ = Column(Enum('sedan',
                        'mpv',
                        'station_wagon',
                        'normal',
                        name='vehicle_type_enum'),
                   label='Type',
                   nullable=True)
    luxury = Column(db.Boolean, name='luxury', label='Luxe ?', nullable=True)
    credit_card_accepted = Column(db.Boolean,
                                  name='credit_card_accepted',
                                  label=u'Carte bancaire acceptée ?',
                                  nullable=True)
    nfc_cc_accepted = Column(
        db.Boolean,
        name='nfc_cc_accepted',
        label=u'Paiement sans contact sur carte bancaire accepté ?',
        nullable=True)
    amex_accepted = Column(db.Boolean,
                           name='amex_accepted',
                           label=u'AMEX acceptée ?',
                           nullable=True)
    bank_check_accepted = Column(db.Boolean,
                                 name='bank_check_accepted',
                                 label=u'Chèque bancaire accepté ?',
                                 nullable=True)
    fresh_drink = Column(db.Boolean,
                         name='fresh_drink',
                         label=u'Boisson fraiche ?',
                         nullable=True)
    dvd_player = Column(db.Boolean,
                        name='dvd_player',
                        label='Lecteur DVD ?',
                        nullable=True)
    tablet = Column(db.Boolean,
                    name='tablet',
                    label='Tablette ?',
                    nullable=True)
    wifi = Column(db.Boolean,
                  name='wifi',
                  label=u'Wifi à bord ?',
                  nullable=True)
    baby_seat = Column(db.Boolean,
                       name='baby_seat',
                       label=u'Siège bébé ?',
                       nullable=True)
    bike_accepted = Column(db.Boolean,
                           name='bike_accepted',
                           label=u'Transport de vélo',
                           nullable=True)
    pet_accepted = Column(db.Boolean,
                          name='pet_accepted',
                          label=u'Animaux de compagnie acceptés ?',
                          nullable=True)
    air_con = Column(db.Boolean,
                     name='air_con',
                     label=u'Véhicule climatisé',
                     nullable=True)
    electronic_toll = Column(db.Boolean,
                             name='electronic_toll',
                             label=u'Véhicule équipé du télépéage',
                             nullable=True)
    gps = Column(db.Boolean,
                 name='gps',
                 label=u'Véhicule équipé d\'un GPS',
                 nullable=True)
    cpam_conventionne = Column(db.Boolean,
                               name='cpam_conventionne',
                               label=u'Conventionné assurance maladie',
                               nullable=True)
    every_destination = Column(db.Boolean,
                               name='every_destination',
                               label=u'Toute destination',
                               nullable=True)
    color = Column(db.String(255),
                   name='color',
                   label='Couleur : ',
                   nullable=True)
    vehicle_id = Column(db.Integer, db.ForeignKey('vehicle.id'))
    UniqueConstraint('vehicle_id', 'added_by', name="uq_vehicle_description")
    _status = Column(Enum(*status_vehicle_description_enum,
                          name='status_taxi_enum'),
                     nullable=True,
                     default='free',
                     name='status')
    nb_seats = Column(
        db.Integer,
        name='nb_seats',
        description=u'Nombre de places assises disponibles pour les voyageurs',
        label=u'Nombre de places')
    __table_args__ = (db.UniqueConstraint('vehicle_id',
                                          'added_by',
                                          name="_uq_vehicle_description"), )

    @property
    def status(self):
        return self._status

    @status.setter
    def status(self, value):
        assert value is None or value == 'None' or value in status_vehicle_description_enum,\
                '{} is not a valid status, (valid statuses are {})'\
                    .format(value, status_vehicle_description_enum)
        self._status = value
        from .taxis import Taxi
        operator = User.query.get(self.added_by)
        for t in Taxi.query.join(Taxi.vehicle,
                                 aliased=True).filter_by(id=self.vehicle_id):
            t.set_avaibility(operator.email, self._status)

    @classmethod
    def to_exclude(cls):
        return list(HistoryMixin.to_exclude()) + ['status']

    @property
    def constructor(self):
        return self.__constructor.name

    @constructor.setter
    def constructor(self, name):
        self.__constructor = Constructor(name)

    @property
    def model(self):
        return self.__model.name

    @model.setter
    def model(self, name):
        self.__model = Model(name)

    @property
    def characteristics(self):
        return VehicleDescription.get_characs(lambda o, f: getattr(o, f), self)

    @staticmethod
    def get_characs(getattr_, obj):
        fields = [
            'special_need_vehicle', 'every_destination', 'gps',
            'electronic_toll', 'air_con', 'pet_accepted', 'bike_accepted',
            'baby_seat', 'wifi', 'tablet', 'dvd_player', 'fresh_drink',
            'amex_accepted', 'bank_check_accepted', 'nfc_cc_accepted',
            'credit_card_accepted', 'luxury'
        ]
        return list(compress(fields, map(lambda f: getattr_(obj, f), fields)))
Ejemplo n.º 4
0
class Vehicle(CacheableMixin, db.Model, AsDictMixin, MarshalMixin,
              FilterOr404Mixin):
    cache_label = 'taxis'
    query_class = query_callable()
    id = Column(db.Integer, primary_key=True)
    licence_plate = Column(db.String(80),
                           label=u'Immatriculation',
                           description=u'Immatriculation du véhicule',
                           unique=True)
    descriptions = db.relationship("VehicleDescription", lazy='joined')

    def __init__(self, licence_plate=None):
        if isinstance(licence_plate, self.__class__):
            self.licence_plate = licence_plate.licence_plate
        else:
            self.licence_plate

    @classmethod
    def marshall_obj(cls, show_all=False, filter_id=False, level=0, api=None):
        if level >= 2:
            return {}
        return_ = super(Vehicle, cls).marshall_obj(show_all,
                                                   filter_id,
                                                   level=level + 1,
                                                   api=api)
        dict_description = VehicleDescription.marshall_obj(show_all,
                                                           filter_id,
                                                           level=level + 1,
                                                           api=api)
        for k, v in dict_description.items():
            dict_description[k].attribute = 'description.{}'.format(k)
        return_.update(dict_description)
        return_.update({
            "model":
            fields.String(attribute="description.model"),
            "constructor":
            fields.String(attribute="description.constructor")
        })
        if not filter_id:
            return_["id"] = fields.Integer()
        return return_

    @property
    def description(self):
        return self.get_description()

    def get_description(self, user=None):
        if not user:
            user = current_user
        returned_description = None
        for description in self.descriptions:
            if description.added_by == user.id:
                returned_description = description
        return returned_description

    @property
    def model(self):
        return self.description.model if self.description else None

    @property
    def constructor(self):
        return self.description.constructor.name if self.description else None

    @property
    def model_year(self):
        return self.description.model_year if self.description else None

    @property
    def engine(self):
        return self.description.engine if self.description else None

    @property
    def horse_power(self):
        return self.description.horse_power if self.description else None

    @property
    def relais(self):
        return self.description.relais if self.description else None

    @property
    def horodateur(self):
        return self.description.horodateur if self.description else None

    @property
    def taximetre(self):
        return self.description.taximetre if self.description else None

    @property
    def date_dernier_ct(self):
        return self.description.date_dernier_ct if self.description else None

    @property
    def date_validite_ct(self):
        return self.description.date_validite_ct if self.description else None

    @property
    def type_(self):
        return self.description.type_ if self.description else None

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

    def __eq__(self, other):
        return self.__repr__() == other.__repr__()

    def __ne__(self, other):
        return not self.__eq__(other)

    @classmethod
    def to_exclude(cls):
        columns = list(
            filter(lambda f: isinstance(getattr(HistoryMixin, f), Column),
                   HistoryMixin.__dict__.keys()))
        columns += ["Vehicle", "vehicle_taxi", "descriptions"]
        return columns
Ejemplo n.º 5
0
class Hail(HistoryMixin, CacheableMixin, db.Model, AsDictMixin, GetOr404Mixin):
    @declared_attr
    def added_by(cls):
        return db.Column(db.Integer, db.ForeignKey('user.id'))

    cache_label = 'hails'
    query_class = query_callable()
    public_fields = [
        'creation_datetime', 'customer_address', 'customer_id', 'customer_lat',
        'customer_lon', 'customer_phone_number', 'id',
        'incident_customer_reason', 'incident_taxi_reason',
        'last_status_change', 'operateur', 'rating_ride', 'rating_ride_reason',
        'reporting_customer', 'reporting_customer_reason', 'status', 'taxi',
        'taxi_phone_number'
    ]

    id = db.Column(db.String, primary_key=True)
    creation_datetime = db.Column(db.DateTime, nullable=False)
    operateur_id = db.Column(db.Integer,
                             db.ForeignKey('user.id'),
                             nullable=True)
    _operateur = db.relationship('User',
                                 primaryjoin=(operateur_id == User.id),
                                 lazy='joined')
    customer_id = db.Column(db.String, nullable=False)
    customer_lon = db.Column(db.Float, nullable=False)
    customer_lat = db.Column(db.Float, nullable=False)
    customer_address = db.Column(db.String, nullable=False)
    customer_phone_number = db.Column(db.String, nullable=False)
    taxi_id = db.Column(db.String, db.ForeignKey('taxi.id'), nullable=False)
    taxi_relation = db.relationship('Taxi', backref="taxi", lazy="joined")
    _status = db.Column(db.Enum(*status_enum_list, name='hail_status'),
                        default='emitted',
                        nullable=False,
                        name='status')
    last_status_change = db.Column(db.DateTime)
    db.ForeignKeyConstraint(
        ['operateur_id', 'customer_id'],
        ['customer.operateur_id', 'customer.id'],
    )
    taxi_phone_number = db.Column(db.String, nullable=True)
    rating_ride = db.Column(db.Integer)
    rating_ride_reason = db.Column(db.Enum(*rating_ride_reason_enum,
                                           name='reason_ride_enum'),
                                   nullable=True)
    incident_customer_reason = db.Column(db.Enum(
        *incident_customer_reason_enum, name='incident_customer_reason_enum'),
                                         nullable=True)
    incident_taxi_reason = db.Column(db.Enum(*incident_taxi_reason_enum,
                                             name='incident_taxi_reason_enum'),
                                     nullable=True)
    # Reporting of the customer by the taxi
    reporting_customer = db.Column(db.Boolean, nullable=True)
    reporting_customer_reason = db.Column(
        db.Enum(*reporting_customer_reason_enum,
                name='reporting_customer_reason_enum'),
        nullable=True)
    initial_taxi_lon = db.Column(db.Float, nullable=True)
    initial_taxi_lat = db.Column(db.Float, nullable=True)
    change_to_sent_to_operator = db.Column(db.DateTime, nullable=True)
    change_to_received_by_operator = db.Column(db.DateTime, nullable=True)
    change_to_received_by_taxi = db.Column(db.DateTime, nullable=True)
    change_to_accepted_by_taxi = db.Column(db.DateTime, nullable=True)
    change_to_accepted_by_customer = db.Column(db.DateTime, nullable=True)
    change_to_declined_by_taxi = db.Column(db.DateTime, nullable=True)
    change_to_declined_by_customer = db.Column(db.DateTime, nullable=True)
    change_to_incident_taxi = db.Column(db.DateTime, nullable=True)
    change_to_incident_customer = db.Column(db.DateTime, nullable=True)
    change_to_timeout_taxi = db.Column(db.DateTime, nullable=True)
    change_to_timeout_customer = db.Column(db.DateTime, nullable=True)
    change_to_failure = db.Column(db.DateTime, nullable=True)

    def __init__(self, *args, **kwargs):
        self.id = str(get_short_uuid())
        self.creation_datetime = datetime.now().isoformat()
        db.Model.__init__(self)
        HistoryMixin.__init__(self)
        super(self.__class__, self).__init__(**kwargs)

    @validates('rating_ride_reason')
    def validate_rating_ride_reason(self, key, value):
        #We need to restrict this to a subset of statuses
        assert value is None or value in rating_ride_reason_enum,\
            'Bad rating_ride_reason\'s value. It can be: {}'.format(
                    rating_ride_reason_enum)
        if current_user.id != self.added_by:
            raise RuntimeError()
        return value

    @validates('incident_customer_reason')
    def validate_incident_customer_reason(self, key, value):
        assert self.status == 'incident_customer', 'Bad status'
        assert value is None or value in incident_customer_reason_enum,\
            'Bad rating_ride_reason\'s value. It can be: {}'.format(
                    incident_customer_reason_enum)
        if current_user.id != self.added_by:
            raise RuntimeError()
        return value

    @validates('incident_taxi_reason')
    def validate_incident_taxi_reason(self, key, value):
        assert self.status == 'incident_taxi', 'Bad status'
        assert value is None or value in incident_taxi_reason_enum,\
            'Bad rating_ride_reason\'s value. It can be: {}'.format(
                    incident_taxi_reason_enum)
        if current_user.id != self.operateur_id:
            raise RuntimeError()
        return value

    @validates('reporting_customer_reason')
    def validate_reporting_customer_reason(self, key, value):
        assert value is None or value in reporting_customer_reason_enum,\
            'Bad reporting_customer_reason\'s value. It can be: {}'.format(
                    reporting_customer_reason_enum)
        if current_user.id != self.operateur_id:
            raise RuntimeError()
        return value

    @validates('reporting_customer')
    def validate_reporting_customer(self, key, value):
        if current_user.id != self.operateur_id:
            raise RuntimeError()
        return value

    @validates('rating_ride')
    def validate_rating_taxi(self, key, value):
        #We need to restrict this to a subset of statuses
        assert 1 <= value <= 5, 'Rating value has to be 1 <= value <= 5'
        return value

    timeouts = {
        'received': (15, 'failure'),
        'sent_to_operator': (10, 'failure'),
        'received_by_operator': (10, 'failure'),
        'received_by_taxi': (30, 'timeout_taxi'),
        'accepted_by_taxi': (20, 'timeout_customer')
    }

    roles_accepted = {
        'received': ['moteur', 'admin'],
        'received_by_taxi': ['operateur', 'admin'],
        'accepted_by_taxi': ['operateur', 'admin'],
        'declined_by_taxi': ['operateur', 'admin'],
        'incident_taxi': ['operateur', 'admin'],
        'incident_customer': ['moteur', 'admin'],
        'accepted_by_customer': ['moteur', 'admin'],
        'declined_by_customer': ['moteur', 'admin'],
    }

    status_required = {
        'sent_to_operator': 'received',
        'received_by_operator': 'received',
        'received_by_taxi': 'received_by_operator',
        'accepted_by_taxi': 'received_by_taxi',
        'declined_by_taxi': 'received_by_taxi',
        'accepted_by_customer': 'accepted_by_taxi',
        'declined_by_customer': 'accepted_by_taxi',
    }

    @property
    def status(self):
        time, next_status = self.timeouts.get(self._status, (None, None))
        if time:
            self.check_time_out(time, next_status)
        return self._status

    @status.setter
    def status(self, value):
        old_status = self._status
        assert value in status_enum_list
        if value == self._status:
            return True
        roles_accepted = self.roles_accepted.get(value, None)
        if roles_accepted:
            perm = Permission(*[RoleNeed(role) for role in roles_accepted])
            if not perm.can():
                raise RuntimeError("You're not authorized to set this status")
        status_required = self.status_required.get(value, None)
        if status_required and self._status != status_required:
            raise ValueError("You cannot set status from {} to {}".format(
                self._status, value))
        self._status = value
        self.status_changed()
        taxi = TaxiM.cache.get(self.taxi_id)
        taxi.synchronize_status_with_hail(self)
        client = influx_db.get_client(current_app.config['INFLUXDB_TAXIS_DB'])
        try:
            client.write_points([{
                "measurement":
                "hails_status_changed",
                "tags": {
                    "added_by": User.query.get(self.added_by).email,
                    "operator": self.operateur.email,
                    "zupc": taxi.ads.zupc.insee,
                    "previous_status": old_status,
                    "status": self._status
                },
                "time":
                datetime.utcnow().strftime('%Y%m%dT%H:%M:%SZ'),
                "fields": {
                    "value": 1
                }
            }])
        except Exception as e:
            current_app.logger.error('Influxdb Error: {}'.format(e))

    def status_changed(self):
        self.last_status_change = datetime.now()
        field = 'change_to_{}'.format(self.status)
        if hasattr(self, field):
            setattr(self, field, self.last_status_change)

    def check_time_out(self, duration, timeout_status):
        if datetime.now() < (self.last_status_change +
                             timedelta(seconds=duration)):
            return True
        self.status = timeout_status
        db.session.commit()
        return False

    def to_dict(self):
        self.check_time_out()
        return self.as_dict()

    @property
    def taxi(self):
        carac = TaxiM.retrieve_caracs(self.taxi_id).get(
            self.operateur.email, None)
        if not carac:
            return {}
        return {
            'position': {
                'lon': carac['lon'],
                'lat': carac['lat']
            },
            'last_update': carac['timestamp'],
            'id': self.taxi_id
        }

    @property
    def operateur(self):
        return User.query.get(self.operateur_id)
Ejemplo n.º 6
0
class Taxi(CacheableMixin, db.Model, HistoryMixin, AsDictMixin, GetOr404Mixin,
           TaxiRedis):
    @declared_attr
    def added_by(cls):
        return Column(db.Integer, db.ForeignKey('user.id'))

    cache_label = 'taxis'
    query_class = query_callable()

    def __init__(self, *args, **kwargs):
        db.Model.__init__(self)
        HistoryMixin.__init__(self)
        kwargs['id'] = kwargs.get('id', None)
        if not kwargs['id']:
            kwargs['id'] = str(get_short_uuid())
        super(self.__class__, self).__init__(**kwargs)
        HistoryMixin.__init__(self)
        TaxiRedis.__init__(self, self.id)

    id = Column(db.String, primary_key=True)
    vehicle_id = db.Column(db.Integer,
                           db.ForeignKey('vehicle.id'),
                           nullable=True)
    vehicle = db.relationship('Vehicle', backref='vehicle_taxi', lazy='joined')
    ads_id = db.Column(db.Integer, db.ForeignKey('ADS.id'), nullable=True)
    ads = db.relationship('ADS', backref='ads', lazy='joined')
    driver_id = db.Column(db.Integer,
                          db.ForeignKey('driver.id'),
                          nullable=True)
    driver = db.relationship('Driver', backref='driver', lazy='joined')

    _ACTIVITY_TIMEOUT = 15 * 60  #Used for dash

    @property
    def rating(self):
        return 4.5

    @property
    def status(self):
        return self.vehicle.description.status

    @status.setter
    def status(self, status):
        self.vehicle.description.status = status
        self.last_update_at = datetime.now()

    def is_free(self, min_time=None):
        return self._is_free(self.vehicle.descriptions,
                             lambda desc: User.query.get(desc.added_by).email,
                             lambda desc: desc.status, min_time)

    def set_free(self):
        #For debugging purposes
        for desc in self.vehicle.descriptions:
            desc.status = 'free'

    @property
    def driver_professional_licence(self):
        return self.driver.professional_licence

    @property
    def vehicle_licence_plate(self):
        return self.vehicle.licence_plate

    @property
    def ads_numero(self):
        return self.ads.numero

    @property
    def driver_insee(self):
        return self.ads.insee

    @property
    def driver_departement(self):
        return self.driver.departement

    map_hail_status_taxi_status = {
        'emitted': 'free',
        'received': 'answering',
        'sent_to_operator': 'answering',
        'received_by_operator': 'answering',
        'received_by_taxi': 'answering',
        'accepted_by_taxi': 'answering',
        'accepted_by_customer': 'oncoming',
        'declined_by_taxi': 'free',
        'declined_by_customer': 'free',
        'incident_customer': 'free',
        'incident_taxi': 'free',
        'timeout_customer': 'free',
        'timeout_taxi': 'free',
        'outdated_customer': 'free',
        'outdated_taxi': 'free',
        'failure': 'free'
    }

    def synchronize_status_with_hail(self, hail):
        description = self.vehicle.get_description(hail.operateur)
        description.status = self.map_hail_status_taxi_status[hail.status]
        self.last_update_at = datetime.now()
        RawTaxi.flush(self.id)
Ejemplo n.º 7
0
class User(CacheableMixin, db.Model, UserMixin, MarshalMixin, FilterOr404Mixin,
           UserBase):
    cache_label = 'users'
    query_class = query_callable()
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role',
                            secondary=roles_users,
                            lazy='joined',
                            query_class=query_callable())
    apikey = db.Column(db.String(36), nullable=False)
    hail_endpoint_production = Column(db.String,
                                      nullable=True,
                                      label=u'Hail endpoint production',
                                      description='Hail endpoint production')
    hail_endpoint_staging = Column(db.String,
                                   nullable=True,
                                   label=u'Hail endpoint staging',
                                   description='Hail endpoint staging')
    hail_endpoint_testing = Column(db.String,
                                   nullable=True,
                                   label=u'Hail endpoint testing',
                                   description='Hail endpoint testing')
    commercial_name = Column(db.String,
                             nullable=True,
                             label='Nom commercial',
                             description='Votre nom commercial')
    phone_number_customer = Column(
        db.String,
        nullable=True,
        label=u'Numéro de téléphone du service client',
        description=u'Numéro de téléphone de support pour les clients')
    phone_number_technical = Column(
        db.String,
        nullable=True,
        label=u'Numéro de téléphone du contact technique',
        description=u'Numéro de téléphone du contact technique')
    email_customer = Column(db.String,
                            nullable=True,
                            label=u'Email du service client',
                            description=u'Email de support pour les clients')
    email_technical = Column(db.String,
                             nullable=True,
                             label=u'Email du contact technique',
                             description=u'Email du contact technique')
    logos = db.relationship('Logo', backref="user", lazy='joined')
    operator_header_name = Column(
        db.String,
        nullable=True,
        label=u'Nom du header http pour l\'authentification',
        description=u"""Cet header sera envoyé lors de la communication
                de l'ODT vers votre serveur""")
    operator_api_key = Column(
        db.String,
        nullable=True,
        label=u'Valeur de la clé d\'api',
        description=u"""Valeur de la clé d'api envoyé par l'ODT
            à votre serveur pour l'authentification.""")

    def __init__(self, *args, **kwargs):
        kwargs['apikey'] = str(uuid.uuid4())
        kwargs['password'] = encrypt_password(kwargs['password'])
        kwargs['active'] = True
        super(self.__class__, self).__init__(*args, **kwargs)