Files
adsPRO/autoload/controls/class.Api.php
Jacek Pyziak 167ced3573 feat: Enhance user settings with cron URL plan display
- Added a new field to display the cron URL plan in user settings.
- Updated JavaScript to handle the new plan data.

refactor: Unify product model and migrate data

- Migrated product data from `products_data` to `products` table.
- Added new columns to `products` for better data organization.
- Created `products_aggregate` table for storing aggregated product metrics.

chore: Drop deprecated products_data table

- Removed `products_data` table as data is now stored in `products`.

feat: Add merchant URL flags to products

- Introduced flags for tracking merchant URL status in `products` table.
- Normalized product URLs to handle empty or invalid values.

feat: Link campaign alerts to specific products

- Added `product_id` column to `campaign_alerts` table for better tracking.
- Created an index for efficient querying of alerts by product.

chore: Add debug scripts for client data inspection

- Created debug scripts to inspect client data from local and remote databases.
- Included error handling and output formatting for better readability.
2026-02-20 17:50:14 +01:00

520 lines
19 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace controls;
class Api
{
static public function campaigns_data_save()
{
global $mdb;
$json = file_get_contents( 'php://input' );
$data = json_decode( $json, true );
if ( $data['clientId'] and $data['date'] )
{
foreach ( $data['data'] as $campaign )
{
if ( !$mdb -> count( 'campaigns', [ 'AND' => [ 'client_id' => $data['clientId'], 'campaign_id' => $campaign['campaignId'] ] ] ) )
{
$campaign_data['client_id'] = $data['clientId'];
$campaign_data['campaign_id'] = $campaign['campaignId'];
$campaign_data['campaign_name'] = $campaign['camapignName'];
$mdb -> insert( 'campaigns', [
'client_id' => $data['clientId'],
'campaign_id' => $campaign['campaignId'],
'campaign_name' => $campaign['camapignName']
] );
$campaign_id = $mdb -> id();
}
else
{
$campaign_id = $mdb -> get( 'campaigns', 'id', [ 'AND' => [ 'client_id' => $data['clientId'], 'campaign_id' => $campaign['campaignId'] ] ] );
}
if ( $campaign_id )
{
$campaign_history_data = [];
$campaign_history_data['roas_30_days'] = $campaign['roas30Days'];
$campaign_history_data['roas_all_time'] = $campaign['roasAllTime'];
$campaign_history_data['budget'] = str_replace( ' zł', '' , $campaign['budget'] );
$campaign_history_data['money_spent'] = floatval( preg_replace(['/[^0-9,]/', '/,/'], ['', '.'], $campaign['spend30Days'] ) );
$campaign_history_data['conversion_value'] = preg_replace( '/[^\d,.-]/', '', $campaign['conversionValue30Days'] );
if ( isset( $campaign['biddingStrategy'] ) and $campaign['biddingStrategy'] == 'MAXIMIZE_CONVERSIONS' )
{
$campaign_history_data['bidding_strategy'] = 'Maksymalizacja liczby konwersji';
}
else if ( isset( $campaign['biddingStrategy'] ) and $campaign['biddingStrategy'] == 'MAXIMIZE_CONVERSION_VALUE' )
{
$campaign_history_data['bidding_strategy'] = 'Maksymalizacja wartości konwersji';
}
else if ( isset( $campaign['biddingStrategy'] ) and $campaign['biddingStrategy'] == 'TARGET_ROAS' )
{
$campaign_history_data['bidding_strategy'] = 'Docelowy ROAS';
}
else if ( isset( $campaign['biddingStrategy'] ) )
{
$campaign_history_data['bidding_strategy'] = $campaign['biddingStrategy'];
}
else
{
$campaign_history_data['bidding_strategy'] = 'brak';
}
if ( isset( $campaign['targetRoas'] ) and (float)$campaign['targetRoas'] > 0 )
{
$campaign_history_data['bidding_strategy'] .= ' | docelowy ROAS: ' . ( (float)$campaign['targetRoas'] * 100 ) . '%';
}
if ( $mdb -> count( 'campaigns_history', [ 'AND' => [ 'campaign_id' => $campaign_id, 'date_add' => $data['date'] ] ] ) )
{
$mdb -> update( 'campaigns_history', $campaign_history_data, [ 'AND' => [ 'campaign_id' => $campaign_id, 'date_add' => $data['date'] ] ] );
}
else
{
$campaign_history_data['campaign_id'] = $campaign_id;
$campaign_history_data['date_add'] = $data['date'];
$mdb -> insert( 'campaigns_history', $campaign_history_data );
}
}
}
}
echo json_encode( [ 'status' => 'ok' ] );
exit;
}
static public function phrases_data_save()
{
global $mdb;
$json = file_get_contents( 'php://input' );
$data = json_decode( $json, true );
if ( $data['client_id'] and $data['date'] )
{
foreach ( $data['data'] as $phrase )
{
$phrase_data = [];
if ( !$mdb -> count( 'phrases', [ 'AND' => [ 'client_id' => $data['client_id'], 'phrase' => $phrase['Query'] ] ] ) )
{
$phrase_data['phrase'] = $phrase['Query'];
$mdb -> insert( 'phrases', [
'client_id' => $data['client_id'],
'phrase' => $phrase['Query']
] );
$phrase_id = $mdb -> id();
}
else
{
$phrase_id = $mdb -> get( 'phrases', 'id', [ 'AND' => [ 'client_id' => $data['client_id'], 'phrase' => $phrase['Query'] ] ] );
}
if ( $phrase_id )
{
$phrase_data['impressions'] = $phrase['Impressions'];
$phrase_data['clicks'] = $phrase['Clicks'];
$phrase_data['cost'] = $phrase['Cost'];
$phrase_data['conversions'] = $phrase['Conversions'];
$phrase_data['conversions_value'] = preg_replace( '/[^\d,.-]/', '', $phrase['ConversionValue'] );
$phrase_data['updated'] = 1;
if ( $mdb -> count( 'phrases_history', [ 'AND' => [ 'phrase_id' => $phrase_id, 'date_add' => $data['date'] ] ] ) )
{
$phrase_data_old = [];
$phrase_data_old = $mdb -> get( 'phrases_history', '*', [ 'AND' => [ 'phrase_id' => $phrase_id, 'date_add' => $data['date'] ] ] );
if (
$phrase_data_old['impressions'] == $phrase_data['impressions']
and $phrase_data_old['clicks'] == $phrase_data['clicks']
and number_format((float)str_replace(',', '.', $phrase_data_old['cost']), 5) == number_format((float)$phrase_data['cost'], 5)
and $phrase_data_old['conversions'] == $phrase_data['conversions']
and number_format((float)str_replace(',', '.', $phrase_data_old['conversions_value']), 5) == number_format((float)$phrase_data['conversions_value'], 5)
) {
continue;
}
$mdb -> update( 'phrases_history', [
'impressions' => $phrase_data['impressions'],
'clicks' => $phrase_data['clicks'],
'cost' => $phrase_data['cost'],
'conversions' => $phrase_data['conversions'],
'conversions_value' => $phrase_data['conversions_value'],
'updated' => 1
], [
'AND' => [ 'phrase_id' => $phrase_id, 'date_add' => $data['date'] ]
] );
}
else
{
$mdb -> insert( 'phrases_history', [
'phrase_id' => $phrase_id,
'date_add' => $data['date'],
'impressions' => $phrase_data['impressions'],
'clicks' => $phrase_data['clicks'],
'cost' => $phrase_data['cost'],
'conversions' => $phrase_data['conversions'],
'conversions_value' => $phrase_data['conversions_value'],
'updated' => 1
] );
}
}
}
}
echo json_encode( [ 'status' => 'ok' ] );
exit;
}
static public function products_data_save()
{
global $mdb;
$json = file_get_contents( 'php://input' );
$data = json_decode( $json, true );
// file_put_contents( 'tmp/products_data_save.txt', print_r( $data, true ) );
if ( $data['client_id'] and $data['date'] )
{
foreach ( $data['data'] as $offer )
{
$offer_data = [];
if ( !$mdb -> count( 'products', [ 'AND' => [ 'client_id' => $data['client_id'], 'offer_id' => $offer['OfferId'] ] ] ) )
{
$offer_data['client_id'] = $data['client_id'];
$offer_data['offer_id'] = $offer['OfferId'];
$offer_data['offer_name'] = $offer['ProductTitle'];
$mdb -> insert( 'products', [
'client_id' => $data['client_id'],
'offer_id' => $offer['OfferId'],
'name' => $offer['ProductTitle']
] );
$offer_id = $mdb -> id();
}
else
{
$offer_id = $mdb -> get( 'products', 'id', [ 'AND' => [ 'client_id' => $data['client_id'], 'offer_id' => $offer['OfferId'] ] ] );
$offer_current_name = $mdb -> get( 'products', 'name', [ 'AND' => [ 'client_id' => $data['client_id'], 'offer_id' => $offer['OfferId'] ] ] );
if ( $offer_current_name != $offer['ProductTitle'] and $data['date'] == date( 'Y-m-d', strtotime( '-1 days', time() ) ) )
{
$mdb -> update( 'products', [ 'name' => $offer['ProductTitle'] ], [ 'AND' => [ 'client_id' => $data['client_id'], 'offer_id' => $offer['OfferId'] ] ] );
}
}
if ( $offer_id )
{
$offer_data['impressions'] = $offer['Impressions'];
$offer_data['clicks'] = $offer['Clicks'];
$offer_data['ctr'] = round( $offer['Clicks'] / $offer['Impressions'], 4 ) * 100;
$offer_data['cost'] = preg_replace( '/[^\d,.-]/', '', $offer['Cost'] );
$offer_data['conversions'] = $offer['Conversions'];
$offer_data['conversions_value'] = preg_replace( '/[^\d,.-]/', '', $offer['ConversionValue'] );
$offer_data['updated'] = 1;
if ( $mdb -> count( 'products_history', [ 'AND' => [ 'product_id' => $offer_id, 'date_add' => $data['date'] ] ] ) )
{
$offer_data_old = [];
$offer_data_old = $mdb -> get( 'products_history', '*', [ 'AND' => [ 'product_id' => $offer_id, 'date_add' => $data['date'] ] ] );
if (
$offer_data_old['impressions'] == $offer_data['impressions']
and $offer_data_old['clicks'] == $offer_data['clicks']
and number_format((float)str_replace(',', '.', $offer_data_old['cost']), 5) == number_format((float)$offer_data['cost'], 5)
and $offer_data_old['conversions'] == $offer_data['conversions']
and number_format((float)str_replace(',', '.', $offer_data_old['conversions_value']), 5) == number_format((float)$offer_data['conversions_value'], 5)
) {
continue;
}
$mdb -> update( 'products_history', [
'impressions' => $offer_data['impressions'],
'clicks' => $offer_data['clicks'],
'ctr' => $offer_data['ctr'],
'cost' => $offer_data['cost'],
'conversions' => $offer_data['conversions'],
'conversions_value' => $offer_data['conversions_value'],
'updated' => 1
], [
'AND' => [ 'product_id' => $offer_id, 'date_add' => $data['date'] ]
] );
}
else
{
$mdb -> insert( 'products_history', [
'product_id' => $offer_id,
'date_add' => $data['date'],
'impressions' => $offer_data['impressions'],
'clicks' => $offer_data['clicks'],
'ctr' => $offer_data['ctr'],
'cost' => $offer_data['cost'],
'conversions' => $offer_data['conversions'],
'conversions_value' => $offer_data['conversions_value'],
'updated' => 1
] );
}
}
}
}
echo json_encode( [ 'status' => 'ok' ] );
exit;
}
static public function products_data_import()
{
global $mdb;
$json = file_get_contents( 'php://input' );
$data = json_decode( $json, true );
if ( !is_array( $data ) || empty( $data['client_id'] ) || empty( $data['date'] ) || !isset( $data['data'] ) || !is_array( $data['data'] ) )
{
echo json_encode( [ 'status' => 'error', 'message' => 'Nieprawidlowe dane wejsciowe. Oczekiwano: client_id, date, data[].' ] );
exit;
}
$client_id = (int) $data['client_id'];
$date = date( 'Y-m-d', strtotime( $data['date'] ) );
if ( !$mdb -> count( 'clients', [ 'id' => $client_id ] ) )
{
echo json_encode( [ 'status' => 'error', 'message' => 'Nie znaleziono klienta o podanym ID.' ] );
exit;
}
$processed = 0;
$skipped = 0;
$touched_scopes = [];
foreach ( $data['data'] as $offer )
{
$offer_external_id = trim( (string) ( $offer['OfferId'] ?? '' ) );
if ( $offer_external_id === '' )
{
$skipped++;
continue;
}
$product_title = trim( (string) ( $offer['ProductTitle'] ?? '' ) );
if ( $product_title === '' )
{
$product_title = $offer_external_id;
}
if ( !$mdb -> count( 'products', [ 'AND' => [ 'client_id' => $client_id, 'offer_id' => $offer_external_id ] ] ) )
{
$mdb -> insert( 'products', [
'client_id' => $client_id,
'offer_id' => $offer_external_id,
'name' => $product_title
] );
$product_id = $mdb -> id();
}
else
{
$product_id = $mdb -> get( 'products', 'id', [ 'AND' => [ 'client_id' => $client_id, 'offer_id' => $offer_external_id ] ] );
$offer_current_name = $mdb -> get( 'products', 'name', [ 'AND' => [ 'client_id' => $client_id, 'offer_id' => $offer_external_id ] ] );
if ( $offer_current_name != $product_title and $date == date( 'Y-m-d', strtotime( '-1 days', time() ) ) )
{
$mdb -> update( 'products', [ 'name' => $product_title ], [ 'AND' => [ 'client_id' => $client_id, 'offer_id' => $offer_external_id ] ] );
}
}
if ( !$product_id )
{
$skipped++;
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 );
$conversions = self::normalize_number( $offer['Conversions'] ?? 0 );
$conversion_value = self::normalize_number( $offer['ConversionValue'] ?? 0 );
$ctr = ( $impressions > 0 ) ? round( $clicks / $impressions, 4 ) * 100 : 0;
$offer_data = [
'impressions' => $impressions,
'clicks' => $clicks,
'ctr' => $ctr,
'cost' => $cost,
'conversions' => $conversions,
'conversions_value' => $conversion_value,
'updated' => 1,
'campaign_id' => $db_campaign_id,
'ad_group_id' => $db_ad_group_id
];
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,
'campaign_id' => $db_campaign_id,
'ad_group_id' => $db_ad_group_id,
'date_add' => $date
] ] );
if (
$offer_data_old['impressions'] == $offer_data['impressions']
and $offer_data_old['clicks'] == $offer_data['clicks']
and number_format( (float) str_replace( ',', '.', $offer_data_old['cost'] ), 5 ) == number_format( (float) $offer_data['cost'], 5 )
and (float) $offer_data_old['conversions'] == (float) $offer_data['conversions']
and number_format( (float) str_replace( ',', '.', $offer_data_old['conversions_value'] ), 5 ) == number_format( (float) $offer_data['conversions_value'], 5 )
)
{
$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,
'campaign_id' => $db_campaign_id,
'ad_group_id' => $db_ad_group_id,
'date_add' => $date
]
] );
}
else
{
$offer_data['product_id'] = $product_id;
$offer_data['date_add'] = $date;
$mdb -> insert( 'products_history', $offer_data );
}
$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 ( $touched_scopes as $scope )
{
$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++;
}
$aggregate_rows = \controls\Cron::rebuild_products_temp_for_client( $client_id );
echo json_encode( [
'status' => 'ok',
'client_id' => $client_id,
'date' => $date,
'processed' => $processed,
'skipped' => $skipped,
'history_30_products' => $history_30_rows,
'products_aggregate_rows' => $aggregate_rows
] );
exit;
}
static private function rebuild_products_temp_for_client( $client_id )
{
return \controls\Cron::rebuild_products_temp_for_client( $client_id );
}
static private function normalize_number( $value )
{
if ( $value === null || $value === '' )
{
return 0.0;
}
if ( is_int( $value ) || is_float( $value ) )
{
return (float) $value;
}
$value = trim( (string) $value );
if ( $value === '' )
{
return 0.0;
}
$value = preg_replace( '/[^\d,.\-]/', '', $value );
if ( $value === '' || $value === '-' || $value === ',' || $value === '.' )
{
return 0.0;
}
$has_comma = strpos( $value, ',' ) !== false;
$has_dot = strpos( $value, '.' ) !== false;
if ( $has_comma && $has_dot )
{
$last_comma = strrpos( $value, ',' );
$last_dot = strrpos( $value, '.' );
if ( $last_comma > $last_dot )
{
$value = str_replace( '.', '', $value );
$value = str_replace( ',', '.', $value );
}
else
{
$value = str_replace( ',', '', $value );
}
}
else
{
$value = str_replace( ',', '.', $value );
}
return (float) $value;
}
}