From 0b34e29fb04ad9ac9912f67b767f9f401700ca97 Mon Sep 17 00:00:00 2001 From: Rolf Fluehmann Date: Wed, 21 Oct 2015 15:07:14 +0200 Subject: [PATCH] countries defaults managed --- SL/Controller/Admin.pm | 48 +- SL/Controller/ClientConfig.pm | 3 +- SL/DB/MetaSetup/Default.pm | 1 + SL/DefaultManager.pm | 102 +++ SL/DefaultManager/German.pm | 23 + SL/DefaultManager/Swiss.pm | 23 + SL/Form.pm | 22 +- SL/IS.pm | 4 +- SL/Layout/Base.pm | 12 +- SL/Locale.pm | 49 +- SL/Menu.pm | 15 +- SL/OE.pm | 4 +- SL/User.pm | 18 +- bin/mozilla/am.pl | 2 +- config/kivitendo.conf.default | 4 + menus/erp_ch.ini | 695 ------------------ menus/user/00-erp.yaml | 17 - new | 8 - scripts/installation_check.pl | 6 +- sql/Pg-upgrade2/defaults_add_country_mode.sql | 5 + t/000setup_database.t | 10 +- templates/webpages/admin/create_dataset.html | 35 +- templates/webpages/am/edit_accounts.html | 18 +- .../client_config/_default_accounts.html | 4 +- templates/webpages/client_config/form.html | 2 +- 25 files changed, 285 insertions(+), 845 deletions(-) create mode 100644 SL/DefaultManager.pm create mode 100644 SL/DefaultManager/German.pm create mode 100644 SL/DefaultManager/Swiss.pm delete mode 100644 menus/erp_ch.ini delete mode 100644 new create mode 100644 sql/Pg-upgrade2/defaults_add_country_mode.sql diff --git a/SL/Controller/Admin.pm b/SL/Controller/Admin.pm index 2145f0564..d48262e75 100644 --- a/SL/Controller/Admin.pm +++ b/SL/Controller/Admin.pm @@ -11,7 +11,6 @@ use SL::Common (); use SL::DB::AuthUser; use SL::DB::AuthGroup; use SL::DB::Printer; -use SL::DBUtils; use SL::Helper::Flash; use SL::Locale::String qw(t8); use SL::System::InstallationLock; @@ -21,7 +20,7 @@ use SL::Layout::AdminLogin; use Rose::Object::MakeMethods::Generic ( 'scalar --get_set_init' => [ qw(client user group printer db_cfg is_locked - all_dateformats all_numberformats all_countrycodes all_stylesheets all_menustyles all_clients all_groups all_users all_rights all_printers + all_dateformats all_numberformats all_countrycodes all_countrymodes all_stylesheets all_menustyles all_clients all_groups all_users all_rights all_printers all_dbsources all_used_dbsources all_accounting_methods all_inventory_systems all_profit_determinations all_charts) ], ); @@ -40,7 +39,6 @@ sub keep_auth_vars { sub action_login { my ($self) = @_; - return $self->login_form if !$::form->{do_login}; return if !$self->authenticate_root; return if !$self->check_auth_db_and_tables; @@ -111,12 +109,13 @@ sub action_show { sub action_new_user { my ($self) = @_; + my $defaults = SL::DefaultManager->new($::lx_office_conf{system}->{default_manager}); $self->user(SL::DB::AuthUser->new( config_values => { vclimit => 200, - countrycode => "de", - numberformat => scalar(grep(/^Switzerland/, get_default_coa($self))) ? "1'000.00" : "1.000,00", - dateformat => "dd.mm.yy", + countrycode => $defaults->language('de'), + numberformat => $defaults->numberformat('1.000,00'), + dateformat => $defaults->dateformat('dd.mm.yy'), stylesheet => "kivitendo.css", menustyle => "neu", }, @@ -550,19 +549,25 @@ sub init_all_countrycodes { return [ map { id => $_, title => $cc{$_} }, sort { $cc{$a} cmp $cc{$b} } keys %cc ]; } +sub init_all_countrymodes { + my %cm = SL::DefaultManager->country_modes; + return [ map { id => $_, title => "$_ ($cm{$_})" }, sort keys %cm ]; +} + # # filters # sub setup_layout { my ($self, $action) = @_; + my $defaults = SL::DefaultManager->new($::lx_office_conf{system}->{default_manager}); $::request->layout(SL::Layout::Dispatcher->new(style => 'admin')); $::form->{favicon} = "favicon.ico"; %::myconfig = ( - countrycode => 'de', - numberformat => '1.000,00', - dateformat => 'dd.mm.yy', + countrycode => $defaults->language('de'), + numberformat => $defaults->numberformat('1.000,00'), + dateformat => $defaults->dateformat('dd.mm.yy'), ) if !%::myconfig; } @@ -627,6 +632,17 @@ sub database_administration_login_form { sub create_dataset_form { my ($self, %params) = @_; + my $defaults = SL::DefaultManager->new($::lx_office_conf{system}->{default_manager}); + + $::request->layout(SL::Layout::Dispatcher->new(style => 'admin')); + $::form->{favicon} = "favicon.ico"; + $::form->{countrymode} = $defaults->country( 'DE' ); + $::form->{chart} = $defaults->chart_of_accounts( 'Germany-DATEV-SKR03EU' ); + $::form->{defaultcurrency} = $defaults->currency( 'EUR' ); + $::form->{precision} = $defaults->precision( '0.01' ); + $::form->{accounting_method} = $defaults->accounting_method( 'cash' ); + $::form->{inventory_system} = $defaults->inventory_system( 'periodic' ); + $::form->{profit_determination} = $defaults->profit_determination( 'balance' ); $self->render('admin/create_dataset', title => (t8('Database Administration') . " / " . t8('Create Dataset'))); } @@ -672,18 +688,4 @@ sub authenticate_root { return undef; } -sub get_default_coa { - my ( $self ) = @_; - my $coa = undef; - eval { - my $client = first { $_->is_default } @{ $self->all_clients }; - my $dbconnect = 'dbi:Pg:dbname=' . $client->dbname . ';host=' . $client->dbhost . ';port=' . $client->dbport; - my $dbh = DBI->connect($dbconnect, $client->dbuser, $client->dbpasswd); - my $query = q{ SELECT coa FROM defaults }; - ($coa) = selectrow_query($::form, $dbh, $query); - $dbh->disconnect; - }; - return $coa; -} - 1; diff --git a/SL/Controller/ClientConfig.pm b/SL/Controller/ClientConfig.pm index a69779a60..e2cc74035 100644 --- a/SL/Controller/ClientConfig.pm +++ b/SL/Controller/ClientConfig.pm @@ -16,7 +16,6 @@ use SL::Helper::Flash; use SL::Locale::String qw(t8); use SL::PriceSource::ALL; use SL::Template; -use SL::DBUtils; __PACKAGE__->run_before('check_auth'); @@ -29,7 +28,7 @@ sub action_edit { my ($self, %params) = @_; $::form->{use_templates} = $self->defaults->templates ? 'existing' : 'new'; - $::form->{use_case} = scalar(grep(/^Switzerland/, (selectrow_query($::form, $::form->get_standard_dbh, 'SELECT coa FROM defaults'))[0])); + $::form->{country_mode} = $self->defaults->country_mode; $self->edit_form; } diff --git a/SL/DB/MetaSetup/Default.pm b/SL/DB/MetaSetup/Default.pm index f17c71d34..81af0548f 100644 --- a/SL/DB/MetaSetup/Default.pm +++ b/SL/DB/MetaSetup/Default.pm @@ -35,6 +35,7 @@ __PACKAGE__->meta->columns( customer_hourly_rate => { type => 'numeric', precision => 8, scale => 2 }, customer_projects_only_in_sales => { type => 'boolean', default => 'false', not_null => 1 }, customernumber => { type => 'text' }, + country_mode => { type => 'text', default => 'DE', not_null => 1 }, datev_check_on_ap_transaction => { type => 'boolean', default => 'true' }, datev_check_on_ar_transaction => { type => 'boolean', default => 'true' }, datev_check_on_gl_transaction => { type => 'boolean', default => 'true' }, diff --git a/SL/DefaultManager.pm b/SL/DefaultManager.pm new file mode 100644 index 000000000..41314ddb3 --- /dev/null +++ b/SL/DefaultManager.pm @@ -0,0 +1,102 @@ +package SL::DefaultManager; + +use strict; + +use SL::Util qw(camelify); +use List::Util qw(first); + +my %manager_cache; + +sub new { + my ($class, @defaults) = @_; + bless [ @defaults ], $class; +} + +sub _managers { + my ($self) = @_; + + map { $self->_get($_) } @$self; +} + +sub _get { + my ($class, $name) = @_; + + return if !$name; + + $manager_cache{$name} ||= do { + die "'$name' doesn't look like a default manager." unless $name =~ /^\w+$/a; + + my $package = 'SL::DefaultManager::' . camelify($name); + + eval "require $package; 1" or die "could not load default manager '$package': $@"; + + $package->new; + } +} + +sub country_modes { + my ($self) = @_; + return ( + 'CH' => 'Switzerland', + 'DE' => 'Germany', + ) +} + +sub AUTOLOAD { + our $AUTOLOAD; + + my ($self, @args) = @_; + + my $method = $AUTOLOAD; + $method =~ s/.*:://; + return if $method eq 'DESTROY'; + + my $manager = first { $_->can($method) } $self->_managers; + + return $manager ? $manager->$method : @args; +} + +1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::DefaultManager - sets of defaults for use outside of clients + +=head1 SYNOPSIS + + # during startup + my $defaults = SL::DefaultManager->new($::lx_office_conf{default_manager}); + + # during tests + my $defaults = SL::DefaultManager->new('swiss'); + + # in consuming code + # will return what the manager provides, or the given value if $defaults does + # not handle dateformat + my $dateformat = $defaults->dateformat('dd.mm.yyyy'); + + # have several default managers for different tasks + # if polled the first defined response will win + my $defaults = SL::DefaultManager->new('swiss', 'mobile', 'point_of_sale'); + +=head1 DESCRIPTION + +TODO + +=head1 FUNCTIONS + +TODO + +=head1 BUGS + +None yet :) + +=head1 AUTHOR + +Sven Schöling Es.schoeling@linet-services.deE + +=cut diff --git a/SL/DefaultManager/German.pm b/SL/DefaultManager/German.pm new file mode 100644 index 000000000..372b8f3a5 --- /dev/null +++ b/SL/DefaultManager/German.pm @@ -0,0 +1,23 @@ +package SL::DefaultManager::German; + +use strict; +use parent qw(Rose::Object); + +# client defaults +sub chart_of_accounts { 'Germany-DATEV-SKR03EU' } +sub accounting_method { 'cash' } +sub inventory_system { 'periodic' } +sub profit_determination { 'income' } +sub currency { 'EUR' } +sub precision { 0.01 } + +# user defaults +sub numberformat { '1.000,00' } +sub dateformat { 'dd.mm.yy' } +sub timeformat { 'hh:mm' } + +# default for login/admin areas +sub country { 'DE' } +sub language { 'de' } + +1; diff --git a/SL/DefaultManager/Swiss.pm b/SL/DefaultManager/Swiss.pm new file mode 100644 index 000000000..78444de68 --- /dev/null +++ b/SL/DefaultManager/Swiss.pm @@ -0,0 +1,23 @@ +package SL::DefaultManager::Swiss; + +use strict; +use parent qw(Rose::Object); + +# client defaults +sub chart_of_accounts { 'Switzerland-deutsch-MWST-2014' } +sub accounting_method { 'accrual' } +sub inventory_system { 'periodic' } +sub profit_determination { 'balance' } +sub currency { 'CHF' } +sub precision { 0.05 } + +# user defaults +sub numberformat { "1'000.00" } +sub dateformat { 'dd.mm.yy' } +sub timeformat { 'hh:mm' } + +# default for login/admin areas +sub country { 'CH' } +sub language { 'de' } + +1; diff --git a/SL/Form.pm b/SL/Form.pm index 339d2bbd2..6a65a82bc 100644 --- a/SL/Form.pm +++ b/SL/Form.pm @@ -969,19 +969,19 @@ sub parse_amount { sub round_amount { my ($self, $amount, $places, $adjust) = @_; + return 0 if !defined $amount; + if ($adjust) { - my $precision = 0.01; + my $precision = SL::DB::Default->get->precision || 0.01; # Round amounts to eight places before rounding to the requested # number of places. This gets rid of errors due to internal floating # point representation. $amount = int($amount * 10**8 + .5 * ($amount <=> 0)) / 10**8 if $places < 8; - $amount = int($amount / ($precision = _get_precision()) + ($amount <=> 0) * .5) * $precision; + $amount = int($amount / $precision + ($amount <=> 0) * .5) * $precision; $amount = int($amount * 10**$places + .5 * ($amount <=> 0)) / 10**$places; return $amount; } - return 0 if !defined $amount; - # We use Perl's knowledge of string representation for # rounding. First, convert the floating point number to a string # with a high number of places. Then split the string on the decimal @@ -3698,20 +3698,6 @@ sub calculate_tax { return ($amount,$tax); }; -sub _get_precision { - my ( $self ) = @_; - my $precision = 0.01; - eval { - my $client = $::auth->{client}; - my $dbconnect = 'dbi:Pg:dbname=' . $client->{dbname} . ';host=' . $client->{dbhost} . ';port=' . $client->{dbport}; - my $dbh = DBI->connect($dbconnect, $client->{dbuser}, $client->{dbpasswd}); - my $query = q{ SELECT precision FROM defaults }; - ($precision) = selectrow_query($::form, $dbh, $query); - $dbh->disconnect; - }; - return $precision; -} - 1; __END__ diff --git a/SL/IS.pm b/SL/IS.pm index 7ac074616..fde061d00 100644 --- a/SL/IS.pm +++ b/SL/IS.pm @@ -1876,8 +1876,8 @@ sub retrieve_invoice { (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id) AS expense_accno, (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id) AS fxgain_accno, (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno, - (SELECT c.accno FROM chart c WHERE d.rndgain_accno_id = c.id) AS rndgain_accno, - (SELECT c.accno FROM chart c WHERE d.rndloss_accno_id = c.id) AS rndloss_accno + (SELECT c.accno FROM chart c WHERE d.rndgain_accno_id = c.id) AS rndgain_accno, + (SELECT c.accno FROM chart c WHERE d.rndloss_accno_id = c.id) AS rndloss_accno ${query_transdate} FROM defaults d|; diff --git a/SL/Layout/Base.pm b/SL/Layout/Base.pm index 8c7aa3927..e39502f1f 100644 --- a/SL/Layout/Base.pm +++ b/SL/Layout/Base.pm @@ -19,7 +19,6 @@ use Rose::Object::MakeMethods::Generic ( use SL::Menu; use SL::Presenter; -use SL::DBUtils; my %menu_cache; @@ -30,16 +29,7 @@ sub new { } sub init_menu { - my @menu_files; - my $dbh = $::form->get_standard_dbh; - if(scalar(grep(/^Switzerland/, (selectrow_query($::form, $dbh, 'SELECT coa FROM defaults'))[0]))) { - @menu_files = qw(menus/erp_ch.ini); - } else { - @menu_files = qw(menus/erp.ini); - } - $dbh->commit; - unshift @menu_files, 'menus/crm.ini' if $::instance_conf->crm_installed; - Menu->new(@menu_files); + SL::Menu->new('user'); } sub init_auto_reload_resources_param { diff --git a/SL/Locale.pm b/SL/Locale.pm index 25e804333..f568b0826 100644 --- a/SL/Locale.pm +++ b/SL/Locale.pm @@ -45,55 +45,56 @@ use SL::LXDebug; use SL::Common; use SL::Iconv; use SL::Inifile; +use XML::LibXML; use strict; -my %locales_by_country; +my %locales_by_language; sub new { $main::lxdebug->enter_sub(); - my ($type, $country) = @_; + my ($type, $language) = @_; - $country ||= $::lx_office_conf{system}->{language}; - $country =~ s|.*/||; - $country =~ s|\.||g; + $language ||= $::lx_office_conf{system}->{language}; + $language =~ s|.*/||; + $language =~ s|\.||g; - if (!$locales_by_country{$country}) { + if (!$locales_by_language{$language}) { my $self = {}; bless $self, $type; - $self->_init($country); + $self->_init($language); - $locales_by_country{$country} = $self; + $locales_by_language{$language} = $self; } $main::lxdebug->leave_sub(); - return $locales_by_country{$country} + return $locales_by_language{$language} } sub _init { my $self = shift; - my $country = shift; + my $language = shift; - $self->{countrycode} = $country; + $self->{countrycode} = $language; - if ($country && -d "locale/$country") { - if (open my $in, "<", "locale/$country/all") { - local $/ = undef; - my $code = <$in>; + if ($language && -d "locale/$language") { + local *IN; + if (open(IN, "<", "locale/$language/all")) { + my $code = join("", ); eval($code); - close($in); + close(IN); } - if (-d "locale/$country/more") { - opendir my $dh, "locale/$country/more" or die "can't open locale/$country/more: $!"; - my @files = sort grep -f "locale/$country/more/$_", readdir $dh; + if (-d "locale/$language/more") { + opendir my $dh, "locale/$language/more" or die "can't open locale/$language/more: $!"; + my @files = sort grep -f "locale/$language/more/$_", readdir $dh; close $dh; for my $file (@files) { - if (open my $in, "<", "locale/$country/more/$file") { + if (open my $in, "<", "locale/$language/more/$file") { local $/ = undef; my $code = <$in>; eval($code); @@ -114,7 +115,7 @@ sub _init { $self->{iconv_to_iso8859} = SL::Iconv->new('UTF-8', 'ISO-8859-15'); $self->{iconv_utf8} = SL::Iconv->new('UTF-8', 'UTF-8'); - $self->_read_special_chars_file($country); + $self->_read_special_chars_file($language); push @{ $self->{LONG_MONTH} }, ("January", "February", "March", "April", @@ -167,14 +168,14 @@ sub _handle_markup { sub _read_special_chars_file { my $self = shift; - my $country = shift; + my $language = shift; - if (! -f "locale/$country/special_chars") { + if (! -f "locale/$language/special_chars") { $self->{special_chars_map} = {}; return; } - $self->{special_chars_map} = Inifile->new("locale/$country/special_chars", 'verbatim' => 1); + $self->{special_chars_map} = Inifile->new("locale/$language/special_chars", 'verbatim' => 1); foreach my $format (keys %{ $self->{special_chars_map} }) { next if (($format eq 'FILE') || ($format eq 'ORDER') || (ref $self->{special_chars_map}->{$format} ne 'HASH')); diff --git a/SL/Menu.pm b/SL/Menu.pm index ac8f7280b..f01b341be 100644 --- a/SL/Menu.pm +++ b/SL/Menu.pm @@ -220,12 +220,6 @@ sub parse_instance_conf_string { return $::instance_conf->data->{$setting}; } -sub parse_compare_string { - my ($self, $switch) = @_; - my ($setting, $mode) = split m/=/, $switch, 2; - return $::instance_conf->data->{$setting} eq $mode; -} - sub clear_access { my ($self) = @_; for my $node ($self->tree_walk("all")) { @@ -236,14 +230,11 @@ sub clear_access { sub set_access { my ($self) = @_; - # 1. evaluate appearence - # 2. evaluate access for all - # 3. if a menu has no visible children, its not visible either + # 1. evaluate access for all + # 2. if a menu has no visible children, its not visible either for my $node (reverse $self->tree_walk("all")) { - $node->{visible} = $node->{inclusion} ? $self->parse_compare_string($node->{inclusion}) : 1 - && $node->{exclusion} ? !$self->parse_compare_string($node->{exclusion}) : 1 - && $node->{access} ? $self->parse_access_string($node) + $node->{visible} = $node->{access} ? $self->parse_access_string($node) : !$node->{children} ? 1 : $node->{visible_children} ? 1 : 0; diff --git a/SL/OE.pm b/SL/OE.pm index 07484f9da..fffd90b9e 100644 --- a/SL/OE.pm +++ b/SL/OE.pm @@ -892,8 +892,8 @@ sub retrieve { (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id) AS expense_accno, (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id) AS fxgain_accno, (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id) AS fxloss_accno, - (SELECT c.accno FROM chart c WHERE d.rndgain_accno_id = c.id) AS rndgain_accno, - (SELECT c.accno FROM chart c WHERE d.rndloss_accno_id = c.id) AS rndloss_accno + (SELECT c.accno FROM chart c WHERE d.rndgain_accno_id = c.id) AS rndgain_accno, + (SELECT c.accno FROM chart c WHERE d.rndloss_accno_id = c.id) AS rndloss_accno $query_add FROM defaults d|; my $ref = selectfirst_hashref_query($form, $dbh, $query); diff --git a/SL/User.pm b/SL/User.pm index b63ffc2a0..7a8d303e5 100644 --- a/SL/User.pm +++ b/SL/User.pm @@ -46,6 +46,7 @@ use SL::DBUtils; use SL::Iconv; use SL::Inifile; use SL::System::InstallationLock; +use SL::DefaultManager; use strict; @@ -284,15 +285,17 @@ sub dbcreate { $dbupdater->process_query($dbh, "sql/lx-office.sql"); # process update-scripts needed before 1st user-login - $dbupdater->process_query($dbh, "sql/Pg-upgrade2/defaults_add_precision.sql"); $self->create_schema_info_table($form, $dbh); + $dbupdater->process_query($dbh, "sql/Pg-upgrade2/defaults_add_precision.sql"); $dbh->do("INSERT INTO schema_info (tag, login) VALUES ('defaults_add_precision', 'admin')"); + $dbupdater->process_query($dbh, "sql/Pg-upgrade2/defaults_add_country_mode.sql"); + $dbh->do("INSERT INTO schema_info (tag, login) VALUES ('defaults_add_country_mode', 'admin')"); # load chart of accounts $dbupdater->process_query($dbh, "sql/$form->{chart}-chart.sql"); - $query = qq|UPDATE defaults SET coa = ?, accounting_method = ?, profit_determination = ?, inventory_system = ?, curr = ?, precision = ?|; - do_query($form, $dbh, $query, map { $form->{$_} } qw(chart accounting_method profit_determination inventory_system defaultcurrency precision)); + $query = qq|UPDATE defaults SET coa = ?, accounting_method = ?, profit_determination = ?, inventory_system = ?, curr = ?, precision = ?, country_mode = ?|; + do_query($form, $dbh, $query, map { $form->{$_} } qw(chart accounting_method profit_determination inventory_system defaultcurrency precision countrymode)); $dbh->disconnect; @@ -419,14 +422,15 @@ sub data { sub get_default_myconfig { my ($self_or_class, %user_config) = @_; + my $defaults = SL::DefaultManager->new($::lx_office_conf{system}->{default_manager}); return ( - countrycode => 'de', + countrycode => $defaults->language('de'), css_path => 'css', # Needed for menunew, see SL::Layout::Base::get_stylesheet_for_user - dateformat => 'dd.mm.yy', - numberformat => '1.000,00', + dateformat => $defaults->dateformat('dd.mm.yy'), + numberformat => $defaults->numberformat('1.000,00'), stylesheet => 'kivitendo.css', - timeformat => 'hh:mm', + timeformat => $defaults->timeformat('hh:mm'), %user_config, ); } diff --git a/bin/mozilla/am.pl b/bin/mozilla/am.pl index 4d4465e7f..392aedcda 100644 --- a/bin/mozilla/am.pl +++ b/bin/mozilla/am.pl @@ -215,7 +215,7 @@ sub account_header { my $select_eur = q|\n|; my %eur; - if ($form->{use_case} = scalar(grep(/^Switzerland/, (selectrow_query($form, $form->get_standard_dbh, 'SELECT coa FROM defaults'))[0]))) { + if (($form->{country_mode} = SL::DB::Default->get->country_mode) eq 'CH') { %eur = ( 1 => "Ertrag", 6 => "Aufwand", diff --git a/config/kivitendo.conf.default b/config/kivitendo.conf.default index 0ff2aa176..09be30c89 100644 --- a/config/kivitendo.conf.default +++ b/config/kivitendo.conf.default @@ -65,6 +65,10 @@ bind_password = # and "en" (English, not perfect) are available. language = de +# Set default_manager for admin forms. Currently "german" +# and "swiss" are available. +default_manager = german + [paths] # path to temporary files (must be writeable by the web server) userspath = users diff --git a/menus/erp_ch.ini b/menus/erp_ch.ini deleted file mode 100644 index d4d43d887..000000000 --- a/menus/erp_ch.ini +++ /dev/null @@ -1,695 +0,0 @@ -[Master Data] - -[Master Data--Add Customer] -ACCESS=customer_vendor_edit -module=controller.pl -action=CustomerVendor/add -db=customer - -[Master Data--Add Vendor] -ACCESS=customer_vendor_edit -module=controller.pl -action=CustomerVendor/add -db=vendor - -[Master Data--Add Part] -ACCESS=part_service_assembly_edit -module=ic.pl -action=add -item=part - -[Master Data--Add Service] -ACCESS=part_service_assembly_edit -module=ic.pl -action=add -item=service - -[Master Data--Add Assembly] -ACCESS=part_service_assembly_edit -module=ic.pl -action=add -item=assembly - -[Master Data--Add Project] -ACCESS=project_edit -module=controller.pl -action=Project/new - -[Master Data--Update Prices] -ACCESS=part_service_assembly_edit -module=ic.pl -action=search_update_prices - - -[Master Data--Reports] -module=menu.pl -action=acc_menu -submenu=1 - -[Master Data--Reports--Customers] -ACCESS=customer_vendor_edit -module=controller.pl -action=CustomerVendor/search -db=customer - -[Master Data--Reports--Vendors] -ACCESS=customer_vendor_edit -module=controller.pl -action=CustomerVendor/search -db=vendor - -[Master Data--Reports--Contacts] -ACCESS=customer_vendor_edit -module=controller.pl -action=CustomerVendor/search_contact -db=customer - -[Master Data--Reports--Parts] -ACCESS=part_service_assembly_details -module=ic.pl -action=search -searchitems=part - -[Master Data--Reports--Services] -ACCESS=part_service_assembly_details -module=ic.pl -action=search -searchitems=service - -[Master Data--Reports--Assemblies] -ACCESS=part_service_assembly_details -module=ic.pl -action=search -searchitems=assembly - -[Master Data--Reports--Projects] -ACCESS=project_edit -module=controller.pl -action=Project/search - -[AR] - -[AR--Add Quotation] -ACCESS=sales_quotation_edit -module=oe.pl -action=add -type=sales_quotation - -[AR--Add Sales Order] -ACCESS=sales_order_edit -module=oe.pl -action=add -type=sales_order - -[AR--Add Delivery Order] -ACCESS=sales_delivery_order_edit -module=do.pl -action=add -type=sales_delivery_order - -[AR--Add Sales Invoice] -ACCESS=invoice_edit -module=is.pl -action=add -type=invoice - -[AR--Add Credit Note] -ACCESS=invoice_edit -module=is.pl -action=add -type=credit_note - -[AR--Add Dunning] -ACCESS=dunning_edit -module=dn.pl -action=add - -[AR--Reports] -module=menu.pl -action=acc_menu -submenu=1 - -[AR--Reports--Quotations] -ACCESS=sales_quotation_edit -module=oe.pl -action=search -type=sales_quotation - -[AR--Reports--Sales Orders] -ACCESS=sales_order_edit -module=oe.pl -action=search -type=sales_order - -[AR--Reports--Delivery Orders] -ACCESS=sales_delivery_order_edit -module=do.pl -action=search -type=sales_delivery_order - -[AR--Reports--Invoices, Credit Notes & AR Transactions] -ACCESS=invoice_edit -module=ar.pl -action=search -nextsub=ar_transactions - -[AR--Reports--Sales Report] -ACCESS=invoice_edit -module=vk.pl -action=search_invoice -nextsub=invoice_transactions - -[AR--Reports--Dunnings] -ACCESS=dunning_edit -module=dn.pl -action=search - -[AR--Reports--Delivery Plan] -ACCESS=sales_order_edit -module=controller.pl -action=DeliveryPlan/list - -[AP] - -[AP--Add RFQ] -ACCESS=request_quotation_edit -module=oe.pl -action=add -type=request_quotation - -[AP--Add Purchase Order] -ACCESS=purchase_order_edit -module=oe.pl -action=add -type=purchase_order - -[AP--Add Delivery Note] -ACCESS=purchase_delivery_order_edit -module=do.pl -action=add -type=purchase_delivery_order - -[AP--Add Vendor Invoice] -ACCESS=vendor_invoice_edit -module=ir.pl -action=add -type=invoice - - -[AP--Reports] -module=menu.pl -action=acc_menu -submenu=1 - -[AP--Reports--RFQs] -ACCESS=request_quotation_edit -module=oe.pl -action=search -type=request_quotation - -[AP--Reports--Purchase Orders] -ACCESS=purchase_order_edit -module=oe.pl -action=search -type=purchase_order - -[AP--Reports--Delivery Orders] -ACCESS=purchase_delivery_order_edit -module=do.pl -action=search -type=purchase_delivery_order - -[AP--Reports--Vendor Invoices & AP Transactions] -ACCESS=vendor_invoice_edit -module=ap.pl -action=search -nextsub=ap_transactions - - -[Warehouse] - -[Warehouse--Stock] -ACCESS=warehouse_management -module=controller.pl -action=Inventory/stock_in - -[Warehouse--Produce Assembly] -ACCESS=warehouse_management -module=wh.pl -action=transfer_warehouse_selection -trans_type=assembly - -[Warehouse--Transfer] -ACCESS=warehouse_management -module=wh.pl -action=transfer_warehouse_selection -trans_type=transfer - -[Warehouse--Removal] -ACCESS=warehouse_management -module=wh.pl -action=transfer_warehouse_selection -trans_type=removal - -[Warehouse--Reports] -module=menu.pl -action=acc_menu -submenu=1 - -[Warehouse--Reports--Warehouse content] -ACCESS=warehouse_contents | warehouse_management -module=wh.pl -action=report - -[Warehouse--Reports--WHJournal] -ACCESS=warehouse_management -module=wh.pl -action=journal - - -[General Ledger] - -[General Ledger--Add Transaction] -ACCESS=general_ledger -module=gl.pl -action=add - -[General Ledger--Add AR Transaction] -ACCESS=general_ledger -module=ar.pl -action=add - -[General Ledger--Add AP Transaction] -ACCESS=general_ledger -module=ap.pl -action=add - - -[General Ledger--Reports] -module=menu.pl -action=acc_menu -submenu=1 - - -[General Ledger--Reports--AR Aging] -ACCESS=general_ledger -module=rp.pl -action=report -report=ar_aging - - -[General Ledger--Reports--AP Aging] -ACCESS=general_ledger -module=rp.pl -action=report -report=ap_aging - -[General Ledger--Reports--Journal] -ACCESS=general_ledger -module=gl.pl -action=search - - -[Cash] -ACCESS=cash - -[Cash--Receipt] -module=cp.pl -action=payment -type=receipt -vc=customer - -[Cash--Payment] -module=cp.pl -action=payment -type=check -vc=vendor - -[Cash--Reconciliation] -ACCESS=cash -module=rc.pl -action=reconciliation - -[Cash--Bank collection via SEPA] -module=sepa.pl -action=bank_transfer_add -vc=customer - -[Cash--Bank transfer via SEPA] -module=sepa.pl -action=bank_transfer_add -vc=vendor - -[Cash--Reports] -module=menu.pl -action=acc_menu -submenu=1 - -[Cash--Reports--Receipts] -module=rp.pl -action=report -report=receipts - -[Cash--Reports--Payments] -module=rp.pl -action=report -report=payments - -[Cash--Reports--Bank collections via SEPA] -module=sepa.pl -action=bank_transfer_search -vc=customer - -[Cash--Reports--Bank transfers via SEPA] -module=sepa.pl -action=bank_transfer_search -vc=vendor - -[Reports] - -[Reports--Chart of Accounts] -ACCESS=report -module=ca.pl -action=chart_of_accounts - -[Reports--Trial Balance] -ACCESS=report -module=rp.pl -action=report -report=trial_balance - -[Reports--Erfolgsrechnung] -ACCESS=report -module=rp.pl -action=report -report=erfolgsrechnung - -[Reports--Projecttransactions] -ACCESS=report -module=rp.pl -action=report -report=projects - - -[Batch Printing] -ACCESS=batch_printing - -[Batch Printing--Sales Invoices] -ACCESS=invoice_edit -module=bp.pl -action=search -vc=customer -type=invoice - -[Batch Printing--Sales Orders] -ACCESS=sales_order_edit -module=bp.pl -action=search -vc=customer -type=sales_order - -[Batch Printing--Quotations] -ACCESS=sales_quotation_edit -module=bp.pl -action=search -vc=customer -type=sales_quotation - -[Batch Printing--Packing Lists] -ACCESS=invoice_edit | sales_order_edit -module=bp.pl -action=search -vc=customer -type=packing_list - -[Batch Printing--Purchase Orders] -ACCESS=purchase_order_edit -module=bp.pl -action=search -vc=vendor -type=purchase_order - -[Batch Printing--RFQs] -ACCESS=request_quotation_edit -module=bp.pl -action=search -vc=vendor -type=request_quotation - -[Batch Printing--Checks] -ACCESS=cash -module=bp.pl -action=search -vc=vendor -type=check - -[Batch Printing--Receipts] -ACCESS=cash -module=bp.pl -action=search -vc=customer -type=receipt - - -[Productivity] -ACCESS=productivity - -[Productivity--Show TODO list] -module=todo.pl -action=show_todo_list - -[Productivity--Add Follow-Up] -module=fu.pl -action=add - -[Productivity--Edit Access Rights] -module=fu.pl -action=edit_access_rights - -[Productivity--Reports] -module=menu.pl -action=acc_menu -submenu=1 - -[Productivity--Reports--Follow-Ups] -module=fu.pl -action=search - - -[System] -ACCESS=config - -[System--Client Configuration] -ACCESS=admin -module=controller.pl -action=ClientConfig/edit - -[System--Edit Dunning] -module=dn.pl -action=edit_config - -[System--Chart of Accounts] -module=menu.pl -action=acc_menu -submenu=1 - -[System--Chart of Accounts--Add Account] -module=am.pl -action=add_account - -[System--Chart of Accounts--List Accounts] -module=am.pl -action=list_account - -[System--Buchungsgruppen] -module=am.pl -action=list_buchungsgruppe - -[System--Taxes] -module=am.pl -action=list_tax - -[System--Bank accounts] -module=bankaccounts.pl -action=bank_account_list - -[System--Groups] -module=pe.pl -action=search -type=partsgroup - -[System--Pricegroups] -module=pe.pl -action=search -type=pricegroup - -[System--Edit units] -module=am.pl -action=edit_units - -[System--Price Factors] -module=am.pl -action=list_price_factors - -[System--Departments] -module=controller.pl -action=Department/list - -[System--Types of Business] -module=controller.pl -action=Business/list - -[System--Leads] -module=am.pl -action=list_lead - -[System--Languages and translations] -module=menu.pl -action=acc_menu -submenu=1 - -[System--Languages and translations--Add Language] -module=am.pl -action=add_language - -[System--Languages and translations--List Languages] -module=am.pl -action=list_language - -[System--Languages and translations--Greetings] -module=generictranslations.pl -action=edit_greetings - -[System--Languages and translations--SEPA strings] -module=generictranslations.pl -action=edit_sepa_strings - - -[System--Payment Terms] -module=controller.pl -action=PaymentTerm/list - -[System--Manage Custom Variables] -module=controller.pl -action=CustomVariableConfig/list - -[System--Warehouses] -module=am.pl -action=list_warehouses - - -[System--Import CSV] -module=menu.pl -action=acc_menu -submenu=1 - -[System--Import CSV--Customers and vendors] -module=controller.pl -action=CsvImport/new -profile.type=customers_vendors - -[System--Import CSV--Contacts] -module=controller.pl -action=CsvImport/new -profile.type=contacts - -[System--Import CSV--Shipto] -module=controller.pl -action=CsvImport/new -profile.type=addresses - -[System--Import CSV--Parts] -module=controller.pl -action=CsvImport/new -profile.type=parts - -[System--Import CSV--Projects] -module=controller.pl -action=CsvImport/new -profile.type=projects - -[System--Templates] -ACCESS=admin -module=menu.pl -action=acc_menu -submenu=1 - -[System--Templates--HTML Templates] -module=amtemplates.pl -action=display_template_form -type=templates -format=html - -[System--Templates--LaTeX Templates] -module=amtemplates.pl -action=display_template_form -type=templates -format=tex - -[System--Templates--Stylesheet] -module=amtemplates.pl -action=display_template_form -type=stylesheet - -[System--General Ledger Corrections] -module=acctranscorrections.pl -action=analyze_filter - -[System--Background jobs and task server] -ACCESS=admin -module=menu.pl -action=acc_menu -submenu=1 - -[System--Background jobs and task server--List current background jobs] -module=controller.pl -action=BackgroundJob/list - -[System--Background jobs and task server--Background job history] -module=controller.pl -action=BackgroundJobHistory/list - -[System--Background jobs and task server--Task server control] -module=controller.pl -action=TaskServer/show - -[System--Audit Control] -module=am.pl -action=audit_control - -[System--History Search Engine] -module=am.pl -action=show_history_search - -[System--Employees] -ACCESS=admin -module=controller.pl -action=Employee/list - -[Program] - -[Program--User Preferences] -module=am.pl -action=config - -[Program--Version] -module=login.pl -action=company_logo -no_todo_list=1 - -[Program--Administration area] -ACCESS=display_admin_link -module=controller.pl -action=Admin/login - -[Program--Documentation (in German)] -href=doc/kivitendo-Dokumentation.pdf -target=_blank - -[Program--kivitendo website (external)] -href=http://www.kivitendo.de/ -target=_blank - -[Program--Logout] -module=controller.pl -action=LoginScreen/logout diff --git a/menus/user/00-erp.yaml b/menus/user/00-erp.yaml index 1dddff202..53d0586b4 100644 --- a/menus/user/00-erp.yaml +++ b/menus/user/00-erp.yaml @@ -574,7 +574,6 @@ id: general_ledger_datev_export_assistent name: DATEV - Export Assistent icon: datev - exclusion: country_mode=CH order: 400 access: datev_export module: datev.pl @@ -773,23 +772,11 @@ params: action: report report: trial_balance -- parent: reports - id: reports_erfolgsrechnung - name: Erfolgsrechnung - icon: income_statement - order: 300 - inclusion: country_mode=CH - access: report - module: rp.pl - params: - action: report - report: erfolgsrechnung - parent: reports id: reports_income_statement name: Income Statement icon: income_statement order: 300 - exclusion: country_mode=CH access: report module: rp.pl params: @@ -799,7 +786,6 @@ id: reports_bwa name: BWA order: 400 - exclusion: country_mode=CH access: report module: rp.pl params: @@ -810,7 +796,6 @@ name: Balance Sheet icon: balance_sheet order: 500 - exclusion: country_mode=CH access: report module: rp.pl params: @@ -821,7 +806,6 @@ name: UStVa icon: ustva order: 600 - exclusion: country_mode=CH access: advance_turnover_tax_return module: ustva.pl params: @@ -1001,7 +985,6 @@ id: system_ustva_einstellungen name: UStVa Einstellungen order: 200 - exclusion: country_mode=CH module: ustva.pl params: action: config_step1 diff --git a/new b/new deleted file mode 100644 index 919d166e4..000000000 --- a/new +++ /dev/null @@ -1,8 +0,0 @@ -bin/mozilla/am.pl -SL/AM.pm -SL/Form.pm -SL/BackgroundJob/CreatePeriodicInvoices.pm -SL/BackgroundJob/SelfTest.pm -SL/DBUpgrade2.pm -SL/Controller/LoginScreen.pm -SL/Controller/Admin.pm diff --git a/scripts/installation_check.pl b/scripts/installation_check.pl index 43b290a35..f7c76fb7c 100755 --- a/scripts/installation_check.pl +++ b/scripts/installation_check.pl @@ -121,7 +121,7 @@ EOL } } -if (@missing_modules && $apt && !$check{s}) { +if (@missing_modules && ($check{a} || $apt && !$check{s})) { print "\nHere are some sample installation lines, choose one appropriate for your system:\n\n"; local $Text::Wrap::separator = " \\\n"; @@ -271,12 +271,12 @@ sub print_result { sub print_line { my ($text, $res, $color) = @_; - return if $check{s}; + return if $check{s} && !$check{a}; print $text, " ", ('.' x (78 - length($text) - length($res))), " ", mycolor($res, $color), $/; } sub print_header { - return if $check{s}; + return if $check{s} && !$check{a}; print $/; print "$_[0]:", $/; } diff --git a/sql/Pg-upgrade2/defaults_add_country_mode.sql b/sql/Pg-upgrade2/defaults_add_country_mode.sql new file mode 100644 index 000000000..d6495e1d7 --- /dev/null +++ b/sql/Pg-upgrade2/defaults_add_country_mode.sql @@ -0,0 +1,5 @@ +-- @tag: defaults_add_country_mode +-- @description: adds new column 'country_mode' (ISO-3166) in table defaults used for erp.ini +-- @depends: release_3_2_0 +ALTER TABLE defaults ADD COLUMN country_mode TEXT NOT NULL DEFAULT('DE'); + diff --git a/t/000setup_database.t b/t/000setup_database.t index 5cf6a2892..3d5ca6c7a 100755 --- a/t/000setup_database.t +++ b/t/000setup_database.t @@ -14,6 +14,7 @@ use SL::InstanceConfiguration; use SL::LXDebug; use SL::Layout::None; use SL::LxOfficeConf; +use XML::LibXML; our ($db_cfg, $dbh); @@ -117,12 +118,17 @@ sub create_initial_schema { $dbh = SL::DBConnect->connect(@dbi_options) || BAIL_OUT("Database connection failed: " . $DBI::errstr); $::auth->{dbh} = $dbh; my $dbupdater = SL::DBUpgrade2->new(form => $::form, return_on_error => 1, silent => 1); - my $coa = 'Germany-DATEV-SKR03EU'; + my $defaults = SL::DefaultManager->new($::lx_office_conf{system}->{default_manager}); + my $coa = $defaults->chart_of_accounts( 'Germany-DATEV-SKR03EU' ); + my $am = $defaults->accounting_method( 'cash' ); + my $pd = $defaults->profit_determination( 'balance' ); + my $is = $defaults->inventory_system( 'periodic' ); + my $curr = $defaults->currency( 'EUR' ); apply_dbupgrade($dbupdater, "sql/lx-office.sql"); apply_dbupgrade($dbupdater, "sql/${coa}-chart.sql"); - dbh_do($dbh, qq|UPDATE defaults SET coa = '${coa}', accounting_method = 'cash', profit_determination = 'income', inventory_system = 'periodic', curr = 'EUR'|); + dbh_do($dbh, qq|UPDATE defaults SET coa = '${coa}', accounting_method = '${am}', profit_determination = '${pd}', inventory_system = '${is}', curr = '${curr}'|); dbh_do($dbh, qq|CREATE TABLE schema_info (tag TEXT, login TEXT, itime TIMESTAMP DEFAULT now(), PRIMARY KEY (tag))|); } diff --git a/templates/webpages/admin/create_dataset.html b/templates/webpages/admin/create_dataset.html index 36b628d07..4f875a882 100644 --- a/templates/webpages/admin/create_dataset.html +++ b/templates/webpages/admin/create_dataset.html @@ -22,33 +22,43 @@ - [% LxERP.t8('Create Chart of Accounts') %] - [% L.select_tag('chart', SELF.all_charts, onchange='comment_selected_chart(this.value)', default=(FORM.chart || 'Germany-DATEV-SKR03EU')) %] + [% LxERP.t8('Country') %] + [% L.select_tag('countrymode', SELF.all_countrymodes, title_key="title", default=(FORM.countrymode), onchange='select_country_defaults(this.value)') %] + + + + +
[% LxERP.t8('Default currency') %] - [% L.input_tag('defaultcurrency', FORM.defaultcurrency || 'EUR') %] + [% L.input_tag('defaultcurrency', FORM.defaultcurrency) %] [% LxERP.t8('Precision') %] - [% L.input_tag('precision', FORM.precision || '0.01') %] + [% L.input_tag('precision', FORM.precision) %] + + + + [% LxERP.t8('Create Chart of Accounts') %] + [% L.select_tag('chart', SELF.all_charts, default=(FORM.chart), onchange='comment_selected_chart(this.value)') %] [% LxERP.t8('Accounting method') %] - [% L.select_tag('accounting_method', SELF.all_accounting_methods, title_key='name', default=(FORM.accounting_method || 'cash')) %] + [% L.select_tag('accounting_method', SELF.all_accounting_methods, title_key='name', default=(FORM.accounting_method)) %] [% LxERP.t8('Inventory system') %] - [% L.select_tag('inventory_system', SELF.all_inventory_systems, title_key='name', default=(FORM.inventory_system || 'periodic')) %] + [% L.select_tag('inventory_system', SELF.all_inventory_systems, title_key='name', default=(FORM.inventory_system)) %] [% LxERP.t8('Profit determination') %] - [% L.select_tag('profit_determination', SELF.all_profit_determinations, title_key='name', default=(FORM.profit_determination || 'income')) %] + [% L.select_tag('profit_determination', SELF.all_profit_determinations, title_key='name', default=(FORM.profit_determination)) %] @@ -79,15 +89,22 @@ function comment_selected_chart(s) { "fuer Kunden im Ausland." + "\n" + "Hinweis vom 20.09.2011"); - } else if (/^Switzerland/.test(s)) { + } + return true; +} + +function select_country_defaults(country) { + if (/^CH/.test(country)) { document.getElementById('defaultcurrency').value='CHF'; document.getElementById('precision').value='0.05'; + document.getElementById('chart').value='Switzerland-deutsch-MWST-2014'; document.getElementById('accounting_method').value='accrual'; document.getElementById('inventory_system').value='periodic'; document.getElementById('profit_determination').value='balance'; } else { - document.getElementById("defaultcurrency").value="EUR"; + document.getElementById('defaultcurrency').value='EUR'; document.getElementById('precision').value='0.01'; + document.getElementById('chart').value='Germany-DATEV-SKR03EU'; document.getElementById('accounting_method').value='cash'; document.getElementById('inventory_system').value='periodic'; document.getElementById('profit_determination').value='income'; diff --git a/templates/webpages/am/edit_accounts.html b/templates/webpages/am/edit_accounts.html index 67ca10c15..7b000d674 100644 --- a/templates/webpages/am/edit_accounts.html +++ b/templates/webpages/am/edit_accounts.html @@ -27,8 +27,8 @@ $(function() { - - + +
@@ -217,7 +217,9 @@ $(function() { [% 'Taxkey' | $T8 %] [% 'valid from' | $T8 %] - [% 'pos_ustva' | $T8 %] + [% IF country_mode != 'CH' %] + [% 'pos_ustva' | $T8 %] + [% END %] [% 'delete' | $T8 %] ? [% FOREACH tk = ACCOUNT_TAXKEYS %] @@ -227,14 +229,18 @@ $(function() { - + [% IF country_mode != 'CH' %] + + [% END %] [% ELSE %] - + [% IF country_mode != 'CH' %] + + [% END %]   [% END %] @@ -251,7 +257,7 @@ $(function() { [% 'EUER' | $T8 %] - [% IF use_case == 0 %] + [% IF country_mode != 'CH' %] [% 'BWA' | $T8 %] diff --git a/templates/webpages/client_config/_default_accounts.html b/templates/webpages/client_config/_default_accounts.html index ff44b4fc1..4727799cf 100644 --- a/templates/webpages/client_config/_default_accounts.html +++ b/templates/webpages/client_config/_default_accounts.html @@ -32,12 +32,12 @@ [% LxERP.t8("Rounding Gain") %] - [% L.select_tag('defaults.rndgain_accno_id', SELF.defaults.rndgain_accno_id, category='I,A', choose=1, style=style) %] + [% L.chart_picker('defaults.rndgain_accno_id', SELF.defaults.rndgain_accno_id, category='I,A', choose=1, style=style) %] [% LxERP.t8("Rounding Loss") %] - [% L.select_tag('defaults.rndloss_accno_id', SELF.accounts.rndloss_accno_id, category='E,A', choose=1, style=style) %] + [% L.chart_picker('defaults.rndloss_accno_id', SELF.defaults.rndloss_accno_id, category='E,A', choose=1, style=style) %] diff --git a/templates/webpages/client_config/form.html b/templates/webpages/client_config/form.html index 1fda95df4..34300383c 100644 --- a/templates/webpages/client_config/form.html +++ b/templates/webpages/client_config/form.html @@ -58,7 +58,7 @@ $(function() {
  • [% LxERP.t8('Ranges of numbers') %]
  • [% LxERP.t8('Default Accounts') %]
  • [% LxERP.t8('Posting Configuration') %]
  • - [% IF use_case == 0 %] + [% IF FORM.country_mode != 'CH' %]
  • [% LxERP.t8('DATEV check configuration') %]
  • [% END %]
  • [% LxERP.t8('Orders / Delivery Orders deleteable') %]
  • -- 2.20.1