How to handle customers with multiple addresses in CakePHP - mysql

I'm putting together a system to track customer orders. Each order will have three addresses; a Main contact address, a billing address and a shipping address. I do not want to have columns in my orders table for the three addresses, I'd like to reference them from a separate table and have some way to enumerate the entry so I can determine if the addressing is main, shipping or billing. Does it make sense to create a column in the address table for AddressType and enumerate that or create another table - AddressTypes - that defines the address enumeration and link to that table?
I have found other questions that touch on this topic and that is where I've taken my model. The problem I'm having is taking that into the cakePHP convention. I've been struggling to internalize the direction BelongsTo relationships are formed - the way the documentation states feels backwards to me.
Any help would be appreciated,
Thanks!

You are spot on. You could do either, depending on how much you want to normalise your database. Personally for me, I'd go with an AddressType model, which gives you the flexibility to add and remove address types at will.
If you want it simpler, then I would just go with an ENUM() field in your Address model.

I prefer to think of hasOne, hasMany and hasAndBelongsToMany as the three real relation types.
The belongsTo relation is there simply to do the reverse of what the former two (hasOne/Many) do.
If you look at this diagram, you will notice the pairing of hasOne/belongsTo and hasMany/belongsTo.
Also, note that model that "belongsTo" is the one storing the foreign key (eg. address_type_id).
So in your case, since an AddressType hasMany Address (ie. you can have many Home addresses), then the Address belongsTo AddressType (ie. each address needs an address_type_id).

Table1: address_types (id, name, active)
Table2: customers (id, name, active, etc.)
Table3: addresses (id, address_type_id, customer_id, country, city, street, etc.)
This way customers can have as many addresses as you want. If you need to add a new address type you must not alter the customers or addresses table.

Related

Reference tables instead of Enum fields for lookup efficiency

In my application I have a user which has a profile and an address. The relationship between those tables are:
users: id, type, registered, email...
profiles: user_id, address_id, first_name, last_name, gender, status, etc..
addresses: id, city, street, house_number, apartment
Those tables have some Enum fields on them, but I think it might not be efficient at-all since I'm going to do some intensive user's lookup based on their address and profile so I thought maybe I should use reference tables instead? (I also gain the indexing with an integer which is better).
For example, In profiles I have a status enum field which gets the following values for now:
single
married
widowed
divorced
so I thought about maybe having a statuses table and a foreign key on profiles - status_id.
Another dilemma about this is should I have a reference table for a gender as-well? Currently I only accept male and female values in my enum field for gender, but maybe in the future we will want to add a transgender or anything else. I will also do an intensive user lookup based on gender of-course. Should I also extract it into a reference table?
Enums are internally stored as numbers. The data like gender or status in profile table doesn't get modified very often. So I personally would prefer enums. This would avoid the referencing overhead.
However, it has its own disadvantages.
Please refer to http://chateau-logic.com/content/why-we-should-not-use-enums-databases to know why not to use enums. If you are using multiple languages in your application then enums are a definite NO.

Would a new table really be needed?

I'm making a sql database for a small company.. Pretty much the other tables don't relate to the question so ill list the two that do...
There is a table:
NextofKin:
fname
lname
street
no
houseno
city
AND
Patient:
ID[pk]
fname
lname
houseno
city
Pretty much would I need a seperate table for street, house and city?
also any idea what i could use as a primary key for NextOfKin?
Your questions are starting to get into database normalization.
What you should be doing is never duplicating data between tables unless that data relates the tables, and that data should be indexed. Something like this comes to mind ( there are different ways you might construct it based on business logic )
PersonalData: id, fname, lname, address1, address2, city, state, zip
Patient: id PK, personal_data_id FK, next_of_kin_id FK
Granted most of the tables already exist so this may be impossible. But to answer your question directly, since the database is not normalized already, there's no good place to put further address records ( don't want them under Patient right? ) and so you're stuck duplicating the data. Even so, there has to be some relationship between Patient and NextOfKin, so either Patient holds a reference to NextOfKin, or NextOfKin hods reference to Patient. Either way, you might consider using a foreign key between them to enforce, and explicitly state, this relationship.
Yes, use a pk for next of kin.
Use a joining table between patient and next of kin. Multiple patients could list the same person as next of kin, and while your app may not today require someone to designate multiple people as next of kin, they may change their mind in the future and your application will support it.
Myself, I always use a separate address table. Since usually more than one person lives in a house, and a person can have more than one home, you would again use a joining table.

Mysql database design for customer multiple addresses and default address

I am creating the database structure of an ecommerce with Mysql and INNODB engine.
Point 1: To create multiple addresses for the customers i have this tables
Am I doing it in the correct way? And how should I store the default address (in which table)?
Point 2: I have another table called "Suppliers", should i just connect it to addresses with a "supplier_address" table or is there a better way?
Point 3: What about the tables cities and countries? Should i add something or is that ok? Maybe a field "district" in another table beetween the two?
In my view you're making this far too complex. There's no need to make your address schema so over-normalized. Most systems I've seen that handle multiple customer addresses have a customer table like yours, and then have an address table, as follows:
customer_id
address_ordinal (small number for each customer: 0,1,2,3 etc).
primary (boolean)
address_1
address_2
locality (city, village, etc)
province (state, etc)
postcode (zip, postcode etc)
country
customer_id is a foreign key to the customer table. The primary key is a composite of (customer_id, address_ordinal). The primary column is true if the address is the primary one.
Regarding your question about suppliers, you might want to create a common table called "contacts", and give both your customers and suppliers contact_ids.
If your system contains a reference table (perhaps something you purchase from a data supplier) containing (postcode, locality, province) rows, you can use that to help populate your address table. But you should avoid forcing your addresses to only contain hard-coded postcodes: those reference tables get out of date very fast.
I'll start out my answer with the ole cliche: "There's more than one way to skin a cat." That said, I have a few suggestions:
Point 1 - Assuming a customer can have multiple addresses (i.e. billing and mailing), then yes, you have the right idea in terms of the separate mapping table. As for adding a field to customer_addresses called default or preferred, or something like that, it's not a bad idea, but another option is to add a new field called address_type that would reference a separate table with two records, "Billing" and "Mailing" and/or whatever else you would want. Then, in whatever application you are coding that is going to use the address data, depending on what context i.e. if you're on the billing info page, then code the address type that you use on the page itself something like SELECT * FROM customer_addresses WHERE address_type = 2 /* Billing */.
Point 2 - Same as for customers.
Point 3 - Do you want to be able to display shortened country names? For example, abbreviate "United States" to "US," "Canada" to "CAN," or "United Kingdom" to "UK?" I'd consider adding a field for abbreviated country names for that purpose.

A User with many Addresses, but User has a primary billing, shipping, and profile Address

I'm building a Rails app where a User can have many Addresses. A User also needs a primary billing Address, primary shipping Address, and primary profile Address. These primary fields can point to the same Address. A User cannot have more than one of any primary Address.
I've created a join table called AddressInfo, and I'm bouncing between a few options:
Make 3 columns on the User model corresponding to each of the primary Address ids (this would remove the need for the join model I think).
Add a primary boolean column to AddressInfo, and make sure only one is true when scoped by user_id, address_id and purpose (purpose being billing, shipping or profile).
Add a primary date time column to AddressInfo, and use the most recently updated as the primary address (scoped like option 2).
Maybe these options aren't the best, but it's what I've come up with so far.
Any help on how to resolve this issue would be appreciated.
UPDATE:
To be clear, once an Address is created it should always belong to that User and be undeletable. Ex. a User changes their primary billing address to a new Address: they should still be able to retrieve that old Address (maybe even make it a primary address again). If I go with option 1 and remove the join table, that means I'll need a user_id on Address.
Go with option 1, 3 columns. This will make less of a headache (as a programmer), will run faster, and is more flexible for doing things like combining similar addresses into one. Maybe you have 2 people with the same address, they could share the same record (not recomeneded though).
If you're using rails I would look to a rails solution to 'stay on the rails'.
I would consider STI (Single Table Inheritance)
More info at Rails: Need help defining association for address table
or a Polymorphic relationship - http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
As you want 1 user to have multiple address (rather than ther being multiple user types) than STI may be best for you.
Note: they can also be combined, e.g. http://www.archonsystems.com/devblog/2011/12/20/rails-single-table-inheritance-with-polymorphic-association/
There's a great example of STI addressing this issue at: http://blog.arkency.com/2013/07/sti/
Another possibility is to create another model to hold user.id, addressinfo.id, and an primary_for_address_type (containing "Shipping", "Profile", "Billing").
Constrain this to be unique on user and primary_for_address_type, and you can tag addresses in AddressInfo as being the primary for particular address types in a completely extensible way that still guarantees uniqueness of the primary address.
You might join directly from this model to address, but there's scope for getting it out of sync with your addressinfo model.

MySQL database basic design

I have 3 entities:
buildings
activities
addresses
And I don't know how to foreign key the relationships between tables.
Buildings are located at addresses.
Activities are performed at addresses (one address at a time).
But I just want one address table.
Suppose the next attributes:
Buildings(id,phone,email,image,comments) <- should I put address_id ?
Activities(id,description) <- should I put address_id?
Addresses(id,street,city,state,postcode) <- or should I put center_id and activity_id here?
Thank you in advance!
You should use address_id both in buildings and activities tables.
Address is unique, while many buildings and many activities can be located to the same address!!
Your question implies that multiple buildings can be located at the same address - is this what you want? If so, just normalize it accordingly:
The Address is your 'root entity':
ADDRESS(address_id,street,city,state,postcode)
A Building can be located at exactly one Address, so include a reference to Address, a foreign key:
BUILDING(building_id,phone,email,image,comments,address_id)
An activity is performed at exactly one address, references to Address by foreign key:
ACTIVITY_ID(activity_id,description,address_id)
Maybe you should think about whether:
a street number is missing in the address?
should having more than one building at a given address be possible?
more than one address for a given building is possible (yes, I've seen this)?
a separate ADDRESS table is really necessary (see above questions)?
Alex, you should have the IDs in both tables, as you're saying in your question. There is no need to have them in separate tables as actually the address of a building will be where an activity will be performed, right?
If you are worried about two buildings having the same location then add a uniq index in the address_id column of the buildings table.
Moving a bit forward. Can you have an address without a building? If that is the case, then you could even add the address data (columns) to the buildings table. Because it would be a one-to-one relationship and no other entity would need to use the address table but the buildings one. That way you would get rid of the addresses table