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>
This commit is contained in:
parent
5f3013b4a4
commit
5b2162fb28
7 changed files with 79 additions and 20 deletions
|
|
@ -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
|
||||
");
|
||||
|
||||
|
|
|
|||
37
modules/billing/sql/normalize_billing_order_status.sql
Normal file
37
modules/billing/sql/normalize_billing_order_status.sql
Normal file
|
|
@ -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;
|
||||
|
|
@ -98,12 +98,14 @@ function exec_ogp_module()
|
|||
}
|
||||
echo "</ul>";
|
||||
|
||||
// Test 7: Sample paid order check
|
||||
echo "<h3>7. Paid Orders Ready for Provisioning</h3>";
|
||||
// Test 7: Active orders ready for provisioning
|
||||
// Canonical status is 'Active'. Legacy rows may still use 'paid' until
|
||||
// normalize_billing_order_status.sql has been run — include them here.
|
||||
echo "<h3>7. Active Orders Ready for Provisioning</h3>";
|
||||
if ($isAdmin) {
|
||||
$paid_orders = $db->resultQuery("SELECT COUNT(*) as count FROM OGP_DB_PREFIXbilling_orders WHERE status='paid'");
|
||||
$paid_orders = $db->resultQuery("SELECT COUNT(*) as count FROM OGP_DB_PREFIXbilling_orders WHERE status IN ('Active','paid')");
|
||||
} else {
|
||||
$paid_orders = $db->resultQuery("SELECT COUNT(*) as count FROM OGP_DB_PREFIXbilling_orders WHERE status='paid' AND user_id=".$db->realEscapeSingle($user_id));
|
||||
$paid_orders = $db->resultQuery("SELECT COUNT(*) as count FROM OGP_DB_PREFIXbilling_orders WHERE status IN ('Active','paid') AND user_id=".$db->realEscapeSingle($user_id));
|
||||
}
|
||||
|
||||
if (!empty($paid_orders)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue