PriceSource: Featureabdeckung
authorSven Schöling <s.schoeling@linet-services.de>
Mon, 28 Jul 2014 13:29:45 +0000 (15:29 +0200)
committerSven Schöling <s.schoeling@linet-services.de>
Thu, 18 Dec 2014 15:18:21 +0000 (16:18 +0100)
- Einkaufs/Verkauf abgedeckt
- Klarere Regeln für price_from_source, available_prices und best_price
- makemodels unterstützung
- bugfixes für Rechnungen und neue Belege
- best_price jetzt getestet
- Verkäuferabhängigkeit von makemodels und pricegroup implementiert und getestet

SL/PriceSource/ALL.pm
SL/PriceSource/Makemodel.pm [new file with mode: 0644]
SL/PriceSource/MasterData.pm
SL/PriceSource/Price.pm
SL/PriceSource/Pricegroup.pm
bin/mozilla/io.pl
bin/mozilla/oe.pl
locale/de/all

index f39df0a..33a7e44 100644 (file)
@@ -3,15 +3,18 @@ package SL::PriceSource::ALL;
 use strict;
 use SL::PriceSource::Pricegroup;
 use SL::PriceSource::MasterData;
+use SL::PriceSource::Makemodel;
 
 my %price_sources_by_name = (
   master_data => 'SL::PriceSource::MasterData',
   pricegroup  => 'SL::PriceSource::Pricegroup',
+  makemodel   => 'SL::PriceSource::Makemodel',
 );
 
 my @price_sources_order = qw(
   master_data
   pricegroup
+  makemodel
 );
 
 sub all_price_sources {
diff --git a/SL/PriceSource/Makemodel.pm b/SL/PriceSource/Makemodel.pm
new file mode 100644 (file)
index 0000000..2a4f5b0
--- /dev/null
@@ -0,0 +1,57 @@
+package SL::PriceSource::Makemodel;
+
+use strict;
+use parent qw(SL::PriceSource::Base);
+
+use SL::PriceSource::Price;
+use SL::Locale::String;
+use SL::DB::MakeModel;
+use List::UtilsBy qw(min_by);
+
+sub name { 'makemodel' }
+
+sub description { t8('Makemodel Price') }
+
+sub available_prices {
+  my ($self, %params) = @_;
+
+  return () if !$self->part;
+  return () if  $self->record->is_sales;
+
+  map { $self->make_price_from_makemodel($_) }
+  grep { $_->make == $self->record->vendor_id }
+  $self->part->makemodels;
+}
+
+sub price_from_source {
+  my ($self, $source, $spec) = @_;
+
+  my $makemodel = SL::DB::Manager::MakeModel->find_by(id => $spec);
+
+  # TODO: if someone deletes the prices entry, this fails. add a fallback
+  return $self->make_price_from_makemodel($makemodel);
+
+}
+
+sub best_price {
+  my ($self, %params) = @_;
+
+  return () if $self->record->is_sales;
+
+  min_by { $_->price } $self->available_prices;
+
+}
+
+sub make_price_from_makemodel {
+  my ($self, $makemodel) = @_;
+
+  return SL::PriceSource::Price->new(
+    price        => $makemodel->lastcost,
+    spec         => $makemodel->id,
+    description  => $makemodel->model,
+    price_source => $self,
+  );
+}
+
+
+1;
index c639ccb..3f7c11d 100644 (file)
@@ -13,31 +13,59 @@ sub description { t8('Master Data') }
 sub available_prices {
   my ($self, %params) = @_;
 
-  my $part = $self->part;
+  return () unless $self->part;
 
-  return () unless $part;
-
-  # TODO: sellprice only in sales, lastcost in purchase
-  return $self->make_sellprice($part);
+  grep { $_->price > 0 } $self->record->is_sales
+    ? ($self->make_sellprice, $self->make_listprice)
+    : ($self->make_lastcost,  $self->make_listprice);
 }
 
 sub price_from_source {
   my ($self, $source, $spec) = @_;
 
-  if ($spec eq 'sellprice') {
-    return $self->make_sellprice($self->part);
-  }
+    $spec eq 'sellprice' ? $self->make_sellprice
+  : $spec eq 'lastcost'  ? $self->make_lastcost
+  : $spec eq 'listprice' ? $self->make_listprice
+  : do { die "unknown spec '$spec'" };
+}
+
+sub best_price {
+  $_[0]->record->is_sales
+  ? $_[0]->make_sellprice
+  : $_[0]->make_lastcost
 }
 
 sub make_sellprice {
-  my ($self, $part) = @_;
+  my ($self) = @_;
 
   return SL::PriceSource::Price->new(
-    price        => $part->sellprice,
+    price        => $self->part->sellprice,
     spec         => 'sellprice',
     description  => t8('Sellprice'),
     price_source => $self,
   );
 }
 
+sub make_listprice {
+  my ($self) = @_;
+
+  return SL::PriceSource::Price->new(
+    price        => $self->part->listprice,
+    spec         => 'listprice',
+    description  => t8('List Price'),
+    price_source => $self,
+  );
+}
+
+sub make_lastcost {
+  my ($self) = @_;
+
+  return SL::PriceSource::Price->new(
+    price        => $self->part->lastcost,
+    spec         => 'lastcost',
+    description  => t8('Lastcost'),
+    price_source => $self,
+  );
+}
+
 1;
index 0a8fc4f..593c5ff 100644 (file)
@@ -8,6 +8,11 @@ use Rose::Object::MakeMethods::Generic (
   array => [ qw(depends_on) ]
 );
 
+use SL::DB::Helper::Attr;
+SL::DB::Helper::Attr::make(__PACKAGE__,
+  price => 'numeric(15,5)',
+);
+
 sub source {
   $_[0]->price_source
   ?  $_[0]->price_source->name . '/' . $_[0]->spec
@@ -22,4 +27,8 @@ sub full_description {
     : $self->description
 }
 
+sub to_str {
+  "source: @{[ $_[0]->source ]}, price: @{[ $_[0]->price]}, description: @{[ $_[0]->description ]}"
+}
+
 1;
index b1c75f8..127ec66 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use parent qw(SL::PriceSource::Base);
 
 use SL::PriceSource::Price;
+use SL::DB::Price;
 use SL::Locale::String;
 use List::UtilsBy qw(min_by);
 use List::Util qw(first);
@@ -15,6 +16,8 @@ sub description { t8('Pricegroup') }
 sub available_prices {
   my ($self, %params) = @_;
 
+  return () unless $self->record->is_sales;
+
   my $item = $self->record_item;
 
   my $prices = SL::DB::Manager::Price->get_all(
@@ -33,23 +36,25 @@ sub available_prices {
 sub price_from_source {
   my ($self, $source, $spec) = @_;
 
-  my $price = SL::DB::Manager::Price->find_by(id => $spec);
+  my $price = SL::DB::Manager::Price->find_by(pricegroup_id => $spec, parts_id => $self->part->id);
 
+  # TODO: if someone deletes the prices entry, this fails. add a fallback
   return $self->make_price($price);
 }
 
 sub best_price {
   my ($self, %params) = @_;
 
-  my @prices    = $self->availabe_prices;
+  return () unless $self->record->is_sales;
+
+  my @prices    = $self->available_prices;
   my $customer  = $self->record->customer;
-  my $min_price = min_by { $_->price } @prices;
 
-  return $min_price if !$customer || !$customer->cv_klass;
+  return () if !$customer || !$customer->klass;
 
-  my $best_price = first { $_->spec == $customer->cv_class } @prices;
+  my $best_price = first { $_->spec == $customer->klass } @prices;
 
-  return $best_price || $min_price;
+  return $best_price || ();
 }
 
 sub make_price {
@@ -57,7 +62,7 @@ sub make_price {
 
   SL::PriceSource::Price->new(
     price        => $price_obj->price,
-    spec         => $price_obj->id,
+    spec         => $price_obj->pricegroup->id,
     description  => $price_obj->pricegroup->pricegroup,
     price_source => $self,
   )
index 49e3528..c7a06af 100644 (file)
@@ -234,7 +234,7 @@ sub display_row {
       $form->{"sellprice_$i"} = $form->{"price_new_$i"};
     }
 
-    my $record_item = $record->items->[$i-1];
+    my $record_item = $record->id && $record->items ? $record->items->[$i-1] : _make_record_item($i);
 
 # unit begin
     $form->{"unit_old_$i"}      ||= $form->{"unit_$i"};
@@ -520,6 +520,16 @@ sub item_selected {
 
   map { $form->{"${_}_$i"} = $new_item->{$_} } @new_fields;
 
+  my $record       = _make_record();
+  my $price_source = SL::PriceSource->new(record_item => $record->items->[$i-1], record => $record);
+  my $best_price   = $price_source->best_price;
+
+  if ($best_price) {
+    $::form->{"sellprice_$i"}           = $best_price->price;
+    $::form->{"active_price_source_$i"} = $best_price->source;
+  }
+
+
   $form->{"marge_price_factor_$i"} = $new_item->{price_factor};
 
   if ($form->{"part_payment_id_$i"} ne "") {
@@ -1941,12 +1951,16 @@ sub _make_record {
     purchase_oder           => 'Order',
     sales_quotation         => 'Order',
     request_quotation       => 'Order',
-    invoice                 => 'Invoice',
-    purchase_invoice        => 'PurchaseInvoice',
     purchase_delivery_order => 'DeliveryOrder',
     sales_delivery_order    => 'DeliveryOrder',
   }->{$::form->{type}};
 
+  if ($::form->{type} eq 'invoice') {
+    $class = $::form->{vc} eq 'customer' ? 'Invoice'
+           : $::form->{vc} eq 'vendor'   ? 'PurchaseInvoice'
+           : do { die 'unknown invoice type' };
+  }
+
   return unless $class;
 
   $class = 'SL::DB::' . $class;
@@ -1976,7 +1990,7 @@ sub _make_record {
     push @items, _make_record_item($i)
   }
 
-  $obj->orderitems(@items);
+  $obj->items(@items) if @items;
 
   return $obj;
 }
index 8424f9c..1460630 100644 (file)
@@ -678,6 +678,15 @@ sub update {
         if ($sellprice) {
           $form->{"sellprice_$i"} = $sellprice;
         } else {
+          my $record       = _make_record();
+          my $price_source = SL::PriceSource->new(record_item => $record->items->[$i-1], record => $record);
+          my $best_price   = $price_source->best_price;
+
+          if ($best_price) {
+            $::form->{"sellprice_$i"}           = $best_price->price;
+            $::form->{"active_price_source_$i"} = $best_price->source;
+          }
+
           $form->{"sellprice_$i"} *= (1 - $form->{tradediscount});
           $form->{"sellprice_$i"} /= $exchangerate;   # if there is an exchange rate adjust sellprice
         }
index a70f791..0d0c635 100755 (executable)
@@ -1442,6 +1442,7 @@ $self->{texts} = {
   'Make (vendor\'s database ID, number or name; with X being a number)' => 'Lieferant (Datenbank-ID, Nummer oder Name des Lieferanten; X ist eine fortlaufende Zahl)',
   'Make compatible for import'  => 'Für den Import kompatibel machen',
   'Make default profile'        => 'Zu Standardprofil machen',
+  'Makemodel Price'             => 'Lieferantenpreis',
   'Manage Custom Variables'     => 'Benutzerdefinierte Variablen',
   'Mandantennummer'             => 'Mandantennummer',
   'Mandate Date of Signature'   => 'Mandat-Unterschriftsdatum',