Nicht benutzte Steuerzonen können jetzt gelöscht werden, sowie deren
Kontenzuordnungen geändert werden (wie bei Buchungsgruppen). Siehe
Feature #70.
Schlägt die Speicherung neuer Steuerzonen fehl, weil z.B. die
Buchungsgruppenkonten fehlen, gibt es nun einen Rollback und eine
ordentliche Fehlermeldung, siehe Fehler #68.
use parent qw(SL::Controller::Base);
use parent qw(SL::Controller::Base);
-#use List::Util qw(first);
-
use SL::DB::TaxZone;
use SL::Helper::Flash;
use SL::Locale::String;
use SL::DB::TaxZone;
use SL::Helper::Flash;
use SL::Locale::String;
);
__PACKAGE__->run_before('check_auth');
);
__PACKAGE__->run_before('check_auth');
-__PACKAGE__->run_before('load_config', only => [ qw(edit update) ]); #destroy
+__PACKAGE__->run_before('load_config', only => [ qw(edit update delete) ]);
my $taxzones = SL::DB::Manager::TaxZone->get_all_sorted();
my $taxzones = SL::DB::Manager::TaxZone->get_all_sorted();
$self->render('taxzones/list',
title => t8('List of tax zones'),
TAXZONES => $taxzones);
$self->render('taxzones/list',
title => t8('List of tax zones'),
TAXZONES => $taxzones);
$self->create_or_update;
}
$self->create_or_update;
}
+sub action_delete {
+ my ($self) = @_;
+
+ # allow deletion of unused tax zones. Will fail, due to database
+ # constraints, if tax zone is used anywhere
+
+ my $db = $self->{config}->db;
+ $db->do_transaction(sub {
+ my $taxzone_charts = SL::DB::Manager::TaxzoneChart->get_all(where => [ taxzone_id => $self->config->id ]);
+ foreach my $taxzonechart ( @{$taxzone_charts} ) { $taxzonechart->delete };
+ $self->config->delete();
+ flash_later('info', $::locale->text('The tax zone has been deleted.'));
+ }) || flash_later('error', $::locale->text('The tax zone is in use and cannot be deleted.'));
+
+ $self->redirect_to(action => 'list');
+
+}
+
sub action_reorder {
my ($self) = @_;
sub action_reorder {
my ($self) = @_;
my $is_new = !$self->config->id;
my $params = delete($::form->{config}) || { };
my $is_new = !$self->config->id;
my $params = delete($::form->{config}) || { };
- $self->config->assign_attributes(%{ $params });
+ my @errors;
+
+ my $db = $self->config->db;
+ $db->do_transaction( sub {
+
+ # always allow editing of description and obsolete
+ $self->config->assign_attributes( %{$params} ) ;
+
+ push(@errors, $self->config->validate); # check for description
+
+ if (@errors) {
+ die @errors . "\n";
+ };
- my @errors = $self->config->validate;
- if (@errors) {
- flash('error', @errors);
- $self->show_form(title => $is_new ? t8('Add taxzone') : t8('Edit taxzone'));
- return;
- }
+ if ( $is_new or $self->config->orphaned ) {
+ # Save taxzone_charts
+ my $buchungsgruppen = SL::DB::Manager::Buchungsgruppe->get_all_sorted();
- $self->config->save;
- $self->config->obsolete($::form->{"obsolete"});
+ foreach my $bg (@{ $buchungsgruppen }) {
+ my $income_accno_id = $::form->{"income_accno_id_" . $bg->id};
+ my $expense_accno_id = $::form->{"expense_accno_id_" . $bg->id};
- #Save taxzone_charts for new taxzones:
- if ($is_new) {
- my $buchungsgruppen = SL::DB::Manager::Buchungsgruppe->get_all_sorted();
+ my ($income_accno, $expense_accno);
+ $income_accno = SL::DB::Manager::Chart->find_by( id => $income_accno_id ) if $income_accno_id;
+ $expense_accno = SL::DB::Manager::Chart->find_by( id => $expense_accno_id ) if $expense_accno_id;
- foreach my $bg (@{ $buchungsgruppen }) {
- my $taxzone_chart = SL::DB::Manager::TaxzoneChart->find_by_or_create(buchungsgruppen_id => $bg->id, taxzone_id => $self->config->id);
+ push(@errors, t8('Buchungsgruppe #1 needs a valid income account' , $bg->description)) unless $income_accno;
+ push(@errors, t8('Buchungsgruppe #1 needs a valid expense account', $bg->description)) unless $expense_accno;
- $taxzone_chart->taxzone_id($self->config->id);
- $taxzone_chart->buchungsgruppen_id($bg->id);
- $taxzone_chart->income_accno_id($::form->{"income_accno_id_" . $bg->id});
- $taxzone_chart->expense_accno_id($::form->{"expense_accno_id_" . $bg->id});
- $taxzone_chart->save;
+ my $taxzone_chart = SL::DB::Manager::TaxzoneChart->find_by_or_create(buchungsgruppen_id => $bg->id, taxzone_id => $self->config->id);
+ # if taxzonechart doesn't exist an empty new TaxzoneChart object is
+ # created by find_by_or_create, so we have to assign buchungsgruppe and
+ # taxzone again for the new case to work
+ $taxzone_chart->taxzone_id($self->config->id);
+ $taxzone_chart->buchungsgruppen_id($bg->id);
+ $taxzone_chart->income_accno_id($income_accno->id);
+ $taxzone_chart->expense_accno_id($expense_accno->id);
+ $taxzone_chart->save;
+ }
+ } ) || die @errors ? join("\n", @errors) . "\n" : $db->error . "\n";
+ # die with rollback of taxzone save if saving of any of the taxzone_charts fails
+ # only show the $db->error if we haven't already identified the likely error ourselves
flash_later('info', $is_new ? t8('The taxzone has been created.') : t8('The taxzone has been saved.'));
$self->redirect_to(action => 'list');
flash_later('info', $is_new ? t8('The taxzone has been created.') : t8('The taxzone has been saved.'));
$self->redirect_to(action => 'list');
+sub orphaned {
+ my ($self) = @_;
+ die 'not an accessor' if @_ > 1;
+
+ my @classes = qw(Customer Vendor Invoice Order DeliveryOrder PurchaseInvoice);
+ foreach my $class ( @classes ) {
+ my $module = 'SL::DB::' . $class;
+ eval "require $module";
+ my $manager = 'SL::DB::Manager::' . $class;
+ return 0 if $manager->get_all_count( query => [ taxzone_id => $self->id ] );
+ };
+ return 1;
+}
+
'Break up the update and contact a service provider.' => 'Diese Option bricht das Update ab. Bitte kontaktieren Sie Ihren Administrator oder beauftragen einen Dienstleister.',
'Buchungsdatum' => 'Buchungsdatum',
'Buchungsgruppe' => 'Buchungsgruppe',
'Break up the update and contact a service provider.' => 'Diese Option bricht das Update ab. Bitte kontaktieren Sie Ihren Administrator oder beauftragen einen Dienstleister.',
'Buchungsdatum' => 'Buchungsdatum',
'Buchungsgruppe' => 'Buchungsgruppe',
+ 'Buchungsgruppe #1 needs a valid expense account' => 'Buchungsgruppe #1 braucht ein gültiges Aufwandskonto',
+ 'Buchungsgruppe #1 needs a valid income account' => 'Buchungsgruppe #1 braucht ein gültiges Erfolgskonto',
'Buchungsgruppe (database ID)' => 'Buchungsgruppe (Datenbank-ID)',
'Buchungsgruppe (name)' => 'Buchungsgruppe (Name)',
'Buchungsgruppen' => 'Buchungsgruppen',
'Buchungsgruppe (database ID)' => 'Buchungsgruppe (Datenbank-ID)',
'Buchungsgruppe (name)' => 'Buchungsgruppe (Name)',
'Buchungsgruppen' => 'Buchungsgruppen',
'The task server is not running.' => 'Der Task-Server läuft nicht.',
'The task server was started successfully.' => 'Der Task-Server wurde erfolgreich gestartet.',
'The task server was stopped successfully.' => 'Der Task-Server wurde erfolgreich beendet.',
'The task server is not running.' => 'Der Task-Server läuft nicht.',
'The task server was started successfully.' => 'Der Task-Server wurde erfolgreich gestartet.',
'The task server was stopped successfully.' => 'Der Task-Server wurde erfolgreich beendet.',
+ 'The tax zone has been deleted.' => 'Die Steuerzone wurde gelöscht.',
+ 'The tax zone is in use and cannot be deleted.' => 'Die Steuerzone wird benutzt und kann nicht gelöscht werden',
'The taxzone has been created.' => 'Die Steuerzone wurde erstellt.',
'The taxzone has been saved.' => 'Die Steuerzone wurde gespeichert.',
'The third way is to download the module from the above mentioned URL and to install the module manually following the installations instructions contained in the source archive.' => 'Die dritte Variante besteht darin, das Paket von der oben genannten URL herunterzuladen und es manuell zu installieren. Beachten Sie dabei die im Paket enthaltenen Installationsanweisungen.',
'The taxzone has been created.' => 'Die Steuerzone wurde erstellt.',
'The taxzone has been saved.' => 'Die Steuerzone wurde gespeichert.',
'The third way is to download the module from the above mentioned URL and to install the module manually following the installations instructions contained in the source archive.' => 'Die dritte Variante besteht darin, das Paket von der oben genannten URL herunterzuladen und es manuell zu installieren. Beachten Sie dabei die im Paket enthaltenen Installationsanweisungen.',
[%- FOREACH bg = BUCHUNGSGRUPPEN %]
<tr>
<th align="right">[% 'Revenue' | $T8 %] [% HTML.escape(bg.description) %]</th>
[%- FOREACH bg = BUCHUNGSGRUPPEN %]
<tr>
<th align="right">[% 'Revenue' | $T8 %] [% HTML.escape(bg.description) %]</th>
- [%- IF SELF.config.id %]
- <td>[% CHARTLIST.${bg.id}.income_accno %] -- [% CHARTLIST.${bg.id}.income_accno_description %]</td>
- [%- ELSE %]
+ [%- IF NOT SELF.config.id %]
<td>[% L.chart_picker('income_accno_id_' _ bg.id, SELF.defaults.income_accno_id, choose=1, type='IC_income,IC_sale', style=style) %]</td>
<td>[% L.chart_picker('income_accno_id_' _ bg.id, SELF.defaults.income_accno_id, choose=1, type='IC_income,IC_sale', style=style) %]</td>
+ [%- ELSIF SELF.config.id AND SELF.config.orphaned %]
+ <td>[% L.chart_picker('income_accno_id_' _ bg.id, CHARTLIST.${bg.id}.income_accno_id, choose=1, type='IC_income,IC_sale', style=style) %]</td>
+ [%- ELSE %]
+ <td>[% CHARTLIST.${bg.id}.income_accno %] -- [% CHARTLIST.${bg.id}.income_accno_description %]</td>
[%- END %]
</tr>
<tr>
<th align="right">[% 'Expense' | $T8 %] [% HTML.escape(bg.description) %]</th>
[%- END %]
</tr>
<tr>
<th align="right">[% 'Expense' | $T8 %] [% HTML.escape(bg.description) %]</th>
- [%- IF SELF.config.id %]
- <td>[% CHARTLIST.${bg.id}.expense_accno %] -- [% CHARTLIST.${bg.id}.expense_accno_description %]</td>
- [%- ELSE %]
+ [%- IF NOT SELF.config.id %]
<td>[% L.chart_picker('expense_accno_id_' _ bg.id, SELF.defaults.expense_accno_id, choose=1, type='IC_expense,IC_cogs', style=style) %]</td>
<td>[% L.chart_picker('expense_accno_id_' _ bg.id, SELF.defaults.expense_accno_id, choose=1, type='IC_expense,IC_cogs', style=style) %]</td>
+ [%- ELSIF SELF.config.id AND SELF.config.orphaned %]
+ <td>[% L.chart_picker('expense_accno_id_' _ bg.id, CHARTLIST.${bg.id}.expense_accno_id, choose=1, type='IC_expense,IC_cogs', style=style) %]</td>
+ [%- ELSE %]
+ <td>[% CHARTLIST.${bg.id}.expense_accno %] -- [% CHARTLIST.${bg.id}.expense_accno_description %]</td>
[%- END %]
</tr>
[%- END %]
[%- END %]
</tr>
[%- END %]
<p>
[% L.hidden_tag("action", "Taxzones/dispatch") %]
[% L.submit_tag("action_" _ (SELF.config.id ? "update" : "create"), LxERP.t8('Save'), onclick="return check_prerequisites();") %]
<p>
[% L.hidden_tag("action", "Taxzones/dispatch") %]
[% L.submit_tag("action_" _ (SELF.config.id ? "update" : "create"), LxERP.t8('Save'), onclick="return check_prerequisites();") %]
+ [%- IF SELF.config.id AND SELF.config.orphaned %]
+ [% L.submit_tag("action_delete", LxERP.t8('Delete'), confirm=LxERP.t8('Are you sure?')) %]
+ [%- END %]
<a href="[% SELF.url_for(action='list') %]">[%- LxERP.t8("Cancel") %]</a>
</p>
<a href="[% SELF.url_for(action='list') %]">[%- LxERP.t8("Cancel") %]</a>
</p>