Commit 2e2195e1 by Vladislav

#20794 Сделать чтобы в целевых РК оставалась одна карточка

1 parent 99aac925
......@@ -109,12 +109,12 @@ protected function schedule(Schedule $schedule)
$schedule->command(VCardsLoad::class)->hourlyAt(25);
$schedule->command(VCardsAdd::class)->hourlyAt(35);
// $schedule->command(AdImagesAdd::class)->hourlyAt(35);
$schedule->command(AdImagesAdd::class)->hourlyAt(35);
$schedule->command(AdExtensionsAdd::class)->hourlyAt(35);
$schedule->command(SitelinksAdd::class)->hourlyAt(35);
$schedule->command(NegativeKeywordSharedSetsAdd::class)->hourlyAt(35);
$schedule->command(NegativeKeywordSharedSetsUpdate::class)->hourlyAt(35);
// $schedule->command(RetargetinglistsAdd::class)->hourlyAt(35);
$schedule->command(RetargetinglistsAdd::class)->hourlyAt(35);
$schedule->command(RetargetinglistsUpdate::class)->hourlyAt(35);
$schedule->command(AdGroupsDelete::class)->hourlyAt(30);
......@@ -130,7 +130,7 @@ protected function schedule(Schedule $schedule)
$schedule->command(KeywordsUpdate::class)->hourlyAt(40);
$schedule->command(AdvertisementsAdd::class)->hourlyAt(50);
// $schedule->command(AdvertisementsUpdate::class)->hourlyAt(50);
$schedule->command(AdvertisementsUpdate::class)->hourlyAt(50);
$schedule->command(AdvertisementsArchive::class)->hourlyAt(50);
$schedule->call(function () {
......
......@@ -22,7 +22,7 @@ class TokensController extends Controller
return Inertia::render('Tokens/Index', [
'filters' => Request::all('api', 'type', 'login'),
'types' => [Tokens::MAIN => 'Основной аккаунт', Tokens::GOAL => 'Целевой аккаунт'],
'tokens' => Tokens::filter(Request::only('api', 'type', 'login'))
'tokens' => Tokens::withCount('errors')->filter(Request::only('api', 'type', 'login'))
->paginate()
->withQueryString()
->through(function ($token) {
......@@ -32,6 +32,7 @@ class TokensController extends Controller
'type' => $token->type,
'api' => $token->api,
'limit' => $token->limit,
'errors_count' => $token->errors_count,
];
}),
]);
......@@ -39,6 +40,7 @@ class TokensController extends Controller
function edit(Tokens $token)
{
$token->loadCount('errors');
$mainToken = Tokens::where('type', Tokens::MAIN)->first();
return Inertia::render('Tokens/Edit', [
'token' => [
......@@ -48,6 +50,7 @@ class TokensController extends Controller
'token' => $token->token,
'type' => $token->type,
'main' => $token->isMain(),
'errors_count' => $token->errors_count,
'campaigns' => (
$token->isMain()
? $token->campaignsForManaged
......@@ -87,6 +90,45 @@ class TokensController extends Controller
return Redirect::back()->with('success', 'Token updated.');
}
public function errors(Tokens $token)
{
return Inertia::render('Tokens/Errors', [
'filters' => Request::all('service', 'method'),
'services' => $token->errors()
->groupBy('service')
->pluck('service', 'service'),
'methods' => $token->errors()
->groupBy('method')
->pluck('method', 'method'),
'token' => [
'id' => $token->getKey(),
'login' => $token->login,
],
'rows' => $token->errors()
->filter(Request::only('service', 'method'))
->paginate()
->withQueryString()
->through(function ($yandexError) {
$data = $yandexError->only([
$yandexError->getKeyName(),
'service',
'method',
'params',
'errors',
'created_at',
]);
$data['created_at'] = $data['created_at']->format('d.m.y H:m:s');
return $data;
}),
]);
}
public function errorsDelete(Tokens $token)
{
$token->errors()->delete();
return Redirect::back()->with('success', 'Errors deleted.');
}
public function managedCampaign(Tokens $token, $campaign_id)
{
if (!$token->isMain()) {
......
......@@ -3,6 +3,7 @@
namespace App\Models\Pivots;
use App\Models\AdImage;
use App\Models\YandexError;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\SoftDeletes;
......@@ -72,4 +73,9 @@ class GoalAdImage extends Pivot
return $this->belongsTo(AdImage::class, 'ad_image_id');
}
public function errors()
{
return $this->morphMany(YandexError::class, 'cause');
}
}
......@@ -3,6 +3,7 @@
namespace App\Models\Pivots;
use App\Models\Keyword;
use App\Models\YandexError;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\SoftDeletes;
......@@ -210,4 +211,9 @@ class GoalKeyword extends Pivot
->get();
}
public function errors()
{
return $this->morphMany(YandexError::class, 'cause');
}
}
......@@ -5,6 +5,7 @@ namespace App\Models\Pivots;
use App\Models\AdExtension;
use App\Models\NegativeKeywordSharedSet;
use App\Models\VCard;
use App\Models\YandexError;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Database\Eloquent\SoftDeletes;
......@@ -125,4 +126,9 @@ class GoalVCard extends Pivot
return $this->hasMany(GoalAdvertisement::class, 'goal_v_card_id');
}
public function errors()
{
return $this->morphMany(YandexError::class, 'cause');
}
}
......@@ -151,6 +151,12 @@ class Tokens extends Model
return $this->type === $this::MAIN;
}
public function errors()
{
return $this->hasMany(YandexError::class, 'token_id')
->orderBy('created_at', 'DESC');
}
public function limits()
{
return $this->hasMany(Limits::class, 'token', 'id')
......
......@@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletes;
class YandexError extends Model
......@@ -35,4 +36,18 @@ class YandexError extends Model
return $this->morphTo('cause');
}
/**
* @param Builder $query
* @param array $filters
* @return Builder
*/
public function scopeFilter($query, array $filters)
{
return $query->when($filters['service'] ?? null, function ($query, $service) {
$query->where('service', $service);
})->when($filters['method'] ?? null, function ($query, $method) {
$query->where('method', $method);
});
}
}
......@@ -55,12 +55,33 @@ class AddAdImages extends DirectRequest
$goalAdImage = $this->goalAdImages->get($key);
$data = $this->getParams()['AdImages'][$key];
if (!isset($add_result['AdImageHash'])) {
if (isset($add_result['Errors']) && count($add_result['Errors'])) {
$goalAdImage->errors()->create([
'token_id' => $this->getToken()->getKey(),
'service' => $this->getService(),
'method' => $this->getMethod(),
'params' => $data,
'errors' => $add_result['Errors'],
]);
GoalAdImage::where('id', $goalAdImage->getKey())
->update([
'reserve_create_at' => null,
]);
continue;
}
Log::debug("AddAdImage, empty AdImageHash, token_id {$this->getToken()->getKey()}");
Log::debug($add_result);
Log::debug($this->getParams()['AdImages'][$key]['Name']);
Log::debug($data['Name']);
$goalAdImage->where('id', $goalAdImage->getKey())
GoalAdImage::where('id', $goalAdImage->getKey())
->update([
'reserve_create_at' => null,
]);
......
......@@ -40,6 +40,8 @@ class DeleteVCards extends DirectRequest
foreach ($response['result']['DeleteResults'] as $key => $delete_result) {
$external_id = $this->getParams()['SelectionCriteria']['Ids'][$key];
if (!isset($delete_result['Id'])) {
if (
......@@ -48,8 +50,6 @@ class DeleteVCards extends DirectRequest
$delete_result['Errors'][0]['Code'] == 8800
) {
if ($external_id = $this->getParams()['SelectionCriteria']['Ids'][$key]){
if ($this->getToken()->isMain()) {
VCard::whereExternalId($external_id)
->delete();
......@@ -60,12 +60,26 @@ class DeleteVCards extends DirectRequest
continue;
} elseif (isset($delete_result['Errors']) && count($delete_result['Errors'])) {
$goalVCard = GoalVCard::whereExternalId($external_id)->first();
if ($goalVCard) {
$goalVCard->errors()->create([
'token_id' => $this->getToken()->getKey(),
'service' => $this->getService(),
'method' => $this->getMethod(),
'params' => $external_id,
'errors' => $delete_result['Errors'],
]);
$goalVCard->update([
'reserve_update_at' => null,
]);
continue;
}
}
Log::debug("DeleteVCards, empty Id, token_id {$this->getToken()->getKey()}");
Log::debug($delete_result);
$external_id = $this->getParams()['SelectionCriteria']['Ids'][$key];
Log::debug($external_id);
if ($this->getToken()->isMain()) {
......
......@@ -58,7 +58,7 @@
<inertia-link class="hover:text-indigo-500 focus:text-indigo-500"
:href="route('token.campaign.variables', [token.id, city.id, dictionary_campaign.campaign_id])"
>
{{ dictionary_campaign.name }}
#{{dictionary_campaign.external_id}} {{ dictionary_campaign.name }}
</inertia-link>
</span>
</td>
......
......@@ -8,14 +8,14 @@
<div class="bg-white rounded-md shadow overflow-hidden max-w-3xl">
<form @submit.prevent="tokenUpdate">
<div class="p-8 -mr-6 -mb-8 flex flex-wrap">
<text-input v-model="form.login" :error="form.errors.login" :readonly="true" class="pr-6 pb-8 w-full lg:w-1/2"
<text-input v-model="form.login" :error="form.errors.login" :disabled="true" class="pr-6 pb-8 w-full lg:w-1/2"
label="Login"/>
<text-input v-model="form.token" :error="form.errors.token" :readonly="true" class="pr-6 pb-8 w-full lg:w-1/2"
<text-input v-model="form.token" :error="form.errors.token" :disabled="true" class="pr-6 pb-8 w-full lg:w-1/2"
label="Token"/>
<text-input v-model="form.api" :error="form.errors.api" :readonly="true" class="pr-6 pb-8 w-full lg:w-1/2"
<text-input v-model="form.api" :error="form.errors.api" :disabled="true" class="pr-6 pb-8 w-full lg:w-1/2"
label="API"/>
<select-input v-model="form.type" :error="form.errors.type"
:readonly="form.type"
:disabled="form.type"
class="pr-6 pb-8 w-full lg:w-1/2"
label="Type">
<option :value="null"/>
......@@ -30,13 +30,22 @@
>
Delete Token
</button>
<loading-button :loading="form.processing" v-if="!this.token.type" class="btn-indigo ml-auto" type="submit">
<loading-button :loading="form.processing" v-if="!token.type" class="btn-indigo ml-auto" type="submit">
Update Token
</loading-button>
</div>
</form>
</div>
<inertia-link class="text-red-600 hover:underline mt-10"
tabindex="-1"
type="button"
v-if="token.errors_count"
:href="route('token.errors', token.id)"
>
Errors {{token.errors_count}}
</inertia-link>
<campaigns-settings v-if="campaigns.length && token.main"
:campaigns="campaigns"
:token="token"
......
<template>
<div>
<h1 class="mb-8 font-bold text-3xl">
<inertia-link class="text-indigo-400 hover:text-indigo-600" :href="route('tokens')">Tokens</inertia-link>
<span class="text-indigo-400 font-medium">/</span>
<inertia-link class="text-indigo-400 hover:text-indigo-600" :href="route('token.edit', token.id)">{{token.login}}</inertia-link>
<span class="text-indigo-400 font-medium">/</span>
Errors
</h1>
<div class="mb-6 flex justify-between items-center">
<search-filter class="w-full max-w-md mr-4" @reset="reset">
<label class="block text-gray-700">Service:</label>
<select v-model="form.service" class="mt-1 w-full form-select">
<option hidden :value="null" />
<option v-for="service in services" :value="service">{{ service }}</option>
</select>
<label class="block text-gray-700 mt-2">Method:</label>
<select v-model="form.method" class="mt-1 w-full form-select">
<option hidden :value="null" />
<option v-for="method in methods" :value="method">{{ method }}</option>
</select>
</search-filter>
<button class="text-red-600 hover:underline mb-4"
tabindex="-1"
type="button"
@click="errorsDestroy"
>
Delete errors
</button>
</div>
<div class="bg-white rounded-md shadow overflow-x-auto">
<table class="w-full whitespace-nowrap">
<tr class="text-left font-bold">
<th class="px-6 pt-6 pb-4">Create</th>
<th class="px-6 pt-6 pb-4">Service</th>
<th class="px-6 pt-6 pb-4">Method</th>
<th class="px-6 pt-6 pb-4">Errors</th>
<th class="px-6 pt-6 pb-4">Params</th>
</tr>
<tr v-for="error in rows.data" :key="error.id" class="">
<td class="border-t px-6 pt-6 pb-4">
{{ error.created_at }}
</td>
<td class="border-t px-6 pt-6 pb-4">
{{ error.service }}
</td>
<td class="border-t px-6 pt-6 pb-4">
{{ error.method }}
</td>
<td class="border-t px-6 pt-6 pb-4">
<pre v-html="objectFormatting(error.errors)"/>
</td>
<td class="border-t px-6 pt-6 pb-4">
<details>
<summary>Params</summary>
<pre v-html="objectFormatting(error.params)"/>
</details>
</td>
</tr>
<tr v-if="rows.data.length === 0">
<td class="border-t px-6 py-4" colspan="6">No errors found.</td>
</tr>
</table>
</div>
<pagination class="mt-6" :links="rows.links" />
</div>
</template>
<script>
import Icon from '@/Shared/Icon'
import pickBy from 'lodash/pickBy'
import Layout from '@/Shared/Layout'
import throttle from 'lodash/throttle'
import mapValues from 'lodash/mapValues'
import Pagination from '@/Shared/Pagination'
import SearchFilter from '@/Shared/SearchFilter'
export default {
metaInfo: { title: 'Token' },
components: {
Icon,
Pagination,
SearchFilter,
},
layout: Layout,
props: {
token: Object,
rows: Object,
filters: Object,
services: Object,
methods: Object,
},
data() {
return {
form: {
service: this.filters.service,
method: this.filters.method,
},
}
},
watch: {
form: {
handler: throttle(function() {
this.$inertia.get(this.route('token.errors', this.token.id), pickBy(this.form))
}, 150),
deep: true,
},
},
methods: {
objectFormatting(object) {
return JSON.stringify(object, null, '&nbsp;').replace(/\n/gi,'<br/>')
},
errorsDestroy() {
if (confirm('Are you sure you want to delete this errors?')) {
this.$inertia.delete(this.route('token.errors.destroy', this.token.id))
}
},
reset() {
this.form = mapValues(this.form, () => null)
},
},
}
</script>
......@@ -23,6 +23,7 @@
<th class="px-6 pt-6 pb-4">АПИ</th>
<th class="px-6 pt-6 pb-4">Баллы</th>
<th class="px-6 pt-6 pb-4" colspan="2">Тип</th>
<th class="px-6 pt-6 pb-4">Ошибки</th>
</tr>
<tr v-for="token in tokens.data" :key="token.id" class="hover:bg-gray-100 focus-within:bg-gray-100">
<td class="border-t">
......@@ -50,9 +51,14 @@
<icon name="cheveron-right" class="block w-6 h-6 fill-gray-400" />
</inertia-link>
</td>
<td class="border-t">
<inertia-link class="px-6 py-4 flex items-center" :href="route('token.errors', token.id)" tabindex="-1">
{{ token.errors_count }} <icon name="cheveron-right" class="block w-6 h-6 fill-gray-400" />
</inertia-link>
</td>
</tr>
<tr v-if="tokens.data.length === 0">
<td class="border-t px-6 py-4" colspan="4">No tokens found.</td>
<td class="border-t px-6 py-4" colspan="5">No tokens found.</td>
</tr>
</table>
</div>
......
......@@ -163,6 +163,10 @@ Route::group(['middleware' => 'auth'], function () {
Route::get('token/edit/{token}', [TokensController::class, 'edit'])
->name('token.edit');
Route::get('token/errors/{token}', [TokensController::class, 'errors'])
->name('token.errors');
Route::delete('token/errors/delete/{token}/', [TokensController::class, 'errorsDelete'])
->name('token.errors.destroy');
Route::post('token/edit/{token}', [TokensController::class, 'update'])
->name('token.update');
Route::delete('token/delete/{token}', [TokensController::class, 'destroy'])
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!