Whats the best way to represent timesheets in database - database

I'm trying to model timesheets, billable hours, projects, users
Whats the best way to represent these in a database
Elaborating more on the question: My biggest predicament is how to keep date, hours, project together
One possible solution
User (PK id, name)
Project (PK id, name, FK user_id)
BillableHour (PK id, FK project_id, hours, date)
Thanks

Start with the reports you want and work backwards.
The minimal input unit is Activity, Duration, but if you use that minimum, you wind up with activities such as sri.attends.scrum.for.parisian.branch.of.client50.via.scype.from.home.to.discuss.installation.routine.of.zoom22, and your report code will have a lot of switch statements.
Presumably you will have at least one report with a name, an activity description, and a total time for a given time-period. If that's your only report, you can implement it as a four-field list: Worker (string), Task (string), Start (time), Duration (integer). If there's a report asking for all the activities ever allocated to a particular project, or one for all the time spent on activity-type X, or a report that allocates activities to particular clients, your design will benefit from more fields.
Perhaps you have a report that distinguishes installing.server.updates at the home office and installing.server.updates under active enemy gunfire in a warzone. If you have a "while.a.target" checkbox on your time-logging screen, that could be a real time-saver for your users.

It's worth learning about Normal Forms if you're not familiar with them. Saves you storing redundant data in your database (amongst other benefits).
http://databases.about.com/od/specificproducts/a/firstnormalform.htm

I can tell you from a very high level how I've done it for a very simple time keeping app. Although, this isn't necessarily the best way.
I don't have a handy ER diagram to share at the moment, but this is just a very basic starting point for a set of tables anyway.
User
ID PK
UserRole
UserID FK
RoleID FK
Role
ID PK
Name
UserProject
ID PK
UserID FK
ProjectID FK
HoursAvailable
Customer
ID PK
Name
Project
ID PK
CustomerID FK
EntryType
ID PK
Name (i.e. billable, non-billable, etc.)
Entry
ID PK
UserID FK
ProjectID FK
EntryTypeID FK
Hours
Date
TaskName (this could be further normalized, esp. if you want to have a bucket of tasks)
Description
I could go on, but you get the idea.

Here's a brief (and incomplete) summary of some of the tables my old accounting system used:
user: the person using the system; name, password, etc
entity: a company or business; name, government IDs, etc
project: a project that can be billed; name, supplier entity, client entity
timesheet: a timesheet entry: user, project, start time/date, number of hours, description of work

Related

System that keeps track of inventory with a history table

I have a system that lets members rent equipment and the system should have a history of each item that was rented and by who. The system should also track who has what equipment rented/checked out and should also sort the equipment by type, status, name, etc. Lastly it should also send out notification email on equipment that are overdue.
I'm trying to understand the relationships and how I should model this. As of now my current tables and thinking is something like this:
Member Table:
Id (PK)
MemberId
FirstName
LastName
Email
EquipmentItem Table:
Id (PK)
EquipmentName
EquipmentType (FK)
EquipmentStatus (FK)
TotalQuantity
RemainingQuantity
EquipmentStatus Table:
Id (PK)
StatusName
EquipmentType Table:
Id (PK)
TypeName
EquipmentRentalHistory Table:
Id (PK)
MemberId (FK)
EquipmentId (FK)
CheckOutDate
ReturnedDate
1) I want to know the relationships between these would the rental history be a many to many relationship between the Member table and EquipmentItem table?
2) Would EquipmentItem table have a one to many relationship between the status and type, the way I see it is EquipmentItems can have many statuses or types but each status or each type can only belong to one EquipmentItem.
3) Does it make sense to have a quantity field in the EquipmentItem, I used to work in a grocery store so I'm basing the logic on barcodes where same products would usually have the same barcode e.g. (Cheetos Puff chips) all Cheetos Puff chips would have the same barcode but would have a quantity value on it. Or would it be better to have each item unique regardless if it's the same product/model?
My logic would be:
member rents out item
system logs it into the history table
system then checks how many of the same item has been checked out so far, if say we have total quantity of 4 on that item and 3 members has checked it out
we update the remaining quantity field to the difference so in this case to 1
system can then track who has what checked out by returning all records with a returned date of null
system will then check all records with a returned date of null and then do a date range on the checked out date to determine if the equipment is overdue
send notification to member emails associated with said records from step 6
I would just like some help better understanding the relationship between these and if I have modelled my tables correctly, if not, it would be great if someone can point me in the right direction of improving upon this.
To answer your questions
With respect to modelling in an ERD, I don't think that qualifies as a many-to-many relationship, but rather, EquipmentRentalHistory is its own entity that has a many-to-many relationship with both Member and EquipmentItem.
A many-to-many would be more like, "a Member has access to 0...n EquipmentItems, and each EquipmentItem can be accessed by 0...n Members".
I would disagree that they are a one-to-many relationships.
An oxygen tank and a pair of flippers can both be classified as 'Scuba Gear' and have the status 'Checked Out'.
You could have multiple 'Scuba Gear' tags and assign each unique 'Scuba Gear' tag to its very own EquipmentItem, but then you'll just be creating new tags for every new EquipmentItem, rather than reusing existing ones.
That really depends on whether you want to identify exactly which piece of equipment a member rented (maybe something is damaged you can track down everyone who rented that specific one?). If you do differentiate, then every item will just be its own row. You should also add a new column as an external identifier, but there would be no need to keep a tally.
If it's all the same to you, then I would only keep the total but not the available. If you kept the available column, then you would constantly have to update it whenever something is logged in EquipmentRentalHistory. This would be annoying if the tables fall out of sync. You could just query EquipmentRentalHistory for the Id of the equipment, and count up the entries where returnedDate IS NULL for the number of equipment that is currently in use
Additional Note
It might be good to have a 'due date' column in the rental history rather than hard code the date calculation in case you want to varying due dates. This way you can also grant extensions.

T-SQL - Using GUID's Across tables for storing common information?

I started building a database to manage things like vehicles, finances, bills, work history, residence history....etc.
I'm mostly doing this as a learning exercise to teach myself different methods of schema design and ground up development. I've been a database developer for 4 years, but I've only ever worked on the same system/schema. Even my ground up development of new features still have to abide by the existing Schema.
Anyways, I have tables for things like Vehicle Registration, Vehicle Loans/Purchases, Bills, etc. But rather than storing their billing info (payment amount, occurrence, etc), I thought maybe I could put a GUID column on every table, and then store the billing info by the GUID, and then have some sort of view or function that lets me look up the object_id (table) for a particular GUID.
Is this design method a good way to do things?
How would I go about designing the function/view to return the objectid / tablename for specific GUID's?
EDIT: I guess this is a poor explanation, so here's a quick example:
Table: VehicleRegistration
This table would have information like license plate, when the registration is good for, etc.
Table: VehicleLoan
This table would have loan information about each vehicle (amount financed, term, apr, date of purchase, etc).
Both of those tables would also have information like Billing Date, Occurence, Estimated Amount, etc. But instead of storing that data in the two tables, I would store it in another table called BillingInfo or something like that. Obviously I could add a FK on the two tables that point to the PK on the BillingInfo table. But that would mean every table that requires billing information would require that FK on it. Rather than creating that FK on every table...what if instead, every row in VehicleRegistration and VehicleLoan had a unique ID. And I would store the billing info by unique ID instead.
And since it's unque across tables, I would have a function or view to tell me which table that GUID is in. (keep in mind, this is a very small personal database, so for now, speed and optimization is not a concern).
If I applied this method to all common info, like billing information, then I could avoid having to put a FK on every table that needs it. I could just create the table and use the Unique ID's instead?

How to maintain data integrity while allowing for real life changes?

In a new database model that I am designing, I have a company table that has a contacts table related to it using a foreign key companyID field.
I have a branch table with PK branchId and FK companyId.
The problem is: Sometimes contacts can move from the company or branch they are in to a different one. And I need to know all the former companies and branches the contact was in.
What is the best way to do this?
I can't figure out anything that makes sense. If I insert another record into contacts with the different details, There will be a duplicate record, and if I just change the details, how will I know what the former details were?
I would suggest a table that joins your contacts table to your company table. This new table would have a contactsid, a companyid, a date (or date range, depending on your needs) and any other info that you would need to describe the relationship between the contact and the company. The contacts table would then no longer need an FK companyID.

Using Multiple Databases

A company is hired by another company for helping in a certain field.
So I created the following tables:
Companies: id, company name, company address
Administrators: (in relation with companies) id, company_id, username, email, password, fullname
Then, each company has some workers in it, I store data about workers.
Hence, workers has a profession, Agreement Type signed and some other common things.
Now, the parent tables and data in it for workers (Agreement Types, Professions, Other Common Things) are going to be the same for each company.
Should I create 1 new database for each company? Or store All data into the same database?
Thanks.
Since "Agreement Types", "Professions" are going to be same for each company, I would suggest to have a lookup table like "AgreementTypes" with columns such as "ID", "Type" and refer "ID" column in "Workers" table. I don't think new database is required, relational databases are used to eliminate data redundancy and create appropriate relationships between entities.
By imagining having one database for one company, it ends up with having one record in "Company" table in each database. "Administrators" & "Workers" are associated with that single record. And other common entities such as "AgreementTypes" will be in other tables.
So, if there is any addition/modification to agreement type, it is difficult to do it in all databases. Similarly, if there is any new entity to be linked to "Company" entity, again all databases needs to be revisited based on assumption that these entities belong to ONE application.
You should have one single database, with a structure something like this (this is somewhat over-simplified, but you get the idea):
Companies
CompanyID PK
CompanyName
CompanyAddress
OtherCompanySpecificData
Workers
WorkerID PK
CompanyID FK
LastName
FirstName
DOB
AgreementTypeID FK
ProfessionID FK
UserID FK - A worker may need more than one user account
Other UserSpecificData
Professions
ProfessionID PK
Profession
OtherProfessionStuff
AgreementType
AgreementTypeID PK
AgreementTypeName
Description
OtherAgreementStuff
Users
UserID PK -- A Worker may need more than 1 user account
WorkerID FK
UserName
Password
AccountStatus
Groups
GroupID PK
GroupName
OtherGroupSpecificData
UserGroups --Composite Key with UserID and GroupID
UserID PK
GroupID PK
Obviously, things will grow a little more complex, and I don't know your requirements or business model. For example, if companies can have different departments, you may wish to create a CompanyDepartment table, and then be able to assign workers to various departments.
And so on.
The more atomic you can make your data structures, the more flexible your database will be as it grows. Google the term Database Normalization, and specifically the Third Normal Form (3NF) for a database (Considered the minimum for efficient database design).
Hope that helps. Feel free to elaborate if you are stuck - there is a lot of great help here on SO.

Share an "identity" across tables

I am working on a database that has an existing Individuals table that every user type derives from. In other words, there are tables like:
Individual: FirstName, LastName, Email, <lots more>
Employee: IndividualId
Customer: IndividualId
etc.
Now, I want to add new type of user (WeirdPerson) that does not derive from Individual. (WeirdPerson has significantly less data associated with it than any Individual, and I really don't want to set practically every field in Individual to null for a WeirdPerson.)
I need a key field to use on a table that will have entries from WeirdPersons and entries from Individuals. This suggests map tables like so:
MashedupIndividuals: MashedupId, IndividualId
MashedupWeirdPerson: MashedupId, WeirdPersonId
I want MashedupId to be an auto-generated field. Since I'm using TSQL, an identity seems a good choice. Except that MashedupId is split across two tables. I considered yet another table:
MashedupIds: MashedupId
Set MashedupId to be an identity, and then make it a foreign key in MashedupIndividuals and MashedupWeirdPerson.
Is this the best way to proceed forward? How would you solve this?
EDIT: To clarify, the only piece of information I have for a WeirdPerson is an email address. I considered pulling the email field out of Individual, and then making a new GlobalPerson table with only GlobalPersonId and Email. The GlobalPerson table (or whatever better name I use) doesn't feel as natural as separating WeirdPerson as an entirely different type. However... I am willing to reconsider this position.
I would suggest a table to host data common to all people in your application. Then you could have additional tables for specific types of people and link them back to your common table.
tblPerson
PersonID (pk)
name, address, birthday, etc.
tblEmployee
EmployeeID (pk)
PersonID (fk to tblPerson)
Title, OfficePhone, Email, etc.
tblCustomer
CustomerID (pk)
PersonID (fk to tblPerson)
Other fields...
EDIT:
Here are some definitions more applicable to your question (and also more fun with these weird people). The key is establishing the data that weird people and normal people share and then establishing the tables/relationships to support that model. It might be necessary to move fields that are not applicable to weird people from tblIndividual to tblNormalPerson.
tblIndividual
IndividualID (pk)
Other fields for data applicable to both weird/normal people
tblWeirdPerson
WeirdPersonID (pk)
IndividualID (fk to tblIndividual)
NumberOfHeads (applicable to weird people)
tblNormalPerson
NormalPersonID (pk)
IndividualID (fk to tblIndividual)
FirstName (other fields applicable to normal people)
LastName
Etc...
You can use a uniqueidentifier field for your id. This is guaranteed to be unique across multiple tables. Use the NEWID() function to generate new values.
You could have a table with three fields, one of which is always null:
MashedupId, IndividualId,WeirdPersonId
or with an ID field and ID type (individual/weird)

Resources