Ejemplo n.º 1
0
    def __init__(self, unit: str):
        """Object that represents path to unit's base folder

        Parameters
        ---
        Unit: string

        Examples
        -------
        >>> uf = UnitFolder(unit='F301')
        >>> uf.p_unit
        '/Volumes/Public/Fort Hills/02. Equipment Files/1. 980E Trucks/F301 - A40017'
        """

        # get unit's row from unit table, save to self attributes
        m = db.get_df_unit().loc[unit]
        f.copy_dict_attrs(m=m, target=self)

        modelpath = self.get_modelpath()  # needs model and model_map
        unitpath = f'{unit} - {self.serial}'

        if not 'shovels' in self.minesite.lower():
            p_unit = cf.p_drive / f'{self.equippath}/{modelpath}/{unitpath}'
        else:
            # shovels doesn't want modelpath. Could make this a list of exclusions or something
            p_unit = cf.p_drive / f'{self.equippath}/{unitpath}'

        p_dls = p_unit / 'Downloads'
        p_dls_year = p_dls / str(dt.now().year)

        f.set_self(vars())
Ejemplo n.º 2
0
    def process_df(self, df):
        """Pivot dates for first of months, then merge unit delivery date/serial from db
        - will fail if most recent dates not in db
        """
        df = df \
            .assign(DateSMR=lambda x: x.DateSMR.dt.strftime('%Y-%m-%d')) \
            .pivot(index='Unit', columns='DateSMR', values='SMR') \
            .rename_axis('Unit', axis=1) \
            .assign(Difference=lambda x: x.iloc[:, 1] - x.iloc[:, 0])

        return db.get_df_unit(minesite=self.minesite) \
            .set_index('Unit')[['Serial', 'DeliveryDate']] \
            .merge(right=df, how='right', on='Unit') \
            .reset_index()
Ejemplo n.º 3
0
def create_fc_manual(units: list, fc_number: str, _type: str, subject: str,
                     release_date: dt, expiry_date: dt, **kw) -> None:
    """Create manual FC from input dialog"""

    df = db.get_df_unit() \
        .pipe(lambda df: df[df.Unit.isin(units)])[['Model', 'Serial']] \
        .reset_index() \
        .assign(
            FCNumber=fc_number,
            Subject=subject,
            Classification=_type,
            StartDate=release_date,
            EndDate=expiry_date)

    import_fc(df=df, **kw)
Ejemplo n.º 4
0
def unit_from_path(p):
    """Regex find first occurance of unit in path
    - Needs minesite
    """
    minesite = plm.minesite_from_path(p)

    units = db.get_df_unit() \
        .pipe(lambda df: df[df.MineSite == minesite]) \
        .Unit.unique().tolist()

    match = re.search(f'({"|".join(units)})', str(p))
    if match:
        return match.groups()[0]
    else:
        log.warning(f'Couldn\'t find unit in path: {p}')
Ejemplo n.º 5
0
def read_fc_old(p):
    # Raw FC data comes from KA as an html page disguised as an xls
    # TODO: Drop ServiceLetterDate > same as StartDate
    # TODO: Drop CompletionDate > changed to DateCompleteKA, Drop ClaimNumber

    with open(p) as html:
        table = BeautifulSoup(
            html,
            features='lxml').findAll('table')[2]  # FC data is in 3rd table

    cols = [hdr.text for hdr in table.find('thead').find_all('th')]
    data = [[col.text for col in row.findAll('td')]
            for row in table.findAll('tr')[1:]]
    dfu = db.get_df_unit()

    df = pd.DataFrame(data=data, columns=cols) \
        .pipe(f.parse_datecols) \
        .merge(right=dfu[['Model', 'Serial', 'Unit']], how='left')

    # Remove missing units
    # TODO: Return these to user somehow?
    df.Unit.replace('', pd.NA, inplace=True)
    df.dropna(subset=['Unit'], inplace=True)

    # Rename Cols
    df.columns = [
        'FCNumber', 'Distributor', 'Branch', 'Model', 'Serial', 'Safety',
        'StartDate', 'EndDate', 'Subject', 'ClaimNumber', 'CompletionSMR',
        'DateCompleteKA', 'Status', 'Hours', 'ServiceLetterDate',
        'Classification', 'Unit'
    ]  # noqa

    # Drop and reorder,  Don't import: CompletionSMR, claimnumber, ServiceLetterDate
    cols = [
        'FCNumber', 'Model', 'Serial', 'Unit', 'StartDate', 'EndDate',
        'DateCompleteKA', 'Subject', 'Classification', 'Hours', 'Distributor',
        'Branch', 'Safety', 'Status'
    ]
    df = df[cols]

    df.FCNumber = df.FCNumber.str.strip()

    return df
Ejemplo n.º 6
0
def read_fc(p: Path) -> pd.DataFrame:
    """
    Read FC csv from KA
    - Removes units not in db
    """
    # Drop and reorder,  Don't import: CompletionSMR, claimnumber, ServiceLetterDate
    cols = [
        'FCNumber', 'Model', 'Serial', 'Unit', 'StartDate', 'EndDate',
        'DateCompleteKA', 'Subject', 'Classification', 'Branch', 'Status'
    ]

    dtypes = dict(Model='object', Serial='object', Unit='object')

    # NOTE only model colulmn has '\t' so far, but would be better to apply to all str cols
    dfu = db.get_df_unit()
    return f.read_csv_firstrow(p, dtype=dtypes, skipinitialspace=True) \
        .rename(columns=cf.config['Headers']['FCImport']) \
        .assign(Model=lambda x: x.Model.str.strip()) \
        .merge(right=dfu[['Model', 'Serial', 'Unit']], how='left') \
        .pipe(db.filter_database_units) \
        .reset_index(drop=True)[cols]
Ejemplo n.º 7
0
    def cb_changed(self, field_name: str) -> None:
        """Update units/models/model_base lists when minesite changed

        - TODO could clear filters when fields de-selected also

        Parameters
        ----------
        index : int
            list index of current minesite, not really needed
        """
        # minesite = self.fMineSite.val
        field = getattr(self, f'f{field_name}')
        if not field.cb.isChecked():
            return

        val = field.val
        df = db.get_df_unit()

        dependent_cols = self.dependents[field_name]

        for col in dependent_cols:
            name = f'f{col}'
            if hasattr(self, name) and not col in self.existing_dependent_cols(
                    field_name):

                # Evaluate each field which is changing based on the active filters it is dependent on
                conds = []
                for dep_col in self.dependent_on(col):
                    if self.field_active(dep_col):

                        cond = df[dep_col] == self.fields[dep_col].val
                        conds.append(cond)

                items = df[np.all(conds, axis=0)][col].pipe(f.clean_series)
                field_change = getattr(self, name)
                field_change.box.set_items(items)
Ejemplo n.º 8
0
    def from_model(cls, e, **kw):
        """Create report from model e, with header data from event dict + unit info"""
        header_data = dbt.model_dict(e, include_none=True)
        header_data.update(db.get_df_unit().loc[e.Unit])

        return cls(e=e, header_data=header_data, **kw)
Ejemplo n.º 9
0
    def add_feature(self,
                    name: str,
                    table: str = None,
                    cb_enabled: bool = False) -> None:
        """Add single feature to refresh menu"""
        parent, ms = self.parent, self.minesite
        name, title = name.lower(), name.replace('_', ' ').title()
        IPF = InputField
        add_input, add_refresh_button = self.add_input, self.add_refresh_button

        if table is None:
            table = self.tables.get(name, None)

        # this is ugly, would rather set up objects and only call when needed, but hard to initialize
        if name == 'all_open':
            add_refresh_button(name=title, func=parent.refresh_allopen)

        elif name == 'last_week':
            add_refresh_button(
                name=title, func=lambda: parent.refresh_lastweek(base=False))

        elif name == 'last_month':
            add_refresh_button(
                name=title, func=lambda: parent.refresh_lastmonth(base=False))

        # TODO remove eventually, temp for EmailList table
        elif name == 'minesite_like':
            title = 'MineSite'
            add_input(field=IPF(text=title, default=ms, like=True),
                      items=cf.config[title],
                      checkbox=True)

        elif name == 'minesite':
            lst = db.get_list_minesite()

            add_input(field=IPF(text='MineSite', default=ms, table=table),
                      items=lst,
                      checkbox=True,
                      box_changed=lambda x: self.cb_changed('MineSite'))

        elif name == 'work_order':
            add_input(field=IPF(text=title), checkbox=True, cb_enabled=False)

        elif name == 'unit':
            df = db.get_df_unit()
            lst = df[df.MineSite == ms].Unit.pipe(f.clean_series)
            add_input(field=IPF(text=title),
                      items=lst,
                      checkbox=True,
                      cb_enabled=False)

        elif 'model' in name:

            col = 'ModelBase' if 'model_base' in name else 'Model'
            df = db.get_df_unit()
            if not 'all' in name:
                df = df.query('MineSite == @ms')

            lst = df[col].pipe(f.clean_series)
            add_input(field=IPF(text=f.lower_cols(col)[0].replace('_',
                                                                  ' ').title(),
                                table=table),
                      items=lst,
                      checkbox=True,
                      cb_enabled=False,
                      box_changed=lambda x: self.cb_changed(col))

        elif name == 'type':
            add_input(field=IPF(text=title,
                                col_db='Classification',
                                table=table),
                      items=['M', 'FAF', 'DO', 'FT'],
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'fc_number':
            df = db.get_df_fc(default=True, minesite=ms)
            lst = f.clean_series(s=df['FC Number'])
            add_input(field=IPF(text='FC Number'),
                      items=lst,
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'fc_complete':
            add_input(field=IPF(text=title, col_db='Complete'),
                      items=['False', 'True'],
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'manual_closed':
            add_input(
                field=IPF(text=title, default='False', table=table),
                items=['False', 'True'],
                checkbox=True,
                tooltip=
                '"Manual Closed = True" means FCs that HAVE been closed/removed from the FC Summary table. \
                This is used to manage which FCs are "active".')

        elif name == 'start_date':
            # TODO: only set up for eventlog table currently
            add_input(field=IPF(text=title,
                                dtype='date',
                                col_db=self.col_db_startdate),
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'end_date':
            add_input(field=IPF(text=title,
                                dtype='date',
                                col_db=self.col_db_enddate,
                                opr=op.le),
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'component':
            df = db.get_df_component()
            lst = f.clean_series(df.Component)
            add_input(field=IPF(text=title, table=table),
                      items=lst,
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'component_oil':
            add_input(field=IPF(text='Component', col_db='component_id'),
                      items=[],
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'limit_component':
            title = 'Limit per Component'
            field = add_input(field=IPF(text=title, dtype='int', default=5),
                              checkbox=True,
                              cb_enabled=True)
            field.exclude_filter = True

        elif name == 'tsi_author':
            add_input(field=IPF(text='TSI Author',
                                default=self.mainwindow.username,
                                col_db='TSIAuthor'),
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'tsi_number':
            add_input(field=IPF(text='TSI Number'),
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'major_components':

            add_input(field=IPF(text=title,
                                default='True',
                                table=table,
                                col_db='Major'),
                      items=['True', 'False'],
                      checkbox=True,
                      cb_enabled=cb_enabled)

        elif name == 'title':
            add_input(
                field=IPF(text=title, col_db=title, like=True),
                checkbox=True,
                cb_enabled=False,
                tooltip=
                'Use wildcards * to match results containing partial text.\nEg:\n\
                - Steering* > return "Steering Pump" and "Steering Arm", but not "Change Steering Pump"\n\
                - *MTA* > return "The MTA Broke" and "MTA Failure"')

        elif name == 'fc_subject':
            df = db.get_df_fc(default=False, minesite=ms)
            lst = f.clean_series(df.Subject)
            add_input(field=IPF(text='Subject',
                                table='FCSummary',
                                col_db='SubjectShort'),
                      items=lst,
                      checkbox=True,
                      cb_enabled=False)

        elif name == 'user_group':
            u = self.mainwindow.u
            enabled = False if self.parent.title in (
                'Event Log', 'Work Orders') and not u.is_cummins else True

            field = IPF(text=title,
                        default=db.domain_map_inv.get(u.domain, 'SMS'),
                        col_db='UserGroup',
                        table=table)

            add_input(
                field=field,
                items=db.domain_map.keys(),
                checkbox=True,
                cb_enabled=enabled,
                tooltip=
                'Limit results to only those created by users in your domain.\n\
                (Ensure users have been correctly initialized.)')

        elif 'part_name' in name:
            col_db = 'PartName'
            if 'alt' in name:
                col_db = 'PartNameAlt'

            add_input(
                field=IPF(text=title, col_db=col_db, like=True),
                checkbox=True,
                cb_enabled=False,
                tooltip='This searches both "Part Name" and "Alt Part Name".')

        elif name == 'part_number':
            add_input(field=IPF(text=title, col_db='PartNo'),
                      checkbox=True,
                      cb_enabled=False)