Add functionality to manage and display minimum ROAS for bestsellers; implement AJAX calls for retrieval and saving
This commit is contained in:
38
.vscode/ftp-kr.sync.cache.json
vendored
38
.vscode/ftp-kr.sync.cache.json
vendored
@@ -13,7 +13,16 @@
|
|||||||
"lmtime": 0,
|
"lmtime": 0,
|
||||||
"modified": false
|
"modified": false
|
||||||
},
|
},
|
||||||
"autoload": {},
|
"autoload": {
|
||||||
|
"controls": {
|
||||||
|
"class.Products.php": {
|
||||||
|
"type": "-",
|
||||||
|
"size": 7477,
|
||||||
|
"lmtime": 1741427168653,
|
||||||
|
"modified": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"config.php": {
|
"config.php": {
|
||||||
"type": "-",
|
"type": "-",
|
||||||
"size": 357,
|
"size": 357,
|
||||||
@@ -38,7 +47,32 @@
|
|||||||
"lmtime": 0,
|
"lmtime": 0,
|
||||||
"modified": false
|
"modified": false
|
||||||
},
|
},
|
||||||
"layout": {},
|
"layout": {
|
||||||
|
"favicon.png": {
|
||||||
|
"type": "-",
|
||||||
|
"size": 353,
|
||||||
|
"lmtime": 0,
|
||||||
|
"modified": false
|
||||||
|
},
|
||||||
|
"style.css": {
|
||||||
|
"type": "-",
|
||||||
|
"size": 18247,
|
||||||
|
"lmtime": 1741427216637,
|
||||||
|
"modified": false
|
||||||
|
},
|
||||||
|
"style.css.map": {
|
||||||
|
"type": "-",
|
||||||
|
"size": 32918,
|
||||||
|
"lmtime": 1741427216637,
|
||||||
|
"modified": false
|
||||||
|
},
|
||||||
|
"style.scss": {
|
||||||
|
"type": "-",
|
||||||
|
"size": 22836,
|
||||||
|
"lmtime": 1741427216477,
|
||||||
|
"modified": false
|
||||||
|
}
|
||||||
|
},
|
||||||
"libraries": {},
|
"libraries": {},
|
||||||
"robots.txt": {
|
"robots.txt": {
|
||||||
"type": "-",
|
"type": "-",
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ class Cron
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$client_bestseller_min_roas = \factory\Products::get_client_bestseller_min_roas( $client_id );
|
||||||
|
|
||||||
$db_result = $mdb -> query( 'SELECT * FROM products AS p INNER JOIN products_history AS ph ON p.id = ph.product_id WHERE p.client_id = ' . $client_id ) -> fetchAll( \PDO::FETCH_ASSOC );
|
$db_result = $mdb -> query( 'SELECT * FROM products AS p INNER JOIN products_history AS ph ON p.id = ph.product_id WHERE p.client_id = ' . $client_id ) -> fetchAll( \PDO::FETCH_ASSOC );
|
||||||
|
|
||||||
$aggregated_data = [];
|
$aggregated_data = [];
|
||||||
@@ -61,46 +63,93 @@ class Cron
|
|||||||
$cpc = $offer_data['clicks'] > 0 ? round( $offer_data['cost'] / $offer_data['clicks'], 6 ) : 0;
|
$cpc = $offer_data['clicks'] > 0 ? round( $offer_data['cost'] / $offer_data['clicks'], 6 ) : 0;
|
||||||
$roas = ($offer_data['conversions'] > 0 and $offer_data['cost']) ? round($offer_data['conversions_value'] / $offer_data['cost'], 2) * 100 : 0;
|
$roas = ($offer_data['conversions'] > 0 and $offer_data['cost']) ? round($offer_data['conversions_value'] / $offer_data['cost'], 2) * 100 : 0;
|
||||||
|
|
||||||
$impressions_30 = \factory\Products::get_impressions_30( $offer_data['product_id'] );
|
// $impressions_30 = \factory\Products::get_impressions_30( $offer_data['product_id'] );
|
||||||
|
|
||||||
if ( $impressions_30 <= 30 )
|
// update custom_label_4 only current is empty or is bestseller
|
||||||
$custom_label_3 = 'product_zombie';
|
$custom_label_4 = \factory\Products::get_product_data( $offer_data['product_id'], 'custom_label_4' );
|
||||||
else
|
if ( $custom_label_4 == null || $custom_label_4 == 'bestseller' )
|
||||||
$custom_label_3 = null;
|
|
||||||
|
|
||||||
$offers_data_tmp = $mdb -> get( 'products_data', '*', [ 'product_id' => $offer_data['product_id'] ] );
|
|
||||||
if ( isset( $offers_data_tmp['id'] ) )
|
|
||||||
{
|
{
|
||||||
if ( $custom_label_3 != $offers_data_tmp['custom_label_3'] )
|
if ( $roas > $client_bestseller_min_roas and (int)$client_bestseller_min_roas > 0 and $offer_data['conversions'] > 10 )
|
||||||
$mdb -> insert( 'products_comments', [
|
|
||||||
'product_id' => $offer_data['product_id'],
|
|
||||||
'comment' => 'Zmiana pola "custom_label_3" na: ' . $custom_label_3,
|
|
||||||
'type' => 1,
|
|
||||||
'date_add' => date( 'Y-m-d' )
|
|
||||||
] );
|
|
||||||
|
|
||||||
$mdb -> update( 'products_data', [
|
|
||||||
'custom_label_3' => $custom_label_3
|
|
||||||
], [ 'id' => $offers_data_tmp['id'] ] );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$mdb -> insert( 'products_data', [
|
|
||||||
'product_id' => $offer_data['product_id'],
|
|
||||||
'custom_label_3' => $custom_label_3
|
|
||||||
] );
|
|
||||||
|
|
||||||
if ( $custom_label_3 == 'product_zombie' )
|
|
||||||
{
|
{
|
||||||
$mdb -> insert( 'products_comments', [
|
$new_custom_label_4 = 'bestseller';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$new_custom_label_4 = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$offers_data_tmp = $mdb -> get( 'products_data', '*', [ 'product_id' => $offer_data['product_id'] ] );
|
||||||
|
if ( isset( $offers_data_tmp['id'] ) )
|
||||||
|
{
|
||||||
|
if ( $new_custom_label_4 != $offers_data_tmp['custom_label_4'] )
|
||||||
|
$mdb -> insert( 'products_comments', [
|
||||||
|
'product_id' => $offer_data['product_id'],
|
||||||
|
'comment' => 'Zmiana pola "custom_label_4" na: ' . $new_custom_label_4,
|
||||||
|
'type' => 1,
|
||||||
|
'date_add' => date( 'Y-m-d' )
|
||||||
|
] );
|
||||||
|
|
||||||
|
$mdb -> update( 'products_data', [
|
||||||
|
'custom_label_4' => $new_custom_label_4
|
||||||
|
], [ 'id' => $offers_data_tmp['id'] ] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$mdb -> insert( 'products_data', [
|
||||||
'product_id' => $offer_data['product_id'],
|
'product_id' => $offer_data['product_id'],
|
||||||
'comment' => 'Zmiana pola "custom_label_3" na: product_zombie',
|
'custom_label_4' => $new_custom_label_4
|
||||||
'type' => 1,
|
|
||||||
'date_add' => date( 'Y-m-d' )
|
|
||||||
] );
|
] );
|
||||||
|
|
||||||
|
if ( $new_custom_label_4 == 'bestseller' )
|
||||||
|
{
|
||||||
|
$mdb -> insert( 'products_comments', [
|
||||||
|
'product_id' => $offer_data['product_id'],
|
||||||
|
'comment' => 'Zmiana pola "custom_label_4" na: bestseller',
|
||||||
|
'type' => 1,
|
||||||
|
'date_add' => date( 'Y-m-d' )
|
||||||
|
] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if ( $impressions_30 <= 30 )
|
||||||
|
// $custom_label_3 = 'product_zombie';
|
||||||
|
// else
|
||||||
|
// $custom_label_3 = null;
|
||||||
|
|
||||||
|
// $offers_data_tmp = $mdb -> get( 'products_data', '*', [ 'product_id' => $offer_data['product_id'] ] );
|
||||||
|
// if ( isset( $offers_data_tmp['id'] ) )
|
||||||
|
// {
|
||||||
|
// if ( $custom_label_3 != $offers_data_tmp['custom_label_3'] )
|
||||||
|
// $mdb -> insert( 'products_comments', [
|
||||||
|
// 'product_id' => $offer_data['product_id'],
|
||||||
|
// 'comment' => 'Zmiana pola "custom_label_3" na: ' . $custom_label_3,
|
||||||
|
// 'type' => 1,
|
||||||
|
// 'date_add' => date( 'Y-m-d' )
|
||||||
|
// ] );
|
||||||
|
|
||||||
|
// $mdb -> update( 'products_data', [
|
||||||
|
// 'custom_label_3' => $custom_label_3
|
||||||
|
// ], [ 'id' => $offers_data_tmp['id'] ] );
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// $mdb -> insert( 'products_data', [
|
||||||
|
// 'product_id' => $offer_data['product_id'],
|
||||||
|
// 'custom_label_3' => $custom_label_3
|
||||||
|
// ] );
|
||||||
|
|
||||||
|
// if ( $custom_label_3 == 'product_zombie' )
|
||||||
|
// {
|
||||||
|
// $mdb -> insert( 'products_comments', [
|
||||||
|
// 'product_id' => $offer_data['product_id'],
|
||||||
|
// 'comment' => 'Zmiana pola "custom_label_3" na: product_zombie',
|
||||||
|
// 'type' => 1,
|
||||||
|
// 'date_add' => date( 'Y-m-d' )
|
||||||
|
// ] );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// Zapisujemy każdy zsumowany wpis do offers_temp
|
// Zapisujemy każdy zsumowany wpis do offers_temp
|
||||||
$clicks_30 = \factory\Products::get_clicks_30( $offer_data['product_id'] );
|
$clicks_30 = \factory\Products::get_clicks_30( $offer_data['product_id'] );
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,33 @@
|
|||||||
namespace controls;
|
namespace controls;
|
||||||
class Products
|
class Products
|
||||||
{
|
{
|
||||||
|
static public function get_client_bestseller_min_roas() {
|
||||||
|
$client_id = \S::get( 'client_id' );
|
||||||
|
|
||||||
|
$min_roas = \factory\Products::get_client_bestseller_min_roas( $client_id );
|
||||||
|
|
||||||
|
if ( $min_roas )
|
||||||
|
{
|
||||||
|
echo json_encode( [ 'status' => 'ok', 'min_roas' => $min_roas ] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo json_encode( [ 'status' => 'error' ] );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function save_client_bestseller_min_roas() {
|
||||||
|
$client_id = \S::get( 'client_id' );
|
||||||
|
$min_roas = \S::get( 'min_roas' );
|
||||||
|
|
||||||
|
if ( \factory\Products::save_client_bestseller_min_roas( $client_id, $min_roas ) )
|
||||||
|
{
|
||||||
|
echo json_encode( [ 'status' => 'ok' ] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo json_encode( [ 'status' => 'error' ] );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
static public function main_view()
|
static public function main_view()
|
||||||
{
|
{
|
||||||
return \Tpl::view( 'products/main_view', [
|
return \Tpl::view( 'products/main_view', [
|
||||||
@@ -41,6 +68,14 @@ class Products
|
|||||||
if ( $custom_label_4 == 'product_deleted' )
|
if ( $custom_label_4 == 'product_deleted' )
|
||||||
$custom_class = 'text-danger';
|
$custom_class = 'text-danger';
|
||||||
|
|
||||||
|
$custom_label_4_color = '';
|
||||||
|
if ( $custom_label_4 == 'bestseller' )
|
||||||
|
$custom_label_4_color = 'background-color:rgb(96, 119, 102); color: #FFF;';
|
||||||
|
else if ( $custom_label_4 == 'deleted' )
|
||||||
|
$custom_label_4_color = 'background-color:rgb(255, 0, 0); color: #FFF;';
|
||||||
|
else if ( $custom_label_4 == 'zombie' )
|
||||||
|
$custom_label_4_color = 'background-color:rgb(58, 58, 58); color: #FFF;';
|
||||||
|
|
||||||
$data['data'][] = [
|
$data['data'][] = [
|
||||||
$row['product_id'],
|
$row['product_id'],
|
||||||
$row['offer_id'],
|
$row['offer_id'],
|
||||||
@@ -54,7 +89,7 @@ class Products
|
|||||||
</div>',
|
</div>',
|
||||||
$row['impressions'],
|
$row['impressions'],
|
||||||
$row['impressions_30'],
|
$row['impressions_30'],
|
||||||
$row['clicks'],
|
'<span style="color: ' . ( $row['clicks'] > 100 ? '#57b951' : '' ) . '">' . $row['clicks'] . '</span>',
|
||||||
$row['clicks_30'],
|
$row['clicks_30'],
|
||||||
round( $row['ctr'], 2 ) . '%',
|
round( $row['ctr'], 2 ) . '%',
|
||||||
\S::number_display( $row['cost'] ),
|
\S::number_display( $row['cost'] ),
|
||||||
@@ -64,7 +99,7 @@ class Products
|
|||||||
$row['roas'] <= $row['min_roas'] ? '<span class="text-danger text-bold">' . $row['roas'] . '</span>' : $row['roas'],
|
$row['roas'] <= $row['min_roas'] ? '<span class="text-danger text-bold">' . $row['roas'] . '</span>' : $row['roas'],
|
||||||
'<input type="text" class="form-control min_roas" product_id="' . $row['product_id'] . '" value="' . $row['min_roas'] . '" style="width: 100px;">',
|
'<input type="text" class="form-control min_roas" product_id="' . $row['product_id'] . '" value="' . $row['min_roas'] . '" style="width: 100px;">',
|
||||||
'',
|
'',
|
||||||
'<input type="text" class="form-control custom_label_4" product_id="' . $row['product_id'] . '" value="' . $custom_label_4 . '">'
|
'<input type="text" class="form-control custom_label_4" product_id="' . $row['product_id'] . '" value="' . $custom_label_4 . '" style="' . $custom_label_4_color . '">'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,18 @@
|
|||||||
namespace factory;
|
namespace factory;
|
||||||
class Products
|
class Products
|
||||||
{
|
{
|
||||||
|
static public function get_client_bestseller_min_roas( $client_id )
|
||||||
|
{
|
||||||
|
global $mdb;
|
||||||
|
return $mdb -> get( 'clients', 'bestseller_min_roas', [ 'id' => $client_id ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function save_client_bestseller_min_roas( $client_id, $min_roas )
|
||||||
|
{
|
||||||
|
global $mdb;
|
||||||
|
return $mdb -> update( 'clients', [ 'bestseller_min_roas' => $min_roas ], [ 'id' => $client_id ] );
|
||||||
|
}
|
||||||
|
|
||||||
static public function save_min_roas( $product_id, $min_roas )
|
static public function save_min_roas( $product_id, $min_roas )
|
||||||
{
|
{
|
||||||
global $mdb;
|
global $mdb;
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
<i class="arrow double"></i>
|
<i class="arrow double"></i>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-1 text-right">
|
||||||
|
<label>Bestseller min ROAS</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<input type="text" id="bestseller_min_roas" name="bestseller_min_roas" class="form-control" placeholder="Minimalny ROAS bestsellerów" value="" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,6 +65,29 @@
|
|||||||
table = $( '#products' ).DataTable();
|
table = $( '#products' ).DataTable();
|
||||||
table.destroy();
|
table.destroy();
|
||||||
|
|
||||||
|
// get min client roas
|
||||||
|
$.ajax({
|
||||||
|
url: '/products/get_client_bestseller_min_roas/',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
client_id: client_id
|
||||||
|
},
|
||||||
|
success: function( response ) {
|
||||||
|
data = JSON.parse(response);
|
||||||
|
if ( data.status == 'ok' )
|
||||||
|
{
|
||||||
|
$( '#bestseller_min_roas' ).val( data.min_roas );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$( '#bestseller_min_roas' ).val( '' );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
new DataTable( '#products', {
|
new DataTable( '#products', {
|
||||||
ajax: {
|
ajax: {
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
@@ -225,5 +254,33 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$( 'body' ).on( 'blur', '#bestseller_min_roas', function(){
|
||||||
|
var min_roas = $( this ).val();
|
||||||
|
var client_id = $( '#client_id' ).val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/products/save_client_bestseller_min_roas/',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
client_id: client_id,
|
||||||
|
min_roas: min_roas
|
||||||
|
},
|
||||||
|
success: function( response ) {
|
||||||
|
data = JSON.parse(response);
|
||||||
|
if ( data.status == 'ok' )
|
||||||
|
{
|
||||||
|
$.alert( 'Minimalny ROAS bestsellerów został pomyślnie zapisany' );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$.alert('Błąd: ' + response);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
$.alert('Wystąpił błąd podczas zapisywania minimalnego ROAS. Spróbuj ponownie.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
Reference in New Issue
Block a user