From: G. Richardson Date: Thu, 8 Nov 2012 10:34:18 +0000 (+0100) Subject: Merge branch 'master' of vc.linet-services.de:public/lx-office-erp X-Git-Tag: release-3.0.0beta1~25^2~2^2 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/4780fc8426841be0838551dea12d8329f32ef65e?hp=a1a1263bff85923b68be47848cd9441dfdba7fb1 Merge branch 'master' of vc.linet-services.de:public/lx-office-erp --- diff --git a/.gitignore b/.gitignore index 6c00133f2..bc497aea1 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ crm /doc/online/*/*.html pod2html* /doc/build/dobudish* +/spool/* diff --git a/SL/CT.pm b/SL/CT.pm index de10623f2..93c3fcea2 100644 --- a/SL/CT.pm +++ b/SL/CT.pm @@ -598,6 +598,7 @@ sub search { my $dbh = $form->dbconnect($myconfig); my $cv = $form->{db} eq "customer" ? "customer" : "vendor"; + my $join_records = $form->{l_invnumber} || $form->{l_ordnumber} || $form->{l_quonumber}; my $where = "1 = 1"; my @values; @@ -611,7 +612,7 @@ sub search { $form->{sort} = $sortorder; my $sortdir = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC'; - if ($sortorder !~ /(business|id)/ && 1 >= scalar grep { $form->{$_} } qw(l_ordnumber l_quonumber l_invnumber )) { + if ($sortorder !~ /(business|id)/ && !$join_records) { $sortorder = "lower($sortorder) ${sortdir}"; } else { $sortorder .= " ${sortdir}"; @@ -705,21 +706,22 @@ sub search { my $query = qq|SELECT ct.*, b.description AS business | . + (qq|, NULL AS invnumber, NULL AS ordnumber, NULL AS quonumber, NULL AS invid, NULL AS module, NULL AS formtype, NULL AS closed | x!! $join_records) . qq|FROM $cv ct | . qq|LEFT JOIN business b ON (ct.business_id = b.id) | . qq|WHERE $where|; my @saved_values = @values; # redo for invoices, orders and quotations - if ($form->{l_invnumber} || $form->{l_ordnumber} || $form->{l_quonumber}) { - my ($ar, $union, $module); - $query = ""; + if ($join_records) { + my $union = "UNION"; if ($form->{l_invnumber}) { my $ar = $cv eq 'customer' ? 'ar' : 'ap'; my $module = $ar eq 'ar' ? 'is' : 'ir'; - - $query = + push(@values, @saved_values); + $query .= + qq| UNION | . qq|SELECT ct.*, b.description AS business, | . qq| a.invnumber, a.ordnumber, a.quonumber, a.id AS invid, | . qq| '$module' AS module, 'invoice' AS formtype, | . @@ -728,16 +730,12 @@ sub search { qq|JOIN $ar a ON (a.${cv}_id = ct.id) | . qq|LEFT JOIN business b ON (ct.business_id = b.id) | . qq|WHERE $where AND (a.invoice = '1')|; - - $union = qq|UNION|; } if ( $form->{l_ordnumber} ) { - if ($union eq "UNION") { - push(@values, @saved_values); - } + push(@values, @saved_values); $query .= - qq| $union | . + qq| UNION | . qq|SELECT ct.*, b.description AS business,| . qq| ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | . qq| 'oe' AS module, 'order' AS formtype, o.closed | . @@ -745,16 +743,12 @@ sub search { qq|JOIN oe o ON (o.${cv}_id = ct.id) | . qq|LEFT JOIN business b ON (ct.business_id = b.id) | . qq|WHERE $where AND (o.quotation = '0')|; - - $union = qq|UNION|; } if ( $form->{l_quonumber} ) { - if ($union eq "UNION") { - push(@values, @saved_values); - } + push(@values, @saved_values); $query .= - qq| $union | . + qq| UNION | . qq|SELECT ct.*, b.description AS business, | . qq| ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | . qq| 'oe' AS module, 'quotation' AS formtype, o.closed | . diff --git a/SL/Controller/CsvImport/Base.pm b/SL/Controller/CsvImport/Base.pm index f84d54b0e..656495e37 100644 --- a/SL/Controller/CsvImport/Base.pm +++ b/SL/Controller/CsvImport/Base.pm @@ -29,6 +29,7 @@ sub run { profile => $profile, ignore_unknown_columns => 1, strict_profile => 1, + case_insensitive_header => 1, map { ( $_ => $self->controller->profile->get($_) ) } qw(sep_char escape_char quote_char), )); @@ -212,6 +213,12 @@ sub init_profile { $profile{$col} = $name; } + if ($self->can('all_cvar_configs')) { + for (@{ $self->all_cvar_configs }) { + $profile{ 'cvar_' . $_->name } = ''; + } + } + $self->profile(\%profile); } diff --git a/SL/DBUpgrade2.pm b/SL/DBUpgrade2.pm index a39ef931b..a84f6b138 100644 --- a/SL/DBUpgrade2.pm +++ b/SL/DBUpgrade2.pm @@ -25,12 +25,17 @@ sub init { $params{path_suffix} ||= ''; $params{schema} ||= ''; + $params{path} = "sql/" . $params{dbdriver} . "-upgrade2" . $params{path_suffix}; map { $self->{$_} = $params{$_} } keys %params; return $self; } +sub path { + $_[0]{path}; +} + sub parse_dbupdate_controls { $::lxdebug->enter_sub(); @@ -42,7 +47,7 @@ sub parse_dbupdate_controls { local *IN; my %all_controls; - my $path = "sql/" . $self->{dbdriver} . "-upgrade2" . $self->{path_suffix}; + my $path = $self->path; foreach my $file_name (<$path/*.sql>, <$path/*.pl>) { next unless (open(IN, $file_name)); diff --git a/SL/Helper/Csv.pm b/SL/Helper/Csv.pm index 5b629ee63..e48161492 100644 --- a/SL/Helper/Csv.pm +++ b/SL/Helper/Csv.pm @@ -10,7 +10,7 @@ use Text::CSV_XS; use Rose::Object::MakeMethods::Generic scalar => [ qw( file encoding sep_char quote_char escape_char header profile class numberformat dateformat ignore_unknown_columns strict_profile _io _csv - _objects _parsed _data _errors + _objects _parsed _data _errors all_cvar_configs case_insensitive_header ) ]; use SL::Helper::Csv::Dispatcher; @@ -33,6 +33,7 @@ sub new { dateformat => 0, ignore_unknown_columns => 0, strict_profile => 0, + case_insensitive_header => 0, }); my $self = bless {}, $class; @@ -120,7 +121,25 @@ sub _check_header { } return unless $header; - return $self->header([ map { lc } @$header ]); + + # Special case: human stupidity + # people insist that case sensitivity doesn't exist and try to enter all + # sorts of stuff. at this point we've got a profile (with keys that represent + # valid methods), and a header full of strings. if two of them match, the user + # mopst likely meant that field, so rewrite the header + if ($self->case_insensitive_header) { + die 'case_insensitive_header is only possible with profile' unless $self->profile; + my @names = ( + keys %{ $self->profile || {} }, + ); + for my $name (@names) { + for my $i (0..$#$header) { + $header->[$i] = $name if lc $header->[$i] eq lc $name; + } + } + } + + return $self->header($header); } sub _parse_data { @@ -345,6 +364,12 @@ these information are unique, and should be connected to preexisting data, you will have to do that for yourself. Since you provided the profile, it is assumed you know what to do in this case. +If no profile is given, any header field found will be taken as is. + +If the path in a profile entry is empty, the field will be subjected to +C and C checking, will be parsed into +C, but will not be attempted to be dispatched into objects. + =item C If present, the line will be handed to the new sub of this class, @@ -355,11 +380,24 @@ and the return value used instead of the line itself. If set, the import will ignore unkown header columns. Useful for lazy imports, but deactivated by default. +=item C + +If set, header columns will be matched against profile entries case +insensitive, and on match the profile name will be taken. + +Only works if a profile is given, will die otherwise. + +If both C and C is set, matched header +columns will be accepted. + =item C If set, all columns to be parsed must be specified in C. Every header field not listed there will be treated like an unknown column. +If both C and C is set, matched header +columns will be accepted. + =back =head1 ERROR HANDLING diff --git a/SL/Helper/Csv/Dispatcher.pm b/SL/Helper/Csv/Dispatcher.pm index be3faddd6..add444b9d 100644 --- a/SL/Helper/Csv/Dispatcher.pm +++ b/SL/Helper/Csv/Dispatcher.pm @@ -78,7 +78,11 @@ sub parse_profile { $self->unknown_column($col, undef); } } else { - push @specs, $self->make_spec($col, $profile->{$col} || $col); + if (exists $profile->{$col}) { + push @specs, $self->make_spec($col, $profile->{$col}); + } else { + push @specs, $self->make_spec($col, $col); + } } } @@ -91,6 +95,9 @@ sub make_spec { my ($self, $col, $path) = @_; my $spec = { key => $col, steps => [] }; + + return unless $path; + my $cur_class = $self->_csv->class; return unless $cur_class; diff --git a/SL/IS.pm b/SL/IS.pm index db18d5a43..616e2bf6f 100644 --- a/SL/IS.pm +++ b/SL/IS.pm @@ -2028,7 +2028,7 @@ sub get_pricegroups_for_parts { my $pricegroup_old = $form->{"pricegroup_old_$i"}; - # sellprice has format 13,0000 or 0,00000, can't check for 0 numerically + # sellprice has format 13,0000 or 0,00000, can't check for 0 numerically my $sellprice = $form->{"sellprice_$i"}; my $pricegroup_id = $form->{"pricegroup_id_$i"}; $form->{"new_pricegroup_$i"} = $selectedpricegroup_id; @@ -2130,14 +2130,12 @@ sub get_pricegroups_for_parts { $pkr->{selected} = ' selected'; # unless $form->{selected}; # no customer pricesgroup set - if ($pkr->{price_unfmt} == $pkr->{default_sellprice}) { + if ($pkr->{price_unfmt} == $pkr->{default_sellprice} || $form->{'sellprice_'.$i} * 1 > 1) { $pkr->{price} = $form->{"sellprice_$i"}; } else { -# this sub should not set anything and only return. --sschoeling, 20090506 -# is this correct? put in again... -- grichardson 20110119 $form->{"sellprice_$i"} = $pkr->{price}; } diff --git a/SL/Menu.pm b/SL/Menu.pm index 48ac6229d..57d8b4e8a 100644 --- a/SL/Menu.pm +++ b/SL/Menu.pm @@ -59,7 +59,7 @@ sub new { } sub menuitem_new { - $main::lxdebug->enter_sub(); + $main::lxdebug->enter_sub(LXDebug::DEBUG2()); my ($self, $name, $item) = @_; @@ -84,7 +84,7 @@ sub menuitem_new { $item->{href} .= "&" . $form->escape($key) . "=" . $form->escape($value); } - $main::lxdebug->leave_sub(); + $main::lxdebug->leave_sub(LXDebug::DEBUG2()); } sub access_control { diff --git a/SL/Template/OpenDocument.pm b/SL/Template/OpenDocument.pm index 12a7bc8c5..b4ea1f2a5 100644 --- a/SL/Template/OpenDocument.pm +++ b/SL/Template/OpenDocument.pm @@ -270,14 +270,14 @@ sub parse { $zip->contents("content.xml", Encode::encode('utf-8-strict', $new_contents)); - my $styles = $zip->contents("styles.xml"); + my $styles = Encode::decode('utf-8-strict', $zip->contents("styles.xml")); if ($contents) { my $new_styles = $self->parse_block($styles); if (!defined($new_contents)) { $main::lxdebug->leave_sub(); return 0; } - $zip->contents("styles.xml", $new_styles); + $zip->contents("styles.xml", Encode::encode('utf-8-strict', $new_styles)); } $zip->writeToFileNamed($form->{"tmpfile"}, 1); diff --git a/bin/mozilla/am.pl b/bin/mozilla/am.pl index c114c7eae..500547597 100644 --- a/bin/mozilla/am.pl +++ b/bin/mozilla/am.pl @@ -426,10 +426,6 @@ sub save_as_new_account { } $form->{id} = 0; - if ($form->{"original_accno"} && - ($form->{"accno"} eq $form->{"original_accno"})) { - $form->error($locale->text('Account Number already used!')); - } $form->redirect($locale->text('Account saved!')) if (AM->save_account(\%myconfig, \%$form)); $form->error($locale->text('Cannot save account!')); diff --git a/bin/mozilla/arap.pl b/bin/mozilla/arap.pl index 27b0e3bfa..fe5fa2d27 100644 --- a/bin/mozilla/arap.pl +++ b/bin/mozilla/arap.pl @@ -78,6 +78,7 @@ sub check_name { $form->{"${name}_id"} = $new_id; + _reset_salesman_id(); IS->get_customer(\%myconfig, \%$form) if ($name eq 'customer'); IR->get_vendor(\%myconfig, \%$form) if ($name eq 'vendor'); @@ -119,6 +120,7 @@ sub check_name { $form->{$name} = $form->{name_list}[0]->{name}; $form->{"old$name"} = qq|$form->{$name}--$form->{"${name}_id"}|; + _reset_salesman_id(); IS->get_customer(\%myconfig, \%$form) if ($name eq 'customer'); IR->get_vendor(\%myconfig, \%$form) if ($name eq 'vendor'); @@ -266,6 +268,8 @@ sub name_selected { # index for new item my $i = $form->{ndx}; + _reset_salesman_id(); + $form->{ $form->{vc} } = $form->{"new_name_$i"}; $form->{"$form->{vc}_id"} = $form->{"new_id_$i"}; $form->{"old$form->{vc}"} = @@ -286,6 +290,14 @@ sub name_selected { $main::lxdebug->leave_sub(); } +# Reset the $::form field 'salesman_id' to the ID of the currently +# logged in user. Useful when changing to a customer/vendor that has +# no salesman listed in their master data. +sub _reset_salesman_id { + my $current_employee = SL::DB::Manager::Employee->current; + $::form->{salesman_id} = $current_employee->id if $current_employee && exists $::form->{salesman_id}; +} + sub check_project { $main::lxdebug->enter_sub(); diff --git a/bin/mozilla/ic.pl b/bin/mozilla/ic.pl index 20c670ca3..b86623b51 100644 --- a/bin/mozilla/ic.pl +++ b/bin/mozilla/ic.pl @@ -38,6 +38,7 @@ use List::MoreUtils qw(any); use SL::AM; use SL::CVar; use SL::IC; +use SL::Helper::Flash; use SL::ReportGenerator; #use SL::PE; @@ -1585,6 +1586,10 @@ sub form_header { IC->retrieve_buchungsgruppen(\%myconfig, $form); @{ $form->{BUCHUNGSGRUPPEN} } = grep { $_->{id} eq $form->{buchungsgruppen_id} || ($form->{id} && $form->{orphaned}) || !$form->{id} } @{ $form->{BUCHUNGSGRUPPEN} }; + if (!SL::TransNumber->new(number => $form->{partnumber}, type => $form->{item}, id => $form->{id})->is_unique) { + flash('info', $::locale->text('This partnumber is not unique. You should change it.')); + } + # use JavaScript Calendar or not (yes!) $form->{jsscript} = 1; diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl index b518db00e..37df55461 100644 --- a/bin/mozilla/io.pl +++ b/bin/mozilla/io.pl @@ -49,6 +49,7 @@ use SL::IO; use SL::DB::Language; use SL::DB::Printer; +use SL::Helper::Flash; require "bin/mozilla/common.pl"; @@ -802,6 +803,7 @@ sub validate_items { # check if items are valid if ($form->{rowcount} == 1) { + flash('warning', $::locale->text('The action you\'ve chosen has not been executed because the document does not contain any item yet.')); &update; ::end_of_request(); } @@ -1536,23 +1538,27 @@ sub print_form { my $emailed = $form->{emailed}; if ($form->{media} eq 'queue') { - my %queued = map { s|.*/|| } split / /, $form->{queued}; + my %queued = map { s|.*[/\\]||; $_ } split / /, $form->{queued}; my $filename; my $suffix = ($form->{postscript}) ? '.ps' : '.pdf'; if ($filename = $queued{ $form->{formname} }) { - $form->{queued} =~ s/\Q$form->{formname} $filename\E//; unlink $::lx_office_conf{paths}->{spool} . "/$filename"; - $filename =~ s/\..*$//g; - $filename .= $suffix; - $form->{OUT} = $::lx_office_conf{paths}->{spool} . "/$filename"; - $form->{OUT_MODE} = '>'; + delete $queued{ $form->{formname} }; + + $form->{queued} = join ' ', %queued; + $filename =~ s/\..*$//g; + $filename .= $suffix; + $form->{OUT} = $::lx_office_conf{paths}->{spool} . "/$filename"; + $form->{OUT_MODE} = '>'; + } else { my $temp_fh; ($temp_fh, $filename) = File::Temp::tempfile( 'kivitendo-spoolXXXXXX', SUFFIX => "$suffix", - DIR => $::lx_office_conf{paths}->{spool}, + DIR => $::lx_office_conf{paths}->{spool}, + UNLINK => 0, ); close $temp_fh; $form->{OUT} = "$filename"; diff --git a/bin/mozilla/wh.pl b/bin/mozilla/wh.pl index 0315bb9dc..92cfcb69b 100644 --- a/bin/mozilla/wh.pl +++ b/bin/mozilla/wh.pl @@ -44,6 +44,8 @@ use SL::WH; use SL::OE; use SL::ReportGenerator; +use SL::DB::Part; + use Data::Dumper; require "bin/mozilla/common.pl"; @@ -85,8 +87,16 @@ sub transfer_warehouse_selection { show_no_warehouses_error() if (!scalar @{ $form->{WAREHOUSES} }); my $units = AM->retrieve_units(\%myconfig, $form); + + my $part = 0; + if ( $form->{parts_id} ) { + $part = SL::DB::Part->new(); + $part->id($form->{parts_id}); + $part->load(); + } + # der zweite Parameter von unit_select_data gibt den default-Namen (selected) vor - $form->{UNITS} = AM->unit_select_data($units, $form->{unit}, 0, $form->{unit}); + $form->{UNITS} = AM->unit_select_data($units, $form->{unit}, 0, $part ? $part->unit : 0); if (scalar @{ $form->{WAREHOUSES} }) { $form->{warehouse_id} ||= $form->{WAREHOUSES}->[0]->{id}; diff --git a/locale/de/all b/locale/de/all index f118a533f..b378b34ee 100644 --- a/locale/de/all +++ b/locale/de/all @@ -87,7 +87,6 @@ $self->{texts} = { 'Account Link IC_taxpart' => 'Warenliste Steuer', 'Account Link IC_taxservice' => 'Dienstleistungen Steuer', 'Account Number' => 'Kontonummer', - 'Account Number already used!' => 'Kontonummer ist bereits in Benutzung!', 'Account Number missing!' => 'Kontonummer fehlt!', 'Account Nummer' => 'Kontonummer', 'Account Type' => 'Kontoart', @@ -1041,6 +1040,7 @@ $self->{texts} = { 'Invoice total less discount' => 'Rechnungssumme abzüglich Skonto', 'Invoice with Storno (abbreviation)' => 'R(S)', 'Invoices' => 'Rechnungen', + 'Invoices, Credit Notes & AR Transactions' => 'Rechnungen, Gutschriften & Debitorenbuchungen', 'Is Searchable' => 'Durchsuchbar', 'Is this a summary account to record' => 'Sammelkonto für', 'It is possible that even after such a correction there is something wrong with this transaction (e.g. taxes that don\'t match the selected taxkey). Therefore you should re-run the general ledger analysis.' => 'Auch nach einer Korrektur kann es mit dieser Buchung noch weitere Probleme geben (z.B. nicht zum Steuerschlüssel passende Steuern), weshalb ein erneutes Ausführen der Hauptbuchanalyse empfohlen wird.', @@ -1874,6 +1874,7 @@ $self->{texts} = { 'The access rights have been saved.' => 'Die Zugriffsrechte wurden gespeichert.', 'The account 3804 already exists, the update will be skipped.' => 'Das Konto 3804 existiert schon, das Update wird übersprungen.', 'The account 3804 will not be added automatically.' => 'Das Konto 3804 wird nicht automatisch hinzugefügt.', + 'The action you\'ve chosen has not been executed because the document does not contain any item yet.' => 'Die von Ihnen ausgewählte Aktion wurde nicht ausgeführt, weil der Beleg noch keine Positionen enthält.', 'The application "#1" was not found on the system.' => 'Die Anwendung "#1" wurde auf dem System nicht gefunden.', 'The assembly has been created.' => 'Das Erzeugnis wurde hergestellt.', 'The assistant could not find anything wrong with #1. Maybe the problem has been solved in the meantime.' => 'Der Korrekturassistent konnte kein Problem bei #1 feststellen. Eventuell wurde das Problem in der Zwischenzeit bereits behoben.', @@ -2057,6 +2058,7 @@ $self->{texts} = { 'This option controls the inventory system.' => 'Dieser Parameter legt die Warenbuchungsmethode fest.', 'This option controls the method used for profit determination.' => 'Dieser Parameter legt die Berechnungsmethode für die Gewinnermittlung fest.', 'This option controls the posting and calculation behavior for the accounting method.' => 'Dieser Parameter steuert die Buchungs- und Berechnungsmethoden für die Versteuerungsart.', + 'This partnumber is not unique. You should change it.' => 'Diese Artikelnummer ist nicht eindeutig. Bitte wählen Sie eine andere.', 'This transaction has to be split into several transactions manually.' => 'Diese Buchung muss manuell in mehrere Buchungen aufgeteilt werden.', 'This update will change the nature the onhand of goods is tracked.' => 'Dieses update ändert die Art und Weise wie Lagermengen gezält werden.', 'This upgrade script tries to map all existing parts in the database to the newly created Buchungsgruppen.' => 'Dieses Upgradescript versucht, bei allen bestehenden Artikeln neu erstellte Buchungsgruppen zuzuordnen.', @@ -2174,7 +2176,7 @@ $self->{texts} = { 'Vendor' => 'Lieferant', 'Vendor (name)' => 'Lieferant (Name)', 'Vendor Invoice' => 'Einkaufsrechnung', - 'Vendor Invoices' => 'Einkaufsrechnungen', + 'Vendor Invoices & AP Transactions' => 'Einkaufsrechnungen & Kreditorenbuchungen', 'Vendor Name' => 'Lieferantenname', 'Vendor Number' => 'Lieferantennummer', 'Vendor Order Number' => 'Bestellnummer beim Lieferanten', diff --git a/locale/de_DE/all b/locale/de_DE/all index 7eb8d8d83..52d3ec595 100644 --- a/locale/de_DE/all +++ b/locale/de_DE/all @@ -2139,7 +2139,7 @@ $self->{texts} = { 'Weight unit' => 'Gewichtseinheit', 'What term you are looking for?' => 'Nach welchem Begriff wollen Sie suchen?', 'What type of item is this?' => 'Was ist dieser Artikel?', - 'Which is located at doc/Lx-Office-Dokumentation.pdf. Click here: ' => 'Zu finden in doc/Lx-Office-Dokumentation.pdf. Oder hier klicken: ', + 'Which is located at doc/kivitendo-Dokumentation.pdf. Click here: ' => 'Zu finden in doc/kivitendo-Dokumentation.pdf. Oder hier klicken: ', 'With Extension Of Time' => 'mit Dauerfristverlängerung', 'Workflow Delivery Order' => 'Workflow Lieferschein', 'Workflow purchase_order' => 'Workflow Lieferantenauftrag', diff --git a/menu.ini b/menu.ini index cb0700309..fa99ded7a 100644 --- a/menu.ini +++ b/menu.ini @@ -149,7 +149,7 @@ module=do.pl action=search type=sales_delivery_order -[AR--Reports--Invoices] +[AR--Reports--Invoices, Credit Notes & AR Transactions] ACCESS=invoice_edit module=ar.pl action=search @@ -222,7 +222,7 @@ module=do.pl action=search type=purchase_delivery_order -[AP--Reports--Vendor Invoices] +[AP--Reports--Vendor Invoices & AP Transactions] ACCESS=vendor_invoice_edit module=ap.pl action=search diff --git a/scripts/dbupgrade2_tool.pl b/scripts/dbupgrade2_tool.pl index 253706c93..f4a7bb7e7 100755 --- a/scripts/dbupgrade2_tool.pl +++ b/scripts/dbupgrade2_tool.pl @@ -43,7 +43,8 @@ use SL::Dispatcher; my ($opt_list, $opt_tree, $opt_rtree, $opt_nodeps, $opt_graphviz, $opt_help); my ($opt_user, $opt_apply, $opt_applied, $opt_unapplied, $opt_format, $opt_test_utf8); -my ($opt_dbhost, $opt_dbport, $opt_dbname, $opt_dbuser, $opt_dbpassword); +my ($opt_dbhost, $opt_dbport, $opt_dbname, $opt_dbuser, $opt_dbpassword, $opt_create, $opt_type); +my ($opt_description, $opt_encoding, @opt_depends); our (%myconfig, $form, $user, $auth, $locale, $controls, $dbupgrader); @@ -231,6 +232,48 @@ sub dump_nodeps { "\n\n"; } +sub create_upgrade { + my (%params) = @_; + + my $filename = $params{filename}; + my $dbupgrader = $params{dbupgrader}; + my $type = $params{type} || ''; + my $description = $params{description} || ''; + my $encoding = $params{encoding} || 'utf-8'; + my @depends = @{ $params{depends} }; + + if (!@depends) { + my @releases = grep { /^release_/ } keys %$controls; + @depends = ((sort @releases)[-1]); + } + + my $comment; + if ($type eq 'sql') { + $comment = '--'; + } elsif ($type eq 'pl') { + $comment = '#'; + } elsif (!$type) { + die 'Error: No --type was given but is required for --create.'; + } else { + die 'Error: Unknown --type. Try "sql" or "pl".'; + } + + my $full_filename = $dbupgrader->path . '/' . $filename . '.' . $type; + + die "file '$full_filename' already exists, aborting" if -f $full_filename; + + + open my $fh, ">:utf8", $full_filename or die "can't open $full_filename"; + print $fh "$comment \@tag: $filename\n"; + print $fh "$comment \@description: $description\n"; + print $fh "$comment \@depends: @depends\n"; + print $fh "$comment \@encoding: $encoding\n"; + close $fh; + + system("\$EDITOR $full_filename"); + exit 0; +} + sub apply_upgrade { my $name = shift; @@ -399,6 +442,11 @@ GetOptions("list" => \$opt_list, "user=s" => \$opt_user, "apply=s" => \$opt_apply, "applied" => \$opt_applied, + "create=s" => \$opt_create, + "type=s" => \$opt_type, + "encoding=s" => \$opt_encoding, + "description=s" => \$opt_description, + "depends=s" => \@opt_depends, "unapplied" => \$opt_unapplied, "test-utf8" => \$opt_test_utf8, "dbhost:s" => \$opt_dbhost, @@ -420,6 +468,12 @@ dump_tree_reverse() if ($opt_rtree); dump_graphviz('file_name' => $opt_graphviz, 'format' => $opt_format) if (defined $opt_graphviz); dump_nodeps() if ($opt_nodeps); +create_upgrade(filename => $opt_create, + dbupgrader => $dbupgrader, + type => $opt_type, + description => $opt_description, + encoding => $opt_encoding, + depends => \@opt_depends) if ($opt_create); if ($opt_user) { $auth = SL::Auth->new(); @@ -456,6 +510,7 @@ if ($opt_unapplied) { dump_unapplied(); } + if ($opt_test_utf8) { $form->error("--test-utf8 used but no database name given with --dbname.") if (!$opt_dbname); diff --git a/t/helper/csv.t b/t/helper/csv.t index 63fc858c9..302383371 100644 --- a/t/helper/csv.t +++ b/t/helper/csv.t @@ -1,11 +1,11 @@ -use Test::More tests => 41; +use Test::More tests => 47; use lib 't'; +use utf8; use Data::Dumper; -use utf8; +use Support::TestSetup; -use_ok 'Support::TestSetup'; use_ok 'SL::Helper::Csv'; Support::TestSetup::login(); @@ -278,6 +278,8 @@ is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'eol bug at the end o $csv = SL::Helper::Csv->new( file => \"Description\nKaffee", class => 'SL::DB::Part', + case_insensitive_header => 1, + profile => { description => 'description' }, ); $csv->parse; is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'case insensitive header from csv works'; @@ -285,9 +287,11 @@ is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'case insensitive hea ##### $csv = SL::Helper::Csv->new( -file => \"Kaffee", -header => [ 'Description' ], -class => 'SL::DB::Part', + file => \"Kaffee", + header => [ 'Description' ], + class => 'SL::DB::Part', + case_insensitive_header => 1, + profile => { description => 'description' }, ); $csv->parse; is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'case insensitive header as param works'; @@ -302,4 +306,54 @@ $csv = SL::Helper::Csv->new( $csv->parse; is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'utf8 BOM works (bug 1872)'; +##### + +$csv = SL::Helper::Csv->new( + file => \"Kaffee", + header => [ 'Description' ], + class => 'SL::DB::Part', +); +$csv->parse; +is_deeply $csv->get_data, undef, 'case insensitive header without flag ignores'; + +##### + +$csv = SL::Helper::Csv->new( + file => \"Kaffee", + header => [ 'foo' ], + class => 'SL::DB::Part', + profile => { foo => '' }, +); +$csv->parse; + +is_deeply $csv->get_data, [ { foo => 'Kaffee' } ], 'empty path still gets parsed into data'; +ok $csv->get_objects->[0], 'empty path gets ignored in object creation'; + +##### + +$csv = SL::Helper::Csv->new( + file => \"Kaffee", + header => [ 'foo' ], + class => 'SL::DB::Part', + strict_profile => 1, + profile => { foo => '' }, +); +$csv->parse; + +is_deeply $csv->get_data, [ { foo => 'Kaffee' } ], 'empty path still gets parsed into data (strict profile)'; +ok $csv->get_objects->[0], 'empty path gets ignored in object creation (strict profile)'; + +$csv = SL::Helper::Csv->new( + file => \"Phil", + header => [ 'CVAR_grOUnDHog' ], + class => 'SL::DB::Part', + strict_profile => 1, + case_insensitive_header => 1, + profile => { cvar_Groundhog => '' }, +); +$csv->parse; + +is_deeply $csv->get_data, [ { cvar_Groundhog => 'Phil' } ], 'using empty path to get cvars working'; +ok $csv->get_objects->[0], '...and not destorying the objects'; + # vim: ft=perl diff --git a/templates/webpages/admin/create_dataset.html b/templates/webpages/admin/create_dataset.html index 191bbec94..94ddf8292 100644 --- a/templates/webpages/admin/create_dataset.html +++ b/templates/webpages/admin/create_dataset.html @@ -57,7 +57,7 @@ - [% '* there are restrictions for the perpetual method, look at chapter "Bemerkungen zu Bestandsmethode" in' | $T8 %] Lx-Office-Dokumentation.pdf. + [% '* there are restrictions for the perpetual method, look at chapter "Bemerkungen zu Bestandsmethode" in' | $T8 %] kivitendo-Dokumentation.pdf. diff --git a/templates/webpages/am/edit_accounts.html b/templates/webpages/am/edit_accounts.html index dcf0be088..1c5e7a969 100644 --- a/templates/webpages/am/edit_accounts.html +++ b/templates/webpages/am/edit_accounts.html @@ -19,7 +19,6 @@ $(function() { - diff --git a/templates/webpages/ic/form_header.html b/templates/webpages/ic/form_header.html index 4beaf5ead..01185cc2b 100644 --- a/templates/webpages/ic/form_header.html +++ b/templates/webpages/ic/form_header.html @@ -6,6 +6,8 @@

[% title %] [% HTML.escape(partnumber) %] [% HTML.escape(description) %]

+[% PROCESS 'common/flash.html' %] +
diff --git a/templates/webpages/menu/menunew.html b/templates/webpages/menu/menunew.html index 7285d867f..4c51b6637 100644 --- a/templates/webpages/menu/menunew.html +++ b/templates/webpages/menu/menunew.html @@ -42,7 +42,7 @@ $(clockon); [%- HTML.escape(mainitem.title) %] [%- IF mainitem.subitems %] - + [%- SET sub1_id = main_id * 100 %] [%- FOREACH sub1item = mainitem.subitems %] [%- SET sub1_id = sub1_id + 1 %] @@ -51,7 +51,7 @@ $(clockon); [%- HTML.escape(sub1item.title) %] [%- IF sub1item.subitems %] - + [%- SET sub2_id = sub1_id * 100 %] [%- FOREACH sub2item = sub1item.subitems %] [%- SET sub2_id = sub2_id + 1 %]