#!/usr/bin/perl -w
use strict;

# template for creating new examples
# look for FILL: and... fill appropriately
# update also the POD, which will be used to generate the article

# FILL: XML module(s) to be used
use XML::<module>;

use FindBin qw($Bin);
use lib $Bin;
use wtr2_base;

init_db();

my $DEBUG=0;

# FILL: set to 1 if the module can output an updated invoice, else 0
my $CAN_OUTPUT= 0;

my @files= @ARGV || (<$dir{invoices}/*.xml>);

foreach my $file (@files)
  { #FILL: create the document in $xml (you might need 2 variables actually:
    #      one for the document itself and one for the extracted data
    #      in which case use $doc for the document and $xml for the data
    my $xml= <get the data>;
    
    
    my $errors= check_invoice( $xml);

    if( !@$errors)
      { store_invoice( $xml); }
    else
      { print "ERROR in $file\n  ", join( "\n  ", @$errors), "\n";
        if( $CAN_OUTPUT) 
          { my $rejected_file= rejected( $file);
            print "adding errors in $rejected_file\n" if( $DEBUG);
            add_errors( $doc, $errors);
            output_doc_to_check(  $rejected_file, $doc);
          }
      };
  }

exit;

sub check_invoice
  { my( $xml)= @_;
    my $errors=[];  # array ref, holds the error messages

    # FILL: get the BuyerPartyIdentifier and BuyerOrganisationName data
    check_buyer( <BuyerPartyDetails/BuyerPartyIdentifier>, 
                 <BuyerPartyDetails/BuyerOrganisationName>,
                 $errors
               );

    # FILL: get the OrderIdentifier data
    check_po(    <InvoiceDetails/OrderIdentifier>, $errors);

    # FILL: get the list of rows
    my @rows= <list of rows>;

    reset_default_row_id();
    
    foreach my $row( @rows)
      { # this does not cope well with broken row numbers

        # FILL: get the RowIdentifier data
        my $row_id= <InvoiceRow/RowIdentifier> || default_row_id();
        
        print "checking row $row_id\n" if $DEBUG;

        # FILL: get the quantity data
        check_qtty( $row_id,
                    <InvoiceRow/DeliveredQuantity>, 
                    <InvoiceRow/DeliveredQuantity[@QuantityUnitCode]>, 
                    <InvoiceRow/OrderedQuantity>, 
                    <InvoiceRow/OrderedQuantity[@QuantityUnitCode]>, 
                    $errors
                  );
      }
    
    return $errors;
  }

sub store_invoice
  { my( $xml)= @_;
    # FILL: get the invoice number 
    print "storing invoice <InvoiceDetails/InvoiceNumber>\n";

    # build the various data structures
    my $data;

    # FILL: fill the data

    $data->{invoice} = { number         => <InvoiceDetails/InvoiceNumber>,
                         date           => <InvoiceDetails/InvoiceDate>,
                         po             => <InvoiceDetails/OrderIdentifier>,
                         amount_no_tax  => <InvoiceDetails/InvoiceTotalVatExcludedAmount>,
                         tax            => <InvoiceDetails/InvoiceTotalVatAmount>,
                         amount         => <InvoiceDetails/InvoiceTotalVatIncludedAmount>,
                         payment_status => <InvoiceDetails/PaymentStatusCode>,
                       };

    $data->{seller}  = { identifier      => <SellerPartyDetails/SellerPartyIdentifier>,
                         name            => <SellerPartyDetails/SellerOrganisationName}->{content},
                         tax_code        => <SellerPartyDetails/SellerOrganisationTaxCode}->{content},
                       };

    $data->{address} = { street         => <SellerPartyDetails/SellerPostalAddressDetails/SellerStreetName>,
                         town           => <SellerPartyDetails/SellerPostalAddressDetails/SellerTownName>,
                         zip            => <SellerPartyDetails/SellerPostalAddressDetails/SellerPostCodeIdentifier>,
                         country_code   => <SellerPartyDetails/SellerPostalAddressDetails/CountryCode>,
                         po_box         => <SellerPartyDetails/SellerPostalAddressDetails/SellerPostOfficeBoxIdentifier>,
                       };

    $data->{contact} = { name           => <SellerContactPersonName>,
                         phone          => <SellerCommunicationDetails/SellerPhoneNumberIdentifier>,
                         email          => <SellerCommunicationDetails/SellerEmailaddressIdentifier>,
                       };

    $data->{invoicerow} ||= [];
    reset_default_row_id();

    # FILL: get the list of InvoiceRow
    my @invoicerows= <InvoiceRow>;
    foreach my $invoicerow (@invoicerows)
      { push @{$data->{invoicerow}},
          { row_id        => <InvoiceRow/RowIdentifier> || default_row_id(),
            sku           => <InvoiceRow/ArticleIdentifier>,
            name          => <InvoiceRow/ArticleName>,
            qty           => <InvoiceRow/DeliveredQuantity>,
            qty_unit      => <InvoiceRow/DeliveredQuantity[@QuantityUnitCode]>,
            unit_price    => <InvoiceRow/UnitPriceAmount>,
            amount_no_tax => <InvoiceRow/RowVatExcludedAmount>,
            tax           => <InvoiceRow/RowVatAmount>,
            amount        => <InvoiceRow/RowAmount>,
          }
      }


    store_all( $data);
  }

sub add_errors
  { my( $doc, $error_messages)= @_;

    # FILL: insert the error messages as <error> elements,
    # wrapped in a <errors> element, first child of the document
    my $errors= <insert errors wrapper>;
    foreach my $message (@$error_messages)
      { <insert error message in the document>
      }
    return $doc;
  }

sub output_doc_to_check
  { my( $file, $doc)= @_;
    open( FILE, ">$file") or die "cannot create file to check $file: $!";
    $doc->print( \*FILE);
    close FILE;
  }

__END__

=head1 NAME

wtr2_template_tree

=head1 SYNOPSYS

edit to taste

=head1 DESCRIPTION

A template convenient for tree-oriented processing of the invoices.

It should be used for modules that load the entire XML document in some
in-memory structure, perform the checks and then load the data in the
DB or (if possible, set the $CAN_OUTPUT variable accordingly) output the
document augmented with the error messages as a new XML document.

=head1 AUTHOR

Michel Rodriguez <mirod@xmltwig.com>

=head1 LICENSE

This code is Copyright (c) 2003 Michel Rodriguez. All rights reserved.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

Comments can be sent to mirod@xmltwig.com

=head1 SEE ALSO

wtr2_simple, wtr2_smart, wtr2_twig_simple, wtr2_twig, wtr2_dom, 
wtr2_libxml_dom, wtr2_libxml, wtr2_pyx_simple

Ways to Rome 2 - Kourallinen Dollareita: http://www.xmltwig.com/article/ways_to_rome_2/

