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( )
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( )
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 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)
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 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( )
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
class SecondaryHeroTotalLengthKpi(UnifiedCalculationsScript): def __init__(self, data_provider, config_params=None, **kwargs): super(SecondaryHeroTotalLengthKpi, 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): # pass secondary scif and matches 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: 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() hero_len = self.util.filtered_scif_secondary[self.util.filtered_scif_secondary[ScifConsts.PRODUCT_FK].isin(available_hero_list)]\ ['updated_gross_length'].sum() self.write_to_db_result(fk=kpi_fk, numerator_id=self.util.own_manuf_fk, denominator_id=self.util.store_id, result=hero_len, score=hero_len) # 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
class SecondaryAllHeroSOSofCSNCategoryKpi(UnifiedCalculationsScript): 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'] def calculate(self): # pass secondary scif and matches 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 lvl3_ass_res_df = self.dependencies_data if lvl3_ass_res_df.empty: self.util.reset_secondary_filtered_scif_and_matches_to_exclusion_all_state( ) return # talk to Nitzan if not lvl3_ass_res_df.empty: 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) available_hero_list = lvl3_ass_res_df[(lvl3_ass_res_df['numerator_result'] == 1)] \ ['numerator_id'].unique().tolist() filtered_scif = filtered_scif[filtered_scif[ ScifConsts.PRODUCT_FK].isin(available_hero_list)] all_hero_cat_df = filtered_scif.groupby([ScifConsts.CATEGORY_FK], as_index=False).\ agg({'updated_gross_length': np.sum}) all_hero_cat_df = all_hero_cat_df.merge( category_df, on=ScifConsts.CATEGORY_FK, how='left') all_hero_cat_df['cat_len'] = all_hero_cat_df['cat_len'].fillna( 0) if not all_hero_cat_df.empty: all_hero_cat_df['sos'] = all_hero_cat_df.apply( self.calculate_sos, axis=1) for i, row in all_hero_cat_df.iterrows(): self.write_to_db_result( fk=kpi_fk, numerator_id=self.util.own_manuf_fk, numerator_result=row['updated_gross_length'], denominator_id=row[ScifConsts.CATEGORY_FK], denominator_result=row['cat_len'], result=row['sos']) # 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 @staticmethod def calculate_sos(row): sos = 0 if row['cat_len'] != 0: sos = float(row['updated_gross_length']) / row['cat_len'] * 100 return sos