use English qw( -no_match_vars );
use Getopt::Long;
use List::MoreUtils qw(none);
+use List::UtilsBy qw(partition_by);
use Pod::Usage;
+use Rose::DB::Object 0.809;
use Term::ANSIColor;
use SL::Auth;
my %config;
-our %foreign_key_name_map = (
- oe => { payment => 'payment_terms', },
- ar => { payment => 'payment_terms', },
- ap => { payment => 'payment_terms', },
+our %foreign_key_name_map = (
+ KIVITENDO => {
+ oe => { payment => 'payment_terms', },
+ ar => { payment => 'payment_terms', },
+ ap => { payment => 'payment_terms', },
- orderitems => { parts => 'part', trans => 'order', },
- delivery_order_items => { parts => 'part' },
- invoice => { parts => 'part' },
- follow_ups => { 'employee_obj' => 'created_for' },
+ orderitems => { parts => 'part', trans => 'order', },
+ delivery_order_items => { parts => 'part' },
+ invoice => { parts => 'part' },
+ follow_ups => { 'employee_obj' => 'created_for' },
- periodic_invoices_configs => { oe => 'order' },
+ periodic_invoices_configs => { oe => 'order' },
+ },
);
sub setup {
}
sub process_table {
- my @spec = @_;
- my $table = $spec[0];
+ my ($domain, $table, $package) = @_;
my $schema = '';
($schema, $table) = split(m/\./, $table) if $table =~ m/\./;
- my $package = ucfirst($spec[1] || $spec[0]);
+ $package = ucfirst($package || $table);
$package =~ s/_+(.)/uc($1)/ge;
my $meta_file = "${meta_path}/${package}.pm";
my $mngr_file = "${manager_path}/${package}.pm";
if ($foreign_key_definition && ($definition =~ /\Q$foreign_key_definition\E/)) {
my ($start, $end) = ($-[0], $+[0]);
- while (my ($auto_generated_name, $desired_name) = each %{ $foreign_key_name_map{$table} || {} }) {
+ my %changes = map { %{$_} } grep { $_ } ($foreign_key_name_map{$domain}->{ALL}, $foreign_key_name_map{$domain}->{$table});
+ while (my ($auto_generated_name, $desired_name) = each %changes) {
$foreign_key_definition =~ s/^ \s \s ${auto_generated_name} \b/ ${desired_name}/msx;
}
my $old_md5 = md5_hex($orig_file);
my $new_size = length $full_definition;
my $new_md5 = md5_hex($full_definition);
- if ($old_size == $new_size && $old_md5 == $new_md5) {
+ if ($old_size == $new_size && $old_md5 eq $new_md5) {
notice("No changes in $meta_file, skipping.") unless $config{quiet};
return;
}
GetOptions(
'client=s' => \ my $client,
all => \ my $all,
+ 'db=s' => \ my $db,
'no-commit|dry-run' => \ my $nocommit,
help => sub { pod2usage(verbose => 99, sections => 'NAME|SYNOPSIS|OPTIONS') },
quiet => \ my $quiet,
$options->{client} = $client;
$options->{all} = $all;
+ $options->{db} = $db;
$options->{nocommit} = $nocommit;
$options->{quiet} = $quiet;
$options->{color} = -t STDOUT ? 1 : 0;
}
sub make_tables {
- my @tables;
+ my %tables_by_domain;
if ($config{all}) {
- my $db = SL::DB::create(undef, 'KIVITENDO');
- @tables = grep { my $table = $_; none { $_ eq $table } @{ $blacklist{KIVITENDO} } } $db->list_tables;
+ my @domains = $config{db} ? (uc $config{db}) : sort keys %package_names;
+
+ foreach my $domain (@domains) {
+ my $db = SL::DB::create(undef, $domain);
+ $tables_by_domain{$domain} = [ grep { my $table = $_; none { $_ eq $table } @{ $blacklist{$domain} } } $db->list_tables ];
+ $db->disconnect;
+ }
} elsif (@ARGV) {
- @tables = @ARGV;
+ %tables_by_domain = partition_by {
+ my ($domain, $table) = split m{:};
+ $table ? uc($domain) : 'KIVITENDO';
+ } @ARGV;
+
+ foreach my $tables (values %tables_by_domain) {
+ s{.*:}{} for @{ $tables };
+ }
+
} else {
error("You specified neither --all nor any specific tables.");
usage();
}
- @tables;
+ return %tables_by_domain;
}
sub error {
print @_, $/;
}
+sub check_errors_in_package_names {
+ foreach my $domain (sort keys %package_names) {
+ my @both = grep { $package_names{$domain}->{$_} } @{ $blacklist{$domain} || [] };
+ next unless @both;
+
+ print "Error: domain '$domain': The following table names are present in both the black list and the package name hash: ", join(' ', sort @both), "\n";
+ exit 1;
+ }
+}
+
parse_args(\%config);
setup();
-my @tables = make_tables();
+check_errors_in_package_names();
-my @unknown_tables = grep { !$package_names{KIVITENDO}->{$_} } @tables;
-if (@unknown_tables) {
- error("The following tables do not have entries in \%SL::DB::Helper::Mappings::kivitendo_package_names: " . join(' ', sort @unknown_tables));
- exit 1;
-}
+my %tables_by_domain = make_tables();
-process_table($_, $package_names{KIVITENDO}->{$_}) for @tables;
+foreach my $domain (keys %tables_by_domain) {
+ my @tables = @{ $tables_by_domain{$domain} };
+ my @unknown_tables = grep { !$package_names{$domain}->{$_} } @tables;
+ if (@unknown_tables) {
+ error("The following tables do not have entries in \%SL::DB::Helper::Mappings::${domain}_package_names: " . join(' ', sort @unknown_tables));
+ exit 1;
+ }
+
+ process_table($domain, $_, $package_names{$domain}->{$_}) for @tables;
+}
1;
=head1 SYNOPSIS
- scripts/rose_auto_create_model.pl --client name-or-id table1 [table2 ...]
+ scripts/rose_auto_create_model.pl --client name-or-id [db1:]table1 [[db2:]table2 ...]
scripts/rose_auto_create_model.pl --client name-or-id [--all|-a]
# updates all models
- scripts/rose_auto_create_model.pl --client name-or-id --all
+ scripts/rose_auto_create_model.pl --client name-or-id --all [--db db]
# updates only customer table, login taken from config
scripts/rose_auto_create_model.pl customer
file. The first one will be updated if the schema changes, the second
and third ones will only be created if it they do not exist.
+=head1 DATABASE NAMES AND TABLES
+
+If you want to generate the data for specific tables only then you
+have to list them on the command line. The format is
+C<db-name:table-name>. The part C<db-name:> is optional and defaults
+to C<KIVITENDO:> – which means the tables in the default kivitendo
+database.
+
+Valid database names are keys in the hash returned by
+L<SL::DB::Helper::Mappings/get_package_names>.
+
=head1 OPTIONS
=over 4
Process all tables from the database. Only those that are blacklistes in
L<SL::DB::Helper::Mappings> are excluded.
+=item C<--db db>
+
+In combination with C<--all> causes all tables in the specific
+database to be processed, not in all databases.
+
=item C<--no-commit, -n>
=item C<--dry-run>