Skip to content

Commit

Permalink
Support multi-currency for AR/AP batch import
Browse files Browse the repository at this point in the history
Since LSMB support for multi-currency, the import should also support too. Previously the AR/AP import batch can import only with default currency. This allows user to import AR/AP batch with different currency defined in the system.
Add the example of the AR/AP batch import csv format
  • Loading branch information
aungzwin10 committed Dec 6, 2021
1 parent f91e0fa commit f4f14c6
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 22 deletions.
3 changes: 3 additions & 0 deletions doc/csv-import/example-ap-batch-upload.csv
@@ -0,0 +1,3 @@
vendor,amount,curr,fx_rate,account,ap,description,invnumber,transdate
00123(Vendor Credit Account Number),10,USD,1(Assume Base Currency is USD),5010--Purchases,2100--Accounts Payable,Line description example,AP001,2021-12-31
00456(Vendor Credit Account Number),15,CAD,0.78((Assume Base Currency is USD),5010--Purchases,2100--Accounts Payable,Line description example,AP002,2021-12-31
3 changes: 3 additions & 0 deletions doc/csv-import/example-ar-batch-upload.csv
@@ -0,0 +1,3 @@
customer,amount,curr,fx_rate,account,ar,description,invnumber,transdate
00123(Customer Credit Account Number),10,USD,1(Assume Base Currency is USD),4010--Sales,1200--Accounts Receivables,Line description example,AP001,2021-12-31
00456(Customer Credit Account Number),15,CAD,0.78(Assume Base Currency is USD),4010--Sales,1200--Accounts Receivables,Line description example,AP002,2021-12-31
67 changes: 45 additions & 22 deletions lib/LedgerSMB/Scripts/import_csv.pm
Expand Up @@ -43,10 +43,10 @@ our $cols = {
gl_multi => ['debit_accno', 'credit_accno', 'amount', 'curr',
'amount_fx', 'reference', 'transdate', 'description',
'source_debit', 'source_credit', 'memo'],
ap_multi => ['vendor', 'amount', 'account', 'ap', 'description',
'invnumber', 'transdate'],
ar_multi => ['customer', 'amount', 'account', 'ar', 'description',
'invnumber', 'transdate'],
ap_multi => ['vendor', 'amount', 'curr', 'fx_rate', 'account', 'ap',
'description', 'invnumber', 'transdate'],
ar_multi => ['customer', 'amount', 'curr', 'fx_rate', 'account', 'ar',
'description', 'invnumber', 'transdate'],
timecard => ['employee', 'business_unit_id', 'transdate',
'partnumber', 'description', 'qty', 'non_billable',
'sellprice', 'allocated', 'notes', 'jctype', 'curr'],
Expand Down Expand Up @@ -132,56 +132,79 @@ sub _aa_multi {
my $vcst = $request->{dbh}->prepare(
'select count(*) from entity_credit_account where meta_number = ?'
);
my $currst = $request->{dbh}->prepare(
'select count(*) from currency where curr = ?'
);
for my $ref (@$entries){
my %entry;
# Reference with name instead of index for better readability
@entry{qw( vc amount curr fx_rate account arap
description invnumber transdate )} = @$ref;
my $pass;
next if $ref->[1] !~ /\d/;
my ($acct) = split /--/, $ref->[2];
next if $entry{amount} !~ /\d/;
my ($acct) = split /--/, $entry{account};
$acst->execute($acct);
($pass) = $acst->fetchrow_array;
$request->error("Account $acct not found") if !$pass;
($acct) = split /--/, $ref->[3]; ## no critic (ProhibitMagicNumbers) sniff
($acct) = split /--/, $entry{arap}; ## no critic (ProhibitMagicNumbers) sniff
$acst->execute($acct);
($pass) = $acst->fetchrow_array;
$request->error("Account $acct not found") if !$pass;
$vcst->execute(uc($ref->[0]));
$vcst->execute($entry{vc});
($pass) = $vcst->fetchrow_array;
if (! $pass) {
if ($arap eq 'ar') {
$request->error("Customer $ref->[0] not found");
$request->error("Customer $entry{vc} not found");
} else {
$request->error("Vendor $ref->[0] not found");
$request->error("Vendor $entry{vc} not found");
}
}
# Check currency is defined in the system
$currst->execute($entry{curr});
($pass) = $currst->fetchrow_array;
$request->error("Currency $entry{curr} not found") if !$pass;
}
for my $ref (@$entries){
my %entry;
@entry{qw( vc amount curr fx_rate account arap
description invnumber transdate )} = @$ref;

my $form = Form->new(); ## no critic
$form->{dbh} = $request->{dbh};
my $default_currency = $request->setting->get('curr');
$form->{rowcount} = 1;
$form->{ARAP} = uc($arap);
$form->{batch_id} = $batch->{id};
$form->{customernumber} = $form->{vendornumber} = shift @$ref;
$form->{amount_1} = shift @$ref;
$form->{customernumber} = $form->{vendornumber} = $entry{vc};
$form->{amount_1} = $entry{amount};
next if $form->{amount_1} !~ /\d/;
$form->{amount_1} = $form->parse_amount(
$request->{_user}, $form->{amount_1});
$form->{"$form->{ARAP}_amount_1"} = shift @$ref;
$form->{"$form->{ARAP}_amount_1"} = $entry{account};
$form->{vc} = ($arap eq 'ar') ? 'customer' : 'vendor';
$form->{arap} = $arap;
$form->{uc($arap)} = shift @$ref;
$form->{description_1} = shift @$ref;
$form->{invnumber} = shift @$ref;
$form->{transdate} = shift @$ref;
$form->{currency} = $default_currency;
$form->{uc($arap)} = $entry{arap};
$form->{description_1} = $entry{description};
$form->{invnumber} = $entry{invnumber};
$form->{transdate} = $entry{transdate};
$form->{currency} = $entry{curr};
$form->{exchangerate} = $entry{fx_rate};
$form->{approved} = '0';
$form->{defaultcurrency} = $default_currency;
# need to fetch due date by terms set on the ECA
# otherwise transaction posted with empty due date
my $sth = $form->{dbh}->prepare(
'SELECT id FROM entity_credit_account
'SELECT id,
(?::date + (concat(
(CASE WHEN terms IS NULL THEN 1 ELSE terms END),
\' days\'))::interval) as duedate
FROM entity_credit_account
WHERE entity_class = ? and meta_number = ?'
);
$sth->execute( ($arap eq 'ar') ? 2 : 1,
uc($form->{vendornumber}));
($form->{vendor_id}) = $sth->fetchrow_array;
$sth->execute( $form->{transdate},
($arap eq 'ar') ? 2 : 1,
$form->{vendornumber} );
($form->{vendor_id}, $form->{duedate}) = $sth->fetchrow_array;
$form->{customer_id} = $form->{vendor_id};

# The 'AA' package is used as 'LedgerSMB::AA'
Expand Down
7 changes: 7 additions & 0 deletions sql/modules/Voucher.sql
Expand Up @@ -365,6 +365,13 @@ $$
WHERE id IN (select trans_id FROM voucher
WHERE batch_id = in_batch_id);

-- When approving the AR/AP batch import,
-- we need to approve the acc_trans line also.
UPDATE acc_trans SET approved = true
WHERE trans_id IN (select trans_id FROM voucher
WHERE batch_id = in_batch_id
AND batch_class IN (1, 2));

UPDATE acc_trans SET approved = true
WHERE voucher_id IN (select id FROM voucher
WHERE batch_id = in_batch_id
Expand Down

0 comments on commit f4f14c6

Please sign in to comment.