Commit 3884f673 by Vladislav

#21467 Удаление ретаргетинга компаний

1 parent e4d8e4a6
......@@ -322,7 +322,7 @@ class DictionaryCampaignsSyncByCampaign extends Command
INNER JOIN campaigns c on aut.campaign_id = c.id
INNER JOIN dictionary_campaigns dc on dc.campaign_id = c.id AND dc.deleted_at is null
INNER JOIN dictionaries d on dc.dictionary_id = d.id
INNER JOIN retargetinglists r on aut.retargetinglist_external_id = r.external_id
INNER JOIN retargetinglists r on aut.retargetinglist_external_id = r.external_id AND r.deleted_at is null
INNER JOIN goal_retargetinglists gr on r.id = gr.retargetinglist_id AND d.token_id = gr.token_id AND gr.deleted_at is null
LEFT JOIN ad_groups ag on c.id = ag.campaign_id AND aut.ad_group_id = ag.id AND ag.deleted_at is null
LEFT JOIN goal_ad_groups gag on dc.id = gag.dictionary_campaign_id AND ag.id = gag.ad_group_id AND gag.deleted_at is null
......
<?php
namespace App\Console\Commands;
use App\Models\Pivots\GoalRetargetinglist;
use App\Models\Tokens;
use App\Service\Requests\Direct\DeleteRetargetinglists;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Relations\HasMany;
class RetargetinglistsDelete extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'retargetinglists:delete';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Удаление созданных условия ретаргетинга и подбора аудитории с целевого аккаунта';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
* @throws \Exception
*/
public function handle()
{
$tokens = Tokens::whereHas('goalRetargetinglistsForExternalNeedDeletedForNotReserveDelete')
->where('type', '!=', Tokens::MAIN)
->get();
foreach ($tokens as $token) {
$token->load([
'goalRetargetinglistsForExternalNeedDeletedForNotReserveDelete'
]);
$goalRetargetinglists = $token->goalRetargetinglistsForExternalNeedDeletedForNotReserveDelete;
foreach (array_chunk($goalRetargetinglists->pluck('id')->toArray(), 1000) as $items) {
GoalRetargetinglist::whereIn('id', $items)
->update([
'reserve_delete_at' => Carbon::now(),
]);
}
$request = new DeleteRetargetinglists();
$request->setToken($token)
->call([
'Ids' => $goalRetargetinglists->pluck('id')->toArray(),
]);
}
return 0;
}
}
......@@ -41,6 +41,7 @@ use App\Console\Commands\NegativeKeywordSharedSetsLoad;
use App\Console\Commands\NegativeKeywordSharedSetsUpdate;
use App\Console\Commands\RefreshLimits;
use App\Console\Commands\RetargetinglistsAdd;
use App\Console\Commands\RetargetinglistsDelete;
use App\Console\Commands\RetargetinglistsLoad;
use App\Console\Commands\RetargetinglistsUpdate;
use App\Console\Commands\SitelinksAdd;
......@@ -118,6 +119,8 @@ protected function schedule(Schedule $schedule)
$schedule->command(SitelinksAdd::class)->hourlyAt(35);
$schedule->command(NegativeKeywordSharedSetsAdd::class)->hourlyAt(35);
$schedule->command(NegativeKeywordSharedSetsUpdate::class)->hourlyAt(35);
$schedule->command(RetargetinglistsDelete::class)->hourlyAt(30);
$schedule->command(RetargetinglistsAdd::class)->hourlyAt(35);
$schedule->command(RetargetinglistsUpdate::class)->hourlyAt(35);
......
......@@ -101,10 +101,19 @@ class GoalAudienceTarget extends Pivot
$query->select(DB::raw(1))
->from('goal_ad_groups')
->join('ad_groups', 'goal_ad_groups.ad_group_id', '=', 'ad_groups.id')
->whereNull('goal_ad_groups.deleted_at')
->join('goal_retargetinglists', 'goal_audience_targets.goal_retargetinglist_id', '=', 'goal_retargetinglists.id')
->join('retargetinglists', 'goal_retargetinglists.retargetinglist_id', '=', 'retargetinglists.id')
->where(function ($query) {
$query->where(function ($query) {
$query->whereNull('goal_ad_groups.deleted_at')
->whereNotNull('goal_ad_groups.external_id')
->whereNotNull('ad_groups.deleted_at')
->whereColumn('goal_audience_targets.goal_ad_group_id', 'goal_ad_groups.id');
})->orWhere(function ($query) {
$query->whereNotNull('retargetinglists.deleted_at')
->orWhereNotNull('goal_retargetinglists.deleted_at');
});
});
});
}
......
......@@ -90,11 +90,29 @@ class GoalRetargetinglist extends Pivot
* @param Builder $query
* @return Builder
*/
public function scopeForNotReserveDelete($query)
{
return $query->whereNull('reserve_delete_at');
}
/**
* @param Builder $query
* @return Builder
*/
public function scopeNeedUpdated($query)
{
return $query->whereNotNull('updated_need');
}
/**
* @param Builder $query
* @return Builder
*/
public function scopeNeedDeleted($query)
{
return $query->whereDoesntHave('retargetinglist')->whereDoesntHave('goalAudienceTargets');
}
public function retargetinglist()
{
return $this->belongsTo(Retargetinglist::class, 'retargetinglist_id');
......
......@@ -98,7 +98,8 @@ class Tokens extends Model
'check_changes',
'check_changes_campaign',
'check_changes_ad_group',
'limit'
'limit',
'retargetinglists_loaded_at'
];
protected $casts = [
......@@ -107,6 +108,7 @@ class Tokens extends Model
'check_changes_campaign' => 'datetime',
'check_changes_ad_group' => 'datetime',
'check_changes_ad_extension' => 'datetime',
'retargetinglists_loaded_at' => 'datetime',
];
public function getCheckChangesAtAttribute()
......@@ -317,6 +319,11 @@ class Tokens extends Model
return $this->goalRetargetinglists()->forNotExternal()->forNotReserveCreate();
}
public function goalRetargetinglistsForExternalNeedDeletedForNotReserveDelete()
{
return $this->goalRetargetinglists()->forExternal()->needDeleted()->forNotReserveDelete();
}
public function goalRetargetinglistsForExternalForNotReserveUpdateNeedUpdated()
{
return $this->goalRetargetinglists()->forExternal()->forNotReserveUpdate()->needUpdated();
......
......@@ -30,7 +30,7 @@ class DeleteAudienceTarget extends DirectRequest
public function slice($maxObjects): ?APIRequest
{
return $this->sliceByKey($maxObjects, ['SelectionCriteria', 'Ids']);;
return $this->sliceByKey($maxObjects, ['SelectionCriteria', 'Ids']);
}
public function handle($response)
......
<?php
namespace App\Service\Requests\Direct;
use App\Jobs\ProcessCallLimitedAPI;
use App\Models\Pivots\GoalRetargetinglist;
use App\Models\Retargetinglist;
use App\Service\Contract\APIRequest;
use App\Service\DirectResponseHelper;
use App\Service\Requests\DirectRequest;
use Illuminate\Support\Facades\Log;
class DeleteRetargetinglists extends DirectRequest
{
protected $max_count = 10000;
protected $timestamp;
public function call($params = null)
{
$this->requestPrepare($params);
$process = new ProcessCallLimitedAPI($this);
dispatch($process)->onQueue('limits');
}
public function getObjectsCount()
{
return count($this->getParams()['SelectionCriteria']['Ids']);
}
public function slice($maxObjects): ?APIRequest
{
return $this->sliceByKey($maxObjects, ['SelectionCriteria', 'Ids']);
}
public function handle($response)
{
if (!isset($response['result']['DeleteResults'])) {
return;
}
foreach (DirectResponseHelper::getExternalIdsChunkByResult($response['result']['DeleteResults']) as $external_ids) {
if ($this->getToken()->isMain()) {
Retargetinglist::whereIn('external_id', $external_ids)
->delete();
} else {
GoalRetargetinglist::whereIn('external_id', $external_ids)
->delete();
}
}
foreach ($response['result']['DeleteResults'] as $key => $delete_result) {
if (isset($delete_result['Id'])) {
continue;
}
$external_id = $this->getParams()['SelectionCriteria']['Ids'][$key];
if (isset($delete_result['Errors']) && count($delete_result['Errors'])) {
if ($this->getToken()->isMain()) {
$model = Retargetinglist::whereExternalId($external_id)->first();
} else {
$model = GoalRetargetinglist::whereExternalId($external_id)->first();
}
if ($model) {
$model->errors()->create([
'token_id' => $this->getToken()->getKey(),
'service' => $this->getService(),
'method' => $this->getMethod(),
'params' => $external_id,
'errors' => $delete_result['Errors'],
]);
}
} else {
Log::debug("DeleteRetargetingLists, empty Id, token_id {$this->getToken()->getKey()}");
Log::debug($delete_result);
Log::debug($external_id);
}
if ($this->getToken()->isMain()) {
Retargetinglist::whereExternalId($external_id)
->update([
'reserve_delete_at' => null,
]);
} else {
GoalRetargetinglist::whereExternalId($external_id)
->update([
'reserve_delete_at' => null,
]);
}
}
}
public function failed()
{
if ($this->getToken()->isMain()) {
Retargetinglist::whereIn('external_id', $this->getParams()['SelectionCriteria']['Ids'])
->update([
'reserve_delete_at' => null,
]);
} else {
GoalRetargetinglist::whereIn('external_id', $this->getParams()['SelectionCriteria']['Ids'])
->update([
'reserve_delete_at' => null,
]);
}
}
private function requestPrepare($params)
{
$this->setService('RetargetingLists');
$this->setMethod('delete');
$this->setParams([
'SelectionCriteria' => [
'Ids' => $params['ids'],
],
]);
}
}
......@@ -56,6 +56,9 @@ class GetRetargetinglists extends DirectRequest
'name' => $retargeting_list['Name'],
'description' => $retargeting_list['Description'],
'rules' => $retargeting_list['Rules'],
'updated_at' => Carbon::now(),
'deleted_at' => null,
];
$retargetinglist = Retargetinglist::updateOrCreate([
......@@ -74,6 +77,25 @@ class GetRetargetinglists extends DirectRequest
}
}
if (!isset($response['result']['LimitedBy'])) {
if ($this->getToken()->isMain()) {
$sql = "UPDATE retargetinglists r
INNER JOIN tokens t ON r.token_id = t.id
SET r.deleted_at = now()
WHERE r.updated_at <= t.retargetinglists_loaded_at
AND r.deleted_at is null
AND r.token_id = (" . $this->getToken()->getKey() . ")";
DB::update($sql);
$this->getToken()->update([
'retargetinglists_loaded_at' => Carbon::now()
]);
}
}
}
}
......
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateColumnTokensRetargetinglistsLoadedAt extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('tokens', function (Blueprint $table) {
$table->timestamp('retargetinglists_loaded_at')->nullable();
});
Schema::table('goal_retargetinglists', function (Blueprint $table) {
$table->timestamp('reserve_delete_at')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!