Ejemplo n.º 1
0
class City(db.Document):
    city_id = db.IntField()
    district_id = db.ObjectIdField()
    state_id = db.ObjectIdField()
    title = db.DictField()
    code = db.StringField(max_lenght=255)
    ward_count = db.IntField(default=0)
    population_bucket = db.IntField()
    population = db.IntField()
    census_code = db.IntField()
    coordinates = db.PointField()

    meta = {
        'collection':
        'cities',
        'indexes': [{
            'fields': ['city_id'],
            'unique': True,
            'name': 'cities_city_id_unique',
        }, {
            'fields': ['state_id'],
            'name': 'cities_state_id_index',
        }, {
            'fields': ['district_id'],
            'name': 'cities_district_id_index',
        }, {
            'fields': ['title.*'],
            'name': 'cities_title_index',
        }]
    }
Ejemplo n.º 2
0
class CivicAgency(db.Document):
    civic_agency_id = db.IntField()
    city_id = db.IntField()
    district_id = db.ObjectIdField()
    state_id = db.ObjectIdField()
    title = db.DictField()

    meta = {
        'collection':
        'civic_agencies',
        'indexes': [{
            'fields': ['civic_agency_id'],
            'unique': True,
            'name': 'civic_agencies_civic_agency_id_id_unique',
        }, {
            'fields': ['district_id'],
            'name': 'civic_agencies_district_id_index',
        }, {
            'fields': ['state_id'],
            'name': 'civic_agencies_state_id_index',
        }, {
            'fields': ['city_id'],
            'name': 'civic_agencies_city_id_index',
        }, {
            'fields': ['title.*'],
            'name': 'civic_agencies_title_index',
        }]
    }
Ejemplo n.º 3
0
class Message(db.Document):

    from_user = db.ReferenceField(User, db_field="fu", reverse_delete_rule=CASCADE)
    to_user = db.ReferenceField(User, db_field="tu", default=None, reverse_delete_rule=CASCADE)
    post = db.StringField(db_field="pt", max_length=1024)
    live = db.BooleanField(db_field="l", default=None)
    create_date = db.LongField(db_field="c", default=now())
    images = db.ListField(db_field="is", default=None)
    parent = db.ObjectIdField(db_field="p", default=None)
    message_type = db.IntField(db_field="mt", default=POST, choices=MESSAGE_TYPE)

    @property
    def likes(self):
        return Message.objects.filter(parent=self.id, message_type=LIKE).order_by("-create_date")

    @property
    def comments(self):
        return Message.objects.filter(parent=self.id, message_type=COMMENT).order_by("create_date")

    @property
    def text_linkified(self):
        return linkify_text(self.post)

    @property
    def human_timestamp(self):
        return ms_stamp_humanize(self.create_date)

    def post_image_src(self, images_time_stamp, size):
        if self.images:
            profile_img = join_path(STATIC_IMAGE_URL, 'posts', "{}.{}.{}.png".format(self.id, images_time_stamp, size))
            return profile_img.replace("\\", '/') # mostly for windows because windows uses a black slash to save.

    meta = {
        'indexes': [("from_user", "to_user", "-create_date", "message_type", "parent", "live")]
    }
Ejemplo n.º 4
0
class OrderStatus(db.Document):
    """"""
    meta = {
        'db_alias': 'db_order',
        'indexes': ['user_id'],
    }
    user_id = db.ObjectIdField(required=True)
    orders = db.ListField(db.ReferenceField('Order'))
    items = db.ListField(db.IntField())
    total = db.FloatField(default=0)
    received = db.FloatField(default=0)
    num_orders = db.IntField(default=0)
    num_unpaid = db.IntField(default=0)
    num_waiting = db.IntField(default=0)

    def clean(self):
        for field in ('total', 'received', 'num_orders', 'num_unpaid',
                      'num_waiting'):
            if getattr(self, field, 0) < 0:
                setattr(self, field, 0)

    @classmethod
    def by_user(cls, user_id):
        cls.objects(user_id=user_id).update_one(set__user_id=user_id,
                                                upsert=True)
        return cls.objects(user_id=user_id).first()
Ejemplo n.º 5
0
class ReviewPoint(db.Document):
    PROS_ID = 1
    CONS_ID = 0

    content = db.StringField()
    role = db.BooleanField()
    parent = db.ObjectIdField()
class BlackListToken(db.Document):
    """
    Document to store blacklisted/invalid auth tokens
    """

    _id = db.ObjectIdField()
    token = db.StringField()
    blacklisted_on = db.StringField(default=util.get_current_time())

    meta = {'collection': app.config.get('BLACKLISTED_TOKEN_COLLECTION')}

    def __init__(self, token, *args, **kwargs):
        super(db.Document, self).__init__(*args, **kwargs)
        self.token = token
        self.blacklisted_on = util.get_current_time()

    def blacklist(self, *args, **kwargs):
        """
        Persist Blacklisted token in the database
        :return:
        """
        super(BlackListToken, self).save(*args, **kwargs)

    @staticmethod
    def check_blacklist(token):
        """
        Check to find out whether a token has already been blacklisted.
        :param token: Authorization token
        :return:
        """
        response = BlackListToken.objects(token=token).first()
        if response:
            return True
        return False
Ejemplo n.º 7
0
class Complaint(db.Document):
    name = db.StringField(requiered=True)
    place = db.StringField(requiered=True)
    location = db.PointField(required=True)
    complaint_photo = db.StringField()
    description = db.StringField(required=True)
    complainer = db.ObjectIdField(requiered=True)
    cancel = db.BooleanField(default=False)
    follow = db.ListField(db.ReferenceField(User))
Ejemplo n.º 8
0
class RedPacketCollectLog(db.Document):
    STATUS_SUCCESS = 0
    STATUS_FAIL = 1
    OPTIONS_STATUS = collections.OrderedDict([(STATUS_SUCCESS, '成功'),
                                              (STATUS_FAIL, '失败')])
    _id = db.ObjectIdField()
    redpacket_id = db.ObjectIdField()
    open_id = db.StringField(max_length=64)
    rp_log_id = db.StringField(max_length=64, default='')
    status = db.IntField(choices=OPTIONS_STATUS.iteritems())

    create_time = db.DateTimeField()

    meta = {
        'db_alias': 'default',
        'collection': 'rp_collect_log',
        'id_field': '_id',
    }
Ejemplo n.º 9
0
class RedPacketLog(db.Document):
    STATUS_UN = 0
    STATUS_DONE = 1
    OPTIONS_STATUS = collections.OrderedDict([(STATUS_UN, '未领取'),
                                              (STATUS_DONE, '已领取')])

    _id = db.ObjectIdField()
    redpacket_id = db.ObjectIdField()
    open_id = db.StringField(max_length=64)
    value = db.IntField()
    status = db.IntField(choices=OPTIONS_STATUS.iteritems(), default=0)

    last_modify = db.DateTimeField()

    meta = {
        'db_alias': 'default',
        'collection': 'redpacket_log',
        'id_field': '_id',
    }
Ejemplo n.º 10
0
class Diary(db.Document):
    user = db.ObjectIdField(User)
    timestamp = db.DateTimeField(required=True)
    diary = db.DictField(db.AnythingField(), required=True)

    def getAll(self):
        return Diary.query.all()

    def getAllByUniqueID(self,
                         uniqueID,
                         from_datetime=None,
                         until_datetime=None):
        query = db.session.query(Diary)

        query.filter(Diary.user == User().query.filter(
            User.uniqueID == uniqueID).first().mongo_id)

        if from_datetime is not None:
            query.filter(Diary.timestamp >= from_datetime)

        if until_datetime is not None:
            query.filter(Diary.timestamp <= until_datetime)

        return query.all()

    def getByUniqueIDAndID(self, uniqueID, _id):
        return Diary.query.filter(
            Diary.user == User().query.filter(
                User.uniqueID == uniqueID).first().mongo_id,
            Diary.mongo_id == _id).first()

    def addByUniqueID(self, uniqueID, diary):
        self.user = User().query.filter(
            User.uniqueID == uniqueID).first().mongo_id
        self.timestamp = datetime.utcnow()
        self.diary = diary
        self.save()
        return True

    def updateByUniqueIDAndID(self, uniqueID, _id, diary):
        Diary.query.filter(
            Diary.user == User().query.filter(
                User.uniqueID == uniqueID).first().mongo_id,
            Diary.mongo_id == _id).set(diary=diary,
                                       timestamp=datetime.utcnow()).execute()
        return True

    def serialize(self):
        d = {
            "id": str(self.mongo_id),
            "timestamp": self.timestamp.isoformat(),
            "diary": self.diary
        }

        return d
Ejemplo n.º 11
0
Archivo: user.py Proyecto: ws999/wx-app
class User(db.Document, ExtUserMixin):
    OPTIONS_GENDER = collections.OrderedDict([
        ('UNKNOWN', '未设置'),
        ('MAN', '男'),
        ('WOMAN', '女'),
    ])
    _id = db.ObjectIdField()
    open_id = db.StringField(max_length=64)
    union_id = db.StringField(max_length=64)
    nickname = db.StringField(max_length=64)

    avatar = db.StringField(max_length=256)
    gender = db.StringField(max_length=16,
                            choices=OPTIONS_GENDER.iteritems(),
                            default='UNKNOWN')  # 性别

    province = db.StringField(max_length=64)
    city = db.StringField(max_length=64)
    intro = db.StringField()

    is_active = db.BooleanField()

    create_time = db.DateTimeField()

    meta = {
        'db_alias': 'default',
        'collection': 'user',
        'id_field': '_id',
    }

    @classmethod
    def create_user(cls, open_id, union_id):
        u = cls.objects.filter(open_id=open_id, union_id=union_id).first()
        if u: return -2
        user = cls(open_id=open_id,
                   union_id=union_id,
                   is_active=True,
                   create_time=datetime.datetime.now())
        r = cls.objects.insert(user)
        if r: return r
        logger.error(msg='insert user err:%s_%s' % (open_id, union_id))

    @property
    def info(self):
        data = self._data
        return data

    @property
    def capital(self):
        capital = Capital.objects.filter(open_id=self.open_id).first()
        return 0 if not capital else capital.value

    def get_operator(self):
        return UserOperator(self, self.__class__)
Ejemplo n.º 12
0
class TransferOrderCode(db.Document):
    """"""
    order_id = db.ObjectIdField()
    code = db.StringField()

    @classmethod
    def set_order(cls, order_id):
        code = random.randint(100000, 999999)
        cls.objects(order_id=order_id).update_one(set__order_id=order_id,
                                                  set__code=code,
                                                  upsert=True)
Ejemplo n.º 13
0
class AnalysisModel(db.DynamicDocument):
    question_num = db.IntField(min_value=0, default=-1)
    exam_id = db.StringField(max_length=32)
    question_id = db.StringField(max_length=32)
    score_detail = db.FloatField(default=0, min_value=0)
    score_key = db.FloatField(default=0, min_value=0)
    voice_features = db.DictField(default={})
    key_hits = db.ListField(db.FloatField(default=0))
    detail_hits = db.ListField(db.ListField(db.FloatField(default=0)))
    user = db.ObjectIdField()
    date = db.DateTimeField()

    meta = {'collection': 'analysis'}
Ejemplo n.º 14
0
class Renant(db.Document):
    name = db.StringField(required=True)
    place = db.StringField(required=True)
    location = db.PointField(required=True)
    start_time = db.DateTimeField(required=True)
    end_time = db.DateTimeField(required=True)
    home_photo = db.StringField()
    description = db.StringField(min_length=20, required=True)
    host = db.ObjectIdField(required=True)  # link to USER DB
    cancel = db.BooleanField(default=False)
    capacity = db.StringField()
    price = db.StringField()
    contact = db.StringField()
    comments = db.ListField(db.ReferenceField(Comment))
Ejemplo n.º 15
0
class UserOrder(db.Document):
    PAY_TYPE_WX = 0
    PAY_TYPE_REDPACKET = 1
    OPTIONS_PAY_TYPE = collections.OrderedDict([
        (PAY_TYPE_WX, '微信账户'),
        (PAY_TYPE_REDPACKET, '红包账户'),
    ])

    PRODUCT_TYPE_WX = 0
    PRODUCT_TYPE_REDPACKET = 1
    OPTIONS_PRODUCT_TYPE = collections.OrderedDict([
        (PRODUCT_TYPE_WX, '微信账户'),
        (PRODUCT_TYPE_REDPACKET, '红包账户'),
    ])

    STATUS_UNPAY = 0
    STATUS_PAID = 1
    OPTIONS_STATUS = collections.OrderedDict([
        (STATUS_UNPAY, '未支付'),
        (STATUS_PAID, '已支付'),
    ])

    _id = db.ObjectIdField()
    open_id = db.StringField(max_length=64)

    order_no = db.StringField(max_length=64)
    pay_type = db.IntField(choices=OPTIONS_PAY_TYPE.iteritems(),
                           default=PAY_TYPE_WX)

    product_type = db.IntField(choices=OPTIONS_PRODUCT_TYPE.iteritems(),
                               default=PRODUCT_TYPE_REDPACKET)
    product_id = db.StringField(max_length=64)
    product_value = db.IntField()
    status = db.IntField(choices=OPTIONS_STATUS.iteritems(),
                         default=STATUS_UNPAY)

    price_origin = db.IntField()
    price_pay = db.IntField()
    product_num = db.IntField()

    order_msg = db.DictField()

    create_time = db.DateTimeField()
    pay_time = db.DateTimeField()

    meta = {
        'db_alias': 'default',
        'collection': 'userorder',
        'id_field': '_id',
    }
Ejemplo n.º 16
0
class Tracker(db.Document):
  _id = db.ObjectIdField()
  tracker_name = db.StringField()
  root_url = db.StringField()
  search_text = db.StringField()
  min_price = db.IntField()
  max_price = db.IntField()
  notify_email = db.EmailField()
  notify_every = db.IntField()
  notify_unit = db.StringField()
  notify_interval = db.IntField(validation=valid_notify_interval)
  last_notified_date = db.DateTimeField()
  
  def __repr__(self):
    return '<Tracker {}>'.format(self.tracker_name)
Ejemplo n.º 17
0
class LogisticLog(db.Document):
    """"""
    meta = {
        'db_alias': 'db_log',
        'allow_inheritance': True,
        'indexes': ['logistic_id', 'timestamp'],
        'ordering': ['-timestamp'],
    }
    log_type = db.StringField()
    logistic_id = db.ObjectIdField(required=True)
    timestamp = db.DateTimeField(default=datetime.utcnow)
    user_id = db.StringField(required=False)
    info = db.DictField()

    @classmethod
    def create(cls, log, data, user_id='system'):
        return cls(logistic_id=log.id, info=data, user_id=user_id).save()
Ejemplo n.º 18
0
class Message(db.Document):
    from_user = db.ReferenceField(User,
                                  db_field="from_user",
                                  reverse_delete_rule=CASCADE)
    to_user = db.ReferenceField(User,
                                db_field="to_user",
                                default=None,
                                reverse_delete_rule=CASCADE)
    text = db.StringField(db_field="text", max_length=1024)
    live = db.BooleanField(db_field="live", default=None)
    create_date = db.LongField(db_field="create_date", default=utc_now_ts_ms())
    parent = db.ObjectIdField(db_field="parent", default=None)
    images = db.ListField(db_field="images")
    message_type = db.IntField(db_field='message_type',
                               default=POST,
                               choices=MESSAGE_TYPE)

    @property
    def text_linkified(self):
        return linkify(self.text)

    @property
    def human_timestamp(self):
        return ms_stamp_humanize(self.create_date)

    @property
    def comments(self):
        return Message.objects.filter(
            parent=self.id, message_type=COMMENT).order_by('create_date')

    @property
    def likes(self):
        return Message.objects.filter(
            parent=self.id, message_type=LIKE).order_by('-create_date')

    def post_imgsrc(self, image_ts, size):
        return url_for('static',
                       filename=os.path.join(
                           'images', 'posts',
                           '%s.%s.%s.png' % (self.id, image_ts, size)))

    meta = {
        'indexes': [('from_user', 'to_user', '-create_date', 'parent',
                     'message_type', 'live')]
    }
Ejemplo n.º 19
0
class District(db.Document):
    district_id = db.IntField()
    state_id = db.ObjectIdField()
    title = db.DictField()
    code = db.StringField(max_lenght=255)

    meta = {
        'collection':
        'districts',
        'indexes': [{
            'fields': ['district_id'],
            'unique': True,
            'name': 'districts_district_id_unique',
        }, {
            'fields': ['state_id'],
            'name': 'districts_state_id_index',
        }, {
            'fields': ['title.*'],
            'name': 'districts_title_index',
        }]
    }
Ejemplo n.º 20
0
class Home(db.Document):
    name = db.StringField(required=True)
    place = db.StringField(required=True)
    location = db.PointField(required=True)
    start_time = db.DateTimeField(required=True)
    end_time = db.DateTimeField(required=True)
    home_photo = db.StringField()
    description = db.StringField(min_length=20, required=True)
    host = db.ObjectIdField(required=True)  #link to USER DB
    cancel = db.BooleanField(default=False)

    occupy = db.BooleanField(default=False)
    capacity = db.StringField()
    price = db.StringField()
    contact = db.StringField()

    #need one attribute ,"occupier" at specific time

    attendees = db.ListField(db.ReferenceField(User))

    comments = db.ListField(db.ReferenceField(Comment))
Ejemplo n.º 21
0
class MoneyEntry(db.EmbeddedDocument):
    class Recurring(IntEnum):
        SINGLE = 0
        EVERY_DAY = 1
        EVERY_MONTH = 2
        EVERY_YEAR = 3

    class Type(IntEnum):
        INCOME = 0
        EXPENSE = 1

    class State(IntEnum):
        PENDING = 0,
        APPROVED = 1

    id = db.ObjectIdField(required=True,
                          default=ObjectId,
                          unique=True,
                          primary_key=True)
    type = db.IntField(required=True, default=Type.INCOME)
    description = db.StringField(required=True)
    value = db.FloatField(required=True, default=1.00)
    currency = db.StringField(required=True,
                              default=constants.DEFAULT_CURRENCY)
    category = db.StringField(required=True)
    date = db.DateTimeField(required=True, default=datetime.now)
    recurring = db.IntField(default=Recurring.SINGLE)
    state = db.IntField(required=True, default=State.APPROVED)

    def clone(self):
        entry = MoneyEntry()
        entry.type = self.type
        entry.description = self.description
        entry.value = self.value
        entry.currency = self.currency
        entry.category = self.category
        entry.date = self.date
        entry.recurring = self.recurring
        entry.state = self.state
        return entry
Ejemplo n.º 22
0
class Review(db.Document):
    title = db.StringField()
    content = db.StringField()
    rating = db.DecimalField(min_value=1, max_value=10, precision=1)
    titleparent = db.ObjectIdField()
    author = db.ObjectIdField()
    points = db.ListField(db.ReferenceField(ReviewPoint))
    recommended = db.BooleanField()

    @staticmethod
    def get_by_id(id):
        try:
            return Review.objects.get(id=id)
        except:
            return None

    @staticmethod
    def get_by_title(title):
        reviews = Review.objects.filter(titleparent=title.id)
        return reviews

    @staticmethod
    def get_avg_rating(title):
        reviews = Review.get_by_title(title)

        avg = 0
        review_count = reviews.count()
        if review_count <= 0:
            return 0

        for review in reviews:
            avg += review.rating

        return avg / review_count

    def get_author(self):
        try:
            return User.get_by_id(self.author)
        except:
            return None

    def is_author(self, user):
        author = self.get_author()
        return author.id == getattr(user, "id", "")

    def __query_points(self, point_type):
        p = []
        for point in self.points:
            if point.role == point_type:
                p.append(point)
        return p

    def pros(self):
        return self.__query_points(ReviewPoint.PROS_ID)

    def cons(self):
        return self.__query_points(ReviewPoint.CONS_ID)

    def pros_as_string(self):
        pros = self.pros()
        pros_string = []
        for pro in pros:
            pros_string.append(pro.content)

        return pros_string

    def cons_as_string(self):
        cons = self.cons()
        cons_string = []
        for con in cons:
            cons_string.append(con.content)

        return cons_string

    def remove_all_points(self):
        for point in self.points:
            point.delete

        self.points = []

    def put_pros(self, pros):
        pros_object = []
        for pro in pros:
            pro_obj = ReviewPoint(content=pro,
                                  role=ReviewPoint.PROS_ID,
                                  parent=self.id)

            pro_obj.save()
            pros_object.append(pro_obj)

        self.points = pros_object

    def add_pros(self, pros):
        for pro in pros:
            pro_obj = ReviewPoint(content=pro,
                                  role=ReviewPoint.PROS_ID,
                                  parent=self.id)

            pro_obj.save()
            self.points.append(pro_obj)

    def put_cons(self, cons):
        cons_object = []
        for con in cons:
            con_obj = ReviewPoint(content=con,
                                  role=ReviewPoint.CONS_ID,
                                  parent=self.id)

            con_obj.save()
            cons_object.append(con_obj)

        self.points = cons_object

    def add_cons(self, cons):
        for con in cons:
            con_obj = ReviewPoint(content=con,
                                  role=ReviewPoint.CONS_ID,
                                  parent=self.id)

            con_obj.save()
            self.points.append(con_obj)
Ejemplo n.º 23
0
class RedPacket(db.Document):
    _id = db.ObjectIdField()
    open_id = db.StringField(max_length=64)
    amount = db.IntField()
    count = db.IntField()
    left_count = db.IntField()
    title = db.StringField(max_length=64)
    level = db.IntField()
    poster = db.StringField(max_length=256)

    create_time = db.DateTimeField()
    expire_time = db.DateTimeField()

    meta = {
        'db_alias': 'default',
        'collection': 'redpacket',
        'id_field': '_id',
    }

    @property
    def could_collect(self):
        flag = False
        if self.left_count and self.expire_time > datetime.datetime.now():
            flag = True
        return flag

    @classmethod
    def get_packet(cls, redpacket_id):
        redpacket_id = str2objectid(redpacket_id)
        packet = cls.objects.filter(
            _id=redpacket_id,
            expire_time__gte=datetime.datetime.now()).first()
        return packet

    @classmethod
    def get_packet_all(cls, redpacket_id):
        redpacket_id = str2objectid(redpacket_id)
        packet = cls.objects.filter(_id=redpacket_id).first()
        if not packet:
            return
        return packet

    @classmethod
    def has_collect(cls, redpacket_id, open_id=None):
        redpacket_id = str2objectid(redpacket_id)
        rpl = RedPacketLog.objects.filter(
            redpacket_id=redpacket_id,
            open_id=open_id,
            status=RedPacketLog.STATUS_DONE).first() if open_id else None
        has_collect, value = (True, rpl.value) if rpl else (False, 0)
        return has_collect, value / 100.0

    @classmethod
    def create_redpacket(cls,
                         open_id,
                         amount,
                         number,
                         title,
                         level,
                         posterurl,
                         _id=None):
        flag, result = redpacketobj.result(amount, number, 1)
        if not flag:
            return result
        now = datetime.datetime.now()
        if not _id: _id = bson.ObjectId()
        redpacket = cls(_id=_id,
                        open_id=open_id,
                        amount=amount,
                        count=number,
                        left_count=number,
                        title=title,
                        level=level,
                        create_time=now,
                        expire_time=now + datetime.timedelta(days=7),
                        poster=posterurl)
        redpacketlog = []
        for value in result:
            redpacketlog.append(
                RedPacketLog(redpacket_id=_id,
                             value=value,
                             status=0,
                             last_modify=now))
        rpl = RedPacketLog.objects.insert(redpacketlog)
        rp = cls.objects.insert(redpacket) if rpl else None
        return _id if rp else None

    @classmethod
    def collect_redpacket(cls, redpacket_id, open_id):
        redpacket_id = str2objectid(redpacket_id)
        rp = cls.objects.filter(
            _id=redpacket_id, left_count__gte=1).update_one(inc__left_count=-1)
        if not rp:
            return False,
        filters = dict(redpacket_id=redpacket_id,
                       status=RedPacketLog.STATUS_UN,
                       open_id__exists=False)
        rpl = RedPacketLog.objects.filter(**filters).first()
        if not rpl:
            return False,
        modify = {
            'status': RedPacketLog.STATUS_DONE,
            'open_id': open_id,
            'last_modify': datetime.datetime.now()
        }
        result = rpl.modify(query=filters, **modify)
        if not result:
            return False,
        return rpl.value, rpl.pk

    def collect_report(self, open_id, status, rp_log_id=None):
        data = dict(redpacket_id=self.pk,
                    status=status,
                    open_id=open_id,
                    create_time=datetime.datetime.now())
        if status == RedPacketCollectLog.STATUS_SUCCESS and rp_log_id:
            data.update({'rp_log_id': str(rp_log_id)})
            rpcl = RedPacketCollectLog(**data)
        elif status == RedPacketCollectLog.STATUS_FAIL:
            rpcl = RedPacketCollectLog(**data)
        else:
            return False
        RedPacketCollectLog.objects.insert(rpcl)
        return RedPacketCollectLog.objects.filter(redpacket_id=self.pk,
                                                  open_id=open_id).count()
Ejemplo n.º 24
0
class Order(db.Document):
    """"""
    meta = {
        'db_alias':
        'db_order',
        'ordering': ['-created_at'],
        'indexes': [
            'customer_id', 'status', 'address', 'amount', 'final',
            'order_type', 'is_paid', 'is_payment_abnormal', 'refund_entries'
        ],
    }
    created_at = db.DateTimeField(default=datetime.datetime.utcnow,
                                  required=True)
    order_type = db.StringField(choices=ORDER_TYPE,
                                default=ORDER_TYPE.COMMODITY)
    # one day
    expired_in = db.IntField(default=1440)  # in minutes
    payment_expired_in = db.IntField(default=1440)
    short_id = db.SequenceField(required=True, unique=True)
    is_vip = db.BooleanField(default=False)
    status = db.StringField(max_length=256,
                            required=True,
                            choices=ORDER_STATUS,
                            default=ORDER_STATUS.PAYMENT_PENDING)
    status_modified = db.DateTimeField()
    source = db.StringField(choices=ORDER_SOURCES)
    is_rewards_given = db.BooleanField(default=False)

    # order detail
    amount_usd = db.FloatField(default=0)
    amount = db.FloatField(default=0)

    discount = db.ListField(db.DictField())
    # 优惠卷兑换码
    coupon_codes = db.ListField(db.StringField())
    coin = db.IntField()
    lucky_money = db.IntField()
    cash = db.IntField()
    final = db.FloatField(required=True)
    # 库存
    logistic_provider = db.StringField()
    # 预估退税
    estimated_tax = db.FloatField(default=0)
    real_tax = db.FloatField(default=-1)
    paid_tax = db.FloatField(default=-1)

    # for internal usage
    # 汇率
    forex = db.FloatField()
    real_shipping = db.FloatField()
    cn_shipping = db.FloatField(default=0)
    address = db.ReferenceField('Address')
    customer_id = db.ObjectIdField(required=True)
    is_new_customer = db.BooleanField(default=False)
    entries = db.ListField(
        db.ReferenceField('OrderEntry', reverse_delete_rule=mongoengine.PULL))
    extra = db.StringField()

    logistics = db.ListField(db.ReferenceField('Logistic'))  # 库存
    closed_logistics = db.ListField(db.ReferenceField('Logistic'))

    is_paid = db.BooleanField(default=False)  # 是否支付
    is_payment_abnormal = db.BooleanField(default=False)  # 是否支付异常
    paid_date = db.DateTimeField()  # 支付时间
    pay_tax_deadline = db.DateTimeField()  # 支付税截至时间

    refund_entries = db.ListField(
        db.ReferenceField('OrderEntry', reverse_delete_rule=mongoengine.PULL))
    refund_amount = db.FloatField(default=0)
    is_test = db.BooleanField(default=False)

    fields_to_log = {
        'status',
        'amount',
        'coin',
        'final',
        'estimated_tax',
        'real_tax',
        'paid_tax',
        'real_shipping',
        'is_paid',
    }
    # 处理中的状态
    PROCESSING_STATUS = [ORDER_STATUS.PAYMENT_RECEIVED, ORDER_STATUS.SHIPPING]
    # 异常状态
    ABNORMAL_STATUS = [
        ORDER_STATUS.CANCELLED, ORDER_STATUS.ABNORMAL,
        ORDER_STATUS.ORDER_DELETE, ORDER_STATUS.EXPIRED, ORDER_STATUS.REFUNDED
    ]

    def __unicode__(self):
        return '%s' % self.sid

    def __str__(self):
        return '{}'.format(self.id)

    @classmethod
    def get_order_or_404(cls, order_id, check_user=True):
        try:
            order = cls.objects(id=order_id).first_or_404()
        except mongoengine.ValidationError:
            try:
                short_id = int(order_id)
            except (ValueError, TypeError):
                abort(404)
            order = cls.objects(short_id=short_id).first_or_404()

        if check_user and str(order.customer_id) != str(current_user.id):
            abort(404)

        return order

    @queryset_manager
    def commodities(doc_cls, queryset):
        return queryset.filter(order_type=ORDER_TYPE.COMMODITY,
                               status__nin=doc_cls.ABNORMAL_STATUS)

    @queryset_manager
    def transfer(doc_cls, queryset):
        return queryset.filter(order_type=ORDER_TYPE.TRANSFER,
                               status__nin=doc_cls.ABNORMAL_STATUS)

    @queryset_manager
    def processing(doc_cls, queryset):
        return queryset.filter(status__in=doc_cls.PROCESSING_STATUS)

    @queryset_manager
    def payment_pending(doc_cls, queryset):
        return queryset.filter(status=ORDER_STATUS.PAYMENT_PENDING)

    @queryset_manager
    def abnormal(doc_cls, queryset):
        return queryset.filter(
            Q(status__in=doc_cls.ABNORMAL_STATUS)
            | Q(refund_entries__0__exists=True)
            & Q(status__in=doc_cls.PROCESSING_STATUS +
                [ORDER_STATUS.RECEIVED]))

    @queryset_manager
    def received(doc_cls, queryset):
        return queryset.filter(status=ORDER_STATUS.RECEIVED)

    @queryset_manager
    def is_processing(self):
        return self.status in self.PROCESSING_STATUS

    @queryset_manager
    def is_payment_pending(self):
        return self.status == ORDER_STATUS.PAYMENT_PENDING

    @queryset_manager
    def is_abnormal(self):
        if self.status in self.ABNORMAL_STATUS:
            return True
        if self.status in self.PROCESSING_STATUS or self.status == ORDER_STATUS.RECEIVED:
            return len(self.refund_entries) > 0
        return False

    def has_refund_entries(self):
        if self.status in (self.PROCESSING_STATUS +
                           [ORDER_STATUS.RECEIVED, ORDER_STATUS.REFUNDED]):
            return len(self.refund_entries) > 0
        return False

    @property
    def tax(self):
        if self.real_tax == -1:
            return self.estimated_tax
        else:
            return self.real_tax

    @property
    def shipping(self):
        return self.cn_shipping

    @property
    def estimated_weight(self):
        return sum(
            float(entry.item_snapshot.weight) * entry.quantity
            for entry in self.entries)

    @property
    def pay_tax_remain_days(self):
        if self.pay_tax_deadline:
            time_remain = self.pay_tax_deadline.date() - datetime.date.today()
            if time_remain.days > 0:
                return time_remain.days

    @property
    def latest_logistic(self):
        attr = LogisticDetail.attr_by_log_status.get(self.status)
        if not attr:
            return None
        return max(self.logistics, key=lambda l: getattr(l.detail, attr))

    @classmethod
    def create_transfer(cls,
                        customer_id,
                        entries,
                        logistic_provider,
                        coupon_codes,
                        coin=0,
                        cash=0,
                        address=None,
                        **kwargs):
        order = cls(customer_id=customer_id,
                    entries=entries,
                    logistic_provider=logistic_provider,
                    coupon_codes=coupon_codes,
                    coin=coin,
                    cash=cash,
                    **kwargs)
        if not order.forex:
            order.forex = ForexRate.get()

        order.update_amount()
        order.reload()
        if address:
            order.set_address(address)

        order_created.send('system', order=order)

        return order

    @classmethod
    def create_from_skus(cls,
                         customer_id,
                         skus,
                         logistic_provider,
                         coupon_codes,
                         coin=0,
                         cash=0,
                         address=None,
                         **kwargs):
        entries = []
        for s in skus:
            availability = check_availability_and_update_stock(
                s['item_id'], s['sku'], s['quantity'])
            if not availability:
                return s
            spec = ItemSpec.objects(sku=s['sku']).first()
            item = Item.objects(item_id=['item_id']).first()
            entry = OrderEntry(spec=spec, item=item,
                               quantity=s['quantity']).save()
            entries.append(entry)

        order = cls(customer_id=customer_id,
                    entries=entries,
                    logistic_provider=logistic_provider,
                    coupon_codes=coupon_codes,
                    coin=coin,
                    cash=cash,
                    **kwargs)
        if not order.forex:
            order.forex = ForexRate.get()

        order.update_amount()
        order.reload()
        # 简介
        for e in order.entries:
            e.create_snapshot()

        if address:
            order.set_address(address)

        order_created.send('system', order=order)
        return order

    @classmethod
    def create(cls,
               customer_id,
               entries,
               logistic_provider,
               coupon_codes,
               coin=0,
               cash=0,
               address=None,
               **kwargs):
        order_entries = []
        for entry in entries:
            availability = check_availability_and_update_stock(
                entry.item_snapshot.item_id, entry.item_spec_snapshot.sku,
                entry.quantity)
            if not availability:
                return entry
            if isinstance(entry, (CartEntry, OrderEntry)):
                e = deepcopy(entry)
                e.__class__ = OrderEntry
                e.id = None
                order_entries.append(e.save())

        order = cls(customer_id=customer_id,
                    entries=order_entries,
                    logistic_provider=logistic_provider,
                    coupon_codes=coupon_codes,
                    coin=coin,
                    cash=cash,
                    **kwargs)
        if not order.forex:
            order.forex = ForexRate.get()

        order.update_amount()
        order.reload()
        for e in order.entries:
            e.create_snapshot()

        if address:
            order.set_address(address)

        order_created.send('system', order=order)
        return order

    @property
    def item_changed(self):
        res = False
        for e in self.entries:
            res = res and e.item_changed
            if res:
                return res
            return res

    def __get__(self, *args, **kwargs):
        order = super(Order, self).__get__(*args, **kwargs)
        if (not order.is_paid) and order.item_changed:
            order.update_entry()
            return order

    def update_entry(self):
        if self.is_paid:
            return
        map(lambda e: e.update_snapshot(), self.entries)
        self.update_amount()

    def set_address(self, addr):
        if not isinstance(addr, Address):
            addr = Address.objects(id=addr).first()
        if not addr:
            return False
        addr_snapshot = deepcopy(addr)
        addr_snapshot.id = None
        addr_snapshot.order_id = self.id
        addr_snapshot.save()
        if self.address:
            self.address.delete(w=1)
        self.address = addr_snapshot
        self.save()
        return True

    @property
    def customer(self):
        return User.objects(id=self.customer_id).first()

    def create_payment(self, ptype, trader):
        ptype = ptype.upper()
        self.update_entry()
        self.reload()
        if self.order_type != ORDER_TYPE.TRANSFER:
            is_available = self.check_entries_avaliable()
            if not is_available or self.status in [
                    'CANCELLED', 'ABNORMAL', 'ORDER_DELETED', 'EXPIRED'
            ]:
                return None

        new_payment = Payment(order=self, ptype=ptype, trader=trader).save()
        return new_payment

    def get_payment(self, ptype):
        ptype = ptype.upper()
        payments = Payment.objects(order=self,
                                   ptype=ptype).order_by('-created_at')
        paid_payments = payments.filter(status=PAYMENT_STATUS.PAID)
        if paid_payments:
            return paid_payments.first()
        else:
            return payments.first()

    @property
    def goods_payment(self):
        return self.get_payment(PAYMENT_TYPE.WITHOUT_TAX)

    @property
    def tax_payment(self):
        return self.get_payment(PAYMENT_TYPE.WITH_TAX)

    @property
    def refunds(self):
        return Refund.objects(order=self)

    def check_entries_avaliable(self):
        availability = all(
            map(lambda e: e.is_available or e.item_spec_snapshot.stock != -1,
                self.entries))
        if not availability:
            self.status = ORDER_STATUS.EXPIRED
            self.save()
        return availability

    def set_paid(self):
        if self.is_paid:
            return
        self.is_new_customer = not bool(
            Order.objects(custom_id=self.customer_id, is_paid=True))
        self.is_paid = True
        self.status = ORDER_STATUS.PAYMENT_RECEIVED
        self.paid_date = datetime.datetime.utcnow()
        self.save()
        payment_received(self)

    def update_payment(self, paid_type, paid_amount, trader):
        if paid_type == PAYMENT_TYPE.WITHOUT_TAX and not self.is_paid and self.status in [
                ORDER_STATUS.PAYMENT_PENDING, ORDER_STATUS.W
        ]:
            if paid_amount == self.final and trader == PAYMENT_TRADERS.PAYPAL:
                self.set_paid()
            elif paid_amount == float('%.2f' % (self.final * self.forex)
                                      ) and trader == PAYMENT_TRADERS.WEIXIN:
                self.set_paid()
            else:
                current_app.logger.error(
                    'error at updating payment. trader: {}; ptype: {}; amount: {} order id: {}'
                    .format(trader, paid_type, paid_amount, self.id))
                self.is_payment_abnormal = True
        else:
            current_app.logger.error(
                'error at updating payment. trader: {}; ptype: {}; amount: {};  order id: {}'
                .format(trader, paid_type, paid_amount, self.id))
            self.is_payment_abnormal = True
        self.save()

    @property
    def coin_trades(self):
        return Trade.objects(reason_id=str(self.id))

    def update_logistic_status(self):
        if self.logistics:
            log_status = map(lambda m: m.detail.status, self.logistics)
            new_status = min(log_status, key=lambda l: LOG_STATUS.index(1))
            self._change_status(new_status)

    def _change_status(self, new_status):
        if self.status == new_status:
            return
        self.status = new_status
        self.status_modified = datetime.datetime.utcnow()
        self.save()

        if new_status in LOG_STATUS:
            notification_order(self, new_status)
            order_logistic_status_changed.send('Order.Logistic.Status.Changed',
                                               order=self,
                                               new_status=new_status)
        else:
            order_status_changed.send('order_status_changed',
                                      order=self,
                                      new_status=new_status)

    def delete_order(self):
        for l in self.logistics:
            l.delete(w=1)

        for entry in self.entries:
            entry.delete(w=1)

        if self.goods_payment:
            self.goods_payment.delete(w=1)
        self.delete(w=1)

    def cancel_order(self, reason, status=None):
        """

        :param reason:
        :param status:
        :return:
        """
        for l in self.logistics:
            l.close(reason)

        self.extra = reason
        self.save()

        if not status:
            status = ORDER_STATUS.ABNORMAL
        self._change_status(status)
        for entry in self.entries:
            try:
                if entry.spec.stock != -1:
                    entry.spec.update(inc__stock=entry.quantity,
                                      set__availability=True)
                    entry.item.update(set__availability=True,
                                      set__status='MOD')

            except AttributeError:
                pass

    def update_amount(self):
        for e in self.entries:
            e.update_amount()
        cal_order_price_and_apply(self)
        self.estimated_tax = cal_order_tax(self)
        self.save()

    @property
    def sid(self):
        return self.short_id

    def to_json(self,
                include_logistic=False,
                replace_entries_to_refunded=False):
        if not self.is_paid:
            self.update_amount()
            self.reload()

        entries_json = []
        if replace_entries_to_refunded and self.has_refund_entries():
            for e in self.refund_entries:
                entries_json.append(e.to_json())
        else:
            for e in self.entries:
                entries_json.append(e.to_json())

        refund_entries_json = []
        for e in self.refund_entries:
            refund_entries_json.append(e.to_json())

        result = dict(
            id=str(self.id),
            short_id=str(self.sid),
            status=self.status,
            customer_id=str(self.customer_id),
            amount=self.amount,
            cn_shipping=self.cn_shipping,
            coin=self.coin,
            lucky_money=self.lucky_money,
            discount=self.discount,
            final=self.final,
            estimated_tax=self.estimated_tax,
            payment_status='PAID' if self.is_paid else 'UNPAID',
            payment_ref_number=[
                p.ref_number for p in Payment.objects(order=self)
            ],
            created_at=format_date(self.created_at),
            entries=entries_json,
            refund_entries=refund_entries_json,
            refund_amount=self.refund_amount,
            real_tax=self.real_tax,
        )
        if self.address:
            result.update({'address': self.address.to_json()})
        if include_logistic:
            result.update(logistics=[l.to_json() for l in self.logistics])

        return result

    def to_grouped_json(self):
        """

        :return:
        """
        res = dict(
            estimated_weight=self.estimated_weight,
            amount=self.amount,
            cn_shipping=self.cn_shipping,
            coin=self.coin,
            lucky_money=self.lucky_money,
            discount=self.discount,
            final=self.final,
            extimated_tax=self.extimated_tax,
        )
        res['sid'] = self.id
        res['status'] = self.status
        if self.address:
            res.update(dict(address=self.address.to_json()))
        return res
Ejemplo n.º 25
0
class MasterFile(db.EmbeddedDocument):
  file_composition = db.ListField(db.ObjectIdField())
  file = db.FileField()
Ejemplo n.º 26
0
class User(db.Document):
  email = db.StringField(required=True)
  name = db.StringField()
  corporate_id = db.ObjectIdField()
  password = db.StringField()
Ejemplo n.º 27
0
class Survey(db.Document):
    user = db.ObjectIdField(User)
    timestamp = db.DateTimeField(required=True)
    survey = db.DictField(db.AnythingField(), required=True)
    tags = db.ListField(db.StringField(), required=True, default=[])
    ongoing = db.BoolField(default=True, required=True)

    def getAll(self, from_datetime=None, until_datetime=None,
               tags=None, ongoing=None):
        """
        Return all surveys registered.
        By setting 'from_datetime'm, 'until_datetime', 'tags' or 'ongoing'
        one could further filter the scope of the query
        """
        # return Survey.query.all()
        query = db.session.query(Survey)

        if from_datetime is not None:
            query.filter(Survey.timestamp >= from_datetime)

        if until_datetime is not None:
            query.filter(Survey.timestamp <= until_datetime)

        if tags is not None:
            query.filter(Survey.tags.in_(tags))

        if ongoing is not None:
            query.filter(Survey.ongoing == ongoing)

        return query.all()

    def getAllByUniqueID(self, uniqueID, from_datetime=None, until_datetime=None,
                         tags=None, ongoing=None):
        """
        Return all surveys registered by a given user.
        By setting 'from_datetime'm, 'until_datetime', 'tags' or 'ongoing'
        one could further filter the scope of the query
        """

        # Check if user exists
        user = User().query.filter(User.uniqueID == uniqueID).first()
        try:
            assert not user is None, "User not found"
        except AssertionError as ax:
            raise UserNotFound(uniqueID)

        query = db.session.query(Survey)

        query.filter(Survey.user == user.mongo_id)

        if from_datetime is not None:
            query.filter(Survey.timestamp >= from_datetime)

        if until_datetime is not None:
            query.filter(Survey.timestamp <= until_datetime)

        if tags is not None:
            query.filter(Survey.tags.in_(tags))

        if ongoing is not None:
            query.filter(Survey.ongoing == ongoing)

        return query.all()

    def getByUniqueIDAndID(self, uniqueID, _id):
        return Survey.query.filter(Survey.user == User().query.filter(User.uniqueID == uniqueID)
                                   .first().mongo_id, Survey.mongo_id == _id).first()

    def getByID(self, survey_id):
        try:
            surveys = Survey.query.filter(Survey.mongo_id == survey_id)
            if surveys.count() == 0:
                raise SurveyNotFound(survey_id)
            return surveys.first()
        except db.BadValueException:
            raise SurveyNotFound(survey_id)

    def addByUniqueID(self, uniqueID, survey, tags=[], ongoing=True):
        self.user = User().query.filter(User.uniqueID == uniqueID).first().mongo_id
        self.timestamp = datetime.utcnow()
        self.survey = survey
        self.tags = tags
        self.ongoing = ongoing
        self.save()
        return True

    def updateByUniqueIDAndID(self, uniqueID, _id, survey, tags, ongoing):
        Survey.query.filter(Survey.user == User().query.filter(User.uniqueID == uniqueID).first().mongo_id,
                            Survey.mongo_id == _id).set(
                                                        survey=survey,
                                                        tags=tags,
                                                        ongoing=ongoing,
                                                        timestamp=datetime.utcnow()).execute()
        return True

    def updateByUniqueID(self, _id, survey, tags, ongoing):
        """
        Verify survey exists.
        Then update its 'survey' content and save it back.
        """

        try:
            surveys = Survey.query.filter(Survey.mongo_id == _id)
            if surveys.count() == 0:
                raise SurveyNotFound(_id)
            if surveys.count() > 1:
                raise NonUniqueSurveyIDError(_id)
        except db.BadValueException as error:
            raise SurveyNotFound(_id)

        existing_survey_object = surveys.first()
        existing_survey_object.survey = survey
        existing_survey_object.tags = tags
        existing_survey_object.ongoing = ongoing
        existing_survey_object.timestamp=datetime.utcnow()
        existing_survey_object.save()
        return True

    def deleteByUniqueID(self, _id):
        """
        Verify survey exists.
        Then delete it.
        """
        try:
            surveys = Survey.query.filter(Survey.mongo_id == _id)
            if surveys.count() == 0:
                raise SurveyNotFound(_id)
            if surveys.count() > 1:
                raise NonUniqueSurveyIDError(_id)
        except db.BadValueException as error:
            raise SurveyNotFound(_id)

        existing_survey_object = surveys.first()
        existing_survey_object.remove()
        return True

    def getCSVReportTagsAndOngoing(self):
        data = [ob.serializeTagsAndOngoing() for ob in self.getAll()]

        filename = str(uuid.uuid4()) + '.csv'
        path = os.path.join(current_app.config['REPORTS_DIR'], filename)
        csv_file = csv.writer(open(path, mode="w"))

        csv_file.writerow(['User ID', 'Survey ID', 'timestamp', 'tags', 'ongoing'])
        for item in data:
            # the `tags` field can apparently contain arbitrary Unicode data (limited to Latin-1, actually, looking
            # at the samples collected so far) so we need to escape it to UTF-8 in order to save into a CSV file
            # According to the Python 2.7 `csv` module docs, "The csv module does not directly support reading
            # and writing Unicode, but it is 8-bit-clean save for some problems with ASCII NUL characters."
            # so reading and writing UTF-8 is OK.
            csv_file.writerow([item['user_id'], item['id'], item['timestamp'], item['tags'].encode('utf-8'), item['ongoing']])

        return filename

    def serialize(self):
        d = {
                "id": str(self.mongo_id),
                "timestamp": self.timestamp.isoformat(),
                "survey": self.survey,
                "tags": self.tags,
                "ongoing": bool(self.ongoing)
            }

        return d

    def serializeTagsAndOngoing(self):
        d = {
                "user_id": User().query.filter(User.mongo_id == self.user).first().uniqueID,
                "id": str(self.mongo_id),
                "timestamp": self.timestamp.isoformat(),
                "tags": ', '.join(self.tags),
                "ongoing": bool(self.ongoing)
            }

        return d
Ejemplo n.º 28
0
class Pomodoro(db.EmbeddedDocument):
    id = db.ObjectIdField(default=ObjectId, required=True)
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
    complete = db.BooleanField(default=False, required=True)
    remaining_length = db.IntField(required=True)
Ejemplo n.º 29
0
class Discussion(db.Document):
    title = db.StringField()
    description = db.StringField()
    created_at = db.DateTimeField()
    answers = db.ListField(
        db.ReferenceField('Discussion', reverse_delete_rule=db.PULL))
    parent = db.ObjectIdField()

    upvotes = db.ListField(db.ReferenceField('Upvote'))

    author = db.ObjectIdField()
    is_answer = db.BooleanField()

    @staticmethod
    def get_by_id(id):
        try:
            return Discussion.objects.get(id=id)
        except:
            return None

    @staticmethod
    def get_by_title(title):
        discussions = Discussion.objects.filter(parent=title.id)
        return discussions

    def get_author(self):
        return User.objects.get(id=self.author)

    def is_author(self, user):
        author = self.get_author()
        return author.id == getattr(user, "id", "")

    def delete_all_answers(self):
        if not self.is_answer:
            for answer in self.answers:
                answer.delete()

    def delete_all_upvotes(self):
        for upvote in self.upvotes:
            upvote.delete()

    def upvotes_count(self):
        return Upvote.objects.filter(parent=self.id).count()

    def upvotes_value(self):
        return Upvote.objects.filter(parent=self.id).sum("value")

    def has_upvoted(self, user_id):
        for upvote in self.upvotes:
            if upvote.user_id == user_id:
                if (upvote.value == 1):
                    return True, "upvote", upvote
                else:
                    return True, "downvote", upvote

        return False, "", None

    def manage_upvote(self, user_id, value):
        has_upvoted, upvote_type, upvote = self.has_upvoted(user_id)

        if not has_upvoted:
            upvote = Upvote(user_id=user_id, value=value, parent=self.id)

            upvote.save()
            self.upvotes.append(upvote)

            self.save()
            return self.upvotes_value()

        if upvote.value != value:
            upvote.value = value
            upvote.save()
            self.save()
        else:
            self.update(pull__upvotes=upvote)
            upvote.delete()

        return self.upvotes_value()
Ejemplo n.º 30
0
class User(db.Document):
    _id = db.ObjectIdField()
    username = db.StringField()
    password = db.StringField()
    accessString = db.StringField()