1package App::Netdisco::Web::Plugin::Report::ModuleInventory;
2
3use Dancer ':syntax';
4use Dancer::Plugin::DBIC;
5use Dancer::Plugin::Auth::Extensible;
6use App::Netdisco::Util::ExpandParams 'expand_hash';
7
8use App::Netdisco::Web::Plugin;
9use List::MoreUtils ();
10
11register_report(
12    {   category     => 'Device',
13        tag          => 'moduleinventory',
14        label        => 'Module Inventory',
15        provides_csv => 1,
16    }
17);
18
19hook 'before_template' => sub {
20    my $tokens = shift;
21
22    return
23        unless (
24        request->path eq uri_for('/report/moduleinventory')->path
25        or index( request->path,
26            uri_for('/ajax/content/report/moduleinventory')->path ) == 0
27        );
28
29    # used in the search sidebar template to set selected items
30    foreach my $opt (qw/class/) {
31        my $p = (
32            ref [] eq ref param($opt)
33            ? param($opt)
34            : ( param($opt) ? [ param($opt) ] : [] )
35        );
36        $tokens->{"${opt}_lkp"} = { map { $_ => 1 } @$p };
37    }
38};
39
40get '/ajax/content/report/moduleinventory/data' => require_login sub {
41    send_error( 'Missing parameter', 400 )
42        unless ( param('draw') && param('draw') =~ /\d+/ );
43
44    my $rs = schema('netdisco')->resultset('DeviceModule');
45    $rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
46
47    if ( param('device') ) {
48        my @ips = schema('netdisco')->resultset('Device')
49            ->search_fuzzy( param('device') )->get_column('ip')->all;
50
51        params->{'ips'} = \@ips;
52    }
53
54    $rs = $rs->search_by_field( scalar params )->columns(
55        [   'ip',     'description', 'name',   'class',
56            'type',   'serial',      'hw_ver', 'fw_ver',
57            'sw_ver', 'model'
58        ]
59        )->search(
60        {},
61        {   '+columns' => [qw/ device.dns device.name /],
62            join       => 'device',
63            collapse   => 1,
64        }
65        );
66
67    my $exp_params = expand_hash( scalar params );
68
69    my $recordsTotal = $rs->count;
70
71    my @data = $rs->get_datatables_data($exp_params)->hri->all;
72
73    my $recordsFiltered = $rs->get_datatables_filtered_count($exp_params);
74
75    content_type 'application/json';
76    return to_json(
77        {   draw            => int( param('draw') ),
78            recordsTotal    => int($recordsTotal),
79            recordsFiltered => int($recordsFiltered),
80            data            => \@data,
81        }
82    );
83};
84
85get '/ajax/content/report/moduleinventory' => require_login sub {
86
87    my $has_opt = List::MoreUtils::any { param($_) }
88    qw/device description name type model serial class/;
89
90    my $rs = schema('netdisco')->resultset('DeviceModule');
91    $rs = $rs->search( { -bool => 'fru' } ) if param('fruonly');
92    my @results;
93
94    if ( $has_opt && !request->is_ajax ) {
95
96        if ( param('device') ) {
97            my @ips = schema('netdisco')->resultset('Device')
98                ->search_fuzzy( param('device') )->get_column('ip')->all;
99
100            params->{'ips'} = \@ips;
101        }
102
103        @results = $rs->search_by_field( scalar params )->columns(
104            [   'ip',     'description', 'name',   'class',
105                'type',   'serial',      'hw_ver', 'fw_ver',
106                'sw_ver', 'model'
107            ]
108            )->search(
109            {},
110            {   '+columns' => [qw/ device.dns device.name /],
111                join       => 'device',
112                collapse   => 1,
113            }
114            )->hri->all;
115
116        return unless scalar @results;
117    }
118    elsif ( !$has_opt ) {
119        @results = $rs->search(
120            { class => { '!=', undef } },
121            {   select   => [ 'class', { count => 'class' } ],
122                as       => [qw/ class count /],
123                group_by => [qw/ class /]
124            }
125        )->order_by( { -desc => 'count' } )->hri->all;
126
127        return unless scalar @results;
128    }
129
130    if ( request->is_ajax ) {
131        my $json = to_json( \@results );
132        template 'ajax/report/moduleinventory.tt',
133            { results => $json, opt => $has_opt },
134            { layout => undef };
135    }
136    else {
137        header( 'Content-Type' => 'text/comma-separated-values' );
138        template 'ajax/report/moduleinventory_csv.tt',
139            { results => \@results, opt => $has_opt },
140            { layout => undef };
141    }
142};
143
1441;
145