package BookPub::Sale::Report::Royalty::RowmanLittlefield;

use strict;
use Template;
use Data::Dumper;

use lib '/app/tools/common/lib';
use Common::Date;
use Common::Log;
use Common::Client;
use Common::Email;
use Common::DB::ItemCollection;
use Common::DB::Item;
use Common::Util qw(formatFixedPoint);

use lib '/app/tools/bookpub/lib';
use BookPub::DB::Item::BookProduct;
use BookPub::DB::Item::BookContributor;
use BookPub::DB::Item::ClientService;
use BookPub::DB::Item::Period;
use BookPub::DB::Item::Sale;
use BookPub::DB::Item::File;
use BookPub::DB::Item::Service;
use BookPub::Tracker::Service;

use base 'BookPub::Sale::Report::Royalty';

use constant kDB         => Common::DB::Item::kClientDB;
use constant OUTDIR_BASE => '/app/data/sale_report/tmp/';

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;

    $self->_init(@_);

    return $self;
}

sub fileName {
    my ($self) = @_;
    if ( !$self->{_fileName} ) {
        my $period = BookPub::DB::Item::Period->Lookup( period_id => $self->{_periodID} );
        my $periodRef = $period->name();
        $periodRef =~ s/\s+/_/g;
        $periodRef =~ s/\W+//g;
        $periodRef =~ s/__/_/g;
        $periodRef ||= $period->period_id();

        $self->{_fileName} = "RLPG_RoyaltyReport_" . $periodRef . "_Sales.txt";
    }
    return $self->{_fileName};
}

sub returnsFileName {
    my ($self) = @_;
    if ( !$self->{_returnsFileName} ) {
        my $period = BookPub::DB::Item::Period->Lookup( period_id => $self->{_periodID} );
        my $periodRef = $period->name();
        $periodRef =~ s/\s+/_/g;
        $periodRef =~ s/\W+//g;
        $periodRef =~ s/__/_/g;
        $periodRef ||= $period->period_id();

        $self->{_returnsFileName} = "RLPG_RoyaltyReport_" . $periodRef . "_Returns.tsv";
    }
    return $self->{_returnsFileName};
}

sub zipFileName {
    my ($self) = @_;
    if ( !$self->{_zipFileName} ) {
        my $period = BookPub::DB::Item::Period->Lookup( period_id => $self->{_periodID} );
        my $periodRef = $period->name();
        $periodRef =~ s/\s+/_/g;
        $periodRef =~ s/\W+//g;
        $periodRef =~ s/__/_/g;
        $periodRef ||= $period->period_id();

        $self->{_zipFileName} = "RLPG_RoyaltyReport_" . $periodRef . ".zip";
    }
    return $self->{_zipFileName};
}

sub _init {
    my $self = shift;
    my %args = @_;

    $self->SUPER::_init(%args);

    $self->{clientID} = $args{clientID} ? $args{clientID} : Common::RSApp::GetClientID();
    $self->{tmplObj} = Template->new( { START_TAG => '{', END_TAG => '}' } );

}

sub create {
    my $self     = shift;
    my $periodID = $self->periodID();

    # We'll keep a separate tally of units and revenue and
    # return those at the end for validation.
    my $totalUnits;
    my $totalRevenueUnrounded;

    # We're going to have two separate output files,
    # one for sales with positive units and one for sales with negative units
    # (also known as returns).
    #
    # FBoD15552: we're actually extending the "AKA returns" output to include
    # zero units and any revenue. Technically, that makes it more than a returns
    # file, but we'll cross that nomenclature bridge later.
    my %sales;
    my %returns;

    # Going to cache some data so that we don't have to look it up every time.
    my %fileNames;
    my %fileVersions;
    my %fileGenerations;
    my %accountInfo;
    my %productData;

    # And now for the sales
    # We want to do this in some kind of order,
    # so let's get the service list sorted alphabeticaly first.
    my $services = BookPub::DB::Item::Service->GetAllSortedByName();

    while ( $services->hasNext() ) {
        my $service     = $services->next();
        my $serviceID   = $service->service_id;
        my $serviceName = $service->service_name;

        # So we're just going to have to grab all of the sales for a service,
        # and then sort them into buckets based on client service id
        my $sales = BookPub::DB::Item::Sale->GetUnconsolidatedForReport( $periodID, $serviceID );

        while ( my $sale = $sales->next() ) {
            my $fileID = $sale->file_id;
            my $saleID = $sale->sale_id;

            my $units   = $sale->units;
            my $revenue = $sale->revenue;

            # Why do we even have sale records like this...
            if ( $units == 0 && $revenue == 0 ) {
                next;
            }

            my $currencyCode   = $sale->currency_code;
            my $conversionRate = $sale->conversion_rate;

            $revenue *= $conversionRate;

            $totalUnits            += $units;
            $totalRevenueUnrounded += $revenue;

            # We're actually using the isbn13 from the product here.
            my $isbn = $sale->r_isbn13;

            my $listPrice = abs( $sale->list_price );

            # !!! Let's skip this for now.
            # We're going to use the purchase price in place of list price for Amazon only
            #if ($serviceID == 8) {
            #    $listPrice = abs($sale->r_purchase_price);
            #}

            my $listPriceCurrency = $sale->r_list_price_currency;
            if ( !$listPriceCurrency ) {
                $listPriceCurrency = $currencyCode;
            }

            # If it's not USD, let's hope we can convert it.
            if ( $listPriceCurrency ne 'USD' ) {
                if ( $listPriceCurrency eq $currencyCode ) {
                    $listPrice *= $conversionRate;
                } else {

                    # Well, we can't convert this so let's throw an error.
                    my $error = "Unable to convert list price to USD - sale id:" . $saleID;

                    $self->_sendErrorEmail($error);

                    die "Unable to convert list price to USD - sale id: $saleID\n";
                }
            }

            my $price;
            if ($units) {
                $price = abs( $revenue / $units );
            }
            my $discount = 0;

            # This shouldn't happen, but let's check for it just in case.
            if ( ( !$listPrice || $listPrice == 0 ) && $revenue != 0 && $sale->is_free eq 'N' ) {
                my $error = "Missing list price for non-free sale with revenue. Sale ID: $saleID";

                $self->_sendErrorEmail($error);

                die "Missing list price for non-free sale with revenue. Sale ID: $saleID\n";
            }

            # If it's free, then we can just hard code the discount rate.
            if ( $sale->is_free eq 'Y' || $revenue == 0 ) {
                $discount = 1;
            } elsif ( $listPrice && $listPrice != 0 ) {
                my $discountRate = 1 - ( $price / $listPrice );
                $discount = formatFixedPoint( $discountRate, 4 );
            }

            # We only want discount rates with a value between 0 and 1.
            # We also want to do this for Findaway World (renamed to InAudio) because rounding
            # their discount rates is throwing off the revenue. (RSD-9857)
            if ( $discount > 1 ||
                 $discount < 0 ||
                 $serviceID == BookPub::Tracker::Service::IN_AUDIO )
            {
                $discount  = 0;
                $listPrice = $price;
            }

            # Let's trim this to two decimal places now.
            # This line was before the listPrice check, but a very small conversion rate was
            # causing the list price to be 0 after formatting.
            $listPrice = formatFixedPoint( $listPrice, 2 );

            my $fileName;
            my $fileGeneration;
            my $fileVersion;

            if ( $fileNames{$fileID} ) {
                $fileName       = $fileNames{$fileID};
                $fileGeneration = $fileGenerations{$fileID};
                $fileVersion    = $fileVersions{$fileID};
            } else {
                my $file = BookPub::DB::Item::File->Lookup( file_id => $fileID );
                $fileName = $file->orig_file_name;
                $fileName =~ s/_/ /g;
                $fileNames{$fileID}       = $fileName;
                $fileVersion              = $file->version_num;
                $fileVersions{$fileID}    = $fileVersion;
                $fileGeneration           = $file->generation;
                $fileGenerations{$fileID} = $fileGeneration;
            }

            # We have to parse the file name to figure out the purchase order number and
            # the client service ID, so let's do them together.
            my $poNumber;
            my $customerSAN;
            my $receiverID;
            my %sanCriteria;

            # We are starting to see some files that need the PO set at the sale level.
            # In those cases, we will look up the account info every time.
            my $cacheAccountInfo = 1;

            if ( $serviceID == BookPub::Tracker::Service::SCRIBD() && $fileName =~ /ADJ 2015/ ) {
                $cacheAccountInfo = 0;
            }

            if ( $accountInfo{$fileID} && $cacheAccountInfo == 1 ) {
                $poNumber    = $accountInfo{$fileID}->{poNumber};
                $customerSAN = $accountInfo{$fileID}->{customerSAN};
                $receiverID  = $accountInfo{$fileID}->{receiverID};
            } else {
                ( $poNumber, $customerSAN, $receiverID, %sanCriteria ) =
                  $self->_getAccountInfo( $serviceID, $fileName, $sale, $fileGeneration, $fileVersion, $fileID );

                # We don't actually use %sanCriteria here.
                # That's for the validation that happens when a file is uploaded.

                # !!! Let's make sure we got everything back that we need.
                if ( !$poNumber || !$customerSAN || !$receiverID ) {

                    # Otherwise, let's quit here and send out the error email.
                    my $service = BookPub::DB::Item::Service->Lookup( service_id => $serviceID );
                    my $serviceName = $service->service_name;

                    my $error = "Unable to process file '" . $fileName . "' for " . $serviceName . ".\n";

                    if ( !$customerSAN ) {
                        $error .= "SAN missing.\n";
                    }
                    if ( !$poNumber ) {
                        $error .= "PO missing.\n";
                    }
                    if ( !$receiverID ) {
                        $error .= "Receiver ID missing.\n";
                    }

                    $self->_sendErrorEmail($error);

                    die $error;
                }

                # If we did get it all, then great.  Add it to the hash and keep going.
                $accountInfo{$fileID}->{poNumber}    = $poNumber;
                $accountInfo{$fileID}->{customerSAN} = $customerSAN;
                $accountInfo{$fileID}->{receiverID}  = $receiverID;
            }

            if ( $units <= 0 ) {

                # The return output file is in a different format
                # so we need to split off here and gather some data for it.
                my $returnDate  = $sale->date_end;
                my $countryCode = $sale->country_code;

                my $productID = $sale->product_id;
                my $title;
                my $author;
                my $imprintName;

                if ( !$productData{$productID} ) {
                    my $bookProduct = BookPub::DB::Item::BookProduct->Lookup( product_id => $productID );
                    my $bookID      = $bookProduct->book_id;
                    my $book        = BookPub::DB::Item::Book->Lookup( book_id => $bookID );
                    $title = $book->title;

                    $author = BookPub::DB::Item::BookContributor->GetAuthorLastNamesByBookID($bookID);

                    my $imprintID = $bookProduct->imprint_id;
                    my $imprint = BookPub::DB::Item::Imprint->Lookup( imprint_id => $imprintID );
                    $imprintName = $imprint->name;

                    $productData{$productID}->{title}       = $title;
                    $productData{$productID}->{author}      = $author;
                    $productData{$productID}->{imprintName} = $imprintName;
                    $productData{$productID}->{isbn}        = $isbn;
                }

                $returns{$serviceName}{$fileName}{$customerSAN}{$productID}{$listPrice}{$discount}{$returnDate}{$countryCode}{units} +=
                  $units;
                $returns{$serviceName}{$fileName}{$customerSAN}{$productID}{$listPrice}{$discount}{$returnDate}{$countryCode}{revenue} +=
                  $revenue;

            } else {

                # And this is the stuff we only need in the sales output file.
                #
                # Let's go ahead and round off the discount rate now.  Might get a little more consolidation this way.
                $discount = formatFixedPoint( $discount, 2 );
                $sales{$serviceName}{$receiverID}{$customerSAN}{$poNumber}{$isbn}{$discount}{$listPrice}{units} += $units;
            }
        }
    }

    if (%sales) {

        # Okay, let's create the sales output file.
        my $outFilePath = $self->filePath();

        unless ( open( OUT, '>:utf8', $outFilePath ) ) {
            die "can't open output file ($outFilePath) - $!\r\n";
        }

        my $saleGroup = 0;

        my $today = new Common::Date->now();
        my $todaysDate = substr( $today, 0, 4 ) . substr( $today, 5, 2 ) . substr( $today, 8, 2 );

        foreach my $serviceName ( sort keys %sales ) {
            my $serviceSales = $sales{$serviceName};

            foreach my $receiverID ( sort keys %$serviceSales ) {
                my $receiverIDSales = $serviceSales->{$receiverID};

                foreach my $customerSAN ( sort keys %$receiverIDSales ) {
                    my $customerSANsales = $receiverIDSales->{$customerSAN};

                    foreach my $poNumber ( sort keys %$customerSANsales ) {
                        $saleGroup++;
                        print OUT "ISA|00|          |00|          |ZZ|ROYALTYSHARE   |ZZ|"
                          . $receiverID
                          . "     |"
                          . substr( $todaysDate, 2 )
                          . "|1346|U|00400|000000349|0|P|>\r\n";
                        print OUT "GS|PO|ROYALTYSHARE|" . $receiverID . "|" . $todaysDate . "|1346|349|X|004010\r\n";
                        print OUT "ST|850|" . sprintf( "%07d", $saleGroup ) . "\r\n";
                        print OUT "BEG|00|NE|" . $poNumber . "||" . $todaysDate . "\r\n";
                        print OUT "CUR|SE|USD\r\n";
                        print OUT "CSH|O\r\n";
                        print OUT "N1|ST|" . $serviceName . "|15|" . $customerSAN . "\r\n";

                        my $saleCount = 0;
                        my $unitTotal = 0;

                        my $poNumberSales = $customerSANsales->{$poNumber};

                        foreach my $isbn ( sort keys %$poNumberSales ) {
                            my $isbnSales = $poNumberSales->{$isbn};

                            foreach my $discount ( sort keys %$isbnSales ) {
                                my $discountSales = $isbnSales->{$discount};

                                foreach my $listPrice ( sort keys %$discountSales ) {
                                    $saleCount++;
                                    my $row   = $discountSales->{$listPrice};
                                    my $units = $row->{units};
                                    $unitTotal += $units;

                                    print OUT "PO1|"
                                      . sprintf( "%05d", $saleCount ) . "|"
                                      . $units . "|UN|"
                                      . $listPrice . "||EN|"
                                      . $isbn . "\r\n";
                                    print OUT "CTP||||||DIS|" . $discount . "\r\n";

                                }
                            }
                        }

                        print OUT "CTT|" . $saleCount . "|" . $unitTotal . "\r\n";
                        my $rowCount = 7 + ( $saleCount * 2 );
                        print OUT "SE|" . $rowCount . "|" . sprintf( "%07d", $saleGroup ) . "\r\n";
                        print OUT "GE|1|349\r\n";
                        print OUT "IEA|1|000000349\r\n";

                    }
                }
            }
        }

        close(OUT);
    }

    if (%returns) {

        # Okay, let's create the returns output file.
        #Common::Log::Print("In the returns section");
        my $baseDir     = $self->_baseDir();
        my $outFilePath = $baseDir . '/' . $self->returnsFileName();

        if ( -e $outFilePath ) {
            Common::Log::Print("$outFilePath exists, removing it...");
            die "\nCan't remove $outFilePath\n" unless ( unlink $outFilePath );
        }

        unless ( open( OUT, '>:utf8', $outFilePath ) ) {
            die "can't open output file ($outFilePath) - $!\r\n";
        }

        my %tmplVars;
        my %HEADER_MAIN = (
            _order => [
                qw(filename san service isbn title units list_price list_price_currency discount revenue currency author imprint return_date country)
            ],
            filename            => 'FILENAME',
            san                 => 'SAN',
            service             => 'SERVICE',
            isbn                => 'DIGITAL ISBN',
            title               => 'TITLE',
            units               => 'QUANTITY RETURNED',
            list_price          => 'LIST PRICE',
            list_price_currency => 'LIST PRICE CURRENCY',
            discount            => 'DISCOUNT',
            revenue             => 'EXTENDED AMOUNT',
            currency            => 'CURRENCY',
            author              => 'AUTHOR',
            imprint             => 'IMPRINT',
            return_date         => 'Return Date',
            country             => 'Country of Sale',
        );

        # print the main header
        my @headers = @HEADER_MAIN{ @{ $HEADER_MAIN{_order} } };
        print OUT join( "\t", @headers ), "\n";

        foreach my $serviceName ( sort keys %returns ) {
            my $fileNames = $returns{$serviceName};
            foreach my $filename ( sort keys %$fileNames ) {
                my $serviceSales = $returns{$serviceName}{$filename};
                foreach my $san ( sort keys %$serviceSales ) {
                    my $sanSales = $serviceSales->{$san};
                    foreach my $productID ( sort keys %$sanSales ) {
                        my $isbn        = $productData{$productID}->{isbn};
                        my $title       = $productData{$productID}->{title};
                        my $author      = $productData{$productID}->{author};
                        my $imprintName = $productData{$productID}->{imprintName};

                        my $productSales = $sanSales->{$productID};

                        foreach my $listPrice ( sort keys %$productSales ) {
                            my $listPriceSales = $productSales->{$listPrice};

                            foreach my $discount ( sort keys %$listPriceSales ) {
                                my $discountSales = $listPriceSales->{$discount};

                                foreach my $returnDate ( sort keys %$discountSales ) {
                                    my $returnDateSales = $discountSales->{$returnDate};

                                    foreach my $countryCode ( sort keys %$returnDateSales ) {
                                        my $row = $returnDateSales->{$countryCode};

                                        # san service isbn title units list_price discount revenue
                                        # author imprint return_date country

                                        $tmplVars{filename}            = $filename;
                                        $tmplVars{san}                 = $san;
                                        $tmplVars{service}             = $serviceName;
                                        $tmplVars{isbn}                = $isbn;
                                        $tmplVars{title}               = $title;
                                        $tmplVars{units}               = abs( $row->{units} );
                                        $tmplVars{list_price}          = $listPrice;
                                        $tmplVars{list_price_currency} = 'USD';
                                        $tmplVars{discount}            = $discount * 100;

                                        # FBoD1552: we were ABSing revenue, but we should simply report the facts
                                        $tmplVars{revenue} = formatFixedPoint( $row->{revenue}, 2 );
                                        $tmplVars{currency} = 'USD', $tmplVars{author} = $author;
                                        $tmplVars{imprint} = $imprintName;
                                        $tmplVars{return_date} = $returnDate;
                                        $tmplVars{country}     = $countryCode;

                                        my @detailRow = @tmplVars{ @{ $HEADER_MAIN{_order} } };
                                        print OUT join( "\t", @detailRow ), "\n";
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        close(OUT);
        Common::Log::Print("Report created: $outFilePath");
    }

    # Going to send everything back in a hash so that it's
    # easy to add more stuff in later.
    #
    my %returnValues;
    $returnValues{totalUnits}            = $totalUnits;
    $returnValues{totalRevenueUnrounded} = $totalRevenueUnrounded;

    return (%returnValues);

}

sub _getAccountInfo {
    my ( $self, $serviceID, $fileName, $sale, $fileGeneration, $fileVersion, $fileID ) = @_;

    # !!! Note that underscores have been replaced with spaces in the file names, to simplify the regexes.

    # !!! Also note, if we're calling this from the validateFile function below, we won't have an actual sale record.
    # We'll be passing the string "IGNORE" in that variable, since we don't have any failure conditions
    # associated with sale data.

    my %monthNames = (
        "january"   => "01",
        "jan"       => "01",
        "february"  => "02",
        "feb"       => "02",
        "march"     => "03",
        "mar"       => "03",
        "april"     => "04",
        "apr"       => "04",
        "may"       => "05",
        "june"      => "06",
        "jun"       => "06",
        "july"      => "07",
        "jul"       => "07",
        "august"    => "08",
        "aug"       => "08",
        "september" => "09",
        "sep"       => "09",
        "sept"      => "09",
        "october"   => "10",
        "oct"       => "10",
        "november"  => "11",
        "nov"       => "11",
        "december"  => "12",
        "dec"       => "12",
    );

    my %quarterNames = (
        "spring" => "1",
        "summer" => "2",
        "fall"   => "3",
        "autumn" => "3",
        "winter" => "4",
    );

    # Time to parse the file name.
    #
    my ( $poNumber, $clientService, $receiver, $year, $quarter, $month, $day, $feedID, $countryCode, %sanCriteria );

    # !!! Quick note about %sanCriteria
    # We need to pass along all of the fields (and their values) that are used to pick a SAN for a service.
    # This is used to validate files as they are imported and provide feedback.
    # Also, there's no need to include service as one of the criteria here as that's assumed.

    if ( $serviceID == BookPub::Tracker::Service::AMAZON() ) {
        if (   $fileName =~ /(\d{4})(\d{2})01-\d{8}/
            || $fileName =~ /\d{8}-(\d{4})(\d{2})(2[89]|3[01])/ ) {
            $year  = $1;
            $month = $2;
        } elsif ( $fileName =~ / (\d{2}) (\d{4})/ ) {
            $month = $1;
            $year  = $2;
        }

        # And now to grab the feed id and country code
        if ( $fileName =~ /^(\w{5}) / ) {
            $feedID = $1;
        }

        if ( $fileName =~ /^\w{5}[ _](?!digi)(\w\w)/i || $fileName =~ /^\w{5}[ _]digi.+?(\w\w)(?:\.|[ _]\1)/i) {
            $countryCode = $1;
        } elsif ( $fileName =~ /^Alban Amazon (\w{2}) /i ) {
            $countryCode = $1;
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Feed ID'}      = $feedID;
        $sanCriteria{'Country Code'} = $countryCode;

        if ( $year && $month && $feedID ) {
            $poNumber = $feedID . "_" . $month . "_" . $year;
            if ( $feedID =~ /^RWSQQ/ ) {
                $poNumber .= "_" . $countryCode;
            }
        }

        if ( $feedID =~ /^NB/ || $feedID =~ /^AU/ || $feedID =~ /^AF/ || $feedID =~ /^SO/ ) {
            $receiver = 'nbn';
        } elsif ( $feedID =~ /^RW/ || $feedID =~ /Alban/i || $feedID =~ /^GO/ || $feedID =~ /^GP/ ) {
            $receiver = 'rlpg';
        }

        # We want to treat these Alban and Globe sales just like RW sales from here on out.
        if ( $feedID =~ /Alban/i || $feedID =~ /^GO/i || $feedID =~ /^GP/i ) {
            $feedID = 'RW';
        }

        if ( $feedID && $countryCode ) {
            if ( $feedID =~ /RWSQQ/ ) {
                $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );

            } else {

                # Taking some steps to simplify looking up the SANs.
                $feedID = substr( $feedID, 0, 2 );
                if ( $feedID eq 'AU' || $feedID eq 'AF' || $feedID eq 'SO' ) {
                    $feedID = 'NB';
                }
                if ( $countryCode eq 'GB' ) {
                    $countryCode = 'UK';
                }
                $feedID .= "_" . $countryCode;
                $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );
            }
        }

    } elsif ( $serviceID == BookPub::Tracker::Service::AMIGOS() ) {
        if ( $fileName =~ /(\d{4})-(\d{2})-(\d{2})[_ ]to[_ ](\d{4})-(\d{2})-(\d{2})/ ) {
            $year = $1;
            my $monthFrom = $2;
            my $monthTo   = $5;

            if ( $monthFrom == $monthTo ) {
                $poNumber = $month . "_" . $year;
            } elsif ( $monthTo % 3 == 0 ) {
                $poNumber = 'Q' . $monthTo / 3 . '_' . $year;
            }
        } elsif ( $fileName =~ /(\d{4})-(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /ESH015A/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /ESH015/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::APPLE() ) {

        # Grab the feed ID
        if ( $fileName =~ /(\d{8}) / ) {
            $feedID = $1;
        } elsif ( $fileName =~ /(Alban) Apple/i ) {
            $feedID = $1;
        }

        # Grab the date
        if ( $fileName =~ / (\d{2})(\d{2}) / ) {
            $month = $1;
            $year  = '20' . $2;
        } elsif ( $fileName =~ / (\d{2}) (\d{4})\./ ) {
            $month = $1;
            $year  = $2;
        }

        # Grab the country code
        if ( $fileName =~ / (\w{2})(?:[ _]WHT)?\./ ) {
            $countryCode = $1;
        } elsif ( $fileName =~ /Alban Apple (\w{2}) /i ) {
            $countryCode = $1;
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Feed ID'}      = $feedID;
        $sanCriteria{'Country Code'} = $countryCode;

        if ( $feedID eq '85107241' || $feedID eq '85609576' ) {
            $receiver = 'nbn';
        } elsif ( $feedID eq '85107299' || $feedID eq '85728109' || $feedID eq '93258348' || $feedID =~ /Alban/i ) {
            $receiver = 'rlpg';
        }

        if ( $year && $month && $feedID && $countryCode ) {
            if ( $feedID eq '85609576' ) {
                if ( $countryCode eq 'JP' ) {
                    $poNumber = $month . "_" . $year . "_" . $countryCode . "_SKO";

                } else {
                    $poNumber = $month . "_" . $year . "_SKO";
                }
            } else {
                $poNumber = $feedID . "_" . $month . "_" . $year;
            }
            if ( $feedID =~ /Alban/i ) {
                $feedID = "85107299";
            }

            $feedID .= "_" . $countryCode;

            # Going to eventually do this for all Apple POs...
            if ( $feedID eq '85107241_BR' && $fileName =~ /[ _]WHT\./ ) {
                $poNumber = $month . "_" . $year . "_" . $countryCode . "_WHT";
            } elsif (
                   $feedID eq '85107299_CL'
                || $feedID eq '85107241_RO'
                || $feedID eq '85107241_CO'
                || $feedID eq '85107241_PL'
                || $feedID eq '85107241_HU'
                || $feedID eq '85107241_SE'
                || $feedID eq '85107241_CL'
                || $feedID eq '85107241_MX'
                || $feedID eq '85107299_BG'
                || $feedID eq '85107299_CZ'
                || $feedID eq '85107299_HU'
                || $feedID eq '85107299_PL'
                || $feedID eq '85107299_RO'
                || $feedID eq '85107241_CZ'
                || $feedID eq '85107241_PE'
                || $feedID eq '85107241_BG'
                || $feedID eq '85107299_CO'
                || $feedID eq '85107241_NO'
                || $feedID eq '85107241_LL'
                || $feedID eq '85107241_DK'
                || $feedID eq '85107299_DK'
                || $feedID eq '85107299_LL'
                || $feedID eq '85107299_SE'
                || $feedID eq '85107241_BR'
            ) {
                $poNumber = $month . "_" . $year . "_" . $countryCode;
            } elsif (
                   $feedID eq '93258348_BR'
                || $feedID eq '93258348_CA'
                || $feedID eq '93258348_EU'
                || $feedID eq '93258348_GB'
                || $feedID eq '93258348_LL'
                || $feedID eq '93258348_US'
            ) {
                $poNumber = substr($feedID, 0, -3) . "_" . $month . "_" . $year . "_" . $countryCode;
            }
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );
        }

    } elsif ( $serviceID == BookPub::Tracker::Service::BAKERANDTAYLOR() ) {
        if ( $fileName =~ /(\d{2})-(\d{2})\./ ) {
            $year  = $2;
            $month = $1;

            $poNumber = $month . "_20" . $year;
        }

        if ( $fileName =~ /^(\w+) / ) {
            if ( $1 eq 'NATL' ) {
                $receiver = 'nbn';
            } elsif ( $1 eq 'ROWMAN' ) {
                $receiver = 'rlpg';
            } elsif ( $1 eq 'GLOBE' ) {
                $receiver = 'rlpg';
                if ($poNumber) {
                    $poNumber = "GPQ_" . $poNumber;
                }
            }
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::BARNES_NOBLE() ) {
        if ( $fileName =~ /eBook Pay (\d{2})(\d{2})(\d{2})/i ) {
            $year     = "20" . $3;
            $month    = $1;
            $day      = $2;
            $poNumber = $month . "_" . $day . "_" . $year;
        } elsif ( $fileName =~ /(\d{4})(\d{2})\d{2}/ ) {
            $year     = $1;
            $month    = $2;
            $poNumber = $month . "_" . $year;
            if (
                $fileName =~ /^NBN B\&N Sales Report export 20160201 20160229/ ||    # FB14994
                $fileName =~ /^NBN B\&N Sales Report export 20160301 20160331/
              ) {
                $poNumber = $poNumber . "_SKO";
            }
        } elsif ( $fileName =~ / (\d{2}) (\d{4})/ ) {
            $month    = $1;
            $year     = $2;
            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /^Alban/i ) {
            $poNumber = "Alban_" . $poNumber;
        }

        if ( ( $fileName =~ /^NBN/i ) || ( $fileName =~ /051900/ ) ) {
            $receiver = 'nbn';
        } elsif ( ( $fileName =~ /^RLPG/i ) || ( $fileName =~ /^Alban/i ) || ( $fileName =~ /071228/ ) ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::BOOKSHOUT() ) {
        if ( $fileName =~ /(\d{4})(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;

            if ( $fileName =~ /SpecialSales/i ) {
                $poNumber .= "_SPECSALE";
            }
        }

        if ( $fileName =~ /NTNL/i || $fileName =~ /NBN/i || $fileName =~ /NATIONALBOOKNETWORK/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /RWMN/i || $fileName =~ /RLPG/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::CALIFA() ) {
        if ( $fileName =~ /^CALIFA.(\d{2}.\d{2}-\d+)/ ) {
            $poNumber = $1;
            $poNumber =~ s/_/ /g;
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        # Receiver is hard coded for this one, but just to be consistent I'll go ahead and set this.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::CHEGG() ) {
        if ( $fileName =~ /^(\d{4})-(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /NBN/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        $poNumber .= "_SUB" if ( $fileName =~ /Subscription/i );

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::CNPEREADING() ) {
        if ( $fileName =~ /^(\w+)\.(\d{4})/ ) {
            $year = $2;
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $year;
            }
        }

        if ( $fileName =~ /NBN/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::CORBAN_UNIVERSITY() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})\./ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        $receiver = 'nbn';

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::COURSE_SMART() ) {
        if ( $fileName =~ /(\d{4}).*trueup/i ) {
            $year = $1;

            $poNumber = $year . "-TrueUp";
        } elsif ( $fileName =~ /(\d{4})(\d{2}) \d{6}/ ) {
            $year  = $1;
            $month = $2;

            # We actually want to display the quarter for this one, so let's convert it.
            $quarter  = ( $month + 2 ) / 3;
            $poNumber = "Q" . $quarter . "_" . $year;

        } elsif ( $fileName =~ /(\d{4})(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            my $countryCode;
            if ( $sale->country_code ) {
                $countryCode = $sale->country_code;
            }
            $poNumber = $month . "_" . $year . "_" . $countryCode;

        } elsif ( $fileName =~ /(\d{4})Q(\d{1})/ ) {
            $year    = $1;
            $quarter = $2;

            $poNumber = "Q" . $quarter . "_" . $year;
        }

        if ($poNumber) {
            if ( $fileName =~ /enrollment/i ) {
                $poNumber .= "_ENROLL";
            }
            if ( $fileName =~ /SUB\./i ) {
                $poNumber .= "_SUB";
            }
        }

        if ( $fileName =~ /SUB\./i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /NBN/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i || $fileName =~ /RLPG/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::COURSELOAD() ) {
        if ( $fileName =~ /(\d{4}).?(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::CREDO() ) {
        if ( $fileName =~ / (\d{4}) (Q\d)/ ) {
            $year    = $1;
            $quarter = $2;

            $poNumber = $quarter . "_" . $year;
        }

        $receiver = 'rlpg';

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::DAWSON_BOOKS() ) {
        if ( $fileName =~ /(\d{4}).?(\d{2})\./ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ / USD / ) {
            $poNumber .= '_USD';
        }

        if ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /National/i || $fileName =~ /N\.B\.N/i ) {
            $receiver = 'nbn';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::DOUGLAS_COUNTY_LIBRARY() ) {
        if ( $fileName =~ /Douglas County Library (.*) (\d{4}) (\d{2})/ ) {
            $poNumber = $1;
            $year     = $2;
            $month    = $3;

            $poNumber .= "_" . $month . "_" . $year;
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::EBOOK() ) {
        if ( $fileName =~ /^(\w{3})-(\d{4})-(\d{2})/ ) {
            $year  = $2;
            $month = $3;

            # We actually want to display the quarter for this one, so let's convert it.
            $quarter = ( $month + 2 ) / 3;

            $poNumber = uc($1) . "_Q" . $quarter . "_" . $year;
        } elsif ( $fileName =~ /(\w{3})SalesReport-(\d{4})-(\d{2})-\d{2}-\d{4}-\d{2}-\d{2}\./ ) {
            $year  = $2;
            $month = $3;

            # We actually want to display the quarter for this one, so let's convert it.
            $quarter = ( $month + 2 ) / 3;

            $poNumber = uc($1) . "_Q" . $quarter . "_" . $year;
        } elsif ( $fileName =~ /SalesReport-Wholesale-(\w{3})-(\d{4})-(\d{2})-\d{2}-\d{4}-\d{2}-\d{2}\./ ) {
            $year  = $2;
            $month = $3;

            # We actually want to display the quarter for this one, so let's convert it.
            $quarter = int(($month + 2 ) / 3);

            $poNumber = "Q".$quarter . "_" . $year . "_" . uc($1);
            $countryCode = $1;
        }

        # Just setting this to NBN for all files.
        $receiver = 'nbn';

        $feedID = $receiver . "_ebl";
        $feedID = $receiver . "_ebc" if $countryCode eq "CAD";

        # check to see if this is the AttaFace pass, the sale object will be set to string
        # value 'IGNORE'
        if ( $sale ne 'IGNORE' ) {
            if ( $sale->format_type && $sale->format_type eq BookPub::DB::Item::Sale::kFormatTypeEBL ) {
                $feedID = $receiver . "_ebl";
            } else {
                $feedID = $receiver . "_ebc";
            }
        }

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Feed ID'} = $feedID;

    } elsif ( $serviceID == BookPub::Tracker::Service::EBRARY() ) {
        if ( $fileName =~ /ebrary/i ) {
            if ( $fileName =~ /(\d{4}) (\d{2})-(\d{4}) (\d{2})/ ) {
                my $yearStart    = $1 - 2000;
                my $monthStart   = int($2);
                my $yearEnd      = $3 - 2000;
                my $monthEnd     = int($4);
                my $quarterStart = int( ( $monthStart + 2 ) / 3 );
                my $quarterEnd   = int( ( $monthEnd + 2 ) / 3 );

                $poNumber = "Q" . $quarterStart . $yearStart . " Q" . $quarterEnd . $yearEnd;
            } elsif ( $fileName =~ /Q(\d)(\d{2}) Q(\d)(\d{2})/i ) {
                my $quarterStart = $1;
                my $yearStart    = $2;
                my $quarterEnd   = $3;
                my $yearEnd      = $4;

                $poNumber = "Q" . $quarterStart . $yearStart . " Q" . $quarterEnd . $yearEnd;
            }
            if ( $poNumber && $fileName =~ /true.*up/i ) {
                $receiver = 'rlpg';
                $poNumber .= ' TRUE UP';
            }
        } elsif ( $fileName =~ /Q(\d)-(\d{4})/ ) {
            $quarter = $1;
            $year    = $2;

            $poNumber = "Q" . $quarter . "_" . $year;
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
            if ( $fileName =~ /Subscription/i ) {
                $poNumber .= '_SUB';
            }
        } elsif ( $fileName =~ /Bernan/i ) {
            $receiver = 'rlpg';
            if ( $fileName =~ /Subscription/i ) {
                $poNumber .= '_BP_SUB';
            } elsif ( $fileName =~ /Corporate/i ) {
                $poNumber .= '_BP_CORP';
            }
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
            if ( $fileName =~ /Subscription/i ) {
                $poNumber .= '_RL_SUB';
            }
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::PROQUEST_SUBSCRIPTION() ) {
        if ( $fileName =~ /(\d{4})-Q(\d)/ ) {
            $quarter = $2;
            $year    = $1;
        } elsif ( $fileName =~ /Q(\d)-(\d{4})/ ) {
            $quarter = $1;
            $year    = $2;
        }
        $poNumber = "Q" . $quarter . "_" . $year . "_SUB";

        $receiver = 'nbn'  if $fileName =~ /10973|2742|10501/i;

        if ( $receiver ) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
            $sanCriteria{'Receiver'} = $receiver;
        }
    } elsif ( $serviceID == BookPub::Tracker::Service::EBSCO() ) {
        my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);

        if ( ( $reportingMonth || $reportingQuarter ) && $reportingYear ) {
            if ($reportingMonth) {
                $poNumber = $reportingMonth . "_" . $reportingYear;
            } else {

                $reportingQuarter = substr( $reportingQuarter, 1 );
                $poNumber = "Q" . $reportingQuarter . "_" . $reportingYear;
            }

            if ( $fileName =~ /perpetual/i ) {
                $poNumber .= "_PER";
            } elsif ( $fileName =~ /stackpole/i ) {
                $poNumber .= "_SKO";
            } elsif ( $fileName =~ /subscription/i ) {
                $poNumber .= "_SUB";
            } elsif ( $fileName =~ /freud/i ) {
                $poNumber .= "_FREUD";
            }
        }

        if ( $fileName =~ /^National/i || $fileName =~ /^Stackpole/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /^Rowman/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::FAITHLIFE() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})/ ) {
            $year  = $1;
            $month = $2;
        } elsif ( $fileName =~ /(\w{3,9}) (\d{4})/ ) {
            $year  = $2;
            $month = $monthNames{lc $1};
        }

        if ( $year && $month ) {
            $poNumber = $month . "_" . $year;
        }

        # Only aware of the RLPG version right now.
        $receiver = 'rlpg';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::IN_AUDIO() ) {

        my $name = 'InAudio NBN';
        if ( $fileName =~ /Rowman Littlefield/i && $fileName =~ /(\d{4})-(\d{1,2})/ ) {
            my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);
            $poNumber = $reportingMonth . '_' . $reportingYear . '_AUDIO_SALE';
            $name .= ' audio sales';
        } elsif ( $fileName =~ /(\d{4})Q(\d)/ ) {
            ($year, $quarter) = ($1, $2);
            $poNumber = "Q" . $quarter . "_" . $year;
        } elsif ( $fileName =~ /Q(\d) (\d{4})/ ) {
            ($year, $quarter) = ($2, $1);
            $poNumber = "Q" . $quarter . "_" . $year;
        }

        # Only aware of the NBN version right now.
        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup(
            service_id => $serviceID,
            feed_id    => $receiver,
            name       => $name
        );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::FOLLETT() ) {
        if ( $fileName =~ /(\d{4})(\d{2})\d{2} \d+\./ ) {

            $year     = $1;
            $month    = $2;
            $poNumber = $month . "_" . $year;

        } elsif ( $fileName =~ / (\w+) (\d{4})\./ || $fileName =~ / (\w+) (\d{4}) \d{5}\./ ) {

            $year = $2;
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $year;
            }

        } elsif ( $fileName =~ / (\d{4}) (\w+)\./ ) {

            $year = $1;
            my $monthName = lc($2);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $year;
            }
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman|GLOBE/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::FOLLETT_HIGHER_EDUCATION() ) {
        if ( $fileName =~ /(FMS) (\d{4}) (\d{2})\./i ) {
            $year  = $2;
            $month = $3;

            $poNumber = uc($1) . "_" . $month . "_" . $year;
            $receiver = 'nbn';
        } elsif ( $fileName =~ /NAT BOOK .+ Sales (\d{4}) (\d{2})(?!\d)/i ) {
            $year  = $1;
            $month = $2;

            $poNumber = $2 . '_' . $1 . '_FMS_NBN';
            $receiver = 'nbn';
        } elsif ( $fileName =~ /(?:Rowman|Globe) .+ Sales (?:FollettAccess |Standard )?(\d{4}) (\d{2})(?!\d)/i ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . '_' . $year . '_FMS';
            $poNumber = $month . '_' . $year . '_FMSACCESS' if ($fileName =~ /FollettAccess/);
            $receiver = 'nbn';
        }

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::CAMPUS_EBOOKSTORE() ) {
        if ( $fileName =~ /(?:eBookstore|StartDate).(\d{4}).?(\d{2})/i ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year . " SALES";
            $receiver = 'rlpg';
        }

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID );
    } elsif ( $serviceID == BookPub::Tracker::Service::GARDNERS() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})\./ ) {
            $year  = $1;
            $month = $2;
        } elsif ( $fileName =~ /^\w{2}(\d{2})(\d{4})/ ) {
            $year  = $2;
            $month = $1;
        } elsif ( $fileName =~ /E (\d{2})(\d{4})/ ) {
            $year  = $2;
            $month = $1;
        } elsif ( $fileName =~ / (\w+)(\d{2})(?: \(\d\))?\./ ) {
            $year  = "20" . $2;
            $month = $monthNames{ lc($1) };
        }

        if ( $year && $month ) {
            if ($fileName =~ /^GardnersBooks.Libri.ROW(M|L)1E/i ) {
                $poNumber = "ROW".$1."1E_$month"."_".$year."_L";
            }
            else {
                $poNumber = $month . "_" . $year;
            }
        }

        # Need to add something to the PO to help the client
        # distinguish between the files.
        if ( $fileName =~ /EBNBNP1E/i ) {
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = "NBN_" . $poNumber;
            }
        } elsif ( $fileName =~ /VLNBNP1E/i ) {
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = "NBNVL_" . $poNumber;
            }
        } elsif ( $fileName =~ /NBNP2E/i ) {
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = "NBNVL2_" . $poNumber;
            }
        } elsif ( $fileName =~ /EMNBRO0E/i ) {    #FB15214
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = "EMNBRO0E_" . $poNumber;
            }
        } elsif ( $fileName =~ /EBROWM1E/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "ROW1_" . $poNumber;
            }
        } elsif ( $fileName =~ /EBROWM2E/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "ROW2_" . $poNumber;
            }
        } elsif ( $fileName =~ /VLROWM1E/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "ROWVL1_" . $poNumber;
            }
        } elsif ( $fileName =~ /VLROWM2E/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "ROWVL2_" . $poNumber;
            }
        } elsif ( $fileName =~ /Bookmate (NBNP1E)/i ) {
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = $1 . '_' . $poNumber . '_B';
            }
        } elsif ( $fileName =~ /Sainsburys (NBNP1E)/i ) {
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = $1 . '_' . $poNumber . '_S';
            }
        } elsif ( $fileName =~ /CNPeReading (NBNP1E)/i ) {
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = $1 . '_' . $poNumber . '_C';
            }
        } elsif ( $fileName =~ /GardnersBooks Libri NBNP1E (\w+?)(\d{2})/i ) {
            $receiver = 'nbn';
            if ($poNumber) {
                $poNumber = 'NBNP1E_' . $monthNames{lc($1)} . '_20' . $2 . '_L';
            }
        } elsif ( $fileName =~ /(?<!Libri) ROWM1E /i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "ROWM1E_" . $poNumber . "_B";
            }
        } elsif ( $fileName =~ /Sainsburys (ROWM1E)/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = $1 . '_' . $poNumber . '_S';
            }
        } elsif ( $fileName =~ /EM(ROWM0E).\d+/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = $1 . '_' . $poNumber;
            }

            # I guess we'll keep the code below for legacy files.
            # Note that we aren't adding anything to the PO in the following cases.
        } elsif ( $fileName =~ /NBN/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /ROW/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::GOOGLE() ) {
        if ( $fileName =~ / (\w+) (\d{4})\./ ) {
            $year = $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $year;
            }

            if ( $fileName =~ /C&T.?Publishing/i ) {
                $poNumber .= "_CT";
            } elsif ( $fileName =~ /Monsoon.?Publishing/i ) {
                $poNumber .= "_MON";
            } elsif ( $fileName =~ /Start.?Publishing/i ) {
                $poNumber .= "_STA";
            } elsif ( $fileName =~ /Brewers.?Publishing/i ) {
                $poNumber .= "_BRE";
            } elsif ( $fileName =~ /JohnHunt.?Publishing/i ) {
                $poNumber .= "_JOH";
            } elsif ( $fileName =~ /Michelin/i ) {
                $poNumber .= "_MICH";
            } elsif ( $fileName =~ /GarretCounty.?Press/i ) {
                $poNumber .= "_GCP";
            } elsif ( $fileName =~ /Stackpole/i ) {
                $poNumber .= "_STACK";
            } elsif ( $fileName =~ /FelonyandMayhem.?Press/i ) {
                $poNumber .= "_FEL";
            } elsif ( $fileName =~ /Blue Dome/i ) {
                $poNumber .= "_BLUE";
            } elsif ( $fileName =~ /Lake Isle Press/i ) {
                $poNumber .= "_LAKE";
            } elsif ( $fileName =~ /Living Miracles Publications/i ) {
                $poNumber .= "_LIV";
            } elsif ( $fileName =~ /Bard Press/i ) {
                $poNumber .= "_BRD";
            } elsif ( $fileName =~ /New in Chess/i ) {
                $poNumber .= "_NIC";
            } elsif ( $fileName =~ /Morris Communications Corp/i ) {
                $poNumber .= "_MOR";
            } elsif ( $fileName =~ /Cleis Press/i ) {
                $poNumber .= "_CLEIS";
            } elsif ( $fileName =~ /IT.Revolution/i ) {
                $poNumber .= "_ITR";
            } elsif ( $fileName =~ /Coolidge.Press-Google/i ) {
                $poNumber .= "_COOL";
            }
        }

        if ( $fileName =~ /^RLPG/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /^GPQ/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "GPQ_" . $poNumber;
            }
        } else {
            $receiver = 'nbn';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::IGROUP() ) {
        if ( $fileName =~ /(\w{3})(\d{2})-\w{3}\d{2}\./ ) {
            $year = $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $quarter  = ( $month + 2 ) / 3;
                $poNumber = "Q" . $quarter . "_20" . $year;
            }
        }

        if ( $fileName =~ /^Rowman/i || $fileName =~ /^RLPG/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /National/i || $fileName =~ /NBN/ ) {
            $receiver = 'nbn';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::INGRAM_DIGITAL() ) {
        if ( $fileName =~ /(Q\d)(\d{2})/ ) {
            $quarter = $1;
            $year    = $2;

            $poNumber = $quarter . "_20" . $year;
        } elsif ( $fileName =~ /\.(\w{3})(\d{2})\./ ) {
            $year = $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_20" . $year;
            }
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i || $fileName =~ /Bernan/i ) {
            $receiver = 'rlpg';

            if ($poNumber) {
                if ( $fileName =~ /Bernan/i ) {
                    $poNumber .= "_BRP";
                } else {
                    $poNumber .= "_RLP";
                }
            }
        }

        if ( $fileName =~ /\.(\w{5})\.xls/ ) {
            $feedID = $1;
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Feed ID'}  = $feedID;
        $sanCriteria{'Receiver'} = $receiver;

        if ( $receiver && $feedID ) {
            $feedID = $receiver . "_" . $feedID;
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );
        }

    } elsif ( $serviceID == BookPub::Tracker::Service::INKLING() ) {
        if ( $fileName =~ / (\w+) (\d{4})/ ) {
            $year = $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_" . $year;
            }
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::KOBO() ) {
        if ( $fileName =~ /(\w+) (\d{4})\./ ) {
            $year = $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_" . $year;
                if ( $fileName =~ /stackpole/i ) {
                    $poNumber .= "_SKO";
                } elsif ( $fileName =~ /ROWMAN ACADEMIC/i ) {
                    $poNumber .= "_AC";
                } elsif ( $fileName =~ /ROWMAN TRADE/i ) {
                    $poNumber .= "_TR";
                }
            }
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /Globe/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "GPQ_" . $poNumber;
            }
        } elsif ( $fileName =~ /Stackpole/i ) {
            $receiver = 'nbn';
        }

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::KORTEXT() ) {
        if ( $fileName =~ /\b(\w{3}) (\d{2})\b/ ) {
            $year = "20" . $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_" . $year;
            }
        } else {
            my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);
            if ( $reportingMonth && $reportingYear ) {
                if ($fileName =~ /Q(\d) \d{4}\./) {
                    $poNumber = "Q$1". "_" . $reportingYear;
                }
                else {
                    $poNumber = $reportingMonth . "_" . $reportingYear;
                }
            }
        }

        $receiver = 'rlpg';
        $receiver = 'nbn' if $fileName =~ /^NBN Fusion - \w{5}/i;

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::KOORONG() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /National Book Network/i || $fileName =~ /NBN/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::LIBRARY_IDEAS() ) {
        if ( $fileName =~ /(\d{4})-(\d{2})-01/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year . "_SALES";
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::LSI() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})\./ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;

            if ( $fileName =~ / (\w{2})\w \d{4} \d{2}/i ) {
                $poNumber .= "_$1";
            }

            if ( $fileName =~ /6030175/ ) {
                $poNumber = "SKO__" . $poNumber;
            }

            if ( $fileName =~ / Agency /i ) {
                $poNumber .= "_AGCY";
            }

            if ( $fileName =~ /Pineapple[_ ]Press[ _]eBook[_ ]Wholesale/i ) {
                $poNumber = $month . "_" . $year . "_PP_WHLS";
            } elsif ( $fileName =~ /Pineapple[_ ]Press[ _]eBook[_ ]Agency/i ) {
                $poNumber = $month . "_" . $year . "_PP_AGCY";
            }
        }

        if ( $fileName =~ /NBN/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /RLPG/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /GPQ/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "GPQ_" . $poNumber;
            }
        } elsif ( $fileName =~ /Pineapple Press/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::MACKIN() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /^National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /^RLPG/i || $fileName =~ /^Rowman/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::MBS_TEX() ) {
        if ( $fileName =~ /([A-Za-z]+).?(\d{4})\./ ) {    # monthname followed by single char followed by YYYY
            $year = $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_" . $year;
            }
        }

        $feedID   = 'nbn & rlpg';
        $receiver = 'nbn';          # We'll just set up the receiver separately so that we can keep that in the SAN table.

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Feed ID'} = $feedID;

    } elsif ( $serviceID == BookPub::Tracker::Service::MULTNOMAH_UNIVERSITY() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        $receiver = 'nbn';

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::NYU() ) {
        if ( $fileName =~ /(\d{4}) (\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        $receiver = 'rlpg';

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::ODILO() ) {
        if ( $fileName =~ /(\d{4})[_\s](\d{2})/ ) {
            $poNumber = $2 . "_" . $1;
        } elsif ( $fileName =~ /(\d{4})[_\s](\w+)[-\.]/ ) {
            my $monthName = lc($2);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $1;
            }
        } elsif ( $fileName =~ /(\w+) Report (\d{4})/i ) {
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $2;
            }
        # RE_Month_YYYY_NBN/RLPG_PPA/LICENSES
        } elsif ( $fileName =~ /^RE[_\s](\w+)[_\s](\d{4})[_\s]\w{3,4}[_\s](PP[UA]|Licenses)/i ) {
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $2;
                my $prefix = $3;
                $poNumber .= "_" . $prefix if $prefix =~ /PP[UA]/;
            }
        # RE_Month_YYYY_RLPG_Textbooks_PPA/Licenses
        } elsif ( $fileName =~ /^RE[_\s](\w+)[_\s](\d{4})[_\s]RLPG[_\s]Textbooks[_\s](PPA|Licenses)/i ) {
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $poNumber = $monthNames{$monthName} . "_" . $2 . "_TXT";
                $poNumber .= "P" if $3 =~ /PPA/;
            }
        }

        if ( $fileName =~ /^NBN/i || $fileName =~ /[_\s]NBN[_\s](?:PP[UA]|Licenses)[_\s.]/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /^RLPG/i || $fileName =~ /[_\s]RLPG[_\s](?:PP[UA][_.\s]|(?:Textbooks[_\s])?(?:Licenses|PPA))/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::OVERDRIVE() ) {
        if ( $fileName =~ /(\d{4})(\d{2})(\d{2})\./ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /^NBN/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /^RLPG/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /^GPQ/i ) {
            $receiver = 'rlpg';
            if ($poNumber) {
                $poNumber = "GPQ_" . $poNumber;
            }
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::OYSTER() ) {
        my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);

        if ( $reportingMonth && $reportingYear ) {
            $poNumber = $reportingMonth . "_" . $reportingYear;
        }

        $receiver = 'rlpg';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::PRINCETON_UNIVERSITY() ) {
        if ( $fileName =~ /(\d{2}) (\d{4})/ ) {
            $year  = $2;
            $month = $1;

            $poNumber .= $month . "_" . $year;
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::PROQUEST() || $serviceID == BookPub::Tracker::Service::EBA() ) {

        # We want to treat EBA sales the same as Proquest sales from this point on.
        $serviceID = BookPub::Tracker::Service::PROQUEST();

        my $formatType;
        my $proquestNYU = 0;
        my ( $yearStart, $monthStart, $yearEnd, $monthEnd, $quarterStart, $quarterEnd );
        my $forceEBLFormat     = 0;
        my $separateEBLReports = 0;
        my $proQuestMonthly    = 0;

        if ( $fileName =~ /RLPG[_\s]ProQuest[_\s]NYU[_\s](\d{4})[_\s](\d{1,2})/i ) {
            $year        = $1;
            $month       = $2;
            $proquestNYU = 1;
        } elsif ( $fileName =~ /RLPG[_\s]ProQuest[_\s]EBA[_\s]\w{2}[_\s](\d{4})[_\s](\d{1,2})/i ) {
            $year       = $1;
            $month      = $2;
            $formatType = 'EBA_TX';
        } elsif ( $fileName =~ /^(\w{3}).*?-(\d{4})-(\d{2})/ ) {
            $formatType = uc($1);
            $year       = $2;
            $month      = $3;

            if ( $fileName !~ /trueup/i ) {

                # We actually want to display the quarter for non-TrueUp files, so let's convert it.
                $month = "Q" . ( ( $month + 2 ) / 3 );
            }
        } elsif ( $fileName =~ /(\d{4})(Q\d{1}).*(\w{3})-\d{2}-\d{5}.*NBN\./ ) {    #FB15187
            $formatType         = 'EBL';
            $separateEBLReports = 1;
            $year               = $1;
            $month              = $2;      # Actually the quarter in this case, despite the name of the variable.
        } elsif ( $fileName =~ /(\d{4})(Q\d{1}).*(\w{3}) RLPG\./ ) {
            $formatType = uc($3);
            $year       = $1;
            $month      = $2;              # Actually the quarter in this case, despite the name of the variable.
        } elsif ( $fileName =~ /(\d{4})(Q\d{1})[\s-](\w{3})/ ) {    #FB15178
            $formatType = uc($3);
            $year       = $1;
            $month      = $2;                                       # Actually the quarter in this case, despite the name of the variable.
        } elsif ( $fileName =~ /(\d{4}) (\d{2})-(\d{4}) (\d{2})/i ) {
            $forceEBLFormat = 1;                                    # these sales do not have a format set, despite being EBL sales
            $yearStart      = $1 - 2000;
            $monthStart     = int($2);
            $yearEnd        = $3 - 2000;
            $monthEnd       = int($4);
            $quarterStart   = int( ( $monthStart + 2 ) / 3 );
            $quarterEnd     = int( ( $monthEnd + 2 ) / 3 );
        } elsif ( $fileName =~ /Q(\d)(\d{2}) Q(\d)(\d{2})/i ) {
            $forceEBLFormat = 1;                                    # these sales do not have a format set, despite being EBL sales
            $quarterStart   = $1;
            $yearStart      = $2;
            $quarterEnd     = $3;
            $yearEnd        = $4;
        } elsif ( $fileName =~ /(\d{4})M(\d{1,2})-MRD-30-(?:10973|2742)/ ) { # YYYYM#-MRD-30-2742
            $proQuestMonthly = 1;
            $year            = $1;
            $month           = $2;
            $poNumber = sprintf("MRD_%02d_%04d", $month, $year);
        } elsif ( $fileName =~ /^(\d{4})M(\d{1,2})-MRD-30-10501/i ) {
            $month = sprintf('%02d', $2);
            $year = $1;
            $poNumber = "MRD_NBN_".$month."_".$year;
        } elsif ( $fileName =~ /(\d{4})M(\d{1,2})-MRD-30-37299/i ) {
            $poNumber .= "_TrueUp";
            $month = sprintf('%02d', $2);
            $year = $1;
            $poNumber = $month."_".$year."_FC";
        } elsif ( $fileName =~ /(\d{4}).*(\d{2})\./ ) {
            $formatType = 'EBL';
            $year       = $1;
            $month      = $2;
            my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);
        }

        if ( $formatType && $month && $year ) {
            $poNumber = $formatType . "_" . $month . "_" . $year;

            if ( $fileName =~ /trueup/i ) {
                $poNumber .= "_TrueUp";
            }
            if ($separateEBLReports) {
                $poNumber .= "_NBN";
            }
            if ( $formatType eq 'EBA_TX' ) {
                $poNumber = $formatType . "_" . $year . "_" . $month;
            }
        }

        if ( $proquestNYU && $month && $year ) {
            $poNumber = $month . "_" . $year;
        }

        if ( $yearStart && $quarterStart && $yearEnd && $quarterEnd ) {
            if ( $fileName =~ /true[\s_]up/i ) {
                $poNumber = "Q" . $quarterStart . $yearStart . " Q" . $quarterEnd . $yearEnd . " TRUE UP";
            }
        }

        # Just setting this to NBN for all files.
        $receiver = 'nbn';

        $feedID = "nbn_ebl";

        # check to see if this is the AttaFace pass, the sale object will be set to string
        # value 'IGNORE'
        if ( $sale ne 'IGNORE' ) {
            if ( $sale->format_type && $sale->format_type eq BookPub::DB::Item::Sale::kFormatTypeEBL ) {
                $feedID = "nbn_ebl";
            } else {
                if ($forceEBLFormat) {
                    $feedID = "nbn_ebl";
                } else {
                    $feedID = "nbn_ebc";
                }
            }
        }

        if ( $formatType eq "EBA_TX" ) {
            $feedID   = "nbn_eba";
            $receiver = 'rlpg';
        }

        if ( $proquestNYU ) {
            $feedID   = "pq_nyu";
            $receiver = 'rlpg';
        }

        if ($proQuestMonthly) {
            $feedID   = "pq_nbn_monthly";
            $receiver = 'nbn';
        }

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Feed ID'} = $feedID;

    } elsif ( $serviceID == BookPub::Tracker::Service::PUBLISHERS_ROW() ) {
        if ( $fileName =~ / (\d{2}) (\d{4})/ ) {
            $year  = $2;
            $month = $1;

            $poNumber .= $month . "_" . $year;
        }

        $receiver = 'rlpg';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::SCRIBD() ) {
        if (   $fileName =~ /^(\d{4})(\d{2})\d{2}/
            || $fileName =~ /^(\d{4}) (\d{2})/
            || $fileName =~ /^(\d{2}) (\d{2})/
            || $fileName =~ /(\d{4})(\d{2})\d{2}[\s-]\d{8}/
            || $fileName =~ /(\d{4}) (\d{2}) to/
            || $fileName =~ /(\d{4})-(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            if ( length($year) == 2 ) {
                $year = "20" . $year;
            }

            $poNumber = $month . "_" . $year;
        } elsif ( $fileName =~ /ADJ 2015/ ) {
            my $dateBegin;
            if ( $sale ne 'IGNORE' ) {
                $dateBegin = substr( $sale->date_begin, 0, 4 );
            } else {
                $dateBegin = 2015;
            }
            $poNumber = "ADJ_" . $dateBegin;
        } elsif ( $fileName =~ /extra payment/i && $fileName =~ /(\d{4}) (\d{2})/ ) {
            my $year = $1;
            $poNumber = "ADJ_" . $year;
        }

        if ( $poNumber && $fileName =~ /store/i ) {
            $poNumber .= "_STORE";
        } elsif ( $poNumber && $fileName =~ /stackpole/i ) {
            $poNumber .= "_SKO";
        }

        if ( $fileName =~ /RLPG/i || $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /nbn/i || $fileName =~ /National/i || $fileName =~ /^stackpole/i ) {
            $receiver = 'nbn';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::XANEDU() ) {
        if ( $fileName =~ /(Q\d)-(\d{4})/i ) {
            $quarter = $1;
            $year    = $2;

            $poNumber = $quarter . "_" . $year;
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::SLICEBOOKS() ) {
        if ( $fileName =~ /Q(\d)-(\d{4})/ ) {
            $quarter = $1;
            $year    = $2;
        } elsif ( $fileName =~ /(\d{4})\w*Q(\d)/ ) {
            $quarter = $2;
            $year    = $1;
        }

        if ( $quarter && $year ) {
            $poNumber = "Q" . $quarter . "_" . $year;
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::SONY() ) {
        if ( $fileName =~ /Q-0(\d)-(\d{4})/ ) {
            $quarter = $1;
            $year    = $2;

            $poNumber = "Q" . $quarter . "_" . $year;
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::THREE_M() || $serviceID == BookPub::Tracker::Service::OCLC() ) {

        if ( $fileName =~ / (\w{2}) / ) {
            $countryCode = $1;
        }

        if ( $fileName =~ /(\d{4})(\d{2})\d{2}/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;

            # We'll add the US country code later, but only if it's a globe file.
            if ( $countryCode ne 'US' ) {
                $poNumber .= "_" . $countryCode;
            }
        }

        if ( $fileName =~ /nbn/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /rowman/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /globe/i || $fileName =~ /globepequot/i ) {
            $receiver = 'rlpg';

            if ($poNumber) {
                $poNumber = "GPQ_" . $poNumber;

                if ( $countryCode eq 'US' ) {
                    $poNumber .= "_US";
                }
            }
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::TXTR() ) {
        if ( $fileName =~ /(\d{4})(\d{2})\d{2}-/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /^rowman/i ) {
            $receiver = 'rlpg';
        } elsif ( $fileName =~ /^nbn/i ) {
            $receiver = 'nbn';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::UNIZIN() ) {
        if ( $fileName =~ / ([A-Za-z]+) Quarter (\d{4})/ ) {
            $year = $2;

            my $quarterName = lc($1);
            if ( $quarterNames{$quarterName} ) {
                $quarter  = $quarterNames{$quarterName};
                $poNumber = "Q" . $quarter . "_" . $year;
            }
        }

        if ( $fileName =~ /R&L/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::VIRDOCS() ) {

        # We can't use the date in the file name anymore, so we'll try to figure it out from the sales dates.
        my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);

        if ( $reportingMonth && $reportingYear ) {
            $poNumber = $reportingMonth . "_" . $reportingYear;
            $poNumber .= "_CONTENT" if ($fileName =~ /^content/i);
            $poNumber .= "_IA"   if ($fileName =~ /^inclusive.access/i);
        }
        elsif ( $fileName =~ /^inclusive.access/i && ( !$reportingMonth || !$reportingYear ) ) {
            $fileName =~ /(\d{4}).(\d{2})\./;
            $year  = $1;
            $month = $2;
            $poNumber = $month . "_" . $year;
        }
        else {
            if ( $fileName =~ /(\d{4})-(\d{2})-(\d{2})/ ) {
                $year  = $1;
                $month = $2;
                $month -= 1;    # filename date is 1 month after reporting period
                $poNumber = $month . "_" . $year;
            }
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID );

        # This SAN is based solely on the service ID, so there's no need to add anything to the
        # sanCriteria hash.

    } elsif ( $serviceID == BookPub::Tracker::Service::VITAL_SOURCE()
        || $serviceID == BookPub::Tracker::Service::BARNES_NOBLE_EDUCATION() ) {
        if ( $fileName =~ /^(\d{4}) (\d)/ ) {
            $year    = $1;
            $quarter = $2;

            $poNumber = "Q" . $quarter . "_" . $year;

        } elsif ( $fileName =~ /^(\d{4}) (\w+)/ ) {
            $year = $1;
            my $monthName = lc($2);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_" . $year;
            }
        } elsif ( $fileName =~ /- (\w+) (\d{4}) -/ ) {
            $year = $2;
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_" . $year;
            }
        } elsif ( $fileName =~ /(\d{4})(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        } elsif ( $fileName =~ /(\w{3})-(\d{2})/ ) {
            $year = $2;
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_20" . $year;
            }
        } elsif ( $fileName =~ /(\w+)-(\d{2})/ ) {
            $year = $2;
            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_20" . $year;
            }
        }

        # Let's not add anything to the PO unless we found the dates above.
        if ($poNumber) {
            if ( $serviceID == BookPub::Tracker::Service::BARNES_NOBLE_EDUCATION() ) {
                $poNumber .= "_BNED";
            } elsif ( $fileVersion >= 14 ) {    # Version 14 and 15 is when Vital Source started combining all of their sales together
                $poNumber .= "_COMBO";
            } elsif ( $fileName =~ /Wholesale/i ) {
                $poNumber .= "_Wholesale";
            } elsif ( $fileName =~ /Retail/i ) {
                $poNumber .= "_Retail";
            } elsif ( $fileName =~ /Intl Bookstore/i ) {
                $poNumber .= "_BKSTR_INTL";
            } elsif ( $fileName =~ /Bookstore/i ) {
                $poNumber .= "_Bookstore";
            } elsif ( $fileName =~ /MBS/ ) {
                $poNumber .= "_MBS";
            } else {

                # The file name should include one of the above
                # so I'm going to purposely trigger an error condition if it doesn't.
                $poNumber = '';
            }
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i || $fileName =~ /RLPG/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::WESTERN_THEOLOGICAL_SEMINARY() ) {
        if ( $fileName =~ / (\d{4})(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber .= $month . "_" . $year;
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::WESTMINSTER_LIBRARY() ) {
        if ( $fileName =~ / (\d{4})(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber .= $month . "_" . $year;
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::YUZU() ) {
        if ( $fileName =~ / ([A-Za-z]+) (\d{4})/ ) {
            $year = $2;

            my $monthName = lc($1);
            if ( $monthNames{$monthName} ) {
                $month    = $monthNames{$monthName};
                $poNumber = $month . "_" . $year;
            }
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::ZINIO() ) {
        if ( $fileName =~ /^(\d{4})-(\d{2})/ ) {
            $year  = $1;
            $month = $2;

            $poNumber = $month . "_" . $year;
        }

        if ( $fileName =~ /National/i ) {
            $receiver = 'nbn';
        } elsif ( $fileName =~ /Rowman/i ) {
            $receiver = 'rlpg';
        }

        if ($receiver) {
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;

    } elsif ( $serviceID == BookPub::Tracker::Service::MORGAN_LIBRARY() ) {
        if ( ( $year, $month ) = $fileName =~ /(\d{4})\s(\d{2})/ ) {
            $poNumber = $month . "_" . $year;
        }

        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;
    } elsif ( $serviceID == BookPub::Tracker::Service::WILLIAM_PERKINS_LIBRARY() ) {
        if ( ( $year, $month ) = $fileName =~ /(\d{4})\s?(\d{2})/ ) {
            $poNumber = $month . "_" . $year;
        }

        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;
    } elsif ( $serviceID == BookPub::Tracker::Service::LIBRIOS() ) {
        $poNumber = $fileName;
        $poNumber =~ s/\d+\s(\d+\..+$)/$1/g;
        $poNumber =~ s/(?:\s|\..+$)//g;

        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );

        # Note which criteria we use for the SAN here, so that we can include it in the error email if needed.
        $sanCriteria{'Receiver'} = $receiver;
    } elsif ( $serviceID == BookPub::Tracker::Service::LEO_DEHON_LIBRARY() ) {
        if ( ( $month, $year ) = $fileName =~ /(\d{2})(\d{4})/ ) {
            $poNumber = $month . "_" . $year;
        }

        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
    } elsif ( $serviceID == BookPub::Tracker::Service::HOOPLA_DIGITAL() ) {
        my $type;
        if ( $fileName =~ /^Hoopla(RLPG|NBN)[ _](\d{2})(\d{4}).*/i ) {
            $poNumber = $2 . "_" . $3 . "_" . $1;
        }
        elsif ( ( $year, $type, $month ) = $fileName =~ /\d+-(\d{4})-\d{2}-\d{2}.*(Audio|eBook)[_\s](\w{3,9})\.\w+/i ) {
            $month = $monthNames{ lc $month };
            $poNumber = $month . "_" . $year . "_" . $type;
        } elsif ( $fileName =~ /.*[_\s](\w{3,9})\.\w+$/i ) {
            my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);
            my $month = $monthNames{lc $1};
            $poNumber = $month . "_" . $reportingYear . "_SALES";
        }

        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
    } elsif ( $serviceID == BookPub::Tracker::Service::ACX() ) {
        if ( ( $month, $year ) = $fileName =~ /.*[_ ](\w{3,9})[_ ](?:20)?(\d{2})\.\w+$/ ) {
            $poNumber = $monthNames{ lc $month} . "_" . "20$year" if exists $monthNames{ lc $month};
        }
        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
    } elsif ( $serviceID == BookPub::Tracker::Service::CATHOLIC_DISTANCE_UNIVERSITY() ) {
        if ( ( $year, $month ) = $fileName =~ /.*(\d{4})-?(\d{2})\.\w+$/ ) {
            $poNumber = $month . "_" . $year;
        }
        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
    } elsif ( $serviceID == BookPub::Tracker::Service::HUMMINGBIRD_DIGITAL() ) {
        if ( ( $month, $year ) = $fileName =~ /.*(\d{2})(\d{2})$/ ) {
            $month = sprintf "%02d", $month;
            $year  = sprintf "20%02d", $year;
            $poNumber = $month . '_' . $year;
        } else {
            my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);
            $poNumber = $reportingMonth . "_" . $reportingYear;
        }

        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
    } elsif ( $serviceID == BookPub::Tracker::Service::OPEN_ROAD_MEDIA() ) {
        if ( ( $month, $year ) = $fileName =~ /.*? (\w+?) (\d{4}).*/ ) {
            $month = sprintf "%02d", $monthNames{lc($month)};

            my $feedID;
            $feedID = "SALES CT" if $fileName =~ /C&T/i;
            $feedID = "SALES FH" if $fileName =~ /Felony/i;
            $feedID = "RLPG" if $fileName =~ /Rowman/i;

            $poNumber = $month . '_' . "$year $feedID";
            $poNumber = $month . '_' . $year. '_' . $feedID if ($feedID eq 'RLPG');

            $receiver = 'nbn';
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $feedID );
        }

    } elsif ( $serviceID == BookPub::Tracker::Service::HEKMAN_LIBRARY() ) {
        if ( ( $year, $month ) = $fileName =~ /.*(\d{4})(\d{2})\./ ) {
            $month = sprintf "%02d", $month;
            $year  = sprintf "%04d", $year;
            $poNumber = $month . '_' . $year;
        } else {
            my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);
            $poNumber = $reportingMonth . "_" . $reportingYear;
        }

        $receiver = 'nbn';
        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
    } elsif ( $serviceID == BookPub::Tracker::Service::BLACKSTONE_AUDIO() ) {
        if ( $fileName =~ /R&L.(\w{3,9}).(\d{4})/i ) {
            $poNumber = $monthNames{lc $1} . "_" . $2 . "_SALES";
            $receiver = 'nbn';
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }
    } elsif ( $serviceID == BookPub::Tracker::Service::PERLEGO() ) {
        my ( $reportingMonth, $reportingQuarter, $reportingYear ) = $self->_getReportingPeriod($fileID);

        if ( $reportingMonth && $reportingYear ) {
            $poNumber = $reportingMonth . "_" . $reportingYear . " SALES";
        }

        $receiver = 'nbn';

        $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID );
    } elsif ( $serviceID == BookPub::Tracker::Service::BIBLIU() ) {
        if ( $fileName =~ /Rowman & Littlefield.*([a-z]{3})(\d{4}).{3}BibliU.*(USD).*/i ) {
            my $reportingMonth = $monthNames{lc $1};
            my $reportingYear = $2;
            $poNumber = $reportingMonth . "_" . $reportingYear . "_US";
            $receiver = 'nbn';
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }
    } elsif ( $serviceID == BookPub::Tracker::Service::SPOTIFY ) {
        if ( $fileName =~ /spotify-abp-detail-pool-for-therowmanlittlefieldpublishinggroupinc-(\d{4})(\d{2})/i ) {
            my $year = $1;
            my $month = $2;
            my $quarter = sprintf "%02d", int(($month - 1) / 3) + 1;
            $poNumber = $quarter . "_" . $year . "_SPOTIFY";
            $receiver = 'nbn';
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }
    } elsif ( $serviceID == BookPub::Tracker::Service::JSTOR_ITHAKA ) {
        if ( $fileName =~ /^Brookings[ _]Institution[ _]Press[ _]JSTOR[ _]Payments[ _](\d{4})[ _]Q(\d)/i ) {
            $poNumber = "0$2" . "_" . $1 . " SALES";
            $receiver = 'rlpg';
            $clientService = BookPub::DB::Item::ClientService->Lookup( service_id => $serviceID, feed_id => $receiver );
        }
    }

    if ($poNumber) {

        # We want to add a little something to the PO number for split files.
        if ($fileGeneration) {
            my $alphaGen = 'a';
            my $count    = 0;
            while ( $count < $fileGeneration ) {
                $alphaGen++;
                $count++;
            }
            $poNumber .= "_" . $alphaGen;
        }

        # Just to be sure that this is always upper case
        $poNumber = uc($poNumber);
    }

    my $receiverID;
    if ( $receiver =~ /^rlpg|nbn$/i && $serviceID == BookPub::Tracker::Service::EBRARY() ) {
        $receiverID = '6300065FTP';
    } elsif ( $receiver eq 'rlpg' ) {
        $receiverID = '2532387FTP';
    } elsif ( $receiver eq 'nbn' ) {
        $receiverID = '6300065FTP';
    }

    my $customerSAN;
    if ($clientService) {
        $customerSAN = $clientService->client_service_id;
    }

    return ( $poNumber, $customerSAN, $receiverID, %sanCriteria );
}

sub validateFile {
    my ( $self, $fileID ) = @_;

    # This is the hash we'll send back all of the data in.
    # We'll need to know exactly which fields are missing.
    my %validation;

    # If everything is good, this is all we'll send back.
    $validation{isValid} = 1;

    my $file = BookPub::DB::Item::File->Lookup( file_id => $fileID );
    my $serviceID = $file->service_id;

    if (   $serviceID == BookPub::Tracker::Service::RSFORMAT()
        || $serviceID == BookPub::Tracker::Service::WILLIAM_PERKINS_LIBRARY()
        || $serviceID == BookPub::Tracker::Service::VITAL_SOURCE() ) {    # We need to grab the service id from a sale if they
                                                                          # are using the royaltyshare template or it's from
                                                                          # a distributor(-ish) source
        my $sale = BookPub::DB::Item::Sale->Lookup( file_id => $fileID );
        $serviceID = $sale->service_id;
    }

    # RLPG uploads some sales files just for analytics and will never close them.
    # For these, we will skip the validation process
    my $skipValidation = $self->_skipValidation($serviceID);

    if ( !$skipValidation ) {
        my $fileGeneration = $file->generation;
        my $fileVersion    = $file->version_num;
        my $fileName       = $file->orig_file_name;
        $fileName =~ s/_/ /g;

        # Most of the attributes are derived from file level data.
        # There are only a few services that look at the actual sale data in _getAccountInfo.
        # But even for those, there is no failure condition involving sale data.
        # So, I think we should just pass a flag to ignore $sale data so that we can get this done quickly.
        my $sale = "IGNORE";
        my ( $poNumber, $customerSAN, $receiverID, %sanCriteria ) =
          $self->_getAccountInfo( $serviceID, $fileName, $sale, $fileGeneration, $fileVersion, $fileID );

        # If any of these are missing, we need to mark this as invalid.
        if ( !$poNumber || !$customerSAN || !$receiverID ) {
            $validation{isValid} = undef;

            if ( !$poNumber ) {

                # The PO is where RLPG stores the reporting period (and some other stuff).
                $validation{"Reporting Period"} = "missing";
            }

            if ( !$receiverID ) {
                $validation{"Receiver"} = "missing";
            }

            if ( !$customerSAN ) {

                # For this one, it would helpful to pass along some additional info about the sale
                # and the criteria we're using to look for the SAN.
                if (%sanCriteria) {
                    foreach my $criteria ( sort keys %sanCriteria ) {
                        $validation{"SAN"}{$criteria} = $sanCriteria{$criteria};
                    }
                } else {

                    # It would also be good to know if we don't have any criteria set up for this service yet.
                    $validation{"SAN"} = "NONE";
                }
            }
        }
    }

    return %validation;
}

sub _skipValidation {
    my ( $self, $serviceID ) = @_;

    # If you don't want to validate a service, add them to this hash.
    my %serviceExceptions;
    $serviceExceptions{ BookPub::Tracker::Service::ROWMAN_COM_ESALES() } = 1;

    if ( $serviceExceptions{$serviceID} ) {
        return 1;
    } else {
        return 0;
    }
}

1;

