From 5b2162fb28c793150b867abcf35c066ee4aba599 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 May 2026 17:24:41 +0000 Subject: [PATCH] fix: standardize billing order status values and apply full-day expiry grace rule - home_handling_functions.php: display expiration as Y-m-d only (not Y-m-d H:i); apply full-day grace by comparing date-only (midnight) in PHP so a server expiring on today's date remains Active the entire day - cron-shop.php Step B & C: change server_expiration_date comparisons from < DATE_SUB(NOW(), ...) to DATE(server_expiration_date) < DATE_SUB(CURDATE(), ...) ensuring the full expiration day is honoured - user_games/check_expire.php: change all three expiration queries from <= time() to < strtotime(date('Y-m-d')) (today-midnight) for full-day grace - billing/test_integration.php: replace status='paid' (old order status) with status IN ('Active','paid') for backward compat during migration - user_games/billing_integration.php: clarify comment that billing_invoices.status uses the payment lifecycle ('paid'/'unpaid'/'due'), separate from billing_orders.status - Add modules/billing/sql/normalize_billing_order_status.sql migration script to convert installed->Active, paid->Active, suspended->Expired in existing rows - Update CHANGELOG.md Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/439845e0-926e-4b49-9cd0-810457b73c12 Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com> --- CHANGELOG.md | 7 +++- modules/billing/cron-shop.php | 4 +- .../sql/normalize_billing_order_status.sql | 37 +++++++++++++++++++ modules/billing/test_integration.php | 10 +++-- .../gamemanager/home_handling_functions.php | 21 +++++++---- modules/user_games/billing_integration.php | 10 +++-- modules/user_games/check_expire.php | 10 +++-- 7 files changed, 79 insertions(+), 20 deletions(-) create mode 100644 modules/billing/sql/normalize_billing_order_status.sql diff --git a/CHANGELOG.md b/CHANGELOG.md index 28e873c9..dac065d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog -## 2026-05-03 (latest) +## 2026-05-05 +- **Billing order status standardization:** Canonical `billing_orders.status` values are now `Active`, `Invoiced`, and `Expired` only. All old writes of `installed`, `paid` (as order status), and `suspended` have been replaced. A SQL migration script `modules/billing/sql/normalize_billing_order_status.sql` converts any existing legacy rows. Backward-compatibility read paths (e.g. renewable-status checks in `my_account.php`) are preserved until the migration runs. +- **Expiration display date-only:** The billing expiration shown on the game server monitor (`server_monitor.php`) now displays as `YYYY-MM-DD` only instead of `YYYY-MM-DD HH:MM`. +- **Full-day expiration grace rule:** A server whose `end_date` falls on today is treated as active for the entire calendar day. Expiration is only processed starting the next calendar day. This rule is applied consistently in: billing cron (`cron-shop.php` Steps B and C), the server monitor expiration helper (`home_handling_functions.php::get_server_billing_expiration_html`), and the OGP user/group assignment expiration processor (`user_games/check_expire.php`). All comparisons now use `DATE(end_date) < CURDATE()` (SQL) or `< strtotime(date('Y-m-d'))` (PHP) — never `<= NOW()` or `<= time()`. + + - **GSP 1.0 baseline:** Reset all bundled/core module versions to `1.0`. DB schema versions (`$db_version`) are unchanged. - **FAQ module refresh:** Restored online RSS update code from upstream (opengamepanel.org), fixed `$local = false` initialization bug, switched local cache to `ogpfaq.rss`, added PHP 8.3-compatible `(array)` casts, restored upstream credits footer, and opened `navigation.xml` access to `user,admin,subuser`. - **Config XML editor improvements:** Added schema validation before save (both structured editor and raw XML path); invalid XML is rejected with line-level error messages instead of being written to disk. Added auto-restore from backup on validation failure. Fields are now displayed in schema-defined order with required/optional badges. Added a raw XML editing panel with validation warning. Unknown/custom XML fields are preserved when only specific nodes are modified. diff --git a/modules/billing/cron-shop.php b/modules/billing/cron-shop.php index 72d82707..9884944d 100644 --- a/modules/billing/cron-shop.php +++ b/modules/billing/cron-shop.php @@ -215,7 +215,7 @@ $past_due = $db->resultQuery(" WHERE sh.billing_enabled = 1 AND sh.billing_status = 'Invoiced' AND sh.server_expiration_date IS NOT NULL - AND sh.server_expiration_date < DATE_SUB(NOW(), INTERVAL {$grace_days} DAY) + AND DATE(sh.server_expiration_date) < DATE_SUB(CURDATE(), INTERVAL {$grace_days} DAY) AND ( sh.last_invoice_id IS NULL OR EXISTS ( @@ -284,7 +284,7 @@ $to_delete = $db->resultQuery(" WHERE sh.billing_enabled = 1 AND sh.billing_status = 'Expired' AND sh.server_expiration_date IS NOT NULL - AND sh.server_expiration_date < DATE_SUB(NOW(), INTERVAL {$delete_after_days} DAY) + AND DATE(sh.server_expiration_date) < DATE_SUB(CURDATE(), INTERVAL {$delete_after_days} DAY) ORDER BY sh.home_id ASC "); diff --git a/modules/billing/sql/normalize_billing_order_status.sql b/modules/billing/sql/normalize_billing_order_status.sql new file mode 100644 index 00000000..4634b2f5 --- /dev/null +++ b/modules/billing/sql/normalize_billing_order_status.sql @@ -0,0 +1,37 @@ +-- normalize_billing_order_status.sql +-- ============================================================ +-- Migrate legacy billing_orders.status values to the canonical +-- three-value lifecycle used by GSP billing: +-- +-- Active – server is provisioned and current +-- Invoiced – renewal invoice generated; payment due +-- Expired – invoice unpaid past due date; server pending deletion +-- +-- Old values and their mappings: +-- installed -> Active (was written by old provisioner) +-- paid -> Active (was written after PayPal capture, before provisioning) +-- suspended -> Expired (was written by old cron when overdue) +-- +-- Run this ONCE against the panel database after deploying the updated +-- cron-shop.php and application code. It is safe to re-run (idempotent). +-- ============================================================ + +-- Map old 'installed' to 'Active' +UPDATE `gsp_billing_orders` +SET `status` = 'Active' +WHERE `status` = 'installed'; + +-- Map old 'paid' to 'Active' +-- (Orders that were paid but not yet provisioned should be provisioned +-- via home.php?m=billing&p=provision_servers after this migration.) +UPDATE `gsp_billing_orders` +SET `status` = 'Active' +WHERE `status` = 'paid'; + +-- Map old 'suspended' to 'Expired' +UPDATE `gsp_billing_orders` +SET `status` = 'Expired' +WHERE `status` = 'suspended'; + +-- Optional: verify counts after migration +-- SELECT status, COUNT(*) AS count FROM gsp_billing_orders GROUP BY status ORDER BY count DESC; diff --git a/modules/billing/test_integration.php b/modules/billing/test_integration.php index 5617c6ac..e1463427 100644 --- a/modules/billing/test_integration.php +++ b/modules/billing/test_integration.php @@ -98,12 +98,14 @@ function exec_ogp_module() } echo ""; - // Test 7: Sample paid order check - echo "