Housing Society management system database structure - mysql

I am designing billing structure for housing society yesterday I googled and gone through banking billing structure and designed my database structure but I am not sure whether this would be correct. So I am putting my billing database structure.
Please tell me if I am wrong any where or any changes has to be done in my database structure.
And one more questions where I have to post society balance (debit, credit )like eg expense Bldg insurance and income like Adv board hoarding and also not sure about balance audit trail (having it in transaction table of separate table with transaction id as FK).
Please note all table will have by default have created,modified time, by and ip address
Table billingstatement
id | description | amount | Bill Month | userId | societyId
1 | Maint Chrg 1000 sqft x 5 per sqft | 5000 | Aug-16 | 1001 | 101
2 | Water Charges | 200 | Aug-16 | 1001 | 101
3 | Construction Charges | 300 | Aug-16 | 1001 | 101
4 | Reserved Parking chrgs | 500 | Aug-16 | 1001 | 101
Table Accounts
id | balance(current bal) | societyId | modifiedTime |
1 | -6000 | 101 | 2016-01-01 21:01:01 |
2 | -5000 | 101 | 2016-01-01 21:01:01 |
3 | 1000 | 101 | 2016-01-01 21:01:01 |
Table transaction
id | amount | balance | trans_type | trans_time | account_id |
1 | 6000 | 0 | 1 | 2016-01-01 21:01:01 | 1 |
2 | 5500 | -6000 | 1 | 2016-02-01 21:01:01 | 2 |
tran_type :- 1 = Payment by user, 2 = Income to society, 3 = Expense to society
Table map_account_user
map_id | account_id | user_id
1 | 2 | 1001
If account mapping is not present then it means it is a society account and not a user account.
Reference :-
billing banking desing
banking project sample

I have a hesitation with storing an aggregate with the entity. Unless the aggregate is very difficult to calculate, you should always account for these by examining the details.

I'm assuming you are designing a relational database. In a relational database, you normalize the data.
I'm having trouble following your database design because you have too many different fields called id. Each id field should get a unique name, so people can tell what the different id fields represent.
Let's start with the Transaction table. Generally table names are singular. I capitalize table names and column names. You don't have to follow that convention.
Transaction
-----------
Transaction ID
Transaction Type
User ID
Society Account
Transaction Amount
Transaction Time Stamp
...
Transaction ID is an auto-incrementing integer. It is also the primary (clustering) key to the Transaction table. Transaction Type is 1 = Payment by user, 2 = Income to society, 3 = Expense to society. I'm not sure what the difference is between Transaction Type 1 and Transaction Type 2.
Either the User ID or the Society Account column is filled in. The User ID column is filled in for Transaction Type 1 and the Society Account column is filled in for Transaction Types 2 and 3. The not filled in column is set to null.
Transaction Amount is always a positive value. Your code will subtract the Transaction Amount from the Society Account for Transaction Type 3.
You will create a unique index for (User ID, Transaction Time Stamp descending, Transaction ID) and a unique index for (Society Account, Transaction Time Stamp descending, Transaction ID). This allows you to quickly get all the transactions for a user or society account, for a given month.
Next, let's look at the UserAccountBalance table.
UserAccountBalance
------------------
User ID
Balance Year and Month
Balance Amount
...
The primary key to this table is (User ID, Balance Year and Month descending). You maintain the historical balances for each month for each User ID. This allows an auditor to verify the balances by running queries against the Transaction table.
Next, let's look at the SocietyAccountBalance table.
SocietyAccountBalance
---------------------
Society Account
Balance Year and Month
Balance Amount
...
This table is similar to the UserAccountBalance table, but for Society accounts.
Next, let's look at the Billing table
Billing
-------
User ID
Billing Year and Month
Billing Type
Square Feet
Charge per Square Foot
Total Charge
...
The primary key is (User ID, Billing Year and Month descending, Billing Type). I'm assuming that you only get one billing charge per billing type per month.
Billing Type is 1 = Maintenance Charge, 2 = Water Charge, 3 = Construction Charge, 4 = Reserved Parking Charge. You can generate the text on the bill from the values in this table, so there's no need to store the text in the database. The Square Feet and Charge per Square Foot columns are filled in for Billing Type 1, otherwise they are null.
You still have to match up the payments with the billings, but this should be enough to get you started on the right path.

The structure works. I would change the id naming a bit.
account_id is referenced in some places
but in the account table it is Id.
I would make it account_id in the Account table. This makes it easier to locate where you can join for the users of the database. Every place you call it "Account_Id" is should be the same Account_Id with a single master table that generates it.

Really appreciated for your efforts. You reference on banking system is really a best approach. I would like to provide you some ideas which may help you if you feel it is better for you.
Let's start. If you use your description column's data:
{Water Charges
Construction Charges
Reserved Parking chrgs}
as a new columns, your no of rows will be decreased and since you can have efficient data maintenance. For each userId you can have a single row of data rather than maintaining four rows. Just verify below provided example.
For each sq ft you can have a description column separately.
id | userId | societyId | BillMonth | MaintChrg | WaterCharges | ConstructionCharges | ReservedParkingCharges | Description
1 | 1001 | 101 | Aug-16 | 5000 | 200 | 300 | 500 | Maint Chrg 1000 sqft x 5 per sqft
2 | 1002 | 101 | Aug-16 | 4000 | 200 | 300 | 500 | Maint Chrg 900 sqft x 5 per sqft
3 | 1003 | 102 | Aug-16 | 5000 | 200 | 300 | 500 | Maint Chrg 900 sqft x 5 per sqft
For you doubt on debit and credit use:
debit as expenseBldginsurance
credit as Adv board hoarding
You can also add may other columns like user name, No of peoples, electricity charges, etc.

Related

select, insert and loop for rows in cronjob

I have a small giveaway table and I need cronjobs in MySQL to make it automatic.
giveaways_participants table
This is where your user id gets added when you participate in a giveaway.
id | user_id | giveaway_id
__________________________
1 | 1 | 4
2 | 67 | 39
giveaways table
All giveaways available
id | user_id | contents | expires
__________________________
1 | 1 | 4,189,45,7 | 1512484213
2 | 67 | 39 | 1512484213
3 | 67 | 8,2,645 | 1512484213
inventory table
The users inventory
id | user_id | item_id
__________________________
1 | 1 | 4
2 | 67 | 2
3 | 67 | 7
I want the cronjob to daily go through giveaways that have expired (ended), pick a random winner from giveaways_participants for that specific giveaway and insert the contents from giveaways into inventory as a new row for every item separated by a comma for that user.
How can this be achieved in the most efficient way possible?
I would just create a php page (if it's possible for you) which can be called from crontab, like php dailyga.php.
What would be in that page? Select from giveaway's table, which data has just expired and pick it's id. Then select all ids from your users and pick random one, then insert into inventory that user's ID and giveaway ID.
Setting a cron job for every morning would do the job (or midnight etc.).
How to pick just expired giveaway? Just select those which expiry date is in the past (even a minute), but the youngest - or the one for which there is no entry in inventory table.
Hope I helped a little.

Improve relationship between 3 tables in MySQL

I have 3 tables on my database: users, payment_methods and user_blocked_pm. The users table speaks for itself, the payment_methods stores all the payment methods the company uses, and the user_blocked_pm has the payment methods blocked for a specific user.
+------------------+
| users |
+-----+------------+
| id | user_name |
+-----+------------+
| 1 | John |
| 2 | Davis |
+-----+------------+
+-----------------------+
| payment_methods |
+-----+-----------------+
| id | payment_method |
+-----+-----------------+
| 1 | credit_card |
| 2 | cash |
+-----+-----------------+
+-----------------------------------+
| user_blocked_pm |
+-----+---------+-------------------+
| id | user_id | payment_method_id |
+-----+---------+-------------------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 2 |
+-----+---------+-------------------+
So, following the structure above, both payment_methods are blocked for the user John and cash is blocked for Davis.
Following this structure when there are multiple users and payment methods I'll have multiple records on user_blocked_pm because each user will be allowed to use only a few of the payment methods.
Is there a better way to work this relationship between the users and the user_blocked_pm so that the table doesn't get gigantic?
You do not need the id column in user_blocked_pm table because you going to select on user_id or pm_id
If the number of the allowed pm is less then the number of the not allowed, why not to make a user_allowed_pm table instead of user_blocked_pm
If you have a fixed number of pm for each user then you do not need a table just you create a column for every pm and you put the key of the pm (like a foreign key)
If you have a few user "types", then perhaps you can replace the user_blocked_pm with a user_type_blocked_pm. A "type" is a set of blocked/permitted payment methods. So the user_type_blocked_pm table is small -- has entries for the different types (users who can pay with cash only, users who can pay with credit and cash, etc. ) Then, you can add a column to the users table to indicate the user type.
Your method is fine, and the other ideas so far suggested are also fine. If the number of payment types is small (not more than 7, say - and certainly less than 64!), and finite, then you might also consider a bitwise method, where 1 = credit_card, 2 = cash, and 3 = both. I do this for days of the week, which are unlikely to ever be more than 7.

How should I design my database for different user has different devices?

I was confused about database design.
This is my request: There are different users; a user can has one or more devices. Some users will have thousands devices even ten thousand devices. A device has many operation records. One day adds 10-20 operation records.
I prepare to create a table for user record userId, passWord. A different user creates different device list table record deviceNum, devicState. A device has a operation table record operation records.
So, my database will have many many tables. I guess I have more one hundred thousand devices. Should I create one hundred thousand devices tables?
From you've said you need 3 tables only:
Users - user_id, username, pass, data, etc...
Devices - device_id, user_id (owner), device_data....
OpRecords - record_id, device_id, record_data_stuff...
All users go to the first table with additional fields you need for user data like address, phone, last login time, etc.
All devices are registered into the Devices table with each device having association to the user who owns it - the user_id. You can make as much columns as needed - like device type, device name, parameters, workhours and so on...
All records go to a single table and record is associated with the device that did the job (device_id). You can make your additional columns here to write record-specific data like start_time, end_time, and so on...
You don't need to have a separate table for the record list of each device. When you need to show the records of a single device just make SELECT with device_id = X and you will receive the records for your device only.
UPDATE:
ten thousand devices ,everyone make ten operation records one day .ten
days
It makes about 1 million records for 10 days. It is a chalange. But I don't think splitting this data into different tables will give you a better performance.
You should set as minimum columns in the records table as possible. Place there the minimum required information. Try not to use strings and if possible use only integer numbers. If you use fields to write date/time use TIMESTAMP as it is closest to integer number. Create indexes on all columns you will use to search data - device_id, time (if you have such column) an so on. This will increase disk usage but I think will raise the performance.
Consider if you can backup your data to external file after a given period - in example after a month you would free 3 million records.
I would suggest using a layout like this:
User
+----+----------+----------+-------+
| id | username | password | email |
+----+----------+----------+-------+
| 1 | jon | xxxx | xxxx |
| 2 | melissa | xxxx | xxxx |
+----+----------+----------+-------+
Device
+----+---------+--------+
| id | user_id | name |
+----+---------+--------+
| 1 | 1 | iPad |
| 2 | 1 | iPhone |
| 3 | 1 | Laptop |
| 4 | 2 | Laptop |
+----+---------+--------+
Operation
+----+-----------+-----+-------+
| id | device_id | key | value |
+----+-----------+-----+-------+
| 1 | 1 | x | y |
| 2 | 1 | y | z |
| 3 | 2 | x | x |
| 4 | 2 | z | y |
| 5 | 3 | x | y |
+----+-----------+-----+-------+
I hope that I got your question right.

How would I normalize this un-normalized database table?

I am programming a site which stores poker session data. A session is a period of time spent at a casino playing poker. A session contains information such as the date/time, the net profit/loss of the session, and the location where they played. However, the part I'm confused about is how to handle a session type. In poker there are two kinds of games: cash games and tournaments. Each have their own specific fields pertinent only to them. Here is an example table (I've removed the irrelevant fields):
+----+--------------+--------+--------+
| id | session type | stakes | buy-in |
+----+--------------+--------+--------+
| 1 | cash | 1/3 NL | NULL |
| 2 | cash | 1/2 NL | NULL |
| 3 | tournament | NULL | $20 |
+----+--------------+--------+--------+
As you can see, I do not need buy-in if the session type is cash. Similarly, if the session type is tournament, I do not need the stakes field.
How would I go about normalizing my table such that I do not have NULL fields? Performance-wise, will my application suffer if I'm normalizing this table just to make it so I do not have NULL values in my row?
Here is one possible solution:
sessions:
id_session (PK)
session_type (Integer/Enum)
cash_sessions:
id_session (FK)
stakes
tournament_sessions:
id_session (FK)
buy_in
So, separate table for every session type, thus you will be able to define different columns for different types, also have common columns in sessions table
Example data:
sessions
1 1
2 1
3 2
cash_sessions
1 1/3 NL
2 1/2 NL
tournament_sessions
3 $20
Another solution:
sessions:
id_session (PK)
session_type (Integer/Enum) <- basically useless field for this schema
attributes:
id_attr (PK)
name (String)
session_attributes:
id_session (FK)
id_attr(FK)
value (String)
so, instead of thinking in terms of "session type" you can change your business model to think about "session attributes", so, different sessions can have different sets of attributes assigned
Example data:
sessions
1 1
2 1
3 2
attributes
1 stakes
2 buy_in
session_attributes
1 1 1/3 NL
2 1 1/2 NL
3 2 $20

How to create mysql db for account balace, add and subtract amounts

I have project like online service, i have made some part and stopped. If user use service it must take some amount (e.g. 5$ per service). I don't know how to build MySQL tables. I have made 2 tables 1st for rest amount 2nd for add and subtract amounts. May be this is wrong way, what is the best practice?
action_table
id | userId | reason | amount
1 | 4 | for service 3 | -5
2 | 2 | refill account | 100
3 | 13 | for service 3 | -5
balance_table
1 | 4 | 23
2 | 2 | 125
3 | 13 | 0
After using service query adds one row to action_table and updates balance_table
Personally, if I was making an account database, I would have one table for an account and one for transactions, like this:
Accounts:
| id | user | name | balance |
Transactions:
| id | account_id | description | amount | is_withdrawal |
The reason I came up with this is because it helps to think of database tables like real world objects sometimes, and in this case you have a Transaction and an Account.
Then, you can use a TRIGGER to update the account table anytime you add a transaction.