use SL::CVar;
use SL::DBUtils;
+use SL::HTML::Restrict;
use SL::TransNumber;
+use SL::Util qw(trim);
+use SL::DB;
use strict;
# copy to $form variables
map { $form->{$_} = $ref->{$_} } (keys %{$ref});
+ $form->{mtime} = $form->{itime} if !$form->{mtime};
+ $form->{lastmtime} = $form->{mtime};
$form->{onhand} *= 1;
# part or service item
my $i = 1;
foreach my $pg (@{ $pricegroups }) {
- $form->{"klass_$i"} = "$pg->{id}";
- $form->{"price_$i"} = $form->format_amount($myconfig, $form->{"price_$i"}, -2);
+ $form->{"price_$i"} = $form->format_amount($myconfig, $form->{"price_$i"}, -2);
$form->{"pricegroup_id_$i"} = "$pg->{id}";
$form->{"pricegroup_$i"} = "$pg->{pricegroup}";
$i++;
}
sub save {
+ my ($self, $myconfig, $form) = @_;
$main::lxdebug->enter_sub();
+ my $rc = SL::DB->client->with_transaction(\&_save, $self, $myconfig, $form);
+
+ $main::lxdebug->leave_sub();
+ return $rc;
+}
+
+sub _save {
my ($self, $myconfig, $form) = @_;
my @values;
- # connect to database, turn off AutoCommit
- my $dbh = $form->get_standard_dbh;
+
+ my $dbh = SL::DB->client->dbh;
+ my $restricter = SL::HTML::Restrict->create;
# save the part
# make up a unique handle and store in partnumber field
map { $form->{$_} = $form->parse_amount($myconfig, $form->{$_}) }
qw(rop weight listprice sellprice gv lastcost);
- my $makemodel = (($form->{make_1}) || ($form->{model_1})) ? 1 : 0;
+ my $makemodel = ($form->{make_1} || $form->{model_1} || ($form->{makemodel_rows} > 1)) ? 1 : 0;
$form->{assembly} = ($form->{item} eq 'assembly') ? 1 : 0;
}
# get old price
- $query = qq|SELECT sellprice, weight FROM parts WHERE id = ?|;
- my ($sellprice, $weight) = selectrow_query($form, $dbh, $query, conv_i($form->{id}));
-
- # if item is part of an assembly adjust all assemblies
- $query = qq|SELECT id, qty FROM assembly WHERE parts_id = ?|;
- $sth = prepare_execute_query($form, $dbh, $query, conv_i($form->{id}));
- while (my ($id, $qty) = $sth->fetchrow_array) {
- &update_assembly($dbh, $form, $id, $qty, $sellprice * 1, $weight * 1);
- }
- $sth->finish;
+ $query = qq|SELECT sellprice FROM parts WHERE id = ?|;
+ my ($sellprice) = selectrow_query($form, $dbh, $query, conv_i($form->{id}));
# delete makemodel records
do_query($form, $dbh, qq|DELETE FROM makemodel WHERE parts_id = ?|, conv_i($form->{id}));
if ($form->{"item"} ne "assembly") {
$subq_expense =
- qq|(SELECT bg.expense_accno_id_0
- FROM buchungsgruppen bg
- WHERE bg.id = | . conv_i($form->{"buchungsgruppen_id"}, 'NULL') . qq|)|;
+ qq|(SELECT tc.expense_accno_id
+ FROM taxzone_charts tc
+ WHERE tc.buchungsgruppen_id = | . conv_i($form->{"buchungsgruppen_id"}, 'NULL') . qq| and tc.taxzone_id = 0)|;
} else {
$subq_expense = "NULL";
}
partnumber = ?,
description = ?,
makemodel = ?,
- alternate = 'f',
assembly = ?,
listprice = ?,
sellprice = ?,
buchungsgruppen_id = ?,
payment_id = ?,
inventory_accno_id = $subq_inventory,
- income_accno_id = (SELECT bg.income_accno_id_0 FROM buchungsgruppen bg WHERE bg.id = ?),
+ income_accno_id = (SELECT tc.income_accno_id FROM taxzone_charts tc WHERE tc.taxzone_id = 0 and tc.buchungsgruppen_id = ?),
expense_accno_id = $subq_expense,
obsolete = ?,
image = ?,
$form->{lastcost},
$form->{weight},
$form->{unit},
- $form->{notes},
+ $restricter->process($form->{notes}),
$form->{formel},
$form->{rop},
conv_i($form->{warehouse_id}),
);
do_query($form, $dbh, $query, @values);
+ $form->new_lastmtime('parts');
+
# delete translation records
do_query($form, $dbh, qq|DELETE FROM translation WHERE parts_id = ?|, conv_i($form->{id}));
$sth = $dbh->prepare($query);
foreach my $translation (@translations) {
- do_statement($form, $sth, $query, conv_i($form->{id}), conv_i($translation->{language_id}), $translation->{translation}, $translation->{longdescription});
+ do_statement($form, $sth, $query, conv_i($form->{id}), conv_i($translation->{language_id}), $translation->{translation}, $restricter->process($translation->{longdescription}));
}
$sth->finish();
$query = qq|INSERT INTO prices (parts_id, pricegroup_id, price) VALUES(?, ?, ?)|;
$sth = prepare_query($form, $dbh, $query);
- # insert price records only if different to sellprice
for my $i (1 .. $form->{price_rows}) {
my $price = $form->parse_amount($myconfig, $form->{"price_$i"});
- next unless $price && ($price != $form->{sellprice});
+ next unless $price;
@values = (conv_i($form->{id}), conv_i($form->{"pricegroup_id_$i"}), $price);
do_statement($form, $sth, $query, @values);
variables => $form,
save_validity => 1);
- # commit
- my $rc = $dbh->commit;
-
- $main::lxdebug->leave_sub();
-
- return $rc;
-}
-
-sub update_assembly {
- $main::lxdebug->enter_sub();
-
- my ($dbh, $form, $id, $qty, $sellprice, $weight) = @_;
-
- my $query = qq|SELECT id, qty FROM assembly WHERE parts_id = ?|;
- my $sth = prepare_execute_query($form, $dbh, $query, conv_i($id));
-
- while (my ($pid, $aqty) = $sth->fetchrow_array) {
- &update_assembly($dbh, $form, $pid, $aqty * $qty, $sellprice, $weight);
- }
- $sth->finish;
-
- $query =
- qq|UPDATE parts SET sellprice = sellprice + ?, weight = weight + ?
- WHERE id = ?|;
- my @values = ($qty * ($form->{sellprice} - $sellprice),
- $qty * ($form->{weight} - $weight), conv_i($id));
- do_query($form, $dbh, $query, @values);
+ # Delete saved custom variable values for configs that have been
+ # marked invalid for this part.
+ $query = <<SQL;
+ DELETE FROM custom_variables
+ WHERE (config_id IN (
+ SELECT val.config_id
+ FROM custom_variables_validity val
+ LEFT JOIN custom_variable_configs val_cfg ON (val.config_id = val_cfg.id)
+ WHERE (val_cfg.module = 'IC')
+ AND (val.trans_id = ?)))
+ AND (trans_id = ?)
+SQL
+ do_query($form, $dbh, $query, ($form->{id}) x 2);
- $main::lxdebug->leave_sub();
+ return 1;
}
sub retrieve_assemblies {
if ($form->{partnumber}) {
$where .= qq| AND (p.partnumber ILIKE ?)|;
- push(@values, '%' . $form->{partnumber} . '%');
+ push(@values, like($form->{partnumber}));
}
if ($form->{description}) {
$where .= qq| AND (p.description ILIKE ?)|;
- push(@values, '%' . $form->{description} . '%');
+ push(@values, like($form->{description}));
}
# retrieve assembly items
}
sub delete {
+ my ($self, $myconfig, $form) = @_;
$main::lxdebug->enter_sub();
+ my $rc = SL::DB->client->with_transaction(\&_delete, $self, $myconfig, $form);
+
+ $main::lxdebug->leave_sub();
+ return $rc;
+}
+
+sub _delete {
my ($self, $myconfig, $form) = @_;
my @values = (conv_i($form->{id}));
- # connect to database, turn off AutoCommit
- my $dbh = $form->get_standard_dbh;
my %columns = ( "assembly" => "id", "parts" => "id" );
for my $table (qw(prices makemodel inventory assembly translation parts)) {
my $column = defined($columns{$table}) ? $columns{$table} : "parts_id";
- do_query($form, $dbh, qq|DELETE FROM $table WHERE $column = ?|, @values);
+ do_query($form, SL::DB->client->dbh, qq|DELETE FROM $table WHERE $column = ?|, @values);
}
- # commit
- my $rc = $dbh->commit;
-
- $main::lxdebug->leave_sub();
-
- return $rc;
+ return 1;
}
sub assembly_item {
while (my ($column, $table) = each(%columns)) {
next unless ($form->{"${column}_$i"});
$where .= qq| AND ${table}.${column} ILIKE ?|;
- push(@values, '%' . $form->{"${column}_$i"} . '%');
+ push(@values, like($form->{"${column}_$i"}));
}
if ($form->{id}) {
$where .= qq| ORDER BY p.description|;
}
- # connect to database
- my $dbh = $form->get_standard_dbh;
-
my $query =
qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
p.weight, p.onhand, p.unit, pg.partsgroup, p.lastcost,
- p.price_factor_id, pfac.factor AS price_factor
+ p.price_factor_id, pfac.factor AS price_factor, p.notes as longdescription
FROM parts p
LEFT JOIN partsgroup pg ON (p.partsgroup_id = pg.id)
LEFT JOIN price_factors pfac ON pfac.id = p.price_factor_id
WHERE $where|;
- $form->{item_list} = selectall_hashref_query($form, $dbh, $query, @values);
+ $form->{item_list} = selectall_hashref_query($form, SL::DB->client->dbh, $query, @values);
$main::lxdebug->leave_sub();
}
my @apoe_filters = qw(transdate);
my @like_filters = (@simple_filters, @invoice_oi_filters);
my @all_columns = (@simple_filters, @makemodel_filters, @apoe_filters, @project_filters, qw(serialnumber));
- my @simple_l_switches = (@all_columns, qw(notes listprice sellprice lastcost priceupdate weight unit rop image));
+ my @simple_l_switches = (@all_columns, qw(notes listprice sellprice lastcost priceupdate weight unit rop image shop insertdate));
my @oe_flags = qw(bought sold onorder ordered rfq quoted);
my @qsooqr_flags = qw(invnumber ordnumber quonumber trans_id name module qty);
my @deliverydate_flags = qw(deliverydate);
'ioi.id' => 'ioi_id',
'ioi.ioi' => 'ioi',
'projectdescription' => 'projectdescription',
+ 'insertdate' => 'insertdate',
);
my %real_column = (
projectdescription => 'description',
+ insertdate => 'itime::DATE',
);
if (($form->{searchitems} eq 'assembly') && $form->{l_lastcost}) {
#===== switches and simple filters ========#
# special case transdate
- if (grep { $form->{$_} } qw(transdatefrom transdateto)) {
+ if (grep { trim($form->{$_}) } qw(transdatefrom transdateto)) {
$form->{"l_transdate"} = 1;
push @select_tokens, 'transdate';
for (qw(transdatefrom transdateto)) {
- next unless $form->{$_};
+ my $value = trim($form->{$_});
+ next unless $value;
push @where_tokens, sprintf "transdate %s ?", /from$/ ? '>=' : '<=';
- push @bind_vars, $form->{$_};
+ push @bind_vars, $value;
+ }
+ }
+
+ # special case smart search
+ if ($form->{all}) {
+ $form->{"l_$_"} = 1 for qw(partnumber description unit sellprice lastcost cvar_packaging linetotal);
+ push @where_tokens, "p.partnumber ILIKE ? OR p.description ILIKE ?";
+ push @bind_vars, (like($form->{all})) x 2;
+ }
+
+ # special case insertdate
+ if (grep { trim($form->{$_}) } qw(insertdatefrom insertdateto)) {
+ $form->{"l_insertdate"} = 1;
+ push @select_tokens, 'insertdate';
+
+ my $token_builder = $make_token_builder->();
+ my $token = $token_builder->('insertdate');
+
+ for (qw(insertdatefrom insertdateto)) {
+ my $value = trim($form->{$_});
+ next unless $value;
+ push @where_tokens, sprintf "$token %s ?", /from$/ ? '>=' : '<=';
+ push @bind_vars, $value;
}
}
push @bind_vars, $form->{"partsgroup_id"};
}
+ if ($form->{shop} ne '') {
+ $form->{l_shop} = '1'; # show the column
+ if ($form->{shop} eq '0' || $form->{shop} eq 'f') {
+ push @where_tokens, 'NOT p.shop';
+ $form->{shop} = 'f';
+ } else {
+ push @where_tokens, 'p.shop';
+ }
+ }
+
foreach (@like_filters) {
next unless $form->{$_};
$form->{"l_$_"} = '1'; # show the column
push @where_tokens, "$table_prefix{$_}$_ ILIKE ?";
- push @bind_vars, "%$form->{$_}%";
+ push @bind_vars, like($form->{$_});
}
foreach (@simple_l_switches) {
# fortunately makemodel doesn't need to be displayed later, so adding a special clause to where_token is sufficient.
if ($form->{make}) {
push @where_tokens, 'mv.name ILIKE ?';
- push @bind_vars, "%$form->{make}%";
+ push @bind_vars, like($form->{make});
}
if ($form->{model}) {
push @where_tokens, 'mm.model ILIKE ?';
- push @bind_vars, "%$form->{model}%";
+ push @bind_vars, like($form->{model});
}
# special case: sorting by partnumber
my $token_builder = $make_token_builder->(\%joins_needed);
- my @sort_cols = (@simple_filters, qw(id priceupdate onhand invnumber ordnumber quonumber name serialnumber soldtotal deliverydate));
+ my @sort_cols = (@simple_filters, qw(id priceupdate onhand invnumber ordnumber quonumber name serialnumber soldtotal deliverydate insertdate shop));
$form->{sort} = 'id' unless grep { $form->{"l_$_"} } grep { $form->{sort} eq $_ } @sort_cols; # sort by id if unknown or invisible column
my $sort_order = ($form->{revers} ? ' DESC' : ' ASC');
my $order_clause = " ORDER BY " . $token_builder->($form->{sort}) . ($form->{revers} ? ' DESC' : ' ASC');
if ($form->{searchitems} eq 'assembly' && $form->{bom}) {
$query =
qq|SELECT p.id, p.partnumber, p.description, a.qty AS onhand,
- p.unit, p.notes,
+ p.unit, p.notes, p.itime::DATE as insertdate,
p.sellprice, p.listprice, p.lastcost,
p.rop, p.weight, p.priceupdate,
p.image, p.drawing, p.microfiche,
$main::lxdebug->leave_sub();
- return wantarray ? @{ $form->{parts} } : $form->{parts};
+ return @{ $form->{parts} };
}
sub _create_filter_for_priceupdate {
next unless ($form->{$column});
$where .= qq| AND $item ILIKE ?|;
- push(@where_values, '%' . $form->{$column} . '%');
+ push(@where_values, like($form->{$column}));
}
foreach my $item (qw(description serialnumber)) {
next unless ($form->{$item});
$where .= qq| AND (${item} ILIKE ?)|;
- push(@where_values, '%' . $form->{$item} . '%');
+ push(@where_values, like($form->{$item}));
}
foreach my $column (qw(make model)) {
next unless ($form->{$column});
$where .= qq| AND p.id IN (SELECT DISTINCT parts_id FROM makemodel WHERE $column ILIKE ?|;
- push(@where_values, '%' . $form->{$column} . '%');
+ push(@where_values, like($form->{$column}));
}
$main::lxdebug->leave_sub();
}
sub update_prices {
+ my ($self, $myconfig, $form) = @_;
$main::lxdebug->enter_sub();
+ my $num_updated = SL::DB->client->with_transaction(\&_update_prices, $self, $myconfig, $form);
+
+ $main::lxdebug->leave_sub();
+ return $num_updated;
+}
+
+sub _update_prices {
my ($self, $myconfig, $form) = @_;
my ($where, @where_values) = $self->_create_filter_for_priceupdate();
my $num_updated = 0;
# connect to database
- my $dbh = $form->get_standard_dbh;
+ my $dbh = SL::DB->client->dbh;
for my $column (qw(sellprice listprice)) {
next if ($form->{$column} eq "");
$sth_add->finish();
$sth_multiply->finish();
- my $rc= $dbh->commit;
-
- $main::lxdebug->leave_sub();
-
return $num_updated;
}
# connect to database
my $dbh = $form->get_standard_dbh;
- my @values = ('%' . $module . '%');
+ my @values = like($module);
my $query;
if ($form->{id}) {
if ($sortorder eq "all") {
$where .= qq| AND (partnumber ILIKE ?) AND (description ILIKE ?)|;
- push(@values, '%' . $form->{partnumber} . '%', '%' . $form->{description} . '%');
+ push(@values, like($form->{partnumber}), like($form->{description}));
} elsif ($sortorder eq "partnumber") {
$where .= qq| AND (partnumber ILIKE ?)|;
- push(@values, '%' . $form->{partnumber} . '%');
+ push(@values, like($form->{partnumber}));
} elsif ($sortorder eq "description") {
$where .= qq| AND (description ILIKE ?)|;
- push(@values, '%' . $form->{description} . '%');
+ push(@values, like($form->{description}));
$order = "description";
}
SELECT
p.id, p.inventory_accno_id AS is_part,
bg.inventory_accno_id,
- bg.income_accno_id_$form->{taxzone_id} AS income_accno_id,
- bg.expense_accno_id_$form->{taxzone_id} AS expense_accno_id,
+ tc.income_accno_id AS income_accno_id,
+ tc.expense_accno_id AS expense_accno_id,
c1.accno AS inventory_accno,
c2.accno AS income_accno,
c3.accno AS expense_accno
FROM parts p
LEFT JOIN buchungsgruppen bg ON p.buchungsgruppen_id = bg.id
+ LEFT JOIN taxzone_charts tc on bg.id = tc.buchungsgruppen_id
LEFT JOIN chart c1 ON bg.inventory_accno_id = c1.id
- LEFT JOIN chart c2 ON bg.income_accno_id_$form->{taxzone_id} = c2.id
- LEFT JOIN chart c3 ON bg.expense_accno_id_$form->{taxzone_id} = c3.id
- WHERE p.id IN ($in)
+ LEFT JOIN chart c2 ON tc.income_accno_id = c2.id
+ LEFT JOIN chart c3 ON tc.expense_accno_id = c3.id
+ WHERE
+ tc.taxzone_id = '$form->{taxzone_id}'
+ and
+ p.id IN ($in)
SQL
my $sth_tax = prepare_query($::form, $dbh, <<SQL);
$sth->finish();
- my @columns = qw(ean image microfiche drawing weight);
+ my @columns = qw(ean image microfiche drawing);
$query = qq|SELECT id, | . join(', ', @columns) . qq|
FROM parts
my %data = selectall_as_map($form, $dbh, $query, 'id', \@columns, @part_ids);
- map { $form->{TEMPLATE_ARRAYS}{$_} = [] } (qw(make model), @columns);
+ my %template_arrays;
+ map { $template_arrays{$_} = [] } (qw(make model), @columns);
foreach my $i (1 .. $rowcount) {
my $id = $form->{"${prefix}${i}"};
next if (!$id);
foreach (@columns) {
- push @{ $form->{TEMPLATE_ARRAYS}{$_} }, $data{$id}->{$_};
+ push @{ $template_arrays{$_} }, $data{$id}->{$_};
}
- push @{ $form->{TEMPLATE_ARRAYS}{make} }, [];
- push @{ $form->{TEMPLATE_ARRAYS}{model} }, [];
+ push @{ $template_arrays{make} }, [];
+ push @{ $template_arrays{model} }, [];
next if (!$makemodel{$id});
foreach my $ref (@{ $makemodel{$id} }) {
- map { push @{ $form->{TEMPLATE_ARRAYS}{$_}->[-1] }, $ref->{$_} } qw(make model);
+ map { push @{ $template_arrays{$_}->[-1] }, $ref->{$_} } qw(make model);
}
}
+ my $parts = SL::DB::Manager::Part->get_all(query => [ id => \@part_ids ]);
+ my %parts_by_id = map { $_->id => $_ } @$parts;
+
+ for my $i (1..$rowcount) {
+ my $id = $form->{"${prefix}${i}"};
+ next unless $id;
+
+ push @{ $template_arrays{part_type} }, $parts_by_id{$id}->type;
+ }
+
+ return %template_arrays;
$main::lxdebug->leave_sub();
}