コード例 #1
0
ファイル: models.py プロジェクト: gorel/dli-reports
class Department(db.Model):
    """Model for DLI's departments"""
    __tablename__ = "department"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), index=True, unique=True)
    users = db.relationship(
        User,
        backref="department",
        lazy="dynamic",
    )
    fields = db.relationship(
        Field,
        backref="department",
    )

    def __init__(self, name):
        """Initialize a Department model"""
        self.name = name

    def __repr__(self):
        """Return a descriptive representation of a Department"""
        return '<Department %r>' % self.name
コード例 #2
0
ファイル: models.py プロジェクト: gorel/dli-reports
class Field(db.Model):
    """Model for a Field within a Report"""
    __tablename__ = "field"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(32))
    ftype_id = db.Column(db.Integer, db.ForeignKey("field_type.id"))
    ftype = db.relationship(FieldType)
    department_id = db.Column(db.Integer, db.ForeignKey("department.id"))
    data_points = db.relationship(
        FieldData,
        backref='field',
        lazy='dynamic',
    )

    def __init__(self, name, ftype, department):
        """Initialize a Field model"""
        self.name = name
        self.ftype = ftype
        self.department = department

    def __repr__(self):
        """Return a descriptive representation of a Field"""
        return '<Field %r>' % self.name

    def get_data_for_date(self, ds, pretty=False):
        """Retrieve the FieldData instance for the given date stamp"""
        data_point = self.data_points.filter_by(ds=ds).first()
        if pretty:
            if data_point is not None:
                data_point = data_point.pretty_value
            else:
                data_point = ""
        return data_point

    @property
    def identifier(self):
        """Property to uniquely identify this Field"""
        return '{}: {}'.format(self.department.name, self.name)
コード例 #3
0
ファイル: models.py プロジェクト: gorel/dli-reports
class Location(db.Model):
    """Model for DLI's physical locations"""
    __tablename__ = "location"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), index=True, unique=True)
    users = db.relationship(
        User,
        backref="location",
    )

    def __init__(self, name):
        """Initialize a Location model"""
        self.name = name

    def __repr__(self):
        """Return a descriptive representation of a Location"""
        return '<Location %r>' % self.name
コード例 #4
0
ファイル: models.py プロジェクト: gorel/dli-reports
class Chart(db.Model):
    """Model for a DLI Chart"""
    __tablename__ = "chart"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), index=True)
    with_table = db.Column(db.Boolean)
    owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True)
    ctype_id = db.Column(db.Integer, db.ForeignKey("chart_type.id"))
    ctype = db.relationship(ChartType, backref="charts")
    fields = db.relationship(
        Field,
        secondary=chart_fields,
        backref='charts',
    )
    tags = db.relationship(
        Tag,
        secondary=chart_tags,
        backref='charts',
    )

    def __init__(self, name, with_table, user, ctype, fields, tags):
        """Initialize a Chart model"""
        self.name = name
        self.with_table = with_table
        self.user = user
        self.ctype = ctype
        self.fields = fields
        self.tags = tags

    def __repr__(self):
        """Return a descriptive representation of a Chart"""
        return '<Chart %r>' % self.name

    @property
    def is_pie_chart(self):
        """Return whether or not this chart is a Pie Chart"""
        ChartTypeConstants.reload()
        return self.ctype == ChartTypeConstants.PIE

    def data_points(self, min_date, max_date=None, ds_format=False):
        """Retrieve the data points needed for this chart"""
        if ds_format:
            min_ds = min_date
            max_ds = max_date
        else:
            min_ds = min_date.strftime('%Y-%m-%d')
            max_ds = datetime.datetime.now().strftime('%Y-%m-%d')
            if max_date:
                max_ds = max_date.strftime('%Y-%m-%d')

        return {
            field.identifier: {
                str(fdata.ds): str(fdata.value)
                for fdata in field.data_points.filter(
                    FieldData.ds >= min_ds).filter(FieldData.ds <= max_ds)
            }
            for field in self.fields
        }

    @property
    def tagnames(self):
        """Helper function to get the names of the Report's tags"""
        return [tag.name for tag in self.tags]

    def generated_js(self):
        """Property that represents this chart generated as C3 JavaScript"""
        min_date = datetime.datetime.now()
        ChartTypeConstants.reload()
        if self.ctype != ChartTypeConstants.PIE:
            min_date = min_date - datetime.timedelta(days=14)

        generate = 'true'
        if self.ctype == ChartTypeConstants.TABLE_ONLY:
            generate = 'false'

        return """
            var data_points = {data_points};
            var time_series = {time_series};
            var chart_type = "{chart_type}";
            var generate = {should_generate};
        """.format(
            time_series=get_time_series_sequence(min_date),
            data_points=self.data_points(min_date),
            chart_type=self.ctype.name,
            should_generate=generate,
        )
コード例 #5
0
ファイル: models.py プロジェクト: gorel/dli-reports
class Report(db.Model):
    """Model for a DLI Report"""
    __tablename__ = "report"
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), index=True)
    name = db.Column(db.String(128))
    fields = db.relationship(
        Field,
        secondary=report_fields,
        backref='reports',
    )
    tags = db.relationship(
        Tag,
        secondary=report_tags,
        backref='reports',
    )

    def __init__(self, user, name, fields, tags):
        """Initialize a Report model"""
        self.user = user
        self.name = name
        self.fields = fields
        self.tags = tags

    def __repr__(self):
        """Return a descriptive representation of a Report"""
        return '<Report %r>' % self.name

    @property
    def tagnames(self):
        """Helper function to get the names of the Report's tags"""
        return [tag.name for tag in self.tags]

    def generate_filename(self, start_ds, end_ds):
        """Generate the filename for the Excel sheet for downloads"""
        return "{filename}-{start}-to-{end}.xlsx".format(
            filename=self.name,
            start=start_ds,
            end=end_ds,
        )

    def collect_dept_data_for_template(self, ds):
        """Collect all of the department data for this Report

        Collect department data for this Report on a given day in a format
        that is easy to template for render_template functions in Jinja2
        """

        dept_data = collections.defaultdict(list)
        for field in self.fields:
            dept_data[field.department.name].append({
                'name':
                field.name,
                'value':
                field.get_data_for_date(ds, pretty=True),
            })
        return dept_data

    def excel_filepath_for_ds(self, start_ds, end_ds):
        """Return the absolute filepath for the Excel sheet on the given ds"""
        return os.path.join(
            os.path.abspath(os.path.dirname(__file__)),
            EXCEL_FILE_DIR,
            self.generate_filename(start_ds, end_ds),
        )

    def excel_file_exists(self, start_ds, end_ds):
        """Determine whether or not an Excel file for this ds exists"""
        return os.path.exists(self.excel_filepath_for_ds(start_ds, end_ds))

    def create_excel_file(self, start_ds, end_ds):
        """Generate an Excel sheet with this Report's data

        Arguments:
        start_ds - Date stamp for the start day of Report data to generate
        end_ds - Date stamp for the end day of Report data to generate
        """

        excel_helper = ExcelSheetHelper(
            filepath=self.excel_filepath_for_ds(start_ds, end_ds),
            report=self,
            date_list=generate_date_list(
                datetime.datetime.strptime(start_ds, '%Y-%m-%d'),
                datetime.datetime.strptime(end_ds, '%Y-%m-%d'),
                step=1,
            ),
        )
        excel_helper.write_all(self.collect_dept_fields(start_ds, end_ds))
        excel_helper.finalize()

    def remove_excel_files(self):
        """Delete the Excel files for this Report"""
        basepath = os.path.join(
            os.path.abspath(os.path.dirname(__file__)),
            EXCEL_FILE_DIR,
        )
        globpath = os.path.join(basepath, self.name + '*.xlsx')

        for filename in glob.glob(globpath):
            os.remove(os.path.join(basepath, filename))

    def collect_dept_fields(self, start_ds, end_ds):
        """Collect all of the department data for this Report

        The best way we can do this is to create a complex dict:
        {dept : {field : {ds : value}}}

        Arguments:
        start_ds - the beginning ds for data to collect
        end_ds - the ending ds for data to collect
        """
        dept_data = {}
        for field in self.fields:
            field_data = {
                pt.ds: pt.value
                for pt in field.data_points.filter(
                    FieldData.ds >= start_ds).filter(FieldData.ds <= end_ds)
            }
            if not dept_data.get(field.department.name):
                dept_data[field.department.name] = {}
            dept_data[field.department.name][field] = field_data
        return dept_data
コード例 #6
0
ファイル: models.py プロジェクト: gorel/dli-reports
class User(db.Model, UserMixin):
    """Model for users of the site"""
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    email = db.Column(db.String(64), index=True, unique=True)
    password = db.Column(db.String(128))
    is_admin = db.Column(db.Boolean)
    location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
    dept_id = db.Column(db.Integer, db.ForeignKey("department.id"))
    pw_reset = db.relationship(
        PasswordReset,
        backref="user",
    )
    reports = db.relationship(
        Report,
        backref="user",
    )
    charts = db.relationship(
        Chart,
        backref="user",
    )
    error_reports = db.relationship(
        ErrorReport,
        backref="user",
    )
    favorite_reports = db.relationship(
        Report,
        secondary=report_users,
        backref='favorite_users',
    )
    favorite_charts = db.relationship(
        Chart,
        secondary=chart_users,
        backref='favorite_users',
    )

    def __init__(self, name, email, password, location, department):
        """Initialize a User model"""
        UserMixin.__init__(self)
        self.name = name
        self.email = email
        self.password = generate_password_hash(password)
        self.location = location
        self.department = department
        self.is_admin = False

    def set_password(self, new_password):
        """Change the user's password to the new password"""
        self.password = generate_password_hash(new_password)

    def check_password(self, password):
        """Check the user's password against the given value"""
        return check_password_hash(self.password, password)

    def favorite(self, report):
        """Add a report to the user's list of favorite reports"""
        if report not in self.favorite_reports:
            self.favorite_reports.append(report)

    def unfavorite(self, report):
        """Remove a report from the user's list of favorite reports"""
        if report in self.favorite_reports:
            self.favorite_reports.remove(report)

    def favorite_chart(self, chart):
        """Add a chart to the user's list of favorite charts"""
        if chart not in self.favorite_charts:
            self.favorite_charts.append(chart)

    def unfavorite_chart(self, chart):
        """Remove a chart from the user's list of favorite charts"""
        if chart in self.favorite_charts:
            self.favorite_charts.remove(chart)

    def __repr__(self):
        """Return a descriptive representation of a User"""
        return '<User %r>' % self.email

    @classmethod
    def get_by_email(cls, email):
        """Retrieve a user by their email address"""
        return User.query.filter_by(email=email).first()