def __init__(self, data_provider, config_params=None, **kwargs):
     super(SecondaryAllHeroSOSofCSNCategoryKpi,
           self).__init__(data_provider,
                          config_params=config_params,
                          **kwargs)
     self.util = PepsicoUtil(None, data_provider)
     self.kpi_name = self._config_params['kpi_type']
class SecondaryPriceMechanicKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SecondaryPriceMechanicKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def kpi_type(self):
        pass

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)
            filtered_matches = self.util.filtered_matches_secondary.merge(
                self.util.all_products, on=[ScifConsts.PRODUCT_FK], how='left')
            filtered_matches = filtered_matches[filtered_matches[ScifConsts.PRODUCT_TYPE] \
                                                              == 'POS'].drop_duplicates(subset=[ScifConsts.PRODUCT_FK])

            kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
            for i, row in filtered_matches.iterrows():
                self.write_to_db_result(
                    fk=kpi_fk,
                    numerator_id=row[ScifConsts.PRODUCT_FK],
                    denominator_id=row['display_id'],
                    denominator_result=row['display_id'],
                    context_id=row['store_area_fk'],
                    result=1)
            self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
            )
Exemple #3
0
class HeroSkuPromoPriceKpi(UnifiedCalculationsScript):

    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroSkuPromoPriceKpi, self).__init__(data_provider, config_params=config_params, **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        if not self.dependencies_data[self.dependencies_data['kpi_type'] == self.util.HERO_SKU_AVAILABILITY_SKU].empty:
            hero_sku_list = self.util.get_available_hero_sku_list(self.dependencies_data)
            promo_price_kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.util.HERO_SKU_PROMO_PRICE)
            for sku in hero_sku_list:
                self.calculate_hero_sku_promo_price(sku, promo_price_kpi_fk)

    def calculate_hero_sku_promo_price(self, sku, kpi_fk):
        price = 0
        prices_df = self.util.filtered_matches[(~(self.util.filtered_matches['promotion_price'].isnull())) &
                                          (self.util.filtered_matches['product_fk'] == sku)]
        if not prices_df.empty:
            price = 1
        result = self.util.commontools.get_yes_no_result(price)
        self.write_to_db_result(fk=kpi_fk, numerator_id=sku, result=result)
        self.util.add_kpi_result_to_kpi_results_df([kpi_fk, sku, None, price, None])
class SecondaryAvailabilityPerProductKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SecondaryAvailabilityPerProductKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def kpi_type(self):
        pass

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)
            if not self.util.filtered_matches_secondary.empty:
                kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
                filtered_matches = self.util.filtered_matches_secondary.copy()
                store_area = filtered_matches['store_area_fk'].values[0]
                product_display = filtered_matches.drop_duplicates(
                    subset=[MatchesConsts.PRODUCT_FK, 'display_id'])
                for i, row in product_display.iterrows():
                    self.write_to_db_result(
                        fk=kpi_fk,
                        result=1,
                        numerator_id=row[MatchesConsts.PRODUCT_FK],
                        denominator_id=row[MatchesConsts.PRODUCT_FK],
                        denominator_result=row['display_id'],
                        context_id=store_area)
            self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
            )
Exemple #5
0
 def __init__(self, data_provider, config_params=None, **kwargs):
     super(SecondaryHeroLengthByHeroTypeKpi,
           self).__init__(data_provider,
                          config_params=config_params,
                          **kwargs)
     self.util = PepsicoUtil(None, data_provider)
     self.kpi_name = self._config_params['kpi_type']
Exemple #6
0
 def __init__(self, data_provider, config_params=None, **kwargs):
     super(SecondarySosBrandOfSegmentKpi,
           self).__init__(data_provider,
                          config_params=config_params,
                          **kwargs)
     self.util = PepsicoUtil(None, data_provider)
     self.kpi_name = self._config_params['kpi_type']
class LinearBrandVsBrandIndexKpi(UnifiedCalculationsScript):

    def __init__(self, data_provider, config_params=None, **kwargs):
        super(LinearBrandVsBrandIndexKpi, self).__init__(data_provider, config_params=config_params, **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        index_targets = self.util.get_relevant_sos_vs_target_kpi_targets(brand_vs_brand=True)
        index_targets['numerator_id'] = index_targets.apply(self.util.retrieve_relevant_item_pks, axis=1,
                                                            args=('numerator_type', 'numerator_value'))
        index_targets['denominator_id'] = index_targets.apply(self.util.retrieve_relevant_item_pks, axis=1,
                                                              args=('denominator_type', 'denominator_value'))
        index_targets['identifier_parent'] = index_targets['KPI Parent'].apply(lambda x:
                                                                           self.util.common.get_dictionary(
                                                                               kpi_fk=int(float(x))))
        index_targets = index_targets[index_targets['type'] == self._config_params['kpi_type']]
        for i, row in index_targets.iterrows():
            general_filters = {row['additional_filter_type_1']: row['additional_filter_value_1']}
            numerator_sos_filters = {row['numerator_type']: row['numerator_value']}
            num_num_linear, num_denom_linear = self.util.calculate_sos(numerator_sos_filters, **general_filters)
            numerator_sos = num_num_linear/num_denom_linear if num_denom_linear else 0

            denominator_sos_filters = {row['denominator_type']: row['denominator_value']}
            denom_num_linear, denom_denom_linear = self.util.calculate_sos(denominator_sos_filters, **general_filters)
            denominator_sos = denom_num_linear/denom_denom_linear if denom_denom_linear else 0

            index = numerator_sos / denominator_sos if denominator_sos else 0
            self.write_to_db_result(fk=row.kpi_level_2_fk, numerator_id=row.numerator_id,
                                    numerator_result=num_num_linear, denominator_id=row.denominator_id,
                                    denominator_result=denom_num_linear, result=index, score=index)
            self.util.add_kpi_result_to_kpi_results_df([row.kpi_level_2_fk, row.numerator_id, row.denominator_id, index,
                                                   index])
class HeroSKUAvailabilityByHeroTypeKpi(UnifiedCalculationsScript):

    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroSKUAvailabilityByHeroTypeKpi, self).__init__(data_provider, config_params=config_params, **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def calculate(self):
        lvl3_ass_res_df = self.dependencies_data
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.util.HERO_SKU_AVAILABILITY_BY_HERO_TYPE)
        if not lvl3_ass_res_df.empty:
            location_type_fk = self.util.scif[self.util.scif[ScifConsts.LOCATION_TYPE] == 'Primary Shelf']\
                [ScifConsts.LOCATION_TYPE_FK].values[0]
            product_hero_df = self.util.all_products[[ScifConsts.PRODUCT_FK, self.util.HERO_SKU_LABEL]]
            lvl3_ass_res_df = lvl3_ass_res_df.merge(product_hero_df, left_on='numerator_id',
                                                    right_on=ScifConsts.PRODUCT_FK,
                                                    how='left')
            lvl3_ass_res_df = lvl3_ass_res_df.merge(self.util.hero_type_custom_entity_df,
                                                    left_on=self.util.HERO_SKU_LABEL, right_on='name', how='left')
            lvl3_ass_res_df['count'] = 1
            kpi_res_df = lvl3_ass_res_df.groupby([self.util.HERO_SKU_LABEL, 'entity_fk'],
                                                 as_index=False).agg({'numerator_result': np.sum, 'count': np.sum})
            kpi_res_df['result'] = kpi_res_df['numerator_result'] / kpi_res_df['count'] * 100
            kpi_res_df['score'] = kpi_res_df['result'].apply(lambda x: 100 if x >= 100 else 0)
            for i, res in kpi_res_df.iterrows():
                self.write_to_db_result(fk=kpi_fk, numerator_id=res['entity_fk'],
                                        numerator_result=res['numerator_result'], result=res['result'],
                                        denominator_id=res['entity_fk'], denominator_result=res['count'],
                                        score=res['score'], context_id=location_type_fk)
                self.util.add_kpi_result_to_kpi_results_df(
                    [kpi_fk, res['entity_fk'], res['entity_fk'], res['result'], res['score'], location_type_fk])

    def kpi_type(self):
        pass
Exemple #9
0
class HeroAvailabilityKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroAvailabilityKpi, self).__init__(data_provider,
                                                  config_params=config_params,
                                                  **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def calculate(self):
        lvl3_ass_res_df = self.dependencies_data
        distribution_kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(
            self.util.HERO_SKU_AVAILABILITY)
        if not lvl3_ass_res_df.empty:
            location_type_fk = self.util.scif[self.util.scif[ScifConsts.LOCATION_TYPE] == 'Primary Shelf'] \
                [ScifConsts.LOCATION_TYPE_FK].values[0]
            total_skus_in_ass = len(lvl3_ass_res_df)
            in_store_skus = len(
                self.util.get_available_hero_sku_list(self.dependencies_data))
            res = np.divide(float(in_store_skus),
                            float(total_skus_in_ass)) * 100
            score = 100 if res >= 100 else 0
            self.write_to_db_result(fk=distribution_kpi_fk,
                                    numerator_id=self.util.own_manuf_fk,
                                    numerator_result=in_store_skus,
                                    result=res,
                                    denominator_id=self.util.store_id,
                                    denominator_result=total_skus_in_ass,
                                    score=score,
                                    context_id=location_type_fk)
            self.util.add_kpi_result_to_kpi_results_df([
                distribution_kpi_fk, self.util.own_manuf_fk,
                self.util.store_id, res, score, None
            ])

    def kpi_type(self):
        pass
Exemple #10
0
class ProductBlockingKpi(UnifiedCalculationsScript):

    def __init__(self, data_provider, config_params=None, **kwargs):
        super(ProductBlockingKpi, self).__init__(data_provider, config_params=config_params, **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.block = None

    def kpi_type(self):
        pass

    def calculate(self):
        if not self.util.filtered_matches.empty:
            self.util.filtered_scif, self.util.filtered_matches = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif,
                                                                                     self.util.filtered_matches,
                                                                                     self.util.PRODUCT_BLOCKING)
            filtered_matches = self.util.filtered_matches.copy()
            if 'sub_category_fk' in filtered_matches.columns:
                filtered_matches = filtered_matches.drop(columns=['sub_category_fk'])
            self.block = Block(self.data_provider, custom_scif=self.util.filtered_scif,
                               custom_matches=filtered_matches)
            if not self.util.filtered_matches.empty:
                self.calculate_product_blocking()
            self.util.reset_filtered_scif_and_matches_to_exclusion_all_state()

    def calculate_product_blocking(self):
        external_targets = self.util.all_targets_unpacked[self.util.all_targets_unpacked['type'] == self.util.PRODUCT_BLOCKING]
        additional_block_params = {'check_vertical_horizontal': True, 'minimum_facing_for_block': 3,
                                   'include_stacking': True,
                                   'allowed_products_filters': {'product_type': ['Empty']}}
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.util.PRODUCT_BLOCKING)

        for i, row in external_targets.iterrows():
            # print row['Group Name']
            group_fk = self.util.custom_entities[self.util.custom_entities['name'] == row['Group Name']]['pk'].values[0]
            # filters = self.util.get_block_and_adjacency_filters(row)
            filters = self.util.get_block_filters(row)
            target = row['Target']
            additional_block_params.update({'minimum_block_ratio': float(target)/100})

            result_df = self.block.network_x_block_together(filters, additional=additional_block_params)
            score = max_ratio = 0
            result = self.util.commontools.get_yes_no_result(0)
            if not result_df.empty:
                max_ratio = result_df['facing_percentage'].max()
                result_df = result_df[result_df['is_block']==True]
                if not result_df.empty:
                    max_ratio = result_df['facing_percentage'].max()
                    result_df = result_df[result_df['facing_percentage'] == max_ratio]
                    result = self.util.commontools.get_yes_no_result(1)
                    orientation = result_df['orientation'].values[0]
                    score = self.util.commontools.get_kpi_result_value_pk_by_value(orientation.upper())
            # print score
            self.write_to_db_result(fk=kpi_fk, numerator_id=group_fk, denominator_id=self.util.store_id,
                                    numerator_result=max_ratio * 100,
                                    score=score, result=result, target=target, by_scene=True)
            self.util.block_results = self.util.block_results.append(pd.DataFrame([{'Group Name': row['Group Name'],
                                                                                    'Score':
                                                                                        result_df['is_block'].values[
                                                                                            0] if not result_df.empty else False}]))
class NumberOfBaysKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(NumberOfBaysKpi, self).__init__(data_provider,
                                              config_params=config_params,
                                              **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        if not self.util.filtered_matches.empty:
            bays_kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(
                self.util.NUMBER_OF_BAYS)
            matches = self.util.match_product_in_scene[~(
                self.util.match_product_in_scene['bay_number'] == -1)]
            bays_in_scene = matches['bay_number'].unique().tolist()
            bays_num = len(bays_in_scene)
            self.write_to_db_result(fk=bays_kpi_fk,
                                    numerator_id=self.util.own_manuf_fk,
                                    result=bays_num,
                                    denominator_id=self.util.store_id,
                                    by_scene=True)
            self.util.add_kpi_result_to_kpi_results_df([
                bays_kpi_fk, self.util.own_manuf_fk, self.util.store_id,
                bays_num, None
            ])
Exemple #12
0
class NumberOfShelvesKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(NumberOfShelvesKpi, self).__init__(data_provider,
                                                 config_params=config_params,
                                                 **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        if not self.util.filtered_matches.empty:
            kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(
                self.util.NUMBER_OF_SHELVES)
            matches = self.util.match_product_in_scene[~(
                self.util.match_product_in_scene['bay_number'] == -1)]
            # bay_shelf = matches.drop_duplicates(subset=['bay_number', 'shelf_number'])
            # shelf_num = len(bay_shelf)
            shelf_num = matches['shelf_number'].max()
            self.write_to_db_result(fk=kpi_fk,
                                    numerator_id=self.util.own_manuf_fk,
                                    result=shelf_num,
                                    denominator_id=self.util.store_id,
                                    by_scene=True)
            self.util.add_kpi_result_to_kpi_results_df([
                kpi_fk, self.util.own_manuf_fk, self.util.store_id, shelf_num,
                None
            ])
 def __init__(self, data_provider, config_params=None, **kwargs):
     super(SecondaryAvailabilityPerProductKpi,
           self).__init__(data_provider,
                          config_params=config_params,
                          **kwargs)
     self.util = PepsicoUtil(None, data_provider)
     self.kpi_name = self._config_params['kpi_type']
class HeroSkuStackingBySequenceNumberKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroSkuStackingBySequenceNumberKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        if not self.dependencies_data[
                self.dependencies_data['kpi_type'] ==
                self.util.HERO_SKU_AVAILABILITY_SKU].empty:
            hero_list = self.util.get_available_hero_sku_list(
                self.dependencies_data)
            if hero_list:
                relevant_matches = self.util.filtered_matches[
                    self.util.filtered_matches['product_fk'].isin(hero_list)]
                relevant_matches = relevant_matches.reset_index(drop=True)
                relevant_matches['facing_sequence_number'] = relevant_matches[
                    'facing_sequence_number'].astype(str)
                relevant_matches['all_sequences'] = relevant_matches.groupby(['scene_fk', 'bay_number', 'shelf_number', 'product_fk']) \
                                                        ['facing_sequence_number'].apply(lambda x: (x + ',').cumsum().str.strip())
                grouped_matches = relevant_matches.drop_duplicates(subset=[
                    'scene_fk', 'bay_number', 'shelf_number', 'product_fk'
                ],
                                                                   keep='last')
                grouped_matches['is_stack'] = grouped_matches.apply(
                    self.get_stack_data, axis=1)
                stacking_kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(
                    self.util.HERO_SKU_STACKING)
                for sku in hero_list:
                    stack_info = grouped_matches[
                        grouped_matches['product_fk'] ==
                        sku]['is_stack'].values.tolist()
                    score = 0
                    if any(stack_info):
                        score = 1
                    result = self.util.commontools.get_yes_no_result(score)
                    self.write_to_db_result(fk=stacking_kpi_fk,
                                            numerator_id=sku,
                                            score=score,
                                            result=result)

                    self.util.add_kpi_result_to_kpi_results_df(
                        [stacking_kpi_fk, sku, None, result, score])

    @staticmethod
    def get_stack_data(row):
        is_stack = False
        sequences_list = row['all_sequences'][0:-1].split(',')
        count_sequences = collections.Counter(sequences_list)
        repeating_items = [c > 1 for c in count_sequences.values()]
        if repeating_items:
            if any(repeating_items):
                is_stack = True
        return is_stack
 def __init__(self, data_provider, config_params=None, **kwargs):
     super(BlocksAdjacencyKpi, self).__init__(data_provider,
                                              config_params=config_params,
                                              **kwargs)
     self.util = PepsicoUtil(None, data_provider)
     self.adjacency = Adjancency(self.data_provider,
                                 custom_scif=self.util.filtered_scif,
                                 custom_matches=self.util.filtered_matches)
class SosBrandOfSegmentKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SosBrandOfSegmentKpi, self).__init__(data_provider,
                                                   config_params=config_params,
                                                   **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        self.util.filtered_scif, self.util.filtered_matches = \
            self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif,
                                                                                 self.util.filtered_matches,
                                                                                 self.util.BRAND_SOS_OF_SEGMENT)
        self.calculate_brand_out_of_sub_category_sos()
        self.util.reset_filtered_scif_and_matches_to_exclusion_all_state()

    def calculate_brand_out_of_sub_category_sos(self):
        location_type_fk = self.util.all_templates[self.util.all_templates[ScifConsts.LOCATION_TYPE] == 'Primary Shelf'] \
            [ScifConsts.LOCATION_TYPE_FK].values[0]
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(
            self.util.BRAND_SOS_OF_SEGMENT)
        filtered_matches = self.util.filtered_matches[~(
            self.util.filtered_matches[ScifConsts.SUB_CATEGORY_FK].isnull())]
        products_df = self.util.all_products[[
            MatchesConsts.PRODUCT_FK, ScifConsts.BRAND_FK,
            ScifConsts.CATEGORY_FK
        ]]
        filtered_matches = filtered_matches.merge(products_df,
                                                  on=MatchesConsts.PRODUCT_FK,
                                                  how='left')
        sub_cat_df = filtered_matches.groupby(
            [ScifConsts.SUB_CATEGORY_FK],
            as_index=False).agg({MatchesConsts.WIDTH_MM_ADVANCE: np.sum})
        sub_cat_df.rename(
            columns={MatchesConsts.WIDTH_MM_ADVANCE: 'sub_cat_len'},
            inplace=True)
        brand_sub_cat_df = filtered_matches.groupby(
            [ScifConsts.BRAND_FK, ScifConsts.SUB_CATEGORY_FK],
            as_index=False).agg({MatchesConsts.WIDTH_MM_ADVANCE: np.sum})
        brand_sub_cat_df = brand_sub_cat_df.merge(
            sub_cat_df, on=ScifConsts.SUB_CATEGORY_FK, how='left')
        brand_sub_cat_df['sos'] = brand_sub_cat_df[
            MatchesConsts.WIDTH_MM_ADVANCE] / brand_sub_cat_df['sub_cat_len']
        for i, row in brand_sub_cat_df.iterrows():
            self.write_to_db_result(
                fk=kpi_fk,
                numerator_id=row[ScifConsts.BRAND_FK],
                numerator_result=row[MatchesConsts.WIDTH_MM_ADVANCE],
                denominator_id=row[ScifConsts.SUB_CATEGORY_FK],
                denominator_result=row['sub_cat_len'],
                result=row['sos'] * 100,
                context_id=location_type_fk)
            self.util.add_kpi_result_to_kpi_results_df([
                kpi_fk, row[ScifConsts.BRAND_FK],
                row[ScifConsts.SUB_CATEGORY_FK], row['sos'] * 100, None, None
            ])
Exemple #17
0
class SecondarySosBrandOfSegmentKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SecondarySosBrandOfSegmentKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def kpi_type(self):
        pass

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)
            self.calculate_brand_out_of_sub_category_sos()
            self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
            )

    def calculate_brand_out_of_sub_category_sos(self):
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
        filtered_matches = self.util.filtered_matches_secondary
        filtered_matches = filtered_matches[~(
            filtered_matches[ScifConsts.SUB_CATEGORY_FK].isnull())]
        products_df = self.util.all_products[[
            MatchesConsts.PRODUCT_FK, ScifConsts.BRAND_FK,
            ScifConsts.CATEGORY_FK
        ]]
        filtered_matches = filtered_matches.merge(products_df,
                                                  on=MatchesConsts.PRODUCT_FK,
                                                  how='left')
        sub_cat_df = filtered_matches.groupby(
            [ScifConsts.SUB_CATEGORY_FK],
            as_index=False).agg({MatchesConsts.WIDTH_MM_ADVANCE: np.sum})
        sub_cat_df.rename(
            columns={MatchesConsts.WIDTH_MM_ADVANCE: 'sub_cat_len'},
            inplace=True)
        brand_sub_cat_df = filtered_matches.groupby(
            [ScifConsts.BRAND_FK, ScifConsts.SUB_CATEGORY_FK],
            as_index=False).agg({MatchesConsts.WIDTH_MM_ADVANCE: np.sum})
        brand_sub_cat_df = brand_sub_cat_df.merge(
            sub_cat_df, on=ScifConsts.SUB_CATEGORY_FK, how='left')
        brand_sub_cat_df['sos'] = brand_sub_cat_df[
            MatchesConsts.WIDTH_MM_ADVANCE] / brand_sub_cat_df['sub_cat_len']
        for i, row in brand_sub_cat_df.iterrows():
            self.write_to_db_result(
                fk=kpi_fk,
                numerator_id=row[ScifConsts.BRAND_FK],
                numerator_result=row[MatchesConsts.WIDTH_MM_ADVANCE],
                denominator_id=row[ScifConsts.SUB_CATEGORY_FK],
                denominator_result=row['sub_cat_len'],
                result=row['sos'] * 100)
class HeroAvailabilitySkuKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroAvailabilitySkuKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def calculate(self):
        self.util.filtered_scif, self.util.filtered_matches = \
            self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif,
                                                                                 self.util.filtered_matches,
                                                                                 self.util.HERO_SKU_AVAILABILITY_SKU)
        self.calculate_kpi_for_main_shelf()
        self.util.reset_filtered_scif_and_matches_to_exclusion_all_state()

    def kpi_type(self):
        pass

    def calculate_kpi_for_main_shelf(self):
        location_type_fk = self.util.all_templates[self.util.all_templates[ScifConsts.LOCATION_TYPE] == 'Primary Shelf'] \
            [ScifConsts.LOCATION_TYPE_FK].values[0]
        lvl3_ass_res = self.util.lvl3_ass_result
        if lvl3_ass_res.empty:
            return

        if not self.util.filtered_scif.empty:
            products_in_session = self.util.filtered_scif.loc[
                self.util.filtered_scif['facings'] > 0]['product_fk'].values
            products_df = self.util.all_products[[
                ScifConsts.PRODUCT_FK, ScifConsts.MANUFACTURER_FK
            ]]
            lvl3_ass_res.loc[
                lvl3_ass_res['product_fk'].isin(products_in_session),
                'in_store'] = 1
            lvl3_ass_res = lvl3_ass_res.merge(products_df,
                                              on=ScifConsts.PRODUCT_FK,
                                              how='left')
            for i, result in lvl3_ass_res.iterrows():
                score = result.in_store * 100
                custom_res = self.util.commontools.get_yes_no_result(score)
                self.write_to_db_result(fk=result.kpi_fk_lvl3,
                                        numerator_id=result.product_fk,
                                        numerator_result=result.in_store,
                                        result=custom_res,
                                        denominator_id=result.manufacturer_fk,
                                        denominator_result=1,
                                        score=score,
                                        context_id=location_type_fk)
                self.util.add_kpi_result_to_kpi_results_df([
                    result['kpi_fk_lvl3'], result['product_fk'],
                    self.util.store_id, custom_res, score, None
                ])
 def test_get_available_hero_sku_list_retrieves_only_skus_in_store(self):
     self.mock_scene_item_facts(pd.read_excel(DataTestUnitPEPSICOUK.test_case_1, sheetname='scif'))
     self.mock_match_product_in_scene(pd.read_excel(DataTestUnitPEPSICOUK.test_case_1, sheetname='matches'))
     self.mock_scene_info(DataTestUnitPEPSICOUK.scene_info)
     self.mock_scene_kpi_results(DataTestUnitPEPSICOUK.scene_kpi_results_test_case_1)
     util = PepsicoUtil(self.output, self.data_provider_mock)
     availability_sku = HeroAvailabilitySkuKpi(self.data_provider_mock, config_params={})
     availability_sku.calculate()
     hero_dependency_df = pd.DataFrame(availability_sku.kpi_results)
     hero_dependency_df['kpi_type'] = util.HERO_SKU_AVAILABILITY_SKU
     hero_list = util.get_available_hero_sku_list(hero_dependency_df)
     self.assertItemsEqual(hero_list, [1, 2])
Exemple #20
0
class SosVsTargetBrandKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SosVsTargetBrandKpi, self).__init__(data_provider,
                                                  config_params=config_params,
                                                  **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        self.util.filtered_scif, self.util.filtered_matches = \
            self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif,
                                                                                 self.util.filtered_matches,
                                                                                 self.util.BRAND_SOS)
        self.calculate_brand_out_of_category_sos()
        self.util.reset_filtered_scif_and_matches_to_exclusion_all_state()

    def calculate_brand_out_of_category_sos(self):
        location_type_fk = self.util.all_templates[self.util.all_templates[ScifConsts.LOCATION_TYPE] == 'Primary Shelf'] \
            [ScifConsts.LOCATION_TYPE_FK].values[0]
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.util.BRAND_SOS)
        filtered_scif = self.util.filtered_scif
        category_df = filtered_scif.groupby([ScifConsts.CATEGORY_FK],
                                            as_index=False).agg({
                                                'updated_gross_length':
                                                np.sum
                                            })
        category_df.rename(columns={'updated_gross_length': 'cat_len'},
                           inplace=True)
        brand_cat_df = filtered_scif.groupby(
            [ScifConsts.BRAND_FK, ScifConsts.CATEGORY_FK],
            as_index=False).agg({'updated_gross_length': np.sum})
        brand_cat_df = brand_cat_df.merge(category_df,
                                          on=ScifConsts.CATEGORY_FK,
                                          how='left')
        brand_cat_df['sos'] = brand_cat_df[
            'updated_gross_length'] / brand_cat_df['cat_len']
        for i, row in brand_cat_df.iterrows():
            self.write_to_db_result(
                fk=kpi_fk,
                numerator_id=row[ScifConsts.BRAND_FK],
                numerator_result=row['updated_gross_length'],
                denominator_id=row[ScifConsts.CATEGORY_FK],
                denominator_result=row['cat_len'],
                result=row['sos'] * 100,
                context_id=location_type_fk)
            self.util.add_kpi_result_to_kpi_results_df([
                kpi_fk, row[ScifConsts.BRAND_FK], row[ScifConsts.CATEGORY_FK],
                row['sos'] * 100, None, None
            ])
Exemple #21
0
class SecondarySOSBrandofCategoryKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SecondarySOSBrandofCategoryKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def kpi_type(self):
        pass

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)
            self.calculate_brand_out_of_category_sos()
            self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
            )

    def calculate_brand_out_of_category_sos(self):
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
        filtered_scif = self.util.filtered_scif_secondary
        category_df = filtered_scif.groupby([ScifConsts.CATEGORY_FK],
                                            as_index=False).agg({
                                                'updated_gross_length':
                                                np.sum
                                            })
        category_df.rename(columns={'updated_gross_length': 'cat_len'},
                           inplace=True)

        brand_cat_df = filtered_scif.groupby(
            [ScifConsts.BRAND_FK, ScifConsts.CATEGORY_FK],
            as_index=False).agg({'updated_gross_length': np.sum})
        brand_cat_df = brand_cat_df.merge(category_df,
                                          on=ScifConsts.CATEGORY_FK,
                                          how='left')
        brand_cat_df['sos'] = brand_cat_df[
            'updated_gross_length'] / brand_cat_df['cat_len']
        for i, row in brand_cat_df.iterrows():
            self.write_to_db_result(
                fk=kpi_fk,
                numerator_id=row[ScifConsts.BRAND_FK],
                numerator_result=row['updated_gross_length'],
                denominator_id=row[ScifConsts.CATEGORY_FK],
                denominator_result=row['cat_len'],
                result=row['sos'] * 100)
Exemple #22
0
 def __init__(self, data_provider, config_params=None, **kwargs):
     super(HeroSKUAvailabilityByHeroTypeKpi,
           self).__init__(data_provider,
                          config_params=config_params,
                          **kwargs)
     self.util = PepsicoUtil(None, data_provider)
     self.kpi_name = self._config_params['kpi_type']
 def __init__(self, data_provider, config_params=None, **kwargs):
     super(SecondaryNumberofUniqueHeroSKUKpi,
           self).__init__(data_provider,
                          config_params=config_params,
                          **kwargs)
     self.util = PepsicoUtil(None, data_provider)
     self.kpi_name = self._config_params['kpi_type']
Exemple #24
0
class BrandFullBayKpi(UnifiedCalculationsScript):

    def __init__(self, data_provider, config_params=None, **kwargs):
        super(BrandFullBayKpi, self).__init__(data_provider, config_params=config_params, **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        self.util.filtered_scif, self.util.filtered_matches = \
            self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif,
                                                                                 self.util.filtered_matches,
                                                                                 self.util.BRAND_FULL_BAY)
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.util.BRAND_FULL_BAY)
        external_kpi_targets = self.util.commontools.all_targets_unpacked[
            self.util.commontools.all_targets_unpacked['kpi_level_2_fk'] == kpi_fk]
        external_kpi_targets = external_kpi_targets.reset_index(drop=True)
        if not external_kpi_targets.empty:
            external_kpi_targets['group_fk'] = external_kpi_targets['Group Name'].apply(lambda x:
                                                                                        self.util.custom_entities[
                                                                                            self.util.custom_entities[
                                                                                                'name'] == x][
                                                                                            'pk'].values[0])
            filtered_matches = self.util.filtered_matches[~(self.util.filtered_matches['bay_number'] == -1)]
            if not filtered_matches.empty:
                scene_bay_product = filtered_matches.groupby(['scene_fk', 'bay_number', 'product_fk'],
                                                             as_index=False).agg({'count': np.sum})
                scene_bay_product = scene_bay_product.merge(self.util.all_products, on='product_fk', how='left')
                scene_bay = scene_bay_product.groupby(['scene_fk', 'bay_number'], as_index=False).agg({'count': np.sum})
                scene_bay.rename(columns={'count': 'total_facings'}, inplace=True)
                for i, row in external_kpi_targets.iterrows():
                    filters = self.util.get_full_bay_and_positional_filters(row)
                    brand_relevant_df = scene_bay_product[
                        self.util.toolbox.get_filter_condition(scene_bay_product, **filters)]
                    result_df = brand_relevant_df.groupby(['scene_fk', 'bay_number'], as_index=False).agg(
                        {'count': np.sum})
                    result_df = result_df.merge(scene_bay, on=['scene_fk', 'bay_number'], how='left')
                    result_df['ratio'] = result_df['count'] / result_df['total_facings']
                    target_ratio = float(self._config_params['ratio'])
                    result = len(result_df[result_df['ratio'] >= target_ratio])
                    self.write_to_db_result(fk=row['kpi_level_2_fk'], numerator_id=row['group_fk'], result=result,
                                            score=result, target=target_ratio*100)
                    self.util.add_kpi_result_to_kpi_results_df(
                        [row['kpi_level_2_fk'], row['group_fk'], None, None, result, None])

        self.util.reset_filtered_scif_and_matches_to_exclusion_all_state()
Exemple #25
0
class HeroAvailabilitySkuKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroAvailabilitySkuKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)
            self.calculate_kpi_for_secondary_shelf()
            self.util.reset_filtered_scif_and_matches_to_exclusion_all_state()

    def kpi_type(self):
        pass

    def calculate_kpi_for_secondary_shelf(self):
        # scif for secondary should have display and store_area breakdown

        lvl3_ass_res = self.util.lvl3_ass_result
        if lvl3_ass_res.empty:
            return
        kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
        ass_list = lvl3_ass_res[ScifConsts.PRODUCT_FK].values.tolist()
        filtered_scif = self.util.filtered_scif_secondary[self.util.filtered_scif_secondary[ScifConsts.PRODUCT_FK]. \
            isin(ass_list)]
        # products_in_session = filtered_scif.loc[filtered_scif['facings'] > 0]['product_fk'].values
        # lvl3_ass_res.loc[lvl3_ass_res['product_fk'].isin(products_in_session), 'in_store'] = 1
        assortment_scif = filtered_scif.drop_duplicates(subset=[
            ScifConsts.TEMPLATE_FK, 'store_area_fk', ScifConsts.PRODUCT_FK
        ])
        for i, result in assortment_scif.iterrows():
            score = 100
            custom_res = self.util.commontools.get_yes_no_result(score)
            self.write_to_db_result(fk=kpi_fk,
                                    numerator_id=result.product_fk,
                                    numerator_result=1,
                                    result=custom_res,
                                    denominator_id=result.template_fk,
                                    denominator_result=1,
                                    score=score,
                                    context_id=result.store_area_fk)
class SeondaryPromoPriceKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SeondaryPromoPriceKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def kpi_type(self):
        pass

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)

            filtered_matches = self.util.filtered_matches_secondary
            if not filtered_matches.empty:
                product_display = filtered_matches.drop_duplicates(
                    subset=[MatchesConsts.PRODUCT_FK, 'display_id'])
                store_area = self.util.filtered_scif_secondary[
                    'store_area_fk'].values[0]
                kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
                for i, row in product_display.iterrows():
                    price = 0
                    prices_df = filtered_matches[
                        (~(filtered_matches[
                            MatchesConsts.PROMOTION_PRICE].isnull()))
                        & (filtered_matches[ScifConsts.PRODUCT_FK] == row[
                            MatchesConsts.PRODUCT_FK]) &
                        (filtered_matches['display_id'] == row['display_id'])]
                    if not prices_df.empty:
                        price = 1
                    result = self.util.commontools.get_yes_no_result(price)
                    self.write_to_db_result(
                        fk=kpi_fk,
                        numerator_id=row[MatchesConsts.PRODUCT_FK],
                        denominator_id=row[MatchesConsts.PRODUCT_FK],
                        denominator_result=row['display_id'],
                        context_id=store_area,
                        result=result)
            self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
            )
class HeroPlacementKpi(UnifiedCalculationsScript):

    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroPlacementKpi, self).__init__(data_provider, config_params=config_params, **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def kpi_type(self):
        pass

    def calculate(self):
        child_kpi_results = self.dependencies_data
        if not child_kpi_results.empty:
            top_sku_parent = self.util.common.get_kpi_fk_by_kpi_type(self.util.HERO_PLACEMENT)
            res = len(child_kpi_results)
            self.write_to_db_result(fk=top_sku_parent, numerator_id=self.util.own_manuf_fk,
                                    denominator_id=self.util.store_id, result=res, score=res)
            self.util.add_kpi_result_to_kpi_results_df(
                [top_sku_parent, self.util.own_manuf_fk, self.util.store_id, res, res])
class HeroAvailabilitySkuKpi(UnifiedCalculationsScript):

    def __init__(self, data_provider, config_params=None, **kwargs):
        super(HeroAvailabilitySkuKpi, self).__init__(data_provider, config_params=config_params, **kwargs)
        self.util = PepsicoUtil(None, data_provider)

    def calculate(self):
        for i, result in self.util.lvl3_ass_result.iterrows():
            score = result.in_store * 100
            custom_res = self.util.commontools.get_yes_no_result(score)
            self.write_to_db_result(fk=result.kpi_fk_lvl3, numerator_id=result.product_fk,
                                    numerator_result=result.in_store, result=custom_res,
                                    denominator_id=self.util.store_id, denominator_result=1, score=score)
            self.util.add_kpi_result_to_kpi_results_df(
                [result['kpi_fk_lvl3'], result['product_fk'], self.util.store_id, custom_res,
                 score, None])

    def kpi_type(self):
        pass
class SecondaryLinearSpacePerProductKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SecondaryLinearSpacePerProductKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def kpi_type(self):
        pass

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)
            if not self.util.filtered_matches_secondary.empty:
                kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
                filtered_matches = self.util.filtered_matches_secondary.copy()
                store_area = self.util.filtered_scif_secondary[
                    'store_area_fk'].values[0]

                result_df = filtered_matches.groupby(
                    [MatchesConsts.PRODUCT_FK, 'display_id'],
                    as_index=False).agg(
                        {MatchesConsts.WIDTH_MM_ADVANCE: np.sum})

                for i, row in result_df.iterrows():
                    self.write_to_db_result(
                        fk=kpi_fk,
                        numerator_result=row[MatchesConsts.WIDTH_MM_ADVANCE],
                        result=row[MatchesConsts.WIDTH_MM_ADVANCE],
                        numerator_id=row[MatchesConsts.PRODUCT_FK],
                        denominator_id=row[MatchesConsts.PRODUCT_FK],
                        denominator_result=row['display_id'],
                        context_id=store_area)
            self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
            )
Exemple #30
0
class SecondaryHeroLengthByHeroTypeKpi(UnifiedCalculationsScript):
    def __init__(self, data_provider, config_params=None, **kwargs):
        super(SecondaryHeroLengthByHeroTypeKpi,
              self).__init__(data_provider,
                             config_params=config_params,
                             **kwargs)
        self.util = PepsicoUtil(None, data_provider)
        self.kpi_name = self._config_params['kpi_type']

    def calculate(self):
        if self.util.commontools.are_all_bins_tagged:
            self.util.filtered_scif_secondary, self.util.filtered_matches_secondary = \
                self.util.commontools.set_filtered_scif_and_matches_for_specific_kpi(self.util.filtered_scif_secondary,
                                                                                     self.util.filtered_matches_secondary,
                                                                                     self.kpi_name)
            total_skus_in_ass = len(self.util.lvl3_ass_result)
            if not total_skus_in_ass:
                self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
                )
                return
            kpi_fk = self.util.common.get_kpi_fk_by_kpi_type(self.kpi_name)
            lvl3_ass_res_df = self.dependencies_data
            if lvl3_ass_res_df.empty and total_skus_in_ass:
                self.write_to_db_result(fk=kpi_fk,
                                        numerator_id=self.util.own_manuf_fk,
                                        result=0,
                                        score=0,
                                        denominator_id=self.util.store_id)
                self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
                )
                return
            if not lvl3_ass_res_df.empty:
                available_hero_list = lvl3_ass_res_df[(lvl3_ass_res_df['numerator_result'] == 1)] \
                    ['numerator_id'].unique().tolist()
                filtered_scif = self.util.filtered_scif_secondary[self.util.filtered_scif_secondary[ScifConsts.PRODUCT_FK].\
                    isin(available_hero_list)]
                result_df = filtered_scif.groupby([self.util.HERO_SKU_LABEL],
                                                  as_index=False).agg({
                                                      'updated_gross_length':
                                                      np.sum
                                                  })
                result_df = result_df.merge(
                    self.util.hero_type_custom_entity_df,
                    left_on=self.util.HERO_SKU_LABEL,
                    right_on='name',
                    how='left')
                for i, row in result_df.iterrows():
                    self.write_to_db_result(fk=kpi_fk,
                                            numerator_id=row['entity_fk'],
                                            denominator_id=row['entity_fk'],
                                            result=row['updated_gross_length'],
                                            score=row['updated_gross_length'])

            # add a function that resets to secondary scif and matches
            self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state(
            )

    def kpi_type(self):
        pass