Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 19e2bb1a

Von Tamino Steinert vor etwa 1 Jahr hinzugefügt

  • ID 19e2bb1a553ce7459e8030343d810e424593f08b
  • Vorgänger 3926714c
  • Nachfolger 66376ef2

EmailJournal: Workflow: Vorschlag der passenden Belege

Unterschiede anzeigen:

SL/Controller/EmailJournal.pm
8 8
use SL::DB::Employee;
9 9
use SL::DB::EmailJournal;
10 10
use SL::DB::EmailJournalAttachment;
11
use SL::Presenter::EmailJournal;
12
use SL::Presenter::Tag qw(html_tag div_tag radio_button_tag);
11 13
use SL::Helper::Flash;
12 14
use SL::Locale::String qw(t8);
13
use SL::System::TaskServer;
14
use SL::Presenter::EmailJournal;
15 15

  
16 16
use SL::DB::Order;
17 17
use SL::DB::Order::TypeData;
......
25 25
use SL::DB::Manager::Customer;
26 26
use SL::DB::Manager::Vendor;
27 27

  
28
use List::MoreUtils qw(any);
29

  
28 30
use Rose::Object::MakeMethods::Generic
29 31
(
30 32
  scalar                  => [ qw(entry) ],
......
37 39
my %RECORD_TYPES_INFO = (
38 40
  Order => {
39 41
    controller => 'Order',
40
    model      => 'SL::DB::Order',
42
    class      => 'Order',
41 43
    types => SL::DB::Order::TypeData->valid_types(),
42 44
  },
43 45
  DeliveryOrder => {
44 46
    controller => 'DeliveryOrder',
45
    model      => 'SL::DB::DeliveryOrder',
47
    class      => 'DeliveryOrder',
46 48
    types => SL::DB::DeliveryOrder::TypeData->valid_types(),
47 49
  },
48 50
  Reclamation => {
49 51
    controller => 'Reclamation',
50
    model      => 'SL::DB::Reclamation',
52
    class      => 'Reclamation',
51 53
    types => SL::DB::Reclamation::TypeData->valid_types(),
52 54
  },
53 55
  ArTransaction => {
54 56
    controller => 'ar.pl',
55
    model      => 'SL::DB::Invoice',
57
    class      => 'Invoice',
56 58
    types => [
57 59
      'ar_transaction',
58 60
    ],
59 61
  },
60 62
  Invoice => {
61 63
    controller => 'is.pl',
62
    model      => 'SL::DB::Invoice',
64
    class      => 'Invoice',
63 65
    types => [
64 66
      'invoice',
65 67
      'invoice_for_advance_payment',
......
72 74
  },
73 75
  ApTransaction => {
74 76
    controller => 'ap.pl',
75
    model      => 'SL::DB::PurchaseInvoice',
77
    class      => 'PurchaseInvoice',
76 78
    types => [
77 79
      'ap_transaction',
78 80
    ],
79 81
  },
80 82
  PurchaseInvoice => {
81 83
    controller => 'ir.pl',
82
    model      => 'SL::DB::PurchaseInvoice',
84
    class      => 'PurchaseInvoice',
83 85
    types => [
84 86
      'purchase_invoice',
85 87
      'purchase_credit_note',
......
93 95
  } keys %RECORD_TYPES_INFO;
94 96
my %RECORD_TYPE_TO_MODEL =
95 97
  map {
96
    my $model = $RECORD_TYPES_INFO{$_}->{model};
97
    map { $_ => $model } @{ $RECORD_TYPES_INFO{$_}->{types} }
98
    my $class = $RECORD_TYPES_INFO{$_}->{class};
99
    map { $_ => "SL::DB::$class" } @{ $RECORD_TYPES_INFO{$_}->{types} }
100
  } keys %RECORD_TYPES_INFO;
101
my %RECORD_TYPE_TO_MANAGER =
102
  map {
103
    my $class = $RECORD_TYPES_INFO{$_}->{class};
104
    map { $_ => "SL::DB::Manager::$class" } @{ $RECORD_TYPES_INFO{$_}->{types} }
98 105
  } keys %RECORD_TYPES_INFO;
106
my @ALL_RECORD_TYPES = map { @{ $RECORD_TYPES_INFO{$_}->{types} } } keys %RECORD_TYPES_INFO;
107

  
108
# has do be done at runtime for translation to work
109
sub get_record_types_with_info {
110
  # TODO: what record types can be created, which are only available in workflows?
111
  my @record_types_with_info = ();
112
  for my $record_class ('SL::DB::Order', 'SL::DB::DeliveryOrder', 'SL::DB::Reclamation') {
113
    my $valid_types = "${record_class}::TypeData"->valid_types();
114
    for my $type (@$valid_types) {
115

  
116
      my $type_data = SL::DB::Helper::TypeDataProxy->new($record_class, $type);
117
      push @record_types_with_info, {
118
        record_type    => $type,
119
        customervendor => $type_data->properties('customervendor'),
120
        text           => $type_data->text('type'),
121
      };
122
    }
123
  }
124
  push @record_types_with_info, (
125
    # invoice
126
    { record_type => 'invoice',                             customervendor => 'customer',  text => t8('Invoice') },
127
    { record_type => 'invoice_for_advance_payment',         customervendor => 'customer',  text => t8('Invoice for Advance Payment')},
128
    { record_type => 'invoice_for_advance_payment_storno',  customervendor => 'customer',  text => t8('Storno Invoice for Advance Payment')},
129
    { record_type => 'final_invoice',                       customervendor => 'customer',  text => t8('Final Invoice')},
130
    { record_type => 'invoice_storno',                      customervendor => 'customer',  text => t8('Storno Invoice')},
131
    { record_type => 'credit_note',                         customervendor => 'customer',  text => t8('Credit Note')},
132
    { record_type => 'credit_note_storno',                  customervendor => 'customer',  text => t8('Storno Credit Note')},
133
    { record_type => 'ar_transaction',                      customervendor => 'customer',  text => t8('AR Transaction')},
134
    # purchase invoice
135
    { record_type => 'purchase_invoice',      customervendor => 'vendor',  text => t8('Purchase Invoice')},
136
    { record_type => 'purchase_credit_note',  customervendor => 'vendor',  text => t8('Purchase Credit Note')},
137
    { record_type => 'ap_transaction',        customervendor => 'vendor',  text => t8('AP Transaction')},
138
  );
139
  return @record_types_with_info;
140
}
141

  
142
sub record_types_for_customer_vendor_type {
143
  my ($self, $customer_vendor_type) = @_;
144
  return [ map { $_->{record_type} } grep { $_->{customervendor} eq $customer_vendor_type } $self->get_record_types_with_info ];
145
}
99 146

  
100 147
#
101 148
# actions
......
129 176
    $::form->error(t8('You do not have permission to access this entry.'));
130 177
  }
131 178

  
132
  # TODO: what record types can be created, which are only available in workflows?
133
  my @record_types_with_info = ();
134
  for my $record_class ('SL::DB::Order', 'SL::DB::DeliveryOrder', 'SL::DB::Reclamation') {
135
    my $valid_types = "${record_class}::TypeData"->valid_types();
136
    for my $type (@$valid_types) {
137

  
138
      my $type_data = SL::DB::Helper::TypeDataProxy->new($record_class, $type);
139
      push @record_types_with_info, {
140
        record_type    => $type,
141
        customervendor => $type_data->properties('customervendor'),
142
        text           => $type_data->text('type'),
143
      };
144
    }
145
  }
146
  push @record_types_with_info, (
147
    # invoice
148
    { record_type => 'ar_transaction'                    ,  customervendor => 'customer',  text => t8('AR Transaction')},
149
    { record_type => 'invoice'                           ,  customervendor => 'customer',  text => t8('Invoice') },
150
    { record_type => 'invoice_for_advance_payment'       ,  customervendor => 'customer',  text => t8('Invoice for Advance Payment')},
151
    { record_type => 'invoice_for_advance_payment_storno',  customervendor => 'customer',  text => t8('Storno Invoice for Advance Payment')},
152
    { record_type => 'final_invoice'                     ,  customervendor => 'customer',  text => t8('Final Invoice')},
153
    { record_type => 'invoice_storno'                    ,  customervendor => 'customer',  text => t8('Storno Invoice')},
154
    { record_type => 'credit_note'                       ,  customervendor => 'customer',  text => t8('Credit Note')},
155
    { record_type => 'credit_note_storno'                ,  customervendor => 'customer',  text => t8('Storno Credit Note')},
156
    # purchase invoice
157
    { record_type => 'ap_transaction'      ,  customervendor => 'vendor',  text => t8('AP Transaction')},
158
    { record_type => 'purchase_invoice'    ,  customervendor => 'vendor',  text => t8('Purchase Invoice')},
159
    { record_type => 'purchase_credit_note',  customervendor => 'vendor',  text => t8('Purchase Credit Note')},
160
  );
179
  my @record_types_with_info = $self->get_record_types_with_info();
161 180

  
162 181
  my $customer_vendor = $self->find_customer_vendor_from_email($self->entry);
182
  my $cv_type = $customer_vendor && $customer_vendor->is_vendor ? 'vendor' : 'customer';
183

  
184
  my $record_types = $self->record_types_for_customer_vendor_type($cv_type);
185
  my @records = $self->get_records_for_types(
186
    $record_types,
187
    customer_vendor_type => $cv_type,
188
    customer_vendor_id   => $customer_vendor && $customer_vendor->id,
189
    with_closed     => 0,
190
  );
163 191

  
164 192
  $self->setup_show_action_bar;
165 193
  $self->render(
......
168 196
    CUSTOMER_VENDOR => , $customer_vendor,
169 197
    CV_TYPE_FOUND => $customer_vendor && $customer_vendor->is_vendor ? 'vendor' : 'customer',
170 198
    RECORD_TYPES_WITH_INFO => \@record_types_with_info,
199
    RECORDS => \@records,
171 200
    back_to  => $back_to
172 201
  );
173 202
}
174 203

  
204
sub get_records_for_types {
205
  my ($self, $record_types, %params) = @_;
206
  $record_types = [ $record_types ] unless ref $record_types eq 'ARRAY';
207

  
208
  my $cv_type     = $params{customer_vendor_type};
209
  my $cv_id       = $params{customer_vendor_id};
210
  my $with_closed = $params{with_closed};
211

  
212
  my @records = ();
213
  foreach my $record_type (@$record_types) {
214
    my $manager = $RECORD_TYPE_TO_MANAGER{$record_type};
215
    my $model = $RECORD_TYPE_TO_MODEL{$record_type};
216
    my %additional_where = ();
217
    if ($cv_type && $cv_id) {
218
      $additional_where{"${cv_type}_id"} = $cv_id;
219
    }
220
    unless ($with_closed) {
221
      if (any {$_ eq 'closed' } $model->meta->columns) {
222
        $additional_where{closed} = 0;
223
      } elsif (any {$_ eq 'paid' } $model->meta->columns) {
224
        $additional_where{amount} = { gt => \'paid' };
225
      }
226
    }
227
    my $records_of_type = $manager->get_all(
228
      where => [
229
        $manager->type_filter($record_type),
230
        %additional_where,
231
      ],
232
    );
233
    push @records, @$records_of_type;
234
  }
235

  
236
  return @records;
237
}
238

  
175 239
sub action_attachment_preview {
176 240
  my ($self) = @_;
177 241

  
......
249 313
  my $customer_vendor    = $::form->{customer_vendor_selection};
250 314
  my $customer_vendor_id = $::form->{"${customer_vendor}_id"};
251 315
  my $action             = $::form->{action_selection};
252
  my $record_type        = $::form->{"${customer_vendor}_record_type_selection"};
253
  my $record_id          = $::form->{"${record_type}_id"};
316
  my $record_type_id     = $::form->{"record_type_id"};
317
  die t8("No record is selected.") unless $record_type_id || $action eq 'create_new';
318

  
319
  die "no 'email_journal_id' was given"          unless $email_journal_id;
320
  die "no 'customer_vendor_selection' was given" unless $customer_vendor;
321
  die "no 'action_selection' was given"          unless $action;
322

  
323
  my ($record_type, $record_id) = split(/-/, $record_type_id);
254 324

  
255 325
  if ($action eq 'linking') {
256 326
    return $self->link_and_add_attachment_to_record({
......
299 369
    ->render();
300 370
}
301 371

  
372
sub action_update_record_list {
373
  my ($self) = @_;
374
  $::auth->assert('email_journal');
375
  my $customer_vendor_type = $::form->{customer_vendor_selection};
376
  my $customer_vendor_id = $::form->{"${customer_vendor_type}_id"};
377
  my $record_type = $::form->{"${customer_vendor_type}_record_type_selection"};
378
  my $with_closed = $::form->{with_closed};
379

  
380
  $record_type ||= $self->record_types_for_customer_vendor_type($customer_vendor_type);
381

  
382
  my @records = $self->get_records_for_types(
383
    $record_type,
384
    customer_vendor_type => $customer_vendor_type,
385
    customer_vendor_id   => $customer_vendor_id,
386
    with_closed          => $with_closed,
387
  );
388

  
389
  unless (@records) {
390
    $self->js->replaceWith('#record_list', div_tag(
391
      html_tag('h3', t8('No records found.')),
392
      id => 'record_list',
393
    ))->render();
394
    return;
395
  }
396

  
397
  my $new_div = div_tag(
398
    join('', map {
399
      div_tag(
400
        radio_button_tag('record_type_id',
401
        value => $_->record_type . "-" . $_->id, label => $_->displayable_name,
402
        class => "record_radio", label_class => "record_radio",
403
        ),
404
        id => "record_$_->{id}",
405
      )
406
    } @records),
407
    id => 'record_list',
408
  );
409

  
410
  $self->js->replaceWith('#record_list', $new_div)->render();
411
}
412

  
302 413
#
303 414
# filters
304 415
#
css/design40/email_journal.css
1 1
/* E-Mail-Journal */
2
.email_journal_details tbody pre {
3
  margin: 0px;
2
input.record_radio {
3
    visibility:hidden;
4
    position:absolute;
5
    float: left;
4 6
}
5

  
6
.email_journal_details tbody th {
7
  text-align: right;
8
  vertical-align: top;
7
label.record_radio {
8
    cursor: pointer;
9
    float: left;
10
    overflow: hidden;
11
    width: 200px;
12
    padding: 5px;
13
    margin: 5px;
14
    border-radius: 5px;
15
    border: 1px solid;
16
    text-align: center;
9 17
}
10

  
11
.email_journal_details tbody td {
12
  vertical-align: top;
18
input.record_radio:checked + label {
19
  background-color: var(--color-lighter);
13 20
}
js/kivi.EmailJournal.js
26 26
      $('#vendor_div').show();
27 27
      $('#vendor_record_types_div').show();
28 28
    }
29
    kivi.EmailJournal.update_record_type_selection(customer_vendor);
29
    kivi.EmailJournal.update_record_list();
30 30
  }
31 31

  
32 32
  ns.update_action_selection = function() {
33 33
    let record_action = $('#action_selection').val();
34 34

  
35
    $('#record_type_div').hide();
36
    $('#no_record_type_div').hide();
35
    $('#record_div').hide();
36
    $('#no_record_div').hide();
37 37

  
38 38
    if (record_action == 'create_new') {
39
      $('#no_record_type_div').show();
39
      $('#no_record_div').show();
40 40
    } else {
41
      $('#record_type_div').show();
41
      $('#record_div').show();
42 42
    }
43 43
  }
44 44

  
45
  ns.update_record_type_selection = function(customer_vendor) {
46
    let record_type = $('#' + customer_vendor + '_record_type_selection').val();
45
  ns.update_record_list = function() {
46
    let $form = $('#record_action_form');
47 47

  
48
    $('.record_type').hide();
49
    if (record_type != '') {
50
      $('#' + record_type + '_div').show();
51
    } else {
52
      $('#record_type_placeholder_div').show();
53
    }
48
    let data = $form.serializeArray();
49
    data.push({ name: 'action', value: 'EmailJournal/update_record_list' });
50

  
51
    $.post("controller.pl", data, kivi.eval_json_result);
54 52
  }
55 53

  
56 54
  ns.apply_action_with_attachment = function() {
templates/design40_webpages/email_journal/show.html
91 91
           cv_type _ "_id",
92 92
           CUSTOMER_VENDOR.is_customer == cv_is_cusotmer ? CUSTOMER_VENDOR : undef,
93 93
           type=cv_type, class="wi-normal", placeholder=LxERP.t8(cv_name)
94
           onchange='kivi.EmailJournal.update_record_list();'
94 95
           ) %]
95 96
    </div>
96 97
    [% END %]
......
126 127
       value_key='value', title_key='name',
127 128
       with_empty=1, empty_value='', empty_title=LxERP.t8("Select record type"),
128 129
       class="wi-normal",
129
       onchange='kivi.EmailJournal.update_record_type_selection("' _ customer_vendor _ '");'
130
       onchange='kivi.EmailJournal.update_record_list();'
130 131
       ) %]
131 132
    </div>
132 133
    [% END %]
133 134

  
134
    <div id="record_type_div" class="col" style="display:block">
135
      [% FOREACH record_info = RECORD_TYPES_WITH_INFO %]
136
      <div id="[% record_info.record_type _ "_div" %]" class="col record_type" style="display:none">
137
        [% L.input_tag(record_info.record_type _ "_id", '',
138
             style="color:black", class="wi-normal",
139
             placeholder=record_info.record_type _ " id") %]
140
      </div>
141
      [% END %]
142
      <div id="record_type_placeholder_div" class="col record_type" style="display:block">
143
        [% L.input_tag('cv_placeholder', '',
144
             style="color:black", class="wi-normal", disabled=1,
145
             placeholder=LxERP.t8("Select record type first"),
146
             ) %]
147
      </div>
148
    </div>
149
    <div id="no_record_type_div" class="col" style="display:none">
150
      [% L.input_tag('cv_placeholder', '',
151
           style="color:black", class="wi-normal", disabled=1,
152
           placeholder=LxERP.t8("No record needed"),
153
           ) %]
135
    <div id="with_closed_div" class="col">
136
      [% L.select_tag('with_closed',
137
         [
138
           {value => "1", name => LxERP.t8("With closed")},
139
           {value => "0", name => LxERP.t8("Only open")},
140
         ],
141
         default = 0, value_key='value', title_key='name',
142
         class="wi-small",
143
         onchange='kivi.EmailJournal.update_record_list();'
144
         ) %]
154 145
    </div>
155 146

  
147

  
156 148
    <div class="col">
157 149
      [% L.button_tag('kivi.EmailJournal.apply_action_with_attachment();', LxERP.t8('Apply with Attachment')) %]
158 150
    </div>
159 151
  </div> <!-- action_div -->
152

  
153
  [% BLOCK panel_1 %]
154
      <div id="record_div">
155
        <div id="record_list">
156
        [% FOREACH record = RECORDS %]
157
          <div id="record_[% record.id %]">
158
            [% L.radio_button_tag('record_type_id', class="record_radio",
159
                value=record.record_type _ '-' _ record.id,
160
                label_class="record_radio", label=record.displayable_name) %]
161
          </div>
162
        [% END %]
163
        [% IF RECORDS.size == 0 %]
164
          <div id="no_record_div">
165
            <h3> [% LxERP.t8("No records found.") %] </h3>
166
          </div>
167
        [% END %]
168
      </div>
169
    </div>
170
    <div id="no_record_div" class="col" style="display:none">
171
      <h3> [% LxERP.t8("No record needed.") %] </h3>
172
    </div>
173
  [% END %]
174
  [% SET display_status = (RECORDS.size > 20 ? 'closed' : 'open');
175
     INCLUDE 'common/toggle_panel.html'
176
      block_name='panel_1'
177
      button_closed  = LxERP.t8('Show Records')
178
      button_open    = LxERP.t8('Hide Records')
179
      ;
180
  %]
160 181
</form>
161 182

  
162 183
<!-- kivi.EmailJournal.update_attachment_preview -->

Auch abrufbar als: Unified diff