6 <& /elements/header-cust_main.html,
8 cust_main => $cust_main,
9 include_selectize => 1,
11 <% include('/elements/error.html') %>
15 let locationnum = "<% $cust_main->ship_locationnum %>";
17 function location_changed(e) {
18 locationnum = $(e).val();
19 $('tr[data-locationnum]').find('input').prop('checked', false);
20 $('tr[data-locationnum]').each( function() {
24 locationnum == tr_el.data('locationnum') ? 'table-row' : 'none'
29 function pkg_class_filter_onchange( selected ) {
30 if ( selected.length == 0 ) {
31 $('tr[data-classnum]').css('display', 'table-row');
33 $('tr[data-classnum]').each( function() {
35 let classnum = tr_el.data('classnum');
36 let is_displayed = $.grep( selected, function( item ) {
37 return item == classnum;
39 let display = is_displayed.length ? 'table-row' : 'none';
40 tr_el.css( 'display', is_displayed.length ? 'table-row' : 'none' );
45 function confirm_form() {
46 let cust_pkg_removed = [];
47 let pkg_part_added = [];
49 $('input[data-locationnum]:checked').each( function() {
50 let this_el = $(this);
51 cust_pkg_removed.push(
52 '#' + this_el.data('pkgnum') + ' ' + this_el.data('pkg')
56 $('input[data-pkgpart]').each( function() {
60 if ( qty < 1 ) { return; }
62 pkg_part_added.push( qty + ' x ' + qty_el.data('pkg') );
65 if ( cust_pkg_removed.length == 0 ) {
66 cust_pkg_removed.push('No Existing Packages Selected');
68 if ( pkg_part_added.length == 0 ) {
69 pkg_part_added.push('No New Packages Selected');
72 console.log( cust_pkg_removed );
73 console.log( pkg_part_added );
76 '<div style="margin: 1em;">'
77 + '<b><u>Removed Packages:</u></b><br>'
78 + cust_pkg_removed.join('<br>')
80 + '<b><u>Replacement Packages:</u></b><br>'
81 + pkg_part_added.join('<br>')
83 + '<input type="button" role="button" onclick="submit_form();" value="Confirm Order">'
88 CAPTION, 'Confirm bulk change',
101 function submit_form() {
102 $('#formBulkEdit').submit();
106 <form action="<% $fsurl %>edit/process/cust_pkg.cgi" method="POST" id="formBulkEdit">
107 <input type="hidden" name="custnum" value="<% $custnum %>">
108 <input type="hidden" name="action" value="bulk">
110 <p style="margin-bottom: 2em;">
111 <label for="locationnum">Service Location</label>
112 <% include( '/elements/select-cust_location.html',
113 cust_main => $cust_main,
115 onchange => 'javascript:location_changed(this);',
117 <span style="font-size: .8em; padding-left: 1em;">
118 Bulk-edit works with one customer location at a time
122 <table style="margin-bottom: 2em;">
124 <tr style="background-color: #ccc;">
125 <th colspan="2" style="text-align: left;">
128 <th style="text-align: left;">
130 <div style="font-size: .8em; padding-left: 1em; font-weight: normal;">
131 Selected packages are removed.<br>
132 Attached services are moved to the new package selected below
138 % for my $cust_pkg ( @cust_pkg ) {
139 % my $id = sprintf 'remove_cust_pkg[%s]', $cust_pkg->pkgnum;
140 % my $is_displayed = $cust_main->ship_locationnum == $cust_pkg->locationnum ? 1 : 0;
141 <tr data-locationnum="<% $cust_pkg->locationnum %>" data-pkg="<% $cust_pkg->pkg |h %>" style="display: <% $is_displayed ? 'table-row' : 'none' %>;">
143 <input type="checkbox"
146 data-pkgnum="<% $cust_pkg->pkgnum %>"
147 data-locationnum="<% $cust_pkg->locationnum %>"
148 data-pkg="<% $part_pkg{ $cust_pkg->pkgpart }->pkg |h %>">
150 <td>#<% $cust_pkg->pkgnum %></td>
152 <label for="<% $id %>">
153 <% $part_pkg{ $cust_pkg->pkgpart }->pkg %><br>
154 % for my $cust_pkg_supp ( @{ $cust_pkg_supp_of{ $cust_pkg->pkgnum }} ) {
155 <span style="font-size: .8em; padding-left: 1em;">
156 <b>Supplementary:</b> <% $part_pkg{ $cust_pkg_supp->pkgpart }->pkg %>
166 <table style="margin-bottom: 2em;">
168 <tr style="background-color: #ccc;">
170 <% include('/elements/selectize/select-multiple-pkg_class.html',
171 id => 'filter_pkg_class',
172 onchange => 'pkg_class_filter_onchange',
176 <tr style="background-color: #ccc;">
179 <th style="text-align: left;">Order New Packages</th>
183 % for my $part_pkg ( @part_pkg_enabled ) {
184 % my $id = sprintf 'qty_part_pkg[%s]', $part_pkg->pkgpart;
185 <tr data-classnum="<% $part_pkg->classnum %>">
192 data-pkgpart="<% $part_pkg->pkgpart %>"
193 data-pkg="<% $part_pkg->pkg %>">
195 <td><% $part_pkg->classname || '(none)' %></td>
196 <td><% $part_pkg->pkg %></td>
202 <input type="button" role="button" value="Order" onclick="confirm_form();">
206 <% include('/elements/footer.html') %>
211 unless $FS::CurrentUser::CurrentUser->access_right('Bulk change customer packages');
213 my $custnum = $cgi->param('keywords') || $cgi->param('custnum');
215 or die "Invalid custnum($custnum)";
217 my $cust_main = qsearchs( cust_main => { custnum => $custnum })
218 or die "Invalid custnum ($custnum)";
221 my @part_pkg_enabled;
223 for my $part_pkg ( qsearch( part_pkg => {} )) {
224 $part_pkg{ $part_pkg->pkgpart } = $part_pkg;
225 push @part_pkg_enabled, $part_pkg
226 unless $part_pkg->disabled;
229 sort { $a->classname cmp $b->classname || $a->pkg cmp $b->pkg }
233 my %cust_pkg_supp_of;
242 if ( my $main_pkgnum = $cust_pkg->main_pkgnum ) {
243 $cust_pkg_supp_of{ $main_pkgnum } //= [];
244 push @{ $cust_pkg_supp_of{ $main_pkgnum } }, $cust_pkg;
246 $cust_pkg_supp_of{ $cust_pkg->pkgnum } //= [];
247 push @cust_pkg, $cust_pkg;