package CLMApp;
no warnings 'all';
use Mojo::Base 'Mojolicious';
use lib '/home/sites/clm.dmadelivers.com/clmapp/lib';
# use CLMApp::Schema;
# use CLMApp::Controller::Root;
use Data::Show;
use Cwd;
use strict;
use DateTime;
use Class::Struct;
use Object::Accessor;
use CLMApp::Schema;
use ExcelExport;
use Perl6::Junction qw/ any /;
use Moose::Autobox;
use DBIx::ResultSet;
use LWP::JSON::Tiny;
use File::Basename;
use JSON;
use File::Copy qw(copy move);
use utf8;

#use Tie::STDERR '>> ' . getcwd() . '/logs/clmapp.debug.log';
#*STDERR = *STDOUT;

# struct FormElement => {type=> '$', attrs => '%', val => '$', vals => '@', labels => '%'};
# struct Form => {attrs => '%', elems => '@'};

	 print "Loaded modules:\n"; foreach my $file (keys %INC) { print "  $file\n"; } 
#	BEGIN { print "Loaded modules:\n"; foreach my $file (keys %INC) { print "  $file\n"; } }

$ENV{MOJO_INACTIVITY_TIMEOUT} = 300;
$ENV{DBIC_TRACE}=1;
# $ENV{DBIC_TRACE}="1;/home/sites/clm.dmadelivers.com/www/clmapp/logs/clmapp.log";
# Connects once for entire application. For real apps, consider using a helper
# that can reconnect on each request if necessary.
has schema => sub {
  my $c = shift;
   my $s = CLMApp::Schema->connect("dbi:mysql:host=dmaclm202601maria.c3uyamkimdwh.us-east-1.rds.amazonaws.com;mysql_ssl=1;db=dmaclm", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});
#   my $s = CLMApp::Schema->connect("dbi:mysql:host=dmaclm202601.c3uyamkimdwh.us-east-1.rds.amazonaws.com;db=dmaclm", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});
#   my $s = CLMApp::Schema->connect("dbi:mysql:host=rds1.dmadelivers.com;db=dmaclm", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});
   # my $s = CLMApp::Schema->connect("dbi:mysql:host=mysql;db=dmaclm", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});
  # $s->storage->dbh_do(sub{ my ($s, $d, @a) = @_; $d->do("SET NAMES utf8");});

#  my $s = CLMApp::Schema->connect("dbi:mysql:host=mysql;db=DMA", 'root', 'b3hereNOW!');
  return $s;
};

has devschema => sub {
  my $c = shift;
#  my $s = CLMApp::Schema->connect("dbi:mysql:host=rds1.dmadelivers.com;db=dmaclmdev", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});    
#  my $s = CLMApp::Schema->connect("dbi:mysql:host=dmaclm202601.c3uyamkimdwh.us-east-1.rds.amazonaws.com;db=dmaclmdev", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});    
  my $s = CLMApp::Schema->connect("dbi:mysql;host=dmaclm202601maria.c3uyamkimdwh.us-east-1.rds.amazonaws.com;db=dmaclmdev", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});    
  # my $h = $c->stash('host');
  # show $h;
  # if($h =~ /\.rajya$/){
  #   $s = CLMApp::Schema->connect("dbi:mysql:host=rds1.dmadelivers.com;db=dmaclm", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});
  # }
   
   # my $s = CLMApp::Schema->connect("dbi:mysql:host=mysql;db=dmaclmdev", 'dmaclm', '3lUz1OV2!',{mysql_enable_utf8 => 1});
  # $s->storage->dbh_do(sub{ my ($s, $d, @a) = @_; $d->do("SET NAMES utf8");});

#  my $s = CLMApp::Schema->connect("dbi:mysql:host=mysql;db=DMA", 'root', 'b3hereNOW!');
  return $s;
};


# has schemadbix => sub {
#   my $c = shift;
#   my $s = DBIx::ResultSet->connect("dbi:mysql:host=mysql;db=dmaclm", 'dmaclm', '3lUz1OV2!');
#   return $s;
# };


sub objectify {

  my $self = shift;
  my $o = shift;


  if(ref($o) eq 'HASH'){
      my $oo = Object::Accessor->new(keys %$o);
      foreach my $k (keys %$o){
        my $oov = $o->{$k};
        if(ref($oov) ne 'SCALAR' && $k ne 'options'){
          $oo->$k($self->objectify($oov));
        }else{
          $oo->$k($oov);
        }
      }
      return $oo;
  }elsif(ref($o) eq 'ARRAY'){
      my @oo;
      foreach my $oov (@$o){
        push(@oo,$self->objectify($oov));
      }
      return \@oo;
  }else{
    return $o;
  }



}

sub load_defaults{
  my $self = shift;



  # get select / radio / input / textarea default values
  my @distributorcompany = $self->db->resultset('DistributorCompany')->search({'me.active' => 1},{result_class=>'DBIx::Class::ResultClass::HashRefInflator', order_by=>'name'});
  my @distributorwarehouse = $self->db->resultset('DistributorWarehouse')->search({'me.active' => 1,'me.clmactive' => 1},{result_class=>'DBIx::Class::ResultClass::HashRefInflator', order_by=>'distributorwarehousename'});
  my @dmaprogrammanager = $self->db->resultset('DmaprogramManager')->search({active=>1},{result_class=>'DBIx::Class::ResultClass::HashRefInflator', order_by=>'dmaprogrammanager'});
  my @dmavp = $self->db->resultset('Dmavp')->search({active=>1},{result_class=>'DBIx::Class::ResultClass::HashRefInflator', order_by=>'dmavp'});
  my @user = $self->db->resultset('User')->search({active=>1},{result_class=>'DBIx::Class::ResultClass::HashRefInflator', order_by=>'fullname'});
  my @chainconcept = $self->db->resultset('ChainConcept')->search(undef,{order_by=>'chainconceptname', result_class=>'DBIx::Class::ResultClass::HashRefInflator'});
  my @chaingroup = $self->db->resultset('ChainGroup')->search(undef,{order_by=>'chaingroupname',result_class=>'DBIx::Class::ResultClass::HashRefInflator'});

  my @astatus = $self->db->resultset('Status')->search(undef,{result_class=>'DBIx::Class::ResultClass::HashRefInflator'});
  my @orderflag = $self->db->resultset('OrderFlag')->search(undef,{result_class=>'DBIx::Class::ResultClass::HashRefInflator'});
  my @backofficesystem = $self->db->resultset('BackOfficeSystem')->search(undef,{result_class=>'DBIx::Class::ResultClass::HashRefInflator', order_by=>'systemname'});
  my @country = $self->db->resultset('Country')->search({active=>1},{result_class=>'DBIx::Class::ResultClass::HashRefInflator', order_by=>'fullname'});

  $self->defaults({
    distributorcompany => \@distributorcompany, 
    distributorwarehouse => \@distributorwarehouse, 
    dmaprogrammanager=>\@dmaprogrammanager, 
    dmavp=>\@dmavp, 
    user=>\@user,
    chainconcept => \@chainconcept,
    chaingroup => \@chaingroup,
    astatus => \@astatus,
    backofficesystem => \@backofficesystem,
    country => \@country
    # orderflag => \@orderflag,

    });

}


# This method will run once at server start
sub startup {
  my $self = shift;

  # Documentation browser under "/perldoc"
  # $self->plugin('PODRenderer');

  $self->plugin('RenderFile');
  $self->plugin('Directory::Stylish' => { auto_index  => 1, handler => sub {

        my $c = shift;
        my $path = shift; 
        my $paths = ['/files/opf','/files/opfreturn'];

        my $passpath = 0;
        foreach my $p (@$paths){
          my $to_string = $path->to_string();
           if($to_string =~ /^.*$p$/){
              $passpath = 1;
           }
        }

        if(!$passpath){
          $path = undef;
        }

        return $path;

  }});

    $self->plugin(MailException => {
        from    => 'root@dmadelivers.com',
        # to      => 'dma@ace4it.com,jim.szatkowski@dmadelivers.com,jason.gross@dmadelivers.com',
        to => 'dma@ace4it.com,opfftp@dmadelivers.com',
        subject => 'DMA CLM Error',
        # headers => {
        #     'X-MySite' => 'crashed'
        # }, 
        stack   => 100
    });


	$self->helper(db => sub { 
    my $c = shift; 
    my $h = $c->req->url->base->host;  
    $c->stash('host', $h);
    $c->stash('dev', 0);
    if($h && $h =~ /^dev/i){
      $c->stash('dev', 1);
      return $self->app->devschema;   
    }
    if($h && $h =~ /^uat/i){
      $c->stash('uat', 1);
      $c->stash('dev', 1);
      return $self->app->devschema;   
    }
    return $self->app->schema; 
  });
  # $self->helper(dbix => sub { $self->app->schemadbix });

  $self->helper(check_email_notification => sub {
      my $c = shift;
      my $customers = shift;
      my $bponly = shift;

# show $customers;

      my $h = $c->req->url->base->host; 
      show $h;
      return if $h =~ /^dev/i || $h !~ /\.com$/;

      # show $customers;

      my @emailn = $c->db->resultset('EmailNotification')->search({'me.active' => 1}, {result_class => 'DBIx::Class::ResultClass::HashRefInflator', prefetch => [qw/email_notification_warehouses/]});
      my @criteria = (qw/chaingroupid chaninconceptid distributorcompanyid distributorwarehouseid systemid brandedprocurement/);
      foreach my $e (@emailn){

# show @emailn;
        my %criteria;
        my %emails;

        if($e->{actiontype} eq 'EMAIL_ON_ADD_BP_MIGRATE'){
            $criteria{'me.brandedprocurement'} = 1;
        }elsif($bponly){
            next;
        }
# show $e;
        foreach my $r (@criteria){
          $criteria{'me.' . $r} = $e->{$r} if $e->{$r} > 0;
        }     

        my @warehouses;
        foreach my $w (@{ $e->{email_notification_warehouses} }){
            push(@warehouses, $w->{distributorwarehouseid});
        }
        if(scalar(@warehouses)){
            $criteria{'me.distributorwarehouseid'} = \@warehouses;
        }




show %criteria;
        foreach my $customer (@$customers){
          $criteria{'me.customerid'} = $customer->{customerid};
#          $criteria{'me.distributorwarehouseid'} = $customer->{distributorwarehouseid};


# show %criteria;

        my $join = ['distributor','chaingrp','concept','warehouse','chainunit'];
        my $as =  [qw/user unit dma  blank statuschar modify no/]; #  password 
        my $select = [\['CONCAT(customernumber,distributor.bpdcode,warehouse.bplocationid)'],
          \['CONCAT("DMA","-",me.chainunitid)'],
          \['"DMA"'],
          \['""'],
          \['IF(me.statusid=1,IF(me.brandedprocurementdeleted=1,"D","A"),IF(me.brandedprocurementdeleted=1,"D","I"))'],
          \['"M"'],
          \['"N"'],
          # \['"Welcome1"'],
          # \['GROUP_CONCAT(back_office_system_customers.systemid)']
        ];

          my @cs = $c->db->resultset('Customer')->search(\%criteria, {join => $join, '+select' => $select, '+as' => $as, prefetch => [qw/distributor warehouse chaingrp concept/], result_class => 'DBIx::Class::ResultClass::HashRefInflator'}) or next;
          if($cs[0]){
            if($cs[0]->{user} =~ /^(201|501)~(.*)$/){
              $cs[0]->{user} = $2;
            }

          $cs[0]->{systemid} = [$c->db->resultset('Customer')->search_related('back_office_system_customers', {"me.customerid" => $cs[0]->{customerid}})]->map(sub {
              my %r = $_[0]->get_columns;
              return $r{systemid};
            });

            my $tl = $e->{targetlist};
            $tl =~ s/\n/,/g;
            push(@{ $emails{ $tl } }, $cs[0]);
          }
        }
# show %emails;
        foreach my $to (keys %emails){
          my $customers = $emails{$to};

# same as export_bpunitloginent in Customer.pm
        foreach my $cust (@$customers){
# show $cust;          

            $cust->{user} =~ s/\s+//g;

            if($cust->{user} =~ /^(\d+)\s*GFSUSGFS_(\d+).*$/){
                $cust->{user} = $1 . 'GFSUS' . $2;
            }
            if($cust->{user} =~ /\d+~(\d+)(FSA|SSA).*_(\d+).*/){
              $cust->{user} = $1 . $2 . $3;

            # 44213759USFSUSFS_9O-DMA
            }
            if($cust->{user} =~ /USFS/){
              if($cust->{user} =~ /^(\d+)USFS/){
                $cust->{user} = $1 . 'USFS9O';
              }
            }            

            if( grep( /14|34/, @{$cust->{systemid}} )){
                $cust->{password} = $cust->{distributor}->{distributorcode} . $cust->{customerid};
                $cust->{password} =~ s/\s+//g;
                $cust->{password} = ucfirst(lc($cust->{password}));
            }

        }

# show $customers;
# show $c->render_to_string(inline => $e->{body}, customers => $customers);
              my $data = $c->render_to_string(inline => $e->{body}, customers => $customers);


# show $data;               

              $c->mail(
                mail   => {
                  To       => $to,
                  # To => 'dma@ace4it.com',
                  From => $c->config->{mail}->{from}, # message NOT from sending user so messages stay in the system
                  'Reply-to' => $c->config->{mail}->{replyto},
                  # Cc => $c->config->{mail}->{cc},
                  # Bcc    => $c->config->{mail}->{bcc},
                  # Bcc => 'dma@ace4it.com',
                  Subject  => $e->{subject},
                  Data     => $data,
                },
                how => $c->config->{mail}->{how},
                howargs => $c->config->{mail}->{howargs},   

              );


        }



      }










  });


  $self->helper(populate_form => sub {
      my $c = shift;
      my $f = shift;
      my $d = shift;

      $c->setup($d);


      foreach my $ec (@{$c->{_forms}->{$f}->eorder},@{$c->{_forms}->{$f}->sorder}){

        my $e = $c->{_forms}->{$f}->elems->$ec;
# show "ERROR: $ec NOT FOUND" if !ref($e) =~ /Object/;
        next unless $e->can('attrs');
        if($e->can('populate')){
            next unless $e->populate->defaults;
            my $def = [];

            # process DB vs default stored on app load
            if(ref($e->populate->defaults) ne ''){
              my $rsearch = {};
              # show  $e->populate;
              my $where = \@{ $e->populate->defaults->where};
              for(my $w = 0; $w < scalar(@$where); $w++){
                $rsearch->{$where->[$w]} = $e->populate->defaults->vals->[$w];
              }
              if($e->populate->defaults->can('fk') && $e->populate->defaults->fk){
                $rsearch->{$e->populate->defaults->fk} = $d->{ $e->populate->defaults->fk };
              }
              my $prefetch = $e->populate->defaults->prefetch || [];
              my $rparams =  $e->populate->defaults->options || {};
              $rparams->{result_class} = 'DBIx::Class::ResultClass::HashRefInflator';
              # show $rsearch;
              # show $rparams;
              my @c = $c->db->resultset($e->populate->defaults->module)->search($rsearch,$rparams);

              $def = \@c;


            }else{             
              $def = $c->app->defaults($e->populate->defaults);
            }
            
            my(@v,@l);
            my(@d,@dv);
            my(@ml,@mv);
            foreach my $dv (@$def){
              if($e->populate->can('metadata') && ref($e->populate->metadata) ne ''){
                my($mv,$ml) = $e->populate->metadata->($e,$dv);
                push(@mv,$mv);
                push(@ml,$ml);
              }


              #show $dv if $e->attrs->name eq 'chainconcept';
              # if(ref($e->populate->vals) eq 'CODE'){
              #   my $v = $e->populate->vals->($e,$d,$dv);
              #   push(@v,$v) if $v;
              # }else{
                push(@v,$dv->{$e->populate->vals});
              # }
              if(ref($e->populate->labels) eq 'CODE'){
                my $v = $e->populate->labels->($e,$dv);
                push(@l,$v)  if $v;
              }else{
                push(@l,$dv->{$e->populate->labels}); 
              }
              if($e->populate->can('data')){
                my %d;
                foreach my $dk (@{ $e->populate->data }){
                  $d{$dk} = $dv->{ $dk };
                }
                push(@d, \%d);
              }
            }    

            if($e->can('default')){

              $e->default($d->{$e->attrs->name});
            }elsif($e->can('defaults')){
              # if($e->type eq 'selectpicker'){
                #my @a = split(",",  $d->{$e->attrs->name}  );
                $e->defaults($d->{$e->attrs->name});
              # }  

            }

            if($e->can('vals')){
              $e->vals(\@v) if scalar(@v);
            }
            if($e->can('labels')){
              $e->labels(\@l) if scalar(@v);
            }
            if($e->can('data')){
              $e->data(\@d) if scalar(@d);
            }else{
              $e->data([]);
            }
            if($e->can('metadataval')){
                  $e->metadatalabel(\@ml)  if scalar(@ml);
                  $e->metadataval(\@mv)  if scalar(@mv);
            }

        }else{
          if(ref($e->attrs) ne 'ARRAY'){
            $e->val($d->{$e->attrs->name}) if $d->{$e->attrs->name} ne ''; # ne vs true for 0
            $e->default($d->{$e->attrs->name}) if $d->{$e->attrs->name} ne '';  # ne vs true for 0
          }
          if($e->can('data') && ref($e->data) eq 'ARRAY'){
                my (%d);
                foreach my $dk (@{ $e->data }){
                  $d{$dk} = $d->{ $dk };
                }

                $e->data(\%d);
          }else{
            $e->mk_accessors('data');
            $e->data({});
          }
# show $e, $d if $e->attrs->name eq 'permissions';
        }
             


      }

    # show $c->{_forms}->{$f};  
      return ($c->{_forms}->{$f},$c->{_buttongroup}->{$f});
    } );


    $self->helper(dtsearch => sub {

        my $c = shift;
        my $args = shift;
#show $args;        
        my $cols = $args->{columns};
#        show $cols;
        my $p = $args->{params};
        my $defer = $args->{defer} || 0;
        my $prefetch = $args->{prefetch};
        my $join = $args->{join};
        my @cols;



#        my $order_by = $p->{ 'columns[' . $p->{'order[0][column]'} . '][data]'  } ? $p->{ 'columns[' . $p->{'order[0][column]'} . '][data]' } : $args->{order_by};
       my $order_by = $p->{ 'columns[' . $p->{'order[0][column]'} . '][data]'  } ? $p->{ 'columns[' . $p->{'order[0][column]'} . '][data]' } : $args->{order_by};
        show $order_by;
	if(ref($order_by) eq 'ARRAY'){
		$order_by = $order_by->[0];
	}
        if($order_by !~ /\./){
          $order_by = 'me.' . $order_by;
        }

        my $sort = $p->{'order[0][dir]'} || $args->{sort};
        my $rsearch = undef;
        my $search = $p->{'search[value]'};
        my $draw = $p->{draw};
        my $length = $p->{length} || 100;
        my $page = ($p->{start} / $length) + 1;

        if($p->{ssearch}){
          my $json = JSON->new->allow_nonref;
          if(ref($p->{ssearch}) =~ /HASH|ARRAY/){
            $rsearch = $p->{ssearch};
          }else{
            my $jobj = $json->decode( $p->{ssearch} );
            $rsearch = $jobj;
          }
        }elsif($p->{asearch}){
show "ASEARCH";
          foreach my $c (keys %$p){
            # this is sloppy

            next if $p->{$c} eq "" || $c eq 'asearch' || $c =~ /\[/ || $c eq 'export' || $c eq 'start' || $c eq 'draw' || $c eq 'length' || $c eq '_' || $c eq 'fuzzy' || $c eq 'boolor' || $c eq 'csv' || $c eq 'csv_seperator';

            if($c =~ /\./){
              if($p->{$c} =~ /^\d+$/  && !$p->{fuzzy}){
                $rsearch->{$c} = $p->{$c};
              }else{
                $rsearch->{$c} = {'like', '%' . $p->{$c} . '%'};
              }
            }else{
              if($p->{$c} =~ /^\d+$/  && !$p->{fuzzy}){
                $rsearch->{'me.' . $c} = $p->{$c};
              }elsif($c =~ /id$/ && $p->{$c} =~ /,/){
                my @in = split(/,/, $p->{$c});
                $rsearch->{'me.' . $c} = {'IN' => \@in}; 
              }else{
                $rsearch->{'me.' . $c} = {'like', '%' . $p->{$c} . '%'};
              }
            }
          }

show $rsearch;
         $rsearch = {'-or' => $rsearch} if $rsearch && $p->{boolor} == 1;

          my %rvals;
          # "columns[2][search][value]"
          foreach my $k (keys %$p){
            if($k =~ /columns\[(\d+)\]\[data\]/){
              $cols[$1] = $p->{$k};
            }
          }
          foreach my $k (keys %$p){     
            if($k =~ /columns\[(\d+)\]\[search\]\[value\]/){
              $rvals{$cols[$1]} = $p->{$k};
            }
          }
          
          foreach my $c (keys %rvals){           
            if($c =~ /\./ && $rvals{$c} ne ""){
              $rsearch->{$c} = {'like', '%' . $rvals{$c} . '%'};
            }elsif($rvals{$c} ne ""){
              $rsearch->{'me.' . $c} = {'like', '%' . $rvals{$c} . '%'};
            }
          }
show $rsearch;

        }elsif($search){

          foreach my $c (@$cols){
            if($c =~ /\./){
              $rsearch->{$c} = {'like', '%' . $search . '%'};
            }else{
              $rsearch->{'me.' . $c} = {'like', '%' . $search . '%'};
            }
          }
          $rsearch = {'-or' => $rsearch} if $rsearch;


        }else{
show 'DEFAULT SEARCH';
          my %rvals;
          # "columns[2][search][value]"
          foreach my $k (keys %$p){
            if($k =~ /columns\[(\d+)\]\[data\]/){
              $cols[$1] = $p->{$k};
            }
          }
          foreach my $k (keys %$p){     
            if($k =~ /columns\[(\d+)\]\[search\]\[value\]/){
              $rvals{$cols[$1]} = $p->{$k};
            }
          }
          foreach my $c (keys %rvals){

            if($c =~ /\./ && $rvals{$c} ne ""){
              if(ref($rvals{$c}) eq '' && $c !~ /.*id$/i){
                $rsearch->{$c} = {'like', '%' . $rvals{$c} . '%'};
              }else{
                 $rsearch->{$c} = $rvals{$c};
              }
            }elsif($rvals{$c} ne ""){
              if(ref($rvals{$c}) eq ''  && $c !~ /.*id$/i){
                $rsearch->{'me.' . $c} = {'like', '%' . $rvals{$c} . '%'};
              }else{
                 $rsearch->{'me.' .$c} = $rvals{$c};
              }              
            }
          }

        }

        my @rsand; 
        # quick hack
        if($args->{table} eq 'Customer'){
          foreach my $k (keys %$rsearch){
              my $v = $rsearch->{$k};
              show $k, $v;
              if($k eq 'me.ordersystem'){
                  my $osystemar = [
                    {'-or' => [{'me.ordersystem' => $v},{'customersystem.systemid' => $v}]}
                  ];
                  push(@rsand, $osystemar);
                  delete($rsearch->{'me.ordersystem'});
              }
              if($k eq 'me.invoicesystem'){
                  my $isystemar = [
                    {'-or' => [{'me.invoicesystem' => $v},{'customersystem.systemid' => $v}]}
                  ];
                  push(@rsand, $isystemar);
                  delete($rsearch->{'me.invoicesystem'});
              }
              # if($k !~ /ordersystem|invoicesystem/){
              #   $nrsearch->{$k} = $v;
              # }

            }
        }

        if(scalar(@rsand)){
          $rsearch->{'-and'} = \@rsand;
        }

        my $total = $c->db->resultset($args->{table})->search(undef,{prefetch=>$prefetch,group_by=>$args->{group_by}, join => $args->{join},having => $args->{having},                '+select' => $args->{select},
                '+as' => $args->{as},})->count;
        my $count = $c->db->resultset($args->{table})->search($rsearch,{prefetch=>$prefetch,group_by=>$args->{group_by},join => $args->{join}, having => $args->{having},                 '+select' => $args->{select},
                '+as' => $args->{as},})->count;

        my $rparams =  {
                order_by => { '-' . $sort => $order_by },  
                result_class=>'DBIx::Class::ResultClass::HashRefInflator',
                group_by => $args->{group_by},
                prefetch => $args->{prefetch},
                join => $args->{join},
                columns => $args->{columns},
                having => $args->{having},
                '+columns' => $args->{ecolumns},
                # collapse => 1,
                '+select' => $args->{select},
                '+as' => $args->{as},
        };
#show $rparams;
        if(!$p->{export} && !$p->{showall}){
          $rparams->{rows} = $length;
          $rparams->{page} = $page;
        }else{
          # $rparams->{rows} = 10;
        }
show $rsearch;
show $p;
        my @c;
        my @rsearch;
        @rsearch = keys %$rsearch if ref($rsearch) eq 'HASH';
        if($p->{export} || ($defer && !scalar(@rsearch))){
          $count = 0;
        }else{
          @c = $c->db->resultset($args->{table})->search($rsearch,$rparams);
          my $rs =  $c->db->resultset($args->{table})->search($rsearch,$rparams);
          show $c->as_query( $rs );          
        }
# show @c; 
        if($args->{returnresult}){
            @c = $c->db->resultset($args->{table})->search($rsearch,$rparams); 
            return \@c, $rsearch, $rparams;
        }


        if($p->{export}){
          $rparams->{result_class} = undef;
#          $rparams->{page} = 0;
#          $rparams->{rows} = 100;
          my $rs = $c->db->resultset($args->{table})->search($rsearch,$rparams);
          my $fdir =  getcwd() . '/public/files/';
          $fdir = '/tmp/';

          if($p->{csv}){
              my $filename = $args->{filename} ? $args->{filename} : $args->{table} . '.' . time();
              $filename .= $args->{filename} ?  "" : $args->{ext} ? '.' . $args->{ext} : '.txt';
              my $filepath = $fdir . $filename;
              my ( $fh, $ofilename ) = $c->export_csv($rs,filename => $filepath, trim => $args->{trim}, columns => $args->{excolumns} || $args->{columns}, sep_char => $args->{sep_char} || "\t", exportrowcb => $args->{exportrowcb}, quote_char => $args->{quote_char}, eheaders => $args->{eheaders});

              $c->res->headers->content_type('text/csv');
              $c->render_file(
                      'filepath' => $filepath,
                      'format' => 'csv',                 
                      # will change Content-Type "application/x-download" to "application/pdf"
                      'content_disposition' => 'attachment',   
                      # will change Content-Disposition from "attachment" to "inline"  
              );  
               

          # return $c->redirect_to('/files/' . $filename);
          # $c->res->code(200);
          # $c->res->headers->content_type('application/x-download');
          # $c->res->headers->content_disposition('attachment; filename=' . $filename);
          # $c->res->headers->content_length((stat $filepath)[7]);
          # use File::Slurp;
          # show $filepath;
          # my $body = read_file($filepath );
          # show $body;
          # $c->res->body($body);
          # $c->render(data => $body);
          return 1;

#return $c->reply->static($filepath);
  # return $c->res->to_string; 


          }else{


              my $filename = $args->{filename} ? $args->{filename} : $args->{table} . '.' . time() . '.xls';
              my $filepath = $fdir . $filename;
              # @c = $c->db->resultset($args->{table})->search($rsearch,$rparams); 
              my ( $fh, $ofilename ) = $c->export($rs, headers => $args->{exheader}, filename => $filepath, columns => $args->{excolumns} || $args->{columns}, nouc => $args->{nouc});

              my $dfilepath = getcwd() . '/public/files/' . $filename;
              move $filepath, $dfilepath;
              $c->res->headers->location('/files/' . $filename);
              $c->rendered(302);
              return 1;

              # my $nfilepath = $fdir . 'X' . $filename;
              # copy $filepath, $nfilepath;
              # show $nfilepath;
              # $c->render_file(
              #         'filepath' => $filepath,
              #         'format' => 'xls',                 
              #         # will change Content-Type "application/x-download" to "application/pdf"
              #         'content_disposition' => 'attachment',   
              #         # will change Content-Disposition from "attachment" to "inline"  
              # );  
# $c->res->headers->cache_control('must-revalidate, post-check=0, pre-check=0, max-age=0');
# $c->res->headers->content_encoding('binary');
# $c->res->headers->expires(0);
# # $c->res->headers->accept_ranges('bytes');
# $c->res->headers->content_type('application/vnd.ms-excel');
# $c->res->headers->content_disposition('attachment; filename=' . $filename);
# # $c->res->headers->server('Apache');
# my $asset = Mojo::Asset::File->new( path => $filepath );
# show $asset;
# $c->res->content->asset($asset);
# $c->rendered(200);
# show $c->res;

              return  1;
          # return $c->redirect_to('/files/' . $filename);

          # $c->res->code(200);
          # my $size = (stat $filepath)[7];
          # $c->res->headers->content_type('application/x-download');
          # $c->res->headers->content_disposition('attachment; filename=' . $filename);
          # $c->res->headers->content_length();

          # use File::Slurp;
          # show $filepath;
          # $/ = undef;
          # my $body = read_file($filepath,  binmode => ':raw' );
          # show $body;
          # write_file('/tmp/test.xls',{binmode => ':raw'},$body);
          # $c->res->body($body);
          # return $c->render(data => $body);
          # return 1;

          }
          # @c = map { 
          #   my $h = flatten($_); 
          #   my @v = @$h{ @$cols };
          #   my $v = \@v; 
          # } @c;

        }

        my $jobj = {
          "draw" => $draw,
          "recordsTotal" => $total,
          "recordsFiltered" => $count,
          "data" => \@c,
          "header" => $cols
        };

        return $jobj;

  });


  $self->helper(as_query => sub {
    my $app = shift;
    my $rs = shift;

    my $pretty = SQL::QueryBuilder::Pretty->new
        if SQL::QueryBuilder::Pretty->can('new');

    sub format_sql{
        my ($sql, @values) = @_;
        $sql =~ s/\?/_sql_value(shift(@values))/ge;
        return $pretty
            ? $pretty->print($sql)
            : $sql;
    }

    sub _sql_value{
        my $value = shift;

        if (ref $value && ref $value eq 'ARRAY'){
            $value = $value->[1];
        }

        if (!defined $value){
            return 'NULL';
        }
        elsif ($value =~ /^\d+(?:\.\d+)?$/){
            return $value;
        }
        else{
            return "'$value'";
        }
    }

    sub format_resultset{
        my ($rs) = @_;
        my $query = ${ $rs->as_query };
        return format_sql(@{$query});
    }
    return format_resultset($rs);

  });


  $self->helper(gpslatlon => sub{
      my $c = shift;
      my $src = shift;
      my $dst = shift;


      if($dst){
          # my $url = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=$src&destinations=$dst&key=AIzaSyCP1YIwEFWU7WDiNbUdo4MPbOZEJcQtN9I";
my $url = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=$src&destinations=$dst&key=AIzaSyDokeXryZ4r_KJmd327UAdPr-41-ry9PAo";
# show $url;
          # AIzaSyDokeXryZ4r_KJmd327UAdPr-41-ry9PAo
          my $ua = LWP::UserAgent::JSON->new;
          my $req = HTTP::Request::JSON->new(GET => $url);
          my $response = $ua->request($req);
          # show $response;
          if($response->can('json_content')){
            if($response->json_content->{rows}->[0]->{elements}->[0]->{status} eq 'NOT_FOUND'  || $response->json_content->{status} eq 'UNKNOWN_ERROR' || $response->json_content->{status} eq 'INVALID_REQUEST'){
              # $response->json_content->{error_message};
              # show $src, $dst, $response->json_content;
            }

            my $r = $response->json_content->{"rows"}->[0]->{"elements"}->[0]->{"distance"}->{"value"};
            show $r;
            if($r){

              my $d = sprintf("%.2f", $r/1609.34);
              return $d;
            }
            return 0;
          }
          return 0;
      }else{
          # my $url = "https://maps.googleapis.com/maps/api/geocode/json?address=$src&key=AIzaSyCP1YIwEFWU7WDiNbUdo4MPbOZEJcQtN9I";
          my $url = "https://maps.googleapis.com/maps/api/geocode/json?address=$src&key=AIzaSyDokeXryZ4r_KJmd327UAdPr-41-ry9PAo";
# show $url;          
          my $ua = LWP::UserAgent::JSON->new;
          my $req = HTTP::Request::JSON->new(GET => $url);
          my $response = $ua->request($req);

          my ($lat,$lon) = (0,0);
          # show $response->json_content;
          if($response->can('json_content')){

            if($response->json_content->{status} eq 'ZERO_RESULTS' || $response->json_content->{status} eq 'UNKNOWN_ERROR'){
              # show $src, $response->json_content;
            }
# show $src, $response->json_content;
            $lat = $response->json_content->{"results"}->[0]->{"geometry"}->{"location"}->{"lat"};
            $lon = $response->json_content->{"results"}->[0]->{"geometry"}->{"location"}->{"lng"};
            return ($lat,$lon);
          }
          return (0,0);
      }
      

  });

  $self->helper(export => sub{
      return ExcelExport->export_excel(@_);
  });
  $self->helper(export_hr => sub{
      return ExcelExport->export_excel_hr(@_);
  });    
  $self->helper(export_csv => sub{
      return ExcelExport->export_csv(@_);
  });  
  $self->helper(dtconvert => sub{
    my($self,$ut) = (@_);
    return DateTime->from_epoch( epoch => $ut )->datetime();

  });

  $self->helper(form => sub {
  	my($self,$fd) = (@_);
    my $f = $self->app->objectify($fd);
  	return $f;
  });

  $self->helper(validate => sub {
    my($self,$c,$v,$j) = (@_);

    my $errors;
    foreach my $k (keys %$v){
      my ($p,$m) = $v->{$k}->($j->{$k});
      $errors->{$k} = $m unless $p;
    }
    return $errors;
  });

  my $config = $self->plugin('Config',{file=> getcwd() . '/clmapp.conf'});
  my $mailconf = $config->{mailconf};
  $self->plugin('mail' => $mailconf);

  #$self->log( Mojo::Log->new( path => getcwd() . '/logs/clmapp.log', level => 'debug' ) );

  # $self->config(hypnotoad => {listen => ['http://*:3000']});


  $self->load_defaults;
  $self->types->type(xls => 'application/vnd.ms-excel', csv => 'application/download');

  # Router
  my $r = $self->routes;
  $self->sessions->default_expiration(14400); # 4 hours
  $self->secrets(['<JgP$)]B-n!5nTsZbD3</5X']);

  $r->post('/api/user/login')->to(controller=>'User', action => 'auth');
  $r->get('/login')->to(controller=>'User', action => 'login');
  $r->get('/logout')->to(controller=>'User', action => 'logout');
  $r->any('/api/session')->to(controller=>'Root', action=>'sessionjson');
  my $a = $r->under('/')->to(controller=>'User', action => 'auth');
  $a->get('/dashboard')->to('root#dashboard');
  $a->get('/api/gps')->to('root#gps');
  $a->get('/')->to('root#dashboard');

  $a->get('/user')->to('user#index');
  $a->get('/api/user')->to('user#list');
  $a->get('/api/user/:user_id')->to(controller=>'User', action => 'read');
  $a->post('/api/user')->to(controller=>'User', action => 'create');
  $a->put('/api/user/:user_id')->to(controller=>'User', action => 'update');
  $a->delete('/api/user/:user_id')->to(controller=>'User', action => 'delete');

  $a->get('/customer')->to('customer#index');
  $a->get('/api/customer')->to('customer#list');
  $a->get('/api/customer/:customerid')->to(controller=>'Customer', action => 'read');
  $a->get('/api/customer/search')->to(controller=>'Customer', action => 'search');
  $a->post('/api/customer')->to(controller=>'Customer', action => 'create');
  $a->post('/api/customer/bulkedit')->to(controller=>'Customer', action => 'bulkeditupdate');  
  $a->put('/api/customer/:customerid')->to(controller=>'Customer', action => 'update');
  $a->delete('/api/customer/:customerid')->to(controller=>'Customer', action => 'delete');
  $a->get('/customer/report/missing')->to(controller=>'Customer', action => 'report');
  $a->get('/customer/report/orderguide')->to(controller=>'Customer', action => 'report');
  $a->get('/customer/report/gps')->to(controller=>'Customer', action => 'report');
  $a->get('/api/customer/report/missing')->to(controller=>'Customer', action => 'report_missing');
  $a->get('/api/customer/report/orderguide')->to(controller=>'Customer', action => 'report_orderguide');
  $a->get('/api/customer/report/gps')->to(controller=>'Customer', action => 'report_gps');
  $a->get('/customer/report/market')->to(controller=>'Customer', action => 'report');

  $a->get('/api/customer/report/market')->to(controller=>'Customer', action => 'report_market'); 
  $a->get('/api/customer/report/export_itn')->to(controller=>'Customer', action => 'export_itn');
  $a->get('/api/customer/report/export_itn_bp')->to(controller=>'Customer', action => 'export_itn_bp');
  # no auth, probably OK
  $r->get('/api/customer/report/export_gfs')->to(controller=>'Customer', action => 'export_gfs');
  $r->get('/api/customer/report/export_gps')->to(controller=>'Customer', action => 'export_gps');
  $a->get('/api/customer/report/export_bpunitmaster')->to(controller=>'Customer', action => 'export_bpunitmaster');
  $a->get('/api/customer/report/export_bpunitloginent')->to(controller=>'Customer', action => 'export_bpunitloginent');
  $a->get('/api/customer/report/export_bpthirdpartyacount')->to(controller=>'Customer', action => 'export_bpthirdpartyacount');
  $a->get('/api/customer/report/export_bphierarchymaster')->to(controller=>'Customer', action => 'export_bphierarchymaster');    
  $a->get('/api/customer/report/export_missing_opstatus')->to(controller=>'Customer', action => 'export_missing_opstatus');    

  $a->get('/customer/report/mismatched')->to(controller=>'Customer', action => 'report');
  $a->get('/api/customer/report/mismatched')->to(controller=>'Customer', action => 'report_mismatched');

  $a->get('/customer/report/email')->to(controller=>'Customer', action => 'report');
  $a->get('/api/customer/report/email')->to(controller=>'Customer', action => 'report_email');

  $a->get('/dmavp')->to('dmavp#index');
  $a->get('/api/dmavp')->to('dmavp#list');
  $a->get('/api/dmavp/:dmavpid')->to(controller=>'dmavp', action => 'read');
  $a->post('/api/dmavp')->to(controller=>'dmavp', action => 'create');
  $a->put('/api/dmavp/:dmavpid')->to(controller=>'dmavp', action => 'update');
  $a->delete('/api/dmavp/:dmavpid')->to(controller=>'dmavp', action => 'delete');

  $a->get('/dmaprogrammanager')->to(controller=>'DmaprogramManager',action => 'index');
  $a->get('/api/dmaprogrammanager')->to(controller=>'DmaprogramManager', action => 'list');
  $a->get('/api/dmaprogrammanager/:dmaprogrammanagerid')->to(controller=>'DmaprogramManager', action => 'read');
  $a->post('/api/dmaprogrammanager')->to(controller=>'DmaprogramManager', action => 'create');
  $a->put('/api/dmaprogrammanager/:dmaprogrammanagerid')->to(controller=>'DmaprogramManager', action => 'update');
  $a->delete('/api/dmaprogrammanager/:dmaprogrammanagerid')->to(controller=>'DmaprogramManager', action => 'delete');

  $a->get('/distributorcompany')->to(controller=>'DistributorCompany',action => 'index');
  $a->get('/api/distributorcompany')->to(controller=>'DistributorCompany', action => 'list');
  $a->get('/api/distributorcompany/:distributorcompanyid')->to(controller=>'DistributorCompany', action => 'read');
  $a->post('/api/distributorcompany')->to(controller=>'DistributorCompany', action => 'create');
  $a->put('/api/distributorcompany/:distributorcompanyid')->to(controller=>'DistributorCompany', action => 'update');
  $a->delete('/api/distributorcompany/:distributorcompanyid')->to(controller=>'DistributorCompany', action => 'delete');
  $a->get('/distributorcompany/report/address')->to(controller=>'DistributorCompany', action => 'report');
  $a->get('/api/distributorcompany/report/address')->to(controller=>'DistributorCompany', action => 'report_address');



  $a->get('/distributorwarehouse')->to(controller=>'DistributorWarehouse',action => 'index');
  $a->get('/api/distributorwarehouse')->to(controller=>'DistributorWarehouse', action => 'list');
  $a->get('/api/distributorwarehouse/:distributorwarehouseid')->to(controller=>'DistributorWarehouse', action => 'read');
  $a->post('/api/distributorwarehouse')->to(controller=>'DistributorWarehouse', action => 'create');
  $a->put('/api/distributorwarehouse/:distributorwarehouseid')->to(controller=>'DistributorWarehouse', action => 'update');
  $a->delete('/api/distributorwarehouse/:distributorwarehouseid')->to(controller=>'DistributorWarehouse', action => 'delete');
  $a->get('/distributorwarehouse/report/all')->to(controller=>'DistributorWarehouse', action => 'report');    
  $a->get('/api/distributorwarehouse/report/all')->to(controller=>'DistributorWarehouse', action => 'report_all'); 
  $a->get('/distributorwarehouse/report/gps')->to(controller=>'DistributorWarehouse', action => 'report');
  $a->get('/api/distributorwarehouse/report/gps')->to(controller=>'DistributorWarehouse', action => 'report_gps');
  $a->get('/distributorwarehouse/report/latlng')->to(controller=>'DistributorWarehouse', action => 'report');
  $a->get('/api/distributorwarehouse/report/latlng')->to(controller=>'DistributorWarehouse', action => 'report_latlng');




  $a->get('/chaingroup')->to(controller=>'ChainGroup',action => 'index');
  $a->get('/api/chaingroup')->to(controller=>'ChainGroup', action => 'list');
  $a->get('/api/chaingroup/:chaingroupid')->to(controller=>'ChainGroup', action => 'read');
  $a->post('/api/chaingroup')->to(controller=>'ChainGroup', action => 'create');
  $a->put('/api/chaingroup/:chaingroupid')->to(controller=>'ChainGroup', action => 'update');
  $a->delete('/api/chaingroup/:chaingroupid')->to(controller=>'ChainGroup', action => 'delete');    

  $a->get('/chainconcept')->to(controller=>'ChainConcept',action => 'index');
  $a->get('/api/chainconcept')->to(controller=>'ChainConcept', action => 'list');
  $a->get('/api/chainconcept/:chainconceptid')->to(controller=>'ChainConcept', action => 'read');
  $a->post('/api/chainconcept')->to(controller=>'ChainConcept', action => 'create');
  $a->put('/api/chainconcept/:chainconceptid')->to(controller=>'ChainConcept', action => 'update');
  $a->delete('/api/chainconcept/:chainconceptid')->to(controller=>'ChainConcept', action => 'delete');
  $a->get('/api/chainconcept/report/export_threshold')->to(controller=>'ChainConcept', action => 'export_threshold');
  
  $a->get('/api/chainunit/bulk_deactivate')->to(controller=>'ChainUnit',action => 'bulk_deactivate');
  $a->get('/chainunit')->to(controller=>'ChainUnit',action => 'index');
  $a->get('/api/chainunit')->to(controller=>'ChainUnit', action => 'list');
  $a->get('/api/chainunit/:chainunitid')->to(controller=>'ChainUnit', action => 'read');
  $a->post('/api/chainunit')->to(controller=>'ChainUnit', action => 'create');
  $a->put('/api/chainunit/:chainunitid')->to(controller=>'ChainUnit', action => 'update');
  $a->delete('/api/chainunit/:chainunitid')->to(controller=>'ChainUnit', action => 'delete');

  $a->get('/chainunit/report/orphaned')->to(controller=>'ChainUnit', action => 'report');
  $a->get('/chainunit/report/unassigned')->to(controller=>'ChainUnit', action => 'report');
  $a->get('/chainunit/report/mismatched')->to(controller=>'ChainUnit', action => 'report');
  $a->get('/api/chainunit/report/mismatched')->to(controller=>'ChainUnit', action => 'report_mismatched');
  $a->get('/api/chainunit/report/orphaned')->to(controller=>'ChainUnit', action => 'report_orphaned');
  $a->get('/api/chainunit/report/unassigned')->to(controller=>'ChainUnit', action => 'report_unassigned');



  $a->get('/backofficesystem')->to(controller=>'BackOfficeSystem',action => 'index');
  $a->get('/api/backofficesystem')->to(controller=>'BackOfficeSystem', action => 'list');
  $a->post('/api/backofficesystem/migrate/:systemid')->to(controller => 'BackOfficeSystem', action => 'migrate');
  $a->get('/api/backofficesystem/:systemid')->to(controller=>'BackOfficeSystem', action => 'read');
  $a->get('/api/backofficesystem/concept/:chainconceptid')->to(controller=>'BackOfficeSystem', action => 'concept');  
  $a->post('/api/backofficesystem')->to(controller=>'BackOfficeSystem', action => 'create');
  $a->put('/api/backofficesystem/:systemid')->to(controller=>'BackOfficeSystem', action => 'update');
  $a->delete('/api/backofficesystem/:systemid')->to(controller=>'BackOfficeSystem', action => 'delete');

  $a->get('/country')->to(controller=>'country',action => 'index');
  $a->get('/api/country')->to(controller=>'country', action => 'list');
  $a->get('/api/country/:countrycode')->to(controller=>'country', action => 'read');
  $a->post('/api/country')->to(controller=>'country', action => 'create');
  $a->put('/api/country/:countrycode')->to(controller=>'country', action => 'update');
  $a->delete('/api/country/:countrycode')->to(controller=>'country', action => 'delete');  

  $a->get('/operatingstatus')->to(controller=>'OperatingStatus',action => 'index');
  $a->get('/api/operatingstatus')->to(controller=>'OperatingStatus', action => 'list');
  $a->get('/api/operatingstatus/:operatingstatusid')->to(controller=>'OperatingStatus', action => 'read');
  $a->post('/api/operatingstatus')->to(controller=>'OperatingStatus', action => 'create');
  $a->put('/api/operatingstatus/:operatingstatusid')->to(controller=>'OperatingStatus', action => 'update');
  $a->delete('/api/operatingstatus/:operatingstatusid')->to(controller=>'OperatingStatus', action => 'delete'); 

  # $self->max_request_size(1073741824);
  $a->get('/import')->to(controller=>'Import',action => 'index');
  $a->post('/import/excel')->to(controller=>'Import',action => 'excel');
  $a->post('/import/itn')->to(controller=>'Import',action => 'itn');
  $a->post('/api/import/itn')->to(controller=>'Import',action => 'itn2');

  $a->any('/api/datatable/view/:table')->to(controller=>'DataTable', action => 'list');
  $a->get('/api/datatable/view/:table/:key')->to(controller=>'DataTable', action => 'read');
  $a->delete('/api/datatable/view/:table/:key')->to(controller=>'DataTable', action => 'delete');

  $a->get('/bpmigration')->to(controller=>'Bpmigration', action => 'index');
  $a->get('/api/bpmigration')->to(controller=>'Bpmigration', action => 'list');

  $a->get('/bpmigration/credential')->to(controller=>'Bpmigration', action => 'credential');
  $a->get('/api/bpmigration/credential')->to(controller=>'Bpmigration', action => 'credentiallist');

  $a->any('/api/bpmigration/check')->to(controller=>'Bpmigration', action => 'check');
  $a->any('/api/bpmigration/migrate/#bpmigrationid')->to(controller=>'Bpmigration', action => 'migrate');
  $a->any('/api/bpmigration/delete/#bpmigrationid')->to(controller=>'Bpmigration', action => 'markdeleted');
  $a->post('/api/bpmigration/list')->to(controller=>'Bpmigration', action => 'list');
  $a->get('/api/bpmigration/#bpmigrationid')->to(controller=>'Bpmigration', action => 'read');
  $a->post('/api/bpmigration')->to(controller=>'Bpmigration', action => 'create');
  $a->put('/api/bpmigration/#bpmigrationid')->to(controller=>'Bpmigration', action => 'update');
  $a->delete('/api/bpmigration/#bpmigrationid')->to(controller=>'Bpmigration', action => 'delete');

  $a->get('/emailnotification')->to(controller=>'EmailNotification', action => 'index');
  $a->get('/api/emailnotification')->to(controller=>'EmailNotification', action => 'list');
  # $a->any('/api/emailnotification/check')->to(controller=>'EmailNotification', action => 'check');
  # $a->any('/api/emailnotification/migrate/#emailnotificationid')->to(controller=>'EmailNotification', action => 'migrate');
  $a->get('/api/emailnotification/template')->to(controller=>'EmailNotification', action => 'template');
  $a->post('/api/emailnotification/list')->to(controller=>'EmailNotification', action => 'list');
  $a->get('/api/emailnotification/#emailnotificationid')->to(controller=>'EmailNotification', action => 'read');
  $a->post('/api/emailnotification')->to(controller=>'EmailNotification', action => 'create');
  $a->put('/api/emailnotification/#emailnotificationid')->to(controller=>'EmailNotification', action => 'update');
  $a->delete('/api/emailnotification/#emailnotificationid')->to(controller=>'EmailNotification', action => 'delete');

  $a->get('/opf')->to(controller=>'Root', action => 'opf');
  $a->get('/opf/*file')->to(controller=>'Root', action => 'opfdownload');
  $a->get('/opfftp/*file')->to(controller=>'Root', action => 'opfftp');
  $a->get('/opfftpupload/*file')->to(controller=>'Root', action => 'opfftpupload');

  $a->get('/opfreturnfile')->to(controller=>'Root', action => 'opfreturnfile');

  $a->get('/bulkedithistory')->to(controller=>'BulkEditHistory',action => 'index');
  $a->get('/api/bulkedithistory')->to(controller=>'BulkEditHistory', action => 'list');
  $a->get('/api/bulkedithistory/:id')->to(controller=>'BulkEditHistory', action => 'read');
  $a->post('/api/bulkedithistory')->to(controller=>'BulkEditHistory', action => 'create');
  $a->put('/api/bulkedithistory/:id')->to(controller=>'BulkEditHistory', action => 'update');
  $a->delete('/api/bulkedithistory/:id')->to(controller=>'BulkEditHistory', action => 'delete');  

  $a->get('/setting')->to(controller=>'Setting', action => 'index');
  $a->get('/api/setting')->to(controller=>'Setting', action => 'list');
  $a->post('/api/setting/list')->to(controller=>'Setting', action => 'list');
  $a->get('/api/setting/#id')->to(controller=>'Setting', action => 'read');
  $a->post('/api/setting')->to(controller=>'Setting', action => 'create');
  $a->put('/api/setting/#id')->to(controller=>'Setting', action => 'update');
  $a->delete('/api/setting/#id')->to(controller=>'Setting', action => 'delete');

  $a->get('/orderinvoicesystem')->to(controller=>'OrderInvoiceSystem', action => 'index');
  $a->get('/api/orderinvoicesystem')->to(controller=>'OrderInvoiceSystem', action => 'list');
  $a->post('/api/orderinvoicesystem/list')->to(controller=>'OrderInvoiceSystem', action => 'list');
  $a->get('/api/orderinvoicesystem/#id')->to(controller=>'OrderInvoiceSystem', action => 'read');
  $a->post('/api/orderinvoicesystem')->to(controller=>'OrderInvoiceSystem', action => 'create');
  $a->put('/api/orderinvoicesystem/#id')->to(controller=>'OrderInvoiceSystem', action => 'update');
  $a->delete('/api/orderinvoicesystem/#id')->to(controller=>'OrderInvoiceSystem', action => 'delete');

  $a->get('/customwarehouse')->to(controller=>'CustomWarehouse', action => 'index');
  $a->get('/api/customwarehouse')->to(controller=>'CustomWarehouse', action => 'list');
  $a->post('/api/customwarehouse/list')->to(controller=>'CustomWarehouse', action => 'list');
  $a->get('/api/customwarehouse/#id')->to(controller=>'CustomWarehouse', action => 'read');
  $a->post('/api/customwarehouse')->to(controller=>'CustomWarehouse', action => 'create');
  $a->put('/api/customwarehouse/#id')->to(controller=>'CustomWarehouse', action => 'update');
  $a->delete('/api/customwarehouse/#id')->to(controller=>'CustomWarehouse', action => 'delete');

  $a->get('/market')->to(controller=>'Market', action => 'index');
  $a->get('/api/market')->to(controller=>'Market', action => 'list');
  $a->post('/api/market/list')->to(controller=>'Market', action => 'list');
  $a->get('/api/market/#marketid')->to(controller=>'Market', action => 'read');
  $a->post('/api/market')->to(controller=>'Market', action => 'create');
  $a->put('/api/market/#marketid')->to(controller=>'Market', action => 'update');
  $a->delete('/api/market/#marketid')->to(controller=>'Market', action => 'delete');

  $a->get('/routing')->to(controller=>'Routing', action => 'index');
  $a->get('/api/routing')->to(controller=>'Routing', action => 'list');
  $a->post('/api/routing/list')->to(controller=>'Routing', action => 'list');
  $a->get('/api/routing/#routingid')->to(controller=>'Routing', action => 'read');
  $a->post('/api/routing')->to(controller=>'Routing', action => 'create');
  $a->put('/api/routing/#routingid')->to(controller=>'Routing', action => 'update');
  $a->delete('/api/routing/#routingid')->to(controller=>'Routing', action => 'delete');

  $a->get('/list')->to(controller=>'ListModule', action=>'index');
  $a->get('/api/list/list')->to(controller=>'ListModule', action=>'index');
  $a->get('/api/list/#listid')->to(controller=>'ListModule', action => 'read');
  $a->post('/api/list')->to(controller=>'ListModule', action => 'create');
  $a->put('/api/list/#listid')->to(controller=>'ListModule', action => 'update');
  $a->delete('/api/list/#listid')->to(controller=>'ListModule', action => 'delete');  

  $a->get('/customersystem')->to(controller=>'CustomerSystem', action => 'index');
  $a->get('/api/customersystem')->to(controller=>'CustomerSystem', action => 'list');
  $a->post('/api/customersystem/list')->to(controller=>'CustomerSystem', action => 'list');
  $a->post('/api/customersystem/market')->to(controller=>'CustomerSystem', action => 'market');
  $a->get('/api/customersystem/#customersystemid')->to(controller=>'CustomerSystem', action => 'read');
  $a->post('/api/customersystem')->to(controller=>'CustomerSystem', action => 'create');
  $a->put('/api/customersystem/#customersystemid')->to(controller=>'CustomerSystem', action => 'update');
  $a->delete('/api/customersystem/#customersystemid')->to(controller=>'CustomerSystem', action => 'delete');


  $a->post('/api/customertemplate/lookup')->to(controller=>'CustomerTemplate', action => 'lookup');
  $a->get('/customertemplate')->to(controller=>'CustomerTemplate', action => 'index');
  $a->get('/api/customertemplate')->to(controller=>'CustomerTemplate', action => 'list');
  $a->post('/api/customertemplate/list')->to(controller=>'CustomerTemplate', action => 'list');
  $a->get('/api/customertemplate/#customertemplateid')->to(controller=>'CustomerTemplate', action => 'read');
  $a->post('/api/customertemplate')->to(controller=>'CustomerTemplate', action => 'create');
  $a->put('/api/customertemplate/#customertemplateid')->to(controller=>'CustomerTemplate', action => 'update');
  $a->delete('/api/customertemplate/#customertemplateid')->to(controller=>'CustomerTemplate', action => 'delete');

  $a->get('/entitytype')->to(controller=>'EntityType', action => 'index');
  $a->get('/api/entitytype')->to(controller=>'EntityType', action => 'list');
  $a->post('/api/entitytype/list')->to(controller=>'EntityType', action => 'list');
  $a->get('/api/entitytype/#entitytypeid')->to(controller=>'EntityType', action => 'read');
  $a->post('/api/entitytype')->to(controller=>'EntityType', action => 'create');
  $a->put('/api/entitytype/#entitytypeid')->to(controller=>'EntityType', action => 'update');
  $a->delete('/api/entitytype/#entitytypeid')->to(controller=>'EntityType', action => 'delete');

  $a->get('/warehousechain')->to(controller=>'WarehouseChain', action => 'index');
  $a->get('/api/warehousechain')->to(controller=>'WarehouseChain', action => 'list');
  $a->post('/api/warehousechain/list')->to(controller=>'WarehouseChain', action => 'list');
  $a->get('/api/warehousechain/#warehousechainid')->to(controller=>'WarehouseChain', action => 'read');
  $a->post('/api/warehousechain')->to(controller=>'WarehouseChain', action => 'create');
  $a->put('/api/warehousechain/#warehousechainid')->to(controller=>'WarehouseChain', action => 'update');
  $a->delete('/api/warehousechain/#warehousechainid')->to(controller=>'WarehouseChain', action => 'delete');

  # $a->get('/listmodule')->to(controller=>'Root', action=>'listmodule');
# create
  # $a->post('/api/datatable/view')->to(controller=>'DataTable', action => 'create');

  $a->get('/customercomment')->to(controller=>'CustomerComment', action => 'index');
  $a->get('/api/customercomment')->to(controller=>'CustomerComment', action => 'list');
  $a->post('/api/customercomment/list')->to(controller=>'CustomerComment', action => 'list');
  $a->get('/api/customercomment/#customercommentid')->to(controller=>'CustomerComment', action => 'read');
  $a->post('/api/customercomment')->to(controller=>'CustomerComment', action => 'create');
  $a->put('/api/customercomment/#customercommentid')->to(controller=>'CustomerComment', action => 'update');
  $a->delete('/api/customercomment/#customercommentid')->to(controller=>'CustomerComment', action => 'delete');




  show %ENV;

}

sub END{



}

1;

