From: Sven Schöling Date: Mon, 28 Jul 2014 13:29:45 +0000 (+0200) Subject: PriceSource: Featureabdeckung X-Git-Tag: release-3.2.0beta~172 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=df1b03d578280d71fb839b437505dd283f6dd749;p=kivitendo-erp.git PriceSource: Featureabdeckung - 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 --- diff --git a/SL/PriceSource/ALL.pm b/SL/PriceSource/ALL.pm index f39df0abc..33a7e447d 100644 --- a/SL/PriceSource/ALL.pm +++ b/SL/PriceSource/ALL.pm @@ -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 index 000000000..2a4f5b043 --- /dev/null +++ b/SL/PriceSource/Makemodel.pm @@ -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; diff --git a/SL/PriceSource/MasterData.pm b/SL/PriceSource/MasterData.pm index c639ccb49..3f7c11d5d 100644 --- a/SL/PriceSource/MasterData.pm +++ b/SL/PriceSource/MasterData.pm @@ -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; diff --git a/SL/PriceSource/Price.pm b/SL/PriceSource/Price.pm index 0a8fc4f5f..593c5ff90 100644 --- a/SL/PriceSource/Price.pm +++ b/SL/PriceSource/Price.pm @@ -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; diff --git a/SL/PriceSource/Pricegroup.pm b/SL/PriceSource/Pricegroup.pm index b1c75f879..127ec660e 100644 --- a/SL/PriceSource/Pricegroup.pm +++ b/SL/PriceSource/Pricegroup.pm @@ -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, ) diff --git a/bin/mozilla/io.pl b/bin/mozilla/io.pl index 49e352894..c7a06af28 100644 --- a/bin/mozilla/io.pl +++ b/bin/mozilla/io.pl @@ -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; } diff --git a/bin/mozilla/oe.pl b/bin/mozilla/oe.pl index 8424f9c64..146063080 100644 --- a/bin/mozilla/oe.pl +++ b/bin/mozilla/oe.pl @@ -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 } diff --git a/locale/de/all b/locale/de/all index a70f79176..0d0c63566 100755 --- a/locale/de/all +++ b/locale/de/all @@ -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',