Jump to content

WHMCS stop renewal invoice creation if unpaid exists for a service.


ambaha

Recommended Posts

How to prevent WHMCS from generating duplicate invoices for the same service renewal?

We are currently facing an issue in WHMCS (version 8.x, PHP 😎 where multiple invoices are generated for the same service during the renewal process. Here’s the scenario:

  1. A renewal invoice is created but remains unpaid.
  2. When the client clicks the “Renew” button again, WHMCS generates a new invoice and cancel Previous invoice, even though an unpaid invoice already exists for the same service.

This behavior clutter in the system. My goal is to prevent WHMCS from generating a new invoice if there is already an unpaid invoice linked to the same service or product.

I use this hook but problem not solved.

 

<?php

use WHMCS\Database\Capsule;

add_hook('InvoiceCreation', 1, function($vars) {
    $relid = $vars['relatedid'];
    if (empty($relid)) {
        return; 
    }
    $unpaidInvoice = Capsule::table('tblinvoices')
        ->join('tblinvoiceitems', 'tblinvoices.id', '=', 'tblinvoiceitems.invoiceid')
        ->where('tblinvoices.status', 'Unpaid') 
        ->where('tblinvoiceitems.relid', $relid)
        ->exists(); 
    if ($unpaidInvoice) {
        throw new \Exception('An unpaid invoice already exists for this service. Please pay it first.');
    }
});


 

 

Edited by ambaha
Link to comment
Share on other sites

Hello

Hope this code fixes the issue

 

<?php
/**
 * prevent_duplicate_renewal.php
 *
 * Prevent WHMCS from generating a new renewal invoice when
 * an unpaid one already exists for the same service.
 *
 * Drop this file into includes/hooks/ and WHMCS will pick it up.
 */

use WHMCS\Database\Capsule;

add_hook('InvoiceCreation', 1, function($vars) {
    // Only act on client-area triggered renewals
    if ($vars['source'] !== 'clientarea') {
        return;
    }

    $invoiceId = $vars['invoiceid'];

    // Fetch all hosting/service items on the newly created invoice
    $items = Capsule::table('tblinvoiceitems')
        ->where('invoiceid', $invoiceId)
        ->where('type', 'Hosting') // for addons/domains you may need 'Addon' or 'Domain'
        ->get();

    foreach ($items as $item) {
        $serviceId = $item->relid;
        if (!$serviceId) {
            continue;
        }

        // Is there another unpaid invoice for this exact service?
        $duplicateExists = Capsule::table('tblinvoices')
            ->join('tblinvoiceitems', 'tblinvoiceitems.invoiceid', '=', 'tblinvoices.id')
            ->where('tblinvoices.status', 'Unpaid')
            ->where('tblinvoiceitems.relid', $serviceId)
            ->where('tblinvoiceitems.invoiceid', '!=', $invoiceId)
            ->exists();

        if ($duplicateExists) {
            // Cancel the just-created invoice
            Capsule::table('tblinvoices')
                ->where('id', $invoiceId)
                ->update(['status' => 'Cancelled']);

            // Log for your reference
            logActivity(
                "Prevented duplicate renewal: cancelled invoice #{$invoiceId} for service ID {$serviceId}"
            );

            // No need to check further line items
            break;
        }
    }
});
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use & Guidelines and understand your posts will initially be pre-moderated