Пример #1
0
class Endorsement(db.Model):
    __tablename__ = 'endorsement'
    id = db.Column(db.BigInteger, nullable=False, unique=True, autoincrement=True, primary_key=True)
    uid = db.Column(db.BigInteger, db.ForeignKey("users.id"), nullable=False, unique=True, index=True)
    total_contacts = db.Column(db.Integer, nullable=False, default=0)
    niubility = db.Column(db.Integer, nullable=False, default=0)
    reliability = db.Column(db.Integer, nullable=False, default=0)

    @staticmethod
    def add(uid):
        # When create a new user, must create a endorsement accordingly
        endorsement = Endorsement(uid=uid)
        db.session.add(endorsement)
        db.session.commit()

    @staticmethod
    def find_by_uid(uid):
        return Endorsement.query.filter(Endorsement.uid == uid).one_or_none()

    @staticmethod
    def update_niubility_count(uid, cnt):
        Endorsement._update_count(uid, "niubility", cnt)

    @staticmethod
    def update_reliability_count(uid, cnt):
        Endorsement._update_count(uid, "reliability", cnt)

    @staticmethod
    def update_total_contacts_count(uid, cnt):
        Endorsement._update_count(uid, "total_contacts", cnt)

    @staticmethod
    def _update_count(uid, attr, cnt):
        if abs(cnt) != 1:
            # cnt must be 1 or -1
            return
        endorsement = Endorsement.query.filter(Endorsement.uid == uid).one_or_none()
        if endorsement:
            count = getattr(endorsement, attr) + cnt
            if count >= 0:
                setattr(endorsement, attr, count)
                db.session.commit()

    def to_dict(self):
        return {
            "total_contacts": self.total_contacts,
            "niubility_count": self.niubility,
            "reliability_count": self.reliability
        }
Пример #2
0
class Organization(db.Model):
    __tablename__ = 'organizations'

    id = db.Column(db.BigInteger,
                   nullable=False,
                   unique=True,
                   autoincrement=True,
                   primary_key=True)
    name = db.Column(db.String(255), unique=True, index=True)
    icon = db.Column(db.TEXT)
    verified = db.Column(db.Boolean)
    alias = db.Column(db.String(255))
    info = db.Column(db.Text)
    created_at = db.Column(db.DateTime,
                           nullable=False,
                           default=datetime.utcnow)

    @staticmethod
    def add(new_one):
        db.session.add(new_one)
        db.session.commit()

    @staticmethod
    def update():
        db.session.commit()

    @staticmethod
    def find(id):
        return Organization.query.filter(Organization.id == id).one_or_none()

    @staticmethod
    def find_by_name(name):
        return Organization.query.filter(
            Organization.name == name).one_or_none()

    @staticmethod
    def like(keyword, count):
        like_query = "%{}%".format(keyword)
        return Organization.query \
            .filter(Organization.name.like(like_query)) \
            .offset(0).limit(count).all()

    def to_dict(self):
        return {
            "id": encode_id(self.id),
            "name": self.name,
            "icon": self.icon,
            "alias": self.alias
        }
Пример #3
0
class Feed(db.Model):
    id = db.Column(db.BigInteger, nullable=False, unique=True, autoincrement=True, primary_key=True)
    uid = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False)
    user = db.relationship("colleague.models.user.User", lazy="selectin")
    type = db.Column(db.SMALLINT, nullable=False, default=0)
    # images are ids of table 'image.id'
    images = db.Column(db.JSON, nullable=False, comment=u"图片id")
    text = db.Column(db.TEXT, nullable=False)
    like_count = db.Column(db.Integer, nullable=False, default=0)
    comment_count = db.Column(db.Integer, nullable=False, default=0)
    create_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)

    @staticmethod
    def find_by_cursor(last_id, size):
        if last_id:
            feeds = Feed.query \
                .filter(Feed.id < last_id) \
                .order_by(db.desc(Feed.id)).offset(0).limit(size).all()
        else:
            feeds = Feed.query \
                .order_by(db.desc(Feed.id)).offset(0).limit(size).all()
        return feeds

    @staticmethod
    def find(id):
        return Feed.query.filter(Feed.id == id).one_or_none()

    @staticmethod
    def add(obj):
        db.session.add(obj)
        db.session.commit()

    def to_dict(self):
        return {
            'id': encode_id(self.id),
            'user': self.user.to_dict(),
            'type': self.type,
            'text': self.text,
            'like_count': self.like_count,
            'comment_count': self.comment_count,
            'create_at': datetime_to_timestamp(self.create_at)
        }
Пример #4
0
class FeedLike(db.Model):
    id = db.Column(db.BigInteger, nullable=False, unique=True, autoincrement=True, primary_key=True)
    uid = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False)
    feed_id = db.Column(db.BigInteger, db.ForeignKey('feed.id'), nullable=False)
    status = db.Column(db.SMALLINT, nullable=False, default=0)
    created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    db.UniqueConstraint(uid, feed_id)

    def update(self):
        db.session.commit()

    @staticmethod
    def find_by_uid(uid, feed_id):
        return FeedLike.query \
            .filter(FeedLike.uid == uid, FeedLike.feed_id == feed_id) \
            .one_or_none()

    @staticmethod
    def add(obj):
        db.session.add(obj)
        db.session.commit()
Пример #5
0
class Image(db.Model):
    id = db.Column(db.BigInteger,
                   nullable=False,
                   unique=True,
                   autoincrement=True,
                   primary_key=True)
    uid = db.Column(db.BigInteger, db.ForeignKey("users.id"), nullable=False)
    path = db.Column(db.String(255), unique=True)
    width = db.Column(db.Integer)
    height = db.Column(db.Integer)
    size = db.Column(db.Integer)
    location = db.Column(db.SMALLINT,
                         default=0,
                         comment="0:local, 1: aliyun oss")
    info = db.Column(db.String(255))
    created_at = db.Column(db.DateTime,
                           nullable=False,
                           default=datetime.utcnow)

    @staticmethod
    def add(obj):
        db.session.add(obj)
        db.session.commit()

    @staticmethod
    def find(id):
        return Image.query.filter(Image.id == id).one_or_none()

    @staticmethod
    def find_by_ids(ids):
        images = Image.query.filter(Image.id.in_(ids)).all()
        image_dict = list_to_dict(images, "id")
        ordered_images = []
        for id in ids:
            image = image_dict.get(id)
            if image:
                ordered_images.append(image)
        return ordered_images

    @staticmethod
    def find_by_path(path):
        return Image.query.filter(Image.path == path).one_or_none()

    @staticmethod
    def path_to_url(path, location=MediaLocation.AliyunOSS):
        if location == MediaLocation.AliyunOSS:
            return os.path.join(os.getenv("SERVER_NAME"), path)

    def to_dict(self):
        return {
            "id": Image.encode_id(self.id),
            "url": Image.path_to_url(self.path),
            "width": self.width,
            "height": self.height,
        }

    @staticmethod
    def encode_id(id):
        return encode_id("image" + str(id))

    @staticmethod
    def decode_id(id):
        return int(decode_id(id)[5:])
Пример #6
0
class User(db.Model):
    __tablename__ = "users"
    id = db.Column(db.BigInteger, nullable=False, unique=True, autoincrement=True, primary_key=True)
    mobile = db.Column(db.String(50), nullable=False, unique=True, index=True)
    password_hash = db.Column(db.String(512), nullable=False)
    user_name = db.Column(db.String(256))
    gender = db.Column(db.Integer)
    avatar = db.Column(db.String(1024))
    colleague_id = db.Column(db.String(255), unique=True, nullable=True, comment=u'同事id')
    status = db.Column(db.Integer)
    title = db.Column(db.String(1024), nullable=True)
    company_id = db.Column(db.BigInteger, db.ForeignKey("organizations.id"), nullable=True)
    company = db.relationship("colleague.models.work.Organization")
    endorsement = db.relationship("Endorsement", uselist=False)
    created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    last_login_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)

    @staticmethod
    def search_users(search_string):
        if search_string.isdigit():
            mobile = search_string
            user = User.find_by_mobile(mobile)
            if user:
                return [user.to_dict()]
        else:
            users = User.query.filter(db.or_(User.user_name == search_string,
                                             User.colleague_id == search_string))
            return [user.to_dict() for user in users]

    @staticmethod
    def find(id):
        return User.query.filter(User.id == id).one_or_none()

    @staticmethod
    def find_by_mobile(mobile):
        return User.query.filter(User.mobile == mobile).one_or_none()

    @staticmethod
    def find_by_ids(ids):
        return User.query.filter(User.id.in_(ids)).all()

    @staticmethod
    def add(mobile, password):
        user = User(mobile=mobile, status=UserStatus.Confirmed)
        user.hash_password(password)
        db.session.add(user)
        db.session.commit()
        return user

    def update_user(self, **kwargs):
        if not kwargs:
            return

        for key, value in kwargs.iteritems():
            if key in ["password", "user_name", "gender", "colleague_id", "avatar"] and value:
                if key == 'password':
                    self.hash_password(value)
                if key == 'colleague_id':
                    if self.colleague_id:
                        st_raise_error(ErrorCode.COLLEAGUE_ID_ALREADY_SET)
                    exist_colleague_id = User.query.filter(User.colleague_id == value).one_or_none()
                    if exist_colleague_id:
                        st_raise_error(ErrorCode.ALREADY_EXIST_COLLEAGUE_ID)
                    self.colleague_id = value
                else:
                    setattr(self, key, value)

        db.session.commit()
        return self.to_dict()

    def update_title(self, company_id, title):
        self.company_id = company_id
        self.title = title
        db.session.commit()

    def hash_password(self, password):
        self.password_hash = pwd_context.encrypt(password)

    def verify_password(self, password):
        return pwd_context.verify(password, self.password_hash)

    def login_on(self, device_id):
        self.last_login_at = arrow.utcnow().naive
        self.status = UserStatus.Confirmed
        db.session.commit()

        payload = self._generate_token_metadata(device_id)
        access_token = create_access_token(identity=payload)
        refresh_token = create_refresh_token(identity=payload)
        return {
            'access_token': access_token,
            'refresh_token': refresh_token
        }

    def _generate_token_metadata(self, device_id):
        return {
            'user_id': encode_id(self.id),
            'device_id': device_id,
            'timestamp': arrow.get(self.last_login_at).timestamp
        }

    def verify_token_metadata(self, metadata, device_id):
        expected = self._generate_token_metadata(device_id)
        return metadata == expected

    def is_available(self):
        return self.status not in [UserStatus.Blocked, UserStatus.Deleted]

    def is_logged_out(self):
        return self.status == UserStatus.Logout

    def logout(self):
        self.status = UserStatus.Logout
        db.session.commit()

    @property
    def avatar_url(self):
        return os.path.join(settings["SERVER_NAME"], self.avatar) if self.avatar else ""

    def to_dict_with_mobile(self):
        d = self.to_dict()
        d['mobile'] = self.mobile
        return d

    def to_dict(self):
        return {
            "id": encode_id(self.id),
            "user_name": self.user_name,
            "gender": self.gender,
            "avatar": self.avatar_url,
            "colleague_id": self.colleague_id,
            "title": self.title,
            "company": self.company.to_dict() if self.company else None,
            "endorsement": self.endorsement.to_dict() if self.endorsement else None
        }
Пример #7
0
class UserEndorse(db.Model):
    __tablename__ = 'user_endorse'
    id = db.Column(db.BigInteger, nullable=False, unique=True, autoincrement=True, primary_key=True)
    uid = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False, comment=u"to uid")
    from_uid = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False, comment=u"from uid")
    fromUser = db.relationship('colleague.models.user.User', foreign_keys=from_uid, lazy="selectin")
    type = db.Column(db.SMALLINT, nullable=False, comment=u"1: 大牛, 2: 靠谱")
    status = db.Column(db.SMALLINT, nullable=False, comment=u"0: 开启, 1: 取消")
    create_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    update_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    db.UniqueConstraint(uid, from_uid, type)

    @staticmethod
    def find_by_from_uid(uid, from_uid, type):
        return UserEndorse.query \
            .filter(UserEndorse.uid == uid,
                    UserEndorse.from_uid == from_uid,
                    UserEndorse.type == type,
                    UserEndorse.status == EndorseStatus.Supported) \
            .one_or_none()

    @staticmethod
    def find_by_cursor(uid, type, latest_id, size):
        if latest_id:
            return UserEndorse.query \
                .filter(UserEndorse.uid == uid,
                        UserEndorse.type == type,
                        UserEndorse.status == EndorseStatus.Supported,
                        UserEndorse.id > latest_id) \
                .order_by(db.desc(UserEndorse.id)) \
                .offset(0).limit(size).all()
        else:
            return UserEndorse.query \
                .filter(UserEndorse.uid == uid,
                        UserEndorse.type == type,
                        UserEndorse.status == EndorseStatus.Supported) \
                .order_by(db.desc(UserEndorse.id)) \
                .offset(0).limit(size).all()

    def to_dict(self):
        return {
            'id': encode_id(self.id),
            'from_user': self.fromUser.to_dict(),
            'type': self.type,
            'create_at': datetime_to_timestamp(self.create_at)
        }

    @staticmethod
    def update(uid, from_uid, type, status):
        endorse = UserEndorse.query.filter(UserEndorse.uid == uid,
                                           UserEndorse.from_uid == from_uid,
                                           UserEndorse.type == type).one_or_none()
        endorse_status = EndorseStatus.Supported if status else EndorseStatus.Removed
        if endorse and endorse.status == endorse_status:
            # duplicate request
            return
        if endorse_status == EndorseStatus.Removed and not endorse:
            # endorse must be existed when u tries to remove
            return
        if not endorse:
            endorse = UserEndorse(uid=uid, from_uid=from_uid, type=type)
            db.session.add(endorse)
        endorse.status = endorse_status
        endorse.update_at = arrow.utcnow().naive
        cnt = 1 if endorse_status == EndorseStatus.Supported else -1
        if type == EndorseType.Niubility:
            Endorsement.update_niubility_count(uid, cnt)
        elif type == EndorseType.Reliability:
            Endorsement.update_reliability_count(uid, cnt)
        db.session.commit()
Пример #8
0
class EndorseComment(db.Model):
    __tablename__ = 'endorse_comment'
    id = db.Column(db.BigInteger, nullable=False, unique=True, autoincrement=True, primary_key=True)
    uid = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False, comment=u"to uid")
    # user = db.relationship('colleague.models.user.User', foreign_keys=[uid])
    from_uid = db.Column(db.BigInteger, db.ForeignKey('users.id'), nullable=False, comment=u"from uid")
    from_user = db.relationship('colleague.models.user.User', foreign_keys=from_uid, lazy="selectin")
    text = db.Column(db.TEXT, nullable=True)
    status = db.Column(db.SMALLINT, nullable=False, default=0, comment=u'0: supported, 1: removed')
    create_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    update_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    db.UniqueConstraint(uid, from_uid)

    @staticmethod
    def update(uid, from_uid, text):
        """
        Update the endorse comment, if text is empty, means user removed the
        endorse comment
        :param uid:
        :param from_uid:
        :param text: comment
        :return:
        """
        comment = EndorseComment.query \
            .filter(EndorseComment.uid == uid,
                    EndorseComment.from_uid == from_uid).one_or_none()
        if not comment:
            comment = EndorseComment(uid=uid, from_uid=from_uid)
            db.session.add(comment)
        comment.update_at = arrow.utcnow().naive
        if text is not None:
            text = text.strip()
        comment.text = text
        comment.status = EndorseStatus.Supported if len(text) > 0 else EndorseStatus.Removed
        db.session.commit()

    @staticmethod
    def find_by_from_uid(uid, from_uid):
        return EndorseComment.query \
            .filter(EndorseComment.uid == uid,
                    EndorseComment.from_uid == from_uid) \
            .one_or_none()

    @staticmethod
    def find_latest_by_uid(uid):
        return EndorseComment.query \
            .filter(EndorseComment.uid == uid,
                    EndorseComment.status == EndorseStatus.Supported) \
            .order_by(db.desc(EndorseComment.id)) \
            .first()

    @staticmethod
    def find_by_cursor(uid, latest_id, size):
        if latest_id:
            return EndorseComment.query \
                .filter(EndorseComment.uid == uid,
                        EndorseComment.status == EndorseStatus.Supported,
                        EndorseComment.id > latest_id) \
                .order_by(db.desc(EndorseComment.id)) \
                .offset(0).limit(size).all()
        else:
            return EndorseComment.query \
                .filter(EndorseComment.uid == uid,
                        EndorseComment.status == EndorseStatus.Supported) \
                .order_by(db.desc(EndorseComment.id)) \
                .offset(0).limit(size).all()

    def to_dict(self):
        return {
            'id': encode_id(self.id),
            'from_user': self.from_user.to_dict(),
            'text': self.text,
            'update_at': datetime_to_timestamp(self.update_at)
        }
Пример #9
0
class Contact(db.Model):
    __tablename__ = 'contact'
    id = db.Column(db.BigInteger,
                   nullable=False,
                   unique=True,
                   autoincrement=True,
                   primary_key=True)
    uidA = db.Column(db.BigInteger, name="uid_a", nullable=False)
    uidB = db.Column(db.BigInteger, name="uid_b", nullable=False)
    status = db.Column(db.Integer,
                       nullable=False,
                       comment=u'0: 已删除, 1: 正常',
                       default=1)
    type = db.Column(db.Integer, nullable=False, comment=u'1: 自己添加, 2: 熟人推荐')
    created_at = db.Column(db.DateTime,
                           nullable=False,
                           default=datetime.utcnow,
                           comment=u'第一次添加时间')
    updated_at = db.Column(db.DateTime,
                           nullable=False,
                           default=datetime.utcnow,
                           comment=u'更新时间')
    removed_at = db.Column(db.DateTime, nullable=True)

    @staticmethod
    def find_by_cursor(from_uid, last_update_date, size):
        if last_update_date:
            contacts = Contact.query \
                .filter((Contact.uidA == from_uid) | (Contact.uidB == from_uid),
                        Contact.status == ContactStatus.Connected,
                        Contact.updated_at < last_update_date) \
                .order_by(db.desc(Contact.updated_at)).offset(0).limit(size).all()
        else:
            contacts = Contact.query \
                .filter((Contact.uidA == from_uid) | (Contact.uidB == from_uid),
                        Contact.status == ContactStatus.Connected) \
                .order_by(db.desc(Contact.updated_at)).offset(0).limit(size).all()
        return contacts

    @staticmethod
    def add(uidA, uidB, type):
        result = False
        contact = Contact.find_by_uid(uidA, uidB)
        if contact is None:
            uid_a, uid_b = Contact._ordered_uid(uidA, uidB)
            contact = Contact(uidA=uid_a, uidB=uid_b, type=type)
            db.session.add(contact)
            result = True
        # 由于联系人的请求有两种来源:自己添加和朋友推荐
        # 这两种情况可能同时会存在,但是以用户添加为主
        if type == ContactRequestType.Added:
            contact.type = ContactRequestType.Added
        contact.status = ContactStatus.Connected
        contact.updated_at = arrow.utcnow().naive
        db.session.commit()
        return result

    @staticmethod
    def find_by_uid(uidA, uidB):
        uid_a, uid_b = Contact._ordered_uid(uidA, uidB)
        return Contact.query.filter(Contact.uidA == uid_a,
                                    Contact.uidB == uid_b).one_or_none()

    @staticmethod
    def _ordered_uid(a, b):
        return (a, b) if a < b else (b, a)
Пример #10
0
class ContactRequest(db.Model):
    """
    关系请求。
    关系请求目前分为两种: 1, 用户主动添加. 2: 用户推荐认识
    uid:  关系发起者,如果是主动添加,则为主动添加的用户。如果是推荐,则为推荐人
    uidA: 关系的一方,如果是主动添加,则为主动添加人uid, 可以理解为A 把"自己"推荐给 B。如果是推荐,则为被推荐人
    uidB: 关系的一方,关系的接受者
    """
    __tablename__ = 'contact_request'
    id = db.Column(db.BigInteger,
                   nullable=False,
                   unique=True,
                   autoincrement=True,
                   primary_key=True)
    # 如果用户主动添加,uidA = 用户id,可以理解为用户把自己推荐给 B
    # 如果用户推荐 A 给 B, 就按照字面解释
    uid = db.Column(db.BigInteger,
                    db.ForeignKey("users.id"),
                    nullable=False,
                    comment=u"请求发起者")
    uidA = db.Column(db.BigInteger,
                     db.ForeignKey("users.id"),
                     name="uid_a",
                     nullable=False,
                     comment=u"被推荐人")
    uidB = db.Column(db.BigInteger,
                     db.ForeignKey("users.id"),
                     name="uid_b",
                     nullable=False,
                     comment=u"被添加人")
    type = db.Column(db.Integer, nullable=False, comment=u"1:添加,2:推荐")
    comment = db.Column(db.Text, nullable=True, comment=u'如果由第三方推荐,推荐语')
    status = db.Column(db.Integer,
                       nullable=False,
                       default=0,
                       comment=u"0:pending, 1: 接受, 2:拒绝")
    created_at = db.Column(db.DateTime,
                           nullable=False,
                           default=datetime.utcnow)
    end_at = db.Column(db.DateTime, comment=u"接受/拒绝 时间")

    def to_dict(self):
        return {
            "id": encode_id(self.id),
            "user": self.user.to_dict(),
            "userA": self.userA.to_dict(),
            "userB": self.userB.to_dict(),
            "type": self.type,
            "status": self.status,
            "comment": self.comment,
            "create_at": datetime_to_timestamp(self.created_at)
        }

    @staticmethod
    def find_by_cursor(uid, last_id, size=20):
        if last_id:
            requests = ContactRequest.query \
                .filter(ContactRequest.uidB == uid) \
                .filter((ContactRequest.status == ContactRequestStatus.Accepted) | (
                    ContactRequestStatus == ContactRequestStatus.Pending)) \
                .filter(ContactRequest.id < last_id) \
                .order_by(db.desc(ContactRequest.id)) \
                .offset(0) \
                .limit(size).all()
        else:
            requests = ContactRequest.query \
                .filter(ContactRequest.uidB == uid) \
                .filter((ContactRequest.status == ContactRequestStatus.Accepted) | (
                    ContactRequest.status == ContactRequestStatus.Pending)) \
                .order_by(db.desc(ContactRequest.id)) \
                .offset(0) \
                .limit(size).all()
        return requests

    @staticmethod
    def add(uid, uidA, uidB, comment):
        result = False
        contact = Contact.find_by_uid(uidA, uidB)
        if contact and contact.status == ContactStatus.Connected:
            st_raise_error(ErrorCode.RELATIONSHIP_ALREADY_CONNECTED)

        type = ContactRequestType.Added if uid == uidA else ContactRequestType.Recommended
        if type == ContactRequestType.Added:
            # the two user must have been in at least one same company if add directly.
            work_experiences_A = set(WorkExperience.get_company_ids(uidA))
            work_experiences_B = set(WorkExperience.get_company_ids(uidB))
            if len(work_experiences_A & work_experiences_B) == 0:
                st_raise_error(ErrorCode.ADD_RELATIONSHIP_NOT_COMMON_COMPANY)

        # TODO: 过期时间
        request = ContactRequest.query.filter(
            ContactRequest.uid == uid,
            ContactRequest.uidA == uidA,
            ContactRequest.uidB == uidB,
        ).one_or_none()

        if request is None:
            request = ContactRequest(uid=uid,
                                     uidA=uidA,
                                     uidB=uidB,
                                     type=type,
                                     comment=comment,
                                     status=ContactRequestStatus.Pending)
            db.session.add(request)
            result = True
        db.session.commit()
        return result
Пример #11
0
class WorkExperience(db.Model):
    __tablename__ = "work_experience"
    id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
    uid = db.Column(db.BigInteger, index=True, nullable=False)
    start_year = db.Column(db.SMALLINT, nullable=False, comment=u'开始-年')
    start_month = db.Column(db.SMALLINT, nullable=False, comment=u'开始-月')
    end_year = db.Column(db.SMALLINT, nullable=False, comment=u'2999表示至今')
    end_month = db.Column(db.SMALLINT, nullable=True)
    title = db.Column(db.String(255), nullable=False, comment=u'职位')
    company_id = db.Column(db.BigInteger,
                           db.ForeignKey("organizations.id"),
                           nullable=False)
    company = db.relationship("Organization")
    status = db.Column(db.SMALLINT,
                       nullable=False,
                       default=0,
                       comment=u"0: normal, 1: deleted")
    create_date = db.Column(db.DateTime,
                            nullable=False,
                            default=datetime.utcnow)
    update_date = db.Column(db.DateTime,
                            nullable=False,
                            default=datetime.utcnow)
    delete_date = db.Column(db.DateTime,
                            nullable=False,
                            default=datetime.utcnow)

    @staticmethod
    def add(new_one):
        db.session.add(new_one)
        db.session.commit()

    def update(self):
        db.session.commit()

    @staticmethod
    def find_by_uid_id(uid, id):
        return WorkExperience.query.filter(
            WorkExperience.id == id, WorkExperience.uid == uid).one_or_none()

    @staticmethod
    def find_all_for_user(uid):
        return WorkExperience.query.filter(
            WorkExperience.uid == uid,
            WorkExperience.status == WorkExperienceStatus.Normal).all()

    @staticmethod
    def get_company_ids(uid):
        return [
            _[0] for _ in WorkExperience.query.with_entities(
                db.distinct(WorkExperience.company_id)).filter(
                    WorkExperience.uid == uid, WorkExperience.status ==
                    WorkExperienceStatus.Normal).all()
        ]

    @staticmethod
    def delete(uid, id):
        we = WorkExperience.find_by_uid_id(uid, id)
        if we:
            we.status = WorkExperienceStatus.Deleted
            we.delete_date = datetime.utcnow()
            db.session.commit()

    def to_dict(self):
        return {
            "id": encode_id(self.id),
            "start_year": self.start_year,
            "start_month": self.start_month,
            "end_year": self.end_year,
            "end_month": self.end_month,
            "title": self.title,
            "company": self.company.to_dict()
        }