class IntIDMixin(object): id = db.IntField(primary_key=True) created_at = db.DateTimeField(default=datetime.now) updated_at = db.DateTimeField() def _generate_id(self): last_obj = self.__class__.objects.only('id').order_by('-id').first() self.id = last_obj.id + 1 if last_obj else 1 def save(self, *args, **kwargs): if not self.id: self._generate_id() if not self.created_at: self.created_at = datetime.now() self.updated_at = datetime.now() super(IntIDMixin, self).save(*args, **kwargs)
class Order(db.Document): apishop_id = db.StringField(required=True) offers = db.ListField(db.EmbeddedDocumentField('OrderOffer'), default=[]) ordered_at = db.DateTimeField() userinfo = db.DictField(default={}) delivery_info = db.DictField(default={}) comment = db.StringField() @property def get_delivery(self): return dict(price=self.delivery_info.get('delivery_price'), total=self.delivery_info.get('order_sum')) \ if self.delivery_info.get('delivery_price', None) is not None else None @property def get_total(self): return sum([offer.price * offer.quantity for offer in self.offers]) def get_relevant_offers(self, max_items=4): offer_ids_not_to = [item.offer.id for item in self.offers] offer_ids = Offer.objects(available=True, id__nin=offer_ids_not_to).distinct('id') length = len(offer_ids) if length: try: ids = random.sample(offer_ids, max_items) except ValueError: ids = random.sample(offer_ids, length) return Offer.objects(id__in=ids) def get_timer(self): timer = self.ordered_at + timedelta(minutes=5) - timedelta(seconds=20) if timer < datetime.now(): return False return timer.strftime('%Y/%m/%d %H:%M:%S') def add_offer(self, offer, quantity=1, variant=None): o = OrderOffer(offer=offer, price=offer.get_price(), oldprice=offer.get_oldprice or 0.0, quantity=quantity, variant=variant) self.update(push__offers=o) self.reload() def populate_offers(self, sended_offers): if not isinstance(sended_offers, (list, tuple)): sended_offers = [sended_offers] for sended_offer in sended_offers: offer = Offer.objects(articul=sended_offer.get('articul')).first() if offer: self.offers.append(OrderOffer(offer=offer, price=offer.get_price(), oldprice=offer.get_oldprice or 0.0, quantity=sended_offer.get('quantity', 1), variant=sended_offer.get('variant', None)))
class BaseModel(db.Document): id = db.IntField(primary_key=True) create_at = db.DateTimeField(default=datetime.now) update_at = db.DateTimeField() meta = {'allow_inheritance': True, 'abstract': True, 'strict': False} @classmethod def get(cls, id): coll_name = cls._meta['collection'] key = OBJ_KEY.format(coll_name=coll_name, id=id) rs = cache.get(key) if rs: return cls.from_json( rs) # Converts json data to an unsaved document instance rs = cls.objects.get(id=id) cache.set(key, rs.to_json()) # Convert this document to JSON. return rs @classmethod def get_multi(cls, ids): return [cls.get(i) for i in ids if i] @classmethod def get_or_create(cls, **kwargs): try: return cls.objects.get(id=kwargs['id']) except DoesNotExist: kwargs.update({'update_at': datetime.now()}) model = cls(**kwargs) model.save() return model @classmethod def get_sample_ids(cls, size): samples = list(cls.objects.aggregate({'$sample': {'size': size}})) return [s['_id'] for s in samples]
class ApishopConfig(TempDBMixin, db.Document): login = db.StringField(max_length=50, required=True) shop_id = db.IntField(required=True) yml_file = db.StringField(max_length=255) task = db.DictField(default={'id': None, 'name': None}) updated_at = db.DateTimeField() _password = db.StringField(required=True) def __unicode__(self): return self.login @classmethod def get_config(cls): return cls.objects.first() @property def password(self): return decode_string(self._password) @password.setter def password(self, value): self._password = encode_string(value) def set_task(self, task): self.update(set__task=dict(id=task.task_id, name=task.task_name)) def set_updated_at(self): self.update(set__updated_at=datetime.datetime.now()) @property def is_yml_exists(self): if self.yml_file: return check_file_exists(self.yml_file, relative=True) return False @property def task_is_ready(self): if self.task.get('id'): return celery.AsyncResult(self.task.get('id')).ready() return True def delete(self, *args, **kwargs): delete_file_by_path(self.yml_file, relative=True) ApishopCategory.objects.delete() ApishopOffer.objects.delete() super(ApishopConfig, self).delete(*args, **kwargs)
class User(db.Document, UserMixin): email = db.StringField(max_length=255, unique=True) password = db.StringField(max_length=255, required=True) name = db.StringField(max_length=255) active = db.BooleanField(default=True) roles = db.ListField(db.ReferenceField(Role), default=[]) registered_at = db.DateTimeField() def __unicode__(self): return 'User %s' % self.email @property def is_admin(self): return self.has_role('admin') def save(self, *args, **kwargs): self.registered_at = datetime.now() super(User, self).save(*args, **kwargs)
class ApishopPriceChange(TempDBMixin, db.Document): oid = db.IntField() name = db.StringField() old_price = db.FloatField() new_price = db.FloatField() date = db.DateTimeField(default=datetime.datetime.now) meta = {'ordering': ['-date']} @classmethod def create_or_update(cls, **kwargs): oid = kwargs.pop('oid') obj = cls.objects(oid=oid) if len(obj) >= 1: for o in obj: o.delete() obj = cls(**kwargs) obj.save() return obj
class Subscriber(IntIDMixin, db.Document): name = db.StringField(max_length=200, required=True) email = db.StringField(max_length=200, required=True) subscribed_at = db.DateTimeField(default=datetime.now()) is_active = db.BooleanField(default=True) def __unicode__(self): return '<Subscriber {}: {}>'.format(self.id, self.email) def mark_subscribed(self): userinfo = session.get('userinfo', None) if not userinfo: session['userinfo'] = dict(fullname=self.name, email=self.email) else: if 'fullname' not in userinfo: userinfo['fullname'] = self.name if 'email' not in userinfo: userinfo['email'] = self.email session['is_subscribed'] = True
class Review(db.Document): offer = db.ReferenceField('Offer') fullname = db.StringField(max_length=200) email = db.StringField(max_length=200) text = db.StringField() rating = db.IntField(default=0) is_moderated = db.BooleanField(default=False) is_viewed = db.BooleanField(default=False) created_at = db.DateTimeField(default=datetime.now) meta = { 'ordering': ['-created_at'] } def toggle_moderate(self): self.update(set__is_moderated=not self.is_moderated) self.reload() def set_viewed(self): if not self.is_viewed: self.update(set__is_viewed=True) self.reload()
class Region(db.Document): id = db.IntField(primary_key=True) name = db.StringField(max_length=400) popularity = db.IntField(default=0) deliveries = db.ListField(db.EmbeddedDocumentField('RegionDelivery'), default=[]) updated_at = db.DateTimeField() meta = { 'ordering': ['-popularity', '+id'], 'indexes': ['name'] } def __unicode__(self): return self.name def __str__(self): return u'%s(%s)' % (self.__class__.__name__, self.id) def int_popularity(self): popularity = (self.popularity or 0) + 1 try: self.update(set__popularity=popularity) except db.OperationError: self.popularity = popularity self.save() def update_deliveries(self, methods): now = datetime.now() try: self.update(set__deliveries=methods, set__updated_at=now) except db.OperationError: self.deliveries = methods self.updated_at = now self.save() def get_delivery_prices(self, result, aid=None): d_methods = {str(d.id): {'id': d.id, 'method': d.name} for d in DeliveryMethod.objects()} if not aid: aids = Offer.objects(available=True).distinct('aid') aid = random.choice(aids) methods = [] if len(result): deliveries = result[0].deliveries for delivery in deliveries: d = d_methods.get(delivery.id, None) if d: prices = [] for payment in delivery.payments: price = payment.sum if price is not None and price > 0 and price not in prices: prices.append(price) if len(prices): price = min(prices) d['price'] = price methods.append(RegionDelivery(**d)) return methods
class OfferSpecial(db.Document): is_active = db.BooleanField(default=False) type = db.StringField(choices=(('real', u'Понизить цену'), ('fake', u'Повысить цену')), default='real', verbose_name=u'Тип акции') price_type = db.StringField(choices=(('percent', u'На проценты'), ('new', u'На сумму')), default='percent') price_value = db.IntField(required=True) timer_type = db.StringField(choices=(('date', u'До даты'), ('time', u'По времени')), default='date') timer_settings = db.DictField(required=True) created_at = db.DateTimeField() prices = db.EmbeddedDocumentField('OfferPrices') def __unicode__(self): return str(self.id) @classmethod def create_or_update(cls, offer, form): special = offer.get_special or cls() form.populate_obj(special) special.populate_price(offer) special.set_created_at() special.save() offer.update(set__special=special) return special def create_from_self(self): offer = Offer.objects(special=self).first() if offer: data = deepcopy(self._data) data.pop('id') data.pop('prices') new = self.__class__(**data) return new def set_created_at(self): self.is_active = True self.created_at = datetime.now() def populate_price(self, offer): if self.type == 'real': if not self.prices: self.prices = offer.price if self.price_type == 'percent': new_price = self.prices.ru * (1 - float(self.price_value) / 100) elif self.price_type == 'new': new_price = self.prices.ru - self.price_value offer.update(set__price__ru=new_price) offer.reload() else: if not self.prices: self.prices = offer.price if self.price_type == 'percent': new_price = self.prices.ru * (1 + float(self.price_value) / 100) elif self.price_type == 'new': new_price = self.prices.ru + self.price_value self.prices.ru = new_price def get_timer(self): if self.timer_type == 'date': date = datetime.strptime(self.timer_settings.get('timer_date'), "%d/%m/%Y").date() return date + timedelta(days=1) elif self.timer_type == 'time': now = datetime.now() delta = now - self.created_at days_step = int(self.timer_settings.get('timer_days', 1)) if self.timer_settings.get('timer_repeat') == 'on' and delta.days > days_step: full = delta.days - (delta.days % days_step) + days_step new_delta = timedelta(days=full) else: new_delta = timedelta(days=days_step) return (self.created_at + new_delta + timedelta(days=1)).date() @property def timer(self): return self.get_timer().strftime('%Y/%m/%d') @cached_property def is_over(self): now = datetime.now() is_over = now.date() >= self.get_timer() if is_over: offer = Offer.objects(special=self).first() if offer: self.remove(offer) else: self.update(set__is_active=False) return is_over def remove(self, offer): atomic = dict(set__special=None) if self.type == 'real': atomic['set__price'] = self.prices offer.update(**atomic) self.delete()