class Pair(db.Document): """ a pair holds the chats between 2 people """ pairname = db.StringField() chats = db.EmbeddedDocumentListField(Chat) person1 = db.ReferenceField(User, reverse_delete_rule=db.CASCADE, required=True) person2 = db.ReferenceField(User, unique_with="person1", reverse_delete_rule=db.CASCADE, required=True) hasBeenModified = db.BooleanField(default=False) @classmethod def getAPair(cls, person1, person2): firstTry = cls.objects(person1=person1, person2=person2).first() lastTry = cls.objects(person1=person2, person2=person1).first() return firstTry or lastTry def generate_pairname(self): return self.person1.username + "-" + self.person2.username def save(self): def addthemselves(): self.pairname = self.generate_pairname() self.person1.addToPairNames(self.pairname) self.person2.addToPairNames(self.pairname) self.person2.save() if not self.hasBeenModified: identical = Pair.objects(person1=self.person2, person2=self.person1).first() if not identical: self.hasBeenModified = True addthemselves() else: raise Exception super().save() self.person1.save() self.person2.save() def delete(self): try: x = self.person1.pairnames.index(self.pairname) y = self.person2.pairnames.index(self.pairname) except ValueError: return -1 self.person1.pairnames.pop(x) self.person2.pairnames.pop(y) super().delete() def addChat(self, **chatdict): """ adds a single chat document to the lists of chats chats args are passed as kwargs """ try: self.chats.create(**chatdict) self.chats.save() except: raise def getlastchat(self): """ returns the last added chat object as a dict""" chat = self.chats[-1] return { "sender": chat.sender, "date": chat.date.isoformat(), "message": chat.message } def getChats(self): """ returns a sorted list of chat dicts""" chats = [] for x in sorted(self.chats, key=lambda x: x.date): x.date = x.date.isoformat() chats.append({ "sender": x.sender, "date": x.date, "message": x.message }) return chats def __str__(self): return f"<{self.person1} {self.person2}>"
class Mood(db.Document): userid = db.IntField(unique=True) mood = db.StringField(max_length=10) streak = db.IntField() date = db.IntField()
class Vendor(db.Document): vend = db.StringField(db_field="c", required=True, Uniqe=True)
class Note(db.Document): created_at = db.DateTimeField() text = db.StringField()
class Course(db.Document): courseID = db.StringField( maxlength=10, unique=True ) title = db.StringField( maxlength = 100 ) description = db.StringField( maxlength = 255 ) credits = db.IntField() term = db.StringField( maxlength=25 )
class CouponCode(db.Document): coupon_code_id = db.StringField(primary_key=True) store = db.ReferenceField(Store, db_field="store_id") code = db.StringField(unique_with="store") style = db.StringField(default="dollars_off") amount = db.IntField(default=0) last_redemption = db.DateTimeField() created_at = db.DateTimeField(default=datetime.now()) updated_at = db.DateTimeField() expires_at = db.DateTimeField(default=datetime.now() + timedelta(days=30)) voided_at = db.DateTimeField() def is_valid(self): """ checks if coupon code is still valid :return: boolean """ return self.voided_at is None and datetime.now() < self.expires_at def redeem(self, invoice): """ adds discount to invoice, creates redemption record :param invoice: invoice :return: redemption object """ if self.is_valid(): redemption = CouponCodeRedemption( coupon_code_redemption_id=str(uuid.uuid4().int), coupon_code=self, invoice=invoice ).save() if self.style == "dollars_off": invoice.discount_amount_cents = min([invoice.get_subtotal_amount(), self.amount]) redemption.amount_in_cents = min([invoice.get_subtotal_amount(), self.amount]) invoice.discount_amount_cents = min([invoice.get_subtotal_amount() , invoice.get_subtotal_amount() * (self.amount / 100.0)]) redemption.discount_amount_cents = min([invoice.get_subtotal_amount() , invoice.get_subtotal_amount() * (self.amount / 100.0)]) self.last_redemption = datetime.now() self.save() invoice.save() redemption.save() return redemption return None def to_dict(self): redemption_count = CouponCodeRedemption.objects.filter(coupon_code=self).count() return { "code": self.code, "style": self.style, "amount": self.amount, "created_at": self.created_at, "updated_at": self.updated_at, "expires_at": self.expires_at, "voided_at": self.voided_at, "store": self.store.name, "redemption_count": redemption_count } meta = { 'indexes': [('code',)] }
class CouponCodeRedemption(db.Document): coupon_code_redemption_id = db.StringField(primary_key=True) coupon_code = db.ReferenceField(CouponCode, db_field="coupon_code_id") invoice = db.ReferenceField(Invoice, db_field="invoice_id") amount_in_cents = db.IntField() created_at = db.DateTimeField(default=datetime.now())
class adminLogin(db.Document): email = db.StringField(max_length=50, validators=[DataRequired(), Email()]) password = db.StringField(max_length=50, validators=[DataRequired()])
class contactUsQuery(db.Document): email = db.StringField(max_length=50, validators=[DataRequired(), Email()]) name = db.StringField(max_length=50, validators=[DataRequired()]) queryDescription = db.StringField(max_length=50, validators=[DataRequired()])
class Course(db.Document): courseID = db.StringField(unique=True, max_length=10) title = db.StringField(max_length=100) description = db.StringField(max_length=250) credits = db.IntField(max_length=30) term = db.StringField(max_length=30)
class test_details(db.Document): testId = db.IntField(unique=True) testName = db.StringField() rate = db.IntField()
class Creds(db.Document): user = db.StringField(db_field="u", required=True) password = db.StringField(db_field="p", required=True) ipaddress = db.StringField(db_field="i", required=True)
class User(db.Document): userID = db.StringField(unique=True, sparse=True) firstName = db.StringField(max_length=60) lastName = db.StringField(max_length=60) email = db.StringField(max_length=60) password = db.StringField(max_length=30)
class Chat(db.EmbeddedDocument): sender = db.StringField(required=True) message = db.StringField(required=True) date = db.DateTimeField(default=datetime.datetime.utcnow())
class ViewDetails(db.Document): medicine_name = db.StringField(max_length=100) test_name = db.StringField(max_length=100)
class insertProduct(db.Document): productName = db.StringField(max_length=50, validators=[DataRequired()]) category = db.StringField(max_length=50, validators=[DataRequired()]) price = db.IntField(validators=[DataRequired()]) imageFile = db.ImageField(thumbnail_size=(150, 150, False))
class User(db.Document): user_id = db.IntField(unique=True) first_name = db.StringField(max_length=50) last_name = db.StringField(max_length=50) email = db.StringField(max_length=30) password = db.StringField(max_length=30)
class Order(db.Document): order_id = db.StringField(db_field="order_id", primary_key=True) invoice = db.ReferenceField(Invoice, db_field="invoice_id") status = db.StringField(default='pending') created_at = db.DateTimeField(default=datetime.now()) shipped_at = db.DateTimeField() delivered_at = db.DateTimeField() canceled_at = db.DateTimeField() meta = {'indexes': [('order_id', ), ('invoice', )]} @classmethod def create_order(cls, invoice): """ creates a new order :param invoice: customer invoice to be fulfilled :return: order object """ order = cls(order_id=str(uuid.uuid4().int), invoice=invoice).save() invoice_line_items = InvoiceLineItem.objects.filter(invoice=invoice, type="item").all() for invoice_line_item in invoice_line_items: OrderLineItem.create_order_line_item( order=order, invoice_line_item=invoice_line_item) return order @classmethod def get_orders(cls, request, customer_id=None): store = Store.objects.filter(app_id=request.headers.get('APP-ID'), deleted_at=None).first() customers = Customer.objects.filter(store_id=store) invoices = Invoice.objects.filter(customer__in=customers) orders = Order.objects.filter(invoice__in=invoices) if customer_id is not None: customer_invoices = Invoice.objects.filter(customer=customer_id) orders = Order.objects.filter(invoice__in=customer_invoices) if "status" in request.args: orders = orders.filter(status=request.args.get("status")) if "created_at_startdate" in request.args: try: start = datetime.strptime( request.args.get("created_at_startdate"), "%Y%m%d") orders = orders.filter(created_at__gte=start) except ValueError: raise IncorrectDateFormat if "delivered_at_startdate" in request.args: try: start = datetime.strptime( request.args.get("delivered_at_startdate"), "%Y%m%d") orders = orders.filter(delivered_at__gte=start) except ValueError: raise IncorrectDateFormat if "canceled_at_startdate" in request.args: try: start = datetime.strptime( request.args.get("canceled_at_startdate"), "%Y%m%d") orders = orders.filter(canceled_at__gte=start) except ValueError: raise IncorrectDateFormat if "shipped_at_startdate" in request.args: try: start = datetime.strptime( request.args.get("shipped_at_startdate"), "%Y%m%d") orders = orders.filter(shipped_at__gte=start) except ValueError: raise IncorrectDateFormat if "created_at_enddate" in request.args: try: end = datetime.strptime( request.args.get("created_at_startdate"), "%Y%m%d") orders = orders.filter(created_at__lte=end) except ValueError: raise IncorrectDateFormat if "delivered_at_enddate" in request.args: try: end = datetime.strptime( request.args.get("delivered_at_startdate"), "%Y%m%d") orders = orders.filter(delivered_at__lte=end) except ValueError: raise IncorrectDateFormat if "canceled_at_enddate" in request.args: try: end = datetime.strptime( request.args.get("canceled_at_startdate"), "%Y%m%d") orders = orders.filter(canceled_at__lte=end) except ValueError: raise IncorrectDateFormat if "shipped_at_enddate" in request.args: try: end = datetime.strptime( request.args.get("shipped_at_startdate"), "%Y%m%d") orders = orders.filter(shipped_at_lte=end) except ValueError: raise IncorrectDateFormat return orders
class Invoice(db.Document): invoice_id = db.StringField(db_field="invoice_id", primary_key=True) customer = db.ReferenceField(Customer, db_field="customer_id") cart = db.ReferenceField(Cart, db_field="cart_id") state = db.StringField(default="open") gift_card_used_amount_in_cents = db.IntField(default=0) credit_used_amount_in_cents = db.IntField(default=0) discount_amount_cents = db.IntField(default=0) created_at = db.DateTimeField(default=datetime.now()) closed_at = db.DateTimeField() meta = { 'indexes': [('customer', ), ('cart', )] } def create_invoice_line_items(self): invoice_line_items = [] for cart_item in self.cart.get_cart_items(): invoice_line_item = InvoiceLineItem( invoice_line_item_id=str(uuid.uuid4().int), invoice=self, cart_item=cart_item, product=cart_item.product_id, quantity=cart_item.quantity, unit_amount_in_cents=cart_item.product_id.sale_price_in_cents, total_amount_in_cents=cart_item.product_id.sale_price_in_cents*cart_item.quantity, type="item" ) invoice_line_items.append(invoice_line_item) invoice_line_item.invoice_created_at = datetime.now() invoice_line_item.save() return invoice_line_items def get_total_amount(self): """ returns the sum of total amount of invoice line items """ invoice_line_items = InvoiceLineItem.objects.filter(invoice=self).all() return sum([invoice_line_item.total_amount_in_cents for invoice_line_item in invoice_line_items]) def get_tax_amount(self): """ returns the sum of tax amount of invoice line items """ invoice_line_items = InvoiceLineItem.objects.filter(invoice=self).all() return sum([invoice_line_item.tax_amount_in_cents for invoice_line_item in invoice_line_items]) def get_subtotal_amount(self): """ returns invoice subtotal total_amount + tax_amount - gift_card_used_amount - credit_used_amount """ return self.get_total_amount() - self.gift_card_used_amount_in_cents - self.credit_used_amount_in_cents \ + self.get_tax_amount() - self.discount_amount_cents def get_pre_tax_amount(self): """ returns invoice pre tax amount total_amount - gift_card_used_amount - credit_used_amount """ return self.get_total_amount() - self.gift_card_used_amount_in_cents - self.credit_used_amount_in_cents @classmethod def get_all_invoices(cls, request): """ :param request: request object to get current store and query params :return: BaseQuerySet object of all invoices for store """ store = Store.objects.filter(app_id=request.headers.get('APP-ID'), deleted_at=None).first() customers = Customer.objects.filter(store_id=store) invoices = Invoice.objects.filter(customer__in=customers) if 'closed' not in request.args: invoices = invoices.filter(state="open") else: if request.args.get("closed").lower() != "true": invoices = invoices.filter(state="open") if "startdate" in request.args: try: start = datetime.strptime(request.args.get("startdate"), "%Y%m%d") invoices = invoices.filter(created_at__gt=start) except ValueError: raise IncorrectDateFormat if "enddate" in request.args: try: end = datetime.strptime(request.args.get("enddate"), "%Y%m%d") invoices = invoices.filter(created_at__lt=end) except ValueError: raise IncorrectDateFormat return invoices meta = { 'indexes': [('customer', ), ('invoice_id', ), ('cart', )] } @classmethod def get_top_N_products(cls, customer, num_items, request): """ returns the top 10 products purchased by customer :param customer: customer of note :return: Produce query object """ invoices = Invoice.objects.filter(customer=customer, state="collected") invoice_line_items = InvoiceLineItem.objects.filter(invoice__in=invoices).all() products = {} for invoice_line_item in invoice_line_items: if invoice_line_item.product.product_id in products.keys(): products[invoice_line_item.product.product_id] += invoice_line_item.quantity else: products[invoice_line_item.product.product_id] = invoice_line_item.quantity product_counts = dict(Counter(products).most_common(num_items)) results = Product.objects.filter(product_id__in=product_counts.keys()) results = paginated_results(objects=results, collection_name='product', request=request , per_page=10, serialization_func=products_obj, dictionary=True) for product in results["products"]: product["num_ordered"] = product_counts[product["product_id"]] return sorted(results["products"], key=lambda product: product["num_ordered"], reverse=True) def get_invoice_line_items(self): """ returns all line items for invoice :return: collection of invoice line item objects """ return InvoiceLineItem.objects.filter(invoice=self).all()
class Enrollment(db.Document): # creating foreign keys to access the required data from other models # To Access the default field generated by MongoDB, the variable should be as db.ObjectIdFiels user_id = db.IntField() course_id = db.StringField( max_length=10 )
class Enrollment(db.Document): userid = db.IntField() #ObjectIdField() courseID = db.StringField( max_length=100 )
class Universitymail(db.Document): user_id = db.IntField( unique=True) email = db.StringField( max_length=30, unique=True ) role = db.StringField( max_length=50 )
class Customer(db.Document): customer_id = db.StringField(db_field="customer_id", primary_key=True) password_hash = db.StringField() store_id = db.ReferenceField(Store, db_field="store_id") currency = db.StringField(db_field="currency") email = db.StringField(db_field="email") first_name = db.StringField(db_field="first_name") last_name = db.StringField(db_field="last_name") total_spent = db.DecimalField(db_field="total_spent", default=0) last_order_date = db.DateTimeField(db_field="last_order_date") last_cart_activity_at = db.DateTimeField(db_field="last_cart_activity_at") last_cart_created_at = db.DateTimeField(db_field="last_cart_created_at") log_out_expires_at = db.DateTimeField(default=datetime.now()) emails = db.ListField(db.EmbeddedDocumentField(Email)) confirmed_on = db.DateTimeField() confirmation_token = db.StringField() confirmation_token_expires_at = db.DateTimeField() last_seen_date = db.DateTimeField(default=datetime.now()) created_at = db.DateTimeField(default=datetime.now()) updated_at = db.DateTimeField(default=datetime.now()) deleted_at = db.DateTimeField() meta = {'indexes': [('customer_id', ), ('email', )]} @classmethod def get_customer(cls, customer_id, request): store = Store.objects.filter(app_id=request.headers.get('APP-ID'), deleted_at=None).first() return Customer.objects.filter(customer_id=customer_id, store_id=store, deleted_at=None).first() @classmethod def get_customer_by_email(cls, email, request): store = Store.objects.filter(app_id=request.headers.get('APP-ID'), deleted_at=None).first() return Customer.objects.filter(email=email, store_id=store, deleted_at=None).first() @classmethod def get_customer_by_token(cls, token): return Customer.objects.filter(confirmation_token=token, deleted_at=None).first() def add_address(self, request, is_primary=False): """ adds a new address based on request :param request: will pull data from flask request object :param is_primary: set new address to primary if true :return: address object """ new_address = Address(address_id=str(uuid.uuid4().int), customer_id=self, street=request.json.get("street"), city=request.json.get("city"), zip=request.json.get("zip"), state=request.json.get("state"), country=request.json.get("country")).save() if is_primary: new_address.make_primary() return new_address def get_primary_address(self): """ :return: current primary address if exists """ return Address.objects.filter(customer_id=self.customer_id, deleted_at=None, is_primary=True).first() def get_addresses(self): """ :return: all not deleted customer addresses """ return Address.objects.filter(customer_id=self.customer_id, deleted_at=None) def set_password(self, password): """ creates password for user :param password: new password :return: null """ self.password_hash = generate_password_hash(password) self.save() def check_password(self, password): """ checks if customer password is correct :param password: password to check :return: boolean """ return check_password_hash(self.password_hash, password) def login(self): """ logs customer in :return: null """ self.log_out_expires_at = datetime.now() + timedelta(hours=24) self.last_seen_date = datetime.now() self.save() def logout(self): """ logs customer out :return: null """ self.log_out_expires_at = datetime.now() self.save() def add_email(self, new_email, is_primary=False): """ adds a new email :param new_email: new email address :param is_primary: true if new email address should :return: null """ for email in self.emails: if is_primary: email.is_primary = False if email.email == new_email and email.deleted_at is None: raise DuplicateDataError new_email_document = Email(email_id=str(uuid.uuid4().int), email=new_email, is_primary=is_primary) if is_primary: self.email = new_email self.updated_at = datetime.now() self.emails.append(new_email_document) self.save() def get_emails(self): """ return list of active emails :return: list of email objects """ active_emails = [] for email in self.emails: if email.deleted_at is None: active_emails.append(email) return active_emails def delete_email(self, email_to_delete): """ deletes a customer email :param email_to_delete: email to be deleted :return: email object """ for email in self.emails: if email.email == email_to_delete and email.deleted_at is None: email.deleted_at = datetime.now() email.updated_at = datetime.now() self.updated_at = datetime.now() self.save() return email return None def make_email_primary(self, new_primay_email): if new_primay_email not in [email.email for email in self.emails]: return None new_primay_email_object = None for email in self.emails: if email.email == new_primay_email: email.is_primary = True new_primay_email_object = email else: email.is_primary = False self.save() return new_primay_email_object def send_email(self, subject, body): """ sends an email to the customers primary email :return: none """ msg = Message(subject, sender="*****@*****.**", recipients=[self.email]) msg.html = body mail.send(msg) def send_confirmation(self): """ sends confirmation email :return: none """ self.confirmation_token = str(uuid.uuid4().int) self.confirmation_token_expires_at = datetime.now() + timedelta( hours=24) self.save() subject = "Store Confirmation" link = "localhost/customer/confirm/" + self.confirmation_token html = "<html>Please click the link to confirm your registration: <a href={}>link</a></html>".format( link) self.send_email(subject=subject, body=html)
class Professor(db.Document): prof_id = db.IntField( unique=True) Name = db.StringField( max_length=50 ) Designation = db.StringField( max_length=50 ) Dept = db.StringField( max_length=30 ) MailID = db.StringField( max_length=30 )
class Enrollment(db.Document): user_id = db.IntField() courseID = db.StringField( maxlength=10 )
class Medicine(db.Document): medicine_name = db.StringField(max_length=100) quantity = db.IntField() rate = db.IntField() amount = db.IntField()
class GenreDB(db.Document): """ Genre will store the genres to be assigned to games. Represents the Genre object to be mapped to the database Attributes: external_id - unique representation data to send to clients genre - Attributes: external_id {String} -- to pass to the client (string) genre {dict} -- a key-value data set indicating the idiom and the value representing the genre in the idiom. Example: {'en':'adventure'} active {boolean} -- informs if the genre is active (valid) assigned_to {GenreDB} -- when reassigned, the current genre is no longer valid, this value is the one to be used assigned_from {list of GenreDB} -- One genre may be assigned from some others. Having this data does not validate the genre as active. It is possible to reassign it to other genre. Methods: to_obj: Returns a python dict representation of the data Action Methods: increase_genre: Increases a genre count (or initializes one with 1) in the game representation decrease_genre: Decreases a genre count (maintaining the lower limit as 0) in the game representation get_genres: Returns a list of the ORM objects of all the genres in game whose count>0 update_data: Disregards thecurrent genreCount and generates another one from the UserGameGenre collection Class/Static Methods: map_genre get_all_genres get_genres (in language) get_genre_obj get_or_create_genre """ external_id = db.StringField(db_field="external_id", unique=True) # pylint: disable=no-member genre = db.DictField(db_field = "genre") # pylint: disable=no-member reassigned_to=db.ReferenceField("self",db_field='reassiged_to') # pylint: disable=no-member reassigned_from=db.ListField(db.ReferenceField('self'),db_field='reassiged_from') # pylint: disable=no-member created = db.DateTimeField(db_field="created", default = datetime.utcnow) # pylint: disable=no-member updated = db.DateTimeField(db_field="updated", default = datetime.utcnow) # pylint: disable=no-member active = db.BooleanField(db_field="active", required=True, default=True) # pylint: disable=no-member meta = { "indexes": [("external_id", "genre", "active")] } def to_obj(self): return GenreAO.from_db(self) def get_reassigned_to_obj(self): retorno=None if(self.reassigned_to): retorno=self.reassigned_to.to_obj() return retorno @staticmethod def get_genre(eid): if not isinstance(eid,str): raise TypeError("ERROR: Invalid type for the identification data.") dbdata = GenreDB.objects.filter(external_id=eid).first() # pylint: disable=no-member if (not dbdata) or (not dbdata.external_id==eid): raise RuntimeError("ERROR: Persistent Data not Found or Mismatched.") return dbdata @staticmethod #TODO: def reassign(old,new): """ Maps the old genre, making it inactive to the new genre, calling the update in the games that were classified with both via UserGameGenre. The process is done via UserGameGenre due to the possibility of some users to have assigned both genres to a game. This invalidates one of the genres and maintains the sanity of the statistical data within the game. This reassignment has 2 purposes: 1 - replace one genre for the other or 2 - merge 2 genres representing the same, but with different languages. For the 1st, imagine someone set "graphic adventure" for a genre and other set just "adventure". Both represents the adventure genre, but one specifically states it has graphics It is of no concern of ours if the game has graphics or not, only the genre, so, the 1st genre will be disregarded. For the 2nd, imagine one started a genre for 'pt' saying: "aventura", and other set a genre for 'en' saying: "adventure". Both represent the same genre, but in different language This form, the assignment is a merge, producing 1 genre with the 2 idioms in the list. Arguments: old {GenreDB} -- The genre to become inactive new {GenreDB} -- The genre to become active TODO: This is a purely administrative task. The genres will be requested to be add by the users, the administrators will attend. So, if no user will tamper with this data, it can be coded later. """ #retrieve all users who assigned only the old genre to the game # onlyOld=UserGameGenre.objects(__raw__={"$and":{"$not":{"$in":new},"$in":old}}) # for ugg in onlyOld: # ugg.addGenre(new) # ugg.removeGenre(old) # ugg.save() ### remove the old genre, add the new #retrieve all users who assigned both genres to the game # both=UserGameGenre.objects(__raw__={"$and":{$in":new,"$in":old}) # for ugg in both: # ugg.remove(old) # ugg.save() ### remove just the old genre #assign the references # old.reassigned_to=new # old.active=false # if not new.reassigned_from: # new.reassigned_from=[] # new.reassigned_from.append(old) # old.save() # new.save() pass @classmethod def pre_save(cls, sender, document, **kwargs): """ prior to saving the genre set the external_id Arguments: sender {GenreDB} -- The sender of the signal document {GenreDB} -- The instance of the document """ if(not document.external_id): document.external_id=str(uuid4()) @classmethod def post_save(cls, sender, document, **kwargs): """ After saving the genre check if the GamesGenresDB data was created Arguments: sender {GenreDB} -- The sender of the signal document {GenreDB} -- The instance of the document """ from game.models.user_game_genre import GamesGenresDB genreGameList=GamesGenresDB.objects.filter(genre=document).first() # pylint: disable=no-member if(not genreGameList): #there is no genre for the games to be assigned to... create one genreGameList=GamesGenresDB() genreGameList.genre=document genreGameList.gamesList=[] genreGameList.save()
class Test(db.Document): test_name = db.StringField(max_length=100) amount = db.IntField()
class PersuasiveFunctionDB(db.Document): external_id = db.StringField(db_field="external_id", required=True) # pylint: disable=no-member interactivity = db.ReferenceField(BehaviorDB, db_field="interactivity", required=True) # pylint: disable=no-member ludic = db.ReferenceField(BehaviorDB, db_field="ludic", required=True) # pylint: disable=no-member gamefication = db.ReferenceField(BehaviorDB, db_field="gamefication", required=True) # pylint: disable=no-member updated = db.DateTimeField(db_field="updated", required=True, default=datetime.utcnow) # pylint: disable=no-member created = db.DateTimeField(db_field="created", required=True, default=datetime.utcnow) # pylint: disable=no-member def to_obj(self): return PersuasiveFunctionAO.from_db(self) def __repr__(self): retorno = "external_id: " + self.external_id if self.external_id else "None**" retorno += "\n" + "*" * 50 + "\ninteractivity: " + self.interactivity.__repr__( ) retorno += "\n" + "*" * 50 + "\nludic: " + self.ludic.__repr__() retorno += "\n" + "*" * 50 + "\ngamefication: " + self.gamefication.__repr__( ) return retorno def __semi_hash__(self): """ The __semi_hash__ constructs the string representing the function disregarding if it is DB or AO This allows for semi-contextual, but meaningful, comparisons and code economy. The calculation is performed in the following form: the external_id concatenated with the string concatenation of every behavior semi_hashes (as string), provided in a sorted list Returns the string computed. """ the_ret = (self.external_id if self.external_id else "None") + " - " + self.interactivity.__semi_hash__( ) + " - " + self.ludic.__semi_hash__( ) + " - " + " - " + self.gamefication.__semi_hash__( ) + " - " + str(self.updated) return the_ret def __hash__(self): the_string = "DB " + self.__semi_hash__() return hash(the_string) @staticmethod def __persist__(pf): if not isinstance(pf, PersuasiveFunctionAO): raise TypeError( "ERROR: Argument is not a valid PersuasiveFunctionAO object.") #get the DB object of the function to_save = PersuasiveFunctionDB.objects.filter( external_id=pf.external_id).first() # pylint: disable=no-member if not to_save: raise RuntimeError( "ERROR: Unable to retrieve reference to persist - PersuasiveFunctionDB - " + pf.external_id) #Behavior objects already saved. Just retrieve the DB reference from them interDB = BehaviorDB.objects.filter( external_id=pf.interactivity.external_id).first() # pylint: disable=no-member ludDB = BehaviorDB.objects.filter( external_id=pf.ludic.external_id).first() # pylint: disable=no-member gameDB = BehaviorDB.objects.filter( external_id=pf.gamefication.external_id).first() # pylint: disable=no-member to_save.interactivity = interDB to_save.ludic = ludDB to_save.gamefication = gameDB to_save.updated = datetime.utcnow() try: to_save.save() except: the_log.log( "ERROR: Persuasive Function not persisted in _persist_.") finally: return to_save @staticmethod def __create_persistence__(): """ Create the persistence object for the persuasive function. (use as constructor) The behaviors are created and assigned to the function If errors occur, the behaviors will be deleted and the function will not be created Raises: RuntimeError -- Error creating the behaviors RuntimeError -- Error creating PersuasiveFunctionDB - external_id not returned RuntimeError -- Error creating PersuasiveFunctionDB - general error Returns: PersuasiveFunctionDB -- The DB object persisted (with valid external_id and oid) """ to_save = PersuasiveFunctionDB() ludic_ = None interactivity_ = None gamefication_ = None not_err = set() # Try creating the behaviors. Adding to the not_err set try: ludic_ = BehaviorDB.__create_persistence__("LUDIC") interactivity_ = BehaviorDB.__create_persistence__("INTERACTIVITY") gamefication_ = BehaviorDB.__create_persistence__("GAMEFICATION") #set the data for the bookkeping if error happened not_err = set([ludic_, interactivity_, gamefication_]) if not ludic_ or not ludic_.external_id: #error persisting ludic. discard it from the set not_err.discard(ludic_) if not interactivity_ or not interactivity_.external_id: #error persisting interactivity. discard it from the set not_err.discard(interactivity_) if not gamefication_ or not gamefication_.external_id: #error persisting gamefication. discard it from the set not_err.discard(gamefication_) except RuntimeError as e: for beh in not_err: #it was created, so we delete... it is empty! beh.delete() raise RuntimeError("ERROR: Error creating BehaviorDB Object. " + str(e)) #all were created, no error made to_save.ludic = ludic_ to_save.interactivity = interactivity_ to_save.gamefication = gamefication_ try: to_save.save() if not to_save.external_id: #there goes all the work! if no external_id is provided, it is an error! ludic_.delete() interactivity_.delete() gamefication_.delete() raise RuntimeError( "ERROR: Error creating PersuasiveFunctionDB object. Persistence did not return an external_id" ) except RuntimeError as e: #there goes all the work! ludic_.delete() interactivity_.delete() gamefication_.delete() raise RuntimeError( "ERROR: Error creating PersuasiveFunctionDB object. - " + str(to_save), e) return to_save @classmethod def pre_save(cls, sender, document, **kwargs): """ prior to saving the function it is needed to guarantee saving their reference data. (is it?) Arguments: sender {PersuasiveFunctionDB} -- The sender of the signal document {PersuasiveFunctionDB} -- The instance of the document """ if (not document.external_id): document.external_id = str(uuid4())
class Product(db.Document, SearchableMixin): __searchable__ = ['description', 'product_type', 'title', 'vendor', 'tags'] __searchable_documents__ = ['tags'] product_id = db.StringField(db_field="id", primary_key=True) title = db.StringField(db_field="title") product_type = db.StringField(db_field="product_type") description = db.StringField() vendor = db.StringField(db_field="vendor") store = db.ReferenceField(Store, db_field="store_id") inventory = db.IntField(db_field="inventory", default=0) sale_price_in_cents = db.IntField() tags = db.ListField(db.EmbeddedDocumentField(ProductTag)) created_at = db.DateTimeField(default=datetime.now()) updated_at = db.DateTimeField(default=datetime.now()) deleted_at = db.DateTimeField() meta = { 'indexes': [('id', 'store', 'deleted_at'), ('vendor', 'product_type', 'store', 'deleted_at'), ('product_type', 'store', 'deleted_at'), ('vendor', 'store', 'deleted_at')] } def adjust_inventory(self, amount): new_amount = amount + self.inventory if new_amount < 0: raise ProductInventoryLessThanZeroException self.inventory = new_amount self.save() def set_inventory(self, amount): if amount < 0: raise ProductInventoryLessThanZeroException self.inventory = amount self.save() def add_tag(self, new_tag): """ adds a new tag to product :param new_tag: new tag :return: null """ if new_tag in [tag.tag for tag in self.tags]: raise DuplicateDataError new_tag_object = ProductTag(product_tag_id=str(uuid.uuid4().int), tag=new_tag) self.tags.append(new_tag_object) self.updated_at = datetime.now() self.save() def get_tags(self): """ return list of active tags :return: list of tag objects """ active_tags = [] for tag in self.tags: if tag.deleted_at is None: active_tags.append(tag) return active_tags def delete_tags(self, tag_to_delete): """ deletes one or all tags :param tag_to_delete: tag to be deleted :return: list of tag objects """ deleted_tags = [] for tag in self.tags: if tag.deleted_at is None and (tag.tag == tag_to_delete or tag_to_delete is None): tag.deleted_at = datetime.now() deleted_tags.append(tag) self.save() return deleted_tags def to_search_format(self, field_name): if field_name == 'tags': return " ".join([tag.tag for tag in self.tags])