Revision e1bf173b
Von Sven Schöling vor mehr als 13 Jahren hinzugefügt
SL/DB/Contact.pm | ||
---|---|---|
use strict;
|
||
|
||
use SL::DB::MetaSetup::Contact;
|
||
use SL::DB::Helper::CustomVariables (
|
||
module => 'Contacts',
|
||
cvars_alias => 1,
|
||
);
|
||
|
||
# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all.
|
||
__PACKAGE__->meta->make_manager_class;
|
SL/DB/CustomVariable.pm | ||
---|---|---|
# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all.
|
||
__PACKAGE__->meta->make_manager_class;
|
||
|
||
sub value {
|
||
my $self = $_[0];
|
||
my $type = $self->config->type;
|
||
|
||
goto &bool_value if $type eq 'boolean';
|
||
goto ×tamp_value if $type eq 'timestamp';
|
||
goto &number_value if $type eq 'number';
|
||
goto &text_value; # text and select
|
||
}
|
||
|
||
1;
|
SL/DB/Customer.pm | ||
---|---|---|
use SL::DB::MetaSetup::Customer;
|
||
use SL::DB::Manager::Customer;
|
||
use SL::DB::Helper::TransNumberGenerator;
|
||
use SL::DB::Helper::CustomVariables (
|
||
module => 'CT',
|
||
cvars_alias => 1,
|
||
);
|
||
|
||
use SL::DB::VC;
|
||
|
SL/DB/DeliveryOrderItem.pm | ||
---|---|---|
use strict;
|
||
|
||
use SL::DB::MetaSetup::DeliveryOrderItem;
|
||
use SL::DB::Helper::CustomVariables (
|
||
sub_module => 'orderitems',
|
||
cvars_alias => 1,
|
||
overloads => {
|
||
parts_id => 'SL::DB::Part',
|
||
},
|
||
);
|
||
|
||
__PACKAGE__->meta->make_manager_class;
|
||
|
SL/DB/Helper/CustomVariables.pm | ||
---|---|---|
package SL::DB::Helper::CustomVariables;
|
||
|
||
use strict;
|
||
use Carp;
|
||
use Data::Dumper;
|
||
use List::Util qw(first);
|
||
use SL::DB::CustomVariableConfig;
|
||
|
||
use constant META_CVARS => 'cvars_config';
|
||
|
||
sub import {
|
||
my ($class, %params) = @_;
|
||
my $caller_package = caller;
|
||
|
||
# TODO: if module is empty, module overloading needs to take effect
|
||
# certain stuff may have more than one overload, odr even more than one type
|
||
defined $caller_package or croak 'need to be included from a caller reference';
|
||
|
||
$params{module} ||= _calc_modules_from_overloads(%params) if $params{overloads};
|
||
$params{sub_module} ||= '';
|
||
$params{id} ||= 'id';
|
||
|
||
$params{module} || $params{sub_module} or croak 'need param module or sub_module';
|
||
|
||
save_meta_info($caller_package, %params);
|
||
make_cvar_accessor($caller_package, %params);
|
||
make_cvar_alias($caller_package, %params) if $params{cvars_alias};
|
||
make_cvar_by_configs($caller_package, %params);
|
||
make_cvar_by_name($caller_package, %params);
|
||
}
|
||
|
||
sub save_meta_info {
|
||
my ($caller_package, %params) = @_;
|
||
|
||
my $meta = $caller_package->meta;
|
||
return 0 if $meta->{META_CVARS()};
|
||
|
||
$meta->{META_CVARS()} = \%params;
|
||
}
|
||
|
||
sub make_cvar_accessor {
|
||
my ($caller_package, %params) = @_;
|
||
|
||
my @module_filter = $params{module} ?
|
||
("config.module" => $params{module}) :
|
||
();
|
||
|
||
$caller_package->meta->add_relationships(
|
||
custom_variables => {
|
||
type => 'one to many',
|
||
class => 'SL::DB::CustomVariable',
|
||
column_map => { ($params{id} || 'id') => 'trans_id' },
|
||
manager_args => { with_objects => 'config' },
|
||
query_args => [ sub_module => $params{sub_module}, @module_filter ],
|
||
}
|
||
);
|
||
}
|
||
|
||
sub make_cvar_alias {
|
||
my ($caller_package) = @_;
|
||
no strict 'refs';
|
||
*{ $caller_package . '::cvars' } = sub {
|
||
goto &{ $caller_package . '::custom_variables' };
|
||
}
|
||
}
|
||
|
||
# this is used for templates where you need to list every applicable config
|
||
# auto vivifies non existant cvar objects as necessary.
|
||
sub make_cvar_by_configs {
|
||
my ($caller_package, %params) = @_;
|
||
|
||
no strict 'refs';
|
||
*{ $caller_package . '::cvars_by_config' } = sub {
|
||
my ($self) = @_;
|
||
@_ > 1 and croak "not an accessor";
|
||
|
||
my $configs = _all_configs(%params);
|
||
my $cvars = $self->custom_variables;
|
||
my %cvars_by_config = map { $_->config_id => $_ } @$cvars;
|
||
|
||
my @return = map { $cvars_by_config{$_->id} || _new_cvar($self, %params, config => $_) } @$configs;
|
||
|
||
return \@return;
|
||
}
|
||
}
|
||
|
||
# this is used for print templates where you need to refer to a variable by name
|
||
# TODO typically these were referred as prefix_'cvar'_name
|
||
sub make_cvar_by_name {
|
||
my ($caller_package, %params) = @_;
|
||
|
||
no strict 'refs';
|
||
*{ $caller_package . '::cvar_by_name' } = sub {
|
||
my ($self, $name) = @_;
|
||
|
||
my $configs = _all_configs(%params);
|
||
my $cvars = $self->custom_variables;
|
||
my $config = first { $_->name eq $name } @$configs;
|
||
|
||
croak "unknown cvar name $name" unless $config;
|
||
|
||
my $cvar = first { $_->config_id eq $config->id } @$cvars;
|
||
|
||
if (!$cvar) {
|
||
$cvar = _new_cvar($self, %params, config => $config);
|
||
$self->add_custom_variables($cvar);
|
||
}
|
||
|
||
return $cvar;
|
||
}
|
||
}
|
||
|
||
sub _all_configs {
|
||
my (%params) = @_;
|
||
$params{module}
|
||
? SL::DB::Manager::CustomVariableConfig->get_all(query => [ module => $params{module} ])
|
||
: SL::DB::Manager::CustomVariableConfig->get_all;
|
||
}
|
||
|
||
sub _overload_by_module {
|
||
my ($module, %params) = @_;
|
||
|
||
while (my ($fk, $class) = each %{ $params{overloads} }) {
|
||
return ($fk, $class) if $class->meta->{META_CVARS()}->{module} eq $module;
|
||
}
|
||
|
||
croak "unknown overload, cannot resolve module $module";
|
||
}
|
||
|
||
sub _new_cvar {
|
||
my ($self, %params) = @_;
|
||
my $inherited_value;
|
||
# check overloading first
|
||
if ($params{sub_module}) {
|
||
my ($fk, $class) = _overload_by_module($params{config}->module, %params);
|
||
my $base_cvar = $class->new(id => $self->$fk)->load->cvar_by_name($params{config}->name);
|
||
$inherited_value = $base_cvar->value;
|
||
}
|
||
|
||
my $cvar = SL::DB::CustomVariable->new(
|
||
config => $params{config},
|
||
trans_id => $self->${ \ $params{id} },
|
||
sub_module => $params{sub_module},
|
||
);
|
||
# value needs config
|
||
$inherited_value
|
||
? $cvar->value($inherited_value)
|
||
: $cvar->value($params{config}->default_value);
|
||
return $cvar;
|
||
}
|
||
|
||
sub _calc_modules_from_overloads {
|
||
my (%params) = @_;
|
||
my %modules;
|
||
|
||
while (my ($fk, $class) = each %{ $params{overloads} }) {
|
||
eval "require $class"; # make sure the class is loaded
|
||
my $module = $class->meta->{META_CVARS()}->{module};
|
||
next if ref $module;
|
||
$modules{$module} = 1;
|
||
}
|
||
|
||
return [ keys %modules ];
|
||
}
|
||
|
||
|
||
1;
|
||
|
||
__END__
|
||
|
||
=encoding utf-8
|
||
|
||
=head1 NAME
|
||
|
||
SL::DB::Helper::CustomVariables - Mixin to provide custom variables relations
|
||
|
||
=head1 SYNOPSIS
|
||
|
||
# use in a primary class
|
||
use SL::DB::Helper::CustomVariables (
|
||
module => 'IC',
|
||
cvars_alias => 1,
|
||
);
|
||
|
||
# use overloading in a secondary class
|
||
use SL::DB::Helper::CustomVariables (
|
||
sub_module => 'orderitems',
|
||
cvars_alias => 1,
|
||
overloads => {
|
||
parts_id => 'SL::DB::Part',
|
||
}
|
||
);
|
||
|
||
=head1 DESCRIPTION
|
||
|
||
This module provides methods to deal with named custom variables. Two concepts are understood.
|
||
|
||
=head2 Primary CVar Classes
|
||
|
||
Primary classes are those that feature cvars for themselves. Currently those
|
||
are Part, Contact, Customer and Vendor. cvars for these will get saved directly
|
||
for the object.
|
||
|
||
=head2 Secondary CVar Classes
|
||
|
||
Secondary classes inherit their cvars from member relationships. This is built
|
||
so that orders can save a copy of the cvars of their parts, customers and the
|
||
like to be immutable later on.
|
||
|
||
Secondary classes may currently not have cvars of their own.
|
||
|
||
=head1 INSTALLED METHODS
|
||
|
||
=over 4
|
||
|
||
=item C<custom_variables [ CUSTOM_VARIABLES ]>
|
||
|
||
This is a Rose::DB::Object::Relationship accessor, generated for cvars. Use it
|
||
like any other OneToMany relationship.
|
||
|
||
=item C<cvars [ CUSTOM_VARIABLES ]>
|
||
|
||
Alias to C<custom_variables>. Will only be installed if C<cvars_alias> was
|
||
passed to import.
|
||
|
||
=item C<cvars_by_config>
|
||
|
||
Thi will return a list of CVars with the following changes over the standard accessor:
|
||
|
||
=over 4
|
||
|
||
=item *
|
||
|
||
The list will be returned in the sorted order of the configs.
|
||
|
||
=item *
|
||
|
||
For every config exactly one CVar will be returned.
|
||
|
||
=item *
|
||
|
||
If no cvar was found for a config, a new one will be vivified, set to the
|
||
correct config, module etc, and registered into the object.
|
||
|
||
=item *
|
||
|
||
Vivified cvars for secondary classes will first try to find their base object
|
||
and use that value. If no such value or cvar is found the default value from
|
||
configs applies.
|
||
|
||
=back
|
||
|
||
This is useful if you need to list every possible CVar, like in CRUD masks.
|
||
|
||
=item C<cvar_by_name NAME [ VALUE ]>
|
||
|
||
Returns the CVar object for this object which matches the given internal name.
|
||
Useful for print templates. If the requested cvar is not present, it will be
|
||
vivified with the same rules as in C<cvars_by_config>.
|
||
|
||
=back
|
||
|
||
=head1 AUTHOR
|
||
|
||
Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
|
||
|
||
=cut
|
SL/DB/Invoice.pm | ||
---|---|---|
use SL::DB::Helper::PriceTaxCalculator;
|
||
use SL::DB::Helper::PriceUpdater;
|
||
use SL::DB::Helper::TransNumberGenerator;
|
||
use SL::DB::Helper::CustomVariables (
|
||
sub_module => 'orderitems',
|
||
cvars_alias => 1,
|
||
overloads => {
|
||
parts_id => 'SL::DB::Part',
|
||
},
|
||
);
|
||
use SL::DB::AccTransaction;
|
||
use SL::DB::Chart;
|
||
use SL::DB::Employee;
|
SL/DB/OrderItem.pm | ||
---|---|---|
use strict;
|
||
|
||
use SL::DB::MetaSetup::OrderItem;
|
||
use SL::DB::Helper::CustomVariables (
|
||
sub_module => 'orderitems',
|
||
cvars_alias => 1,
|
||
overloads => {
|
||
parts_id => 'SL::DB::Part',
|
||
},
|
||
);
|
||
|
||
__PACKAGE__->meta->add_relationship(
|
||
part => {
|
SL/DB/Part.pm | ||
---|---|---|
use SL::DB::Manager::Part;
|
||
use SL::DB::Chart;
|
||
use SL::DB::Helper::TransNumberGenerator;
|
||
use SL::DB::Helper::CustomVariables (
|
||
module => 'IC',
|
||
cvars_alias => 1,
|
||
);
|
||
|
||
__PACKAGE__->meta->add_relationships(
|
||
unit_obj => {
|
SL/DB/Vendor.pm | ||
---|---|---|
|
||
use SL::DB::MetaSetup::Vendor;
|
||
use SL::DB::Helper::TransNumberGenerator;
|
||
use SL::DB::Helper::CustomVariables (
|
||
module => 'CT',
|
||
cvars_alias => 1,
|
||
);
|
||
|
||
use SL::DB::VC;
|
||
|
Auch abrufbar als: Unified diff
CVars als Object Mixin.
Conflicts: