twhiting9275 Posted January 9, 2017 Share Posted January 9, 2017 (edited) As you may have noticed, the open invoices widget was removed from whmcs in 7.1. While you can find and copy the old widget (hint, it's in your backup, under whmcs/addons/widgets/), the best approach is to write this in a forward thinking way. Rather than use sql_query functions that may not work with php 7.x , and probably won't work with future versions of WHMCS, this widget was written to mimic the functionality of the old while utilizing Capsule, which (hopefully) won't be going away any time soon. Copy and paste the following into a php file in whmcs/modules/widgets/ . I used openinvoices.php , but you can use whatever you like. If you run into problems, let me know, but this is pretty straightforward stuff. <?php //open invoices widget , rewritten for 7.1 //courtesy of https://www.whmcs.guru //version 1.0.1 use Illuminate\Database\Capsule\Manager as Capsule; add_hook('AdminHomeWidgets', 1, function() { return new InvoiceWidget(); }); /** * Updated invoices widget */ class InvoiceWidget extends \WHMCS\Module\AbstractWidget { protected $title = 'Open Invoices'; protected $description = 'An overview of Open Invoices.'; protected $weight = 150; protected $columns = 1; protected $cache = false; protected $cacheExpiry = 120; protected $requiredPermission = 'View Income Totals'; public function getData() { return array(); } public function generateOutput($data) { foreach (Capsule::table('tblinvoices') ->WHERE ('status', '=' , 'Unpaid')->get() as $invoice) { $invowner = $invoice->userid; $invid = $invoice->id; $invgenerated = $invoice->date; $invoicedue = $invoice->duedate; $invoiceamt = $invoice->total; $invoicemethod = $invoice->paymentmethod; $invlink = "invoices.php?action=edit&id=$invid"; $userlink = "clientssummary.php?userid=$invowner"; $invgenerated = $date = fromMySQLDate($invgenerated); $invoicedue = $date = fromMySQLDate($invoicedue); $invoicemethod = ucwords($invoicemethod); foreach(Capsule::table('tblclients')->WHERE ('id', '=', $invowner)->get() as $whoami) { $fname = $whoami->firstname; $lname = $whoami->lastname; $cname = $whoami->companyname; $theuser = "$fname $lname"; $currencyid = $whoami->currency; } if (empty($currencyid)) { //set to default currency $currencyid = '1'; } foreach(Capsule::table('tblcurrencies')->WHERE ('id', '=', $currencyid)->get() as $currency) { $prefix = $currency->prefix; $suffix = $currency->suffix; } $theoutput .= " <div class=\"row\"> <div class=\"col-xs-1\"> <div class=\"item\"> <a href=\"$invlink\">$invid</a> </div> </div> <div class=\"col-sm-2\"> <div class=\"item\"> <a href=\"$userlink\">$theuser</a> </div> </div> <div class=\"col-xs-3\"> <div class=\"item\"> $invgenerated </div> </div> <div class=\"col-xs-3\"> <div class=\"item\"> $invoicedue </div> </div> <div class=\"col-xs-2\"> <div class=\"item\"> $prefix$invoiceamt $suffix </div> </div> <div class=\"col-sm-1\"> <div class=\"item\"> $invoicemethod </div> </div> </div>"; } return <<<EOF <div class="widget-content-padded"> <div class="row"> <div class="col-xs-1"> <div class="item"> <strong>ID</strong> </div> </div> <div class="col-sm-2"> <div class="item"> <strong>User</strong> </div> </div> <div class="col-xs-3"> <div class="item"> <strong>Generated</strong> </div> </div> <div class="col-xs-3"> <div class="item"> <strong>Due Date</strong> </div> </div> <div class="col-xs-2"> <div class="item"> <strong>Amount</strong> </div> </div> <div class="col-sm-1"> <div class="item"> <strong>Method</strong> </div> </div> </div> $theoutput <br /> <a href="invoices.php?status=Unpaid" class="btn btn-info btn-sm">View All »</a> </br> <p align = "center">Widget courtesy of <a href="https://www.whmcs.guru/"> WHMCS Guru</a></p> </div> EOF; } } Edited January 9, 2017 by twhiting9275 1 Quote Link to comment Share on other sites More sharing options...
brian! Posted January 9, 2017 Share Posted January 9, 2017 i'm getting an error when adding it to our v7.1.1 dev... Parse error: syntax error, unexpected end of file in /modules/widgets/openinvoices.php on line 149 if I replace your return block with the return block from the Hello World hook in the widget developer page, the dashboard loads with the widget containing "Hello World" - so I can only assume there is something in your return block that WHMCS doesn't like. 0 Quote Link to comment Share on other sites More sharing options...
twhiting9275 Posted January 9, 2017 Author Share Posted January 9, 2017 hm, worked fine last night. I'll take a look and see what happened 0 Quote Link to comment Share on other sites More sharing options...
twhiting9275 Posted January 9, 2017 Author Share Posted January 9, 2017 Original post updated. Turns out that I missed the unpaid status. Still haven't been able to find where you were able to find that error though. What version of php are you running? It's possible (though not likely) that's part of the issue. 0 Quote Link to comment Share on other sites More sharing options...
brian! Posted January 10, 2017 Share Posted January 10, 2017 Original post updated. Turns out that I missed the unpaid status. Still haven't been able to find where you were able to find that error though. What version of php are you running? It's possible (though not likely) that's part of the issue. thanks for the tweak, v1.0.1 is working without issues. if it helps, I have a couple of suggested improvements.. 1. wrap the return block of code with an IF statement to detect if $theoutput is empty (e.g there are no unpaid invoices)... if (!empty($theoutput)) { ... } if there are no unpaid invoices, it seems pointless to output the table headings - and the above code will effectively minimise the widget to save space on the dashboard. 2. again to save space, I moved the button link to view the unpaid invoices to the header - you could do that by either adding a link to the widget title... protected $title = '<a href="invoices.php?status=Unpaid">Open Invoices</a>'; but that link might not be obvious to users, so you can add your previous button to the title (either as a button or link)... protected $title = 'Open Invoices <a href="invoices.php?status=Unpaid" class="btn btn-link btn-xs">View All »</a>'; one weird thing that I did spot is that it's very difficult to make these v7 widgets multilingual - with previous versions you could reference the $_adminlang, but with these widgets, it either ignores the value or it causes an error. 1 Quote Link to comment Share on other sites More sharing options...
WHMCS Technical Analyst WHMCS Edward Posted January 10, 2017 WHMCS Technical Analyst Share Posted January 10, 2017 Great job on this @twhiting9275 One suggestion that might simplify the code somewhat is to use the model that's available for invoices (http://docs.whmcs.com/classes/7.1/WHMCS/Billing/Invoice.html). For example: use WHMCS\Billing\Invoice; $unpaidInvoices = Invoice::with('client')->unpaid()->get(); foreach ($unpaidInvoices as $invoice) { // ... } As well if you move that to the data method, you could take advantage of the caching. @brian For language variables you should be using the translation helper available in WHMCS 6+: AdminLang::trans('some.variable') -Eddy 1 Quote Link to comment Share on other sites More sharing options...
brian! Posted January 10, 2017 Share Posted January 10, 2017 @brian For language variables you should be using the translation helper available in WHMCS 6+: AdminLang::trans('some.variable') interesting - I don't ever recall reading about AdminLang::trans in any of the documentation or release notes... i'm familiar with Lang::trans, but wasn't aware there was an admin equivalent. so if you wanted to change... <strong>Due Date</strong> you can't use the AdminLang within the output (as it causes an error), it seems you need to declare it as a variable first before the return and then use that variable later in the output... $duedate = AdminLang::trans('fields.duedate'); <strong>$duedate</strong> out of interest Eddy, what about $title - it seems to only accept a string and not a variable, so I can't see how you could make the widget title multilingual. 1 Quote Link to comment Share on other sites More sharing options...
WHMCS Technical Analyst WHMCS Edward Posted January 10, 2017 WHMCS Technical Analyst Share Posted January 10, 2017 The output is being built as a heredoc so you might find you can enclose it in curly braces {AdminLang::trans('xxx')} to have it work inline, otherwise defining as a variable first would be the only way. For a title to use language variables, you would want to do that via a constructor method: use AdminLang; public function __construct() { $this->title = AdminLang::trans('global.success'); } HTH -Eddy 0 Quote Link to comment Share on other sites More sharing options...
J-B Posted January 29, 2017 Share Posted January 29, 2017 (edited) I get a HTTP 500 error. I cant see anything in the error.log. Any Idea? Edited January 29, 2017 by J-B 0 Quote Link to comment Share on other sites More sharing options...
J-B Posted January 30, 2017 Share Posted January 30, 2017 (edited) Some Whitespace was the error! Thanks for this Widget! Edited January 30, 2017 by J-B 0 Quote Link to comment Share on other sites More sharing options...
lucianmih Posted February 6, 2017 Share Posted February 6, 2017 @J-B -- I get the same HTTP 500 error, where was that whitespace in the script? Thanks! 0 Quote Link to comment Share on other sites More sharing options...
J-B Posted February 7, 2017 Share Posted February 7, 2017 @J-B -- I get the same HTTP 500 error, where was that whitespace in the script? Thanks! They are a lot whitespaces. Here are the Script without whitespaces -> https://oc3.jaba.hosting/s/UAkJ3xI5l84QDgg 0 Quote Link to comment Share on other sites More sharing options...
twhiting9275 Posted February 11, 2017 Author Share Posted February 11, 2017 If there's whitespace, that's going to be due to your browser's interpretation of the code itself, or how it's pasted into your editor. I literally just did a c&p from the code entry in my original post, and there's nothing there for whitespace. That said, I've added this as an attachment to prevent that . Just change the extension from .txt to .php open_invoices.txt 0 Quote Link to comment Share on other sites More sharing options...
boost Posted April 25, 2017 Share Posted April 25, 2017 Parse error: syntax error, unexpected '<<' (T_SL) in /home/admin/domains/domain.com/public_html/whmcs/modules/widgets/OpenInvoices.php on line 103 Any help to fix this? 0 Quote Link to comment Share on other sites More sharing options...
boost Posted April 25, 2017 Share Posted April 25, 2017 I removed whitespaces but now when I try access "edit admin roles" I'm getting Catchable fatal error: Object of class Closure could not be converted to string in /home/admin/domains/domain.com/public_html/whmcs/admin/configadminroles.php on line 0 0 Quote Link to comment Share on other sites More sharing options...
brian! Posted April 25, 2017 Share Posted April 25, 2017 if it helps, the version below is the one I have working in a v7.2beta dev, but it worked fine when it was v7.1 too... <?php //open invoices widget , rewritten for 7.1 //courtesy of https://www.whmcs.guru //version 1.0.1 use Illuminate\Database\Capsule\Manager as Capsule; add_hook('AdminHomeWidgets', 1, function() { return new InvoiceWidget(); }); /** * Updated invoices widget */ class InvoiceWidget extends \WHMCS\Module\AbstractWidget { protected $title = 'Open Invoices <a href="invoices.php?status=Unpaid" class="btn btn-link btn-xs">View All »</a>'; protected $description = 'An overview of Open Invoices.'; protected $weight = 150; protected $columns = 1; protected $cache = false; protected $cacheExpiry = 120; protected $requiredPermission = 'View Income Totals'; public function getData() { return array(); } public function generateOutput($data) { foreach (Capsule::table('tblinvoices') ->WHERE ('status', '=' , 'Unpaid')->get() as $invoice) { $invowner = $invoice->userid; $invid = $invoice->id; $invgenerated = $invoice->date; $invoicedue = $invoice->duedate; $invoiceamt = $invoice->total; $invoicemethod = $invoice->paymentmethod; $invlink = "invoices.php?action=edit&id=$invid"; $userlink = "clientssummary.php?userid=$invowner"; $invgenerated = $date = fromMySQLDate($invgenerated); $invoicedue = $date = fromMySQLDate($invoicedue); $invoicemethod = ucwords($invoicemethod); foreach(Capsule::table('tblclients')->WHERE ('id', '=', $invowner)->get() as $whoami) { $fname = $whoami->firstname; $lname = $whoami->lastname; $cname = $whoami->companyname; $theuser = "$fname $lname"; $currencyid = $whoami->currency; } if (empty($currencyid)) { //set to default currency $currencyid = '1'; } foreach(Capsule::table('tblcurrencies')->WHERE ('id', '=', $currencyid)->get() as $currency) { $prefix = $currency->prefix; $suffix = $currency->suffix; } $theoutput .= " <div class=\"row\"> <div class=\"col-xs-1\"> <div class=\"item\"> <a href=\"$invlink\">$invid</a> </div> </div> <div class=\"col-sm-2\"> <div class=\"item\"> <a href=\"$userlink\">$theuser</a> </div> </div> <div class=\"col-xs-3\"> <div class=\"item\"> $invgenerated </div> </div> <div class=\"col-xs-3\"> <div class=\"item\"> $invoicedue </div> </div> <div class=\"col-xs-2\"> <div class=\"item\"> $prefix$invoiceamt $suffix </div> </div> <div class=\"col-sm-1\"> <div class=\"item\"> $invoicemethod </div> </div> </div>"; } if (!empty($theoutput)) { return <<<EOF <div class="widget-content-padded"> <div class="row"> <div class="col-xs-1"> <div class="item"> <strong>ID</strong> </div> </div> <div class="col-sm-2"> <div class="item"> <strong>User</strong> </div> </div> <div class="col-xs-3"> <div class="item"> <strong>Generated</strong> </div> </div> <div class="col-xs-3"> <div class="item"> <strong>Due Date</strong> </div> </div> <div class="col-xs-2"> <div class="item"> <strong>Amount</strong> </div> </div> <div class="col-sm-1"> <div class="item"> <strong>Method</strong> </div> </div> </div> $theoutput </div> EOF; } } } 1 Quote Link to comment Share on other sites More sharing options...
boost Posted April 25, 2017 Share Posted April 25, 2017 Widget is showing, but still when I try access Setup > Staff Management > Administrator Roles > ex. full administrator > edit i got Catchable fatal error: Object of class Closure could not be converted to string in /home/admin/domains/domain/public_html/whmcs/admin/configadminroles.php on line 0 when I remove widget file from server I can edit admin roles, so there is some issue with widget code I guess. 0 Quote Link to comment Share on other sites More sharing options...
brian! Posted April 25, 2017 Share Posted April 25, 2017 hmm, it's not something i'm seeing on v7.2b - what I am seeing is that I can't disable it by changing permissions... i'm sure that worked in v7.1 as a temporary fix, the v6 widget should still work in v7 - you'd just need to upload it and enable it for your admin role. 0 Quote Link to comment Share on other sites More sharing options...
NoDoze Posted September 11, 2017 Share Posted September 11, 2017 WHMCS 7.2.3 I created and uploaded OpenInvoices.php but it doesn't appear. Is there something more I need to do? Or is 7.2.3 not supported? Thanks 0 Quote Link to comment Share on other sites More sharing options...
Patty Posted October 2, 2017 Share Posted October 2, 2017 It does work on v7.2.3. Just need a little tweak on the layout but it works like a charm! Thank you, guys! 0 Quote Link to comment Share on other sites More sharing options...
twhiting9275 Posted October 2, 2017 Author Share Posted October 2, 2017 4 hours ago, Patty said: It does work on v7.2.3. Just need a little tweak on the layout but it works like a charm! Thank you, guys! What tweaks did you need to use to get this working? 0 Quote Link to comment Share on other sites More sharing options...
Patty Posted October 2, 2017 Share Posted October 2, 2017 Like less space between columns so it won't need the horizontal scroll bar... Things like that. 0 Quote Link to comment Share on other sites More sharing options...
bayden10 Posted March 22, 2018 Share Posted March 22, 2018 WHMCS 7.4.2 Some cosmetic changes (FireFox user) and weight adjustment, works for me. <?php //open invoices widget , rewritten for 7.1 //courtesy of https://www.whmcs.com //version 1.0.1 use Illuminate\Database\Capsule\Manager as Capsule; add_hook('AdminHomeWidgets', 1, function() { return new InvoiceWidget(); }); /** * Open Invoices widget */ class InvoiceWidget extends \WHMCS\Module\AbstractWidget { protected $title = 'ICT Open Invoices <a href="invoices.php?status=Unpaid" class="btn btn-link btn-xs">View All »</a>'; protected $description = 'An overview of Open Invoices.'; protected $weight = 50; protected $columns = 1; protected $cache = false; protected $cacheExpiry = 120; protected $requiredPermission = 'View Income Totals'; public function getData() { return array(); } public function generateOutput($data) { foreach (Capsule::table('tblinvoices') ->WHERE ('status', '=' , 'Unpaid')->get() as $invoice) { $invowner = $invoice->userid; $invid = $invoice->id; $invgenerated = $invoice->date; $invoicedue = $invoice->duedate; $invoiceamt = $invoice->total; $invoicemethod = $invoice->paymentmethod; $invlink = "invoices.php?action=edit&id=$invid"; $userlink = "clientssummary.php?userid=$invowner"; $invgenerated = $date = fromMySQLDate($invgenerated); $invoicedue = $date = fromMySQLDate($invoicedue); $invoicemethod = ucwords($invoicemethod); foreach(Capsule::table('tblclients')->WHERE ('id', '=', $invowner)->get() as $whoami) { $fname = $whoami->firstname; $lname = $whoami->lastname; $cname = $whoami->companyname; $theuser = "$fname $lname"; $currencyid = $whoami->currency; } if (empty($currencyid)) { //set to default currency $currencyid = '1'; } foreach(Capsule::table('tblcurrencies')->WHERE ('id', '=', $currencyid)->get() as $currency) { $prefix = $currency->prefix; $suffix = $currency->suffix; } $theoutput .= " <div class=\"row\"> <div class=\"col-xs-2\"> <div class=\"item\"> <a href=\"$invlink\">$invid</a> </div> </div> <div class=\"col-sm-4\"> <div class=\"item\"> <a href=\"$userlink\">$theuser</a> </div> </div> <div class=\"col-xs-3\"> <div class=\"item\"> $invgenerated </div> </div> <div class=\"col-xs-3\"> <div class=\"item\"> $prefix$invoiceamt $suffix </div> </div> </div>"; } if (!empty($theoutput)) { return <<<EOF <div class="widget-content-padded"> <div class="row"> <div class="col-xs-2"> <div class="item"> <strong>ID</strong> </div> </div> <div class="col-sm-4"> <div class="item"> <strong>User</strong> </div> </div> <div class="col-xs-3"> <div class="item"> <strong>Generated</strong> </div> </div> <div class="col-xs-3"> <div class="item"> <strong>Amount</strong> </div> </div> </div> $theoutput </div> EOF; } } } 0 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.