class GenericStep(db.Model): task_name = db.Property() step_number = db.Property() duration = db.Property() next = db.RelatedTo('GenericStep') depends_on = db.RelatedTo('GenericStep') needs_document = db.RelatedTo('GenericDocument') @staticmethod def create(task_name, step_number, step_duration): step = GenericStep() step.task_name = task_name step.step_number = step_number step.duration = step_duration db.graph.create(step) return step @staticmethod def all(): return [_ for _ in GenericStep.select(db.graph)] @staticmethod def get_by_step_number(step_number): return GenericStep.select( db.graph).where(step_number=step_number).first()
class Item(db.Model): label = db.Label(name="item") next = db.RelatedTo('Item') property = db.RelatedTo('Property') name = db.Property() synonym = db.Property() config = db.Property() @classmethod def create(cls, name, synonym=None, config={}): _item = cls() _item.name = name _item.score = 0 if synonym: _item.synonym = synonym if config: _item.config = config db.graph.create(_item) return _item def add_item(self, item): self.next.add(item) db.graph.push(self) return self def add_property(self, property): self.property.add(property) db.graph.push(self) return self
class Action(db.Model): number = db.Property() taken_at = db.Property() has_completed = db.RelatedTo('GenericStep') action_taken = db.RelatedTo('Action') @staticmethod def create(company_id): action = Action() a = arrow.utcnow() action.number = action.get_num_actions(company_id) action.taken_at = a.timestamp db.graph.create(action) return action def _is_client_onboard_structure_built(self, company_id): cursor = db.graph.run(( "match (:Client {company_id: '%s'})-[r:HAS_ONBOARD]->()" "return r" % company_id )) return cursor.forward() def _is_onboard_activity_structure_built(self, company_id): cursor = db.graph.run(( "match (:Client {company_id: '%s'})-[:HAS_ONBOARD]->()-[r:HAS_ACTIVITY]->()" "return r" % company_id )) return cursor.forward() def _structure_is_built(self, company_id): if self._is_client_onboard_structure_built(company_id) and self._is_onboard_activity_structure_built(company_id): return True return False def get_num_actions(self, company_id): if self._structure_is_built(company_id): cursor = db.graph.run(( "match (:Client {company_id: '%s'})-[:HAS_ONBOARD]->()-[:HAS_ACTIVITY]->()-[:ACTION_TAKEN*]->(a) " "return count(a) as num_actions" % company_id )) return cursor.next()['num_actions'] return None def add_has_completed_rel(self, company_id, step_number): if self._structure_is_built(company_id): step = GenericStep.get_by_step_number(step_number) self.has_completed.add(step) db.graph.push(self) return self raise LookupError('required graph structure missing')
class Employee(db.Model): __primarykey__ = 'id' person = db.Label() id = db.Property() email = db.Property() first_name = db.Property() last_name = db.Property() street_address = db.Property() city = db.Property() state = db.Property() zip_code = db.Property() works_for = db.RelatedTo('Company') worked_on = db.RelatedTo('Project') has_access_to = db.RelatedTo('Application') @staticmethod def push(employee_id, employee_email): employee = Employee() employee.person = True employee.id = employee_id employee.email = employee_email db.graph.push(employee) return employee
class Client(db.Model): """define the client node""" __primarykey__ = 'company_id' person = db.Label() company_id = db.Property() company_name = db.Property() has_onboard = db.RelatedTo('Onboard') @staticmethod def create(company_id, company_name): client = Client() client.person = True client.company_id = company_id client.company_name = company_name db.graph.create(client) return client @staticmethod def list_all(): """list all clients""" return [_ for _ in Client.select(db.graph)] @staticmethod def list_all_with_compliance_status(): """get a list of all clients with compliance status""" cursor = db.graph.run( ("match (c:Client)-[:HAS_ONBOARD]->(o) " "return c, o.completed AS completed, o.valid_onboard AS v " "order by c.company_name")) return [{ 'client': result['c'], 'completed': result['completed'], 'valid_onboard': result['v'] } for result in cursor] @staticmethod def list_all_with_document_status(): """get a list of all clients with document status""" cursor = db.graph.run(( "match (c:Client)-[:HAS_ONBOARD]->()-[:MISSING_DOCUMENT]->(d)-[:FOR_STEP]->(s) " "return c, d, s " "order by c.company_name, s.step_number")) return [{ 'client': result['c'], 'document_type': result['d']['document_type'], 'step_number': result['s']['step_number'] } for result in cursor]
class GenericDocument(db.Model): document_id = db.Property() document_type = db.Property() for_step = db.RelatedTo('GenericStep') @staticmethod def create(document_id, document_type): document = GenericDocument() document.document_id = document_id document.document_type = document_type db.graph.create(document) return document
class Database(db.Model): type = db.Property() in_use_by = db.RelatedFrom('Application') @staticmethod def push(database_type): database = Database() database.type = database_type db.graph.push(database) return database
class Company(db.Model): __primarykey__ = 'name' name = db.Property() @staticmethod def push(company_name): company = Company() company.name = company_name db.graph.push(company) return company
class Onboard(db.Model): """define the onboard node""" completed = db.Property() valid_onboard = db.Property() time_created = db.Property() time_completed = db.Property() has_completed = db.RelatedTo('GenericStep') invalid = db.RelatedTo('GenericStep') must_follow = db.RelatedTo('GenericProcess') missing_document = db.RelatedTo('GenericDocument') submitted_document = db.RelatedTo('GenericDocument') has_activity = db.RelatedTo('Activity') @staticmethod def create(): onboard = Onboard() onboard.completed = False onboard.valid_onboard = True a = arrow.utcnow() onboard.time_created = a.timestamp onboard.time_completed = None db.graph.create(onboard) return onboard @staticmethod def compute_average(): """calculate the average time to completion""" ttc = [ _.time_completed - _.time_created for _ in Onboard.select(db.graph) if _.time_completed ] if ttc: ave_ttc = int(round(float(sum(ttc)) / len(ttc))) return ave_ttc return None
class Property(db.Model): label = db.Label(name="property") next = db.RelatedTo('Property') name = db.Property() synonym = db.Property() score = db.Property() @classmethod def create(cls, name, synonym=None): _property = cls() _property.name = name _property.score = 0 if synonym: _property.synonym = synonym db.graph.create(_property) return _property def add_property(self, property): self.next.add(property) db.graph.push(self) return self
class Application(db.Model): __primarykey__ = 'name' crm = db.Label() erp = db.Label() compliance = db.Label() cloud = db.Label() name = db.Property() # accessed_by = db.RelatedFrom('Employee') uses_database = db.RelatedTo('Database') @staticmethod def push_crm(app_name): crm_app = Application() crm_app.crm = True crm_app.cloud = True crm_app.name = app_name db.graph.push(crm_app) return crm_app @staticmethod def push_erp(app_name): erp_app = Application() erp_app.erp = True erp_app.name = app_name db.graph.push(erp_app) return erp_app @staticmethod def push_compliance(app_name): comp_app = Application() comp_app.compliance = True comp_app.name = app_name db.graph.push(comp_app) return comp_app