Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision db7a2e79

Von Sven Schöling vor mehr als 8 Jahren hinzugefügt

  • ID db7a2e79d8f43e94709f9fe56d30d8cda23e856a
  • Vorgänger 25117316
  • Nachfolger 2fe91d5d

Briefe: Lieferantenbriefe

Unterschiede anzeigen:

SL/Controller/Letter.pm
23 23
use SL::Webdav::File;
24 24

  
25 25
use Rose::Object::MakeMethods::Generic (
26
  'scalar --get_set_init' => [ qw(letter all_employees models webdav_objects) ],
26
  'scalar --get_set_init' => [ qw(letter all_employees models webdav_objects is_sales) ],
27 27
);
28 28

  
29 29
__PACKAGE__->run_before('check_auth_edit');
......
37 37
  subject               => t8('Subject'),
38 38
  letternumber          => t8('Letternumber'),
39 39
  customer_id           => t8('Customer'),
40
  vendor_id             => t8('Vendor'),
40 41
  contact               => t8('Contact'),
41 42
);
42 43

  
44
### actions
45

  
43 46
sub action_add {
44 47
  my ($self, %params) = @_;
45 48

  
......
60 63
  return $self->action_add
61 64
    unless $::form->{letter} || $::form->{draft};
62 65

  
63
  $self->letter(SL::DB::Letter->new_from_draft($::form->{draft}{id}))
64
    if $::form->{draft};
66
  if ($::form->{draft}) {
67
    $self->letter(SL::DB::Letter->new_from_draft($::form->{draft}{id}));
68
    $self->is_sales($self->letter->is_sales);
69
  }
65 70

  
66 71
  $self->_display(
67 72
    title  => t8('Edit Letter'),
......
94 99

  
95 100
  my $letter = $self->letter;
96 101

  
97
  if (!$self->letter->customer_id || !$self->letter->customer) {
102
  if (!$self->letter->has_customer_vendor) {
98 103
    return $self->js
99 104
      ->replaceWith(
100 105
        '#letter_cp_id',
......
103 108
      ->render;
104 109
  }
105 110

  
106
  my $contacts = $letter->customer->contacts;
111
  my $contacts = $letter->customer_vendor->contacts;
107 112

  
108 113
  my $default;
109 114
  if (   $letter->contact
110 115
      && $letter->contact->cp_cv_id
111
      && $letter->contact->cp_cv_id == $letter->customer_id) {
116
      && $letter->contact->cp_cv_id == $letter->customer_vendor_id) {
112 117
    $default = $letter->contact->cp_id;
113 118
  } else {
114 119
    $default = '';
......
336 341
  );
337 342
}
338 343

  
344
### internal methods
345

  
339 346
sub _display {
340 347
  my ($self, %params) = @_;
341 348

  
......
346 353
 $params{title} ||= t8('Edit Letter');
347 354

  
348 355
  $::form->{type}             = 'letter';   # needed for print_options
349
  $::form->{vc}               = 'customer'; # needs to be for _get_contacts...
356
  $::form->{vc}               = $letter->is_sales ? 'customer' : 'vendor'; # needs to be for _get_contacts...
350 357

  
351 358
  $::request->layout->add_javascripts('customer_or_vendor_selection.js');
352 359
  $::request->layout->add_javascripts('edit_part_window.js');
......
386 393
  my $report      = SL::ReportGenerator->new(\%::myconfig, $::form);
387 394
  $self->{report} = $report;
388 395

  
389
  my @columns  = qw(date subject letternumber customer_id contact date);
390
  my @sortable = qw(date subject letternumber customer_id contact date);
396
  my @columns  = qw(date subject letternumber customer_id vendor_id contact date);
397
  my @sortable = qw(date subject letternumber customer_id vendor_id contact date);
391 398

  
392 399
  my %column_defs = (
393 400
    date                  => { text => t8('Date'),         sub => sub { $_[0]->date_as_date } },
......
395 402
                               obj_link => sub { $self->url_for(action => 'edit', 'letter.id' => $_[0]->id, callback => $self->models->get_callback) }  },
396 403
    letternumber          => { text => t8('Letternumber'), sub => sub { $_[0]->letternumber },
397 404
                               obj_link => sub { $self->url_for(action => 'edit', 'letter.id' => $_[0]->id, callback => $self->models->get_callback) }  },
398
    customer_id           => { text => t8('Customer'),      sub => sub { SL::DB::Manager::Customer->find_by_or_create(id => $_[0]->customer_id)->displayable_name } },
405
    customer_id           => { text => t8('Customer'),      sub => sub { SL::DB::Manager::Customer->find_by_or_create(id => $_[0]->customer_id)->displayable_name }, visible => $self->is_sales },
406
    vendor_id             => { text => t8('Vendor'),        sub => sub { SL::DB::Manager::Vendor->find_by_or_create(id => $_[0]->vendor_id)->displayable_name }, visible => !$self->is_sales},
399 407
    contact               => { text => t8('Contact'),       sub => sub { $_[0]->contact ? $_[0]->contact->full_name : '' } },
400 408
  );
401 409

  
......
413 421

  
414 422
  $report->set_columns(%column_defs);
415 423
  $report->set_column_order(@columns);
416
  $report->set_export_options(qw(list filter));
424
  $report->set_export_options(qw(list filter is_sales));
417 425
  $report->set_options_from_form;
418 426

  
419 427
  $self->models->disable_plugin('paginated') if $report->{options}{output_format} =~ /^(pdf|csv)$/i;
428
  $self->models->add_additional_url_params(is_sales => $self->is_sales);
420 429
  $self->models->finalize;
421 430
  $self->models->set_report_generator_sort_options(report => $report, sortable_columns => \@sortable);
422 431

  
......
465 474

  
466 475
  return 0 if $params{skip_drafts};
467 476

  
468
  my $letter_drafts = SL::DB::Manager::LetterDraft->get_all;
477
  my $letter_drafts = SL::DB::Manager::LetterDraft->get_all(
478
    query => [
479
      SL::DB::Manager::Letter->is_sales_filter($self->is_sales),
480
    ]
481
  );
469 482

  
470 483
  return unless @$letter_drafts;
471 484

  
......
552 565
                                           ->assign_attributes(%{ $::form->{letter} });
553 566

  
554 567
  if ($letter->cp_id) {
555
#     $letter->customer_id($letter->contact->cp_cv_id);
568
#     $letter->customer_vendor_id($letter->contact->cp_cv_id);
556 569
      # contacts don't have language_id yet
557 570
#     $letter->greeting(GenericTranslations->get(
558 571
#       translation_type => 'greetings::' . ($letter->contact->cp_gender eq 'f' ? 'female' : 'male'),
......
561 574
#     ));
562 575
  }
563 576

  
577
  $self->is_sales($letter->is_sales);
578

  
564 579
  $letter;
565 580
}
566 581

  
......
570 585
  SL::Controller::Helper::GetModels->new(
571 586
    controller   => $self,
572 587
    model        => 'Letter',
588
    query        => [
589
      SL::DB::Manager::Letter->is_sales_filter($self->is_sales),
590
    ],
573 591
    sorted       => \%sort_columns,
574 592
    with_objects => [ 'contact', 'salesman', 'employee' ],
575 593
  );
......
600 618
  } @all_objects ];
601 619
}
602 620

  
621
sub init_is_sales {
622
  die 'is_sales must be set' unless defined $::form->{is_sales};
623
  $::form->{is_sales};
624
}
625

  
603 626
sub check_auth_edit {
604 627
  $::auth->assert('sales_letter_edit');
605 628
}
......
622 645

  
623 646
Simple letter CRUD controller with drafting capabilities.
624 647

  
625
=head1 TODO
626

  
627
  Customer/Vendor switch for dealing with vendor letters
628

  
629 648
copy to webdav is crap
630 649

  
631
customer/vendor stuff
632

  
633 650
=head1 AUTHOR
634 651

  
635 652
Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
SL/DB/Letter.pm
28 28
  $self;
29 29
}
30 30

  
31
sub is_sales {
32
  die 'not an accessor' if @_ > 1;
33
  $_[0]{customer_id} * 1;
34
}
35

  
36
sub has_customer_vendor {
37
  my ($self) = @_;
38
  die 'not an accessor' if @_ > 1;
39

  
40
  return $self->is_sales
41
    ? ($self->customer_id && $self->customer)
42
    : ($self->vendor_id   && $self->vendor);
43
}
44

  
45
sub customer_vendor {
46
  die 'not an accessor' if @_ > 1;
47
  $_[0]->is_sales ? $_[0]->customer : $_[0]->vendor;
48
}
49

  
50
sub customer_vendor_id {
51
  die 'not an accessor' if @_ > 1;
52
  $_[0]->customer_id || $_[0]->vendor_id;
53
}
54

  
31 55
1;
SL/DB/Manager/Letter.pm
12 12
sub object_class { 'SL::DB::Letter' }
13 13

  
14 14
__PACKAGE__->make_manager_methods;
15
__PACKAGE__->add_filter_specs(
16
  is_sales => sub {
17
    my ($key, $value, $prefix) = @_;
18
    __PACKAGE__->is_sales_filter($value, $prefix);
19
  },
20
);
21

  
22
sub is_sales_filter {
23
  my ($class, $value, $prefix) = @_;
24

  
25
  return () if !defined $value;
26
  return ($prefix . 'customer_id' => { gt => 0 }) if $value;
27
  return ($prefix . 'vendor_id'   => { gt => 0 }) if !$value;
28
}
15 29

  
16 30
sub _sort_spec {
17 31
  return ( columns => { SIMPLE    => 'ALL',
SL/DB/MetaSetup/Letter.pm
11 11
__PACKAGE__->meta->columns(
12 12
  body         => { type => 'text' },
13 13
  cp_id        => { type => 'integer' },
14
  customer_id  => { type => 'integer', not_null => 1 },
14
  customer_id  => { type => 'integer' },
15 15
  date         => { type => 'date' },
16 16
  employee_id  => { type => 'integer' },
17 17
  greeting     => { type => 'text' },
......
23 23
  reference    => { type => 'text' },
24 24
  salesman_id  => { type => 'integer' },
25 25
  subject      => { type => 'text' },
26
  vendor_id    => { type => 'integer' },
26 27
);
27 28

  
28 29
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
......
49 50
    class       => 'SL::DB::Employee',
50 51
    key_columns => { salesman_id => 'id' },
51 52
  },
53

  
54
  vendor => {
55
    class       => 'SL::DB::Vendor',
56
    key_columns => { vendor_id => 'id' },
57
  },
52 58
);
53 59

  
54 60
1;
SL/DB/MetaSetup/LetterDraft.pm
11 11
__PACKAGE__->meta->columns(
12 12
  body         => { type => 'text' },
13 13
  cp_id        => { type => 'integer' },
14
  customer_id  => { type => 'integer', not_null => 1 },
14
  customer_id  => { type => 'integer' },
15 15
  date         => { type => 'date' },
16 16
  employee_id  => { type => 'integer' },
17 17
  greeting     => { type => 'text' },
......
23 23
  reference    => { type => 'text' },
24 24
  salesman_id  => { type => 'integer' },
25 25
  subject      => { type => 'text' },
26
  vendor_id    => { type => 'integer' },
26 27
);
27 28

  
28 29
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
......
49 50
    class       => 'SL::DB::Employee',
50 51
    key_columns => { salesman_id => 'id' },
51 52
  },
53

  
54
  vendor => {
55
    class       => 'SL::DB::Vendor',
56
    key_columns => { vendor_id => 'id' },
57
  },
52 58
);
53 59

  
54 60
1;
doc/UPGRADE
19 19
  das auf dem Zielsystem absolut nicht möglich ist, muss das Upgradescript
20 20
  sql/Pg-Upgrade2/trigram_indices.sql deaktiviert oder entfernt werden.
21 21

  
22
* Für das neue Feature Lieferantenbriefe ist die Standardvorlage für Briefe
23
  (letter.tex) angepasst worden. Statt letter.customer muss der Adressat jetzt
24
  aus letter.custoemr_vendor erzeugt werden.
25

  
22 26

  
23 27
Upgrade auf v3.4.1
24 28
==================
doc/changelog
15 15
  - Neues Recht "Verknüpfte Belege", standardmäßig erlaubt. Betrifft alle
16 16
    Belege und die Projektstammdaten
17 17

  
18
  - Briefe sind jetzt auch für Lieferanten verfügbar. Die neuen Rechte dafür
19
    sind für Gruppen vergeben, die auch Einkaufsbelege bearbeiten dürfen.
20

  
18 21
Administrative Änderungen
19 22

  
20 23
  - Diverse Textsuchen werden jetzt durch eine neue Klasse Indizes
locale/de/all
1089 1089
  'Edit project link'           => 'Projektverknüpfung bearbeiten',
1090 1090
  'Edit project status'         => 'Projektstatus bearbeiten',
1091 1091
  'Edit project type'           => 'Projekttypen bearbeiten',
1092
  'Edit purchase letters'       => 'Einkaufsbrief erstellen',
1092 1093
  'Edit purchase price rule'    => 'Einkaufspreisregel bearbeiten',
1093 1094
  'Edit requirement spec'       => 'Pflichtenheft bearbeiten',
1094 1095
  'Edit requirement spec status' => 'Pflichtenheftstatus bearbeiten',
......
2544 2545
  'Show overdue sales quotations and requests for quotations...' => 'Überfällige Angebote und Preisanfragen anzeigen...',
2545 2546
  'Show parts'                  => 'Artikel anzeigen',
2546 2547
  'Show parts longdescription (notes) in select list' => 'Langtext in Auswahlliste bei mehreren Treffern im Stammdaten-Bestand anzeigen',
2548
  'Show purchase letters report' => 'Einkaufsbriefe zeigen',
2547 2549
  'Show requirement spec'       => 'Pflichtenheft anzeigen',
2548 2550
  'Show requirement spec template' => 'Pflichtenheftvorlage anzeigen',
2549 2551
  'Show sales letters report'   => 'Verkaufsbrief anzeigen',
menus/user/00-erp.yaml
264 264
  access: sales_letter_edit
265 265
  params:
266 266
    action: Letter/add
267
    is_sales: 1
267 268
- parent: ar
268 269
  id: ar_invoices
269 270
  name: Invoices
......
377 378
  access: sales_letter_report
378 379
  params:
379 380
    action: Letter/list
381
    is_sales: 1
380 382
- id: ap
381 383
  name: AP
382 384
  icon: ap
......
419 421
  params:
420 422
    action: add
421 423
    type: invoice
424
- parent: ap
425
  id: ap_add_letter
426
  name: Add Letter
427
  order: 450
428
  access: purchase_letter_edit
429
  params:
430
    action: Letter/add
431
    is_sales: 0
422 432
- parent: ap
423 433
  id: ap_reports
424 434
  name: Reports
......
478 488
  params:
479 489
    action: DeliveryValueReport/list
480 490
    vc: vendor
491
- parent: ap_reports
492
  id: ap_reports_letters
493
  name: Letters
494
  order: 1100
495
  access: purchase_letter_report
496
  params:
497
    action: Letter/list
498
    is_sales: 0
481 499
- id: warehouse
482 500
  name: Warehouse
483 501
  icon: warehouse
sql/Pg-upgrade2-auth/purchase_letter_rights.pl
1
# @tag: purchase_letter_rights
2
# @description: Neue Rechte für Lieferantenbriefe
3
# @depends: release_3_2_0 sales_letter_rights
4
# @locales: Edit purchase letters
5
# @locales: Show purchase letters report
6
package SL::DBUpgrade2::purchase_letter_rights;
7

  
8
use strict;
9
use utf8;
10

  
11
use parent qw(SL::DBUpgrade2::Base);
12

  
13
use SL::DBUtils;
14

  
15
sub run {
16
  my ($self) = @_;
17

  
18
  $self->db_query("INSERT INTO auth.master_rights (position, name, description) VALUES (?, ?, ?)", bind => $_) for
19
    [ 2550, 'purchase_letter_edit',   'Edit purchase letters'        ],
20
    [ 2650, 'purchase_letter_report', 'Show purchase letters report' ];
21

  
22
  my $groups = $main::auth->read_groups();
23

  
24
  foreach my $group (values %{$groups}) {
25
    $group->{rights}->{purchase_letter_edit} = $group->{rights}->{purchase_order_edit};
26
    $group->{rights}->{purchase_letter_report} = $group->{rights}->{purchase_order_edit};
27
    $main::auth->save_group($group);
28
  }
29

  
30
  return 1;
31
} # end run
32

  
33
1;
sql/Pg-upgrade2/letter_vendorletter.sql
1
-- @tag: letter_vendorletter
2
-- @description: Briefe jetzt auch für Lieferanten
3
-- @depends: release_3_4_1
4
-- @encoding: utf-8
5

  
6
ALTER TABLE letter ALTER COLUMN customer_id DROP NOT NULL;
7
ALTER TABLE letter ADD COLUMN vendor_id INTEGER REFERENCES vendor(id);
8

  
9
ALTER TABLE letter_draft ALTER COLUMN customer_id DROP NOT NULL;
10
ALTER TABLE letter_draft ADD COLUMN vendor_id INTEGER REFERENCES vendor(id);
templates/print/RB/letter.tex
2 2
% config: tag-style=$( )$
3 3
$( USE KiviLatex )$
4 4
$( USE P )$
5
$( SET customer = letter.customer )$
5
$( SET customer = letter.customer_vendor )$
6 6
\input{inheaders.tex}
7 7
$( KiviLatex.required_packages_for_html )$
8 8

  
templates/webpages/letter/edit.html
10 10
  <input type="hidden" name="letter.id" value="[% letter.id | html %]">
11 11
  <input type="hidden" name="draft.id" value="[% draft.id | html %]">
12 12
  <input type="hidden" name="type" value="[% type | html %]">
13
  [% L.hidden_tag('is_sales', SELF.is_sales) %]
13 14

  
14 15
  [%- INCLUDE 'common/flash.html' %]
15 16

  
......
31 32
 <td width=50%>
32 33
  <!-- upper left block -->
33 34
   <table width=90%>
35
[%- IF SELF.is_sales %]
34 36
    <tr>
35 37
     <th align='right'>[% 'Customer' | $T8 %]:</th>
36 38
     <td>[% P.customer_vendor_picker('letter.customer_id', letter.customer_id, type='customer') %]
......
39 41
[%- END %]
40 42
     </td>
41 43
    </tr>
44
[%- ELSE %]
45
    <tr>
46
     <th align='right'>[% 'Vendor' | $T8 %]:</th>
47
     <td>[% P.customer_vendor_picker('letter.vendor_id', letter.vendor_id, type='vendor') %]
48
[%- IF letter.vendor_id %]
49
      <input type="button" value="[% 'Details (one letter abbreviation)' | $T8 %]" onclick="show_vc_details('vendor')">
50
[%- END %]
51
     </td>
52
    </tr>
53
[%- END %]
42 54
    <tr>
43 55
     <th align='right'>[% 'Contact Person' | $T8 %]</th>
44
     <td>[% L.select_tag('letter.cp_id', letter.customer_id ? letter.customer.contacts : [], value_key='cp_id', title_key='full_name', default=letter.cp_id) %]</td>
56
     <td>[% L.select_tag('letter.cp_id', letter.customer_vendor_id ? letter.customer_vendor.contacts : [], value_key='cp_id', title_key='full_name', default=letter.cp_id) %]</td>
45 57
    </tr>
46 58
    <tr>
47 59
     <th align='right'>[% 'Your Reference' | $T8 %]:</th>
......
167 179
      var data = $('form').serializeArray();
168 180
      data.push({ name: 'action_update_contacts', value: 1 });
169 181
      $.post('controller.pl', data, kivi.eval_json_result);
182
    });
183
    $('#letter_vendor_id').change(function(){
184
      var data = $('form').serializeArray();
185
      data.push({ name: 'action_update_contacts', value: 1 });
186
      $.post('controller.pl', data, kivi.eval_json_result);
170 187
    })
171 188
  })
172 189
</script>
templates/webpages/letter/load_drafts.html
14 14
       <th class="listheading">&nbsp;</th>
15 15
       <th class="listheading">[% 'Date' | $T8 %]</th>
16 16
       <th class="listheading">[% 'Subject' | $T8 %]</th>
17
[%- IF SELF.is_sales %]
17 18
       <th class="listheading">[% 'Customer' | $T8 %]</th>
19
[%- ELSE %]
20
       <th class="listheading">[% 'Vendor' | $T8 %]</th>
21
[%- END %]
18 22
      </tr>
19 23

  
20 24
      [% FOREACH row = LETTER_DRAFTS %]
......
22 26
        <td>[% L.checkbox_tag("ids[+]", value=row.id) %]</td>
23 27
        <td>[% row.date.to_kivitendo | html %]</td>
24 28
        <td><a href="[% SELF.url_for(action='edit', 'draft.id'=row.id) %]">[% row.subject | html %]</a></td>
29
[%- IF SELF.is_sales %]
25 30
        <td>[% row.customer.displayable_name | html %]</td>
31
[%- ELSE %]
32
        <td>[% row.vendor.displayable_name | html %]</td>
33
[%- END %]
26 34
       </tr>
27 35
      [% END %]
28 36
     </table>
......
31 39
   <tr>
32 40
    <td>
33 41
     <input type="hidden" name="action" value="Letter/dispatch">
42
     [% L.hidden_tag('is_sales', SELF.is_sales) %]
34 43
     <input type="submit" class="submit" name="action_skip_draft" value="[% 'Skip' | $T8 %]">
35 44
     <input type="submit" class="submit" name="action_delete_drafts" value="[% 'Delete drafts' | $T8 %]">
36 45
   </td>
templates/webpages/letter/search.html
17 17
   <th align='right'>[% 'Letternumber' | $T8 %]</th>
18 18
   <td>[% L.input_tag('filter.letternumber:substr::ilike', filter.letternumber_substr__ilike, style='width:250px') %]</th>
19 19
  </tr>
20
[%- IF SELF.is_sales %]
20 21
  <tr>
21 22
   <td align="right">[% 'Customer' | $T8 %]</td>
22 23
   <td>[% L.customer_vendor_picker('filter.customer_id', filter.customer_id, type='customer', style='width:250px') %]</td>
23 24
  </tr>
24

  
25
[%- ELSE %]
26
  <tr>
27
   <td align="right">[% 'Vendor' | $T8 %]</td>
28
   <td>[% L.customer_vendor_picker('filter.vendor_id', filter.vendor_id, type='vendor', style='width:250px') %]</td>
29
  </tr>
30
[%- END %]
25 31
  <tr>
26 32
   <td align="right">[% 'Contact' | $T8 %]</td>
27 33
   <td>[% L.input_tag('filter.contact.cp_name:substr::ilike', filter.contact.cp_name_substr__ilike, style='width:250px') %]</th>
......
45 51
  </tr>
46 52
 </table>
47 53

  
54
 [% L.hidden_tag('is_sales', SELF.is_sales) %]
48 55
 [% L.hidden_tag('sort_by', FORM.sort_by) %]
49 56
 [% L.hidden_tag('sort_dir', FORM.sort_dir) %]
50 57
 [% L.hidden_tag('page', FORM.page) %]

Auch abrufbar als: Unified diff