From 046f2d8455a264eeaf9f6eaf57d8cc64c07d542f Mon Sep 17 00:00:00 2001 From: Rene Krenn Date: Mon, 18 May 2015 11:02:05 +0200 Subject: [PATCH] MT#12643 billing networks +billing networks, profile packages +service charge and "topup" balance interval start mode added to profile package +profile package <-> customer relationship +delete cascade and relationship joins revised Change-Id: I5cb58c810e90ec7550549ccc4d71bbce855fe851 --- lib/NGCP/Schema/Result/billing_mappings.pm | 32 +++ .../Schema/Result/billing_mappings_actual.pm | 2 +- .../Schema/Result/billing_network_blocks.pm | 174 +++++++++++++++ lib/NGCP/Schema/Result/billing_networks.pm | 130 +++++++++++ lib/NGCP/Schema/Result/billing_profiles.pm | 7 + lib/NGCP/Schema/Result/contracts.pm | 19 ++ .../Schema/Result/package_profile_sets.pm | 93 ++++++++ lib/NGCP/Schema/Result/profile_packages.pm | 201 ++++++++++++++++++ lib/NGCP/Schema/Result/resellers.pm | 14 ++ lib/NGCP/Schema/Result/voip_intercept.pm | 2 +- .../Schema/Result/voip_pbx_autoattendants.pm | 2 +- 11 files changed, 673 insertions(+), 3 deletions(-) create mode 100644 lib/NGCP/Schema/Result/billing_network_blocks.pm create mode 100644 lib/NGCP/Schema/Result/billing_networks.pm create mode 100644 lib/NGCP/Schema/Result/package_profile_sets.pm create mode 100644 lib/NGCP/Schema/Result/profile_packages.pm diff --git a/lib/NGCP/Schema/Result/billing_mappings.pm b/lib/NGCP/Schema/Result/billing_mappings.pm index 4c701e8a..ceb24ebc 100644 --- a/lib/NGCP/Schema/Result/billing_mappings.pm +++ b/lib/NGCP/Schema/Result/billing_mappings.pm @@ -49,6 +49,13 @@ __PACKAGE__->add_columns( is_foreign_key => 1, is_nullable => 1, }, + "network_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 1, + }, ); __PACKAGE__->set_primary_key("id"); @@ -97,6 +104,18 @@ __PACKAGE__->belongs_to( }, ); +__PACKAGE__->belongs_to( + "network", + "NGCP::Schema::Result::billing_networks", + { id => "network_id" }, + { + is_deferrable => 1, + join_type => "LEFT", + on_delete => "RESTRICT", + on_update => "CASCADE", + }, +); + sub TO_JSON { my ($self) = @_; return { @@ -166,6 +185,13 @@ NGCP::Schema::Result::billing_mappings extra: {unsigned => 1} is_foreign_key: 1 is_nullable: 1 + +=head2 network_id + + data_type: 'integer' + extra: {unsigned => 1} + is_foreign_key: 1 + is_nullable: 1 =head1 PRIMARY KEY @@ -200,3 +226,9 @@ Related object: L Type: belongs_to Related object: L + +=head2 network + +Type: belongs_to + +Related object: L diff --git a/lib/NGCP/Schema/Result/billing_mappings_actual.pm b/lib/NGCP/Schema/Result/billing_mappings_actual.pm index 2831e8f0..0aafdd3f 100644 --- a/lib/NGCP/Schema/Result/billing_mappings_actual.pm +++ b/lib/NGCP/Schema/Result/billing_mappings_actual.pm @@ -62,7 +62,7 @@ select bm.contract_id,max(bm.id) as actual_bm_id from billing.billing_mappings b where ( bmm.`end_date` >= ? OR bmm.`end_date` IS NULL ) AND ( bmm.`start_date` <= ? OR bmm.`start_date` IS NULL ) group by bmm.contract_id - ) bmm on bm.contract_id=bmm.contract_id and (bm.start_date=bmm.max_start_date or bmm.max_start_date is null) + ) bmm on bm.contract_id=bmm.contract_id and (bm.start_date=bmm.max_start_date or (bmm.max_start_date is null and bm.start_date is null)) group by bm.contract_id "); diff --git a/lib/NGCP/Schema/Result/billing_network_blocks.pm b/lib/NGCP/Schema/Result/billing_network_blocks.pm new file mode 100644 index 00000000..7a556409 --- /dev/null +++ b/lib/NGCP/Schema/Result/billing_network_blocks.pm @@ -0,0 +1,174 @@ +package NGCP::Schema::Result::billing_network_blocks; +use Scalar::Util qw(blessed); +use Math::BigInt; +use parent 'DBIx::Class::Core'; + +our $VERSION = '2.007'; + +__PACKAGE__->load_components("InflateColumn::DateTime", "Helper::Row::ToJSON"); + +__PACKAGE__->table("billing.billing_network_blocks"); + +__PACKAGE__->add_columns( + "id", + { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, + "network_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 0, + }, + "ip", + { data_type => "varchar", is_nullable => 0, size => 39 }, + "mask", + { data_type => "tinyint", extra => { unsigned => 1 }, is_nullable => 1 }, + "_ipv4_net_from", + { data_type => "varbinary", is_nullable => 1, size => 4 }, + "_ipv4_net_to", + { data_type => "varbinary", is_nullable => 1, size => 4 }, + "_ipv6_net_from", + { data_type => "varbinary", is_nullable => 1, size => 16 }, + "_ipv6_net_to", + { data_type => "varbinary", is_nullable => 1, size => 16 }, + +); + +__PACKAGE__->set_primary_key("id"); + +__PACKAGE__->belongs_to( + "billing_network", + "NGCP::Schema::Result::billing_networks", + { "foreign.id" => "self.network_id" }, + { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, +); + + __PACKAGE__->inflate_column('_ipv4_net_from', { + inflate => sub { + my ($data) = @_; + _bytes_to_bigint($data,4); + }, + deflate => sub { + my ($bigint) = @_; + _bigint_to_bytes($bigint,4); + }, + }); + __PACKAGE__->inflate_column('_ipv4_net_to', { + inflate => sub { + my ($data) = @_; + _bytes_to_bigint($data,4); + }, + deflate => sub { + my ($bigint) = @_; + _bigint_to_bytes($bigint,4); + }, + }); + __PACKAGE__->inflate_column('_ipv6_net_from', { + inflate => sub { + my ($data) = @_; + _bytes_to_bigint($data,16); + }, + deflate => sub { + my ($bigint) = @_; + _bigint_to_bytes($bigint,16); + }, + }); + __PACKAGE__->inflate_column('_ipv6_net_to', { + inflate => sub { + my ($data) = @_; + _bytes_to_bigint($data,16); + }, + deflate => sub { + my ($bigint) = @_; + _bigint_to_bytes($bigint,16); + }, + }); + +sub TO_JSON { + my ($self) = @_; + return { + map { if (blessed($_)) { + if ($_->isa('DateTime')) { + $_->datetime; + } elsif ($_->isa('Math::BigInt')) { + $_->as_hex(); + } else { + $_; + } + } else { + $_; + } + } %{ $self->next::method } + }; +} + +sub _bigint_to_bytes { + my ($bigint,$size) = @_; + return undef if !defined $bigint; + #print '>'.sprintf('%0' . 2 * $size . 's',substr($bigint->as_hex(),2)) . "\n"; + return pack('C' x $size, map { hex($_) } (sprintf('%0' . 2 * $size . 's',substr($bigint->as_hex(),2)) =~ /(..)/g)); + #print '>' . join('',map { sprintf('%02x',$_) } unpack('C' x $size, $data)) . "\n"; + #return $data; +} + +sub _bytes_to_bigint { + my ($data,$size) = @_; + return undef if !defined $data; + return Math::BigInt->new('0x' . join('',map { sprintf('%02x',$_) } unpack('C' x $size, $data))) +} + +1; +__END__ + +=encoding UTF-8 + +=head1 NAME + +NGCP::Schema::Result::billing_network_blocks + +=head1 COMPONENTS LOADED + +=over 4 + +=item * L + +=item * L + +=back + +=head1 TABLE: C + +=head1 ACCESSORS + +=head2 id + + data_type: 'integer' + is_auto_increment: 1 + is_nullable: 0 + +=head2 ip + + data_type: 'varchar' + is_nullable: 0 + size: 39 + +=head2 mask + + data_type: 'tinyint' + is_nullable: 0 + +=head1 PRIMARY KEY + +=over 4 + +=item * L + +=back + +=head1 RELATIONS + +=head2 billing_networks + +Type: has_many + +Related object: L diff --git a/lib/NGCP/Schema/Result/billing_networks.pm b/lib/NGCP/Schema/Result/billing_networks.pm new file mode 100644 index 00000000..ff40cd33 --- /dev/null +++ b/lib/NGCP/Schema/Result/billing_networks.pm @@ -0,0 +1,130 @@ +package NGCP::Schema::Result::billing_networks; +use Scalar::Util qw(blessed); +use parent 'DBIx::Class::Core'; + +our $VERSION = '2.007'; + +__PACKAGE__->load_components("InflateColumn::DateTime", "Helper::Row::ToJSON"); + +__PACKAGE__->table("billing.billing_networks"); + +__PACKAGE__->add_columns( + "id", + { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, + "reseller_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 1, + }, + "name", + { data_type => "varchar", is_nullable => 0, size => 255 }, + "description", + { data_type => "varchar", is_nullable => 0, size => 255 }, + "status", + { + data_type => "enum", + default_value => "active", + extra => { list => ["active", "terminated"] }, + is_nullable => 0, + }, +); + +__PACKAGE__->set_primary_key("id"); + +__PACKAGE__->add_unique_constraint("bn_resname_idx", ["reseller_id", "name"]); +#__PACKAGE__->add_unique_constraint("bn_name_idx", ["name"]); + +__PACKAGE__->has_many( + "billing_network_blocks", + "NGCP::Schema::Result::billing_network_blocks", + { "foreign.network_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +__PACKAGE__->belongs_to( + "reseller", + "NGCP::Schema::Result::resellers", + { "foreign.id" => "self.reseller_id" }, + { is_deferrable => 1, join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, +); + +__PACKAGE__->has_many( + "billing_mappings", + "NGCP::Schema::Result::billing_mappings", + { "foreign.network_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +__PACKAGE__->has_many( + "profile_packages", + "NGCP::Schema::Result::profile_packages", + { "foreign.network_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +sub TO_JSON { + my ($self) = @_; + return { + map { blessed($_) && $_->isa('DateTime') ? $_->datetime : $_ } %{ $self->next::method } + }; +} + +1; +__END__ + +=encoding UTF-8 + +=head1 NAME + +NGCP::Schema::Result::billing_networks + +=head1 COMPONENTS LOADED + +=over 4 + +=item * L + +=item * L + +=back + +=head1 TABLE: C + +=head1 ACCESSORS + +=head2 id + + data_type: 'integer' + is_auto_increment: 1 + is_nullable: 0 + +=head2 name + + data_type: 'varchar' + is_nullable: 0 + size: 255 + +=head2 description + + data_type: 'varchar' + is_nullable: 0 + size: 255 + +=head1 PRIMARY KEY + +=over 4 + +=item * L + +=back + +=head1 RELATIONS + +=head2 billing_network_blocks + +Type: has_many + +Related object: L + diff --git a/lib/NGCP/Schema/Result/billing_profiles.pm b/lib/NGCP/Schema/Result/billing_profiles.pm index 721ff523..f912b62e 100644 --- a/lib/NGCP/Schema/Result/billing_profiles.pm +++ b/lib/NGCP/Schema/Result/billing_profiles.pm @@ -163,6 +163,13 @@ __PACKAGE__->belongs_to( }, ); +__PACKAGE__->has_many( + "profile_packages", + "NGCP::Schema::Result::profile_packages", + { "foreign.profile_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + sub TO_JSON { my ($self) = @_; return { diff --git a/lib/NGCP/Schema/Result/contracts.pm b/lib/NGCP/Schema/Result/contracts.pm index b9eb61c0..bf2429dd 100644 --- a/lib/NGCP/Schema/Result/contracts.pm +++ b/lib/NGCP/Schema/Result/contracts.pm @@ -37,6 +37,13 @@ __PACKAGE__->add_columns( is_foreign_key => 1, is_nullable => 1, }, + "profile_package_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 1, + }, "status", { data_type => "enum", @@ -246,6 +253,18 @@ __PACKAGE__->has_many( { cascade_copy => 0, cascade_delete => 0 }, ); +__PACKAGE__->belongs_to( + "profile_package", + "NGCP::Schema::Result::profile_packages", + { id => "profile_package_id" }, + { + is_deferrable => 1, + join_type => "LEFT", + on_delete => "SET NULL", + on_update => "CASCADE", + }, +); + sub TO_JSON { my ($self) = @_; return { diff --git a/lib/NGCP/Schema/Result/package_profile_sets.pm b/lib/NGCP/Schema/Result/package_profile_sets.pm new file mode 100644 index 00000000..4dc10c6a --- /dev/null +++ b/lib/NGCP/Schema/Result/package_profile_sets.pm @@ -0,0 +1,93 @@ +package NGCP::Schema::Result::package_profile_sets; +use Scalar::Util qw(blessed); +use parent 'DBIx::Class::Core'; + +our $VERSION = '2.007'; + +__PACKAGE__->load_components("InflateColumn::DateTime", "Helper::Row::ToJSON"); + +__PACKAGE__->table("billing.package_profile_sets"); + +__PACKAGE__->add_columns( + "id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_auto_increment => 1, + is_nullable => 0, + }, + "package_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 0, + }, + #"topup_id", + #{ + # data_type => "integer", + # extra => { unsigned => 1 }, + # is_foreign_key => 1, + # is_nullable => 1, + #}, + "discriminator", + { + data_type => "enum", + #default_value => "", + extra => { list => ["initial", "underrun", "topup"] }, + is_nullable => 0, + }, + "profile_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 0, + }, + "network_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 1, + }, +); + +__PACKAGE__->set_primary_key("id"); + +__PACKAGE__->belongs_to( + "profile_package", + "NGCP::Schema::Result::profile_packages", + { id => "package_id" }, + { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, +); + +#__PACKAGE__->belongs_to( +# "package_topup", +# "NGCP::Schema::Result::package_topups", +# { id => "package_id" }, +# { is_deferrable => 1, join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, +#); + +__PACKAGE__->belongs_to( + "billing_profile", + "NGCP::Schema::Result::billing_profiles", + { id => "profile_id" }, + { is_deferrable => 1, on_delete => "RESTRICT", on_update => "CASCADE" }, +); + +__PACKAGE__->belongs_to( + "billing_network", + "NGCP::Schema::Result::billing_networks", + { id => "network_id" }, + { is_deferrable => 1, join_type => "LEFT", on_delete => "RESTRICT", on_update => "CASCADE" }, +); + +sub TO_JSON { + my ($self) = @_; + return { + map { blessed($_) && $_->isa('DateTime') ? $_->datetime : $_ } %{ $self->next::method } + }; +} + +1; \ No newline at end of file diff --git a/lib/NGCP/Schema/Result/profile_packages.pm b/lib/NGCP/Schema/Result/profile_packages.pm new file mode 100644 index 00000000..004142b7 --- /dev/null +++ b/lib/NGCP/Schema/Result/profile_packages.pm @@ -0,0 +1,201 @@ +package NGCP::Schema::Result::profile_packages; +use Scalar::Util qw(blessed); +use parent 'DBIx::Class::Core'; + +our $VERSION = '2.007'; + +__PACKAGE__->load_components("InflateColumn::DateTime", "Helper::Row::ToJSON"); + +__PACKAGE__->table("billing.profile_packages"); + +__PACKAGE__->add_columns( + "id", + { data_type => "integer", is_auto_increment => 1, is_nullable => 0 }, + "reseller_id", + { + data_type => "integer", + extra => { unsigned => 1 }, + is_foreign_key => 1, + is_nullable => 1, + }, + "name", + { data_type => "varchar", is_nullable => 0, size => 255 }, + "description", + { data_type => "varchar", is_nullable => 0, size => 255 }, + "status", + { + data_type => "enum", + default_value => "active", + extra => { list => ["active", "terminated"] }, + is_nullable => 0, + }, + + "initial_balance", + { data_type => "double precision", default_value => 0, is_nullable => 0 }, + "service_charge", + { data_type => "double precision", default_value => 0, is_nullable => 0 }, + "balance_interval_unit", + { + data_type => "enum", + default_value => "month", + extra => { list => ["day", "week", "month"] }, + is_nullable => 0, + }, + "balance_interval_value", + { + data_type => "integer", + default_value => 1, + extra => { unsigned => 1 }, + is_nullable => 0, + }, + "balance_interval_start_mode", + { + data_type => "enum", + default_value => "create", + extra => { list => ["create", "1st", "topup"] }, + is_nullable => 0, + }, + + "carry_over_mode", + { + data_type => "enum", + default_value => "carry_over", + extra => { list => ["carry_over", "carry_over_timely", "discard"] }, + is_nullable => 0, + }, + #"timely_carry_over_mode", + #{ + # data_type => "enum", + # default_value => "carry_over", + # extra => { list => ["carry_over", "discard"] }, + # is_nullable => 0, + #}, + "timely_duration_unit", + { + data_type => "enum", + #default_value => "day", + extra => { list => ["day", "week", "month"] }, + is_nullable => 1, + }, + "timely_duration_value", + { + data_type => "integer", + #default_value => 1, + extra => { unsigned => 1 }, + is_nullable => 1, + }, + "notopup_discard_intervals", + { + data_type => "integer", + #default_value => 1, + extra => { unsigned => 1 }, + is_nullable => 1, + }, + + "underrun_lock_threshold", + { data_type => "double precision", default_value => 0, is_nullable => 1 }, + #{ + # data_type => "integer", + # #default_value => 0, + # extra => { unsigned => 1 }, + # is_nullable => 1, + #}, + "underrun_lock_level", + { data_type => "tinyint", extra => { unsigned => 1 }, is_nullable => 1 }, + "underrun_profile_threshold", + { data_type => "double precision", default_value => 0, is_nullable => 1 }, + #{ + # data_type => "integer", + # default_value => 0, + # extra => { unsigned => 1 }, + # is_nullable => 1, + #}, + + "topup_lock_level", + { data_type => "tinyint", extra => { unsigned => 1 }, is_nullable => 1 }, + +); + +__PACKAGE__->set_primary_key("id"); + +__PACKAGE__->add_unique_constraint("pp_resname_idx", ["reseller_id", "name"]); + +__PACKAGE__->belongs_to( + "reseller", + "NGCP::Schema::Result::resellers", + { "foreign.id" => "self.reseller_id" }, + { is_deferrable => 1, join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, +); + +__PACKAGE__->has_many( + "initial_profiles", + "NGCP::Schema::Result::package_profile_sets", + sub { + return _join_condition(shift,'initial'); + }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +__PACKAGE__->has_many( + "underrun_profiles", + "NGCP::Schema::Result::package_profile_sets", + sub { + return _join_condition(shift,'underrun'); + }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +#__PACKAGE__->has_many( +# "topups", +# "NGCP::Schema::Result::package_topups", +# { "foreign.package_id" => "self.id" }, +# { cascade_copy => 0, cascade_delete => 0 }, +#); + +__PACKAGE__->has_many( + "topup_profiles", + "NGCP::Schema::Result::package_profile_sets", + sub { + return _join_condition(shift,'topup'); + }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +__PACKAGE__->has_many( + "profiles", + "NGCP::Schema::Result::package_profile_sets", + { "foreign.package_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +__PACKAGE__->has_many( + "contracts", + "NGCP::Schema::Result::contracts", + { "foreign.profile_package_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +sub _join_condition { + my ($args,$discriminator) = @_; + return { #[{ + "$args->{foreign_alias}.package_id" => { -ident => "$args->{self_alias}.id" }, + "$args->{foreign_alias}.discriminator" => { '=' => $discriminator }, + }; #, + #! $args->{self_result_object} ? () : { + # "$args->{foreign_alias}.package_id" => $args->{self_result_object}->id, + # "$args->{foreign_alias}.discriminator" => { '=' => $discriminator }, + #}, + #! $args->{foreign_values} ? () : { + # "$args->{self_alias}.id" => $args->{foreign_values}{package_id}, + #} + #]; +} + +sub TO_JSON { + my ($self) = @_; + return { + map { blessed($_) && $_->isa('DateTime') ? $_->datetime : $_ } %{ $self->next::method } + }; +} + +1; \ No newline at end of file diff --git a/lib/NGCP/Schema/Result/resellers.pm b/lib/NGCP/Schema/Result/resellers.pm index 05426f6f..d398957a 100644 --- a/lib/NGCP/Schema/Result/resellers.pm +++ b/lib/NGCP/Schema/Result/resellers.pm @@ -165,6 +165,20 @@ __PACKAGE__->has_many( { cascade_copy => 0, cascade_delete => 0 }, ); +__PACKAGE__->has_many( + "billing_networks", + "NGCP::Schema::Result::billing_networks", + { "foreign.reseller_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + +__PACKAGE__->has_many( + "profile_packages", + "NGCP::Schema::Result::profile_packages", + { "foreign.reseller_id" => "self.id" }, + { cascade_copy => 0, cascade_delete => 0 }, +); + sub TO_JSON { my ($self) = @_; return { diff --git a/lib/NGCP/Schema/Result/voip_intercept.pm b/lib/NGCP/Schema/Result/voip_intercept.pm index ff1e7408..b9aee7f2 100644 --- a/lib/NGCP/Schema/Result/voip_intercept.pm +++ b/lib/NGCP/Schema/Result/voip_intercept.pm @@ -72,7 +72,7 @@ __PACKAGE__->set_primary_key("id"); __PACKAGE__->belongs_to( "reseller", - "NGCP::Schema::billing::Result::resellers", + "NGCP::Schema::Result::resellers", { id => "reseller_id" }, { is_deferrable => 1, diff --git a/lib/NGCP/Schema/Result/voip_pbx_autoattendants.pm b/lib/NGCP/Schema/Result/voip_pbx_autoattendants.pm index be636942..1787cfc3 100644 --- a/lib/NGCP/Schema/Result/voip_pbx_autoattendants.pm +++ b/lib/NGCP/Schema/Result/voip_pbx_autoattendants.pm @@ -43,7 +43,7 @@ __PACKAGE__->set_primary_key("id"); __PACKAGE__->belongs_to( "subscriber", - "NGCP::Schema::provisioning::Result::voip_subscribers", + "NGCP::Schema::Result::voip_subscribers", { id => "subscriber_id" }, { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" }, );