feat: update FTP ignore list and add repository guidelines documentation

This commit is contained in:
2026-02-23 13:57:32 +01:00
parent 9fb7b20828
commit 63857639ff
4 changed files with 61 additions and 50 deletions

6
.vscode/ftp-kr.json vendored
View File

@@ -12,6 +12,10 @@
"ignoreRemoteModification": true,
"ignore": [
".git",
"/.vscode"
"/.vscode",
"/.serena",
"/.claude",
"CLAUDE.md",
"AGENTS.md"
]
}

46
AGENTS.md Normal file
View File

@@ -0,0 +1,46 @@
# Repository Guidelines
## Struktura projektu i organizacja modułów
To repozytorium zawiera aplikację PHP w lekkiej architekturze MVC do zarządzania reklamami.
- Punkty wejścia: `index.php`, `ajax.php`, `api.php`, `cron.php`, `install.php`
- Kontrolery: `autoload/controls/class.*.php` (`\controls`)
- Fabryki (dostęp do danych): `autoload/factory/class.*.php` (`\factory`)
- Warstwa widoku: `autoload/view/class.*.php` (`\view`)
- Integracje zewnętrzne (Google Ads, OpenAI, Claude, Meta): `autoload/services/`
- Szablony: `templates/<moduł>/`
- Style: `layout/style.scss` -> `layout/style.css`
- Zmiany schematu bazy: `migrations/*.sql` (numerowane, przyrostowe)
- Dokumentacja techniczna i notatki: `docs/`
## Komendy build/test/development
- `php -S localhost:8000` - uruchamia lokalny serwer PHP z katalogu repozytorium.
- `php install.php` - wykonuje oczekujące migracje bazy danych.
- `php install.php --with_demo` - wykonuje migracje i ładuje dane demonstracyjne.
- `php install.php --force` - wymusza ponowne uruchomienie wszystkich migracji (ostrożnie).
- `php -l ścieżka\do\pliku.php` - sprawdza składnię pliku PHP.
Projekt nie wymaga standardowo pipeline `Node`/`Composer` do uruchomienia. SCSS kompiluje się zwykle przez VS Code Live Sass Compiler podczas edycji `layout/style.scss`.
## Styl kodu i konwencje nazewnictwa
- Zachowuj obecny wzorzec nazw plików/klas: `class.Moduł.php`, namespace małymi literami (np. `\controls`).
- Nazwy klas: `PascalCase`; metody, zmienne i kolumny DB: `snake_case`.
- Utrzymuj styl formatowania zgodny z edytowanym plikiem (historyczny styl nawiasów i wcięć).
- Preferuj małe, statyczne metody w kontrolerach/fabrykach oraz jawne tablice danych do szablonów/JSON.
## Wytyczne testowania
W repozytorium nie ma obecnie skonfigurowanego automatycznego zestawu testów (`phpunit` nie jest skonfigurowany).
- Wykonuj ręczne testy smoke dla zmienionych tras, np. `/campaigns/main_view`, `/users/settings`.
- Dla zmian w API/AJAX sprawdzaj odpowiedzi JSON zarówno dla sukcesu, jak i błędów.
- Przed PR uruchamiaj `php -l` dla każdego modyfikowanego pliku PHP.
## Zasady commitów i pull requestów
- Stosuj krótkie, rzeczowe komunikaty commitów. Historia preferuje prefiksy Conventional Commits, szczególnie `feat:` (oraz `fix:`, `refactor:`, `chore:`).
- Jeden commit powinien obejmować jeden spójny zakres zmian (schema, backend, UI).
- PR powinien zawierać: cel zmian, listę zmienionych modułów/ścieżek, wpływ na migracje, kroki testowe i zrzuty ekranu dla zmian UI.
- Dodawaj powiązane ID zadania/issue, jeśli istnieją.
## Bezpieczeństwo i konfiguracja
- Traktuj `config.php` i klucze API jako dane wrażliwe; nie commituj prawdziwych sekretów.
- Tymczasowe pliki debugowe z `tmp/` nie powinny trafiać do commitów produkcyjnych, chyba że jest to celowe.

View File

@@ -2201,6 +2201,16 @@ class Cron
$campaigns_all_time = [];
}
// Brak danych kampanii dla dnia: nie zapisujemy zerowego snapshotu historii.
if ( empty( $campaigns_30 ) )
{
return [
'processed_records' => 0,
'ad_groups_synced' => 0,
'errors' => []
];
}
$all_time_map = [];
$all_time_totals = [ 'cost' => 0.0, 'conversion_value' => 0.0 ];
foreach ( $campaigns_all_time as $cat )

View File

@@ -2552,55 +2552,6 @@ class GoogleAdsApi
unset( $c['cost_total'] );
}
// Fallback: gdy raport metryk zwraca pusty wynik dla danego dnia/okna,
// pobieramy aktywne kampanie, aby zachowac budzet/strategie zamiast pustych rekordow.
if ( empty( $campaigns ) )
{
$meta_gaql = "SELECT "
. "campaign.id, "
. "campaign.name, "
. "campaign.advertising_channel_type, "
. "campaign.bidding_strategy_type, "
. "campaign.target_roas.target_roas, "
. "campaign_budget.amount_micros "
. "FROM campaign "
. "WHERE campaign.status = 'ENABLED'";
$meta_rows = $this -> search_stream( $customer_id, $meta_gaql );
if ( is_array( $meta_rows ) )
{
foreach ( $meta_rows as $row )
{
$cid = $row['campaign']['id'] ?? null;
if ( !$cid )
{
continue;
}
if ( isset( $campaigns[ $cid ] ) )
{
continue;
}
$campaigns[ $cid ] = [
'campaign_id' => $cid,
'campaign_name' => $row['campaign']['name'] ?? '',
'advertising_channel_type' => (string) ( $row['campaign']['advertisingChannelType'] ?? '' ),
'bidding_strategy' => $row['campaign']['biddingStrategyType'] ?? 'UNKNOWN',
'target_roas' => isset( $row['campaign']['targetRoas']['targetRoas'] )
? (float) $row['campaign']['targetRoas']['targetRoas']
: 0,
'budget' => isset( $row['campaignBudget']['amountMicros'] )
? (float) $row['campaignBudget']['amountMicros'] / 1000000
: 0,
'money_spent' => 0,
'conversion_value' => 0,
'roas_30_days' => 0,
];
}
}
}
return array_values( $campaigns );
}