def sync_tables(): """ Periodic task for fetching and saving tables from Poster @todo #187:30min Set up scheduler for celery, docs - http://docs.celeryproject.org/en/ latest/userguide/periodic-tasks.html#id5 Also should make small refactoring: celery.py should situated in timelessis/celery.py not in timelessis/sync/celery.py """ auth_data = PosterAuthData( application_id=os.environ.get("poster_application_id"), application_secret=os.environ.get("poster_application_secret"), redirect_uri=os.environ.get("poster_redirect_uri"), code=os.environ.get("poster_code"), ) auth_token = Authenticated(auth_data=auth_data).auth() poster = Poster(auth_token=auth_token) for poster_table in poster.tables(): table = DB.session(Table).query.filter_by( name=poster_table["name"], floor_id=poster_table["floor_id"]).first() if table: new_table = Table.merge_with_poster(table, poster_table) DB.session.add(new_table) else: new_table = Table.create_by_poster(poster_table) DB.session.merge(new_table) DB.session.commit()
class Date(DB.Model): __tablename__ = "dates" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) date = DB.Column(DB.DateTime, unique=True, nullable=False) scheme_condition_id = DB.Column(DB.Integer, DB.ForeignKey("scheme_conditions.id")) scheme_condition = DB.relationship("SchemeCondition", back_populates="dates") @validate_required("date") def __init__(self, **kwargs): super(Date, self).__init__(**kwargs) def __repr__(self): return "<Date %r>" % self.id
class SchemeType(DB.Model): __tablename__ = "scheme_types" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) description = DB.Column(DB.String, unique=True, nullable=False) default_value = DB.Column(DB.String, nullable=False) value_type = DB.Column(DB.String, nullable=False) conditions = DB.relationship("SchemeCondition", order_by=SchemeCondition.id, back_populates="scheme_type") @validate_required("description", "default_value", "value_type") def __init__(self, **kwargs): super(SchemeType, self).__init__(**kwargs) def __repr__(self): return "<SchemeType %r>" % self.id
class WeekDay(DB.Model): """ WeekDay model""" __tablename__ = "weekdays" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) weekday = DB.Column(DB.Integer, unique=True, nullable=False) scheme_condition_id = DB.Column(DB.Integer, DB.ForeignKey("scheme_conditions.id")) scheme_condition = DB.relationship("SchemeCondition", back_populates="weekdays") @validate_required("weekday") def __init__(self, **kwargs): super(WeekDay, self).__init__(**kwargs) def __repr__(self): return "<Weekday %r>" % self.id
class Role(DB.Model): """Settings model for Role.""" __tablename__ = "roles" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) name = DB.Column(DB.String, unique=True) works_on_shifts = DB.Column(DB.Boolean) company_id = DB.Column(DB.Integer, DB.ForeignKey("companies.id")) company = DB.relationship("Company", back_populates="roles") employees = DB.relationship("Employee", back_populates="role") def __repr__(self): return "<Role %r>" % self.name def is_master_or_intern(self): """ @todo #341:30m Need to find nice way to understand what is role of this instance. May be it's better to introduce `type` field with choices. """ return self.name in ( "Master", "Intern", ) def is_director(self): return self.name == "Director"
class SchemeType(DB.Model): """ @todo #17:30min Continue implementation as in #17. SchemeType should have its own management pages to list, create, edit and delete them. In the index page it should be possible to sort and filter for every column. """ __tablename__ = "scheme_types" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) description = DB.Column(DB.String, unique=True, nullable=False) default_value = DB.Column(DB.String, nullable=False) value_type = DB.Column(DB.String, nullable=False) conditions = DB.relationship("SchemeCondition", order_by=SchemeCondition.id, back_populates="scheme_type") def __repr__(self): return "<SchemeType %r>" % self.id
class ReservationSettings(TimestampsMixin, DB.Model): """Settings model for Reservations""" __tablename__ = "reservation_settings" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) name = DB.Column(DB.String, unique=True) default_duration = DB.Column(DB.SmallInteger) default_deposit = DB.Column(DB.SmallInteger) sms_notifications = DB.Column(DB.Boolean) threshold_sms_time = DB.Column(DB.SmallInteger) greeting_by_time = DB.Column(DB.JSON) sex = DB.Column(DB.String)
class ItemHistory(DB.Model): """Model for item assigning history """ __tablename__ = "itemsHistory" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) start_time = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) end_time = DB.Column(DB.DateTime) employee_id = DB.Column(DB.Integer, DB.ForeignKey("employees.id")) employee = DB.relationship("Employee", back_populates="history") item_id = DB.Column(DB.Integer, DB.ForeignKey("items.id")) item = DB.relationship("Item", back_populates="history") def __repr__(self): """Return object information - String""" return f"<Item {self.id}>"
def sync_locations(): """ Periodic task for fetching and saving location from Poster """ for poster_location in __poster_api().locations(): location = DB.session(Location).query.filter_by( name=poster_location["name"], code=poster_location["code"] ).first() merge_data( model=Location, poster_data=poster_location, timelessis_data=location )
def sync_customers(): """ Periodic task for fetching and saving tables from Poster """ for poster_customer in __poster_api().customers(): customer = DB.session(Customer).query.filter_by( first_name=poster_customer["first_name"], last_name=poster_customer["last_name"] ).first() merge_data( model=Customer, poster_data=poster_customer, timelessis_data=customer )
class Comment(TimestampsMixin, DB.Model): """Model for comment business entity""" __tablename__ = "comments" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) employee_id = DB.Column(DB.Integer, DB.ForeignKey("employees.id")) body = DB.Column(DB.String, nullable=False) date = DB.Column(DB.DateTime, nullable=False) employee = DB.Column(DB.Integer, DB.ForeignKey("employees.id")) def __repr__(self): return "<Comment %r>" % self.description
def sync_tables(): """ Periodic task for fetching and saving tables from Poster @todo #187:30min Set up scheduler for celery, docs - http://docs.celeryproject.org/en/ latest/userguide/periodic-tasks.html#id5 Also should make small refactoring: celery.py should situated in timelessis/celery.py not in timelessis/sync/celery.py """ for poster_table in __poster_api().tables(): table = DB.session(Table).query.filter_by( name=poster_table["name"], floor_id=poster_table["floor_id"] ).first() merge_data( model=Table, poster_data=poster_table, timelessis_data=table )
class Role(DB.Model): """Settings model for Role.""" __tablename__ = "roles" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) name = DB.Column(DB.String, unique=True) works_on_shifts = DB.Column(DB.Boolean) company_id = DB.Column(DB.Integer, DB.ForeignKey("companies.id")) company = DB.relationship("Company", back_populates="roles") def __repr__(self): return "<Role %r>" % self.name
class Customer(PosterSyncMixin, DB.Model): """Model for customer business entity. """ __tablename__ = "customers" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) first_name = DB.Column(DB.String, nullable=False) last_name = DB.Column(DB.String, nullable=False) phone_number = DB.Column(DB.String, nullable=False) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) def __repr__(self): return "<Customer(name=%s %s)>" % (self.first_name, self.last_name) @classmethod def merge_with_poster(cls, customer: "Customer", poster_customer: dict): """ Method should return Customer object with merged data from table entity and poster customer dict """ return Customer(id=customer.id, first_name=poster_customer["firstname"], last_name=poster_customer["lastname"], phone_number=poster_customer["phone_number"], created_on=poster_customer["date_activate"], updated_on=datetime.utcnow(), poster_id=customer.poster_id, synchronized_on=datetime.utcnow()) @classmethod def create_by_poster(cls, poster_customer: dict): """ Method should return Customer object with given data from poster_customer dict """ return Customer(first_name=poster_customer["firstname"], last_name=poster_customer["lastname"], phone_number=poster_customer["phone_number"], created_on=poster_customer["date_activate"], updated_on=datetime.utcnow(), poster_id=poster_customer["client_id"], synchronized_on=datetime.utcnow())
class Customer(PosterSyncMixin, DB.Model): """Model for customer business entity. """ __tablename__ = "customers" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) first_name = DB.Column(DB.String, nullable=False) last_name = DB.Column(DB.String, nullable=False) phone_number = DB.Column(DB.String, nullable=False) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) def __repr__(self): return "<Customer(name=%s %s)>" % (self.first_name, self.last_name)
class Customer(PosterSyncMixin, DB.Model): """Model for customer business entity. @todo #102:30min Set up celery to project which will provide async jobs. Docs is here - http://flask.pocoo.org/docs/1.0/patterns/celery/ Create celery task for customer synchronization. """ __tablename__ = "customers" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) first_name = DB.Column(DB.String, nullable=False) last_name = DB.Column(DB.String, nullable=False) phone_number = DB.Column(DB.String, nullable=False) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) def __repr__(self): return "<Customer(name=%s %s)>" % (self.first_name, self.last_name)
class Customer(PosterSyncMixin, DB.Model): """Model for customer business entity. """ __tablename__ = "customers" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) first_name = DB.Column(DB.String, nullable=False) last_name = DB.Column(DB.String, nullable=False) phone_number = DB.Column(DB.String, nullable=False) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) def __repr__(self): return "<Customer(name=%s %s)>" % (self.first_name, self.last_name) @classmethod def merge_with_poster(cls, customer, poster_customer: dict): """ Method should return Customer object with merged data from table entity and poster customer dict @todo #262:30min Implement two class methods merge_with_poster and create_by_poster. merge_with_poster will merge entry entity with poster entity, we should make right fields mapping, as result returns Customer instance. The same should be made with method create_by_poster, returns Customer instance with data from poster_customer """ return cls() @classmethod def create_by_poster(cls, poster_customer: dict): """ Method should return Customer object with given data from poster_customer dict """ poster_customer return cls()
class Item(DB.Model): """Model for item entity """ __tablename__ = "items" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) name = DB.Column(DB.String, nullable=False) stock_date = DB.Column(DB.DateTime, nullable=False) comment = DB.Column(DB.String, nullable=True) company_id = DB.Column(DB.Integer, DB.ForeignKey("companies.id")) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) company = DB.relationship("Company", back_populates="items") employee_id = DB.Column(DB.Integer, DB.ForeignKey("employees.id")) empolyee = DB.relationship("Employee", back_populates="items") history = DB.relationship("ItemHistory", back_populates="item") @validate_required("name", "stock_date", "comment", "created_on") def __init__(self, **kwargs): super(Item, self).__init__(**kwargs) def assign(self, employee): """ Assigning the item to an employee """ self.employee_id = employee.id item_history = ItemHistory(employee_id=self.employee_id, item_id=self.id) def item_history(self): """ Returns item history @todo #217:30min Implement function to return item history. history() function must return item assignement history, a list of ItemHistory with all the items assignment history. Then remove skip annotation from test_items.test_item_assign """ pass def __repr__(self): """Return object information - String""" return "<Item %r>" % self.name
class SchemeCondition(DB.Model): """ @todo #43:30min Continue implementation as in #18. The possibility to create, edit, delete the conditions shall be made inside SchemeType page for consistency. """ __tablename__ = "scheme_conditions" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) scheme_type_id = DB.Column(DB.Integer, DB.ForeignKey("scheme_types.id")) value = DB.Column(DB.String, unique=True, nullable=False) priority = DB.Column(DB.Integer, nullable=False) start_time = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) end_time = DB.Column(DB.DateTime, nullable=False) weekdays = DB.relationship("WeekDay", order_by=WeekDay.id, back_populates="scheme_condition") monthdays = DB.relationship("MonthDay", order_by=MonthDay.id, back_populates="scheme_condition") dates = DB.relationship("Date", order_by=Date.id, back_populates="scheme_condition") scheme_type = DB.relationship("SchemeType", back_populates="conditions") @validate_required("value", "priority", "start_time", "end_time") def __init__(self, **kwargs): super(SchemeCondition, self).__init__(**kwargs) def __repr__(self): return "<SchemeCondition %r>" % self.id
class Item(DB.Model): """Model for item entity """ __tablename__ = "items" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) name = DB.Column(DB.String, nullable=False) stock_date = DB.Column(DB.DateTime, nullable=False) comment = DB.Column(DB.String, nullable=True) company_id = DB.Column(DB.Integer, DB.ForeignKey("companies.id")) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) company = DB.relationship("Company", back_populates="items") employee_id = DB.Column(DB.Integer, DB.ForeignKey("employees.id")) empolyee = DB.relationship("Employee", back_populates="items") history = DB.relationship("ItemHistory", back_populates="item") @validate_required("name", "stock_date", "comment", "created_on") def __init__(self, **kwargs): super(Item, self).__init__(**kwargs) def assign(self, employee): """ Assigning the item to an employee """ self.employee_id = employee.id for hist_item in self.history: if not hist_item.end_time: hist_item.end_time = datetime.utcnow break self.history.append( ItemHistory( employee_id=self.employee_id, item_id=self.id, start_time=datetime.utcnow ) ) def item_history(self): """ Returns item history """ return self.history def __repr__(self): """Return object information - String""" return "<Item %r>" % self.name
class SchemeCondition(DB.Model): __tablename__ = "scheme_conditions" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) scheme_type_id = DB.Column(DB.Integer, DB.ForeignKey("scheme_types.id")) value = DB.Column(DB.String, unique=True, nullable=False) priority = DB.Column(DB.Integer, nullable=False) start_time = DB.Column( DB.DateTime, default=datetime.utcnow, nullable=False ) end_time = DB.Column(DB.DateTime, nullable=False) weekdays = DB.relationship( "WeekDay", order_by=WeekDay.id, back_populates="scheme_condition" ) monthdays = DB.relationship( "MonthDay", order_by=MonthDay.id, back_populates="scheme_condition" ) dates = DB.relationship( "Date", order_by=Date.id, back_populates="scheme_condition" ) scheme_type = DB.relationship("SchemeType", back_populates="conditions") @validate_required("value", "priority", "start_time", "end_time") def __init__(self, **kwargs): super(SchemeCondition, self).__init__(**kwargs) def __repr__(self): return "<SchemeCondition %r>" % self.id
class Item(DB.Model): """Model for item entity @todo #15:30min Continue the implementation. Items must have their own management pages to list, create, edit, and delete them. On the index page, you should be able to sort and filter for each column. """ __tablename__ = "items" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) name = DB.Column(DB.String, nullable=False) stock_date = DB.Column(DB.DateTime, nullable=False) comment = DB.Column(DB.String, nullable=True) company_id = DB.Column(DB.Integer, DB.ForeignKey("companies.id")) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) company = DB.relationship("Company", back_populates="items") employee_id = DB.Column(DB.Integer, DB.ForeignKey("employees.id")) empolyee = DB.relationship("Employee", back_populates="items") history = DB.relationship("ItemHistory", back_populates="item") def assign(self, employee): """ Assing the item to an employee @todo #142:30min Continue implememntation of assining. Update the old ItemHistory record if current employee_id in not null. ItemHistory should have the needed functions to continue this. """ self.employee_id = employee.id item_history = ItemHistory(employee_id=self.employee_id, item_id=self.id) def __repr__(self): """Return object information - String""" return "<Item %r>" % self.name
class Item(DB.Model): """Model for item entity """ __tablename__ = "items" id = DB.Column(DB.Integer, primary_key=True, autoincrement=True) name = DB.Column(DB.String, nullable=False) stock_date = DB.Column(DB.DateTime, nullable=False) comment = DB.Column(DB.String, nullable=True) company_id = DB.Column(DB.Integer, DB.ForeignKey("companies.id")) created_on = DB.Column(DB.DateTime, default=datetime.utcnow, nullable=False) updated_on = DB.Column(DB.DateTime, onupdate=datetime.utcnow) company = DB.relationship("Company", back_populates="items") employee_id = DB.Column(DB.Integer, DB.ForeignKey("employees.id")) empolyee = DB.relationship("Employee", back_populates="items") history = DB.relationship("ItemHistory", back_populates="item") @validate_required("name", "stock_date", "comment", "created_on") def __init__(self, **kwargs): super(Item, self).__init__(**kwargs) def assign(self, employee): """ Assing the item to an employee @todo #142:30min Continue implememntation of assining. Update the old ItemHistory record if current employee_id in not null. ItemHistory should have the needed functions to continue this. """ self.employee_id = employee.id item_history = ItemHistory(employee_id=self.employee_id, item_id=self.id) def __repr__(self): """Return object information - String""" return "<Item %r>" % self.name
class PosterSyncMixin: """Mixin with fields needed for data synchronization with Poster. """ poster_id = DB.Column(DB.Integer) synchronized_on = DB.Column(DB.DateTime)