class HostRule(db.Document): """ Host Rule to add custom Parameters for importers or exporters """ name = db.StringField(required=True, unique=True) conditions = db.ListField(db.EmbeddedDocumentField(HostCondition)) params = db.ListField(db.EmbeddedDocumentField(HostParams)) enabled = db.BooleanField()
class ActionRule(db.Document): """ Rule to control Actions based on labels """ name = db.StringField(required=True, unique=True) condition_typ = db.StringField(choices=rule_types) conditions = db.ListField(db.EmbeddedDocumentField(ActionCondition)) outcome = db.ListField(db.EmbeddedDocumentField(ActionOutcome)) last_match = db.BooleanField(default=False) enabled = db.BooleanField() meta = { 'strict': False, }
class User(db.Document, UserMixin): def __str__(self): return self.full_name meta = { 'allow_inheritance': True, 'indexes': [ 'id', 'slug', ], } email = db.StringField(max_length=128, required=True) password = db.StringField(max_length=128, required=True) full_name = db.StringField(max_length=128, required=True) slug = db.StringField(max_length=128, required=True) subjects = db.ListField(db.EmbeddedDocumentField(Subject)) def get_id(self): return str(self.id) @staticmethod def authenticate(email, password): user = User.objects(email=email, password=password).first() return user @classmethod def pre_save(cls, sender, document, **kwargs): document.slug = slugify(document.full_name) document.email = document.email.lower()
class BesoinFinancier(db.Document): commande = db.StringField() fournisseur = db.StringField() montant = db.FloatField() avance = db.FloatField() paye = db.FloatField() date_echeance = db.DateTimeField() projet_id = db.ReferenceField(Projet) attente = db.BooleanField(default=True) rejet = db.BooleanField(default=False) parent = db.ReferenceField('self') last_child = db.BooleanField(default=False) updated = db.ListField(db.EmbeddedDocumentField(Update_Besoin)) def child(self): childs = BesoinFinancier.objects(parent=self.id) return childs def lasted_child(self): last = BesoinFinancier.objects(Q(parent=self.id) & Q(last_child=True)).first() return last def notified(self): data = [] for notifie in self.updated: if notifie.notified: data.append(notifie) return data
class LabelRule(db.Document): """ Rule to filter Labels """ name = db.StringField(required=True, unique=True) conditions = db.ListField(db.EmbeddedDocumentField(LabelCondition)) outcome = db.ListField(db.StringField(choices=label_outcome_types)) enabled = db.BooleanField()
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 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])
class Projet(db.Document): code = db.StringField() titre = db.StringField() heure = db.IntField() montant = db.FloatField() date_start = db.DateTimeField() date_end = db.DateTimeField() facturable = db.BooleanField() domaine_id = db.ReferenceField(Domaine) client_id = db.ReferenceField(Client) service_id = db.ReferenceField(Service) prospect_id = db.ReferenceField(Client) responsable_id = db.ReferenceField(Users) closed = db.BooleanField(default=False) suspend = db.BooleanField(default=False) montant_projet_fdt = db.FloatField() attente = db.BooleanField(default=False) rejet = db.BooleanField(default=False) updated = db.ListField(db.EmbeddedDocumentField(Update_Projet)) def ratio_user(self, user_id): from ..tache.models_tache import Tache, Users user = Users.objects.get(id=user_id) tache_projet = Tache.objects(Q(projet_id=self.id) & Q(user_id=user.id)) total = 0.0 for tache in tache_projet: if tache.prestation_sigle() == 'PRO' and tache.facturable: user_taux = tache.get_user().tauxH time = tache.detail_heure pre_total = user_taux * time total += pre_total ratio = 0.0 if self.montant_projet_fdt: ratio = total / self.montant_projet_fdt return round(ratio, 1) def besoin(self, rejet=False, attente=True): besoins = BesoinFinancier.objects( Q(projet_id=self.id) & Q(rejet=rejet) & Q(attente=attente)).order_by('-date_echeance') return besoins def besoin_unsolde(self): besoin = [] besoins = BesoinFinancier.objects( Q(projet_id=self.id) & Q(attente=False) & Q(parent=None)).order_by('-date_echeance') for bes in besoins: if len(bes.child()): if bes.lasted_child().paye < bes.lasted_child().montant: besoin.append(bes) else: if bes.paye < bes.montant: besoin.append(bes) return besoin def notified(self): data = [] for notifie in self.updated: if notifie.notified: data.append(notifie) return data
class User(BaseDocument): control = db.EmbeddedDocumentField(Control, verbose_name=u'control', required=False) username = db.StringField(verbose_name=u'login', max_length=30, required=True, unique=True) name = db.StringField(verbose_name=u'nome', max_length=100) institution = db.StringField(verbose_name=u'institution', required=True, max_length=100) email = db.EmailField(verbose_name=u'e-mail', max_length=100, required=True, unique=True) pw_hash = db.StringField(verbose_name=u'senha', max_length=100, required=True) is_active = db.BooleanField(verbose_name=u'ativo', default=True, required=True) is_superuser = db.BooleanField(verbose_name=u'super usuário', default=False, required=True) last_login = db.DateTimeField(verbose_name=u'último login', required=False) meta = {'indexes': ['username', 'email', 'control', 'is_superuser']} def __unicode__(self): return self.username def __init__(self, *args, **kwargs): password = kwargs.pop('password', None) super(User, self).__init__(*args, **kwargs) if password: self.set_password(password) def set_password(self, password): self.pw_hash = generate_password_hash( password, method=current_app.config['PROJECT_PASSWORD_HASH_METHOD']) def add_project(self, project_name): self.control.projects.append(project_name) self.save() def remove_project(self, project_name): if project_name in self.control.projects: self.control.projects.remove(project_name) self.save() def check_password(self, password): return check_password_hash(self.pw_hash, password) def refresh_last_login(self): self.last_login = datetime.now() self.save() def change_active(self, is_active): self.is_active = is_active self.save() def change_superuser(self, is_superuser): self.is_superuser = is_superuser self.save() def add_control(self): self.control = Control(projects=[]) self.save()
class Refund(db.Document): refund_id = db.StringField(primary_key=True) invoice = db.ReferenceField(Invoice, db_field="invoice_id") credit = db.ReferenceField(Credit, db_field="credit_id") state = db.StringField(default="open") refund_line_items = db.ListField(db.EmbeddedDocumentField(RefundLineItem)) created_at = db.DateTimeField(default=datetime.now()) closed_at = db.DateTimeField() @classmethod def refund_invoice(cls, invoice, refund_object=None, amount=None, credit=False): """ refunds invoice :param invoice: invoice to be refunded :param refund_object: list of objects with invoice_line_items and amounts to be refunded :param amount: amount for refund open amount :param credit: true if refund is to credit :return: refund """ refund = cls(refund_id=str(uuid.uuid4().int), invoice=invoice).save() order = Order.objects.filter(invoice=invoice).first() if amount: refund_line_item = RefundLineItem(refund_line_item_id=str( uuid.uuid4().int), total_amount_in_cents=amount) refund.refund_line_items.append(refund_line_item) refund.save() if credit: refund.create_credit() invoice.state = "partially refunded" invoice.save() return refund if refund_object is None: invoice_line_items = invoice.get_invoice_line_items() for invoice_line_item in invoice_line_items: refund.create_refund_line_item(invoice_line_item) invoice.state = "refunded" invoice.save() if order: if order.status == "pending": order.status = "canceled" order.save() else: invoice_line_item_ids = [ refund["invoice_line_item_id"] for refund in refund_object ] amounts = [refund.get("amount") for refund in refund_object] invoice_line_items = InvoiceLineItem.objects.filter( invoice_line_item_id__in=invoice_line_item_ids, invoice=invoice) for invoice_line_item in list(zip(invoice_line_items, amounts)): refund.create_refund_line_item(invoice_line_item[0], invoice_line_item[1]) refund.save() invoice.state = "partially refunded" invoice.save() if credit: refund.create_credit() return refund def create_refund_line_item(self, invoice_line_item, amount=None): """ adds a refund line item to refund :param invoice_line_item: invoice_line_item to be refunded :param amount: amount for partial refund :return: none """ if amount: total_amount = amount else: total_amount = invoice_line_item.total_amount_in_cents refund_line_item = RefundLineItem( refund_line_item_id=str(uuid.uuid4().int), invoice_line_item=invoice_line_item, total_amount_in_cents=total_amount, tax_amount_in_cents=invoice_line_item.tax_amount_in_cents) self.refund_line_items.append(refund_line_item) self.save() def get_refund_total(self): """ get the total refund amount. sum of line item total amounts :return: integer """ return sum([ refund_line_item.total_amount_in_cents + refund_line_item.tax_amount_in_cents for refund_line_item in self.refund_line_items ]) def create_credit(self): """ creates a customer credit for the total refund amount. :return: """ credit = Credit( credit_id=str(uuid.uuid4().int), customer=self.invoice.customer, original_balance_in_cents=self.get_refund_total(), current_balance_in_cents=self.get_refund_total()).save() self.credit = credit self.save()
class Host(db.Document): """ Host """ hostname = db.StringField(required=True, unique=True) labels = db.ListField(db.EmbeddedDocumentField(Label)) force_update = db.BooleanField(default=False) source_account_id = db.StringField() source_account_name = db.StringField() available = db.BooleanField() last_seen = db.DateTimeField() log = db.ListField(db.StringField()) meta = { 'strict': False, } @staticmethod def get_host(hostname): """ Return existing Host or create a object and return it """ try: return Host.objects.get(hostname=hostname) except DoesNotExist: pass new_host = Host() new_host.hostname = hostname return new_host def set_labels(self,label_dict): """ Overwrites the Labels on this object """ labels = [] for key, value in label_dict.items(): if not value: continue label = Label() label.key = key label.value = value labels.append(label) self.labels = labels def get_labels(self): """ Return Labels in Dict Format """ return dict({x.key:x.value for x in self.labels}) def add_log(self, entry): """ Add a new Entry to the Host log """ entries = self.log[:app.config['HOST_LOG_LENGTH']-1] date = datetime.datetime.now().strftime(app.config['TIME_STAMP_FORMAT']) self.log = [f"{date} {entry}"] + entries def set_account(self, account_id, account_name): """ Set account Information """ if self.source_account_id and self.source_account_id != account_id: raise HostError(f"Host {self.hostname} already importet by source {self.source_name}") self.source_account_id = account_id self.source_account_name = account_name def set_source_update(self): """ Called all the time when found on """ self.available = True self.last_seen = datetime.datetime.now() def set_source_not_found(self): """ When not found anymore on source, this will be set """ self.available = False self.add_log("Not found on Source anymore") def need_sync(self, hours=24): """ Check if the host needs to be synced from the source """ if not self.available: return True timediff = datetime.datetime.now() - self.last_seen if divmod(timediff.total_seconds(), 3600)[0] > hours: return True return False def need_update(self, hours=24*7): """ Check if we need to Update this host on the target """ # @TODO refactor need_update handling return True if not self.last_update_on_target: return True if self.force_update: self.force_update = False self.save() return True timediff = datetime.datetime.now() - self.last_update_on_target if divmod(timediff.total_seconds(), 3600)[0] > hours: return True return False