]> wagnertech.de Git - kivitendo-erp.git/commitdiff
Neuen Artikeltyp Sortiment in kivitendo eingebaut
authorG. Richardson <information@kivitendo-premium.de>
Sun, 7 Aug 2016 20:34:31 +0000 (22:34 +0200)
committerG. Richardson <information@kivitendo-premium.de>
Tue, 22 Nov 2016 13:11:25 +0000 (14:11 +0100)
* eigenen TopQuickSearch
* eigener Nummernkreis
* Links und Menüeinträge gehen zu neuen Part Controller

SL/Controller/TopQuickSearch.pm
SL/Controller/TopQuickSearch/Article.pm
SL/Controller/TopQuickSearch/Assortment.pm [new file with mode: 0644]
SL/DB/Helper/TransNumberGenerator.pm
SL/DB/Manager/Part.pm
SL/DB/Part.pm
SL/Presenter/Part.pm
SL/TransNumber.pm
bin/mozilla/ic.pl
locale/de/all
menus/user/00-erp.yaml

index 7a014302126652ee3870e04eba64429716bcfa63..c3ad7f37abcc898b32630d244ba64230b82c0045 100644 (file)
@@ -16,6 +16,7 @@ my @available_modules = (
   'SL::Controller::TopQuickSearch::Part',
   'SL::Controller::TopQuickSearch::Service',
   'SL::Controller::TopQuickSearch::Assembly',
+  'SL::Controller::TopQuickSearch::Assortment',
   'SL::Controller::TopQuickSearch::Contact',
   'SL::Controller::TopQuickSearch::SalesQuotation',
   'SL::Controller::TopQuickSearch::SalesOrder',
index b0a28e00bf27cb9d9732e735a8575327cd89adda..f3fc1acbef25b4c2f0c1be30918dbc1d265e7cc8 100644 (file)
@@ -64,8 +64,8 @@ sub redirect_to_part {
   my ($self, $term) = @_;
 
   SL::Controller::Base->new->url_for(
-    controller => 'ic.pl',
-    action     => 'edit',
+    controller => 'controller.pl',
+    action     => 'Part/edit',
     id         => $term,
   );
 }
diff --git a/SL/Controller/TopQuickSearch/Assortment.pm b/SL/Controller/TopQuickSearch/Assortment.pm
new file mode 100644 (file)
index 0000000..9de5b84
--- /dev/null
@@ -0,0 +1,16 @@
+package SL::Controller::TopQuickSearch::Assortment;
+
+use strict;
+use parent qw(SL::Controller::TopQuickSearch::Article);
+
+use SL::Locale::String qw(t8);
+
+sub name { 'assortment' }
+
+sub description_config { t8('Assortment') }
+
+sub description_field { t8('Assortment') }
+
+sub part_type { 'assortment' }
+
+1;
index 9c657293bc9b36150584cf5f35e4658ae50f4a51..fab4a7c0015d87ec6f0b1ee13c3411544c07862b 100644 (file)
@@ -35,6 +35,7 @@ my %specs = ( ar                      => { number_column => 'invnumber',
               part                    => { number_column => 'partnumber',     number_range_column => 'articlenumber',  scoping => \&parts_scoping, },
               service                 => { number_column => 'partnumber',     number_range_column => 'servicenumber',  scoping => \&parts_scoping, },
               assembly                => { number_column => 'partnumber',     number_range_column => 'assemblynumber', scoping => \&parts_scoping, },
+              assortment              => { number_column => 'partnumber',     number_range_column => 'assortmentnumber', scoping => \&parts_scoping, },
             );
 
 sub get_next_trans_number {
@@ -97,7 +98,7 @@ sub get_next_trans_number {
   my $range_table    = ($business ? $business : SL::DB::Default->get)->load(for_update => 1);
 
   my $start_number   = $range_table->$number_range_column;
-  $start_number      = $range_table->articlenumber if ($number_range_column eq 'assemblynumber') && (length($start_number) < 1);
+  $start_number      = $range_table->articlenumber if ($number_range_column =~ /^(assemblynumber|assortmentnumber)$/) && (length($start_number) < 1);
   my $sequence       = SL::PrefixedNumber->new(number => $start_number // 0);
 
   if (!$fill_holes_in_range) {
index b94d7f443abc4300cd7f062685807605f32a0513..088d4c838c63789ee373890675aa03498f3dc832 100644 (file)
@@ -48,6 +48,8 @@ sub type_filter {
       push @filter, ($prefix . part_type => 'service');
     } elsif ($type =~ m/^assembly/) {
       push @filter, ($prefix . part_type => 'assembly');
+    } elsif ($type =~ m/^assortment/) {
+      push @filter, ($prefix . part_type => 'assortment');
     }
   }
 
index 8b149ad4c0e0b646d89554bc8e35ffd2148f3ee5..d336af38d088c77b943fffee0359619816b17711 100644 (file)
@@ -61,14 +61,15 @@ sub _before_save_set_partnumber {
 sub is_type {
   my $self = shift;
   my $type  = lc(shift || '');
-  die 'invalid type' unless $type =~ /^(?:part|service|assembly)$/;
+  die 'invalid type' unless $type =~ /^(?:part|service|assembly|assortment)$/;
 
   return $self->type eq $type ? 1 : 0;
 }
 
-sub is_part     { $_[0]->part_type eq 'part' }
-sub is_assembly { $_[0]->part_type eq 'assembly' }
-sub is_service  { $_[0]->part_type eq 'service' }
+sub is_part       { $_[0]->part_type eq 'part'       }
+sub is_assembly   { $_[0]->part_type eq 'assembly'   }
+sub is_service    { $_[0]->part_type eq 'service'    }
+sub is_assortment { $_[0]->part_type eq 'assortment' }
 
 sub type {
   return $_[0]->part_type;
@@ -99,6 +100,11 @@ sub new_service {
   $class->new(%params, part_type => 'service');
 }
 
+sub new_assortment {
+  my ($class, %params) = @_;
+  $class->new(%params, part_type => 'assortment');
+}
+
 sub orphaned {
   my ($self) = @_;
   die 'not an accessor' if @_ > 1;
@@ -107,6 +113,8 @@ sub orphaned {
     SL::DB::InvoiceItem
     SL::DB::OrderItem
     SL::DB::Inventory
+    SL::DB::Assembly
+    SL::DB::AssortmentItem
   );
 
   for my $class (@relations) {
@@ -245,13 +253,15 @@ flavours called:
 
 =item Assembly - a collection of both parts and services
 
+=item Assortment - a collection of parts
+
 =back
 
 These types are sadly represented by data inside the class and cannot be
 migrated into a flag. To work around this, each C<Part> object knows what type
 it currently is. Since the type is data driven, there ist no explicit setting
 method for it, but you can construct them explicitly with C<new_part>,
-C<new_service>, and C<new_assembly>. A Buchungsgruppe should be supplied in this
+C<new_service>, C<new_assembly> and C<new_assortment>. A Buchungsgruppe should be supplied in this
 case, but it will use the default Buchungsgruppe if you don't.
 
 Matching these there are assorted helper methods dealing with types,
index 5ec55503a0d7911c0d3b95dea3d292a3350a7a7a..f634b3fcd1cd7482fc30e20a8fe4c45106262aca 100644 (file)
@@ -17,7 +17,7 @@ sub part {
   croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;
 
   my $text = join '', (
-    $params{no_link} ? '' : '<a href="ic.pl?action=edit&id=' . $self->escape($part->id) . '">',
+    $params{no_link} ? '' : '<a href="controller.pl?action=Part/edit&id=' . $self->escape($part->id) . '">',
     $self->escape($part->partnumber),
     $params{no_link} ? '' : '</a>',
   );
index 42e85a9fdc5b2e14dee2559b9366ceba3fb1524a..bd3e7533297dd649f6d33052d7f413c3ffa548e9 100644 (file)
@@ -15,7 +15,7 @@ use Rose::Object::MakeMethods::Generic
  scalar => [ qw(type id number save dbh dbh_provided business_id) ],
 );
 
-my @SUPPORTED_TYPES = qw(invoice credit_note customer vendor sales_delivery_order purchase_delivery_order sales_order purchase_order sales_quotation request_quotation part service assembly letter);
+my @SUPPORTED_TYPES = qw(invoice credit_note customer vendor sales_delivery_order purchase_delivery_order sales_order purchase_order sales_quotation request_quotation part service assembly assortment letter);
 
 sub new {
   my $class = shift;
@@ -67,10 +67,14 @@ sub _get_filters {
     $filters{where}         = 'COALESCE(quotation, FALSE)';
     $filters{where}        .= $type =~ /^sales/ ? ' AND (customer_id IS NOT NULL)' : ' AND (vendor_id IS NOT NULL)';
 
-  } elsif ($type =~ /part|service|assembly/) {
+  } elsif ($type =~ /^(part|service|assembly|assortment)$/) {
     $filters{trans_number}  = "partnumber";
-    $filters{numberfield}   = $type eq 'service' ? 'servicenumber' : 'articlenumber';
-    $filters{numberfield}   = $type eq 'assembly' ? 'assemblynumber' : $filters{numberfield};
+    my %numberfield_hash = ( service    => 'servicenumber',
+                             assembly   => 'assemblynumber',
+                             assortment => 'assortmentnumber',
+                             part       => 'articlenumber'
+                           );
+    $filters{numberfield}   = $numberfield_hash{$type};
     $filters{table}         = "parts";
   } elsif ($type =~ /letter/) {
     $filters{trans_number}  = "letternumber";
index 0405aa0511c6c1911d1fba0530a2e65141be9502..08dc40db0fc10d3e83953e3997d98534d01e0599 100644 (file)
@@ -590,7 +590,7 @@ sub generate_report {
       $soldtotal                  = 0 if ($form->{sold});
     }
 
-    my $edit_link               = build_std_url('action=edit', 'id=' . E($ref->{id}), 'callback');
+    my $edit_link               = build_std_url('script=controller.pl', 'action=Part/edit', 'id=' . E($ref->{id}), 'callback');
     $row->{partnumber}->{link}  = $edit_link;
     $row->{description}->{link} = $edit_link;
 
index 9c662f81501685b843e90dce8fdedab17f6616be..d9dbc2fa3925c582ae1cb5aaf3894696984b9507 100755 (executable)
@@ -147,6 +147,7 @@ $self->{texts} = {
   'Add Accounts Payables Transaction' => 'Kreditorenbuchung erfassen',
   'Add Accounts Receivables Transaction' => 'Debitorenbuchung erfassen',
   'Add Assembly'                => 'Erzeugnis erfassen',
+  'Add Assortment'              => 'Sortiment erfassen',
   'Add Client'                  => 'Neuer Mandant',
   'Add Credit Note'             => 'Gutschrift erfassen',
   'Add Customer'                => 'Kunde erfassen',
@@ -312,6 +313,9 @@ $self->{texts} = {
   'Assigned invoices'           => 'Zugewiesene Rechnungen',
   'Assignment of articles to sections' => 'Zuweisung von Artikeln zu Abschnitten',
   'Assistant for general ledger corrections' => 'Assistent für die Korrektur von Hauptbucheinträgen',
+  'Assortment'                  => 'Sortiment',
+  'Assortment items'            => 'Sortimentsartikel',
+  'Assortments'                 => 'Sortimente',
   'Assume Tax Consultant Data in Tax Computation?' => 'Beraterdaten in UStVA übernehmen?',
   'At least'                    => 'Mindestens',
   'At least one Perl module that kivitendo ERP requires for running is not installed on your system.' => 'Mindestes ein Perl-Modul, das kivitendo ERP zur Ausf&uuml;hrung ben&ouml;tigt, ist auf Ihrem System nicht installiert.',
@@ -1049,6 +1053,7 @@ $self->{texts} = {
   'Edit Accounts Payables Transaction' => 'Kreditorenbuchung bearbeiten',
   'Edit Accounts Receivables Transaction' => 'Debitorenbuchung bearbeiten',
   'Edit Assembly'               => 'Erzeugnis bearbeiten',
+  'Edit Assortment'             => 'Sortiment bearbeiten',
   'Edit Bins'                   => 'Lagerpl&auml;tze bearbeiten',
   'Edit Client'                 => 'Mandanten bearbeiten',
   'Edit Credit Note'            => 'Gutschrift bearbeiten',
@@ -1600,6 +1605,7 @@ $self->{texts} = {
   'Languages and translations'  => 'Sprachen und Übersetzungen',
   'Last Article Number'         => 'Letzte Artikelnummer',
   'Last Assembly Number'        => 'Letzte Erzeugnisnummer',
+  'Last Assortment Number'      => 'Letzte Sortimentsnummer',
   'Last Cost'                   => 'Einkaufspreis',
   'Last Credit Note Number'     => 'Letzte Gutschriftnummer',
   'Last Customer Number'        => 'Letzte Kundennummer',
@@ -2813,6 +2819,7 @@ $self->{texts} = {
   'The application "#1" was not found on the system.' => 'Die Anwendung "#1" wurde auf dem System nicht gefunden.',
   'The assembly has been created.' => 'Das Erzeugnis wurde hergestellt.',
   'The assistant could not find anything wrong with #1. Maybe the problem has been solved in the meantime.' => 'Der Korrekturassistent konnte kein Problem bei #1 feststellen. Eventuell wurde das Problem in der Zwischenzeit bereits behoben.',
+  'The assortment doesn\'t have any items.' => 'Das Sortiment enthält keine Artikel.',
   'The authentication database is not reachable at the moment. Either it hasn\'t been set up yet or the database server might be down. Please contact your administrator.' => 'Die Authentifizierungs-Datenbank kann momentan nicht erreicht werden. Entweder wurde sie noch nicht eingerichtet, oder der Datenbankserver ist momentan nicht verfügbar. Bitte wenden Sie sich an Ihren Administrator.',
   'The available options depend on the varibale type:' => 'Die verf&uuml;gbaren Optionen h&auml;ngen vom Variablentypen ab:',
   'The background job could not be destroyed.' => 'Der Hintergrund-Job konnte nicht gelöscht werden.',
index 1900d6267b884f291505ee17dc449a544a49fc46..8d8741fcafca4a9210cb96078b33c78158e3c9a3 100644 (file)
   icon: part_add
   order: 300
   access: part_service_assembly_edit
-  module: ic.pl
   params:
-    action: add
-    part_type: part
+    action: Part/add_part
 - parent: master_data
   id: master_data_add_service
   name: Add Service
   icon: service_add
   order: 400
   access: part_service_assembly_edit
-  module: ic.pl
   params:
-    action: add
-    part_type: service
+    action: Part/add_service
 - parent: master_data
   id: master_data_add_assembly
   name: Add Assembly
   icon: assembly_add
   order: 500
   access: part_service_assembly_edit
-  module: ic.pl
   params:
-    action: add
-    part_type: assembly
+    action: Part/add_assembly
+- parent: master_data
+  id: master_data_add_assortment
+  name: Add Assortment
+  icon: assortment_add
+  order: 550
+  access: part_service_assembly_edit
+  params:
+    action: Part/add_assortment
 - parent: master_data
   id: master_data_add_project
   name: Add Project
   params:
     action: search
     searchitems: assembly
+- parent: master_data_reports
+  id: master_data_reports_assortments
+  name: Assortments
+  icon: assortment_report
+  order: 650
+  access: part_service_assortment_details
+  module: ic.pl
+  params:
+    action: search
+    searchitems: assortment
 - parent: master_data_reports
   id: master_data_reports_projects
   name: Projects