Commit 69a2a40d authored by Nigel Kukard's avatar Nigel Kukard

* Preliminary work on supplier credit notes

* Added caching library
* Added first Engine function to get caching library stats
parent 52632dcf
......@@ -39,7 +39,33 @@
URGENT
* Add in the variable each module bitches about when setting the error so we at least know wtf is wrong
* fix template variable names!!
* PULL CONFIG OUT CONFIG HANDLE, NOT CONFIG MODULE??
* Supplier credit notes module
=> Entire invoice credited
- - linkSupplierInvoice function
- Loop with all items
- if its a GL linking, pass opposite transaction to GL ... including tax accounts
- if its a inventory linking, pass opposite transaction to GL accounts, including tax accounts, including stock adjust (option to stock adjust!!!!), what happens if we keep the item? trnasactions?
=> Items' entire price on invoice credited
- same as above
=> Items' partial price on invoice credited
- same as above, cept adjust cost price aswell ... what happens if we already sold the item?
* Book inventory items out as an expense (ie. company uses them)
* Credit notes module
* Link assets to supplier invoice
ACCEPTED CHANGES
......
......@@ -44,6 +44,8 @@ CREATE TABLE soap_caps (
/* SOAPTest */
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'SOAP/Test');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'SOAP/User');
/* Engine */
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Engine/Cache/Stats');
/* Clients */
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Clients/Add');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Clients/Remove');
......@@ -91,9 +93,13 @@ INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Statements/Send');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Suppliers/Show');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Suppliers/Add');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Suppliers/Remove');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Suppliers/GL/Show');
/* Tax */
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'Tax/Type/Add');
/* Supplier Credit Notes */
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'SupplierCreditNotes/Add');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'SupplierCreditNotes/Show');
INSERT INTO soap_caps (GroupID,Capability) VALUES (1,'SupplierCreditNotes/Post');
......
......@@ -69,7 +69,7 @@ sub aclAdd {
$itemInfo->{'function'} = $function;
$itemInfo->{'capability'} = $capability;
printf(STDERR 'Adding %s::%s to capability "%s"'."\n",$package,$function,$capability);
# printf(STDERR 'Adding %s::%s to capability "%s"'."\n",$package,$function,$capability);
push(@acl,$itemInfo);
# Map function into dispatch
......
......@@ -22,15 +22,39 @@ use strict;
use warnings;
use Auth;
use wiaflos::constants;
use wiaflos::soap;
use wiaflos::server::Engine;
# Plugin info
our $pluginInfo = {
Name => "Engine",
Init => \&init,
};
# Initialize module
sub init {
my $server = shift;
Auth::aclAdd('Engine','cacheGetStats','Engine/Cache/Stats');
}
# Get cache stats
sub cacheGetStats {
# Do transaction
my $res = wiaflos::server::Engine::cacheGetStats();
if (ref $res ne "HASH") {
return SOAPResponse(RES_ERROR,$res,wiaflos::server::Engine::Error());
}
return SOAPResponse(RES_OK,$res);
}
......
......@@ -295,7 +295,7 @@ sub getGLAccountEntries {
if (!defined($data->{'AccountNumber'}) || $data->{'AccountNumber'} eq "") {
return SOAPResponse(RES_ERROR,ERR_S_PARAM,"Parameter 'AccountNumber' ainvalid");
return SOAPResponse(RES_ERROR,ERR_S_PARAM,"Parameter 'AccountNumber' invalid");
}
......
# Wiaflos SOAP server caching
# SOAP interface to SupplierCreditNotes module
# Copyright (C) 2007 Nigel Kukard <nkukard@lbsd.net>
#
# This program is free software; you can redistribute it and/or modify
......@@ -16,28 +16,80 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# Caching package
package Cache;
package SupplierCreditNotes;
use strict;
use warnings;
use wiaflos::version;
use Auth;
use wiaflos::constants;
use wiaflos::soap;
use wiaflos::server::SupplierCreditNotes;
require Exporter;
our (@ISA,@EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(
registerCache
);
# Plugin info
our $pluginInfo = {
Name => "SupplierCreditNotes",
Init => \&init,
};
# Initialize module
sub init {
my $server = shift;
Auth::aclAdd('SupplierCreditNotes','createSupplierCreditNote','SupplierCreditNotes/Add');
}
# Create client invoice
# Parameters:
# SupplierCode - Supplier code
# Number - Credit note number
# SupplierCreditNoteNumber - Supplier credit note number
# IssueDate - Issue date of credit note
# Optional:
# SupplierInvoiceNumber - Supplier invoice number
# Note - Notes
sub createSupplierCreditNote {
my (undef,$data) = @_;
# Check params
if (!defined($data->{'SupplierCode'}) || $data->{'SupplierCode'} eq "") {
return SOAPResponse(RES_ERROR,ERR_S_PARAM,"Parameter 'SupplierCode' invalid");
}
if (!defined($data->{'Number'}) || $data->{'Number'} eq "") {
return SOAPResponse(RES_ERROR,ERR_S_PARAM,"Parameter 'Number' invalid");
}
if (!defined($data->{'IssueDate'}) || $data->{'IssueDate'} eq "") {
return SOAPResponse(RES_ERROR,ERR_S_PARAM,"Parameter 'IssueDate' invalid");
}
my $authInfo = Auth::sessionGetData();
# Do transaction
my $detail;
$detail->{'SupplierCode'} = $data->{'SupplierCode'};
$detail->{'Number'} = $data->{'Number'};
$detail->{'SupplierCreditNoteNumber'} = $data->{'SupplierCreditNoteNumber'};
$detail->{'IssueDate'} = $data->{'IssueDate'};
$detail->{'SupplierInvoiceNumber'} = $data->{'SupplierInvoiceNumber'};
$detail->{'Note'} = $data->{'Note'};
my $res = wiaflos::server::SupplierCreditNotes::createSupplierCreditNote($detail);
if ($res < 1) {
return SOAPResponse(RES_ERROR,$res,wiaflos::server::SupplierCreditNotes::Error());
}
return SOAPResponse(RES_OK,$res);
}
use Data::Dumper;
# IPC Stuff
#my $IPC_key = "Wiaflos-$VERSION";
#use IPC::Shareable;
#my $lastmsg_handle = tie my $lastmsg, 'IPC::Shareable', undef, { 'destroy' => 1 };
......
......@@ -43,6 +43,8 @@ sub init {
Auth::aclAdd('Suppliers','createSupplier','Suppliers/Add');
Auth::aclAdd('Suppliers','removeSupplier','Suppliers/Remove');
Auth::aclAdd('Suppliers','getSupplierGLAccountEntries','Suppliers/GL/Show');
Auth::aclAdd('Suppliers','linkSupplierAddress','Suppliers/Add');
Auth::aclAdd('Suppliers','linkSupplierEmailAddress','Suppliers/Add');
......@@ -430,6 +432,47 @@ sub removeSupplier {
}
# Return list of supplier GL account entries
# Parameters:
# AccountNumber - GL account number
sub getSupplierGLAccountEntries {
my (undef,$data) = @_;
if (!defined($data->{'Code'}) || $data->{'Code'} eq "") {
return SOAPResponse(RES_ERROR,ERR_S_PARAM,"Parameter 'Code' invalid");
}
my $authInfo = Auth::sessionGetData();
# Grab and sanitize data
my $detail;
$detail->{'Code'} = $data->{'Code'};
my $rawData = wiaflos::server::Suppliers::getGLAccountEntries($detail);
if (ref $rawData ne "ARRAY") {
return SOAPResponse(RES_ERROR,$rawData,wiaflos::server::GL::Error());
}
# Build result
my @data;
foreach my $item (@{$rawData}) {
my $tmpItem;
$tmpItem->{'ID'} = $item->{'ID'};
$tmpItem->{'TransactionID'} = $item->{'TransactionID'};
$tmpItem->{'Reference'} = $item->{'Reference'};
$tmpItem->{'TransactionDate'} = $item->{'TransactionDate'};
$tmpItem->{'Amount'} = $item->{'Amount'};
$tmpItem->{'TransactionReference'} = $item->{'TransactionReference'};
push(@data,$tmpItem);
}
return SOAPResponse(RES_OK,\@data);
}
......
......@@ -167,7 +167,7 @@ sub post_configure_hook
$self->log(3,"Initializing authentication module.");
Auth::init($self);
$self->log(3,"Plugin load started...");
$self->log(2,"Plugin load started...");
# Load plugins
foreach my $plugin (@{$soapcfg->{'plugins'}}) {
......@@ -181,12 +181,14 @@ sub post_configure_hook
}
}
$self->log(3,"Plugin load done, ".(@{$soapcfg->{'dispatch_to'}})." functions.");
$self->log(2,"Plugin load done, ".(@{$soapcfg->{'dispatch_to'}})." functions.");
$self->log(3,"Initializing system modules.");
$self->log(2,"Initializing system modules.");
wiaflos::server::config::Init($self);
$self->log(3,"System modules initialized.");
# Init cache & store handle
($self->{'cache_engine'}{'handle'},$self->{'cache_engine'}{'data'}) = wiaflos::server::cache::Init($self);
$self->log(2,"System modules initialized.");
}
......@@ -227,9 +229,13 @@ sub child_init_hook
{
my $self = shift;
$self->log(4,"Firing up SOAP engine\n");
$self->SUPER::child_init_hook();
$self->log(4,"Firing up caching engine\n");
wiaflos::server::cache::connect();
$self->log(4,"Firing up SOAP engine\n");
# Init system stuff
$self->{'client'}->{'dbh'} = wiaflos::server::dbilayer::Init($self);
if (!defined($self->{'client'}->{'dbh'})) {
......
......@@ -39,6 +39,8 @@ Purchasing
Payments
Receipting
Statements
SupplierCreditNotes
Engine
EOT
......@@ -53,6 +53,7 @@ my @modules = qw(
Payments
Receipting
Statements
SupplierCreditNotes
);
my @plugins;
......@@ -225,7 +226,7 @@ sub processCommand
# Check for special: help
} elsif ($cmdline =~ /^\s*help$/) {
} elsif ($cmdline =~ /^\s*help\s*$/i) {
print($OUT "Valid commands...\n");
# Loop commands
......@@ -250,12 +251,15 @@ sub processCommand
return 0;
# Check for special: help <command>
} elsif (my ($cmd) = ($cmdline =~ /^\s*help (\S+)/)) {
} elsif (my ($cmd) = ($cmdline =~ /^\s*help\s*(\S+)\s*$/i)) {
my $res = 0;
# Loop with commands
foreach my $i (@{$cmdMap->{'Children'}}) {
if ($cmd =~ /^\s*$i->{'Regex'}/) {
# Hop over children menu items
next if (defined($i->{'Children'}));
print(STDERR "DEBUG: cmdline = '$cmd' vs. '$i->{'Regex'}'\n");
if ($cmd =~ /^\s*$i->{'Regex'}\s*$/i) {
print($OUT "Usage...\n");
print($OUT " ".$i->{'Help'}."\n");
$res = 1;
......@@ -277,8 +281,8 @@ sub processCommand
foreach my $i (@{$cmdMap->{'Children'}}) {
# Test command for match
if ((defined($i->{'Children'}) && $cmdline =~ /^\s*$i->{'MenuItem'}/i)
|| (defined($i->{'Regex'}) && $cmdline =~ /^\s*$i->{'Regex'}/) ) {
if ((defined($i->{'Children'}) && $cmdline =~ /^\s*$i->{'MenuItem'}\s*$/i)
|| (defined($i->{'Regex'}) && $cmdline =~ /^\s*$i->{'Regex'}(?:\s+|$)/) ) {
# Check state definition
# if (!defined($i->{'type'})
......@@ -300,7 +304,7 @@ sub processCommand
} else {
# Substitute
my $substitution = $i->{'Substitute'} ? defined($i->{'Substitute'}) : "";
(my $fcmd = $cmdline) =~ s/^\s*$i->{'Regex'}\s*/$substitution/;
(my $fcmd = $cmdline) =~ s/^\s*$i->{'Regex'}\s*/$substitution/i;
print($OUT "Found '".$i->{'Regex'}."', dest '".$fcmd."'\n");
......
......@@ -39,49 +39,49 @@ our $pluginInfo = {
Children => [
{
MenuItem => "Create",
Regex => "create ",
Regex => 'create',
Desc => "Create a client",
Help => 'create code="<reference>" name="<client name>" [reg="<registration num>"] [taxref="<tax reference number>"] account="<GL account>" [contactperson="<contact person name>"] [createsubaccount="<y to create sub account>"]',
Function => \&create,
},
{
MenuItem => "LinkAddr",
Regex => "linkaddr ",
MenuItem => "LinkAddress",
Regex => "linkaddr(?:ess)?",
Desc => "Link in an address",
Help => 'linkaddr client="<client code>" type="<billing or shipping>" address="<address>"',
Help => 'linkAddress client="<client code>" type="<billing or shipping>" address="<address>"',
Function => \&linkAddress,
},
{
MenuItem => "LinkEmail",
Regex => "linkemail ",
MenuItem => "LinkEmailAddress",
Regex => "linkemail(?:address)?",
Desc => "Link in an email address",
Help => 'linkemail(?:addr)? client="<client code>" type="<accounts or general>" address="<address>"',
Help => 'linkEmailAddress client="<client code>" type="<accounts or general>" address="<address>"',
Function => \&linkEmailAddress,
},
{
MenuItem => "LinkPhNum",
Regex => "linkphnum ",
MenuItem => "LinkPhoneNumber",
Regex => "link(?:phnum|phonenumber)",
Desc => "Link in a phone number",
Help => 'linkphnum client="<client code>" type="<phone or fax>" number="<phone number>" [name="<name>"]',
Help => 'linkPhoneNumber client="<client code>" type="<phone or fax>" number="<phone number>" [name="<name>"]',
Function => \&linkPhoneNumber,
},
{
MenuItem => "Remove",
Regex => "remove ",
Regex => "remove",
Desc => "Remove client",
Help => 'remove client="<client code>"',
Function => \&remove,
},
{
MenuItem => "List",
Regex => "list\$",
Regex => "list",
Desc => "Display list of clients",
Help => 'list',
Function => \&list,
},
{
MenuItem => "Show",
Regex => "show ",
Regex => "show",
Desc => "Show client",
Help => 'show client="<client code>"',
Function => \&show,
......
......@@ -23,6 +23,7 @@ package wiaflos::client::cmdline::Engine;
use strict;
use warnings;
use wiaflos::constants;
use wiaflos::client::misc;
use wiaflos::client::soap;
use wiaflos::client::reportwriter;
......@@ -36,6 +37,13 @@ our $pluginInfo = {
{
MenuItem => "Engine",
Children => [
{
MenuItem => "CacheStats",
Regex => "cachestats",
Desc => "Display cache stats",
Help => 'cacheStats',
Function => \&cacheGetStats,
},
],
},
],
......@@ -44,5 +52,40 @@ our $pluginInfo = {
# Display cache stats
sub cacheGetStats
{
my ($OUT,@args) = @_;
if (@args > 0) {
print($OUT " => ERROR: Too many arguments provided\n");
return ERR_C_PARAM;
}
my $detail;
my $res = soapCall($OUT,"Engine","cacheGetStats",$detail);
if ($res->{'Result'} == RES_OK) {
print swrite(<<'END', "Hits", "Misses");
+=======================+=========================+
| @|||||||||||||||||||| | @|||||||||||||||||||||| |
+=======================+=========================+
END
print swrite(<<'END', $res->{'Data'}->{'Hits'}, $res->{'Data'}->{'Misses'});
| @>>>>>>>>>>>>>>>>>>>> | @>>>>>>>>>>>>>>>>>>>>>> |
END
print swrite(<<'END');
+=======================+=========================+
END
} else {
soapDebug($OUT,$res);
}
return $res->{'Result'};
}
1;
# vim: ts=4
......@@ -42,14 +42,14 @@ our $pluginInfo = {
Children => [
{
MenuItem => "List",
Regex => "list ?",
Regex => "list",
Desc => "Display list of accounts",
Help => 'list [format="<text or html>"]',
Function => \&list,
},
{
MenuItem => "Show",
Regex => "show ",
Regex => "show",
Desc => "Show an account",
Help => 'show account="<account number>"',
Function => \&show,
......@@ -68,42 +68,42 @@ our $pluginInfo = {
Children => [
{
MenuItem => "Create",
Regex => "create ",
Regex => "create",
Desc => "Create transaction",
Help => 'create date="<YYYY-MM-DD>" reference="<reference>"',
Function => \&createTransaction,
},
{
MenuItem => "List",
Regex => "list\$",
Regex => "list",
Desc => "List transactions",
Help => 'list',
Function => \&listTransactions,
},
{
MenuItem => "Link",
Regex => "link ",
Regex => "link",
Desc => "Link transactions",
Help => 'link transaction="<transaction id>" account="<account number>" amount="<amount>" [reference="<reference>"]',
Function => \&linkTransaction,
},
{
MenuItem => "Post",
Regex => "post ",
Regex => "post",
Desc => "post transactions",
Help => 'post transaction="<transaction id>"',
Function => \&postTransaction,
},
{
MenuItem => "Remove",
Regex => "remove ",
Regex => "remove",
Desc => "Remove transactions",
Help => 'remove transaction="<transaction id>"',
Function => \&removeTransaction,
},
{
MenuItem => "Show",
Regex => "show ",
Regex => "show",
Desc => "Display transaction entries",
Help => 'show transaction="<transaction id>"',
Function => \&showTransaction,
......
......@@ -38,7 +38,7 @@ our $pluginInfo = {
Children => [
{
MenuItem => "Create",
Regex => "create ",
Regex => "create",
Desc => "Create inventory item",
Help => 'create code="<product code>" type="<product or service>" [mode="<bulk or track for products>"] '.
'description="<description>" incomeaccount="<income account>" [assetaccount="<asset account>"] '.
......@@ -48,21 +48,21 @@ our $pluginInfo = {
},
{
MenuItem => "Remove",
Regex => "remove ",
Regex => "remove",
Desc => "Remove inventory item",
Help => 'remove item="<product code>"',
Function => \&remove,
},
{
MenuItem => "Update",
Regex => "update ",
Regex => "update",
Desc => "Update inventory item",
Help => 'update item="<product code>" [description="<description>"] [sellprice="<sell price>"] [discountable="<yes or no>"] [unit="<unit>"]',
Function => \&update,
},
{
MenuItem => "List",
Regex => "list\$",
Regex => "list",
Desc => "Display list of inventory items",
Help => 'list',
Function => \&list,
......
......@@ -45,16 +45,16 @@ our $pluginInfo = {
Children => [
{
MenuItem => "Create",
Regex => "create ",
Regex => "create",
Desc => "Create a client invoice",
Help => 'create client="<client code>" invoice="<invoice number>" [shipaddress="<shipping address>"] issuedate="<issue date" duedate="<due date>" [ordernumber="<order number>"] [note="<notes>]"',
Function => \&createInvoice,
},
{
MenuItem => "LinkInventory",
Regex => "linkinventory ",
Regex => "linkinventory",
Desc => "Link inventory item",
Help => 'linkinventory invoice="<invoice number>" inventory="<inventory item code>" [description="<description of item>"] [serial="<serial number of item>"] qty="<quantity>" [unitprice="<unit price>"] [discount="<discount>"]',
Help => 'linkInventory invoice="<invoice number>" inventory="<inventory item code>" [description="<description of item>"] [serial="<serial number of item>"] qty="<quantity>" [unitprice="<unit price>"] [discount="<discount>"]',
Function => \&linkInventoryItem,
},
# {
......@@ -73,21 +73,21 @@ our $pluginInfo = {
},
{
MenuItem => "Send",
Regex => "send ",
Regex => "send",
Desc => "Send client invoice",
Help => 'send invoice="<invoice number>" sendto="<email[:addy1,addy2...] or file:filename>"',
Function => \&send,
},
{
MenuItem => "Show",
Regex => "show ",
Regex => "show",
Desc => "Show client invoice",
Help => 'show invoice="<invoice number>"',
Function => \&show,
},
{
MenuItem => "Post",
Regex => "post ",
Regex => "post",
Desc => "Post client invoice",
Help => 'post invoice="<invoice number>"',
Function => \&post,
......
......@@ -45,11 +45,11 @@ our $pluginInfo = {
# Payments
{
MenuItem => "Payments",
Regex => "pay(?:ments)?",
Regex => "pay(?:ments?)?",
Children => [
{
MenuItem => "CreatePayment",
Regex => "create ",
Regex => "create",
Desc => "Create a payment",
Help => 'create supplier="<supplier code>" account="<GL account source of payment>" number="<payment number>" date="<payment date>" reference="<journal reference>" amount="<amount paid>"',
Function => \&createPayment,
......@@ -63,28 +63,28 @@ our $pluginInfo = {
},
{
MenuItem => "Post",
Regex => "post ",
Regex => "post",
Desc => "Post payment",
Help => 'post payment="<payment number>"',
Function => \&postPayment,
},
{
MenuItem => "Allocate",
Regex => "alloc(?:ate)? ",
Regex => "alloc(?:ate)?",
Desc => "Allocate monies from a payment",
Help => 'alloc payment="<payment number>" invoice="<supplier invoice number>" amount="<amount to allocate>"',
Help => 'allocate payment="<payment number>" invoice="<supplier invoice number>" amount="<amount to allocate>"',
Function => \&createAllocation,
},
{
MenuItem => "PostAllocation",
Regex => "postalloc ",
Regex => "postalloc(?:ation)?",
Desc => "Post payment allocation",
Help => 'postalloc id="<allocation ID>>"',
Help => 'postAllocation id="<allocation ID>>"',
Function => \&postAllocation,
},
{
MenuItem => "Show",
Regex => "show ",
Regex => "show",
Desc => "Show payment allocations",
Help => 'show payment="<payment number>"',
Function => \&show,
......
......@@ -46,23 +46,23 @@ our $pluginInfo = {
Children => [
{
MenuItem => "Create",
Regex => "create[ \$]",
Regex => "create",
Desc => "Create a supplier invoice",
Help => 'create supplier="<supplier ref>" invoice="<invoice number>" supplierinvoice="<suppliers invoice number>" issuedate="<issue date" duedate="<due date>" [orderm="<order number>"] [subtotal="<sub total>"] [taxtotal="<tax total>"] [total="<inv total>"] [note="<notes>]"',
Function => \&createInvoice,
},
{
MenuItem => "LinkInventory",
Regex => "linkinventory[ \$]",
Regex => "linkinventory",
Desc => "Link inventory item",
Help => 'linkinventory invoice="<invoice number>" inventory="<inventory item code>" description="<description of item>" [serial="<item serial number>"] qty="<quantity>" [unit="<unit>"] unitprice="<unit price>" discount="<discount>" taxtypeid="<tax type id>" taxmode="<incl or excl>"',
Help => 'linkInventory invoice="<invoice number>" inventory="<inventory item code>" description="<description of item>" [serial="<item serial number>"] qty="<quantity>" [unit="<unit>"] unitprice="<unit price>" discount="<discount>" taxtypeid="<tax type id>" taxmode="<incl or excl>"',
Function => \&linkInventoryItem,
},
{
MenuItem => "LinkExpense",
Regex => "linkexpense[ \$]",
Regex => "linkexpense",
Desc => "Link expense item",
Help => 'linkexpense invoice="<invoice number>" account="<expense account>" description="<description of item>" [serial="<item serial number>"] qty="<quantitiy>" [unit="<unit>"] unitprice="<unitprice>" discount="<discount in %>" taxtypeid="<tax type id>" taxmode="<incl or excl>"',
Help => 'linkExpense invoice="<invoice number>" account="<expense account>" description="<description of item>" [serial="<item serial number>"] qty="<quantitiy>" [unit="<unit>"] unitprice="<unitprice>" discount="<discount in %>" taxtypeid="<tax type id>" taxmode="<incl or excl>"',
Function => \&linkExpenseItem,
},
# {
......@@ -74,21 +74,21 @@ our $pluginInfo = {
# },
{
MenuItem => "list",
Regex => "list[ \$]",