Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision eebe8e90

Von Sven Schöling vor etwa 10 Jahren hinzugefügt

  • ID eebe8e90991eacadb6fbd20a648c152017a620c7
  • Vorgänger c21d2acc
  • Nachfolger 0409db7c

PriceSource: Erste Version

- Preisgruppen und Stammdaten sind implementiert
- Persistenz in allen Belegen funktioniert
- Rudimentäre Visualisierung funktioniert
- Klassen sind alle da

- Doku fehlt
- Verkauf/Einkaufweiche fehlt
- best_price ungetestet
- Preisgruppen hängen noch nicht von Verkäufer ab
- dependancy system fehlt
- verhalten bei fehlerhaften sources
- pricegroup -> active_source migration

Unterschiede anzeigen:

SL/DB/Helper/PriceTaxCalculator.pm
use strict;
use parent qw(Exporter);
our @EXPORT = qw(calculate_prices_and_taxes);
our @EXPORT = qw(calculate_prices_and_taxes _calculate_item);
use Carp;
use List::Util qw(sum min max);
......
my ($self, $item, $idx, $data, %params) = @_;
my $part = SL::DB::Part->load_cached($item->parts_id);
return unless $item->part;
my $part_unit = $data->{units_by_name}->{ $part->unit };
my $item_unit = $data->{units_by_name}->{ $item->unit };
SL/DB/MetaSetup/DeliveryOrderItem.pm
__PACKAGE__->meta->table('delivery_order_items');
__PACKAGE__->meta->columns(
base_qty => { type => 'float', scale => 4 },
cusordnumber => { type => 'text' },
delivery_order_id => { type => 'integer', not_null => 1 },
description => { type => 'text' },
discount => { type => 'float', scale => 4 },
id => { type => 'integer', not_null => 1, sequence => 'delivery_order_items_id' },
itime => { type => 'timestamp', default => 'now()' },
lastcost => { type => 'numeric', precision => 15, scale => 5 },
longdescription => { type => 'text' },
marge_price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
mtime => { type => 'timestamp' },
ordnumber => { type => 'text' },
parts_id => { type => 'integer', not_null => 1 },
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
price_factor_id => { type => 'integer' },
pricegroup_id => { type => 'integer' },
project_id => { type => 'integer' },
qty => { type => 'numeric', precision => 25, scale => 5 },
reqdate => { type => 'date' },
sellprice => { type => 'numeric', precision => 15, scale => 5 },
serialnumber => { type => 'text' },
transdate => { type => 'text' },
unit => { type => 'varchar', length => 20 },
base_qty => { type => 'float', scale => 4 },
cusordnumber => { type => 'text' },
delivery_order_id => { type => 'integer', not_null => 1 },
description => { type => 'text' },
discount => { type => 'float', scale => 4 },
id => { type => 'integer', not_null => 1, sequence => 'delivery_order_items_id' },
itime => { type => 'timestamp', default => 'now()' },
lastcost => { type => 'numeric', precision => 15, scale => 5 },
longdescription => { type => 'text' },
marge_price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
mtime => { type => 'timestamp' },
ordnumber => { type => 'text' },
parts_id => { type => 'integer', not_null => 1 },
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
price_factor_id => { type => 'integer' },
pricegroup_id => { type => 'integer' },
project_id => { type => 'integer' },
qty => { type => 'numeric', precision => 25, scale => 5 },
reqdate => { type => 'date' },
sellprice => { type => 'numeric', precision => 15, scale => 5 },
serialnumber => { type => 'text' },
transdate => { type => 'text' },
unit => { type => 'varchar', length => 20 },
active_price_source => { type => 'text', default => '', not_null => 1 },
);
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
SL/DB/MetaSetup/InvoiceItem.pm
__PACKAGE__->meta->table('invoice');
__PACKAGE__->meta->columns(
allocated => { type => 'float', scale => 4 },
assemblyitem => { type => 'boolean', default => 'false' },
base_qty => { type => 'float', scale => 4 },
cusordnumber => { type => 'text' },
deliverydate => { type => 'date' },
description => { type => 'text' },
discount => { type => 'float', scale => 4 },
donumber => { type => 'text' },
fxsellprice => { type => 'numeric', precision => 15, scale => 5 },
id => { type => 'integer', not_null => 1, sequence => 'invoiceid' },
itime => { type => 'timestamp', default => 'now()' },
lastcost => { type => 'numeric', precision => 15, scale => 5 },
longdescription => { type => 'text' },
marge_percent => { type => 'numeric', precision => 15, scale => 5 },
marge_price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
marge_total => { type => 'numeric', precision => 15, scale => 5 },
mtime => { type => 'timestamp' },
ordnumber => { type => 'text' },
parts_id => { type => 'integer' },
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
price_factor_id => { type => 'integer' },
pricegroup_id => { type => 'integer' },
project_id => { type => 'integer' },
qty => { type => 'float', scale => 4 },
sellprice => { type => 'numeric', precision => 15, scale => 5 },
serialnumber => { type => 'text' },
subtotal => { type => 'boolean', default => 'false' },
trans_id => { type => 'integer' },
transdate => { type => 'text' },
unit => { type => 'varchar', length => 20 },
allocated => { type => 'float', scale => 4 },
assemblyitem => { type => 'boolean', default => 'false' },
base_qty => { type => 'float', scale => 4 },
cusordnumber => { type => 'text' },
deliverydate => { type => 'date' },
description => { type => 'text' },
discount => { type => 'float', scale => 4 },
donumber => { type => 'text' },
fxsellprice => { type => 'numeric', precision => 15, scale => 5 },
id => { type => 'integer', not_null => 1, sequence => 'invoiceid' },
itime => { type => 'timestamp', default => 'now()' },
lastcost => { type => 'numeric', precision => 15, scale => 5 },
longdescription => { type => 'text' },
marge_percent => { type => 'numeric', precision => 15, scale => 5 },
marge_price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
marge_total => { type => 'numeric', precision => 15, scale => 5 },
mtime => { type => 'timestamp' },
ordnumber => { type => 'text' },
parts_id => { type => 'integer' },
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
price_factor_id => { type => 'integer' },
pricegroup_id => { type => 'integer' },
project_id => { type => 'integer' },
qty => { type => 'float', scale => 4 },
sellprice => { type => 'numeric', precision => 15, scale => 5 },
serialnumber => { type => 'text' },
subtotal => { type => 'boolean', default => 'false' },
trans_id => { type => 'integer' },
transdate => { type => 'text' },
unit => { type => 'varchar', length => 20 },
active_price_source => { type => 'text', default => '', not_null => 1 },
);
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
SL/DB/MetaSetup/OrderItem.pm
__PACKAGE__->meta->table('orderitems');
__PACKAGE__->meta->columns(
base_qty => { type => 'float', scale => 4 },
cusordnumber => { type => 'text' },
description => { type => 'text' },
discount => { type => 'float', scale => 4 },
id => { type => 'integer', not_null => 1, sequence => 'orderitemsid' },
itime => { type => 'timestamp', default => 'now()' },
lastcost => { type => 'numeric', precision => 15, scale => 5 },
longdescription => { type => 'text' },
marge_percent => { type => 'numeric', precision => 15, scale => 5 },
marge_price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
marge_total => { type => 'numeric', precision => 15, scale => 5 },
mtime => { type => 'timestamp' },
ordnumber => { type => 'text' },
parts_id => { type => 'integer' },
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
price_factor_id => { type => 'integer' },
pricegroup_id => { type => 'integer' },
project_id => { type => 'integer' },
qty => { type => 'float', scale => 4 },
reqdate => { type => 'date' },
sellprice => { type => 'numeric', precision => 15, scale => 5 },
serialnumber => { type => 'text' },
ship => { type => 'float', scale => 4 },
subtotal => { type => 'boolean', default => 'false' },
trans_id => { type => 'integer' },
transdate => { type => 'text' },
unit => { type => 'varchar', length => 20 },
base_qty => { type => 'float', scale => 4 },
cusordnumber => { type => 'text' },
description => { type => 'text' },
discount => { type => 'float', scale => 4 },
id => { type => 'integer', not_null => 1, sequence => 'orderitemsid' },
itime => { type => 'timestamp', default => 'now()' },
lastcost => { type => 'numeric', precision => 15, scale => 5 },
longdescription => { type => 'text' },
marge_percent => { type => 'numeric', precision => 15, scale => 5 },
marge_price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
marge_total => { type => 'numeric', precision => 15, scale => 5 },
mtime => { type => 'timestamp' },
ordnumber => { type => 'text' },
parts_id => { type => 'integer' },
price_factor => { type => 'numeric', default => 1, precision => 15, scale => 5 },
price_factor_id => { type => 'integer' },
pricegroup_id => { type => 'integer' },
project_id => { type => 'integer' },
qty => { type => 'float', scale => 4 },
reqdate => { type => 'date' },
sellprice => { type => 'numeric', precision => 15, scale => 5 },
serialnumber => { type => 'text' },
ship => { type => 'float', scale => 4 },
subtotal => { type => 'boolean', default => 'false' },
trans_id => { type => 'integer' },
transdate => { type => 'text' },
unit => { type => 'varchar', length => 20 },
active_price_source => { type => 'text', default => '', not_null => 1 },
);
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
SL/DO.pm
id, delivery_order_id, parts_id, description, longdescription, qty, base_qty,
sellprice, discount, unit, reqdate, project_id, serialnumber,
ordnumber, transdate, cusordnumber,
lastcost, price_factor_id, price_factor, marge_price_factor, pricegroup_id)
lastcost, price_factor_id, price_factor, marge_price_factor, pricegroup_id,
active_price_source)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
(SELECT factor FROM price_factors WHERE id = ?), ?, ?)|;
(SELECT factor FROM price_factors WHERE id = ?), ?, ?, ?)|;
my $h_item = prepare_query($form, $dbh, $q_item);
my $q_item_stock =
......
$form->{"lastcost_$i"},
conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
conv_i($form->{"marge_price_factor_$i"}),
$pricegroup_id);
$pricegroup_id,
$form->{"active_price_source_$i"});
do_statement($form, $h_item, $q_item, @values);
my $stock_info = DO->unpack_stock_information('packed' => $form->{"stock_${in_out}_$i"});
......
doi.reqdate, doi.project_id, doi.serialnumber, doi.lastcost,
doi.ordnumber, doi.transdate, doi.cusordnumber, doi.longdescription,
doi.price_factor_id, doi.price_factor, doi.marge_price_factor, doi.pricegroup_id,
doi.active_price_source,
pr.projectnumber, dord.transdate AS dord_transdate, dord.donumber,
pg.partsgroup
FROM delivery_order_items doi
SL/IS.pm
$main::lxdebug->leave_sub();
}
##########################
# get pricegroups from database
# build up selected pricegroup
# if an exchange rate - change price
# for each part
#
sub get_pricegroups_for_parts {
$main::lxdebug->enter_sub();
my ($self, $myconfig, $form) = @_;
my $dbh = $form->get_standard_dbh;
$form->{"PRICES"} = {};
my $i = 1;
my $id = 0;
my $all_units = AM->retrieve_units($myconfig, $form);
while (($form->{"id_$i"}) or ($form->{"new_id_$i"})) {
$form->{"PRICES"}{$i} = [];
$id = $form->{"id_$i"};
if (!($form->{"id_$i"}) and $form->{"new_id_$i"}) {
$id = $form->{"new_id_$i"};
}
my ($price, $selectedpricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
my $pricegroup_old = $form->{"pricegroup_old_$i"};
# sellprice has format 13,0000 or 0,00000, can't check for 0 numerically
my $sellprice = $form->{"sellprice_$i"};
my $pricegroup_id = $form->{"pricegroup_id_$i"};
$form->{"new_pricegroup_$i"} = $selectedpricegroup_id;
$form->{"old_pricegroup_$i"} = $pricegroup_old;
my $price_new = $form->{"price_new_$i"};
my $price_old = $form->{"price_old_$i"};
if (!$form->{"unit_old_$i"}) {
# Neue Ware aus der Datenbank. In diesem Fall ist unit_$i die
# Einheit, wie sie in den Stammdaten hinterlegt wurde.
# Es sollte also angenommen werden, dass diese ausgewaehlt war.
$form->{"unit_old_$i"} = $form->{"unit_$i"};
}
# Die zuletzt ausgewaehlte mit der aktuell ausgewaehlten Einheit
# vergleichen und bei Unterschied den Preis entsprechend umrechnen.
$form->{"selected_unit_$i"} = $form->{"unit_$i"} unless ($form->{"selected_unit_$i"});
if (!$all_units->{$form->{"selected_unit_$i"}} ||
($all_units->{$form->{"selected_unit_$i"}}->{"base_unit"} ne
$all_units->{$form->{"unit_old_$i"}}->{"base_unit"})) {
# Die ausgewaehlte Einheit ist fuer diesen Artikel nicht gueltig
# (z.B. Dimensionseinheit war ausgewaehlt, es handelt sich aber
# um eine Dienstleistung). Dann keinerlei Umrechnung vornehmen.
$form->{"unit_old_$i"} = $form->{"selected_unit_$i"} = $form->{"unit_$i"};
}
my $basefactor = 1;
if ($form->{"unit_old_$i"} ne $form->{"selected_unit_$i"}) {
if (defined($all_units->{$form->{"unit_old_$i"}}->{"factor"}) &&
$all_units->{$form->{"unit_old_$i"}}->{"factor"}) {
$basefactor = $all_units->{$form->{"selected_unit_$i"}}->{"factor"} /
$all_units->{$form->{"unit_old_$i"}}->{"factor"};
}
}
if (!$form->{"basefactor_$i"}) {
$form->{"basefactor_$i"} = 1;
}
my $query =
qq|SELECT
0 as pricegroup_id,
sellprice AS default_sellprice,
'' AS pricegroup,
sellprice AS price,
'selected' AS selected
FROM parts
WHERE id = ?
UNION ALL
SELECT
pricegroup_id,
parts.sellprice AS default_sellprice,
pricegroup.pricegroup,
price,
'' AS selected
FROM prices
LEFT JOIN parts ON parts.id = parts_id
LEFT JOIN pricegroup ON pricegroup.id = pricegroup_id
WHERE parts_id = ?
ORDER BY pricegroup|;
my @values = (conv_i($id), conv_i($id));
my $pkq = prepare_execute_query($form, $dbh, $query, @values);
while (my $pkr = $pkq->fetchrow_hashref('NAME_lc')) {
$pkr->{id} = $id;
$pkr->{selected} = '';
# if there is an exchange rate change price
if (($form->{exchangerate} * 1) != 0) {
$pkr->{price} /= $form->{exchangerate};
}
$pkr->{price} *= $form->{"basefactor_$i"};
$pkr->{price} *= $basefactor;
$pkr->{price_ufmt} = $pkr->{price};
$pkr->{price} = $form->format_amount($myconfig, $pkr->{price}, 5);
if (!defined $selectedpricegroup_id) {
# new entries in article list, either old invoice was loaded (edit) or a new article was added
# Case A: open old invoice, no pricegroup selected
# Case B: add new article to invoice, no pricegroup selected
# to distinguish case A and B the variable pricegroup_id_$i is used
# for new articles this variable isn't defined, for loaded articles it is
# sellprice can't be used, as it already has 0,00 set
if ($pkr->{pricegroup_id} eq $form->{"pricegroup_id_$i"} and defined $form->{"pricegroup_id_$i"}) {
# Case A
$pkr->{selected} = ' selected';
} elsif ($pkr->{pricegroup_id} eq $form->{customer_klass}
and not defined $form->{"pricegroup_id_$i"}
and $pkr->{price_ufmt} != 0 # only use customer pricegroup price if it has a value, else use default_sellprice
# for the case where pricegroup prices haven't been set
) {
# Case B: use default pricegroup of customer
$pkr->{selected} = ' selected'; # unless $form->{selected};
# no customer pricesgroup set
if ($pkr->{price_ufmt} == $pkr->{default_sellprice}) {
$pkr->{price} = $form->{"sellprice_$i"};
} else {
# this sub should not set anything and only return. --sschoeling, 20090506
# is this correct? put in again... -- grichardson 20110119
$form->{"sellprice_$i"} = $pkr->{price};
}
} elsif ($pkr->{price_ufmt} == $pkr->{default_sellprice} and $pkr->{default_sellprice} != 0) {
$pkr->{price} = $form->{"sellprice_$i"};
$pkr->{selected} = ' selected';
}
}
# existing article: pricegroup or price changed
if ($selectedpricegroup_id or $selectedpricegroup_id == 0) {
if ($selectedpricegroup_id ne $pricegroup_old) {
# pricegroup has changed
if ($pkr->{pricegroup_id} eq $selectedpricegroup_id) {
$pkr->{selected} = ' selected';
}
} elsif ( ($form->parse_amount($myconfig, $price_new)
!= $form->parse_amount($myconfig, $form->{"sellprice_$i"}))
and ($price_new ne 0) and defined $price_new) {
# sellprice has changed
# when loading existing invoices $price_new is NULL
if ($pkr->{pricegroup_id} == 0) {
$pkr->{price} = $form->{"sellprice_$i"};
$pkr->{selected} = ' selected';
}
} elsif ($pkr->{pricegroup_id} eq $selectedpricegroup_id) {
# neither sellprice nor pricegroup changed
$pkr->{selected} = ' selected';
if ( ($pkr->{pricegroup_id} == 0) and ($pkr->{price} == $form->{"sellprice_$i"})) {
# $pkr->{price} = $form->{"sellprice_$i"};
} else {
$pkr->{price} = $form->{"sellprice_$i"};
}
}
}
push @{ $form->{PRICES}{$i} }, $pkr;
}
$form->{"basefactor_$i"} *= $basefactor;
$i++;
$pkq->finish;
}
$main::lxdebug->leave_sub();
}
sub has_storno {
$main::lxdebug->enter_sub();
SL/OE.pm
sellprice = ?, discount = ?, unit = ?, reqdate = ?, project_id = ?, serialnumber = ?, ship = ?,
pricegroup_id = ?, ordnumber = ?, transdate = ?, cusordnumber = ?, subtotal = ?,
marge_percent = ?, marge_total = ?, lastcost = ?, price_factor_id = ?,
active_price_source = ?,
price_factor = (SELECT factor FROM price_factors WHERE id = ?), marge_price_factor = ?
WHERE id = ?
SQL
......
$form->{"cusordnumber_$i"}, $form->{"subtotal_$i"} ? 't' : 'f',
$form->{"marge_percent_$i"}, $form->{"marge_absolut_$i"},
$form->{"lastcost_$i"},
$form->{"active_price_source_$i"},
conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
conv_i($form->{"marge_price_factor_$i"}),
conv_i($orderitems_id),
......
o.sellprice, o.parts_id AS id, o.unit, o.discount, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id,
o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
o.price_factor_id, o.price_factor, o.marge_price_factor,
o.price_factor_id, o.price_factor, o.marge_price_factor, o.active_price_source,
pr.projectnumber, p.formel,
pg.partsgroup, o.pricegroup_id, (SELECT pricegroup FROM pricegroup WHERE id=o.pricegroup_id) as pricegroup
FROM orderitems o
SL/PriceSource.pm
package SL::PriceSource;
use strict;
use parent 'SL::DB::Object';
use Rose::Object::MakeMethods::Generic (
scalar => [ qw(record_item) ],
);
use List::UtilsBy qw(min_by);
use SL::PriceSource::ALL;
use SL::PriceSource::Price;
use SL::Locale::String;
sub all_price_sources {
my ($self) = @_;
return map {
$_->new(record_item => $self->record_item)
} SL::PriceSource::ALL->all_price_sources
}
sub price_from_source {
my ($self, $source) = @_;
my ($source_name, $spec) = split m{/}, $source, 2;
my $class = SL::PriceSource::ALL->price_source_class_by_name($source_name);
return $class
? $class->new(record_item => $self->record_item)->price_from_source($source, $spec)
: empty_price();
}
sub available_prices {
map { $_->available_prices } $_[0]->all_price_sources;
}
sub best_price {
min_by { $_->price } map { $_->best_price } $_[0]->all_price_sources;
}
sub empty_price {
SL::PriceSource::Price->new(
source => '',
description => t8('None (PriceSource)'),
);
}
1;
__END__
=encoding utf-8
=head1 NAME
SL::PriceSource - mixin for price_sources in record items
=head1 SYNOPSIS
# in record item class
use SL::PriceSource;
# later on:
$record_item->all_price_sources
$record_item->price_source # get
$record_item->price_source($c) # set
$record_item->update_price_source # set price to calculated
=head1 DESCRIPTION
This mixin provides a way to use price_source objects from within a record item.
Record items in this contest mean OrderItems, InvoiceItems and
DeliveryOrderItems.
=head1 FUNCTIONS
price_sources
returns a list of price_source objects which are created with the current record
item.
active_price_source
returns the object representing the currently chosen price_source method or
undef if custom price is chosen. Note that this must not necessarily be the
active price, if something affecting the price_source has changed, the price
calculated can differ from the price in the record. It is the responsibility of
the implementing code to decide what to do in this case.
=head1 BUGS
None yet. :)
=head1 AUTHOR
Sven Schoeling E<lt>s.schoeling@linet-services.deE<gt>
=cut
SL/PriceSource/ALL.pm
package SL::PriceSource::ALL;
use strict;
use SL::PriceSource::Pricegroup;
use SL::PriceSource::MasterData;
my %price_sources_by_name = (
master_data => 'SL::PriceSource::MasterData',
pricegroup => 'SL::PriceSource::Pricegroup',
);
my @price_sources_order = qw(
master_data
pricegroup
);
sub all_price_sources {
map { $price_sources_by_name{$_} } @price_sources_order;
}
sub price_source_class_by_name {
$price_sources_by_name{$_[1]};
}
1;
SL/PriceSource/Base.pm
package SL::PriceSource::Base;
use strict;
use parent qw(SL::DB::Object);
use Rose::Object::MakeMethods::Generic (
scalar => [ qw(record_item record) ],
);
sub name { die 'name needs to be implemented' }
sub description { die 'description needs to be implemented' }
sub available_prices { die 'available_prices needs to be implemented' }
sub best_price { die 'best_price needs to be implemented' }
sub price_from_source { die 'price_from_source needs to be implemented:' . "@_" }
sub part {
$_[0]->record_item->part;
}
1;
__END__
=encoding utf-8
=head1 NAME
SL::PriceSource::Base - <oneliner description>
=head1 SYNOPSIS
# in consuming module
# TODO: thats bullshit, theres no need to have this pollute the namespace
# make a manager that handles this
my @list_of_price_sources = $record_item->price_sources;
for (@list_of_price_sources) {
my $internal_name = $_->name;
my $translated_name = $_->description;
my $price = $_->price;
}
$record_item->set_active_price_source($price_source) # equivalent to:
$record_item->active_price_source($price_source->name);
$record_item->sellprice($price_source->price);
# for finer control
$price_source->needed_params
$price_source->supported_params
=head1 DESCRIPTION
PriceSource is an interface that allows generic algorithms to be used, to
calculate a price for a position in a record.
If any such price_source algorithm is known to the system, a user can chose
which of them should be used to claculate the price displayed in the record.
The algorithm is saved togetherwith the target price, so that changes in the
record can recalculate the price accordingly, and otherwise manual changes to
the price can reset the price_source used to custom (aka no price_source).
=head1 INTERFACE METHODS
=over 4
=item C<name>
Should return a unique internal name. Should be entered in
L<SL::PriceSource::ALL> so that a name_to_class lookup works.
=item C<description>
Should return a translated name.
=item C<needed_params>
Should return a list of elements that a record_item NEEDS to be used with this calulation.
Both C<needed_params> nad C<supported_params> are purely informational at this point.
=item C<supported_params>
Should return a list of elements that a record_item MAY HAVE to be used with this calulation.
Both C<needed_params> nad C<supported_params> are purely informational at this point.
=item C<price>
Calculate a price and return. Do not mutate the record_item. Should will return
undef if price is not applicable to the current record_item.
=back
=head1 BUGS
None yet. :)
=head1 AUTHOR
Sven Schoeling E<lt>s.schoeling@linet-services.deE<gt>
=cut
SL/PriceSource/MasterData.pm
package SL::PriceSource::MasterData;
use strict;
use parent qw(SL::PriceSource::Base);
use SL::PriceSource::Price;
use SL::Locale::String;
sub name { 'master_data' }
sub description { t8('Master Data') }
sub available_prices {
my ($self, %params) = @_;
my $part = $self->part;
return () unless $part;
# TODO: sellprice only in sales, lastcost in purchase
return $self->make_sellprice($part);
}
sub price_from_source {
my ($self, $source, $spec) = @_;
if ($spec eq 'sellprice') {
return $self->make_sellprice($self->part);
}
}
sub make_sellprice {
my ($self, $part) = @_;
return SL::PriceSource::Price->new(
price => $part->sellprice,
source => 'master_data/sellprice',
description => t8('Sellprice'),
price_source => $self,
);
}
1;
SL/PriceSource/Price.pm
package SL::PriceSource::Price;
use strict;
use parent 'SL::DB::Object';
use Rose::Object::MakeMethods::Generic (
scalar => [ qw(price description source price_source) ],
array => [ qw(depends_on) ]
);
sub full_description {
my ($self) = @_;
$self->price_source
? $self->price_source->description . ': ' . $self->description
: $self->description
}
1;
SL/PriceSource/Pricegroup.pm
package SL::PriceSource::Pricegroup;
use strict;
use parent qw(SL::PriceSource::Base);
use SL::PriceSource::Price;
use SL::Locale::String;
sub name { 'pricegroup' }
sub description { t8('Pricegroup') }
sub available_prices {
my ($self, %params) = @_;
my $item = $self->record_item;
my $prices = SL::DB::Manager::Price->get_all(
query => [ parts_id => $item->parts_id, price => { gt => 0 } ],
with_objects => 'pricegroup',
order_by => 'pricegroun.id',
);
return () unless @$prices;
return map {
$self->make_price($_);
} @$prices;
}
sub price_from_source {
my ($self, $source, $spec) = @_;
my $price = SL::DB::Manager::Price->find_by(id => $spec);
return $self->make_price($price);
}
sub make_price {
my ($self, $price_obj) = @_;
SL::PriceSource::Price->new(
price => $price_obj->price,
source => 'pricegroup/' . $price_obj->id,
description => $price_obj->pricegroup->pricegroup,
price_source => $self,
)
}
1;
bin/mozilla/do.pl
# Kunde mit Rabatt 20 -> Rabatt 5,5 i.O.
$form->{payment_id} = $payment_id if $form->{payment_id} eq "";
# for pricegroups
my $i = $form->{rowcount};
if ( ($form->{"partnumber_$i"} eq "")
......
$form->{"sellprice_$i"} = $form->format_amount(\%myconfig, $form->{"sellprice_$i"} * (1 - $form->{tradediscount}));
$form->{"lastcost_$i"} = $form->format_amount(\%myconfig, $form->{"lastcost_$i"});
$form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
# build up html code for prices_$i
&set_pricegroup($i);
}
display_form();
......
}
# show pricegroup in newly loaded invoice when creating invoice from delivery order
for my $i (1 .. $form->{rowcount}) {
$form->{"sellprice_pg_$i"} = join '--', $form->{"sellprice_$i"}, $form->{"pricegroup_id_$i"};
}
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
set_pricegroup($form->{rowcount});
display_form();
$main::lxdebug->leave_sub();
......
invoice_links();
prepare_invoice();
# show pricegroup in newly loaded invoice when creating invoice from delivery order
for my $i (1 .. $form->{rowcount}) {
$form->{"sellprice_pg_$i"} = join '--', $form->{"sellprice_$i"}, $form->{"pricegroup_id_$i"};
}
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
set_pricegroup($_) for 1 .. $form->{rowcount};
display_form();
$main::lxdebug->leave_sub();
bin/mozilla/invoice_io.pl
use SL::AM;
use Data::Dumper;
sub set_pricegroup {
$main::lxdebug->enter_sub();
my $form = $main::form;
my %myconfig = %main::myconfig;
my $locale = $main::locale;
my $rowcount = shift;
for my $j (1 .. $rowcount) {
my $pricegroup_old = $form->{"pricegroup_old_$j"};
if ($form->{PRICES}{$j}) {
my $len = 0;
my $prices = '<option value="--">' . $locale->text("none (pricegroup)") . '</option>';
my $price = 0;
foreach my $item (@{ $form->{PRICES}{$j} }) {
#$price = $form->round_amount($myconfig, $item->{price}, 5);
#$price = $form->format_amount($myconfig, $item->{price}, 2);
my $price = $item->{price};
my $pricegroup_id = $item->{pricegroup_id};
my $pricegroup = $item->{pricegroup};
# build drop down list for pricegroups
$prices .=
qq|<option value="$price--$pricegroup_id"$item->{selected}>$pricegroup</option>\n|;
$len += 1;
# map {
# $form->{"${_}_$j"} =
# $form->format_amount(\%myconfig, $form->{"${_}_$j"})
# } qw(sellprice price_new price_old);
# set new selectedpricegroup_id and prices for "Preis"
if ($item->{selected} && ($pricegroup_id != 0)) {
$form->{"pricegroup_old_$j"} = $pricegroup_id;
$form->{"price_new_$j"} = $price;
# edit: don't change the sellprice here
# $form->{"sellprice_$j"} = $price; # this must only be updated for existing articles, not new ones
}
if ($pricegroup_id == 0) {
$form->{"price_new_$j"} = $form->{"sellprice_$j"};
}
}
$form->{"prices_$j"} = $prices;
}
}
$main::lxdebug->leave_sub();
}
sub display_form {
$main::lxdebug->enter_sub();
......
# $form->{rowcount}--;
# my $rowcount = $form->{rowcount};
#
# # get pricegroups for parts
# IS->get_pricegroups_for_parts(\%myconfig, \%$form);
#
# # build up html code for prices_$i
# set_pricegroup($rowcount);
#
# $form->{resubmit} = 1;
#
# }
bin/mozilla/io.pl
use Carp;
use CGI;
use List::MoreUtils qw(any uniq);
use List::MoreUtils qw(any uniq apply);
use List::Util qw(min max first);
use SL::CVar;
......
use SL::CT;
use SL::IC;
use SL::IO;
use SL::PriceSource;
use SL::DB::Customer;
use SL::DB::Default;
......
}
# column_index
my @header_sort = qw(runningnumber partnumber description ship qty unit weight sellprice_pg sellprice discount linetotal);
my @header_sort = qw(runningnumber partnumber description ship qty unit weight sellprice discount linetotal);
my @HEADER = (
{ id => 'runningnumber', width => 5, value => $locale->text('No.'), display => 1, },
{ id => 'partnumber', width => 8, value => $locale->text('Number'), display => 1, },
......
{ id => 'serialnr', width => 10, value => $locale->text('Serial No.'), display => 0, },
{ id => 'projectnr', width => 10, value => $locale->text('Project'), display => 0, },
{ id => 'sellprice', width => 15, value => $locale->text('Price'), display => !$is_delivery_order, },
{ id => 'sellprice_pg', width => 8, value => $locale->text('Pricegroup'), display => !$is_delivery_order && !$is_purchase, },
{ id => 'price_source', width => 5, value => $locale->text('Price Source'), display => !$is_delivery_order, },
{ id => 'discount', width => 5, value => $locale->text('Discount'), display => !$is_delivery_order, },
{ id => 'linetotal', width => 10, value => $locale->text('Extended'), display => !$is_delivery_order, },
{ id => 'bin', width => 10, value => $locale->text('Bin'), display => 0, },
......
my $deliverydate = $locale->text('Required by');
# special alignings
my %align = map { $_ => 'right' } qw(qty ship right sellprice_pg discount linetotal stock_in_out weight);
my %align = map { $_ => 'right' } qw(qty ship right discount linetotal stock_in_out weight);
my %nowrap = map { $_ => 1 } qw(description unit);
$form->{marge_total} = 0;
......
$form->{"sellprice_$i"} = $form->{"price_new_$i"};
}
my $record_item = _make_record_item($i);
# unit begin
$form->{"unit_old_$i"} ||= $form->{"unit_$i"};
$form->{"selected_unit_$i"} ||= $form->{"unit_$i"};
......
|| !AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units)) { # (z.B. Dimensionseinheit war ausgewaehlt, es handelt sich aber
$form->{"unit_old_$i"} = $form->{"selected_unit_$i"} = $form->{"unit_$i"}; # um eine Dienstleistung). Dann keinerlei Umrechnung vornehmen.
}
# adjust prices by unit, ignore if pricegroup changed
if ((!$form->{"prices_$i"}) || ($form->{"new_pricegroup_$i"} == $form->{"old_pricegroup_$i"})) {
$form->{"sellprice_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
$form->{"lastcost_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
$form->{"unit_old_$i"} = $form->{"selected_unit_$i"};
}
$form->{"sellprice_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
$form->{"lastcost_$i"} *= AM->convert_unit($form->{"selected_unit_$i"}, $form->{"unit_old_$i"}, $all_units) || 1;
$form->{"unit_old_$i"} = $form->{"selected_unit_$i"};
my $this_unit = $form->{"unit_$i"};
$this_unit = $form->{"selected_unit_$i"} if AM->convert_unit($this_unit, $form->{"selected_unit_$i"}, $all_units);
......
$column_data{ship} = $form->format_amount(\%myconfig, $form->round_amount($ship_qty, 2) * 1) . ' ' . $form->{"unit_$i"};
}
# build in drop down list for pricesgroups
# $sellprice_value setzt den Wert etwas unabhängiger von der Darstellung.
# Hintergrund: Preisgruppen werden hier überprüft und neu berechnet.
# Vorher wurde der ganze cgi->textfield Block zweimal identisch eingebaut, dass passiert
# jetzt nach der Abfrage.
my $sellprice_value;
if ($form->{"prices_$i"}) {
$column_data{sellprice_pg} = qq|<select name="sellprice_pg_$i" style="width: 8em">$form->{"prices_$i"}</select>|;
$sellprice_value =($form->{"new_pricegroup_$i"} != $form->{"old_pricegroup_$i"})
? $form->format_amount(\%myconfig, $form->{"price_new_$i"}, $decimalplaces)
: $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
} else {
# for last row and report
# set pricegroup drop down list from report menu
if ($form->{"sellprice_$i"} != 0) {
# remember the pricegroup_id in pricegroup_old
# but don't overwrite it
$form->{"pricegroup_old_$i"} = $form->{"pricegroup_id_$i"};
my $default_option = $form->{"sellprice_$i"}.'--'.$form->{"pricegroup_id_$i"};
$column_data{sellprice_pg} = NTI($cgi->popup_menu("sellprice_pg_$i", [ $default_option ], $default_option, { $default_option => $form->{"pricegroup_$i"} || '' }));
} else {
$column_data{sellprice_pg} = qq|&nbsp;|;
}
$sellprice_value = $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
}
# Falls der Benutzer die Preise nicht anpassen sollte, wird das entsprechende
# Textfield auf readonly gesetzt. Anm. von Sven: Manipulation der Preise ist
# immer noch möglich, konsequenterweise sollten diese NUR aus der Datenbank
# geholt werden.
my $edit_prices = $main::auth->assert('edit_prices', 1);
$column_data{sellprice} = (!$edit_prices)
? $cgi->textfield(-readonly => "readonly",
-name => "sellprice_$i", -size => 10, -onBlur => "check_right_number_format(this)", -value => $sellprice_value)
: $cgi->textfield(-name => "sellprice_$i", -size => 10, -onBlur => "check_right_number_format(this)", -value => $sellprice_value);
my $sellprice_value = $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
my $edit_prices = $main::auth->assert('edit_prices', 1) && !$::form->{"active_price_source_$i"};
$column_data{sellprice} = (!$edit_prices)
? $cgi->hidden( -name => "sellprice_$i", -id => "sellprice_$i", -value => $sellprice_value) . $sellprice_value
: $cgi->textfield(-name => "sellprice_$i", -id => "sellprice_$i", -size => 10, -onBlur => "check_right_number_format(this)", -value => $sellprice_value);
$column_data{discount} = (!$edit_prices)
? $cgi->textfield(-readonly => "readonly",
-name => "discount_$i", -size => 3, -value => $form->format_amount(\%myconfig, $form->{"discount_$i"}))
......
$column_data{weight} = $form->format_amount(\%myconfig, $form->{"qty_$i"} * $form->{"weight_$i"}, 3) . ' ' . $defaults->{weightunit} if $defaults->{show_weight};
if ($form->{"id_${i}"}) {
my $price_source = SL::PriceSource->new(record_item => $record_item);
my $price = $price_source->price_from_source($::form->{"active_price_source_$i"});
$::form->{price_sources}[$i] = $price_source;
$column_data{price_source} .= $cgi->button(-value => $price->full_description, -onClick => "toggle_price_source($i)");
}
if ($is_delivery_order) {
$column_data{stock_in_out} = calculate_stock_in_out($i);
}
......
if ($is_delivery_order) {
map { $form->{"${_}_${i}"} = $form->format_amount(\%myconfig, $form->{"${_}_${i}"}) } qw(sellprice discount lastcost);
$form->{"pricegroup_id_$i"} = $form->{"pricegroup_old_$i"} if $form->{"pricegroup_old_$i"};
$form->{"sellprice_pg_$i"} = $form->{"hidden_prices_$i"} if $form->{"hidden_prices_$i"};
push @hidden_vars, grep { defined $form->{"${_}_${i}"} } qw(sellprice discount not_discountable price_factor_id lastcost pricegroup_id sellprice_pg);
push @hidden_vars, grep { defined $form->{"${_}_${i}"} } qw(sellprice discount not_discountable price_factor_id lastcost);
push @hidden_vars, "stock_${stock_in_out}_sum_qty", "stock_${stock_in_out}";
}
......
$cgi->hidden("-name" => "unit_old_$i", "-value" => $form->{"selected_unit_$i"}),
$cgi->hidden("-name" => "price_new_$i", "-value" => $form->format_amount(\%myconfig, $form->{"price_new_$i"})),
map { ($cgi->hidden("-name" => $_, "-id" => $_, "-value" => $form->{$_})); } map { $_."_$i" }
(qw(orderitems_id bo pricegroup_old price_old id inventory_accno bin partsgroup partnotes
(qw(orderitems_id bo price_old id inventory_accno bin partsgroup partnotes active_price_source
income_accno expense_accno listprice assembly taxaccounts ordnumber donumber transdate cusordnumber
longdescription basefactor marge_absolut marge_percent marge_price_factor weight), @hidden_vars)
);
......
# Benutzerdefinierte Variablen für Waren/Dienstleistungen/Erzeugnisse
_render_custom_variables_inputs(ROW2 => \@ROW2, row => $i, part_id => $form->{"id_$i"});
push @ROWS, { ROW1 => \@ROW1, ROW2 => \@ROW2, HIDDENS => \@HIDDENS, colspan => $colspan, error => $form->{"row_error_$i"}, };
push @ROWS, { ROW1 => \@ROW1, ROW2 => \@ROW2, HIDDENS => \@HIDDENS, colspan => $colspan, error => $form->{"row_error_$i"}, obj => $record_item };
}
$form->{totalweight} = $totalweight;
......
$main::lxdebug->leave_sub();
}
##################################################
# build html-code for pricegroups in variable $form->{prices_$j}
sub set_pricegroup {
$main::lxdebug->enter_sub();
my $form = $main::form;
my $locale = $main::locale;
my $cgi = $::request->{cgi};
_check_io_auth();
my $rowcount = shift;
for my $j (1 .. $rowcount) {
next unless $form->{PRICES}{$j};
# build drop down list for pricegroups
my $option_tmpl = qq|<option value="%s--%s" %s>%s</option>|;
$form->{"prices_$j"} = join '', map { sprintf $option_tmpl, @$_{qw(price pricegroup_id selected pricegroup)} }
(+{ pricegroup => $locale->text("none (pricegroup)") }, @{ $form->{PRICES}{$j} });
foreach my $item (@{ $form->{PRICES}{$j} }) {
# set new selectedpricegroup_id and prices for "Preis"
$form->{"pricegroup_old_$j"} = $item->{pricegroup_id} if $item->{selected} && $item->{pricegroup_id};
$form->{"sellprice_$j"} = $item->{price} if $item->{selected} && $item->{pricegroup_id};
$form->{"price_new_$j"} = $form->{"sellprice_$j"} if $item->{selected} || !$item->{pricegroup_id};
}
# save hidden pricegroups for delivery_orders
next unless my @selected_prices = grep { $_->{selected} } @{ $form->{PRICES}{$j} };
$form->{"hidden_prices_$j"} = $selected_prices[-1]{price} . "--" . $selected_prices[-1]{pricegroup_id};
}
$main::lxdebug->leave_sub();
}
sub select_item {
$main::lxdebug->enter_sub();
......
$form->format_amount(\%myconfig, $form->{"${_}_$i"}, $decimalplaces)
} qw(sellprice listprice lastcost) if $form->{item} ne 'assembly';
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
# build up html code for prices_$i
set_pricegroup($form->{rowcount});
&display_form;
$main::lxdebug->leave_sub();
......
or (($form->{level} eq undef) and ($form->{type} =~ /invoice/))
or ($form->{type} =~ /sales_order/)) {
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
# build up html code for prices_$i
set_pricegroup($form->{rowcount});
}
&display_form;
......
taxaccounts bin assembly weight projectnumber project_id
oldprojectnumber runningnumber serialnumber partsgroup payment_id
not_discountable shop ve gv buchungsgruppen_id language_values
sellprice_pg pricegroup_old price_old price_new unit_old ordnumber donumber
price_old price_new unit_old ordnumber donumber
transdate longdescription basefactor marge_total marge_percent
marge_price_factor lastcost price_factor_id partnotes
stock_out stock_in has_sernumber reqdate orderitems_id);
......
# get details for customer/vendor
call_sub($::form->{vc} . "_details", qw(name department_1 department_2 street zipcode city country contact email phone fax), $::form->{vc} . "number");
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%::myconfig, \%$::form);
# build up html code for prices_$i
set_pricegroup($::form->{rowcount});
$::form->{rowcount}--;
my @shipto_vars = qw(shiptoname shiptostreet shiptozipcode shiptocity shiptocountry
......
$::form->redo_rows(\@fields, \@new_rows, scalar(@new_rows), $::form->{rowcount});
$::form->{rowcount} -= $removed_rows;
}
sub _make_record_item {
my ($row) = @_;
my $class = {
sales_order => 'OrderItem',
purchase_oder => 'OrderItem',
sales_quotation => 'OrderItem',
request_quotation => 'OrderItem',
invoice => 'InvoiceItem',
purchase_invoice => 'InvoiceItem',
purchase_delivery_order => 'DeliveryOrderItem',
sales_delivery_order => 'DeliveryOrderItem',
}->{$::form->{type}};
return unless $class;
$class = 'SL::DB::' . $class;
eval "require $class";
my $obj = $::form->{"orderitems_id_$row"}
? $class->meta->convention_manager->auto_manager_class_name->find_by(id => $::form->{"orderitems_id_$row"})
: $class->new;
for my $method (apply { s/_$row$// } grep { /_$row$/ } keys %$::form) {
next unless $obj->meta->column($method);
if ($obj->meta->column($method)->isa('Rose::DB::Object::Metadata::Column::Date')) {
$obj->${\"$method\_as_date"}($::form->{"$method\_$row"});
} else {
$obj->$method($::form->{"$method\_$row"});
}
}
if ($::form->{"id_$row"}) {
$obj->part(SL::DB::Part->load_cached($::form->{"id_$row"}));
}
return $obj;
}
bin/mozilla/is.pl
$form->{rowcount} = $i;
}
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
# Problem: set_pricegroup resets the sellprice of old invoices to the price
# currently defined in the pricegroup, which is a problem if the price has
# changed, as the old invoice gets the new price
# set_pricegroup must never be called, when an old invoice is initially loaded
# set_pricegroup($_) for 1 .. $form->{rowcount};
}
$main::lxdebug->leave_sub();
}
......
map { $form->{"${_}_$i"} = $form->format_amount(\%myconfig, $form->{"${_}_$i"}, $decimalplaces) } qw(sellprice lastcost);
$form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
# build up html code for prices_$i
&set_pricegroup($i);
}
&display_form;
......
$form->{forex} = $form->check_exchangerate(\%myconfig, $form->{currency}, $form->{invdate}, 'buy');
$form->{exchangerate} = $form->{forex} if $form->{forex};
# remember pricegroups for "use as new"
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
set_pricegroup($_) for 1 .. $form->{rowcount};
&display_form;
$main::lxdebug->leave_sub();
bin/mozilla/oe.pl
check_oe_access();
my $order = _make_record();
set_headings($form->{"id"} ? "edit" : "add");
$form->{update} = 1;
......
$form->{"sellprice_$i"} = $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
$form->{"lastcost_$i"} = $form->format_amount(\%myconfig, $form->{"lastcost_$i"}, $decimalplaces);
$form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"}, $dec_qty);
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
# build up html code for prices_$i
&set_pricegroup($i);
}
display_form();
......
$form->format_amount(\%myconfig, $form->{"qty_$i"}, $dec_qty);
}
# show pricegroup in newly loaded invoice when creating invoice from quotation/order
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
set_pricegroup($_) for 1 .. $form->{rowcount};
&display_form;
$main::lxdebug->leave_sub();
......
$::form->error($::locale->text('No action defined.'));
}
sub _make_record {
my $obj = SL::DB::Order->new;
for my $method (keys %$::form) {
next unless $obj->can($method);
next unless $obj->meta->column($method);
if ($obj->meta->column($method)->isa('Rose::DB::Object::Metadata::Column::Date')) {
$obj->${\"$method\_as_date"}($::form->{$method});
} elsif ((ref $obj->meta->column($method)) =~ /^Rose::DB::Object::Metadata::Column::(?:Integer|Numeric|Float|DoublePrecsion)$/) {
$obj->$method($::form->{$method});
}
}
my @items;
for my $i (1 .. $::form->{rowcount}) {
next unless $::form->{"id_$i"};
push @items, _make_record_item($i)
}
$obj->orderitems(@items);
return $obj;
}
locale/de/all
'No.' => 'Position',
'No/individual shipping address' => 'Keine/individuelle Lieferadresse',
'None' => 'Kein',
'None (PriceSource)' => 'Freier Preis',
'Normal users cannot log in.' => 'Normale Benutzer können sich nicht anmelden.',
'Normalize Customer / Vendor names' => 'Normalisierung Kunden- / Lieferantennamen',
'Normalize part description and part notes' => 'Normalisierung Artikelbeschreibung und Artikellangtext (Bemerkung)',
......
'Price' => 'Preis',
'Price Factor' => 'Preisfaktor',
'Price Factors' => 'Preisfaktoren',
'Price Source' => 'Preisquelle',
'Price factor (database ID)' => 'Preisfaktor (Datenbank-ID)',
'Price factor (name)' => 'Preisfaktor (Name)',
'Price factor deleted!' => 'Preisfaktor gel&ouml;scht.',
......
'no article assigned yet' => 'noch kein Artikel zugewiesen',
'no bestbefore' => 'keine Mindesthaltbarkeit',
'no chargenumber' => 'keine Chargennummer',
'none (pricegroup)' => 'keine',
'not configured' => 'nicht konfiguriert',
'not delivered' => 'nicht geliefert',
'not executed' => 'nicht ausgeführt',
sql/Pg-upgrade2/recorditem_active_price_source.sql
-- @tag: recorditem_active_price_source
-- @description: Preisquelle in Belegpositionen
-- @depends: release_2_6_2
-- @encoding: utf-8
ALTER TABLE orderitems ADD COLUMN active_price_source TEXT NOT NULL DEFAULT '';
ALTER TABLE delivery_order_items ADD COLUMN active_price_source TEXT NOT NULL DEFAULT '';
ALTER TABLE invoice ADD COLUMN active_price_source TEXT NOT NULL DEFAULT '';
templates/webpages/oe/_price_sources_row.html
[%- USE T8 %]
[%- USE HTML %]
[%- USE L %]
[%- USE LxERP %]
<tr class="listrow[% i % 2 %]" id="row[% i %]_3" style='display:none'>
<td colspan="[% row.colspan %]">
<span class="[% IF !row.obj.active_price_source %]bold[% END %]">
[% L.radio_button_tag('active_price_source_' _ i, label=LxERP.t8('None (PriceSource)'), checked=!row.obj.active_price_source, value='', onChange='update_price_source(' _ i _ ', \'\')') %]
</span>
[%- FOREACH price IN price_sources.$i.available_prices %]
<div class="[% IF price.source == row.obj.active_price_source %]bold[% END %]">
[% L.radio_button_tag('active_price_source_' _ i, value=price.source, checked=price.source == row.obj.active_price_source, label=LxERP.format_amount(price.price, 2) _ ' (' _ price.full_description _ ')', onChange='update_price_source(' _ i _ ', \'' _ price.source _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')' ) %]
</div>
[%- END %]
</td>
</tr>
templates/webpages/oe/sales_order.html
[%- USE T8 %]
[%- USE HTML %]
[%- USE L %]
[%- USE LxERP %]
[%- PROCESS 'amcvar/render_inputs_block.html' %]
<tr>
<td>
......
</td>
</tr>
... Dieser Diff wurde abgeschnitten, weil er die maximale Anzahl anzuzeigender Zeilen überschreitet.

Auch abrufbar als: Unified diff