Revision 89b26688
Von Sven Schöling vor etwa 10 Jahren hinzugefügt
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 },
|
||
active_price_source => { type => 'text', default => '', not_null => 1 },
|
||
active_discount_source => { type => 'text', default => '', not_null => 1 },
|
||
active_price_source => { type => 'text', default => '', not_null => 1 },
|
||
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 },
|
||
);
|
||
|
||
__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 },
|
||
active_price_source => { type => 'text', default => '', not_null => 1 },
|
||
active_discount_source => { type => 'text', default => '', not_null => 1 },
|
||
active_price_source => { type => 'text', default => '', not_null => 1 },
|
||
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 },
|
||
);
|
||
|
||
__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 },
|
||
active_price_source => { type => 'text', default => '', not_null => 1 },
|
||
active_discount_source => { type => 'text', default => '', not_null => 1 },
|
||
active_price_source => { type => 'text', default => '', not_null => 1 },
|
||
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 },
|
||
);
|
||
|
||
__PACKAGE__->meta->primary_key_columns([ 'id' ]);
|
SL/DO.pm | ||
---|---|---|
sellprice, discount, unit, reqdate, project_id, serialnumber,
|
||
ordnumber, transdate, cusordnumber,
|
||
lastcost, price_factor_id, price_factor, marge_price_factor, pricegroup_id,
|
||
active_price_source)
|
||
active_price_source, active_discount_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 =
|
||
... | ... | |
conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
|
||
conv_i($form->{"marge_price_factor_$i"}),
|
||
$pricegroup_id,
|
||
$form->{"active_price_source_$i"});
|
||
$form->{"active_price_source_$i"}, $form->{"active_discount_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,
|
||
doi.active_price_source, doi.active_discount_source,
|
||
pr.projectnumber, dord.transdate AS dord_transdate, dord.donumber,
|
||
pg.partsgroup
|
||
FROM delivery_order_items doi
|
SL/IR.pm | ||
---|---|---|
$query =
|
||
qq|INSERT INTO invoice (id, trans_id, parts_id, description, longdescription, qty, base_qty,
|
||
sellprice, fxsellprice, discount, allocated, unit, deliverydate,
|
||
project_id, serialnumber, price_factor_id, price_factor, marge_price_factor)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT factor FROM price_factors WHERE id = ?), ?, ?)|;
|
||
project_id, serialnumber, price_factor_id, price_factor, marge_price_factor,
|
||
active_price_source, active_discount_source)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (SELECT factor FROM price_factors WHERE id = ?), ?, ?, ?)|;
|
||
@values = ($invoice_id, conv_i($form->{id}), conv_i($form->{"id_$i"}),
|
||
$form->{"description_$i"}, $restricter->process($form->{"longdescription_$i"}), $form->{"qty_$i"} * -1,
|
||
$baseqty * -1, $form->{"sellprice_$i"}, $fxsellprice, $form->{"discount_$i"}, $allocated,
|
||
$form->{"unit_$i"}, conv_date($form->{deliverydate}),
|
||
conv_i($form->{"project_id_$i"}), $form->{"serialnumber_$i"},
|
||
conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"marge_price_factor_$i"}),
|
||
conv_i($form->{"active_price_source_$i"}),
|
||
conv_i($form->{"active_price_source_$i"}), conv_i($form->{"active_discount_source_$i"}),
|
||
);
|
||
do_query($form, $dbh, $query, @values);
|
||
|
||
... | ... | |
|
||
i.id AS invoice_id,
|
||
i.description, i.longdescription, i.qty, i.fxsellprice AS sellprice, i.parts_id AS id, i.unit, i.deliverydate, i.project_id, i.serialnumber,
|
||
i.price_factor_id, i.price_factor, i.marge_price_factor, i.discount, i.active_price_source,
|
||
i.price_factor_id, i.price_factor, i.marge_price_factor, i.discount, i.active_price_source, i.active_discount_source,
|
||
p.partnumber, p.inventory_accno_id AS part_inventory_accno_id, pr.projectnumber, pg.partsgroup
|
||
|
||
FROM invoice i
|
SL/IS.pm | ||
---|---|---|
sellprice, fxsellprice, discount, allocated, assemblyitem,
|
||
unit, deliverydate, project_id, serialnumber, pricegroup_id,
|
||
ordnumber, donumber, transdate, cusordnumber, base_qty, subtotal,
|
||
marge_percent, marge_total, lastcost, active_price_source,
|
||
marge_percent, marge_total, lastcost, active_price_source, active_discount_source,
|
||
|
||
price_factor_id, price_factor, marge_price_factor)
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
||
(SELECT factor FROM price_factors WHERE id = ?), ?)|;
|
||
|
||
@values = ($invoice_id, conv_i($form->{id}), conv_i($form->{"id_$i"}),
|
||
... | ... | |
$form->{"cusordnumber_$i"}, $baseqty, $form->{"subtotal_$i"} ? 't' : 'f',
|
||
$form->{"marge_percent_$i"}, $form->{"marge_absolut_$i"},
|
||
$form->{"lastcost_$i"},
|
||
$form->{"active_price_source_$i"},
|
||
$form->{"active_price_source_$i"}, $form->{"active_discount_source_$i"},
|
||
conv_i($form->{"price_factor_id_$i"}), conv_i($form->{"price_factor_id_$i"}),
|
||
conv_i($form->{"marge_price_factor_$i"}));
|
||
do_query($form, $dbh, $query, @values);
|
||
... | ... | |
i.id AS invoice_id,
|
||
i.description, i.longdescription, i.qty, i.fxsellprice AS sellprice, i.discount, i.parts_id AS id, i.unit, i.deliverydate AS reqdate,
|
||
i.project_id, i.serialnumber, i.id AS invoice_pos, i.pricegroup_id, i.ordnumber, i.donumber, i.transdate, i.cusordnumber, i.subtotal, i.lastcost,
|
||
i.price_factor_id, i.price_factor, i.marge_price_factor, i.active_price_source,
|
||
i.price_factor_id, i.price_factor, i.marge_price_factor, i.active_price_source, i.active_discount_source,
|
||
p.partnumber, p.assembly, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id, p.formel, p.listprice,
|
||
pr.projectnumber, pg.partsgroup, prg.pricegroup
|
||
|
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 = ?,
|
||
active_price_source = ?, active_discount_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"},
|
||
$form->{"active_price_source_$i"}, $form->{"active_discount_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.active_price_source,
|
||
o.price_factor_id, o.price_factor, o.marge_price_factor, o.active_price_source, o.active_discount_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 | ||
---|---|---|
scalar => [ qw(record_item record) ],
|
||
);
|
||
|
||
use List::UtilsBy qw(min_by);
|
||
use List::UtilsBy qw(min_by max_by);
|
||
use SL::PriceSource::ALL;
|
||
use SL::PriceSource::Price;
|
||
use SL::Locale::String;
|
||
... | ... | |
sub all_price_sources {
|
||
my ($self) = @_;
|
||
|
||
return map {
|
||
map {
|
||
$_->new(record_item => $self->record_item, record => $self->record)
|
||
} SL::PriceSource::ALL->all_enabled_price_sources
|
||
}
|
||
... | ... | |
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)
|
||
? $class->new(record_item => $self->record_item, record => $self->record)->price_from_source($source, $spec)
|
||
: empty_price();
|
||
}
|
||
|
||
... | ... | |
map { $_->available_prices } $_[0]->all_price_sources;
|
||
}
|
||
|
||
sub available_discounts {
|
||
map { $_->available_discounts } $_[0]->all_price_sources;
|
||
}
|
||
|
||
sub best_price {
|
||
min_by { $_->price } grep { $_->price > 0 } map { $_->best_price } $_[0]->all_price_sources;
|
||
min_by { $_->price } grep { $_->price > 0 } grep { $_ } map { $_->best_price } $_[0]->all_price_sources;
|
||
}
|
||
|
||
sub best_discount {
|
||
max_by { $_->discount } grep { $_->discount } grep { $_ } map { $_->best_discount } $_[0]->all_price_sources;
|
||
}
|
||
|
||
sub empty_price {
|
SL/PriceSource/ALL.pm | ||
---|---|---|
use SL::PriceSource::Pricegroup;
|
||
use SL::PriceSource::MasterData;
|
||
use SL::PriceSource::Makemodel;
|
||
use SL::PriceSource::Customer;
|
||
use SL::PriceSource::Vendor;
|
||
use SL::PriceSource::Business;
|
||
|
||
my %price_sources_by_name = (
|
||
master_data => 'SL::PriceSource::MasterData',
|
||
customer => 'SL::PriceSource::Customer',
|
||
vendor => 'SL::PriceSource::Vendor',
|
||
pricegroup => 'SL::PriceSource::Pricegroup',
|
||
makemodel => 'SL::PriceSource::Makemodel',
|
||
business => 'SL::PriceSource::Business',
|
||
);
|
||
|
||
my @price_sources_order = qw(
|
||
master_data
|
||
customer
|
||
vendor
|
||
pricegroup
|
||
makemodel
|
||
business
|
||
);
|
||
|
||
sub all_enabled_price_sources {
|
SL/PriceSource/Base.pm | ||
---|---|---|
|
||
sub available_prices { die 'available_prices needs to be implemented' }
|
||
|
||
sub available_discounts { die 'available_discounts needs to be implemented' }
|
||
|
||
sub best_price { die 'best_price needs to be implemented' }
|
||
|
||
sub best_discounts { die 'best_discounts needs to be implemented' }
|
||
|
||
sub price_from_source { die 'price_from_source needs to be implemented:' . "@_" }
|
||
|
||
sub part {
|
||
$_[0]->record_item->part;
|
||
}
|
||
|
||
sub customer_vendor {
|
||
$_[0]->record->is_sales ? $_[0]->record->customer : $_[0]->record->vendor;
|
||
}
|
||
|
||
1;
|
||
|
||
__END__
|
||
... | ... | |
|
||
Shortcut to C<< record_item->part >>
|
||
|
||
=item C<customer_vendor>
|
||
|
||
Shortcut to C<< record->is_sales ? record->customer : record->vendor >>
|
||
|
||
=back
|
||
|
||
=head1 INTERFACE METHODS
|
||
... | ... | |
to recreate it later. Try to be brief, no one needs 20 different price
|
||
suggestions.
|
||
|
||
=item C<available_discounts>
|
||
|
||
Must return a list of all prices that you algorithm can recommend the user
|
||
for the current situation. Each discount must have a unique spec that can be
|
||
used to recreate it later. Try to be brief, no one needs 20 different discount
|
||
suggestions.
|
||
|
||
=item C<best_price>
|
||
|
||
Must return what you think of as the best matching price in your
|
||
C<available_prices>. This does not have to be the lowest price, but it will be
|
||
compared later to other price sources, and the lowest will be set.
|
||
|
||
=item C<best_discount>
|
||
|
||
Must return what you think of as the best matching discount in your
|
||
C<available_discounts>. This does not have to be the highest discount, but it
|
||
will be compared later to other price sources, and the highest will be set.
|
||
|
||
=item C<price_from_source SOURCE, SPEC>
|
||
|
||
Must recreate the price from C<SPEC> and return. For reference, the complete
|
||
C<SOURCE> entry from C<record_item.active_price_source> is included.
|
||
Must recreate the price or discount from C<SPEC> and return. For reference, the
|
||
complete C<SOURCE> entry from C<record_item.active_price_source> or
|
||
C<record_item.active_discount_source> is included.
|
||
|
||
Note that constraints from the rest of the C<record> do not apply anymore. If
|
||
information needed for the retrieval can be deleted elsewhere, then you must
|
SL/PriceSource/Business.pm | ||
---|---|---|
package SL::PriceSource::Business;
|
||
|
||
use strict;
|
||
use parent qw(SL::PriceSource::Base);
|
||
|
||
use SL::DB::Business;
|
||
use SL::PriceSource::Discount;
|
||
use SL::Locale::String;
|
||
|
||
sub name { 'business' }
|
||
|
||
sub description { t8('Business') }
|
||
|
||
sub available_prices { }
|
||
|
||
sub available_discounts {
|
||
my ($self, %params) = @_;
|
||
|
||
return unless $self->customer_vendor;
|
||
return unless $self->customer_vendor->business;
|
||
return unless $self->customer_vendor->business->discount != 0;
|
||
|
||
SL::PriceSource::Discount->new(
|
||
discount => $self->customer_vendor->business->discount,
|
||
spec => $self->customer_vendor->business->id,
|
||
description => t8('Business Discount'),
|
||
price_source => $self,
|
||
);
|
||
}
|
||
|
||
sub price_from_source {
|
||
my ($self, $source, $spec) = @_;
|
||
|
||
my $business = SL::DB::Business->load_cached($spec);
|
||
|
||
if (!$business) {
|
||
return SL::PriceSource::Discount->new(
|
||
missing => t8('Could not load this business'),
|
||
price_source => $self,
|
||
)
|
||
}
|
||
|
||
if (!$self->customer_vendor) {
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $business->discount,
|
||
spec => $business->id,
|
||
description => t8('Business Discount'),
|
||
price_source => $self,
|
||
invalid => t8('This discount is only valid in records with customer or vendor'),
|
||
)
|
||
}
|
||
|
||
if ($business->id != $self->customer_vendor->business->id) {
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $business->discount,
|
||
spec => $business->id,
|
||
description => t8('Business Discount'),
|
||
price_source => $self,
|
||
invalid => t8('This discount is only valid for business #1', $business->full_description),
|
||
)
|
||
}
|
||
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $business->discount,
|
||
spec => $business->id,
|
||
description => t8('Business Discount'),
|
||
price_source => $self,
|
||
);
|
||
}
|
||
|
||
sub best_price { }
|
||
|
||
sub best_discount {
|
||
&available_discounts;
|
||
}
|
||
|
||
1;
|
||
|
SL/PriceSource/Customer.pm | ||
---|---|---|
package SL::PriceSource::Customer;
|
||
|
||
use strict;
|
||
use parent qw(SL::PriceSource::Base);
|
||
|
||
use SL::DB::Customer;
|
||
use SL::PriceSource::Discount;
|
||
use SL::Locale::String;
|
||
|
||
sub name { 'customer_discount' }
|
||
|
||
sub description { t8('Customer Discount') }
|
||
|
||
sub available_prices { }
|
||
|
||
sub available_discounts {
|
||
my ($self, %params) = @_;
|
||
|
||
return unless $self->record->is_sales;
|
||
return unless $self->record->customer;
|
||
return unless $self->record->customer->discount != 0;
|
||
|
||
SL::PriceSource::Discount->new(
|
||
discount => $self->record->customer->discount,
|
||
spec => $self->record->customer->id,
|
||
description => t8('Customer Discount'),
|
||
price_source => $self,
|
||
);
|
||
}
|
||
|
||
sub price_from_source {
|
||
my ($self, $source, $spec) = @_;
|
||
|
||
my $customer = SL::DB::Customer->load_cached($spec);
|
||
|
||
if (!$customer) {
|
||
return SL::PriceSource::Discount->new(
|
||
missing => t8('Could not load this customer'),
|
||
price_source => $self,
|
||
)
|
||
}
|
||
|
||
if (!$self->record->customer) {
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $customer->discount,
|
||
spec => $customer->id,
|
||
description => t8('Customer Discount'),
|
||
price_source => $self,
|
||
invalid => t8('This discount is only valid in sales documents'),
|
||
)
|
||
}
|
||
|
||
if ($customer->id != $self->record->customer->id) {
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $customer->discount,
|
||
spec => $customer->id,
|
||
description => t8('Customer Discount'),
|
||
price_source => $self,
|
||
invalid => t8('This discount is only valid for customer #1', $customer->full_description),
|
||
)
|
||
}
|
||
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $customer->discount,
|
||
spec => $customer->id,
|
||
description => t8('Customer Discount'),
|
||
price_source => $self,
|
||
);
|
||
}
|
||
|
||
sub best_price { }
|
||
|
||
sub best_discount {
|
||
&available_discounts;
|
||
}
|
||
|
||
1;
|
||
|
SL/PriceSource/Discount.pm | ||
---|---|---|
package SL::PriceSource::Discount;
|
||
|
||
use strict;
|
||
|
||
use parent 'SL::DB::Object';
|
||
use Rose::Object::MakeMethods::Generic (
|
||
scalar => [ qw(discount description spec price_source invalid missing) ],
|
||
);
|
||
|
||
require SL::DB::Helper::Attr;
|
||
SL::DB::Helper::Attr::make(__PACKAGE__,
|
||
discount => 'numeric(15,5)',
|
||
);
|
||
|
||
sub source {
|
||
$_[0]->price_source
|
||
? $_[0]->price_source->name . '/' . $_[0]->spec
|
||
: '';
|
||
}
|
||
|
||
sub full_description {
|
||
my ($self) = @_;
|
||
|
||
$self->price_source
|
||
? $self->price_source->description . ': ' . $self->description
|
||
: $self->description
|
||
}
|
||
|
||
sub source_description {
|
||
my ($self) = @_;
|
||
|
||
$self->price_source
|
||
? $self->price_source->description
|
||
: $self->description
|
||
}
|
||
|
||
sub to_str {
|
||
"source: @{[ $_[0]->source ]}, discount: @{[ $_[0]->discount ]}, description: @{[ $_[0]->description ]}"
|
||
}
|
||
|
||
1;
|
||
|
||
__END__
|
||
|
||
=encoding utf-8
|
||
|
||
=head1 NAME
|
||
|
||
SL::PriceSource::Price - contrainer to pass calculated prices around
|
||
|
||
=head1 SYNOPSIS
|
||
|
||
# in PriceSource::Base implementation
|
||
$price = SL::PriceSource::Price->new(
|
||
discount => 10,
|
||
spec => 'summersale2014', # something you can easily parse later
|
||
description => t8('10% discount during summer sale 2014'),
|
||
price_source => $self,
|
||
)
|
||
|
||
# special empty price in SL::PriceSource, for internal use.
|
||
SL::PriceSource::Price->new(
|
||
description => t8('None (PriceSource)'),
|
||
);
|
||
|
||
# price can't be restored
|
||
SL::PriceSource::Price->new(
|
||
missing => t8('Um, sorry, cannot find that one'),
|
||
price_source => $self,
|
||
);
|
||
|
||
# invalid price
|
||
SL::PriceSource::Price->new(
|
||
price => $original_price,
|
||
spec => $original_spec,
|
||
description => $original_description,
|
||
invalid => t8('Offer expired #1 weeks ago', $dt->delta_weeks),
|
||
price_source => $self,
|
||
);
|
||
|
||
=head1 DESCRIPTION
|
||
|
||
See L<SL::PriceSource> for information about the mechanism.
|
||
|
||
This is a container for prices that are generated by L<SL::PriceSource::Base>
|
||
implementations.
|
||
|
||
=head1 CONSTRUCTOR FIELDS
|
||
|
||
=over 4
|
||
|
||
=item C<discount>
|
||
|
||
The discount in percent. A discount of 0 will be ignored. If passed as
|
||
part of C<available_prices> it will be filtered out. If returned as
|
||
C<best_price> or C<price_from_source> it will trigger a warning.
|
||
|
||
=item C<spec>
|
||
|
||
A unique string that can later be understood by the creating implementation.
|
||
Can be empty if the implementation only supports one price for a given
|
||
record_item.
|
||
|
||
=item C<description>
|
||
|
||
A localized short description of the origins of this price.
|
||
|
||
=item C<price_source>
|
||
|
||
A ref to the creating algorithm.
|
||
|
||
=item C<missing>
|
||
|
||
OPTIONAL. Both indicator and localized message that the price with this spec
|
||
could not be reproduced and should be changed.
|
||
|
||
If price is missing, you do not need to supply anything except C<source>.
|
||
|
||
=item C<invalid>
|
||
|
||
OPTIONAL. Both indicator and localized message that the conditions for this
|
||
price are no longer valid, and that the price should be changed.
|
||
|
||
If price is missing, you do not need to supply anything except C<source>.
|
||
|
||
=back
|
||
|
||
=head1 SEE ALSO
|
||
|
||
L<SL::PriceSource>,
|
||
L<SL::PriceSource::Base>,
|
||
L<SL::PriceSource::ALL>
|
||
|
||
=head1 BUGS
|
||
|
||
None yet. :)
|
||
|
||
=head1 AUTHOR
|
||
|
||
Sven Schoeling E<lt>s.schoeling@linet-services.deE<gt>
|
||
|
||
=cut
|
SL/PriceSource/Makemodel.pm | ||
---|---|---|
$self->part->makemodels;
|
||
}
|
||
|
||
sub available_discounts { }
|
||
|
||
sub price_from_source {
|
||
my ($self, $source, $spec) = @_;
|
||
|
||
... | ... | |
|
||
}
|
||
|
||
sub best_discount { }
|
||
|
||
sub make_price_from_makemodel {
|
||
my ($self, $makemodel) = @_;
|
||
|
SL/PriceSource/MasterData.pm | ||
---|---|---|
: ($self->make_lastcost, $self->make_listprice);
|
||
}
|
||
|
||
sub available_discounts { }
|
||
|
||
sub price_from_source {
|
||
my ($self, $source, $spec) = @_;
|
||
|
||
... | ... | |
: $_[0]->make_lastcost
|
||
}
|
||
|
||
sub best_discount { }
|
||
|
||
sub make_sellprice {
|
||
my ($self) = @_;
|
||
|
SL/PriceSource/Price.pm | ||
---|---|---|
scalar => [ qw(price description spec price_source invalid missing) ],
|
||
);
|
||
|
||
use SL::DB::Helper::Attr;
|
||
require 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
|
||
? $_[0]->price_source->name . '/' . $_[0]->spec
|
||
: '';
|
||
}
|
||
|
||
... | ... | |
|
||
$self->price_source
|
||
? $self->price_source->description
|
||
: $self->description
|
||
: $self->description
|
||
}
|
||
|
||
sub to_str {
|
||
"source: @{[ $_[0]->source ]}, price: @{[ $_[0]->price]}, description: @{[ $_[0]->description ]}"
|
||
"source: @{[ $_[0]->source ]}, price: @{[ $_[0]->price ]}, description: @{[ $_[0]->description ]}"
|
||
}
|
||
|
||
1;
|
||
... | ... | |
# in PriceSource::Base implementation
|
||
$price = SL::PriceSource::Price->new(
|
||
price => 10.3,
|
||
spec => '10.3', # something you can easily parse later
|
||
description => t8('Fix price 10.3'),
|
||
spec => '3', # something you can easily parse later
|
||
description => t8('Fix price 10.3 for customer 3'),
|
||
price_source => $self,
|
||
)
|
||
|
||
# special empty price in SL::PriceSource
|
||
# special empty price in SL::PriceSource, for internal use.
|
||
SL::PriceSource::Price->new(
|
||
description => t8('None (PriceSource)'),
|
||
);
|
||
|
||
# invalid price
|
||
# price can't be restored
|
||
SL::PriceSource::Price->new(
|
||
price => $original_price,
|
||
spec => $original_spec,
|
||
description => $original_description,
|
||
invalid => t8('Offer expired #1 weeks ago', $dt->delta_weeks),
|
||
missing => t8('Um, sorry, cannot find that one'),
|
||
price_source => $self,
|
||
);
|
||
|
||
# missing price
|
||
# invalid price
|
||
SL::PriceSource::Price->new(
|
||
price => $original_price, # will keep last entered price
|
||
price => $original_price,
|
||
spec => $original_spec,
|
||
description => '',
|
||
missing => t8('Um, sorry, cannot find that one'),
|
||
description => $original_description,
|
||
invalid => t8('Offer expired #1 weeks ago', $dt->delta_weeks),
|
||
price_source => $self,
|
||
);
|
||
|
||
|
||
=head1 DESCRIPTION
|
||
|
||
See L<SL::PriceSource> for information about the mechanism.
|
||
... | ... | |
|
||
The price. A price of 0 is special and is considered undesirable. If passed as
|
||
part of C<available_prices> it will be filtered out. If returned as
|
||
C<best_price> or C<price_from_source> it will be warned about.
|
||
C<best_price> or C<price_from_source> it will trigger a warning.
|
||
|
||
=item C<spec>
|
||
|
||
... | ... | |
OPTIONAL. Both indicator and localized message that the price with this spec
|
||
could not be reproduced and should be changed.
|
||
|
||
If price is missing, you do not need to supply anything except C<source>.
|
||
|
||
=item C<invalid>
|
||
|
||
OPTIONAL. Both indicator and localized message that the conditions for this
|
||
price are no longer valid, and that the price should be changed.
|
||
|
||
If price is missing, you do not need to supply anything except C<source>.
|
||
|
||
=back
|
||
|
||
=head1 SEE ALSO
|
SL/PriceSource/Pricegroup.pm | ||
---|---|---|
} @$prices;
|
||
}
|
||
|
||
sub available_discounts { }
|
||
|
||
sub price_from_source {
|
||
my ($self, $source, $spec) = @_;
|
||
|
||
... | ... | |
return $best_price || ();
|
||
}
|
||
|
||
sub best_discount { }
|
||
|
||
sub make_price {
|
||
my ($self, $price_obj) = @_;
|
||
|
SL/PriceSource/Vendor.pm | ||
---|---|---|
package SL::PriceSource::Vendor;
|
||
|
||
use strict;
|
||
use parent qw(SL::PriceSource::Base);
|
||
|
||
use SL::DB::Vendor;
|
||
use SL::PriceSource::Price;
|
||
use SL::Locale::String;
|
||
|
||
sub name { 'vendor_discount' }
|
||
|
||
sub description { t8('Vendor Discount') }
|
||
|
||
sub available_prices { }
|
||
|
||
sub available_discounts {
|
||
my ($self, %params) = @_;
|
||
|
||
return if $self->record->is_sales;
|
||
return unless $self->record->vendor;
|
||
return unless $self->record->vendor->discount != 0;
|
||
|
||
SL::PriceSource::Vendor->new(
|
||
discount => $self->record->vendor->discount,
|
||
spec => $self->record->vendor->id,
|
||
description => t8('Vendor Discount'),
|
||
price_source => $self,
|
||
);
|
||
}
|
||
|
||
sub price_from_source {
|
||
my ($self, $source, $spec) = @_;
|
||
|
||
my $vendor = SL::DB::Vendor->load_cached($spec);
|
||
|
||
if (!$vendor) {
|
||
return SL::PriceSource::Discount->new(
|
||
missing => t8('Could not load this vendor'),
|
||
price_source => $self,
|
||
)
|
||
}
|
||
|
||
if (!$self->record->vendor) {
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $vendor->discount,
|
||
spec => $vendor->id,
|
||
description => t8('Vendor Discount'),
|
||
price_source => $self,
|
||
invalid => t8('This discount is only valid in purchase documents'),
|
||
)
|
||
}
|
||
|
||
if ($vendor->id != $self->record->vendor->id) {
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $vendor->discount,
|
||
spec => $vendor->id,
|
||
description => t8('Vendor Discount'),
|
||
price_source => $self,
|
||
invalid => t8('This discount is only valid for vendor #1', $vendor->full_description),
|
||
)
|
||
}
|
||
|
||
return SL::PriceSource::Discount->new(
|
||
discount => $vendor->discount,
|
||
spec => $vendor->id,
|
||
description => t8('Vendor Discount'),
|
||
price_source => $self,
|
||
);
|
||
}
|
||
|
||
|
||
sub best_price { }
|
||
|
||
sub best_discount {
|
||
&available_discounts;
|
||
}
|
||
|
||
1;
|
||
|
bin/mozilla/do.pl | ||
---|---|---|
map { $form->{"${_}_$i"} = $form->{item_list}[0]{$_} } keys %{ $form->{item_list}[0] };
|
||
|
||
$form->{"marge_price_factor_$i"} = $form->{item_list}->[0]->{price_factor};
|
||
$form->{"sellprice_$i"} = $form->format_amount(\%myconfig, $form->{"sellprice_$i"} * (1 - $form->{tradediscount}));
|
||
$form->{"sellprice_$i"} = $form->format_amount(\%myconfig, $form->{"sellprice_$i"});
|
||
$form->{"lastcost_$i"} = $form->format_amount(\%myconfig, $form->{"lastcost_$i"});
|
||
$form->{"qty_$i"} = $form->format_amount(\%myconfig, $form->{"qty_$i"});
|
||
}
|
bin/mozilla/io.pl | ||
---|---|---|
for my $i (1 .. $numrows) {
|
||
my %column_data = ();
|
||
|
||
my $record_item = $record->id && $record->items ? $record->items->[$i-1] : _make_record_item($i);
|
||
|
||
# undo formatting
|
||
map { $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"}) }
|
||
qw(qty discount sellprice lastcost price_new price_old)
|
||
... | ... | |
$form->{"sellprice_$i"} = $form->{"price_new_$i"};
|
||
}
|
||
|
||
my $record_item = $record->id && $record->items ? $record->items->[$i-1] : _make_record_item($i);
|
||
|
||
# unit begin
|
||
$form->{"unit_old_$i"} ||= $form->{"unit_$i"};
|
||
$form->{"selected_unit_$i"} ||= $form->{"unit_$i"};
|
||
... | ... | |
}
|
||
|
||
my $sellprice_value = $form->format_amount(\%myconfig, $form->{"sellprice_$i"}, $decimalplaces);
|
||
my $discount_value = $form->format_amount(\%myconfig, $form->{"discount_$i"});
|
||
my $edit_prices = $main::auth->assert('edit_prices', 1) && !$::form->{"active_price_source_$i"};
|
||
my $edit_discounts = $main::auth->assert('edit_prices', 1) && !$::form->{"active_discount_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"}))
|
||
: $cgi->textfield(-name => "discount_$i", -size => 3, -value => $form->format_amount(\%myconfig, $form->{"discount_$i"}));
|
||
$column_data{discount} = (!$edit_discounts)
|
||
? $cgi->hidden( -name => "discount_$i", -id => "discount_$i", -value => $discount_value) . $discount_value . ' %'
|
||
: $cgi->textfield(-name => "discount_$i", -id => "discount_$i", -size => 3, -value => $discount_value);
|
||
$column_data{linetotal} = $form->format_amount(\%myconfig, $linetotal, 2);
|
||
$column_data{bin} = $form->{"bin_$i"};
|
||
|
||
... | ... | |
|
||
if ($form->{"id_${i}"} && !$is_delivery_order) {
|
||
my $price_source = SL::PriceSource->new(record_item => $record_item, record => $record);
|
||
my $price = $price_source->price_from_source($::form->{"active_price_source_$i"});
|
||
my $price = $price_source->price_from_source($::form->{"active_price_source_$i"});
|
||
my $discount = $price_source->price_from_source($::form->{"active_discount_source_$i"});
|
||
$column_data{price_source} .= $cgi->button(-value => $price->source_description, -onClick => "kivi.io.price_chooser($i)");
|
||
if ($price->source) {
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $price->invalid, title => $price->invalid }) if $price->invalid;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $price->missing, title => $price->missing }) if $price->missing;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/up.png', alt => t8('This price has since gone up'), title => t8('This price has since gone up' ) }) if $price->price > $record_item->sellprice;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/down.png', alt => t8('This price has since gone down'), title => t8('This price has since gone down') }) if $price->price < $record_item->sellprice;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/ok.png', alt => t8('There is a better price available'), title => t8('There is a better price available') }) if $price->source ne $price_source->best_price->source;
|
||
if (!$price->missing && !$price->invalid) {
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/up.png', alt => t8('This price has since gone up'), title => t8('This price has since gone up' ) }) if $price->price > $record_item->sellprice;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/down.png', alt => t8('This price has since gone down'), title => t8('This price has since gone down') }) if $price->price < $record_item->sellprice;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/ok.png', alt => t8('There is a better price available'), title => t8('There is a better price available') }) if $price->source ne $price_source->best_price->source;
|
||
}
|
||
}
|
||
if ($discount->source) {
|
||
$column_data{discount_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $discount->invalid, title => $discount->invalid }) if $discount->invalid;
|
||
$column_data{discount_source} .= ' ' . $cgi->img({src => 'image/flag-red.png', alt => $discount->missing, title => $discount->missing }) if $discount->missing;
|
||
if (!$discount->missing && !$discount->invalid) {
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/up.png', alt => t8('This discount has since gone up'), title => t8('This discount has since gone up') }) if $discount->discount * 100 > $record_item->discount;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/down.png', alt => t8('This discount has since gone down'), title => t8('This discount has since gone down') }) if $discount->discount * 100 < $record_item->discount;
|
||
$column_data{price_source} .= ' ' . $cgi->img({src => 'image/ok.png', alt => t8('There is a better discount available'), title => t8('There is a better discount available') }) if $discount->source ne $price_source->best_discount->source;
|
||
}
|
||
}
|
||
}
|
||
|
||
... | ... | |
$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 price_old id inventory_accno bin partsgroup partnotes active_price_source
|
||
(qw(orderitems_id bo price_old id inventory_accno bin partsgroup partnotes active_price_source active_discount_source
|
||
income_accno expense_accno listprice assembly taxaccounts ordnumber donumber transdate cusordnumber
|
||
longdescription basefactor marge_absolut marge_percent marge_price_factor weight), @hidden_vars)
|
||
);
|
||
... | ... | |
$::form->header;
|
||
|
||
my @item_list = map {
|
||
$_->{display_sellprice} = $_->{sellprice} * (1 - $::form->{tradediscount});
|
||
$_->{display_sellprice} /= $_->{price_factor} if ($_->{price_factor});
|
||
$_;
|
||
} @{ $::form->{item_list} };
|
||
... | ... | |
$::form->{"active_price_source_$i"} = $best_price->source;
|
||
}
|
||
|
||
my $best_discount = $price_source->best_discount;
|
||
|
||
if ($best_discount) {
|
||
$::form->{"discount_$i"} = $best_discount->discount;
|
||
$::form->{"active_discount_source_$i"} = $best_discount->source;
|
||
}
|
||
|
||
|
||
$form->{"marge_price_factor_$i"} = $new_item->{price_factor};
|
||
|
||
... | ... | |
$form->{"sellprice_$i"} =
|
||
$form->round_amount($form->{"sellprice_$i"}, $decimalplaces);
|
||
}
|
||
|
||
# tradediscount
|
||
if ($::form->{tradediscount}) {
|
||
$::form->{"sellprice_$i"} *= 1 - $::form->{tradediscount};
|
||
}
|
||
}
|
||
|
||
map { $form->{$_} = $form->parse_amount(\%myconfig, $form->{$_}) }
|
||
... | ... | |
transdate longdescription basefactor marge_total marge_percent
|
||
marge_price_factor lastcost price_factor_id partnotes
|
||
stock_out stock_in has_sernumber reqdate orderitems_id
|
||
active_price_source);
|
||
active_price_source active_discount_source);
|
||
|
||
my $ic_cvar_configs = CVar->get_configs(module => 'IC');
|
||
push @flds, map { "ic_cvar_$_->{name}" } @{ $ic_cvar_configs };
|
bin/mozilla/ir.pl | ||
---|---|---|
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;
|
||
my $best_discount = $price_source->best_discount;
|
||
|
||
if ($best_price) {
|
||
$::form->{"sellprice_$i"} = $best_price->price;
|
||
$::form->{"active_price_source_$i"} = $best_price->source;
|
||
}
|
||
if ($best_discount) {
|
||
$::form->{"discount_$i"} = $best_discount->discount;
|
||
$::form->{"active_discount_source_$i"} = $best_discount->source;
|
||
}
|
||
|
||
# if there is an exchange rate adjust sellprice
|
||
$form->{"sellprice_$i"} /= $exchangerate;
|
||
}
|
bin/mozilla/is.pl | ||
---|---|---|
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;
|
||
my $best_discount = $price_source->best_discount;
|
||
|
||
if ($best_price) {
|
||
$::form->{"sellprice_$i"} = $best_price->price;
|
||
$::form->{"active_price_source_$i"} = $best_price->source;
|
||
}
|
||
if ($best_discount) {
|
||
$::form->{"discount_$i"} = $best_discount->discount;
|
||
$::form->{"active_discount_source_$i"} = $best_discount->source;
|
||
}
|
||
|
||
# if there is an exchange rate adjust sellprice
|
||
$form->{"sellprice_$i"} *= (1 - $form->{tradediscount});
|
||
$form->{"sellprice_$i"} /= $exchangerate;
|
||
}
|
||
|
bin/mozilla/oe.pl | ||
---|---|---|
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;
|
||
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;
|
||
my $best_discount = $price_source->best_discount;
|
||
|
||
if ($best_price) {
|
||
$::form->{"sellprice_$i"} = $best_price->price;
|
||
$::form->{"active_price_source_$i"} = $best_price->source;
|
||
}
|
||
if ($best_discount) {
|
||
$::form->{"discount_$i"} = $best_discount->discount;
|
||
$::form->{"active_discount_source_$i"} = $best_discount->source;
|
||
}
|
||
|
||
$form->{"sellprice_$i"} *= (1 - $form->{tradediscount});
|
||
$form->{"sellprice_$i"} /= $exchangerate; # if there is an exchange rate adjust sellprice
|
||
}
|
||
|
js/kivi.io.js | ||
---|---|---|
if (price_str) $('#sellprice_' + row).val(price_str);
|
||
$('#update_button').click();
|
||
}
|
||
|
||
ns.update_discount_source = function(row, source, discount_str) {
|
||
$('#active_discount_source_' + row).val(source);
|
||
if (discount_str) $('#discount_' + row).val(discount_str);
|
||
$('#update_button').click();
|
||
}
|
||
});
|
locale/de/all | ||
---|---|---|
'Beratername' => 'Beratername',
|
||
'Beraternummer' => 'Beraternummer',
|
||
'Best Before' => 'Mindesthaltbarkeit',
|
||
'Best Discount' => 'Bester Rabatt',
|
||
'Best Price' => 'Bester Preis',
|
||
'Bilanz' => 'Bilanz',
|
||
'Billable amount' => 'Abrechenbarer Betrag',
|
||
... | ... | |
'Buchungsgruppen' => 'Buchungsgruppen',
|
||
'Buchungskonto' => 'Buchungskonto',
|
||
'Buchungsnummer' => 'Buchungsnummer',
|
||
'Business' => 'Kunden-/Lieferantentyp',
|
||
'Business Discount' => 'Kunden-/Lieferantentyp-Rabatt',
|
||
'Business Number' => 'Firmennummer',
|
||
'Business Volume' => 'Geschäftsvolumen',
|
||
'Business evaluation' => 'Betriebswirtschaftliche Auswertung',
|
||
... | ... | |
'Could not load class #1 (#2): "#3"' => 'Konnte Klasse #1 (#2) nicht laden: "#3"',
|
||
'Could not load class #1, #2' => 'Konnte Klasse #1 nicht laden: "#2"',
|
||
'Could not load employee' => 'Konnte Benutzer nicht laden',
|
||
'Could not load this business' => 'Konnte diesen Kunden-/Lieferantentyp nicht laden',
|
||
'Could not load this customer' => 'Konnte diesen Kunden nicht laden',
|
||
'Could not load this vendor' => 'Konnte diesen Lieferanten nicht laden',
|
||
'Could not print dunning.' => 'Die Mahnungen konnten nicht gedruckt werden.',
|
||
'Could not spawn ghostscript.' => 'Die Anwendung "ghostscript" konnte nicht gestartet werden.',
|
||
'Could not spawn the printer command.' => 'Die Druckanwendung konnte nicht gestartet werden.',
|
||
... | ... | |
'Customer' => 'Kunde',
|
||
'Customer (database ID)' => 'Kunde (Datenbank-ID)',
|
||
'Customer (name)' => 'Kunde (Name)',
|
||
'Customer Discount' => 'Kundenrabatt',
|
||
'Customer Master Data' => 'Kundenstammdaten',
|
||
'Customer Name' => 'Kundenname',
|
||
'Customer Number' => 'Kundennummer',
|
||
... | ... | |
'Destination warehouse' => 'Ziellager',
|
||
'Destination warehouse and bin' => 'Ziellager und -lagerplatz',
|
||
'Detail view' => 'Detailanzeige',
|
||
'Details' => 'Details',
|
||
'Details (one letter abbreviation)' => 'D',
|
||
'Dial command missing in kivitendo configuration\'s [cti] section' => 'Wählbefehl fehlt im Abschnitt [cti] der kivitendo-Konfiguration',
|
||
'Difference' => 'Differenz',
|
||
... | ... | |
'Discard duplicate entries in CSV file' => 'Doppelte Einträge in CSV-Datei verwerfen',
|
||
'Discard entries with duplicates in database or CSV file' => 'Einträge aus CSV-Datei verwerfen, die es bereits in der Datenbank oder der CSV-Datei gibt',
|
||
'Discount' => 'Rabatt',
|
||
'Discounts' => 'Rabatte',
|
||
'Display' => 'Anzeigen',
|
||
'Display file' => 'Datei anzeigen',
|
||
'Display options' => 'Anzeigeoptionen',
|
||
... | ... | |
'No.' => 'Position',
|
||
'No/individual shipping address' => 'Keine/individuelle Lieferadresse',
|
||
'None' => 'Kein',
|
||
'None (PriceSource Discount)' => 'Freier Rabatt',
|
||
'None (PriceSource)' => 'Freier Preis',
|
||
'Normal users cannot log in.' => 'Normale Benutzer können sich nicht anmelden.',
|
||
'Normalize Customer / Vendor names' => 'Normalisierung Kunden- / Lieferantennamen',
|
||
... | ... | |
'Pricegroup missing!' => 'Preisgruppe fehlt!',
|
||
'Pricegroup saved!' => 'Preisgruppe gespeichert!',
|
||
'Pricegroups' => 'Preisgruppen',
|
||
'Prices' => 'Preise',
|
||
'Print' => 'Drucken',
|
||
'Print and Post' => 'Drucken und Buchen',
|
||
'Print automatically' => 'Automatisch ausdrucken',
|
||
... | ... | |
'There are still transfers not matching the qty of the delivery order. Stock operations can not be changed later. Do you really want to proceed?' => 'Einige der Lagerbewegungen sind nicht vollständig und Lagerbewegungen können nachträglich nicht mehr verändert werden. Wollen Sie wirklich fortfahren?',
|
||
'There are undefined currencies in your system.' => 'In Ihrer Datenbank wurden Währungen benutzt, die nicht ordnungsgemäß in den Währungen eingetragen wurden.',
|
||
'There are usually three ways to install Perl modules.' => 'Es gibt normalerweise drei Arten, ein Perlmodul zu installieren.',
|
||
'There is a better discount available' => 'Es is ein besserer Rabatt verfügbar',
|
||
'There is a better price available' => 'Es ist ein besserer Preis verfügbar',
|
||
'There is already a taxkey 0 with tax rate not 0.' => 'Es existiert bereits ein Steuerschlüssel mit Steuersatz ungleich 0%.',
|
||
'There is an inconsistancy in your database.' => 'In Ihrer Datenbank sind Unstimmigkeiten vorhanden.',
|
||
... | ... | |
'This can be done with the following query:' => 'Dies kann mit der folgenden Datenbankabfrage erreicht werden:',
|
||
'This could have happened for two reasons:' => 'Dies kann aus zwei Gründen geschehen sein:',
|
||
'This customer number is already in use.' => 'Diese Kundennummer wird bereits verwendet.',
|
||
'This discount has since gone down' => 'Dieser Rabatt ist mittlerweile niedriger',
|
||
'This discount has since gone up' => 'Dieser Rabatt ist mittlerweile höher',
|
||
'This discount is only valid for business #1' => 'Dieser Rabatt ist nur für Kunden-/Lieferantentyp #1 gültig',
|
||
'This discount is only valid for customer #1' => 'Dieser Rabatt ist nur für Kunde #1 gültig',
|
||
'This discount is only valid for vendor #1' => 'Dieser Rabatt ist nur für Lieferant #1 gültig',
|
||
'This discount is only valid in purchase documents' => 'Dieser Rabatt ist nur in Einkaufsdokumenten gültig',
|
||
'This discount is only valid in records with customer or vendor' => 'Dieser Rabatt ist nur in Dokumenten mit Kunde oder Lieferant gültig',
|
||
'This discount is only valid in sales documents' => 'Dieser Rabatt ist nur in Verkaufsdokumenten gültig',
|
||
'This feature especially prevents mistakes by mixing up prior tax and sales tax.' => 'Dieses Feature vermeidet insbesondere Verwechslungen von Umsatz- und Vorsteuer.',
|
||
'This function requires the presence of articles with a time-based unit such as "h" or "min".' => 'Für diese Funktion mussen Artikel mit einer Zeit-basierten Einheit wie "Std" oder "min" existieren.',
|
||
'This group is valid for the following clients' => 'Diese Gruppe ist für die folgenden Mandanten gültig',
|
||
... | ... | |
'Unsupported image type (supported types: #1)' => 'Nicht unterstützter Bildtyp (unterstützte Typen: #1)',
|
||
'Until' => 'Bis',
|
||
'Update' => 'Erneuern',
|
||
'Update Discount' => 'Rabatt übernehmen',
|
||
'Update Price' => 'Preis übernehmen',
|
||
'Update Prices' => 'Preise aktualisieren',
|
||
'Update SKR04: new tax account 3804 (19%)' => 'Update SKR04: neues Steuerkonto 3804 (19%) für innergemeinschaftlichen Erwerb',
|
||
... | ... | |
'Vendor' => 'Lieferant',
|
||
'Vendor (database ID)' => '(Datenbank-ID)',
|
||
'Vendor (name)' => 'Lieferant (Name)',
|
||
'Vendor Discount' => 'Lieferantenrabatt',
|
||
'Vendor Invoice' => 'Einkaufsrechnung',
|
||
'Vendor Invoices & AP Transactions' => 'Einkaufsrechnungen & Kreditorenbuchungen',
|
||
'Vendor Name' => 'Lieferantenname',
|
sql/Pg-upgrade2/recorditem_active_dicount_source.sql | ||
---|---|---|
-- @tag: recorditem_active_record_source
|
||
-- @description: Preisquellen: Rabatte
|
||
-- @depends: release_3_1_0 recorditem_active_price_source
|
||
-- @encoding: utf-8
|
||
|
||
ALTER TABLE orderitems ADD COLUMN active_discount_source TEXT NOT NULL DEFAULT '';
|
||
ALTER TABLE delivery_order_items ADD COLUMN active_discount_source TEXT NOT NULL DEFAULT '';
|
||
ALTER TABLE invoice ADD COLUMN active_discount_source TEXT NOT NULL DEFAULT '';
|
templates/webpages/oe/price_sources_dialog.html | ||
---|---|---|
[%- USE L %]
|
||
[%- USE LxERP %]
|
||
[% SET best_price = price_source.best_price %]
|
||
[% SET best_discount = price_source.best_discount %]
|
||
<h2>[% 'Prices' | $T8 %]</h2>
|
||
|
||
<table>
|
||
<tr class='listheading'>
|
||
<th></th>
|
||
<th>[% 'Price Source' | $T8 %]</th>
|
||
<th>[% 'Price' | $T8 %]</th>
|
||
<th>[% 'Best Price' | $T8 %]</th>
|
||
<th>[% 'Details' | $T8 %]</th>
|
||
</tr>
|
||
<tr class='listrow'>
|
||
[%- IF price_source.record_item.active_price_source %]
|
||
... | ... | |
<td>[% 'None (PriceSource)' | $T8 %]</td>
|
||
<td>-</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
[%- FOREACH price IN price_source.available_prices %]
|
||
<tr class='listrow'>
|
||
[%- IF price_source.record_item.active_price_source != price.source %]
|
||
<td>[% L.button_tag('kivi.io.update_price_source(' _ FORM.row _ ', \'' _ price.source _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')', LxERP.t8('Select')) %]</td>
|
||
[%- ELSIF price_source.record_item.sellprice_as_number != price.price_as_number %]
|
||
[%- ELSIF price_source.record_item.sellprice != price.price %]
|
||
<td>[% L.button_tag('kivi.io.update_price_source(' _ FORM.row _ ', \'' _ price.source _ '\', \'' _ LxERP.format_amount(price.price, -2) _ '\')', LxERP.t8('Update Price')) %]</td>
|
||
[%- ELSE %]
|
||
<td><b>[% 'Selected' | $T8 %]</b></td>
|
||
[% END %]
|
||
<td>[% price.full_description | html %]</td>
|
||
<td>[% price.source_description | html %]</td>
|
||
<td>[% price.price_as_number %]</td>
|
||
[% IF price.source == best_price.source %]
|
||
<td align='center'>•</td>
|
||
[% ELSE %]
|
||
<td></td>
|
||
[% END %]
|
||
<td>[% price.description | html %]</td>
|
||
</tr>
|
||
[%- END %]
|
||
</table>
|
||
|
||
<h2>[% 'Discounts' | $T8 %]</h2>
|
||
|
||
<table>
|
||
<tr class='listheading'>
|
||
<th></th>
|
||
<th>[% 'Price Source' | $T8 %]</th>
|
||
<th>[% 'Discount' | $T8 %]</th>
|
||
<th>[% 'Best Discount' | $T8 %]</th>
|
||
<th>[% 'Details' | $T8 %]</th>
|
||
</tr>
|
||
<tr class='listrow'>
|
||
[%- IF price_source.record_item.active_discount_source %]
|
||
<td>[% L.button_tag('kivi.io.update_discount_source(' _ FORM.row _ ', \'\')', LxERP.t8('Select')) %]</td>
|
||
[%- ELSE %]
|
||
<td><b>[% 'Selected' | $T8 %]</b></td>
|
||
[%- END %]
|
||
<td>[% 'None (PriceSource Discount)' | $T8 %]</td>
|
||
<td>-</td>
|
||
<td></td>
|
||
<td></td>
|
||
</tr>
|
||
[%- FOREACH price IN price_source.available_discounts %]
|
||
<tr class='listrow'>
|
||
[%- IF price_source.record_item.active_discount_source != price.source %]
|
||
<td>[% L.button_tag('kivi.io.update_discount_source(' _ FORM.row _ ', \'' _ price.source _ '\', \'' _ price.discount_as_percent _ '\')', LxERP.t8('Select')) %]</td>
|
||
[%- ELSIF price_source.record_item.discount != price.discount * 100 %]
|
||
<td>[% L.button_tag('kivi.io.update_discount_source(' _ FORM.row _ ', \'' _ price.source _ '\', \'' _ price.discount_as_percent _ '\')', LxERP.t8('Update Discount')) %]</td>
|
||
[%- ELSE %]
|
||
<td><b>[% 'Selected' | $T8 %]</b></td>
|
Auch abrufbar als: Unified diff
PriceSource: Rabattbehandlung