Laravel - Approach to store almost identical data - php

I am building a small system to control my rental properties. In this system, I want to be able to capture any regulations that can happen to a lease. A regulation can happen for:
The rent amount
The prepaid rent amount
The prepaid deposit amount
I am thinking on how I can structure this. I have a Lease model with leases table (simplified):
id | name | address | rent | prepaid_rent_amount | prepaid_deposit_amount
1 | Unit no. 1 | Highland Drive | 1000 | 3000 | 3000
In order to capture if any regulation has happened on the above three parameters (rent amount, prepaid rent or prepaid deposit), I need to store this in a database. The information needed to be capture from these parameters are almost identical:
//Regulation in rent
- lease_id
- amount
- date
- flag
//Regulation in prepaid rent
- lease_id
- amount
- date
//Regulation in prepaid deposit
- lease_id
- amount
- date
Solution 1
I was thinking to create a model/table for each parameter, and simply just store data relevant for each regulation in the corresponding table:
RentRegulation
PrepaidRentRegulation
PrepaidDepositRegulation
I think the benefits of this solution is that the data is separated, however it feels like it is bloating my codebase.
Solution 2
Instead of creating three models/tables to store the above information in, I was thinking to just create one model:
Regulation
An inside this model, simply have a column called type. The value for this column would then control what kind of regulation we were talking about (e.g. RentRegulation, PrepaidRentRegulation etc.)
The only concern I have for solution #2, is for the type RentRegulation there can be different types of regulations. So a rent can be regulated due to the following stuff (all regulated by law):
Increase in inflation
Renovating the lease
Agreement with the tenant that rent should increase
To cater for the above, I was thinking of also adding a nullable flag column to the regulations table, and then just rely on scopes when retreiving data?

Related

PHP+mysql : What would be the simplest way to calculate individual profits from a transaction list containing deposits, gains and withdrawals

I'm absolutely stumped on the right way to do this (let alone the best way).
I have a group of users with shared quantities of bitcoins. We collectively trade and share the profits each day (minus a small percentage which goes to me for the management).
I'm trying to build a system to accurately calculate profits and fees but I just can't figure out the way to do it.
These are the tables I've created in the mysql db:
tansactions: (this information is pulled from the exchange api)
id (primary key)
transactionID (unique)
transactionType (Deposit, Profit/Loss, Withdrawal)
amount (btc amount of deposit, profit or loss, withdrawal)
balance (balance after transaction)
timestamp (timestamp of the transaction)
users:
id (primary key)
nickname (person's name)
accounting:
id (primary key)
userId (id from users table)
transactionType (Deposit, Profit/Loss, Withdrawal)
amount (btc amount of deposits, calculated profits, withdrawal)
date
In my mind, I was thinking I would run a nightly script that would calculate the percentage of each person's profits and record it to the accounting table for that day.
I was thinking the accounting table could look something like this with the nightly script:
Date Transaction Amount Person / System
1/02/2021 Deposit 0.10000000 Person 1
2/02/2021 Profit 0.00041235 System
3/02/2021 Profit 0.00032456 System
4/02/2021 Profit 0.00021435 System
5/02/2021 Deposit 0.13234000 Person 2
6/02/2021 Profit 0.00152390 System
7/02/2021 Profit 0.00143540 System
8/02/2021 Profit 0.00325476 System
9/02/2021 Profit 0.00462534 System
10/02/2021 Deposit 0.00432100 Person 2
11/02/2021 Deposit 0.00625300 Person 3
12/02/2021 Profit 0.00876000 System
13/02/2021 Profit 0.00453720 System
14/02/2021 Profit 0.00642620 System
15/02/2021 Profit 0.00754000 System
16/02/2021 Withdraw 0.00087640 Person 1
17/02/2021 Profit 0.00245300 System
18/02/2021 Withdraw 0.00032625 Person 2
19/02/2021 Profit 0.00134432 System
20/02/2021 Deposit 0.01234500 Person 3
I can't think of an easy way to calculate the profit daily...
Any guidance / advice / help would be greatly appreciated!
Figured this out..
In short, here are the loops (not the most efficient way but, it works)
foreach(user)
{
check initial deposit amount and date
make an array of every date since
foreach(date since)
{
check what the whole account did on that day
calculate this user's percentage on that day
if there is a withdraw / deposit, handle that too
}
}
vague but hopefully explains the logic.

Create view from live stats

I created a sistem to input results from a school basketball tournament. The idea is that after the game the operators will input the result in a format that the system fetches to save in the db in a format like the one below:
Date | Team | Score 1Q | Score 2Q | Score 3Q | Score 4Q | Score OT | Final Score | W | L | Won over Team | Lost to Team | Regular Season? | Finals?
I created a PHP page that calculate many stats from the table above, like Total Wins, Win%, Avg Points, Avg. Points per Quarter, % Turn Around Games when loosing on Half Time or 3Q, % Finals games disputed, Times became champions etc, and many more deep stats.
But I was thinking in creating a View with this information calcalated on the DB and in real time, instead of having the script handles it.
But how can I turn the selects needed from the first table into a working second table with all calculations done whenever we make the selection?
Thanks
#decio, I think your idea about creating a view to calculate those stats is not a bad idea. You might be able to do so with the something similar to the following SQL script:
CREATE VIEW result_stats_view AS SELECT SUM(W) as total_wins, SUM(L) as total_losses FROM precalculate_stats_table_name;
This shows the total wins and losses for the season, but you probably get the idea. Check out MySQL aggregate functions (like average, sum, etc.) here:
https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html
Once you have your calculations added to the view then you can simply do query like this to get your calculated data:
SELECT * from result_stats_view

What is best way of changing between active and upcoming_active records?

I'm using tokens for how many messages a user can send (1 message requires 1 token). At the moment I've just got it subtracting the value from an overall value to check if the user has tokens remaining and that's working fine.
I'm trying to change it so that it shows which bundle is active, so I need to check if the user doesn't have enough tokens remaining in the active bundle change to the upcoming_bundle.
Example:
Stored User Data:
Table Name: Tokens
First Record
id: 1
user_id: 5
bundle_type: small
value: 10
value_remaining: 4
state: active_bundle
Second Record
id: 2
user_id: 5
bundle_type: large
value: 100
value_remaining: 100
state: Upcoming_bundle
User sends 10 messages (10 tokens)
Only 4 remaining tokens in first record. Use 4 remaining tokens and leave
6 tokens
Then subtract the 6 tokens from second record which is now active so that will leave 94 remaining tokens.
Should I have a check to database every time the message is sent and update the database to subtract 1 token at a time, then when the remaining_value hits 0 change active_bundle to inactive and upcoming_bundle to active?
If this is your data model then I would fetch all active & upcoming bundles and then do the logic in php, e.g. subtract remaining tokens, change status, etc and then update them as a transaction.
If you are flexible on how the data is structured, I would rather have some kind of transaction log, from which I can read each action, i.e. whether a bundle was added or a token was used with a timestamp. For example like this:
id | user | change | comment | timestamp
1 | 1 | 10 | bought small bundle | 2016-09-06 09:30:00
2 | 1 | -1 | sent message | 2016-09-06 10:56:00
3 | 2 | -3 | sent multi-message | 2016-09-06 10:57:00
Where id is the transaction id, user the user id, change is the number of tokens added (by adding a bundle) or used (by sending one or many messages) and comment a message describing the action. When you want to find out how many tokens there are left you can just do a search for that user and check their SUM(change) instead of weird searches for active/upcoming bundles. Obviously this can be more or less elaborate depending on your needs.
This does not take into account your actual domain! There are more approaches each having their drawbacks. For example my approach might have problems wen the transaction_log-table gets large because of number of users and increased activity, although it is very unlikely (I have seen mysql perform well with a few million records in a similar log table). The important part is: You should figure out what is important to your use case and build a solution around the requirements.
What I would do is, I would subtract it one at a time, not only this is safer, but also a lot easier.

Altering thousands of records every page refresh

I am starting to think about my new project and I've found a couple of speed issues, so I hope you can help me with selecting a good and elegant way to code it.
Each user has in the database records of "places" he has visited. Each place has "schools" - a number of schools in this particular place. Each school has classes. Each class may end its "learning year" at different times, so it's number should increment if date is >= end of learning year.
So we have such a database:
"places" table:
place | user_id |
-----------------
1 | 4 |
2 | 4 |
User no 4 visited place no 1 and 2
"schools" table:
school | place |
----------------
5 | 2 |
6 | 2 |
Place 2 has two schools - with id 5 and 6.
"class" table:
class | school | end_learning | class_number
---------------------------------------------
20 | 5 | 01.01.2013 | 2
21 | 5 | 03.01.2013 | 3
22 | 5 | 05.01.2013 | 4
School 5 has 3 classes with ids 20, 21, 22. If date is greater than 01.01.2013, the class number of class 20 should be incremented to 3 and end learning date changed to 01.01.2014. And so on.
And now we got into the problem - if there is 1000 places, each with 100 schools, each with 10 classes we got 1000000 records. It's a lot. Because all I have presented is just a simple example I have to consider updating whole database every time user refreshes the page so I'm afraid it might be laggy on that amount of records.
I also can serialize class into one field in school table:
school | place | classes
-------------------------------------------------------------------------
5 | 2 | serialized class 20, 21, 22 with end_learning field and class number
6 | 2 | other serialized classes from school 6
In that case I get 10 times less records but each time I have to deserialize data, check dates and if it's less than now alter it, serialize and save to database. The second problem is that I have to select all records from db to manipulate them not only all those need to be altered.
I am also thinking about having two databases: One with records that might need change in further future, and second that might need change in next 24hrs (near future). Every 24hrs all the classes which end learning in next 24 hrs are moved to "near future" db so every refresh of the page works on thousands of records, not hundreds of thousands or millions. Instead of that it works on millions of records (further future) to create "near future" table only once per day.
What do you think about all those database schemas? Maybe you have a better idea?
I don't quite understand the business logic or data model you outline - but I will assume you have thought this through.
Firstly, RDBMS solutions like MySQL are really, really good at managing large numbers of records, as long as the data you are working with is relational. As far as I can tell, you will be searching across many records, but only updating a few (a user will only be enrolled in a limited number of classes); I don't see this as a huge problem.
Secondly, it's nearly always better to go with the "standard" relational model until you can prove it doesn't meet your performance needs than to go for "exotic" solutions at the start off (I class your serialization and partitioning solution as "exotic" for the purpose of this answer). A lot of time and energy has gone into optimizing performance of SQL; if there were a simple alternative, it would be part of the standard solution. There are, of course, points at which the standard relational model doesn't scale (Facebook-size traffic, for instance), or business domains where the relational model doesn't really fit (documents, graphs). However, all the alternatives have benefits and drawbacks just like "standard" MySQL.
Thirdly, the best way to deal with possible performance issues is, well, to deal with them. In code. Build a test rig, create a schema according to the relational model, populate it with test data (e.g. using DbMonster), throw some load at it (e.g. using JMeter) and tune your schema and queries to prove your situation doesn't fit the standard solution. Only go for something exotic if you really can prove that you can't play nice with standard, relational database stuff.

Managing quotas on CATI software - workaround

I'm trying to figuriung out a way to manage quotas over a CATI system (written in PHP+SQL and XML)
let's say we have a population like this:
CITY | #MALE | #FEMALE | AGE CLUSTER (YOUNG) | AGE CLUSTER (OLD)
NY 200 250 350 100
LA 300 350 250 400
Then we have the db containing all the ppl to be interviewed:
(name, city, sex, age cluster, telphone)
this db will not be necessarely representative of the first table, we have to consider also wrong tel number and any other sort of situation that may force us to drop a record and pass forward.
So, how we can achieve a good quota management at the end of the campaign? What's the best approach? It would be great, also, to maintain quotas over the time: let's say my campign'll last 1 year, I would like to perform a checkpoint at the end of the first 2 month and discover that quotas are ok...
The queXS software (I am the author) implements quotas for telephone interviewing (it calls them row quotas). The code is available here.
Have a look at the admin/rowquota.php file and the functions/functions.operator.php file.
Basically what occurs is:
Setup:
You have a list of people to be interviewed (sample) as you describe
There should be 2 lists, split by area (LA, NY)
Each sample would have a quota of Males, Females, and Age cluster Young/Old
Running:
The system records the outcomes of contacts to each number
Where the outcome is "completed" the system finds all quotas that are fulfilled by that record and adds to the quota
Where the quota is reached - all records that match the query (e.g. Males in LA) will be excluded
Describing the code here would be a bit tedious as a lot of the code is specific to the database setup of the system, but if you require further explanation please let me know.

Categories