Hello all:

I'm working on a simple event registration form. I was hoping to avoid having to recreate all that business acocunting logic which folks like Dieter Simander and the LedgerSMB team have already figured out and automate the process of keeping the books up to snuff as registrations were made across my client's webform.

I have found that I can perform all sorts of useful interactions with the SL/LS database using either direct connections to the database backend (for data searches) or using WWW::Mechanize (so I can count on th SL / LS code to handle data integrity issues on a data insert operation. My $reg_form->create_sl_customer_mech() method works just fine and even prevents exact duplicates.

But the one method which would be the clincher for me in terms of delivering the functionality required by my client on this project, is the ability to create an invoice. On this piece I have been unable to achieve success.

sub create_sl_invoice_mech { my $self = shift; my ($customer, $event_id) = @_; my ($inv_id,$inv_pdf_path,$inv_html_path); $inv_pdf_path = '/path/to/pdf/file'; $inv_html_path = '/path/to/html/file'; print STDERR "Now creating new invoice for $customer->{'name'}.\n"; my $base_url = $self->{'Cfg'}->{'default'}->{'base_url'}; my $user = $self->{'Cfg'}->{'sl_event_registration'}->{'user'}; my $pw = $self->{'Cfg'}->{'sl_event_registration'}->{'pw'}; # 'is.pl?path=bin/mozilla&action=add&level=AR--Sales%20Invoice&login +=test-user&js=1&type=invoice'; my $arg = 'path=bin/mozilla'; $arg .= '&login=' .$user; $arg .= '&password=' . $pw; $arg .= '&action=Login'; $arg .= '&action=add'; $arg .= '&level=AR--Sales%20Invoice'; $arg .= '&login=' .$user; $arg .= '&js=1'; $arg .= '&type=invoice'; my $url = $base_url . 'is.pl?' . $arg; print STDERR "\$url is: $url \n"; my $agent = $self->{'mech'}; $agent->get($url); if($agent->success()){ $agent->field('customer', $customer->{'customer_id'}); print STDERR "customer_id is: $customer->{'customer_id'}\n"; $agent->field('employee', $self->{'Cfg'}->{'default'}->{'employee' +}); print STDERR "Employee is: $self->{'Cfg'}->{'default'}->{'employee +'}\n"; # 'Finding Your Center Event Registration--10064'); $agent->field('partnumber_1', $event_id ); print STDERR "As partnumber_1 we will use $event_id\n"; $agent->click_button( name => 'action', value => 'Update' ); if($agent->success()){ print "\$agent reports that invoice was successfully updated\n"; } $agent->click_button( name => 'action', value => 'Post' ); if($agent->success()){ print '\$agent reports that invoice was successfully posted',"\n +"; } # sleep 15; # $agent->click_button( name => 'action', value => 'Post' ); # $agent->click_button( name => 'action', value => 'Post' ); # sleep 15; # $agent->click_button( name => 'action', value => 'Post' ); # $agent->click_button( name => 'action', value => 'Post' ); # sleep 15; # $agent->click_button( name => 'action', value => 'Post' ); } else { croak "Unable to get invoice creation form.\n"; } # print STDERR $agent->content(); open('INVOICE','>','/home/hesco/sb/fyc_registration/invoice.htm +l'); print INVOICE $agent->content(); close(INVOICE); print STDERR "We're about to search_sl_invoice_mech for $customer->{ +'customer_id'} at this point . . . \n"; my @invoice_ids = $self->search_sl_invoice_mech($customer->{'custome +r_id'}); print STDERR "We have search_sl_invoice_mech and found |@invoice_ids +| . . . \n"; # print Dumper($customer); # print STDERR "We're about to retrieve_sl_invoice_mech at this poin +t . . . "; my $inv = $self->retrieve_sl_invoice_mech($customer,$invoice_ids[0]) +; # print STDERR 'We have retrieve_sl_invoice_mech at this point . . + . '; $inv_id = $inv->{'id'} || $invoice_ids[0] || 0; my $amount = $inv->{'amount'} || 0; my $msg = sprintf ("Have now grabbed id: %u for \$%.2f as the new in +voice.\n", $inv_id, $amount); print STDERR $msg; my %invoice = ( id => $inv_id, amount => $amount, pdf_path => "$inv_pdf_path", html_path => "$inv_html_path", ); $self->{'Cfg'}->{'invoices'}->{'latest_invoice'} = \%invoice; return \%invoice; }
My test results are looking like this:

ok 7 - Correctly identified that no invoice id number exists for new c +ustomer. ok 8 - ->search_sl_customer_by_name_mech() found id: 10089 for newly c +reated customer. Now creating new invoice for Testy D Tester. $url is: http://192.168.1.103/sl-test/is.pl?path=bin/mozilla&login=tes +t_user&password=secret&action=Login&action=add&level=AR--Sales%20Invo +ice&login=test_user&js=1&type=invoice customer_id is: Testy D Tester--10089 Employee is: Finding Your Center Event Registration--10064 As partnumber_1 we will use G0002 $agent reports that invoice was successfully updated \$agent reports that invoice was successfully posted We're about to search_sl_invoice_mech for Testy D Tester--10089 at thi +s point . . . We have search_sl_invoice_mech and found || . . . $VAR1 = { 'pdf_path' => '', 'amount' => undef, 'customer' => 'Testy D Tester', 'id' => 0, 'event' => '', 'html_path' => '' }; Have now grabbed id: 0 for $0.00 as the new invoice. <h1>Software error:</h1> <pre>Delete this croak statement to run rest of test script.
The readmore tags hide the subroutine I'm working on now and the output of the test script I'm using to exercise it.

My apologies for not distilling this to something which can run in a local environment. Unless you have SL or LS installed locally, this is not code which can be easily tested. But I'm hoping that someone familiar with either WWW::Mechanize or with the SL / LS code base or both might be able to recognize from this routine something obvious to them which I have overlooked.

If I take the invoice.html file written out by my debugging code, adjust the action tag to give a fully qualified url and then invoke it with lynx to 'Post' it, a new invoice shows up in my accounting backend. But no matter how many times I try to post it using WWW::Mechanize, or sleep between different invocations, nothing seems to work inside the ->create_sl_invoice_mech() method that would look like success.

I'm guessing that I should not have to edit $agent->content() before posting the create invoice form, but perhaps I don't understand enough about how this works.

Any ideas about how to proceed would be geratly appreciated.

-- Hugh

if( $lal && $lol ) { $life++; }

In reply to Integration with SQL-Ledger / LedgerSMB by hesco

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.