Jump to content

ClientEdit hook code to cycle through unpaid invoices to apply credit and cancel invoice


TBroMEM

Recommended Posts

I am hoping to aid the finance/billing team with writing off bad debt using a hook.

The manual process is as follows (high level):

1. add credit
2. apply credit to invoice
3. cancel invoice

ultimately term/inactivate client product/service.

I am somewhat novice, but curious how things stand with the following code. I hope to simplify step 2 and 3 via hook. Am I approaching the logic properly? Any other guidance would be appreciated. As I understand it, when a credit is added to a client account, it will update the Credit value for the related client.

<?php
 
if (!defined("WHMCS"))
    die("This file cannot be accessed directly");

add_hook("ClientEdit", 1, "hook_applycredit_thencancel");

function hook_applycredit_thencancel($vars)
{
	try {
		//vars from hook
		$clientid = $vars['userid'];
		$adminuser = 'sys.admin'; 

		logActivity('Checking Client unpaid invoices ' . $clientid . ' from hook_applycredit_thencancel...');

		// Get Invoices
		// Define parameters
		$command = 'GetInvoices';
		$values = array(
			'userid' => $clientid,
			'status' => 'Unpaid',
		);

		// Call the localAPI function
		$invoiceData = localAPI($command, $values, $adminuser);
		if ($invoiceData['result'] == 'success') {
			foreach ($invoiceData['invoices']['invoice'][0] as $invoice) {
				$invoiceId = $invoice->'id';
				$creditamt = $invoice->'credit';
				
				//Apply Credit
				$command = 'ApplyCredit';
				$values = array(
				'invoiceid' => $invoiceId,
				'amount' => $creditamt,
				'noemail' => '1',
				);
				
				$addCredit = localAPI($command, $values, $adminuser);
				if ($addCredit['result'] == 'success') {
					logActivity('Credit amount ' . $creditamt . 'has been applied to Invoice ' . $invoiceId . ' by hook_applycredit_thencancel...');
				}
				
				else {
				logActivity('Credit amount ' . $creditamt . ' FAILED to apply to Invoice ' . $invoiceId . ' by hook_applycredit_thencancel...');
				}
				
				//Cancel Invoice
				$command = 'UpdateInvoice';
				$values = array(
				'invoiceid' => $invoiceId,
				'status' => 'Cancelled'
				);
				
				$cancelInvoice = localAPI($command, $values, $adminuser);
				if ($canceInvoice['result'] == 'success') {
					logActivity('Invoice ' . $invoiceId . ' has been cancelled by hook_applycredit_thencancel...');
				}
				
				else {
				logActivity('Invoice ' . $invoiceId . ' FAILED cancel by hook_applycredit_thencancel...');
				}
			}
		}
		
		else }
		logActivity('Credit application for ' . $clientid . ' FAILED by hook_applycredit_thencancel...' . $invoiceData['message']);
		}
			
	} catch (\Exception $e) {
		logActivity("Credit application failed: {$e->getMessage()}");	
	}
} 

 

Link to comment
Share on other sites

There are few issues in the hook logic for applying credit and cancelling invoices:

  1. Incorrect array index usage in the loop
     

    You had:
    foreach ($invoiceData['invoices']['invoice'][0] as $invoice)
    This loops only over the first invoice.
    Use:
    foreach ($invoiceData['invoices']['invoice'] as $invoice)

     

  2. Incorrect object access
     

    You used:
    $invoiceId = $invoice->'id';
    $creditamt = $invoice->'credit';
    But $invoice is an associative array, not an object.
    Use:
    $invoiceId = $invoice['id'];
    $creditamt = $invoice['credit'];

     

  3. Incorrect variable name
    You had:
    if ($canceInvoice['result'] == 'success')
    Correct to:
    if ($cancelInvoice['result'] == 'success')

     

  4. Syntax error in else
    You had:
    else }
    Correct to:
    else {

     

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