summaryrefslogtreecommitdiff
path: root/bin/jc.pl
blob: 5066dc41b402e3f9d614d80b4ac661d1b68eb89d (plain)
  1. #=====================================================================
  2. # LedgerSMB Small Medium Business Accounting
  3. # http://www.ledgersmb.org/
  4. #
  5. # Copyright (C) 2006
  6. # This work contains copyrighted information from a number of sources all used
  7. # with permission.
  8. #
  9. # This file contains source code included with or based on SQL-Ledger which
  10. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  11. # under the GNU General Public License version 2 or, at your option, any later
  12. # version. For a full list including contact information of contributors,
  13. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  14. #
  15. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  16. # Copyright (c) 2005
  17. #
  18. # Author: DWS Systems Inc.
  19. # Web: http://www.sql-ledger.org
  20. #
  21. #
  22. #
  23. # This program is free software; you can redistribute it and/or modify
  24. # it under the terms of the GNU General Public License as published by
  25. # the Free Software Foundation; either version 2 of the License, or
  26. # (at your option) any later version.
  27. #
  28. # This program is distributed in the hope that it will be useful,
  29. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  30. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  31. # GNU General Public License for more details.
  32. # You should have received a copy of the GNU General Public License
  33. # along with this program; if not, write to the Free Software
  34. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  35. #======================================================================
  36. #
  37. # Job Costing module
  38. #
  39. #======================================================================
  40. use LedgerSMB::JC;
  41. 1;
  42. # end of main
  43. sub add {
  44. if ($form->{type} eq 'timecard') {
  45. $form->{title} = $locale->text('Add Time Card');
  46. }
  47. if ($form->{type} eq 'storescard') {
  48. $form->{title} = $locale->text('Add Stores Card');
  49. }
  50. $form->{callback} = "$form->{script}?action=add&type=$form->{type}&login=$form->{login}&path=$form->{path}&sessionid=$form->{sessionid}&project=$form->{project}" unless $form->{callback};
  51. &{ "prepare_$form->{type}" };
  52. $form->{orphaned} = 1;
  53. &display_form;
  54. }
  55. sub edit {
  56. if ($form->{type} eq 'timecard') {
  57. $form->{title} = $locale->text('Edit Time Card');
  58. }
  59. if ($form->{type} eq 'storescard') {
  60. $form->{title} = $locale->text('Add Stores Card');
  61. }
  62. &{ "prepare_$form->{type}" };
  63. &display_form;
  64. }
  65. sub jcitems_links {
  66. if (@{ $form->{all_project} }) {
  67. $form->{selectprojectnumber} = "<option>\n";
  68. foreach $ref (@{ $form->{all_project} }) {
  69. $form->{selectprojectnumber} .= qq|<option value="$ref->{projectnumber}--$ref->{id}">$ref->{projectnumber}\n|;
  70. if ($form->{projectnumber} eq "$ref->{projectnumber}--$ref->{id}") {
  71. $form->{projectdescription} = $ref->{description};
  72. }
  73. }
  74. } else {
  75. if ($form->{project} eq 'job') {
  76. $form->error($locale->text('No open Jobs!'));
  77. } else {
  78. $form->error($locale->text('No open Projects!'));
  79. }
  80. }
  81. if (@{ $form->{all_parts} }) {
  82. $form->{selectpartnumber} = "<option>\n";
  83. foreach $ref (@{ $form->{all_parts} }) {
  84. $form->{selectpartnumber} .= qq|<option value="$ref->{partnumber}--$ref->{id}">$ref->{partnumber}\n|;
  85. if ($form->{partnumber} eq "$ref->{partnumber}--$ref->{id}") {
  86. if ($form->{partnumber} ne $form->{oldpartnumber}) {
  87. for (qw(description unit sellprice pricematrix)) { $form->{$_} = $ref->{$_} }
  88. }
  89. }
  90. }
  91. } else {
  92. if ($form->{type} eq 'timecard') {
  93. if ($form->{project} eq 'job') {
  94. $form->error($locale->text('No Labor codes on file!'));
  95. } else {
  96. $form->error($locale->text('No Services on file!'));
  97. }
  98. } else {
  99. $form->error($locale->text('No Parts on file!'));
  100. }
  101. }
  102. # employees
  103. if (@{ $form->{all_employee} }) {
  104. $form->{selectemployee} = "<option>\n";
  105. for (@{ $form->{all_employee} }) { $form->{selectemployee} .= qq|<option value="$_->{name}--$_->{id}">$_->{name}\n| }
  106. } else {
  107. $form->error($locale->text('No Employees on file!'));
  108. }
  109. }
  110. sub search {
  111. # accounting years
  112. $form->all_years(\%myconfig);
  113. if (@{ $form->{all_years} }) {
  114. $form->{selectaccountingyear} = "<option>\n";
  115. for (@{ $form->{all_years} }) { $form->{selectaccountingyear} .= qq|<option>$_\n| }
  116. $form->{selectaccountingmonth} = "<option>\n";
  117. for (sort keys %{ $form->{all_month} }) { $form->{selectaccountingmonth} .= qq|<option value=$_>|.$locale->text($form->{all_month}{$_}).qq|\n| }
  118. $selectfrom = qq|
  119. <tr>
  120. <th align=right>|.$locale->text('Period').qq|</th>
  121. <td colspan=3>
  122. <select name=month>$form->{selectaccountingmonth}</select>
  123. <select name=year>$form->{selectaccountingyear}</select>
  124. <input name=interval class=radio type=radio value=0 checked>&nbsp;|.$locale->text('Current').qq|
  125. <input name=interval class=radio type=radio value=1>&nbsp;|.$locale->text('Month').qq|
  126. <input name=interval class=radio type=radio value=3>&nbsp;|.$locale->text('Quarter').qq|
  127. <input name=interval class=radio type=radio value=12>&nbsp;|.$locale->text('Year').qq|
  128. </td>
  129. </tr>
  130. |;
  131. }
  132. $fromto = qq|
  133. <tr>
  134. <th align=right nowrap>|.$locale->text('Startdate').qq|</th>
  135. <td>|.$locale->text('From').qq| <input name=startdatefrom size=11 title="$myconfig{dateformat}">
  136. |.$locale->text('To').qq| <input name=startdateto size=11 title="$myconfig{dateformat}"></td>
  137. </tr>
  138. $selectfrom
  139. |;
  140. if ($form->{type} eq 'timecard') {
  141. $form->{title} = $locale->text('Time Cards');
  142. JC->jcitems_links(\%myconfig, \%$form);
  143. }
  144. if ($form->{type} eq 'storescard') {
  145. $form->{title} = $locale->text('Stores Cards');
  146. JC->jcitems_links(\%myconfig, \%$form);
  147. }
  148. if (@{ $form->{all_project} }) {
  149. $form->{selectprojectnumber} = "<option>\n";
  150. for (@{ $form->{all_project} }) { $form->{selectprojectnumber} .= qq|<option value="$_->{projectnumber}--$_->{id}">$_->{projectnumber}\n| }
  151. }
  152. if (@{ $form->{all_parts} }) {
  153. $form->{selectpartnumber} = "<option>\n";
  154. foreach $ref (@{ $form->{all_parts} }) {
  155. $form->{selectpartnumber} .= qq|<option value="$ref->{partnumber}--$ref->{id}">$ref->{partnumber}\n|;
  156. }
  157. }
  158. if ($form->{project} eq 'job') {
  159. $joblabel = $locale->text('Job Number');
  160. $laborlabel = $locale->text('Labor Code');
  161. } elsif ($form->{project} eq 'project') {
  162. $joblabel = $locale->text('Project Number');
  163. $laborlabel = $locale->text('Service Code');
  164. } else {
  165. $joblabel = $locale->text('Project/Job Number');
  166. $laborlabel = $locale->text('Service/Labor Code');
  167. }
  168. if ($form->{selectprojectnumber}) {
  169. $jobnumber = qq|
  170. <tr>
  171. <th align=right nowrap>$joblabel</th>
  172. <td colspan=3><select name=projectnumber>$form->{selectprojectnumber}</select></td>
  173. </tr>
  174. |;
  175. }
  176. if ($form->{type} eq 'timecard') {
  177. # employees
  178. if (@{ $form->{all_employee} }) {
  179. $form->{selectemployee} = "<option>\n";
  180. for (@{ $form->{all_employee} }) { $form->{selectemployee} .= qq|<option value="$_->{name}--$_->{id}">$_->{name}\n| }
  181. } else {
  182. $form->error($locale->text('No Employees on file!'));
  183. }
  184. if ($form->{selectpartnumber}) {
  185. $partnumber = qq|
  186. <tr>
  187. <th align=right nowrap>$laborlabel</th>
  188. <td colspan=3><select name=partnumber>$form->{selectpartnumber}</select></td>
  189. </tr>
  190. |;
  191. }
  192. $employee = qq|
  193. <tr>
  194. <th align=right nowrap>|.$locale->text('Employee').qq|</th>
  195. <td colspan=3><select name=employee>$form->{selectemployee}</select></td>
  196. </tr>
  197. |;
  198. $l_time = qq|<td nowrap><input name=l_time class=checkbox type=checkbox value=Y>&nbsp;|.$locale->text('Time').qq|</td>|;
  199. }
  200. $form->header;
  201. print qq|
  202. <body>
  203. <form method=post action=$form->{script}>
  204. <table width=100%>
  205. <tr>
  206. <th class=listtop>$form->{title}</th>
  207. </tr>
  208. <tr height="5"></tr>
  209. <tr valign=top>
  210. <td>
  211. <table>
  212. $jobnumber
  213. $partnumber
  214. $employee
  215. $fromto
  216. <tr>
  217. <th align=right nowrap>|.$locale->text('Include in Report').qq|</th>
  218. <td>
  219. <table>
  220. <tr>
  221. <td nowrap><input name=open class=checkbox type=checkbox value=Y checked> |.$locale->text('Open').qq|</td>
  222. <td nowrap><input name=closed class=checkbox type=checkbox value=Y> |.$locale->text('Closed').qq|</td>
  223. </tr>
  224. <tr>
  225. $l_time
  226. <td nowrap><input name=l_allocated class=checkbox type=checkbox value=Y> |.$locale->text('Allocated').qq|</td>
  227. </tr>
  228. <tr>
  229. <td><input name=l_subtotal class=checkbox type=checkbox value=Y>&nbsp;|.$locale->text('Subtotal').qq|</td>
  230. </tr>
  231. </table>
  232. </td>
  233. </tr>
  234. </table>
  235. </td>
  236. </tr>
  237. <tr>
  238. <td><hr size=3 noshade></td>
  239. </tr>
  240. </table>
  241. <input type=hidden name=nextsub value="list_$form->{type}">
  242. <input type=hidden name=sort value="transdate">
  243. |;
  244. $form->hide_form(qw(db path login sessionid project type));
  245. print qq|
  246. <br>
  247. <button type="submit" class="submit" name="action" value="continue">|.$locale->text('Continue').qq|</button>
  248. </form>
  249. |;
  250. if ($form->{lynx}) {
  251. require "bin/menu.pl";
  252. &menubar;
  253. }
  254. print qq|
  255. </body>
  256. </html>
  257. |;
  258. }
  259. sub display_form {
  260. &{ "$form->{type}_header" };
  261. &{ "$form->{type}_footer" };
  262. }
  263. sub form_header {
  264. &{ "$form->{type}_header" };
  265. }
  266. sub form_footer {
  267. &{ "form->{type}_footer" };
  268. }
  269. sub prepare_timecard {
  270. $form->{formname} = "timecard";
  271. $form->{format} = "postscript" if $myconfig{printer};
  272. $form->{media} = $myconfig{printer};
  273. JC->get_jcitems(\%myconfig, \%$form);
  274. $form->{selectformname} = qq|<option value="timecard">|.$locale->text('Time Card');
  275. foreach $item (qw(in out)) {
  276. ($form->{"${item}hour"}, $form->{"${item}min"}, $form->{"${item}sec"}) = split /:/, $form->{"checked$item"};
  277. for (qw(hour min sec)) {
  278. if (($form->{"$item$_"} *= 1) > 0) {
  279. $form->{"$item$_"} = substr(qq|0$form->{"$item$_"}|,-2);
  280. } else {
  281. $form->{"$item$_"} ||= "";
  282. }
  283. }
  284. }
  285. $form->{checkedin} = $form->{inhour} * 3600 + $form->{inmin} * 60 + $form->{insec};
  286. $form->{checkedout} = $form->{outhour} * 3600 + $form->{outmin} * 60 + $form->{outsec};
  287. if ($form->{checkedin} > $form->{checkedout}) {
  288. $form->{checkedout} = 86400 - ($form->{checkedin} - $form->{checkedout});
  289. $form->{checkedin} = 0;
  290. }
  291. $form->{clocked} = ($form->{checkedout} - $form->{checkedin}) / 3600;
  292. if ($form->{clocked}) {
  293. $form->{oldnoncharge} = $form->{clocked} - $form->{qty};
  294. }
  295. $form->{oldqty} = $form->{qty};
  296. $form->{noncharge} = $form->format_amount(\%myconfig, $form->{clocked} - $form->{qty}, 4) if $form->{checkedin} != $form->{checkedout};
  297. $form->{clocked} = $form->format_amount(\%myconfig, $form->{clocked}, 4);
  298. $form->{amount} = $form->{sellprice} * $form->{qty};
  299. for (qw(sellprice amount)) { $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 2) }
  300. $form->{qty} = $form->format_amount(\%myconfig, $form->{qty}, 4);
  301. $form->{allocated} = $form->format_amount(\%myconfig, $form->{allocated});
  302. $form->{employee} .= "--$form->{employee_id}";
  303. $form->{projectnumber} .= "--$form->{project_id}";
  304. $form->{partnumber} .= "--$form->{parts_id}";
  305. $form->{oldpartnumber} = $form->{partnumber};
  306. if (@{ $form->{all_language} }) {
  307. $form->{selectlanguage} = "<option>\n";
  308. for (@{ $form->{all_language} }) { $form->{selectlanguage} .= qq|<option value="$_->{code}">$_->{description}\n| }
  309. }
  310. &jcitems_links;
  311. $form->{locked} = ($form->{revtrans}) ? '1' : ($form->datetonum(\%myconfig, $form->{transdate}) <= $form->datetonum(\%myconfig, $form->{closedto}));
  312. $form->{readonly} = 1 if $myconfig{acs} =~ /Production--Add Time Card/;
  313. if ($form->{income_accno_id}) {
  314. $form->{locked} = 1 if $form->{production} == $form->{completed};
  315. }
  316. }
  317. sub timecard_header {
  318. # set option selected
  319. for (qw(employee projectnumber partnumber)) {
  320. $form->{"select$_"} =~ s/ selected//;
  321. $form->{"select$_"} =~ s/(<option value="\Q$form->{$_}\E")/$1 selected/;
  322. }
  323. $rows = $form->numtextrows($form->{description}, 50, 8);
  324. for (qw(transdate checkedin checkedout partnumber)) { $form->{"old$_"} = $form->{$_} }
  325. for (qw(partnumber description)) { $form->{$_} = $form->quote($form->{$_}) }
  326. if ($rows > 1) {
  327. $description = qq|<textarea name=description rows=$rows cols=46 wrap=soft>$form->{description}</textarea>|;
  328. } else {
  329. $description = qq|<input name=description size=48 value="$form->{description}">|;
  330. }
  331. if ($form->{project} eq 'job') {
  332. $projectlabel = $locale->text('Job Number');
  333. $laborlabel = $locale->text('Labor Code');
  334. $rate = qq|<input type=hidden name=sellprice value=$form->{sellprice}>|;
  335. } else {
  336. if ($form->{project} eq 'project') {
  337. $projectlabel = $locale->text('Project Number');
  338. $laborlabel = $locale->text('Service Code');
  339. } else {
  340. $projectlabel = $locale->text('Project/Job Number');
  341. $laborlabel = $locale->text('Service/Labor Code');
  342. }
  343. if ($myconfig{role} ne 'user') {
  344. $rate = qq|
  345. <tr>
  346. <th align=right nowrap>|.$locale->text('Chargeout Rate').qq|</th>
  347. <td><input name=sellprice value=$form->{sellprice}></td>
  348. <th align=right nowrap>|.$locale->text('Total').qq|</th>
  349. <td>$form->{amount}</td>
  350. </tr>
  351. <tr>
  352. <th align=right nowrap>|.$locale->text('Allocated').qq|</th>
  353. <td><input name=allocated value=$form->{allocated}></td>
  354. </tr>
  355. |;
  356. } else {
  357. $rate = qq|
  358. <tr>
  359. <th align=right nowrap>|.$locale->text('Chargeout Rate').qq|</th>
  360. <td>$form->{sellprice}</td>
  361. <th align=right nowrap>|.$locale->text('Total').qq|</th>
  362. <td>$form->{amount}</td>
  363. </tr>
  364. <tr>
  365. <th align=right nowrap>|.$locale->text('Allocated').qq|</th>
  366. <td>$form->{allocated}</td>
  367. </tr>
  368. <input type=hidden name=sellprice value=$form->{sellprice}>
  369. <input type=hidden name=allocated value=$form->{allocated}>
  370. |;
  371. }
  372. }
  373. if ($myconfig{role} eq 'user') {
  374. $charge = qq|<input type=hidden name=qty value=$form->{qty}>$form->{qty}|;
  375. } else {
  376. $charge = qq|<input name=qty value=$form->{qty}>|;
  377. }
  378. if (($rows = $form->numtextrows($form->{notes}, 40, 6)) < 2) {
  379. $rows = 2;
  380. }
  381. $notes = qq|<tr>
  382. <th align=right>|.$locale->text('Notes').qq|</th>
  383. <td colspan=3><textarea name="notes" rows=$rows cols=46 wrap=soft>$form->{notes}</textarea>
  384. </td>
  385. </tr>
  386. |;
  387. ##################
  388. ($null, $form->{oldproject_id}) = split /--/, $form->{projectnumber};
  389. $form->header;
  390. print qq|
  391. <body>
  392. <form method=post action="$form->{script}">
  393. |;
  394. $form->hide_form(qw(id type media format printed queued title closedto locked oldtransdate oldcheckedin oldcheckedout oldpartnumber project oldqty oldnoncharge pricematrix oldproject_id));
  395. print qq|
  396. <table width=100%>
  397. <tr class=listtop>
  398. <th class=listtop>$form->{title}</th>
  399. </tr>
  400. <tr height="5"></tr>
  401. <tr>
  402. <td>
  403. <table>
  404. <tr>
  405. <td>
  406. <table>
  407. <tr>
  408. <th align=right nowrap>|.$locale->text('Employee').qq|</th>
  409. <td><select name=employee>$form->{selectemployee}</select></td>
  410. </tr>
  411. <tr>
  412. <th align=right nowrap>$projectlabel</th>
  413. <td><select name=projectnumber>$form->{selectprojectnumber}</select>
  414. </td>
  415. <td></td>
  416. <td>$form->{projectdescription}</td>
  417. <input type=hidden name=projectdescription value="|.$form->quote($form->{projectdescription}).qq|">
  418. </tr>
  419. <tr>
  420. <th align=right nowrap>|.$locale->text('Date worked').qq|</th>
  421. <td><input name=transdate size=11 title="$myconfig{dateformat}" value=$form->{transdate}></td>
  422. </tr>
  423. <tr>
  424. <th align=right nowrap>$laborlabel</th>
  425. <td><select name=partnumber>$form->{selectpartnumber}</select></td>
  426. </tr>
  427. <tr valign=top>
  428. <th align=right nowrap>|.$locale->text('Description').qq|</th>
  429. <td colspan=3>$description</td>
  430. </tr>
  431. <tr>
  432. <th align=right nowrap>|.$locale->text('Time In').qq|</th>
  433. <td>
  434. <table>
  435. <tr>
  436. <td><input name=inhour title="hh" size=3 maxlength=2 value=$form->{inhour}></td>
  437. <td><input name=inmin title="mm" size=3 maxlength=2 value=$form->{inmin}></td>
  438. <td><input name=insec title="ss" size=3 maxlength=2 value=$form->{insec}></td>
  439. </tr>
  440. </table>
  441. </td>
  442. <th align=right nowrap>|.$locale->text('Time Out').qq|</th>
  443. <td>
  444. <table>
  445. <tr>
  446. <td><input name=outhour title="hh" size=3 maxlength=2 value=$form->{outhour}></td>
  447. <td><input name=outmin title="mm" size=3 maxlength=2 value=$form->{outmin}></td>
  448. <td><input name=outsec title="ss" size=3 maxlength=2 value=$form->{outsec}></td>
  449. </tr>
  450. </table>
  451. </td>
  452. </tr>
  453. <tr>
  454. <th align=right nowrap>|.$locale->text('Clocked').qq|</th>
  455. <td>$form->{clocked}</td>
  456. </tr>
  457. <tr>
  458. <th align=right nowrap>|.$locale->text('Non-chargeable').qq|</th>
  459. <td><input name=noncharge value=$form->{noncharge}></td>
  460. </tr>
  461. <tr>
  462. <th align=right nowrap>|.$locale->text('Chargeable').qq|</th>
  463. <td>$charge</td>
  464. </tr>
  465. $rate
  466. $notes
  467. </table>
  468. </td>
  469. </tr>
  470. |;
  471. }
  472. sub timecard_footer {
  473. print qq|
  474. </table>
  475. </td>
  476. </tr>
  477. <tr>
  478. <td><hr size=3 noshade></td>
  479. </tr>
  480. <tr>
  481. <td>
  482. |;
  483. &print_options;
  484. print qq|
  485. </td>
  486. </tr>
  487. </table>
  488. <br>
  489. |;
  490. $transdate = $form->datetonum(\%myconfig, $form->{transdate});
  491. $closedto = $form->datetonum(\%myconfig, $form->{closedto});
  492. if (! $form->{readonly}) {
  493. # type=submit $locale->text('Update')
  494. # type=submit $locale->text('Print')
  495. # type=submit $locale->text('Save')
  496. # type=submit $locale->text('Print and Save')
  497. # type=submit $locale->text('Save as new')
  498. # type=submit $locale->text('Print and Save as new')
  499. # type=submit $locale->text('Delete')
  500. %button = ('update' => { ndx => 1, key => 'U', value => $locale->text('Update') },
  501. 'print' => { ndx => 2, key => 'P', value => $locale->text('Print') },
  502. 'save' => { ndx => 3, key => 'S', value => $locale->text('Save') },
  503. 'print_and_save' => { ndx => 6, key => 'R', value => $locale->text('Print and Save') },
  504. 'save_as_new' => { ndx => 7, key => 'N', value => $locale->text('Save as new') },
  505. 'print_and_save_as_new' => { ndx => 8, key => 'W', value => $locale->text('Print and Save as new') },
  506. 'delete' => { ndx => 16, key => 'D', value => $locale->text('Delete') },
  507. );
  508. %a = ();
  509. if ($form->{id}) {
  510. if (!$form->{locked}) {
  511. for ('update', 'print', 'save', 'save_as_new') { $a{$_} = 1 }
  512. if (${LedgerSMB::Sysconfig::latex}) {
  513. for ('print_and_save', 'print_and_save_as_new') { $a{$_} = 1 }
  514. }
  515. if ($form->{orphaned}) {
  516. $a{'delete'} = 1;
  517. }
  518. }
  519. } else {
  520. if ($transdate > $closedto) {
  521. for ('update', 'print', 'save') { $a{$_} = 1 }
  522. if (${LedgerSMB::Sysconfig::latex}) {
  523. $a{'print_and_save'} = 1;
  524. }
  525. }
  526. }
  527. }
  528. for (keys %button) { delete $button{$_} if ! $a{$_} }
  529. for (sort { $button{$a}->{ndx} <=> $button{$b}->{ndx} } keys %button) { $form->print_button(\%button, $_) }
  530. if ($form->{lynx}) {
  531. require "bin/menu.pl";
  532. &menubar;
  533. }
  534. $form->hide_form(qw(callback path login sessionid));
  535. print qq|
  536. </form>
  537. </body>
  538. </html>
  539. |;
  540. }
  541. sub prepare_storescard {
  542. $form->{formname} = "storescard";
  543. $form->{format} = "postscript" if $myconfig{printer};
  544. $form->{media} = $myconfig{printer};
  545. JC->get_jcitems(\%myconfig, \%$form);
  546. $form->{selectformname} = qq|<option value="storescard">|.$locale->text('Stores Card');
  547. $form->{amount} = $form->{sellprice} * $form->{qty};
  548. for (qw(sellprice amount)) { $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 2) }
  549. $form->{qty} = $form->format_amount(\%myconfig, $form->{qty}, 4);
  550. $form->{employee} .= "--$form->{employee_id}";
  551. $form->{projectnumber} .= "--$form->{project_id}";
  552. $form->{partnumber} .= "--$form->{parts_id}";
  553. $form->{oldpartnumber} = $form->{partnumber};
  554. if (@{ $form->{all_language} }) {
  555. $form->{selectlanguage} = "<option>\n";
  556. for (@{ $form->{all_language} }) { $form->{selectlanguage} .= qq|<option value="$_->{code}">$_->{description}\n| }
  557. }
  558. &jcitems_links;
  559. $form->{locked} = ($form->{revtrans}) ? '1' : ($form->datetonum(\%myconfig, $form->{transdate}) <= $form->datetonum(\%myconfig, $form->{closedto}));
  560. $form->{readonly} = 1 if $myconfig{acs} =~ /Production--Add Time Card/;
  561. if ($form->{income_accno_id}) {
  562. $form->{locked} = 1 if $form->{production} == $form->{completed};
  563. }
  564. }
  565. sub storescard_header {
  566. # set option selected
  567. for (qw(employee projectnumber partnumber)) {
  568. $form->{"select$_"} =~ s/ selected//;
  569. $form->{"select$_"} =~ s/(<option value="\Q$form->{$_}\E")/$1 selected/;
  570. }
  571. $rows = $form->numtextrows($form->{description}, 50, 8);
  572. for (qw(transdate partnumber)) { $form->{"old$_"} = $form->{$_} }
  573. for (qw(partnumber description)) { $form->{$_} = $form->quote($form->{$_}) }
  574. if ($rows > 1) {
  575. $description = qq|<textarea name=description rows=$rows cols=46 wrap=soft>$form->{description}</textarea>|;
  576. } else {
  577. $description = qq|<input name=description size=48 value="$form->{description}">|;
  578. }
  579. $form->header;
  580. print qq|
  581. <body>
  582. <form method=post action="$form->{script}">
  583. |;
  584. $form->hide_form(qw(id type media format printed queued title closedto locked oldtransdate oldpartnumber project));
  585. print qq|
  586. <table width=100%>
  587. <tr class=listtop>
  588. <th class=listtop>$form->{title}</th>
  589. </tr>
  590. <tr height="5"></tr>
  591. <tr>
  592. <td>
  593. <table>
  594. <tr>
  595. <td>
  596. <table>
  597. <tr>
  598. <th align=right nowrap>|.$locale->text('Job Number').qq|</th>
  599. <td><select name=projectnumber>$form->{selectprojectnumber}</select>
  600. </td>
  601. <td>$form->{projectdescription}</td>
  602. <input type=hidden name=projectdescription value="|.$form->quote($form->{projectdescription}).qq|">
  603. </tr>
  604. <tr>
  605. <th align=right nowrap>|.$locale->text('Date').qq|</th>
  606. <td><input name=transdate size=11 title="$myconfig{dateformat}" value=$form->{transdate}></td>
  607. </tr>
  608. <tr>
  609. <th align=right nowrap>|.$locale->text('Part Number').qq|</th>
  610. <td><select name=partnumber>$form->{selectpartnumber}</td>
  611. </tr>
  612. <tr valign=top>
  613. <th align=right nowrap>|.$locale->text('Description').qq|</th>
  614. <td>$description</td>
  615. </tr>
  616. <tr>
  617. <th align=right nowrap>|.$locale->text('Qty').qq|</th>
  618. <td><input name=qty size=6 value=$form->{qty}>
  619. <b>|.$locale->text('Cost').qq|</b>
  620. <input name=sellprice size=10 value=$form->{sellprice}></td>
  621. </tr>
  622. <tr>
  623. <th align=right nowrap>|.$locale->text('Total').qq|</th>
  624. <td>$form->{amount}</td>
  625. </tr>
  626. </table>
  627. </td>
  628. </tr>
  629. |;
  630. }
  631. sub storescard_footer {
  632. print qq|
  633. </table>
  634. </td>
  635. </tr>
  636. <tr>
  637. <td><hr size=3 noshade></td>
  638. </tr>
  639. <tr>
  640. <td>
  641. |;
  642. &print_options;
  643. print qq|
  644. </td>
  645. </tr>
  646. </table>
  647. <br>
  648. |;
  649. $transdate = $form->datetonum(\%myconfig, $form->{transdate});
  650. $closedto = $form->datetonum(\%myconfig, $form->{closedto});
  651. # type=submit $locale->text('Update')
  652. # type=submit $locale->text('Print')
  653. # type=submit $locale->text('Save')
  654. # type=submit $locale->text('Print and Save')
  655. # type=submit $locale->text('Save as new')
  656. # type=submit $locale->text('Print and Save as new')
  657. # type=submit $locale->text('Delete')
  658. if (! $form->{readonly}) {
  659. %button = ('update' => { ndx => 1, key => 'U', value => $locale->text('Update') },
  660. 'print' => { ndx => 2, key => 'P', value => $locale->text('Print') },
  661. 'save' => { ndx => 3, key => 'S', value => $locale->text('Save') },
  662. 'print_and_save' => { ndx => 6, key => 'R', value => $locale->text('Print and Save') },
  663. 'save_as_new' => { ndx => 7, key => 'N', value => $locale->text('Save as new') },
  664. 'print_and_save_as_new' => { ndx => 8, key => 'W', value => $locale->text('Print and Save as new') },
  665. 'delete' => { ndx => 16, key => 'D', value => $locale->text('Delete') },
  666. );
  667. %a = ();
  668. if ($form->{id}) {
  669. if (!$form->{locked}) {
  670. for ('update', 'print', 'save', 'save_as_new') { $a{$_} = 1 }
  671. if (${LedgerSMB::Sysconfig::latex}) {
  672. for ('print_and_save', 'print_and_save_as_new') { $a{$_} = 1 }
  673. }
  674. if ($form->{orphaned}) {
  675. $a{'delete'} = 1;
  676. }
  677. }
  678. } else {
  679. if ($transdate > $closedto) {
  680. for ('update', 'print', 'save') { $a{$_} = 1 }
  681. if (${LedgerSMB::Sysconfig::latex}) {
  682. $a{'print_and_save'} = 1;
  683. }
  684. }
  685. }
  686. for (keys %button) { delete $button{$_} if ! $a{$_} }
  687. for (sort { $button{$a}->{ndx} <=> $button{$b}->{ndx} } keys %button) { $form->print_button(\%button, $_) }
  688. }
  689. if ($form->{lynx}) {
  690. require "bin/menu.pl";
  691. &menubar;
  692. }
  693. $form->hide_form(qw(callback path login sessionid));
  694. print qq|
  695. </form>
  696. </body>
  697. </html>
  698. |;
  699. }
  700. sub update {
  701. ($null, $form->{project_id}) = split /--/, $form->{projectnumber};
  702. # check labor/part
  703. JC->jcitems_links(\%myconfig, \%$form);
  704. &jcitems_links;
  705. $checkmatrix = 1 if $form->{oldproject_id} != $form->{project_id};
  706. if ($form->{type} eq 'timecard') {
  707. # time clocked
  708. %hour = ( in => 0, out => 0 );
  709. for $t (qw(in out)) {
  710. if ($form->{"${t}sec"} > 60) {
  711. $form->{"${t}sec"} -= 60;
  712. $form->{"${t}min"}++;
  713. }
  714. if ($form->{"${t}min"} > 60) {
  715. $form->{"${t}min"} -= 60;
  716. $form->{"${t}hour"}++;
  717. }
  718. $hour{$t} = $form->{"${t}hour"};
  719. }
  720. $form->{checkedin} = $hour{in} * 3600 + $form->{inmin} * 60 + $form->{insec};
  721. $form->{checkedout} = $hour{out} * 3600 + $form->{outmin} * 60 + $form->{outsec};
  722. if ($form->{checkedin} > $form->{checkedout}) {
  723. $form->{checkedout} = 86400 - ($form->{checkedin} - $form->{checkedout});
  724. $form->{checkedin} = 0;
  725. }
  726. $form->{clocked} = ($form->{checkedout} - $form->{checkedin}) / 3600;
  727. for (qw(sellprice qty noncharge allocated)) { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
  728. $checkmatrix = 1 if $form->{oldqty} != $form->{qty};
  729. if (($form->{oldcheckedin} != $form->{checkedin}) || ($form->{oldcheckedout} != $form->{checkedout})) {
  730. $checkmatrix = 1;
  731. $form->{oldqty} = $form->{qty} = $form->{clocked} - $form->{noncharge};
  732. $form->{oldnoncharge} = $form->{noncharge};
  733. }
  734. if (($form->{qty} != $form->{oldqty}) && $form->{clocked}) {
  735. $form->{oldnoncharge} = $form->{noncharge} = $form->{clocked} - $form->{qty};
  736. $checkmatrix = 1;
  737. }
  738. if (($form->{oldnoncharge} != $form->{noncharge}) && $form->{clocked}) {
  739. $form->{oldqty} = $form->{qty} = $form->{clocked} - $form->{noncharge};
  740. $checkmatrix = 1;
  741. }
  742. if ($checkmatrix) {
  743. @a = split / /, $form->{pricematrix};
  744. if (scalar @a > 2) {
  745. for (@a) {
  746. ($q, $p) = split /:/, $_;
  747. if (($p * 1) && ($form->{qty} >= ($q * 1))) {
  748. $form->{sellprice} = $p;
  749. }
  750. }
  751. }
  752. }
  753. $form->{amount} = $form->{sellprice} * $form->{qty};
  754. $form->{clocked} = $form->format_amount(\%myconfig, $form->{clocked}, 4);
  755. for (qw(sellprice amount)) { $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 2) }
  756. for (qw(qty noncharge)) {
  757. $form->{"old$_"} = $form->{$_};
  758. $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 4);
  759. }
  760. } else {
  761. for (qw(sellprice qty allocated)) { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
  762. if ($form->{oldqty} != $form->{qty}) {
  763. @a = split / /, $form->{pricematrix};
  764. if (scalar @a > 2) {
  765. for (@a) {
  766. ($q, $p) = split /:/, $_;
  767. if (($p * 1) && ($form->{qty} >= ($q * 1))) {
  768. $form->{sellprice} = $p;
  769. }
  770. }
  771. }
  772. }
  773. $form->{amount} = $form->{sellprice} * $form->{qty};
  774. for (qw(sellprice amount)) { $form->{$_} = $form->format_amount(\%myconfig, $form->{$_}, 2) }
  775. }
  776. $form->{allocated} = $form->format_amount(\%myconfig, $form->{allocated});
  777. &display_form;
  778. }
  779. sub save {
  780. $form->isblank("transdate", $locale->text('Date missing!'));
  781. if ($form->{project} eq 'project') {
  782. $form->isblank("projectnumber", $locale->text('Project Number missing!'));
  783. $form->isblank("partnumber", $locale->text('Service Code missing!'));
  784. } else {
  785. $form->isblank("projectnumber", $locale->text('Job Number missing!'));
  786. $form->isblank("partnumber", $locale->text('Labor Code missing!'));
  787. }
  788. $closedto = $form->datetonum(\%myconfig, $form->{closedto});
  789. $transdate = $form->datetonum(\%myconfig, $form->{transdate});
  790. $msg = ($form->{type} eq 'timecard') ? $locale->text('Cannot save time card for a closed period!') : $locale->text('Cannot save stores card for a closed period!');
  791. $form->error($msg) if ($transdate <= $closedto);
  792. if (! $form->{resave}) {
  793. if ($form->{id}) {
  794. &resave;
  795. exit;
  796. }
  797. }
  798. $rc = JC->save(\%myconfig, \%$form);
  799. if ($form->{type} eq 'timecard') {
  800. $form->error($locale->text('Cannot change time card for a completed job!')) if ($rc == -1);
  801. $form->error($locale->text('Cannot add time card for a completed job!')) if ($rc == -2);
  802. if ($rc) {
  803. $form->redirect($locale->text('Time Card saved!'));
  804. } else {
  805. $form->error($locale->text('Cannot save time card!'));
  806. }
  807. } else {
  808. $form->error($locale->text('Cannot change stores card for a completed job!')) if ($rc == -1);
  809. $form->error($locale->text('Cannot add stores card for a completed job!')) if ($rc == -2);
  810. if ($rc) {
  811. $form->redirect($locale->text('Stores Card saved!'));
  812. } else {
  813. $form->error($locale->text('Cannot save stores card!'));
  814. }
  815. }
  816. }
  817. sub save_as_new {
  818. delete $form->{id};
  819. &save;
  820. }
  821. sub print_and_save_as_new {
  822. delete $form->{id};
  823. &print_and_save;
  824. }
  825. sub resave {
  826. if ($form->{print_and_save}) {
  827. $form->{nextsub} = "print_and_save";
  828. $msg = $locale->text('You are printing and saving an existing transaction!');
  829. } else {
  830. $form->{nextsub} = "save";
  831. $msg = $locale->text('You are saving an existing transaction!');
  832. }
  833. $form->{resave} = 1;
  834. $form->header;
  835. print qq|
  836. <body>
  837. <form method=post action=$form->{script}>
  838. |;
  839. delete $form->{action};
  840. $form->hide_form;
  841. print qq|
  842. <h2 class=confirm>|.$locale->text('Warning!').qq|</h2>
  843. <h4>$msg</h4>
  844. <button name="action" class="submit" type="submit" value="continue">|.$locale->text('Continue').qq|</button>
  845. </form>
  846. </body>
  847. </html>
  848. |;
  849. }
  850. sub print_and_save {
  851. $form->error($locale->text('Select postscript or PDF!')) if $form->{format} !~ /(postscript|pdf)/;
  852. $form->error($locale->text('Select a Printer!')) if $form->{media} eq 'screen';
  853. if (! $form->{resave}) {
  854. if ($form->{id}) {
  855. $form->{print_and_save} = 1;
  856. &resave;
  857. exit;
  858. }
  859. }
  860. $old_form = new Form;
  861. $form->{display_form} = "save";
  862. for (keys %$form) { $old_form->{$_} = $form->{$_} }
  863. &{ "print_$form->{formname}" }($old_form);
  864. }
  865. sub delete_timecard {
  866. $form->header;
  867. $employee = $form->{employee};
  868. $employee =~ s/--.*//g;
  869. $projectnumber = $form->{projectnumber};
  870. $projectnumber =~ s/--.*//g;
  871. print qq|
  872. <body>
  873. <form method=post action=$form->{script}>
  874. |;
  875. delete $form->{action};
  876. $form->hide_form;
  877. print qq|
  878. <h2 class=confirm>|.$locale->text('Confirm!').qq|</h2>
  879. <h4>|.$locale->text('Are you sure you want to delete time card for').qq|
  880. <p>$form->{transdate}
  881. <br>$employee
  882. <br>$projectnumber
  883. </h4>
  884. <p>
  885. <button name="action" class="submit" type="submit" value="yes">|.$locale->text('Yes').qq|</button>
  886. </form>
  887. |;
  888. }
  889. sub delete { &{ "delete_$form->{type}" } };
  890. sub yes { &{ "yes_delete_$form->{type}" } };
  891. sub yes_delete_timecard {
  892. if (JC->delete_timecard(\%myconfig, \%$form)) {
  893. $form->redirect($locale->text('Time Card deleted!'));
  894. } else {
  895. $form->error($locale->text('Cannot delete time card!'));
  896. }
  897. }
  898. sub list_timecard {
  899. $form->{type} = "timecard";
  900. JC->jcitems(\%myconfig, \%$form);
  901. $form->{title} = $locale->text('Time Cards');
  902. @a = qw(type direction oldsort path login sessionid project l_subtotal open closed l_time l_allocated);
  903. $href = "$form->{script}?action=list_timecard";
  904. for (@a) { $href .= "&$_=$form->{$_}" }
  905. $href .= "&title=".$form->escape($form->{title});
  906. $form->sort_order();
  907. $callback = "$form->{script}?action=list_timecard";
  908. for (@a) { $callback .= "&$_=$form->{$_}" }
  909. $callback .= "&title=".$form->escape($form->{title},1);
  910. @column_index = (qw(transdate projectnumber projectdescription id partnumber description));
  911. push @column_index, (qw(allocated)) if $form->{l_allocated};
  912. push @column_index, (qw(1 2 3 4 5 6 7));
  913. @column_index = $form->sort_columns(@column_index);
  914. if ($form->{project} eq 'job') {
  915. $joblabel = $locale->text('Job Number');
  916. $laborlabel = $locale->text('Labor Code');
  917. $desclabel = $locale->text('Job Name');
  918. } elsif ($form->{project} eq 'project') {
  919. $joblabel = $locale->text('Project Number');
  920. $laborlabel = $locale->text('Service Code');
  921. $desclabel = $locale->text('Project Name');
  922. } else {
  923. $joblabel = $locale->text('Project/Job Number');
  924. $laborlabel = $locale->text('Service/Labor Code');
  925. $desclabel = $locale->text('Project/Job Name');
  926. }
  927. if ($form->{projectnumber}) {
  928. $callback .= "&projectnumber=".$form->escape($form->{projectnumber},1);
  929. $href .= "&projectnumber=".$form->escape($form->{projectnumber});
  930. ($var) = split /--/, $form->{projectnumber};
  931. $option .= "\n<br>" if ($option);
  932. $option .= "$joblabel : $var";
  933. @column_index = grep !/projectnumber/, @column_index;
  934. }
  935. if ($form->{partnumber}) {
  936. $callback .= "&partnumber=".$form->escape($form->{partnumber},1);
  937. $href .= "&partnumber=".$form->escape($form->{partnumber});
  938. ($var) = split /--/, $form->{partnumber};
  939. $option .= "\n<br>" if ($option);
  940. $option .= "$laborlabel : $var";
  941. @column_index = grep !/partnumber/, @column_index;
  942. }
  943. if ($form->{employee}) {
  944. $callback .= "&employee=".$form->escape($form->{employee},1);
  945. $href .= "&employee=".$form->escape($form->{employee});
  946. }
  947. if ($form->{startdatefrom}) {
  948. $callback .= "&startdatefrom=$form->{startdatefrom}";
  949. $href .= "&startdatefrom=$form->{startdatefrom}";
  950. $option .= "\n<br>" if ($option);
  951. $option .= $locale->text('From')."&nbsp;".$locale->date(\%myconfig, $form->{startdatefrom}, 1);
  952. }
  953. if ($form->{startdateto}) {
  954. $callback .= "&startdateto=$form->{startdateto}";
  955. $href .= "&startdateto=$form->{startdateto}";
  956. $option .= "\n<br>" if ($option);
  957. $option .= $locale->text('To')."&nbsp;".$locale->date(\%myconfig, $form->{startdateto}, 1);
  958. }
  959. if ($form->{open}) {
  960. $callback .= "&open=$form->{open}";
  961. $href .= "&open=$form->{open}";
  962. $option .= "\n<br>" if ($option);
  963. $option .= $locale->text('Open');
  964. }
  965. if ($form->{closed}) {
  966. $callback .= "&closed=$form->{closed}";
  967. $href .= "&closed=$form->{closed}";
  968. $option .= "\n<br>" if ($option);
  969. $option .= $locale->text('Closed');
  970. }
  971. %weekday = ( 1 => $locale->text('Sunday'),
  972. 2 => $locale->text('Monday'),
  973. 3 => $locale->text('Tuesday'),
  974. 4 => $locale->text('Wednesday'),
  975. 5 => $locale->text('Thursday'),
  976. 6 => $locale->text('Friday'),
  977. 7 => $locale->text('Saturday'),
  978. );
  979. for (keys %weekday) { $column_header{$_} = "<th class=listheading width=25>".substr($weekday{$_},0,3)."</th>" }
  980. $column_header{id} = "<th><a class=listheading href=$href&sort=id>".$locale->text('ID')."</a></th>";
  981. $column_header{transdate} = "<th><a class=listheading href=$href&sort=transdate>".$locale->text('Date')."</a></th>";
  982. $column_header{description} = "<th><a class=listheading href=$href&sort=description>" . $locale->text('Description') . "</th>";
  983. $column_header{projectnumber} = "<th><a class=listheading href=$href&sort=projectnumber>$joblabel</a></th>";
  984. $column_header{partnumber} = "<th><a class=listheading href=$href&sort=partnumber>$laborlabel</a></th>";
  985. $column_header{projectdescription} = "<th><a class=listheading href=$href&sort=projectdescription>$desclabel</a></th>";
  986. $column_header{allocated} = "<th class=listheading></th>";
  987. $form->header;
  988. if (@{ $form->{transactions} }) {
  989. $sameitem = $form->{transactions}->[0]->{$form->{sort}};
  990. $sameemployeenumber = $form->{transactions}->[0]->{employeenumber};
  991. $employee = $form->{transactions}->[0]->{employee};
  992. $sameweek = $form->{transactions}->[0]->{workweek};
  993. }
  994. print qq|
  995. <body>
  996. <table width=100%>
  997. <tr>
  998. <th class=listtop>$form->{title}</th>
  999. </tr>
  1000. <tr height="5"></tr>
  1001. <tr>
  1002. <td>$option</td>
  1003. </tr>
  1004. <tr>
  1005. <td>
  1006. <table width=100%>
  1007. <tr>
  1008. <th colspan=2 align=left>
  1009. $employee
  1010. </th>
  1011. <th align=left>
  1012. $sameemployeenumber
  1013. </th>
  1014. <tr class=listheading>
  1015. |;
  1016. for (@column_index) { print "\n$column_header{$_}" }
  1017. print qq|
  1018. </tr>
  1019. |;
  1020. # add sort and escape callback, this one we use for the add sub
  1021. $form->{callback} = $callback .= "&sort=$form->{sort}";
  1022. # escape callback for href
  1023. $callback = $form->escape($callback);
  1024. # flip direction
  1025. $direction = ($form->{direction} eq 'ASC') ? "ASC" : "DESC";
  1026. $href =~ s/&direction=(\w+)&/&direction=$direction&/;
  1027. %total = ();
  1028. foreach $ref (@{ $form->{transactions} }) {
  1029. if ($sameemployeenumber ne $ref->{employeenumber}) {
  1030. $sameemployeenumber = $ref->{employeenumber};
  1031. $sameweek = $ref->{workweek};
  1032. if ($form->{l_subtotal}) {
  1033. print qq|
  1034. <tr class=listsubtotal>
  1035. |;
  1036. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  1037. $weektotal = 0;
  1038. for (keys %weekday) {
  1039. $column_data{$_} = "<th class=listsubtotal align=right>".$form->format_amount(\%myconfig, $subtotal{$_}, "", "&nbsp;")."</th>";
  1040. $weektotal += $subtotal{$_};
  1041. $subtotal{$_} = 0;
  1042. }
  1043. $column_data{$form->{sort}} = "<th class=listsubtotal align=right>".$form->format_amount(\%myconfig, $weektotal, "", "&nbsp;")."</th>";
  1044. for (@column_index) { print "\n$column_data{$_}" }
  1045. }
  1046. # print total
  1047. print qq|
  1048. <tr class=listtotal>
  1049. |;
  1050. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  1051. $total = 0;
  1052. for (keys %weekday) {
  1053. $column_data{$_} = "<th class=listtotal align=right>".$form->format_amount(\%myconfig, $total{$_}, "", "&nbsp;")."</th>";
  1054. $total += $total{$_};
  1055. $total{$_} = 0;
  1056. }
  1057. $column_data{$form->{sort}} = "<th class=listtotal align=right>".$form->format_amount(\%myconfig, $total, "", "&nbsp;")."</th>";
  1058. for (@column_index) { print "\n$column_data{$_}" }
  1059. print qq|
  1060. <tr height=30 valign=bottom>
  1061. <th colspan=2 align=left>
  1062. $ref->{employee}
  1063. </th>
  1064. <th align=left>
  1065. $ref->{employeenumber}
  1066. </th>
  1067. <tr class=listheading>
  1068. |;
  1069. for (@column_index) { print "\n$column_header{$_}" }
  1070. print qq|
  1071. </tr>
  1072. |;
  1073. }
  1074. if ($form->{l_subtotal}) {
  1075. if ($ref->{workweek} != $sameweek) {
  1076. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  1077. $weektotal = 0;
  1078. for (keys %weekday) {
  1079. $column_data{$_} = "<th class=listsubtotal align=right>".$form->format_amount(\%myconfig, $subtotal{$_}, "", "&nbsp;")."</th>";
  1080. $weektotal += $subtotal{$_};
  1081. $subtotal{$_} = 0
  1082. }
  1083. $column_data{$form->{sort}} = "<th class=listsubtotal align=right>".$form->format_amount(\%myconfig, $weektotal, "", "&nbsp;")."</th>";
  1084. $sameweek = $ref->{workweek};
  1085. print qq|
  1086. <tr class=listsubtotal>
  1087. |;
  1088. for (@column_index) { print "\n$column_data{$_}" }
  1089. print qq|
  1090. </tr>
  1091. |;
  1092. }
  1093. }
  1094. for (@column_index) { $column_data{$_} = "<td>$ref->{$_}&nbsp;</td>" }
  1095. for (keys %weekday) { $column_data{$_} = "<td>&nbsp;</td>" }
  1096. $column_data{allocated} = "<td align=right>".$form->format_amount(\%myconfig, $ref->{allocated}, "", "&nbsp;")."</td>";
  1097. $column_data{$ref->{weekday}} = "<td align=right>".$form->format_amount(\%myconfig, $ref->{qty}, "", "&nbsp;");
  1098. if ($form->{l_time}) {
  1099. $column_data{$ref->{weekday}} .= "<br>$ref->{checkedin}<br>$ref->{checkedout}";
  1100. }
  1101. $column_data{$ref->{weekday}} .= "</td>";
  1102. $column_data{id} = "<td><a href=$form->{script}?action=edit&id=$ref->{id}&type=$form->{type}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&project=$form->{project}&callback=$callback>$ref->{id}</a></td>";
  1103. $subtotal{$ref->{weekday}} += $ref->{qty};
  1104. $total{$ref->{weekday}} += $ref->{qty};
  1105. $j++; $j %= 2;
  1106. print qq|
  1107. <tr class=listrow$j>
  1108. |;
  1109. for (@column_index) { print "\n$column_data{$_}" }
  1110. print qq|
  1111. </tr>
  1112. |;
  1113. }
  1114. # print last subtotal
  1115. if ($form->{l_subtotal}) {
  1116. print qq|
  1117. <tr class=listsubtotal>
  1118. |;
  1119. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  1120. $weektotal = 0;
  1121. for (keys %weekday) {
  1122. $column_data{$_} = "<th class=listsubtotal align=right>".$form->format_amount(\%myconfig, $subtotal{$_}, "", "&nbsp;")."</th>";
  1123. $weektotal += $subtotal{$_};
  1124. }
  1125. $column_data{$form->{sort}} = "<th class=listsubtotal align=right>".$form->format_amount(\%myconfig, $weektotal, "", "&nbsp;")."</th>";
  1126. for (@column_index) { print "\n$column_data{$_}" }
  1127. }
  1128. # print last total
  1129. print qq|
  1130. <tr class=listtotal>
  1131. |;
  1132. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  1133. $total = 0;
  1134. for (keys %weekday) {
  1135. $column_data{$_} = "<th class=listtotal align=right>".$form->format_amount(\%myconfig, $total{$_}, "", "&nbsp;")."</th>";
  1136. $total += $total{$_};
  1137. $total{$_} = 0;
  1138. }
  1139. $column_data{$form->{sort}} = "<th class=listtotal align=right>".$form->format_amount(\%myconfig, $total, "", "&nbsp;")."</th>";
  1140. for (@column_index) { print "\n$column_data{$_}" }
  1141. if ($form->{project} eq 'job') {
  1142. if ($myconfig{acs} !~ /Production--Production/) {
  1143. $i = 1;
  1144. $button{'Production--Add Time Card'}{code} = qq|<button class="submit" type="submit" name="action" value="add_time_card">|.$locale->text('Add Time Card').qq|</button> |;
  1145. $button{'Production--Add Time Card'}{order} = $i++;
  1146. }
  1147. } elsif ($form->{project} eq 'project') {
  1148. if ($myconfig{acs} !~ /Projects--Projects/) {
  1149. $i = 1;
  1150. $button{'Projects--Add Time Card'}{code} = qq|<button class="submit" type="submit" name="action" value="add_time_card">|.$locale->text('Add Time Card').qq|</button> |;
  1151. $button{'Projects--Add Time Card'}{order} = $i++;
  1152. }
  1153. } else {
  1154. if ($myconfig{acs} !~ /Time Cards--Time Cards/) {
  1155. $i = 1;
  1156. $button{'Time Cards--Add Time Card'}{code} = qq|<button class="submit" type="submit" name="action" value="add_time_card">|.$locale->text('Add Time Card').qq|</button> |;
  1157. $button{'Time Cards--Add Time Card'}{order} = $i++;
  1158. }
  1159. }
  1160. for (split /;/, $myconfig{acs}) { delete $button{$_} }
  1161. print qq|
  1162. </tr>
  1163. </table>
  1164. </td>
  1165. </tr>
  1166. <tr>
  1167. <td><hr size=3 noshade></td>
  1168. </tr>
  1169. </table>
  1170. <br>
  1171. <form method=post action=$form->{script}>
  1172. |;
  1173. $form->hide_form(qw(callback path login sessionid project));
  1174. foreach $item (sort { $a->{order} <=> $b->{order} } %button) {
  1175. print $item->{code};
  1176. }
  1177. if ($form->{lynx}) {
  1178. require "bin/menu.pl";
  1179. &menubar;
  1180. }
  1181. print qq|
  1182. </form>
  1183. </body>
  1184. </html>
  1185. |;
  1186. }
  1187. sub list_storescard {
  1188. $form->{type} = "storescard";
  1189. JC->jcitems(\%myconfig, \%$form);
  1190. $form->{title} = $locale->text('Stores Cards');
  1191. $href = "$form->{script}?action=list_storescard";
  1192. for (qw(type direction oldsort path login sessionid project)) { $href .= "&$_=$form->{$_}" }
  1193. $href .= "&title=".$form->escape($form->{title});
  1194. $form->sort_order();
  1195. $callback = "$form->{script}?action=list_storescard";
  1196. for (qw(type direction oldsort path login sessionid project)) { $callback .= "&$_=$form->{$_}" }
  1197. $callback .= "&title=".$form->escape($form->{title},1);
  1198. @column_index = $form->sort_columns(qw(transdate projectnumber projectdescription id partnumber description qty amount));
  1199. if ($form->{projectnumber}) {
  1200. $callback .= "&projectnumber=".$form->escape($form->{projectnumber},1);
  1201. $href .= "&projectnumber=".$form->escape($form->{projectnumber});
  1202. ($var) = split /--/, $form->{projectnumber};
  1203. $option .= "\n<br>" if ($option);
  1204. $option .= "$joblabel : $var";
  1205. @column_index = grep !/projectnumber/, @column_index;
  1206. }
  1207. if ($form->{partnumber}) {
  1208. $callback .= "&partnumber=".$form->escape($form->{partnumber},1);
  1209. $href .= "&partnumber=".$form->escape($form->{partnumber});
  1210. ($var) = split /--/, $form->{partnumber};
  1211. $option .= "\n<br>" if ($option);
  1212. $option .= "$laborlabel : $var";
  1213. @column_index = grep !/partnumber/, @column_index;
  1214. }
  1215. if ($form->{startdatefrom}) {
  1216. $callback .= "&startdatefrom=$form->{startdatefrom}";
  1217. $href .= "&startdatefrom=$form->{startdatefrom}";
  1218. $option .= "\n<br>" if ($option);
  1219. $option .= $locale->text('From')."&nbsp;".$locale->date(\%myconfig, $form->{startdatefrom}, 1);
  1220. }
  1221. if ($form->{startdateto}) {
  1222. $callback .= "&startdateto=$form->{startdateto}";
  1223. $href .= "&startdateto=$form->{startdateto}";
  1224. $option .= "\n<br>" if ($option);
  1225. $option .= $locale->text('To')."&nbsp;".$locale->date(\%myconfig, $form->{startdateto}, 1);
  1226. }
  1227. $column_header{id} = "<th><a class=listheading href=$href&sort=id>" . $locale->text('ID') . "</a></th>";
  1228. $column_header{transdate} = "<th><a class=listheading href=$href&sort=transdate>".$locale->text('Date')."</a></th>";
  1229. $column_header{projectnumber} = "<th><a class=listheading href=$href&sort=projectnumber>" . $locale->text('Job Number') . "</a></th>";
  1230. $column_header{projectdescription} = "<th><a class=listheading href=$href&sort=projectdescription>" . $locale->text('Job Description') . "</a></th>";
  1231. $column_header{partnumber} = "<th><a class=listheading href=$href&sort=partnumber>" . $locale->text('Part Number') . "</a></th>";
  1232. $column_header{description} = "<th><a class=listheading href=$href&sort=description>" . $locale->text('Description') . "</a></th>";
  1233. $column_header{qty} = "<th class=listheading>" . $locale->text('Qty') . "</th>";
  1234. $column_header{amount} = "<th class=listheading>" . $locale->text('Amount') . "</th>";
  1235. $form->header;
  1236. if (@{ $form->{transactions} }) {
  1237. $sameitem = $form->{transactions}->[0]->{$form->{sort}};
  1238. }
  1239. print qq|
  1240. <body>
  1241. <table width=100%>
  1242. <tr>
  1243. <th class=listtop>$form->{title}</th>
  1244. </tr>
  1245. <tr height="5"></tr>
  1246. <tr>
  1247. <td>$option</td>
  1248. </tr>
  1249. <tr>
  1250. <td>
  1251. <table width=100%>
  1252. <tr class=listheading>
  1253. |;
  1254. for (@column_index) { print "\n$column_header{$_}" }
  1255. print qq|
  1256. </tr>
  1257. |;
  1258. # add sort and escape callback, this one we use for the add sub
  1259. $form->{callback} = $callback .= "&sort=$form->{sort}";
  1260. # escape callback for href
  1261. $callback = $form->escape($callback);
  1262. # flip direction
  1263. $direction = ($form->{direction} eq 'ASC') ? "ASC" : "DESC";
  1264. $href =~ s/&direction=(\w+)&/&direction=$direction&/;
  1265. $total = 0;
  1266. foreach $ref (@{ $form->{transactions} }) {
  1267. for (@column_index) { $column_data{$_} = "<td>$ref->{$_}&nbsp;</td>" }
  1268. $column_data{qty} = qq|<td align=right>|.$form->format_amount(\%myconfig, $ref->{qty}, "", "&nbsp;")."</td>";
  1269. $column_data{amount} = qq|<td align=right>|.$form->format_amount(\%myconfig, $ref->{qty} * $ref->{sellprice}, 2)."</td>";
  1270. $column_data{id} = "<td><a href=$form->{script}?action=edit&id=$ref->{id}&type=$form->{type}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&project=$form->{project}&callback=$callback>$ref->{id}</a></td>";
  1271. $total += ($ref->{qty} * $ref->{sellprice});
  1272. $j++; $j %= 2;
  1273. print qq|
  1274. <tr class=listrow$j>
  1275. |;
  1276. for (@column_index) { print "\n$column_data{$_}" }
  1277. print qq|
  1278. </tr>
  1279. |;
  1280. }
  1281. # print total
  1282. print qq|
  1283. <tr class=listtotal>
  1284. |;
  1285. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  1286. $column_data{amount} = qq|<th align=right>|.$form->format_amount(\%myconfig, $total, 2)."</th";
  1287. for (@column_index) { print "\n$column_data{$_}" }
  1288. if ($form->{project} eq 'job') {
  1289. if ($myconfig{acs} !~ /Production--Production/) {
  1290. $i = 1;
  1291. $button{'Production--Add Stores Card'}{code} = qq|<button class="submit" type="submit" name="action" value="add_stores_card">|.$locale->text('Add Stores Card').qq|</button> |;
  1292. $button{'Production--Add Stores Card'}{order} = $i++;
  1293. }
  1294. }
  1295. for (split /;/, $myconfig{acs}) { delete $button{$_} }
  1296. print qq|
  1297. </tr>
  1298. </table>
  1299. </td>
  1300. </tr>
  1301. <tr>
  1302. <td><hr size=3 noshade></td>
  1303. </tr>
  1304. </table>
  1305. <br>
  1306. <form method=post action=$form->{script}>
  1307. |;
  1308. $form->hide_form(qw(callback path login sessionid project));
  1309. foreach $item (sort { $a->{order} <=> $b->{order} } %button) {
  1310. print $item->{code};
  1311. }
  1312. if ($form->{lynx}) {
  1313. require "bin/menu.pl";
  1314. &menubar;
  1315. }
  1316. print qq|
  1317. </form>
  1318. </body>
  1319. </html>
  1320. |;
  1321. }
  1322. sub continue { &{ $form->{nextsub} } };
  1323. sub add_time_card {
  1324. $form->{type} = "timecard";
  1325. &add;
  1326. }
  1327. sub add_stores_card {
  1328. $form->{type} = "storescard";
  1329. &add;
  1330. }
  1331. sub print_options {
  1332. if ($form->{selectlanguage}) {
  1333. $form->{"selectlanguage"} = $form->unescape($form->{"selectlanguage"});
  1334. $form->{"selectlanguage"} =~ s/ selected//;
  1335. $form->{"selectlanguage"} =~ s/(<option value="\Q$form->{language_code}\E")/$1 selected/;
  1336. $lang = qq|<select name=language_code>$form->{selectlanguage}</select>
  1337. <input type=hidden name=selectlanguage value="|.
  1338. $form->escape($form->{selectlanguage},1).qq|">|;
  1339. }
  1340. $form->{selectformname} = $form->unescape($form->{selectformname});
  1341. $form->{selectformname} =~ s/ selected//;
  1342. $form->{selectformname} =~ s/(<option value="\Q$form->{formname}\E")/$1 selected/;
  1343. $type = qq|<select name=formname>$form->{selectformname}</select>
  1344. <input type=hidden name=selectformname value="|.$form->escape($form->{selectformname},1).qq|">|;
  1345. $media = qq|<select name=media>
  1346. <option value="screen">|.$locale->text('Screen');
  1347. $form->{selectformat} = qq|<option value="html">html\n|;
  1348. if (%{LedgerSMB::Sysconfig::printer} && ${LedgerSMB::Sysconfig::latex}) {
  1349. for (sort keys %{LedgerSMB::Sysconfig::printer}) { $media .= qq|
  1350. <option value="$_">$_| }
  1351. }
  1352. if (${LedgerSMB::Sysconfig::latex}) {
  1353. $media .= qq|
  1354. <option value="queue">|.$locale->text('Queue');
  1355. $form->{selectformat} .= qq|
  1356. <option value="postscript">|.$locale->text('Postscript').qq|
  1357. <option value="pdf">|.$locale->text('PDF');
  1358. }
  1359. $format = qq|<select name=format>$form->{selectformat}</select>|;
  1360. $format =~ s/(<option value="\Q$form->{format}\E")/$1 selected/;
  1361. $format .= qq|
  1362. <input type=hidden name=selectformat value="|.$form->escape($form->{selectformat},1).qq|">|;
  1363. $media .= qq|</select>|;
  1364. $media =~ s/(<option value="\Q$form->{media}\E")/$1 selected/;
  1365. print qq|
  1366. <table width=100%>
  1367. <tr>
  1368. <td>$type</td>
  1369. <td>$lang</td>
  1370. <td>$format</td>
  1371. <td>$media</td>
  1372. <td align=right width=90%>
  1373. |;
  1374. if ($form->{printed} =~ /$form->{formname}/) {
  1375. print $locale->text('Printed').qq|<br>|;
  1376. }
  1377. if ($form->{queued} =~ /$form->{formname}/) {
  1378. print $locale->text('Queued');
  1379. }
  1380. print qq|
  1381. </td>
  1382. </tr>
  1383. </table>
  1384. |;
  1385. }
  1386. sub print {
  1387. if ($form->{media} !~ /screen/) {
  1388. $form->error($locale->text('Select postscript or PDF!')) if $form->{format} !~ /(postscript|pdf)/;
  1389. $old_form = new Form;
  1390. for (keys %$form) { $old_form->{$_} = $form->{$_} }
  1391. }
  1392. &{ "print_$form->{formname}" }($old_form);
  1393. }
  1394. sub print_timecard {
  1395. my ($old_form) = @_;
  1396. $display_form = ($form->{display_form}) ? $form->{display_form} : "update";
  1397. $form->{description} =~ s/^\s+//g;
  1398. for (qw(partnumber projectnumber)) { $form->{$_} =~ s/--.*// }
  1399. @a = qw(hour min sec);
  1400. foreach $item (qw(in out)) {
  1401. for (@a) { $form->{"$item$_"} = substr(qq|00$form->{"$item$_"}|, -2) }
  1402. $form->{"checked$item"} = qq|$form->{"${item}hour"}:$form->{"${item}min"}:$form->{"${item}sec"}|;
  1403. }
  1404. @a = ();
  1405. for (qw(company address tel fax businessnumber)) { $form->{$_} = $myconfig{$_} }
  1406. $form->{address} =~ s/\\n/\n/g;
  1407. push @a, qw(partnumber description projectnumber projectdescription);
  1408. push @a, qw(company address tel fax businessnumber username useremail);
  1409. $form->format_string(@a);
  1410. $form->{total} = $form->format_amount(\%myconfig, $form->parse_amount(\%myconfig, $form->{qty}) * $form->parse_amount(\%myconfig, $form->{sellprice}), 2);
  1411. ($form->{employee}, $form->{employee_id}) = split /--/, $form->{employee};
  1412. $form->{templates} = "$myconfig{templates}";
  1413. $form->{IN} = "$form->{formname}.html";
  1414. if ($form->{format} =~ /(postscript|pdf)/) {
  1415. $form->{IN} =~ s/html$/tex/;
  1416. }
  1417. if ($form->{media} !~ /(screen|queue)/) {
  1418. $form->{OUT} = "${LedgerSMB::Sysconfig::printer}{$form->{media}}";
  1419. $form->{printmode} = '|-';
  1420. if ($form->{printed} !~ /$form->{formname}/) {
  1421. $form->{printed} .= " $form->{formname}";
  1422. $form->{printed} =~ s/^ //;
  1423. $form->update_status(\%myconfig);
  1424. }
  1425. %audittrail = ( tablename => jcitems,
  1426. reference => $form->{id},
  1427. formname => $form->{formname},
  1428. action => 'printed',
  1429. id => $form->{id} );
  1430. %status = ();
  1431. for (qw(printed queued audittrail)) { $status{$_} = $form->{$_} }
  1432. $status{audittrail} .= $form->audittrail("", \%myconfig, \%audittrail);
  1433. }
  1434. if ($form->{media} eq 'queue') {
  1435. %queued = split / /, $form->{queued};
  1436. if ($filename = $queued{$form->{formname}}) {
  1437. $form->{queued} =~ s/$form->{formname} $filename//;
  1438. unlink "${LedgerSMB::Sysconfig::spool}/$filename";
  1439. $filename =~ s/\..*$//g;
  1440. } else {
  1441. $filename = time;
  1442. $filename .= $$;
  1443. }
  1444. $filename .= ($form->{format} eq 'postscript') ? '.ps' : '.pdf';
  1445. $form->{OUT} = "${LedgerSMB::Sysconfig::spool}/$filename";
  1446. $form->{printmode} = '>';
  1447. $form->{queued} = "$form->{formname} $filename";
  1448. $form->update_status(\%myconfig);
  1449. %audittrail = ( tablename => jcitems,
  1450. reference => $form->{id},
  1451. formname => $form->{formname},
  1452. action => 'queued',
  1453. id => $form->{id} );
  1454. %status = ();
  1455. for (qw(printed queued audittrail)) { $status{$_} = $form->{$_} }
  1456. $status{audittrail} .= $form->audittrail("", \%myconfig, \%audittrail);
  1457. }
  1458. $form->parse_template(\%myconfig, ${LedgerSMB::Sysconfig::userspath});
  1459. if (defined %$old_form) {
  1460. for (keys %$old_form) { $form->{$_} = $old_form->{$_} }
  1461. for (qw(printed queued audittrail)) { $form->{$_} = $status{$_} }
  1462. &{ "$display_form" };
  1463. }
  1464. }