Phone books and databases : what's the best option? - sql

I am currently working on a development project for which I need to make a database (I will be using Postgre).
Part of that database must store a phonebook for every company, and also for every user. Those two "types" of phonebook are stored in two tables, although they contain the same type of information :
PersonalPhoneBook(IdOwner, IdUser)
//Ids of the owner and a user he's in contact with.
CompanyPhoneBook(IdCompany, IdUser)
//Ids of the company and a user it's in contact with
The personal phonebook will be retrieved with a request like:
SELECT * F
ROM User
WHERE IdUser IN
(SELECT IdUser FROM PersonalPhoneBook WHERE IdOwner = x);
(this request isn't optimized, but you get the gist).
I should also mention that every user and company has as many details (phone numbers, addresses, ...) as they want, thanks to these three tables :
ContactDetail(IdContactDetail, LbContactDetail, ValueContactDetail)
Company_ContactDetail(IdCompany, IdContactDetail)
User_ContactDetail(IdUser, IdContactDetail)
Now there is something that I didn't take in count in that model : the users and companies will want to include in their phone books some people that aren't users in the database.
So I've been exploring several solutions, and I'd need advice to determine which is best:
Making two other tables to store a fixed number of details (2 phone numbers, 1 address) on those "outsiders".
Making all "outsiders" users (but I find that pretty ugly to store them together)
Store an independent phonebook (LDAP-type) for every company and every user (but then data is replicated)
Keep the contact detail system for companies and users and use a LDAP system for the others
Other...?

Related

Messages read by groups without own database table

I have this table used when a user writes a note.
When writing a note, the user specifies if a sell-department and/or a buy-department should receive the note.
Each user can create a Case (lets say its just a table with case_id and case_text). And the notes the users write are related to a case.
So the table NOTES is (postgres database) something like this:
ID
TEXT (the message itself)
USER_ID (the user that writes the note)
CASE_ID (the case_id for which the note is been written)
Short word about users:
There are "ordinary" users and those working on a department. This should not make big difference for the description here.
When an ordinary user writes a note, let's say he want both buy-department and sell-department to be included (being informed about the note/see the note).
What happens now is that there is another table called UserNotes. It looks like this:
ID
IS_READ
NOTE_ID
USER_ID
DEPARTMENT_ID
READ_AT_DATE
So ordinary user with id = 1 writes this note and in the code (as he tells sell and buy-departments have to be included) I search for all the users working at that specific sell-department and all those working at that specific buy-department. I then put all these users in the table UserNotes. With IS_READ false by default.
When a user in the specific sell-department reads the note, I will then change IS_READ for this user's entry in UserNotes.
This is how it works today. I don't think this is scalable. I'm already getting performance issues. I don't think it is important to know when a note has been read. So because of this I was thinking that maybe the following solution could work. Please have a look and tell me if it could be better and the current one or if you have some other suggestion please let me know:
I drop UserNotes table. I add a new filed in table Notes: READ_BY. Here I will update the field each time a user reads the note.
I don't know if I could use some postgres-specific thing, maybe making this field a json-string and searchable.

Will First Name + Last Name + Date Of Birth combination be unique enough?

I need help with the algorithms/ database design for my current working on web-based application (I apologize for the long question in advance)
Application description:
I am building a customer check-in station (it's basically just a monitor that displays a webpage and was connected to a scanner) where customers who come into an office (similar to a library) can scan their office ID card (it has an unique bar code on it) to check-in, customer information (First name, Last name, date of birth, check-in time...) will be sent/saved onto server and the office administrator will be able to see who is in the office right now and do stuff...)
When creating ID card for a new customer, the only information needed is: first name, last name and date of birth (customer can be any ages from kids to elder) => system will generate a unique bar-code (16 digits) and print out a new ID card (with only the bar-code on it)
Problem:
If a customer forgot/ lost their ID card or sometimes the card is too old so the bar-code can't be scanned, customer can type in their first+last name and date of birth into the check-in station then system will search for (first name + last name + date of birth) and determine whether that customer existing and check them in. But it is possible that there is more than one person who has same name + birthday:
- system then can display all matched people to screen but how can customer know which one is them self?
- or that situation can be avoided if system would not allowing customer who has same name and dob to be saved the to database in first place. But then the customer who came "second" will be very upset that he/she can not have a card :))
Edit:
How do I deal with this problem, I mean this is just a office so we can not ask for SSN or driver license ... the check-in process have to be simple and quick some of them maybe a kids who don't have any ID or phone (they will come with their parents/guardians) and many of them are older people (older than 70, or even 80) they can't even type that why the "ID card - scanning idea is here to help them - all they need to do is scan their card... (I don't think they ever can remember the "security question"), SMS verify will not work (phone number may be changed, not all of customer have a phone, the carrier will be involved here (coverage, rate charge...) I don't want any of that ).
OK after read all your suggestion:
I am thinking about a 4 digit pass-code (like 3 digits security code in the back of a credit card) - it will be printed out in the ID card with the instructions and everything, this will be different from the unique customer number (used to scan), here how it works:
- when creating a new customer ID card, system will ask for an additional 4 digits pass-code and also print it out to the card, an algorithms also will be put there to make sure that customers who have same name + dob can't have same pass-code.
In case customer can't use/lost the card, after they entering name+dob to check-in, system only ask this 4-digit passcode if there are more than 1 matched person, otherwise if there is only 1 person matched, system will check-in them in right on.
if they ever forgot this pass code, I mean there is nothing else they can do for them self, the receptionist will have to somehow help them, what do you guys think, I am still open for suggestions?
My final solution:
Because the cards have nothing else (of customer information) rather than the bar code (customer number) on it so the best way is to preprint (pre-made)them, have them ready in the desk to give to new customers or for card replacement purposes.
When creating a new customer, receptionist will manually input first name + last name + dob + phone number (optional) + email (optional) + home address + customer number (as same as in the card that they about to give to the customer) +. submit, system will check for everything, if everything is good receptionist then give customer a new card => customer come back to check-in station and check-in.
When customers forgot card => they will need to see the receptionist => do verification process => receptionist will check them in manually.
When customer lost card or card is damaged => they will need to see the receptionist => do verification process => receptionist then give customer a replacement card => customer come back to check-in station and check-in.
Have each customer tell you two "security question" style data: Location of birth, favorite dish, ... These can serve as uniquifiers.
You can then prevent duplicates from being entered because in case there is a colliding registration the customer must simply chose a different question.
Some rambling thoughts:
You could assign users a PIN and use that to make the account unique. Presumably to insure that it is unique you would have to assign it, you can't let them invent one. (You could let them invent one and then verify it's unique. That might be good to allow people to use numbers that have some meaning to them so they can remember them.) The big catch to this is that if the person loses his PIN, you're stuck. If the PIN is printed on the card, then if the card is damaged or worn, yes, they could type in the PIN. But if they lost the card, they might have no other record of the PIN.
You could ask for their phone number and use that as an identifier. My grocery store does that for their discount card. I think almost everyone has a phone these days. For the small number who don't, you could generate a random number that looks like a phone number but is not valid (so it won't coincidentally duplicate any real phone number), and use it like a PIN. For example if you're in the US, you could make generated numbers all start 555-555 and then make the last 4 digits be like a PIN. Then the only people who would be a problem are those who don't have a phone AND who lost their card, which should be a very small number.
Is there any information in this system that is confidential, or are people committing to spending money? I mean, if someone walked up to a kiosk and typed in the name and birth-date of his next door neighbor and accessed that person's account, would that be a problem? You haven't said what the system does. If getting into the system gives someone access to the person's medical records or bank account or transcripts of his last confession to his priest, then you have to take steps to prevent unauthorized access, you can't let just anyone come up and claim to be someone else and get in. I'm reminded of a case a few years ago where a reporter got access to records of some politician's DVD rentals. He was apparently hoping to find that he had rented a lot of vile pornography or some such that he could use to embarrass the guy, though as it turned out it was mostly westerns. My point is that even seemingly innocent information could be embarrassing to someone under the right circumstances, so you have to be careful.
How often do people have lost or damaged cards? And are there clerks available who could help someone in such cases? That is, if 99% of the time someone comes in, swipes his card, and he's in and everything is good, and the number of times that someone has a lost or damaged card is very small, you could say that in those cases they have to go to a clerk and show the damaged card, or if they say they lost their card, show identification. Then the clerk can verify whatever and give them a new card. You could have the clerk search by name and have a screen that shows birth dates and addresses, ask the customer what their birth date and address is and if it matches one, give them a new card, if not, say I'm sorry you're not on file. This is quite different from a security point of view of showing the customer the list of birth dates and addresses and letting them pick one, as a customer could, (a) type in a common or overheard name and then pick any matching entry that shows up, or even (b) use this to find the address of someone they want to harass, and then you could be liable.
On the current project I met the same way to find a customer. The project is about TV stuff, so the second level of 'sieve' is address. And I think you need to expand the customer information: a username, an email, an avatar or something easy to remember (or send a SMS with code). Also you can add user friendly behavior: if a customer cannot decide which record about him/her, the customer should go through the wizard and add needed information. Yes, it's hard to find a general evidence for all customers, but you can support several kinds of extra information.
In other words: first name, last name, and birth date aren't enough for unambiguously getting a person.

Database Model - SQL - Best Approach

I'm looking for help with part of a database design.
I have to Model the Database for a Group of Contacts and a Group of Distribution Lists.
Each Contact can be in many Distribution Lists and each Distribution List can have many Contacts. In a normal Instance, I could use a Junction table to achieve this solution.
But there's one more thing to add. Contacts have the option to receive notifications via two different methods which are SMS or Email.
A Contact can request to be sent notification via either or both methods.
The piece of the problem that I am stuck with, is that a Contact may wish to receive notifications differently depending on the specific distribution list.
So we have a problem like this :--
CONTACT A is in DL-A - Receives Notification via SMS
CONTACT A is in DL-B - Recieves Notification via Email & SMS.
I'm trying to avoid having more than one entry for a Contact in my Contacts Table, each contact should be unique.
Can Anyone help?
You could use another junction table:
contactid, distributionlistid, messagepreference
Messagepreference can be email or SMS. Two rows if they want both. New messaging types can be added with no changes to the DB. To be safe, use constants in your code to represent the values you will put into the columns.
Or, add sendemail and sendsms columns to the original junction table, but this has the drawback that you have to change DB structure if you introduce a new messaging type.
So you can add to fields in the junction table:
ContactsDistributions(ContactId, DistributionId, SMSFlag, EmailFlag)
in order to specify the type of notification choosen by the contact for each distribution.
You can add one more field in junction table which will represent how given contact will receive notification from given distribution list.
In this case I would add two fields to the junction table SMS and email both boolean and set to true if and only if they wish to receive notification in that matter. This allows the notifications to be set differently for combination list and contact.
Also depending on how you want to deal with removal from lists you could add a constraint on the junction table so that at least one of the two fields is true so that a notification is always sent although say in google groups I do have access to some lists which I have chosen not to get notifications from.

Organising resource (URI) in REST API

Scenario 1
In my web application say for there is a screen for adding an employee to system. As soon as user tabs after entering name of the employee, it generates the employee code automatically (which is the next field) based on some logic and already present records in the database.
Now I want to expose rest API for this application so that third party devs can build on top of it. So, I will have a resource called as /Employee which will respond for GET, PUT and DELETE verbs. But when a client needs to autofill the code, which is a GET operation, it will be on what resource? Should I make a new resource /EmployeeCodeFor/{Name} or I should get it on /Employee/{Name}/GenerateCode? If I go with /Employee/{Name}/GenerateCode then what about my resource to GET, PUT and DELETE for Employee i.e. actually /Employee/{Id}?
Scenario 2
Here lets take the case of a stackoverflow post. So lets say the resource would be /Post/{Id}. In the same way as in the previous example it lists me possible duplicate question as soon as I tab out of the Title field.
Again on what URL I should get those possible duplicates?
I can't think of more scenarios just now. But many such kind of scenarios may come up in real life application development. How to implement them in RESTful way?
Update on scenario 1
Code and Id are two different fields. Id is primary key, code can be duplicate across departments just to illustrate. Also to generate a code, name should be provided first. So, if user types a name "FirstName LastName" then server might generate FL003 as code assuming that there are already two more employees with firstname starting from F and lastname starting from L in the said department. Department can be identified based on the logged in user.
One way to allow the server an opportunity to pre-fill a bunch of elements in a new resource is to do
POST /Employees
{with empty body}
=>
201 Created
Location: http://example.org/employee/3443
<Employee Id="3443">
<Code>E1001</Code>
<FirstName></FirstName>
<LastName></LastName>
</Employee>
This gives the server one chance to provide default values. If you are looking for a more interactive way for the server to provide feedback during the input, I have another approach but it will take quite a bit more explaining.
Scenario 1
Let say your employee code is a unique identifier. In this case, to get it, you would allow the user to complete any field for the new employee and then make a POST. The server would generate the code and respond to the POST with a link to /Employee/{generated_code} which is the record for your newly created employee.
A GET on /Employee would return a list of all employees. A GET on /Employee/{a_code} will give you the employee detail.
Scenario 2
You could have some kind of query on the /Post collection like /Post?title_like={question_title}. A GET /Post?title_like=REST How to would return you a list of all questions containing "REST How to".

MySQL joins for friend feed

I'm currently logging all actions of users and want to display their actions for the people following them to see - kind of like Facebook does it for friends.
I'm logging all these actions in a table with the following structure:
id - PK
userid - id of the user whose action gets logged
actiondate - when the action happened
actiontypeid - id of the type of action (actiontypes stored in a different table - i.e. following other users, writing on people's profiles, creating new content, commenting on existing content, etc.)
objectid - id of the object they just created (i.e. comment id)
onobjectid - id of the object they did the action to (i.e. id of the content that they commented on)
Now the problem is there are several types of actions that get logged (actiontypeid).
What would be the best way of retrieving the data to display to the user?
The easiest way out would be gabbing the people the user follows dataset and then just go from there and grab all other info from the other tables (i.e. the names of the users the people you're following just started following, names of the user profiles they wrote on, etc.). This however would create a a huge amount of small queries and trips to the database in a while loop. Not a good idea.
I could use joins to retrieve everything in one massive data set, but how would I know where to grab the data from in just one query? - there's different types of actions that require me to look into several different tables to retrieve data, based on the actiontypeid...
i.e. To get User X is now following User Y I'd have to get my data (User Y's username) from the followers table, whereas User X commented on content Y would need me to look in the content table to get the content's title and URL.
Any tips are welcome, thanks!
Consider creating several views for different actiontypeids. Union them to have one full history.