There's just a few issues with this:
If an invoice has 4 lines: 2 products and 2 Late Fees (if that's even possible).
If one of the products is terminated, while the other isn't, there's no way for me to know which late fee to remove.
Anyways, you can use this:
<?php
use WHMCS\Database\Capsule;
add_hook('PreModuleTerminate', 1, function($vars) {
$invoices = Capsule::table('tblinvoiceitems')
->where('relid', $vars['params']['serviceid'])
->where('type', '!=', 'GroupDiscount')
->get();
logActivity('Auto Cancel Invoice: Starting...');
foreach($invoices as $key){
$invoiceIDs = Capsule::table('tblinvoices')
->where('id', $key->invoiceid)
->where('status', 'Unpaid')
->value('id');
$invoiceLine = Capsule::table('tblinvoiceitems')
->where('invoiceid', $invoiceIDs)
->where('relid', $vars['params']['serviceid'])
->value('id');
$invoiceLines = Capsule::table('tblinvoiceitems')
->where('invoiceid', $invoiceIDs)
->get();
$description = Capsule::table('tblinvoiceitems')
->where('relid', $vars['params']['serviceid'])
->where('invoiceid', $invoiceIDs)
->value('description');
$discountLine = Capsule::table('tblinvoiceitems')
->where('invoiceid', $invoiceIDs)
->where('type', 'GroupDiscount')
->where('description', 'like', '% '.$description.'%')
->value('id');
if($invoiceIDs){
logActivity('Auto Cancel Invoice: Invoice ' . $invoiceIDs . ' has had a line removed. This invoice previously had ' . count($invoiceLines) . ' lines.');
if(count($invoiceLines) > 1){
$command = 'UpdateInvoice';
$postData = array(
'invoiceid' => $invoiceIDs,
'deletelineids' => array($invoiceLine),
);
$results = localAPI($command, $postData);
}elseif(count($invoiceLines) == 1){
logActivity('Auto Cancel Invoice: Invoice ' . $invoiceIDs . ' has been cancelled because the product was terminated.');
$command = 'UpdateInvoice';
$postData = array(
'invoiceid' => $invoiceIDs,
'status' => 'Cancelled',
);
$results = localAPI($command, $postData);
}
if(count($invoiceLines) <= 2 && Capsule::table('tblinvoiceitems')->where('invoiceid', $invoiceIDs)->where('type', 'LateFee')->get()){
logActivity('Auto Cancel Invoice: Invoice ' . $invoiceIDs . ' has been cancelled because the only line was a Late Fee.');
$command = 'UpdateInvoice';
$postData = array(
'invoiceid' => $invoiceIDs,
'status' => 'Cancelled',
);
$results = localAPI($command, $postData);
}
if($discountLine){
logActivity('Auto Cancel Invoice: Invoice ' . $invoiceIDs . ' had a Group Discount. This has been removed.');
$command = 'UpdateInvoice';
$postData = array(
'invoiceid' => $invoiceIDs,
'deletelineids' => array($discountLine),
);
$results = localAPI($command, $postData);
}
}
}
});
If there's 2 or less lines, and one of them is a Late Fee, it will cancel the invoice.
When using the PreModuleTerminate hook, I can't do it for less than 2 lines because the LateFee doesn't have a relid. This should work just fine though.