From 1650732b0a3a3d52a2072d72aa75b2c6939bacfe Mon Sep 17 00:00:00 2001 From: Mitch Jackson Date: Wed, 13 Dec 2017 18:13:01 -0600 Subject: [PATCH] rt# 74031 reworked realestate schema as locations and units - Update schemas - Original approach discarded and rewritten as locations with units --- FS/FS/Mason.pm | 2 + FS/FS/Schema.pm | 56 ++++--- FS/FS/realestate_location.pm | 178 +++++++++++++++++++++ FS/FS/realestate_property.pm | 176 -------------------- FS/FS/realestate_subproperty.pm | 125 --------------- FS/FS/realestate_unit.pm | 134 ++++++++++++++++ ...realestate_property.t => realestate_location.t} | 2 +- ...{realestate_subproperty.t => realestate_unit.t} | 2 +- 8 files changed, 349 insertions(+), 326 deletions(-) create mode 100644 FS/FS/realestate_location.pm delete mode 100644 FS/FS/realestate_property.pm delete mode 100644 FS/FS/realestate_subproperty.pm create mode 100644 FS/FS/realestate_unit.pm rename FS/t/{realestate_property.t => realestate_location.t} (77%) rename FS/t/{realestate_subproperty.t => realestate_unit.t} (75%) diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index 7bdb6059e..068f5b6c0 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -223,6 +223,8 @@ if ( -e $addl_handler_use_file ) { use FS::cdr_batch; use FS::inventory_class; use FS::inventory_item; + use FS::realestate_location; + use FS::realestate_unit; use FS::pkg_category; use FS::pkg_class; use FS::access_user; diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index b94407bc8..e1301b6ca 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -7636,38 +7636,48 @@ sub tables_hashref { 'foreign_keys' => [], }, - 'realestate_property' => { + 'realestate_unit' => { 'columns' => [ - 'propnum', 'serial', '', '', '', '', - 'agentnum', 'int', 'NULL', '', '', '', - 'title', 'varchar', '', $char_d, '', '', - 'address1', 'varchar', 'NULL', $char_d, '', '', - 'address2', 'varchar', 'NULL', $char_d, '', '', - 'city', 'varchar', 'NULL', $char_d, '', '', - 'state', 'varchar', 'NULL', $char_d, '', '', - 'zip', 'char', 'NULL', 5, '', '', - 'disabled', 'char', '', 1, '0', '', + 'realestatenum', 'serial', '', '', '', '', + 'realestatelocnum', 'int', '', '', '', '', + 'agentnum', 'int', 'NULL', '', '', '', + 'custnum', 'int', 'NULL', '', '', '', + 'unit_title', 'varchar', '', $char_d, '', '', + 'disabled', 'char', 'NULL', 1, '', '', + ], + 'primary_key' => 'realestatenum', + 'unique' => [ ['unit_title'] ], + 'index' => [ + ['agentnum'], + ['custnum'], + ['realestatelocnum'], + ['disabled'], + ['title'] ], - 'primary_key' => 'propnum', - 'unique' => [], - 'index' => [ ['agentnum'] ], 'foreign_keys' => [ - {columns => ['agentnum'], table => 'agent'} + {columns => ['agentnum'], table => 'agent'}, + {columns => ['custnum'], table => 'cust_main'}, + {columns => ['realestatelocnum'] => table => 'realestate_location'}, ], }, - 'realestate_subproperty' => { + realestate_location => { 'columns' => [ - 'subpropnum', 'serial', '', '', '', '', - 'propnum', 'int', '', '', '', '', - 'subtitle', 'varchar', '', $char_d, '', '', - 'disabled', 'char', '', 1, '0', '', + 'realestatelocnum', 'serial', '', '', '', '', + 'agentnum', 'int', 'NULL', '', '', '', + 'location_title', 'varchar', '', $char_d, '', '', + 'address1', 'varchar', 'NULL', $char_d, '', '', + 'address2', 'varchar', 'NULL', $char_d, '', '', + 'city', 'varchar', 'NULL', $char_d, '', '', + 'state', 'varchar', 'NULL', $char_d, '', '', + 'zip', 'char', 'NULL', 5, '', '', + 'disabled', 'char', 'NULL', 1, '', '', ], - 'primary_key' => 'subpropnum', - 'unique' => [], - 'index' => [ ['propnum'],['subtitle'] ], + primary_key => 'realestatelocnum', + 'unique' => [ ['location_title'] ], + 'index' => [ ['agentnum'], ['disabled'] ], 'foreign_keys' => [ - {columns => ['propnum'], table => 'realestate_property'} + {columns => ['agentnum'], table => 'agent'}, ], }, diff --git a/FS/FS/realestate_location.pm b/FS/FS/realestate_location.pm new file mode 100644 index 000000000..08d6dd3fa --- /dev/null +++ b/FS/FS/realestate_location.pm @@ -0,0 +1,178 @@ +package FS::realestate_location; +use strict; +use warnings; +use Carp qw(croak); + +use base 'FS::Record'; + +use FS::Record qw(qsearchs qsearch); + +=head1 NAME + +FS::realestate_location - Object representing a realestate_location record + +=head1 SYNOPSIS + + use FS::realestate_location; + + $location = new FS::realestate_location \%values; + $location = new FS::realestate_location { + agentnum => 1, + title => 'Superdome', + address1 => '1500 Sugar Bowl Dr', + city => 'New Orleans', + state => 'LA', + zip => '70112', + }; + + $error = $location->insert; + $error = $new_loc->replace($location); + $error = $record->check; + + $error = $location->add_unit('Box Seat No. 42'); + @units = $location->units; + @units = $location->active_units; + +=head1 DESCRIPTION + +An FS::realestate_location object represents a location for one or more +FS::realestate_unit objects. Expected to contain at least one unit, as only +realestate_unit objects are assignable to packages via +L. + +FS::realestate_location inherits from FS::Record. + +The following fields are currently supported: + +=over 4 + +=item realestatelocnum + +=item agentnum + +=item location_title + +=item address1 (optional) + +=item address2 (optional) + +=item city (optional) + +=item state (optional) + +=item zip (optional) + +=item disabled + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF (see L) + +=cut + +sub table {'realestate_location';} + +=item insert (see L) + +=item delete + + FS::realestate_location records should never be deleted, only disabled + +=cut + +sub delete { + # Once this record has been associated with a customer in any way, it + # should not be deleted. todo perhaps, add a is_deletable function that + # checks if the record has ever actually been used, and allows deletion + # if it hasn't. (entered in error, etc). + croak "FS::realestate_location records should never be deleted"; +} + +=item replace OLD_RECORD (see L) + +=item check (see L) + +=item agent + +Returns the associated agent + +=cut + +sub agent { + my $self = shift; + return undef unless $self->agentnum; + return exists $self->{agent} + ? $self->{agent} + : $self->{agent} = qsearchs('agent', {agentnum => $self->agentnum} ); +} + + +=item add_unit UNIT_TITLE + +Create an associated L record + +=cut + +sub add_unit { + my ($self, $unit_title) = @_; + croak "add_unit() requires a \$unit_title parameter" unless $unit_title; + + if ( + qsearchs('realestate_unit',{ + realestatelocnum => $self->realestatelocnum, + unit_title => $unit_title, + }) + ) { + return "Unit Title ($unit_title) has already been used for location (". + $self->location_title.")"; + } + + my $unit = FS::realestate_unit->new({ + realestatelocnum => $self->realestatelocnum, + agentnum => $self->agentnum, + unit_title => $unit_title, + }); + my $err = $unit->insert; + die "Error creating FS::realestate_new record: $err" if $err; + + return; +} + + +=item units + +Returns all units associated with this location + +=cut + +sub units { + my $self = shift; + return qsearch( + 'realestate_unit', + {realestatelocnum => $self->realestatelocnum} + ); +} + + +=head1 SUBROUTINES + +=over 4 + +=cut + + + + +=back + +=head1 SEE ALSO + +L, L, L + +=cut + +1; diff --git a/FS/FS/realestate_property.pm b/FS/FS/realestate_property.pm deleted file mode 100644 index 4e564175a..000000000 --- a/FS/FS/realestate_property.pm +++ /dev/null @@ -1,176 +0,0 @@ -package FS::realestate_property; -use strict; -use warnings; -use Carp qw(croak); - -use base 'FS::Record'; -use FS::Record qw(qsearch qsearchs); - -=head1 NAME - -FS::realestate_property - Object representing a realestate_property record - -=head1 SYNOPSIS - - use FS::realestate_property; - - $record = new FS:realestate_property \%values; - $record = new FS::realestate_property { - title => 'Superdome', - address1 => '1500 Sugar Bowl Dr', - city => 'New Orleans', - state => 'LA', - zip => '70112', - disabled => 0, - agentnum => 1, - }; - - $error = $record->insert; - $error = $new_rec->replace($record) - $error = $record->check; - - $sub_record = $record->add_subproperty('Box Seat No. 42'); - - @subprops = $record->subproperties; - @subprops = $record->enabled_subproperties; - -=head1 DESCRIPTION - -An FS::realestate_property object represents a real estate property. This -object may represent a single property, such as a rental house. It may also -represent a group of properties sharing a common address or identifier, such -as a shopping mall, apartment complex, or office building. - -FS::realestate_property inherits from FS::Record. - -The following fields are currently supported: - -=over 4 - -=item propnum - -=item agentnum - -=item title - -=item address1 *optional - -=item address2 *optional - -=item city *optional - -=item state *optional - -=item zip *optional - -=item disabled - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF (see L) - -=cut - -sub table {'realestate_property';} - -=item insert (see L) - -=item delete - - FS::realestate_property records should never be deleted, only disabled - -=cut - -sub delete { - # Once this record has been associated with a customer in any way, it - # should not be deleted. todo perhaps, add a is_deletable function that - # checks if the record has ever actually been used, and allows deletion - # if it hasn't. (entered in error, etc). - croak "FS::realestate_property records should never be deleted"; -} - - -=item replace OLD_RECORD (see L) - -=item check (see L) - -=item agent - -Returns the associated agent, if any, for this object - -=cut - -sub agent { - my $self = shift; - return undef unless $self->agentnum; - return qsearchs('agent', {agentnum => $self->agentnum} ); -} - - -=item subproperties - -Returns all subproperties linked to this property - -=cut - -sub subproperties { - qsearch('realestate_subproperty', {propnum => shift->propnum} ); -} - - -=item enabled_subproperties - -Returns all subproperties linked to this property where disabled = 0 - -=cut - -sub enabled_subproperties { - qsearch( 'realestate_subproperty', { - propnum => shift->propnum, - disabled => 0, - }); -} - -=item add_subproperty SUBPROPERTY_TITLE - -Create a new subproperty record for this property - -=cut - -sub add_subproperty { - my ($self, $subtitle) = @_; - croak "add_subproperty() requires a \$subtitle parameter" unless $subtitle; - - my $subp = new FS::realestate_subproperty { - propnum => $self->propnum, - subtitle => $subtitle, - disabled => 0, - }; - my $err = $subp->insert; - die "Error inserting subproperty: $err" if $err; - $subp; -} - - -=back - -=head1 SUBROUTINES - -=over 4 - -=cut - - -=back - -=head1 SEE ALSO - -L, L, L - -=cut - -1; diff --git a/FS/FS/realestate_subproperty.pm b/FS/FS/realestate_subproperty.pm deleted file mode 100644 index 5a93934da..000000000 --- a/FS/FS/realestate_subproperty.pm +++ /dev/null @@ -1,125 +0,0 @@ -package FS::realestate_subproperty; -use strict; -use warnings; -use Carp qw(croak); - -use base 'FS::Record'; - -use FS::Record qw(qsearchs); - -=head1 NAME - -FS::realestate_subproperty - Object representing a realestate_subproperty record - -=head1 SYNOPSIS - - use FS::realestate_subproperty; - - $record = new FS::realestate_subproperty \%values; - $record = new FS::realestate_subproperty { - propnum => 65535, - subtitle => 'Box Seat No. 42', - }; - - $error = $record->insert; - $error = new_rec->replace($record); - $error = $record->check; - - $parent = $record->property; - -=head1 DESCRIPTION - -An FS::realestate_subproperty object represents a unit of real estate property. -Every L must contain at least one subproperty, or unit, -which is the actual unit considered for sale, rent, etc as tied to -L. - -FS::realestate_subproperty inherits from FS::Record. - -The following fields are currently supported: - -=over 4 - -=item subpropnum - -=item propnum - -=item subtitle - -=item disabled - -=back - -=head1 METHODS - -=over 4 - -=item new HASHREF (see L) - -=cut - -sub table {'realestate_subproperty';} - -=item insert (see L) - -=item delete - - FS::realestate_subproperty records should never be deleted, only disabled - -=cut - -sub delete { - # Once this record has been associated with a customer in any way, it - # should not be deleted. todo perhaps, add a is_deletable function that - # checks if the record has ever actually been used, and allows deletion - # if it hasn't. (entered in error, etc). - croak "FS::realestate_subproperty records should never be deleted"; -} - -=item replace OLD_RECORD (see L) - -=item check (see L) - -=item agent - -Returns the associated agent, if any, for the parent L - -=cut - -sub agent { - shift->property->agent; -} - -=item property - -Returns the associated parent L record - -=cut - -sub property { - my $self = shift; - exists $self->{property} - ? $self->{property} - : $self->{property} = qsearchs('realestate_property',$self->propnum); -} - -=back - -=head1 SUBROUTINES - -=over 4 - -=cut - - - - -=back - -=head1 SEE ALSO - -L, L, L - -=cut - -1; diff --git a/FS/FS/realestate_unit.pm b/FS/FS/realestate_unit.pm new file mode 100644 index 000000000..98b333765 --- /dev/null +++ b/FS/FS/realestate_unit.pm @@ -0,0 +1,134 @@ +package FS::realestate_unit; +use strict; +use warnings; +use Carp qw(croak); + +use base 'FS::Record'; +use FS::Record qw(qsearch qsearchs); + +=head1 NAME + +FS::realestate_unit - Object representing a realestate_unit record + +=head1 SYNOPSIS + + use FS::realestate_unit; + + $record = new FS:realestate_unit \%values; + $record = new FS::realestate_unit { + realestatelocnum => 42, + agentnum => 1, + unit_title => 'Ste 404', + }; + + $error = $record->insert; + $error = $new_rec->replace($record) + $error = $record->check; + + $location = $record->location; + +=head1 DESCRIPTION + +An FS::realestate_unit object represents an invoicable unit of real estate. +Object may represent a single property, such as a rental house. It may also +represent a group of properties sharing a common address or identifier, such +as a shopping mall, apartment complex, or office building, concert hall. + +A FS::realestate_unit object must be associated with a FS::realestate_location + +FS::realestate_unit inherits from FS::Record. + +The following fields are currently supported: + +=over 4 + +=item realestatenum + +=item realestatelocnum + +=item agentnum + +=item custnum + +=item unit_title + +=item disabled + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF (see L) + +=cut + +sub table {'realestate_unit';} + +=item insert (see L) + +=item delete + + FS::realestate_unit records should never be deleted, only disabled + +=cut + +sub delete { + # Once this record has been associated with a customer in any way, it + # should not be deleted. todo perhaps, add a is_deletable function that + # checks if the record has ever actually been used, and allows deletion + # if it hasn't. (entered in error, etc). + croak "FS::realestate_unit records should never be deleted"; +} + + +=item replace OLD_RECORD (see L) + +=item check (see L) + +=item agent + +Returns the associated agent, if any, for this object + +=cut + +sub agent { + my $self = shift; + return undef unless $self->agentnum; + return qsearchs('agent', {agentnum => $self->agentnum} ); +} + +=item location + + Return the associated FS::realestate_location object + +=cut + +sub location { + my $self = shift; + return $self->{location} if exists $self->{location}; + return $self->{location} = qsearchs( + 'realestate_location', + {realestatelocnum => $self->realestatelocnum} + ); +} + +=back + +=head1 SUBROUTINES + +=over 4 + +=cut + + +=back + +=head1 SEE ALSO + +L, L, L + +=cut + +1; diff --git a/FS/t/realestate_property.t b/FS/t/realestate_location.t similarity index 77% rename from FS/t/realestate_property.t rename to FS/t/realestate_location.t index af7f2f4de..ecb1d8be9 100644 --- a/FS/t/realestate_property.t +++ b/FS/t/realestate_location.t @@ -1,5 +1,5 @@ BEGIN { $| = 1; print "1..1\n" } END {print "not ok 1\n" unless $loaded;} -use FS::realestate_property; +use FS::realestate_location; $loaded=1; print "ok 1\n"; diff --git a/FS/t/realestate_subproperty.t b/FS/t/realestate_unit.t similarity index 75% rename from FS/t/realestate_subproperty.t rename to FS/t/realestate_unit.t index 0f00eeec5..bbecc1a4c 100644 --- a/FS/t/realestate_subproperty.t +++ b/FS/t/realestate_unit.t @@ -1,5 +1,5 @@ BEGIN { $| = 1; print "1..1\n" } END {print "not ok 1\n" unless $loaded;} -use FS::realestate_subproperty; +use FS::realestate_unit; $loaded=1; print "ok 1\n"; -- 2.11.0