feat: update font to Roboto across templates and add campaign/ad group filters in product views
- Changed font from Open Sans to Roboto in layout files. - Added campaign and ad group filters in products main view. - Enhanced product history to include campaign and ad group IDs. - Updated migrations to support new campaign and ad group dimensions in product statistics. - Introduced new migration files for managing campaign types and dropping obsolete columns.
This commit is contained in:
@@ -295,7 +295,7 @@ class Api
|
||||
|
||||
$processed = 0;
|
||||
$skipped = 0;
|
||||
$touched_product_ids = [];
|
||||
$touched_scopes = [];
|
||||
|
||||
foreach ( $data['data'] as $offer )
|
||||
{
|
||||
@@ -338,6 +338,23 @@ class Api
|
||||
continue;
|
||||
}
|
||||
|
||||
$campaign_external_id = (int) self::normalize_number( $offer['CampaignId'] ?? ( $offer['campaign_id'] ?? 0 ) );
|
||||
$campaign_name = trim( (string) ( $offer['CampaignName'] ?? ( $offer['campaign_name'] ?? '' ) ) );
|
||||
$ad_group_external_id = (int) self::normalize_number( $offer['AdGroupId'] ?? ( $offer['ad_group_id'] ?? 0 ) );
|
||||
$ad_group_name = trim( (string) ( $offer['AdGroupName'] ?? ( $offer['ad_group_name'] ?? '' ) ) );
|
||||
|
||||
$scope = \controls\Cron::resolve_products_scope_ids(
|
||||
$client_id,
|
||||
$campaign_external_id,
|
||||
$campaign_name,
|
||||
$ad_group_external_id,
|
||||
$ad_group_name,
|
||||
$date
|
||||
);
|
||||
|
||||
$db_campaign_id = (int) ( $scope['campaign_id'] ?? 0 );
|
||||
$db_ad_group_id = (int) ( $scope['ad_group_id'] ?? 0 );
|
||||
|
||||
$impressions = (int) round( self::normalize_number( $offer['Impressions'] ?? 0 ) );
|
||||
$clicks = (int) round( self::normalize_number( $offer['Clicks'] ?? 0 ) );
|
||||
$cost = self::normalize_number( $offer['Cost'] ?? 0 );
|
||||
@@ -352,12 +369,24 @@ class Api
|
||||
'cost' => $cost,
|
||||
'conversions' => $conversions,
|
||||
'conversions_value' => $conversion_value,
|
||||
'updated' => 1
|
||||
'updated' => 1,
|
||||
'campaign_id' => $db_campaign_id,
|
||||
'ad_group_id' => $db_ad_group_id
|
||||
];
|
||||
|
||||
if ( $mdb -> count( 'products_history', [ 'AND' => [ 'product_id' => $product_id, 'date_add' => $date ] ] ) )
|
||||
if ( $mdb -> count( 'products_history', [ 'AND' => [
|
||||
'product_id' => $product_id,
|
||||
'campaign_id' => $db_campaign_id,
|
||||
'ad_group_id' => $db_ad_group_id,
|
||||
'date_add' => $date
|
||||
] ] ) )
|
||||
{
|
||||
$offer_data_old = $mdb -> get( 'products_history', '*', [ 'AND' => [ 'product_id' => $product_id, 'date_add' => $date ] ] );
|
||||
$offer_data_old = $mdb -> get( 'products_history', '*', [ 'AND' => [
|
||||
'product_id' => $product_id,
|
||||
'campaign_id' => $db_campaign_id,
|
||||
'ad_group_id' => $db_ad_group_id,
|
||||
'date_add' => $date
|
||||
] ] );
|
||||
|
||||
if (
|
||||
$offer_data_old['impressions'] == $offer_data['impressions']
|
||||
@@ -367,13 +396,23 @@ class Api
|
||||
and number_format( (float) str_replace( ',', '.', $offer_data_old['conversions_value'] ), 5 ) == number_format( (float) $offer_data['conversions_value'], 5 )
|
||||
)
|
||||
{
|
||||
$touched_product_ids[ $product_id ] = true;
|
||||
$scope_key = (int) $product_id . '|' . $db_campaign_id . '|' . $db_ad_group_id;
|
||||
$touched_scopes[ $scope_key ] = [
|
||||
'product_id' => (int) $product_id,
|
||||
'campaign_id' => $db_campaign_id,
|
||||
'ad_group_id' => $db_ad_group_id
|
||||
];
|
||||
$processed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
$mdb -> update( 'products_history', $offer_data, [
|
||||
'AND' => [ 'product_id' => $product_id, 'date_add' => $date ]
|
||||
'AND' => [
|
||||
'product_id' => $product_id,
|
||||
'campaign_id' => $db_campaign_id,
|
||||
'ad_group_id' => $db_ad_group_id,
|
||||
'date_add' => $date
|
||||
]
|
||||
] );
|
||||
}
|
||||
else
|
||||
@@ -383,19 +422,33 @@ class Api
|
||||
$mdb -> insert( 'products_history', $offer_data );
|
||||
}
|
||||
|
||||
$touched_product_ids[ $product_id ] = true;
|
||||
$scope_key = (int) $product_id . '|' . $db_campaign_id . '|' . $db_ad_group_id;
|
||||
$touched_scopes[ $scope_key ] = [
|
||||
'product_id' => (int) $product_id,
|
||||
'campaign_id' => $db_campaign_id,
|
||||
'ad_group_id' => $db_ad_group_id
|
||||
];
|
||||
$processed++;
|
||||
}
|
||||
|
||||
$history_30_rows = 0;
|
||||
foreach ( array_keys( $touched_product_ids ) as $product_id )
|
||||
foreach ( $touched_scopes as $scope )
|
||||
{
|
||||
\controls\Cron::cron_product_history_30_save( (int) $product_id, $date );
|
||||
$mdb -> update( 'products_history', [ 'updated' => 0 ], [ 'AND' => [ 'product_id' => (int) $product_id, 'date_add' => $date ] ] );
|
||||
$product_id = (int) ( $scope['product_id'] ?? 0 );
|
||||
$campaign_id = (int) ( $scope['campaign_id'] ?? 0 );
|
||||
$ad_group_id = (int) ( $scope['ad_group_id'] ?? 0 );
|
||||
|
||||
\controls\Cron::cron_product_history_30_save( $product_id, $date, $campaign_id, $ad_group_id );
|
||||
$mdb -> update( 'products_history', [ 'updated' => 0 ], [ 'AND' => [
|
||||
'product_id' => $product_id,
|
||||
'campaign_id' => $campaign_id,
|
||||
'ad_group_id' => $ad_group_id,
|
||||
'date_add' => $date
|
||||
] ] );
|
||||
$history_30_rows++;
|
||||
}
|
||||
|
||||
$temp_rows = self::rebuild_products_temp_for_client( $client_id );
|
||||
$temp_rows = \controls\Cron::rebuild_products_temp_for_client( $client_id );
|
||||
|
||||
echo json_encode( [
|
||||
'status' => 'ok',
|
||||
@@ -411,67 +464,7 @@ class Api
|
||||
|
||||
static private function rebuild_products_temp_for_client( $client_id )
|
||||
{
|
||||
global $mdb;
|
||||
|
||||
$client_id = (int) $client_id;
|
||||
if ( $client_id <= 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
$product_ids = $mdb -> select( 'products', 'id', [ 'client_id' => $client_id ] );
|
||||
if ( empty( $product_ids ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
$mdb -> delete( 'products_temp', [ 'product_id' => $product_ids ] );
|
||||
|
||||
$rows = $mdb -> query(
|
||||
'SELECT p.id AS product_id, p.name,
|
||||
COALESCE( SUM( ph.impressions ), 0 ) AS impressions,
|
||||
COALESCE( SUM( ph.clicks ), 0 ) AS clicks,
|
||||
COALESCE( SUM( ph.cost ), 0 ) AS cost,
|
||||
COALESCE( SUM( ph.conversions ), 0 ) AS conversions,
|
||||
COALESCE( SUM( ph.conversions_value ), 0 ) AS conversions_value
|
||||
FROM products AS p
|
||||
LEFT JOIN products_history AS ph ON p.id = ph.product_id
|
||||
WHERE p.client_id = :client_id
|
||||
GROUP BY p.id, p.name',
|
||||
[ ':client_id' => $client_id ]
|
||||
) -> fetchAll( \PDO::FETCH_ASSOC );
|
||||
|
||||
$inserted = 0;
|
||||
foreach ( $rows as $row )
|
||||
{
|
||||
$impressions = (int) $row['impressions'];
|
||||
$clicks = (int) $row['clicks'];
|
||||
$cost = (float) $row['cost'];
|
||||
$conversions = (float) $row['conversions'];
|
||||
$conversion_value = (float) $row['conversions_value'];
|
||||
$ctr = ( $impressions > 0 ) ? round( $clicks / $impressions, 4 ) * 100 : 0;
|
||||
$cpc = ( $clicks > 0 ) ? round( $cost / $clicks, 6 ) : 0;
|
||||
$roas = ( $cost > 0 ) ? round( $conversion_value / $cost, 2 ) * 100 : 0;
|
||||
|
||||
$mdb -> insert( 'products_temp', [
|
||||
'product_id' => (int) $row['product_id'],
|
||||
'name' => $row['name'],
|
||||
'impressions' => $impressions,
|
||||
'impressions_30' => (int) \factory\Products::get_impressions_30( (int) $row['product_id'] ),
|
||||
'clicks' => $clicks,
|
||||
'clicks_30' => (int) \factory\Products::get_clicks_30( (int) $row['product_id'] ),
|
||||
'ctr' => $ctr,
|
||||
'cost' => $cost,
|
||||
'conversions' => $conversions,
|
||||
'conversions_value' => $conversion_value,
|
||||
'cpc' => $cpc,
|
||||
'roas' => $roas
|
||||
] );
|
||||
|
||||
$inserted++;
|
||||
}
|
||||
|
||||
return $inserted;
|
||||
return \controls\Cron::rebuild_products_temp_for_client( $client_id );
|
||||
}
|
||||
|
||||
static private function normalize_number( $value )
|
||||
|
||||
Reference in New Issue
Block a user