safe web demo operation! closes: Bug#217
[freeside.git] / httemplate / edit / part_pkg.cgi
1 <!-- mason kludge -->
2 <%
3
4 if ( $cgi->param('clone') && $cgi->param('clone') =~ /^(\d+)$/ ) {
5   $cgi->param('clone', $1);
6 } else {
7   $cgi->param('clone', '');
8 }
9 if ( $cgi->param('pkgnum') && $cgi->param('pkgnum') =~ /^(\d+)$/ ) {
10   $cgi->param('pkgnum', $1);
11 } else {
12   $cgi->param('pkgnum', '');
13 }
14
15 my ($query) = $cgi->keywords;
16 my $action = '';
17 my $part_pkg = '';
18 if ( $cgi->param('error') ) {
19   $part_pkg = new FS::part_pkg ( {
20     map { $_, scalar($cgi->param($_)) } fields('part_pkg')
21   } );
22 }
23 if ( $cgi->param('clone') ) {
24   $action='Custom Pricing';
25   my $old_part_pkg =
26     qsearchs('part_pkg', { 'pkgpart' => $cgi->param('clone') } );
27   $part_pkg ||= $old_part_pkg->clone;
28   $part_pkg->disabled('Y');
29 } elsif ( $query && $query =~ /^(\d+)$/ ) {
30   $part_pkg ||= qsearchs('part_pkg',{'pkgpart'=>$1});
31 } else {
32   unless ( $part_pkg ) {
33     $part_pkg = new FS::part_pkg {};
34     $part_pkg->plan('flat');
35   }
36 }
37 unless ( $part_pkg->plan ) { #backwards-compat
38   $part_pkg->plan('flat');
39   $part_pkg->plandata("setup_fee=". $part_pkg->setup. "\n".
40                       "recur_fee=". $part_pkg->recur. "\n");
41 }
42 $action ||= $part_pkg->pkgpart ? 'Edit' : 'Add';
43 my $hashref = $part_pkg->hashref;
44
45 %>
46
47 <SCRIPT>
48 function visualize(what) {
49   if (document.getElementById) {
50     document.getElementById('d<%= $part_pkg->plan %>').style.visibility = "visible";
51   } else {
52     document.l<%= $part_pkg->plan %>.visibility = "visible";
53   }
54 }
55 </SCRIPT>
56
57 <% 
58
59 print header("$action Package Definition", menubar(
60   'Main Menu' => popurl(2),
61   'View all packages' => popurl(2). 'browse/part_pkg.cgi',
62 ), ' onLoad="visualize()"');
63
64 print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'),
65       "</FONT>"
66   if $cgi->param('error');
67
68 #print '<FORM ACTION="', popurl(1), 'process/part_pkg.cgi" METHOD=POST>';
69 print '<FORM NAME="dummy">';
70
71 #if ( $cgi->param('clone') ) {
72 #  print qq!<INPUT TYPE="hidden" NAME="clone" VALUE="!, $cgi->param('clone'), qq!">!;
73 #}
74 #if ( $cgi->param('pkgnum') ) {
75 #  print qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="!, $cgi->param('pkgnum'), qq!">!;
76 #}
77 #
78 #print qq!<INPUT TYPE="hidden" NAME="pkgpart" VALUE="$hashref->{pkgpart}">!,
79 print "Package Part #", $hashref->{pkgpart} ? $hashref->{pkgpart} : "(NEW)";
80
81 print ntable("#cccccc",2), <<END;
82 <TR><TD ALIGN="right">Package (customer-visable)</TD><TD><INPUT TYPE="text" NAME="pkg" SIZE=32 VALUE="$hashref->{pkg}"></TD></TR>
83 <TR><TD ALIGN="right">Comment (customer-hidden)</TD><TD><INPUT TYPE="text" NAME="comment" SIZE=32 VALUE="$hashref->{comment}"></TD></TR>
84 <TR><TD ALIGN="right">Frequency (months) of recurring fee</TD><TD><INPUT TYPE="text" NAME="freq" VALUE="$hashref->{freq}" SIZE=3></TD></TR>
85 <TR><TD ALIGN="right">Setup fee tax exempt</TD><TD>
86 END
87
88 print '<INPUT TYPE="checkbox" NAME="setuptax" VALUE="Y"';
89 print ' CHECKED' if $hashref->{setuptax} eq "Y";
90 print '>';
91
92 print <<END;
93 </TD></TR>
94 <TR><TD ALIGN="right">Recurring fee tax exempt</TD><TD>
95 END
96
97 print '<INPUT TYPE="checkbox" NAME="recurtax" VALUE="Y"';
98 print ' CHECKED' if $hashref->{recurtax} eq "Y";
99 print '>';
100
101 print '</TD></TR>';
102
103 print '<TR><TD ALIGN="right">Disable new orders</TD><TD>';
104 print '<INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"';
105 print ' CHECKED' if $hashref->{disabled} eq "Y";
106 print '>';
107 print '</TD></TR></TABLE>';
108
109 my $thead =  "\n\n". ntable('#cccccc', 2). <<END;
110 <TR><TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Quan.</FONT></TH><TH BGCOLOR="#dcdcdc">Service</TH></TR>
111 END
112
113 unless ( $cgi->param('clone') ) {
114   #print <<END, $thead;
115   print <<END, itable(), '<TR><TD VALIGN="top">', $thead;
116 <BR><BR>Enter the quantity of each service this package includes.<BR><BR>
117 END
118 }
119
120 my @fixups = ();
121 my $count = 0;
122 my $columns = 3;
123 my @part_svc = qsearch( 'part_svc', { 'disabled' => '' } );
124 foreach my $part_svc ( @part_svc ) {
125   my $svcpart = $part_svc->svcpart;
126   my $pkg_svc = qsearchs( 'pkg_svc', {
127     'pkgpart'  => $cgi->param('clone') || $part_pkg->pkgpart,
128     'svcpart'  => $svcpart,
129   } ) || new FS::pkg_svc ( {
130     'pkgpart'  => $cgi->param('clone') || $part_pkg->pkgpart,
131     'svcpart'  => $svcpart,
132     'quantity' => 0,
133   });
134   #? #next unless $pkg_svc;
135
136   push @fixups, "pkg_svc$svcpart";
137
138   unless ( defined ($cgi->param('clone')) && $cgi->param('clone') ) {
139     print '<TR>'; # if $count == 0 ;
140     print qq!<TD><INPUT TYPE="text" NAME="pkg_svc$svcpart" SIZE=4 MAXLENGTH=3 VALUE="!,
141           $cgi->param("pkg_svc$svcpart") || $pkg_svc->quantity || 0,
142           qq!"></TD><TD><A HREF="part_svc.cgi?!,$part_svc->svcpart,
143           qq!">!, $part_svc->getfield('svc'), "</A></TD></TR>";
144 #    print "</TABLE></TD><TD>$thead" if ++$count == int(scalar(@part_svc) / 2);
145     $count+=1;
146     foreach ( 1 .. $columns-1 ) {
147       print "</TABLE></TD><TD VALIGN=\"top\">$thead"
148         if $count == int( $_ * scalar(@part_svc) / $columns );
149     }
150   } else {
151     print qq!<INPUT TYPE="hidden" NAME="pkg_svc$svcpart" VALUE="!,
152           $cgi->param("pkg_svc$svcpart") || $pkg_svc->quantity || 0, qq!">\n!;
153   }
154 }
155
156 unless ( $cgi->param('clone') ) {
157   print "</TR></TABLE></TD></TR></TABLE>";
158   #print "</TR></TABLE>";
159 }
160
161 # prolly should be in database
162 use Tie::IxHash;
163 tie my %plans, 'Tie::IxHash',
164   'flat' => {
165     'name' => 'Flat rate',
166     'fields' => {
167       'setup_fee' => { 'name' => 'Setup fee for this package',
168                        'default' => 0,
169                      },
170       'recur_fee' => { 'name' => 'Recurring fee for this package',
171                        'default' => 0,
172                       },
173     },
174     'fieldorder' => [ 'setup_fee', 'recur_fee' ],
175     'setup' => 'what.setup_fee.value',
176     'recur' => 'what.recur_fee.value',
177   },
178
179   'prorate' => {
180     'name' => 'First month pro-rated, then flat-rate',
181     'fields' =>  {
182       'setup_fee' => { 'name' => 'Setup fee for this package',
183                        'default' => 0,
184                      },
185       'recur_fee' => { 'name' => 'Recurring fee for this package',
186                        'default' => 0,
187                       },
188     },
189     'fieldorder' => [ 'setup_fee', 'recur_fee' ],
190     'setup' => 'what.setup_fee.value',
191     'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; my $mstart = timelocal(0,0,0,1,$mon,$year); my $mend = timelocal(0,0,0,1, $mon == 11 ? 0 : $mon+1, $year+($mon==11)); $sdate = $mstart; ( $part_pkg->freq - 1 ) * \' + what.recur_fee.value + \' / $part_pkg->freq + \' + what.recur_fee.value + \' / $part_pkg->freq * ($mend-$mnow) / ($mend-$mstart) ; \'',
192   },
193
194   'flat_comission_cust' => {
195     'name' => 'Flat rate with recurring comission per active customer',
196     'fields' => {
197       'setup_fee' => { 'name' => 'Setup fee for this package',
198                        'default' => 0,
199                      },
200       'recur_fee' => { 'name' => 'Recurring fee for this package',
201                        'default' => 0,
202                      },
203       'comission_amount' => { 'name' => 'Comission amount per month (per active customer)',
204                               'default' => 0,
205                             },
206       'comission_depth'  => { 'name' => 'Number of layers',
207                               'default' => 1,
208                             },
209     },
210     'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ],
211     'setup' => 'what.setup_fee.value',
212     'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_main_ncancelled(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
213   },
214
215   'flat_comission' => {
216     'name' => 'Flat rate with recurring comission per (any) active package',
217     'fields' => {
218       'setup_fee' => { 'name' => 'Setup fee for this package',
219                        'default' => 0,
220                      },
221       'recur_fee' => { 'name' => 'Recurring fee for this package',
222                        'default' => 0,
223                      },
224       'comission_amount' => { 'name' => 'Comission amount per month (per active package)',
225                               'default' => 0,
226                             },
227       'comission_depth'  => { 'name' => 'Number of layers',
228                               'default' => 1,
229                             },
230     },
231     'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ],
232     'setup' => 'what.setup_fee.value',
233     'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
234   },
235
236   'flat_comission_pkg' => {
237     'name' => 'Flat rate with recurring comission per (selected) active package',
238     'fields' => {
239       'setup_fee' => { 'name' => 'Setup fee for this package',
240                        'default' => 0,
241                      },
242       'recur_fee' => { 'name' => 'Recurring fee for this package',
243                        'default' => 0,
244                      },
245       'comission_amount' => { 'name' => 'Comission amount per month (per uncancelled package)',
246                               'default' => 0,
247                             },
248       'comission_depth'  => { 'name' => 'Number of layers',
249                               'default' => 1,
250                             },
251       'comission_pkgpart' => { 'name' => 'Applicable packages<BR><FONT SIZE="-1">(hold <b>ctrl</b> to select multiple packages)</FONT>',
252                                'type' => 'select_multiple',
253                                'select_table' => 'part_pkg',
254                                'select_hash'  => { 'disabled' => '' } ,
255                                'select_key'   => 'pkgpart',
256                                'select_label' => 'pkg',
257                              },
258     },
259     'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount', 'comission_pkgpart' ],
260     'setup' => 'what.setup_fee.value',
261     'recur' => '""; var pkgparts = ""; for ( var c=0; c < document.flat_comission_pkg.comission_pkgpart.options.length; c++ ) { if (document.flat_comission_pkg.comission_pkgpart.options[c].selected) { pkgparts = pkgparts + document.flat_comission_pkg.comission_pkgpart.options[c].value + \', \'; } } what.recur.value = \'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar( grep { my $pkgpart = $_->pkgpart; grep { $_ == $pkgpart } ( \' + pkgparts + \'  ) } $cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
262   },
263
264
265
266   'sesmon_hour' => {
267     'name' => 'Base charge plus charge per-hour from the session monitor',
268     'fields' => {
269       'setup_fee' => { 'name' => 'Setup fee for this package',
270                        'default' => 0,
271                      },
272       'recur_flat' => { 'name' => 'Base monthly charge for this package',
273                         'default' => 0,
274                       },
275       'recur_included_hours' => { 'name' => 'Hours included',
276                                   'default' => 0,
277                                 },
278       'recur_hourly_charge' => { 'name' => 'Additional charge per hour',
279                                  'default' => 0,
280                                },
281     },
282     'fieldorder' => [ 'setup_fee', 'recur_flat', 'recur_included_hours', 'recur_hourly_charge' ],
283     'setup' => 'what.setup_fee.value',
284     'recur' => '\'my $hours = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; \' + what.recur_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'',
285   },
286
287   'sesmon_minute' => {
288     'name' => 'Base charge plus charge per-minute from the session monitor',
289     'fields' => {
290       'setup_fee' => { 'name' => 'Setup fee for this package',
291                        'default' => 0,
292                      },
293       'recur_flat' => { 'name' => 'Base monthly charge for this package',
294                         'default' => 0,
295                       },
296       'recur_included_min' => { 'name' => 'Minutes included',
297                                 'default' => 0,
298                                 },
299       'recur_minly_charge' => { 'name' => 'Additional charge per minute',
300                                 'default' => 0,
301                               },
302     },
303     'fieldorder' => [ 'setup_fee', 'recur_flat', 'recur_included_min', 'recur_minly_charge' ],
304     'setup' => 'what.setup_fee.value',
305     'recur' => '\'my $min = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 60 - \' + what.recur_included_min.value + \'; $min = 0 if $min < 0; \' + what.recur_flat.value + \' + \' + what.recur_minly_charge.value + \' * $min;\'',
306
307   },
308
309 ;
310
311 %>
312
313 <SCRIPT>
314 var layer = null;
315
316 function changed(what) {
317   layer = what.options[what.selectedIndex].value;
318 <% foreach my $layer ( keys %plans ) { %>
319   if (layer == "<%= $layer %>" ) {
320     <% foreach my $not ( grep { $_ ne $layer } keys %plans ) { %>
321       if (document.getElementById) {
322         document.getElementById('d<%= $not %>').style.visibility = "hidden";
323       } else {
324         document.l<%= $not %>.visibility = "hidden";
325       }
326     <% } %>
327     if (document.getElementById) {
328       document.getElementById('d<%= $layer %>').style.visibility = "visible";
329     } else {
330       document.l<%= $layer %>.visibility = "visible";
331     }
332   }
333 <% } %>
334 }
335
336 </SCRIPT>
337 <BR>
338 Price plan <SELECT NAME="plan" SIZE=1 onChange="changed(this);">
339 <OPTION>
340 <% foreach my $layer (keys %plans ) { %>
341 <OPTION VALUE="<%= $layer %>"<%= ' SELECTED'x($layer eq $part_pkg->plan) %>><%= $plans{$layer}->{'name'} %>
342 <% } %>
343 </SELECT></FORM>
344
345 <SCRIPT>
346 function fchanged(what) {
347   fixup(what.form);
348 }
349
350 function fixup(what) {
351 <% foreach my $f ( qw( pkg comment freq ), @fixups ) { %>
352   what.<%= $f %>.value = document.dummy.<%= $f %>.value;
353 <% } %>
354 <% foreach my $f ( qw( setuptax recurtax disabled ) ) { %>
355   if (document.dummy.<%= $f %>.checked)
356     what.<%= $f %>.value = 'Y';
357   else
358     what.<%= $f %>.value = '';
359 <% } %>
360   what.plan.value = document.dummy.plan.options[document.dummy.plan.selectedIndex].value;
361 <% foreach my $p ( keys %plans ) { %>
362   if ( what.plan.value == "<%= $p %>" ) {
363     what.setup.value = <%= $plans{$p}->{setup} %>;
364     what.recur.value = <%= $plans{$p}->{recur} %>;
365   }
366 <% } %>
367 }
368 </SCRIPT>
369
370 <% my %plandata = map { /^(\w+)=(.*)$/; ( $1 => $2 ); }
371                     split("\n", $part_pkg->plandata );
372    #foreach my $layer ( 'konq_kludge', keys %plans ) { 
373    foreach my $layer ( 'konq_kludge', keys %plans ) {
374      my $visibility = "hidden";
375 %>
376 <SCRIPT>
377 if (document.getElementById) {
378     document.write("<DIV ID=\"d<%= $layer %>\" STYLE=\"visibility: <%= $visibility %>; position: absolute\">");
379 } else {
380 <% $visibility="show" if $visibility eq "visible"; %>
381     document.write("<LAYER ID=\"l<%= $layer %>\" VISIBILITY=\"<%= $visibility %>\">");
382 }
383 </SCRIPT>
384
385 <FORM NAME="<%= $layer %>" ACTION="process/part_pkg.cgi" METHOD=POST onSubmit="fixup(this)">
386 <INPUT TYPE="hidden" NAME="plan" VALUE="<%= $part_pkg->plan %>">
387 <INPUT TYPE="hidden" NAME="pkg" VALUE="<%= $hashref->{pkg} %>">
388 <INPUT TYPE="hidden" NAME="comment" VALUE="$<%= $hashref->{comment} %>">
389 <INPUT TYPE="hidden" NAME="freq" VALUE="<%= $hashref->{freq} %>">
390 <INPUT TYPE="hidden" NAME="setuptax" VALUE="<%= $hashref->{setuptax} %>">
391 <INPUT TYPE="hidden" NAME="recurtax" VALUE="<%= $hashref->{recurtax} %>">
392 <INPUT TYPE="hidden" NAME="disabled" VALUE="<%= $hashref->{disabled} %>">
393 <% foreach my $f ( @fixups ) { %>
394 <INPUT TYPE="hidden" NAME="<%= $f %>" VALUE="">
395 <% } %>
396
397 <%
398 if ( $cgi->param('clone') ) {
399   print qq!<INPUT TYPE="hidden" NAME="clone" VALUE="!, $cgi->param('clone'), qq!">!;
400 }
401 if ( $cgi->param('pkgnum') ) {
402   print qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="!, $cgi->param('pkgnum'), qq!">!;
403 }
404 %>
405
406 <INPUT TYPE="hidden" NAME="pkgpart" VALUE="<%= $hashref->{pkgpart} %>">
407 <%= ntable("#cccccc",2) %>
408
409 <% my $href = $plans{$layer}->{'fields'};
410    foreach my $field ( exists($plans{$layer}->{'fieldorder'})
411                          ? @{$plans{$layer}->{'fieldorder'}}
412                          : keys %{ $href }
413                      ) {
414 %>
415   <TR><TD ALIGN="right"><%= $href->{$field}{'name'} %></TD>
416   <TD>
417   <% if ( ! exists($href->{$field}{'type'}) ) { %>
418        <INPUT TYPE="text" NAME="<%= $field %>" VALUE="<%= exists($plandata{$field}) ? $plandata{$field} : $href->{$field}{'default'} %>" onChange="fchanged(this)">
419   <% } elsif ( $href->{$field}{'type'} eq 'select_multiple' ) { %>
420        <SELECT MULTIPLE NAME="<%= $field %>" onChange="fchanged(this)">
421        <% foreach my $record ( qsearch( $href->{$field}{'select_table'}, $href->{$field}{'select_hash'} ) ) {
422           my $value = $record->getfield($href->{$field}{'select_key'}); %>
423          <OPTION VALUE="<%= $value %>"<%= $plandata{$field} =~ /(^|, *)$value *(,|$)/ ? ' SELECTED' : '' %>><%= $record->getfield($href->{$field}{'select_label'}) %>
424        <% } %>
425        </SELECT>
426   <% } %>
427   </TD></TR>
428 <% } %>
429
430 </TABLE>
431 <INPUT TYPE="hidden" NAME="plandata" VALUE="<%= join(',', keys %{ $href } ) %>">
432 <BR><BR>
433
434 <%
435 print qq!<INPUT TYPE="submit" VALUE="!,
436       $hashref->{pkgpart} ? "Apply changes" : "Add package",
437       qq!" onClick="fchanged(this)">!;
438 %>
439
440 <BR><BR>don't edit this unless you know what you're doing <INPUT TYPE="button" VALUE="refresh expressions" onClick="fchanged(this)"><%= ntable("#cccccc",2) %><TR><TD>
441 <FONT SIZE="1">Setup expression<BR><INPUT TYPE="text" NAME="setup" SIZE="160" VALUE="<%= $hashref->{setup} %>" onLoad="fchanged(this)"></FONT><BR>
442 <FONT SIZE="1">Recurring espression<BR><INPUT TYPE="text" NAME="recur" SIZE="160" VALUE="<%= $hashref->{recur} %>" onLoad="fchanged(this)"></FONT>
443 </TR></TD>
444 </TABLE>
445
446 </FORM>
447
448 <SCRIPT>
449 if (document.getElementById) {
450   document.write("</DIV>");
451 } else {
452   document.write("</LAYER>");
453 }
454 </SCRIPT>
455
456 <% } %>
457
458 <TAG onLoad="
459     if (document.getElementById) {
460       document.getElementById('d<%= $part_pkg->plan %>').style.visibility = 'visible';
461     } else {
462       document.l<%= $part_pkg->plan %>.visibility = 'visible';
463     }
464 ">
465   </BODY>
466 </HTML>