- #=====================================================================
- # LedgerSMB
- # Small Medium Business Accounting software
- # http://www.ledgersmb.org/
- #
- # Copyright (C) 2006
- # This work contains copyrighted information from a number of sources all used
- # with permission.
- #
- # This file contains source code included with or based on SQL-Ledger which
- # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
- # under the GNU General Public License version 2 or, at your option, any later
- # version. For a full list including contact information of contributors,
- # maintainers, and copyright holders, see the CONTRIBUTORS file.
- #
- # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
- # Copyright (C) 2005
- #
- # Author: DWS Systems Inc.
- # Web: http://www.sql-ledger.org
- #
- # Contributors:
- #
- #======================================================================
- #
- # This file has NOT undergone whitespace cleanup.
- #
- #======================================================================
- #
- # Job Costing
- #
- #======================================================================
- package JC;
- use LedgerSMB::IS;
- sub get_jcitems {
- my ($self, $myconfig, $form) = @_;
- # connect to database
- my $dbh = $form->dbconnect($myconfig);
- my $query = qq|SELECT current_date FROM defaults|;
- ($form->{transdate}) = $dbh->selectrow_array($query);
- ($form->{employee}, $form->{employee_id}) = $form->get_employee($dbh);
-
- my $dateformat = $myconfig->{dateformat};
- $dateformat =~ s/yy/yyyy/;
- $dateformat =~ s/yyyyyy/yyyy/;
-
- if ($form->{id}) {
- # retrieve timecard/storescard
- $query = qq|SELECT j.*, to_char(j.checkedin, 'HH24:MI:SS') AS checkedina,
- to_char(j.checkedout, 'HH24:MI:SS') AS checkedouta,
- to_char(j.checkedin, '$dateformat') AS transdate,
- e.name AS employee, p.partnumber,
- pr.projectnumber, pr.description AS projectdescription,
- pr.production, pr.completed, pr.parts_id AS project
- FROM jcitems j
- JOIN employee e ON (e.id = j.employee_id)
- JOIN parts p ON (p.id = j.parts_id)
- JOIN project pr ON (pr.id = j.project_id)
- WHERE j.id = $form->{id}|;
- $sth = $dbh->prepare($query);
- $sth->execute || $form->dberror($query);
- $ref = $sth->fetchrow_hashref(NAME_lc);
-
- for (keys %$ref) { $form->{$_} = $ref->{$_} }
- $sth->finish;
- $form->{project} = ($form->{project}) ? "job" : "project";
- for (qw(checkedin checkedout)) {
- $form->{$_} = $form->{"${_}a"};
- delete $form->{"${_}a"};
- }
- $query = qq|SELECT s.printed, s.spoolfile, s.formname
- FROM status s
- WHERE s.formname = '$form->{type}'
- AND s.trans_id = $form->{id}|;
- $sth = $dbh->prepare($query);
- $sth->execute || $form->dberror($query);
- while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
- $form->{printed} .= "$ref->{formname} " if $ref->{printed};
- $form->{queued} .= "$ref->{formname} $ref->{spoolfile} " if $ref->{spoolfile};
- }
- $sth->finish;
- for (qw(printed queued)) { $form->{$_} =~ s/ +$//g }
- }
-
- JC->jcitems_links($myconfig, $form, $dbh);
-
- # get language codes
- $query = qq|SELECT *
- FROM language
- ORDER BY 2|;
- $sth = $dbh->prepare($query);
- $sth->execute || $form->dberror($query);
- $form->{all_language} = ();
- while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
- push @{ $form->{all_language} }, $ref;
- }
- $sth->finish;
-
- $dbh->disconnect;
- }
- sub jcitems_links {
- my ($self, $myconfig, $form, $dbh) = @_;
-
- my $disconnect = 0;
- if (! $dbh) {
- $dbh = $form->dbconnect($myconfig);
- $disconnect = 1;
- }
-
- my $query;
- if ($form->{project_id}) {
- $form->{orphaned} = 1;
- $query = qq|SELECT parts_id
- FROM project
- WHERE id = $form->{project_id}|;
- if ($dbh->selectrow_array($query)) {
- $form->{project} = 'job';
- $query = qq|SELECT id
- FROM project
- WHERE parts_id > 0
- AND production > completed
- AND id = $form->{project_id}|;
- ($form->{orphaned}) = $dbh->selectrow_array($q);
- } else {
- $form->{project} = 'project';
- }
- }
- JC->jcparts($myconfig, $form, $dbh);
-
- $form->all_employees($myconfig, $dbh, $form->{transdate});
-
- my $where;
-
- if ($form->{transdate}) {
- $where .= qq| AND (enddate IS NULL
- OR enddate >= '$form->{transdate}')
- AND (startdate <= '$form->{transdate}'
- OR startdate IS NULL)|;
- }
-
- if ($form->{project} eq 'job') {
- $query = qq|
- SELECT pr.*
- FROM project pr
- WHERE pr.parts_id > 0
- AND pr.production > pr.completed
- $where|;
- } elsif ($form->{project} eq 'project') {
- $query = qq|
- SELECT pr.*
- FROM project pr
- WHERE pr.parts_id IS NULL
- $where|;
- } else {
- $query = qq|
- SELECT pr.*
- FROM project pr
- WHERE 1=1
- $where
- EXCEPT
- SELECT pr.*
- FROM project pr
- WHERE pr.parts_id > 0
- AND pr.production = pr.completed|;
- }
- if ($form->{project_id}) {
- $query .= qq|
- UNION
- SELECT *
- FROM project
- WHERE id = $form->{project_id}|;
- }
-
- $query .= qq|
- ORDER BY projectnumber|;
- $sth = $dbh->prepare($query);
- $sth->execute || $form->dberror($query);
- while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
- push @{ $form->{all_project} }, $ref;
- }
- $sth->finish;
-
- $dbh->disconnect if $disconnect;
-
- }
- sub jcparts {
- my ($self, $myconfig, $form, $dbh) = @_;
-
- my ($null, $project_id) = split /--/, $form->{projectnumber};
- $project_id *= 1;
- my $query = qq|SELECT customer_id
- FROM project
- WHERE id = $project_id|;
- my ($customer_id) = $dbh->selectrow_array($query);
- $customer_id *= 1;
-
- my $where;
- if ($form->{project} eq 'job') {
- $where = " AND p.income_accno_id IS NULL";
- if ($form->{type} eq 'storescard') {
- $where = " AND p.inventory_accno_id > 0
- AND p.income_accno_id > 0";
- }
-
- $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
- p.unit, t.description AS translation
- FROM parts p
- LEFT JOIN translation t ON (t.trans_id = p.id AND t.language_code = '$form->{language_code}')
- WHERE p.obsolete = '0'
- $where|;
- } elsif ($form->{project} eq 'project') {
- $where = " AND p.inventory_accno_id IS NULL";
- if ($form->{type} eq 'storescard') {
- $where = " AND p.inventory_accno_id > 0";
- }
-
- $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
- p.unit, t.description AS translation
- FROM parts p
- LEFT JOIN translation t ON (t.trans_id = p.id AND t.language_code = '$form->{language_code}')
- WHERE p.obsolete = '0'
- AND p.assembly = '0'
- $where|;
- } else {
-
- $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
- p.unit, t.description AS translation
- FROM parts p
- LEFT JOIN translation t ON (t.trans_id = p.id AND t.language_code = '$form->{language_code}')
- WHERE p.obsolete = '0'
- AND p.income_accno_id IS NULL
- UNION
- SELECT p.id, p.partnumber, p.description, p.sellprice,
- p.unit, t.description AS translation
- FROM parts p
- LEFT JOIN translation t ON (t.trans_id = p.id AND t.language_code = '$form->{language_code}')
- WHERE p.obsolete = '0'
- AND p.assembly = '0'
- AND p.inventory_accno_id IS NULL|;
- }
- $query .= qq|
- ORDER BY 2|;
- my $sth = $dbh->prepare($query);
- $sth->execute || $form->dberror($query);
- my $pmh = price_matrix_query($dbh, $project_id, $customer_id);
- IS::exchangerate_defaults($dbh, $form);
- while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
- $ref->{description} = $ref->{translation} if $ref->{translation};
- IS::price_matrix($pmh, $ref, $form->datetonum($form->{transdate}), 4, $form, $myconfig);
- push @{ $form->{all_parts} }, $ref;
- }
- $sth->finish;
- }
- sub delete_timecard {
- my ($self, $myconfig, $form) = @_;
- # connect to database
- my $dbh = $form->dbconnect_noauto($myconfig);
-
- my %audittrail = ( tablename => 'jcitems',
- reference => $form->{id},
- formname => $form->{type},
- action => 'deleted',
- id => $form->{id} );
- $form->audittrail($dbh, "", \%audittrail);
-
- my $query = qq|DELETE FROM jcitems
- WHERE id = $form->{id}|;
- $dbh->do($query) || $form->dberror($query);
- # delete spool files
- $query = qq|SELECT spoolfile FROM status
- WHERE formname = '$form->{type}'
- AND trans_id = $form->{id}
- AND spoolfile IS NOT NULL|;
- my $sth = $dbh->prepare($query);
- $sth->execute || $form->dberror($query);
- my $spoolfile;
- my @spoolfiles = ();
- while (($spoolfile) = $sth->fetchrow_array) {
- push @spoolfiles, $spoolfile;
- }
- $sth->finish;
- # delete status entries
- $query = qq|DELETE FROM status
- WHERE formname = '$form->{type}'
- AND trans_id = $form->{id}|;
- $dbh->do($query) || $form->dberror($query);
- my $rc = $dbh->commit;
- if ($rc) {
- foreach $spoolfile (@spoolfiles) {
- unlink "$spool/$spoolfile" if $spoolfile;
- }
- }
- $dbh->disconnect;
- $rc;
- }
- sub jcitems {
- my ($self, $myconfig, $form) = @_;
- # connect to database
- my $dbh = $form->dbconnect($myconfig);
-
- my $query;
- my $where = "1 = 1";
- my $null;
- my $var;
-
- if ($form->{projectnumber}) {
- ($null, $var) = split /--/, $form->{projectnumber};
- $where .= " AND j.project_id = $var";
- $query = qq|SELECT parts_id
- FROM project
- WHERE id = $var|;
- my ($job) = $dbh->selectrow_array($query);
- $form->{project} = ($job) ? "job" : "project";
-
- }
- if ($form->{partnumber}) {
- ($null, $var) = split /--/, $form->{partnumber};
- $where .= " AND j.parts_id = $var";
- $query = qq|SELECT inventory_accno_id
- FROM parts
- WHERE id = $var|;
- my ($job) = $dbh->selectrow_array($query);
- $form->{project} = ($job) ? "job" : "project";
-
- }
- if ($form->{employee}) {
- ($null, $var) = split /--/, $form->{employee};
- $where .= " AND j.employee_id = $var";
- }
- if ($form->{open} || $form->{closed}) {
- unless ($form->{open} && $form->{closed}) {
- $where .= " AND j.qty != j.allocated" if $form->{open};
- $where .= " AND j.qty = j.allocated" if $form->{closed};
- }
- }
-
- ($form->{startdatefrom}, $form->{startdateto}) = $form->from_to($form->{year}, $form->{month}, $form->{interval}) if $form->{year} && $form->{month};
-
- $where .= " AND j.checkedin >= '$form->{startdatefrom}'" if $form->{startdatefrom};
- $where .= " AND j.checkedout < date '$form->{startdateto}' + 1" if $form->{startdateto};
- my %ordinal = ( id => 1,
- description => 2,
- transdate => 7,
- partnumber => 9,
- projectnumber => 10,
- projectdescription => 11,
- );
-
- my @a = (transdate, projectnumber);
- my $sortorder = $form->sort_order(\@a, \%ordinal);
-
- my $dateformat = $myconfig->{dateformat};
- $dateformat =~ s/yy$/yyyy/;
- $dateformat =~ s/yyyyyy/yyyy/;
-
- if ($form->{project} eq 'job') {
- if ($form->{type} eq 'timecard') {
- $where .= " AND pr.parts_id > 0
- AND p.income_accno_id IS NULL";
- }
-
- if ($form->{type} eq 'storescard') {
- $where .= " AND pr.parts_id > 0
- AND p.income_accno_id > 0";
- }
- }
- if ($form->{project} eq 'project') {
- $where .= " AND pr.parts_id IS NULL";
- }
-
- $query = qq|SELECT j.id, j.description, j.qty, j.allocated,
- to_char(j.checkedin, 'HH24:MI') AS checkedin,
- to_char(j.checkedout, 'HH24:MI') AS checkedout,
- to_char(j.checkedin, 'yyyymmdd') AS transdate,
- to_char(j.checkedin, '$dateformat') AS transdatea,
- to_char(j.checkedin, 'D') AS weekday,
- p.partnumber,
- pr.projectnumber, pr.description AS projectdescription,
- e.employeenumber, e.name AS employee,
- to_char(j.checkedin, 'WW') AS workweek, pr.parts_id,
- j.sellprice
- FROM jcitems j
- JOIN parts p ON (p.id = j.parts_id)
- JOIN project pr ON (pr.id = j.project_id)
- JOIN employee e ON (e.id = j.employee_id)
- WHERE $where
- ORDER BY employee, employeenumber, $sortorder|;
- $sth = $dbh->prepare($query);
- $sth->execute || $form->dberror($query);
- while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
- $ref->{project} = ($ref->{parts_id}) ? "job" : "project";
- $ref->{transdate} = $ref->{transdatea};
- delete $ref->{transdatea};
- push @{ $form->{transactions} }, $ref;
- }
- $sth->finish;
-
- $dbh->disconnect;
- }
- sub save {
- my ($self, $myconfig, $form) = @_;
-
- # connect to database
- my $dbh = $form->dbconnect_noauto($myconfig);
- my $query;
- my $sth;
-
- my ($null, $project_id) = split /--/, $form->{projectnumber};
- if ($form->{id}) {
- # check if it was a job
- $query = qq|SELECT pr.parts_id, pr.production - pr.completed
- FROM project pr
- JOIN jcitems j ON (j.project_id = pr.id)
- WHERE j.id = $form->{id}|;
- my ($job_id, $qty) = $dbh->selectrow_array($query);
- if ($job_id && $qty == 0) {
- $dbh->disconnect;
- return -1;
- }
-
- # check if new one belongs to a job
- if ($project_id) {
- $query = qq|SELECT pr.parts_id, pr.production - pr.completed
- FROM project pr
- WHERE pr.id = $project_id|;
- my ($job_id, $qty) = $dbh->selectrow_array($query);
- if ($job_id && $qty == 0) {
- $dbh->disconnect;
- return -2;
- }
- }
-
- } else {
- my $uid = localtime;
- $uid .= "$$";
- $query = qq|INSERT INTO jcitems (description)
- VALUES ('$uid')|;
- $dbh->do($query) || $form->dberror($query);
- $query = qq|SELECT id FROM jcitems
- WHERE description = '$uid'|;
- ($form->{id}) = $dbh->selectrow_array($query);
- }
- for (qw(inhour inmin insec outhour outmin outsec)) { $form->{$_} = substr("00$form->{$_}", -2) }
- for (qw(qty sellprice allocated)) { $form->{$_} = $form->parse_amount($myconfig, $form->{$_}) }
- my $checkedin = "$form->{inhour}$form->{inmin}$form->{insec}";
- my $checkedout = "$form->{outhour}$form->{outmin}$form->{outsec}";
-
- my $outdate = $form->{transdate};
- if ($checkedout < $checkedin) {
- $outdate = $form->add_date($myconfig, $form->{transdate}, 1, 'days');
- }
- ($null, $form->{employee_id}) = split /--/, $form->{employee};
- unless ($form->{employee_id}) {
- ($form->{employee}, $form->{employee_id}) = $form->get_employee($dbh);
- }
- my $parts_id;
- ($null, $parts_id) = split /--/, $form->{partnumber};
-
- $query = qq|UPDATE jcitems SET
- project_id = $project_id,
- parts_id = $parts_id,
- description = |.$dbh->quote($form->{description}).qq|,
- qty = $form->{qty},
- allocated = $form->{allocated},
- sellprice = $form->{sellprice},
- fxsellprice = $form->{sellprice},
- serialnumber = |.$dbh->quote($form->{serialnumber}).qq|,
- checkedin = timestamp '$form->{transdate} $form->{inhour}:$form->{inmin}:$form->{insec}',
- checkedout = timestamp '$outdate $form->{outhour}:$form->{outmin}:$form->{outsec}',
- employee_id = $form->{employee_id},
- notes = |.$dbh->quote($form->{notes}).qq|
- WHERE id = $form->{id}|;
- $dbh->do($query) || $form->dberror($query);
- # save printed, queued
- $form->save_status($dbh);
- my %audittrail = ( tablename => 'jcitems',
- reference => $form->{id},
- formname => $form->{type},
- action => 'saved',
- id => $form->{id} );
- $form->audittrail($dbh, "", \%audittrail);
-
- my $rc = $dbh->commit;
-
- $rc;
- }
- sub price_matrix_query {
- my ($dbh, $project_id, $customer_id) = @_;
-
- my $query = qq|SELECT p.id AS parts_id, 0 AS customer_id, 0 AS pricegroup_id,
- 0 AS pricebreak, p.sellprice, NULL AS validfrom, NULL AS validto,
- (SELECT substr(curr,1,3) FROM defaults) AS curr, '' AS pricegroup
- FROM parts p
- WHERE p.id = ?
- UNION
-
- SELECT p.*, g.pricegroup
- FROM partscustomer p
- LEFT JOIN pricegroup g ON (g.id = p.pricegroup_id)
- WHERE p.parts_id = ?
- AND p.customer_id = $customer_id
-
- UNION
- SELECT p.*, g.pricegroup
- FROM partscustomer p
- LEFT JOIN pricegroup g ON (g.id = p.pricegroup_id)
- JOIN customer c ON (c.pricegroup_id = g.id)
- WHERE p.parts_id = ?
- AND c.id = $customer_id
-
- UNION
- SELECT p.*, '' AS pricegroup
- FROM partscustomer p
- WHERE p.customer_id = 0
- AND p.pricegroup_id = 0
- AND p.parts_id = ?
- ORDER BY customer_id DESC, pricegroup_id DESC, pricebreak
-
- |;
- my $sth = $dbh->prepare($query) || $form->dberror($query);
- $sth;
- }
- 1;
|