I mean, I have a referral system which is every parent_id has parent and the parent_id of that parent until it gets to the last parent which is the Senior.
Given that a user has purchased an item and it is successful, now I am calling the insertEarnings function to insert the corresponding amount to his parent_id, if his parent_id is Junior his parent_id will get 100.
This is how the question begin, what if his parent doesn't have a rank meaning not active, the amount to be insert to his parent_id will go through the next rank which is the Premium so the Premium will no have 250 total, after that proceed the normal insertion of the amount to the parent_id of Premium which is the Advanced- he will get the corresponding amount which is 200, because the rank below him which is the Premium is existing, the insertion will go through until it gets to the last rank which is the Senior
Imagine that it is looping through the parent until it gets to the last rank - Senior.
The ranks are in order
Junior
Premium
Advanced
Senior
Ranks with their corresponding amount value
Junior - 100
Premium - 150
Advanced - 200
Senior - 250
Users table
+------+------------+-------------+------------+
| id | username | parent_id | rank |
+------+------------+-------------+------------+
| 1 | john | NULL | Senior |
| 2 | jane | 1 | Advanced |
| 3 | josh | 2 | Premium |
| 4 | joey | 3 | Junior |
| 5 | jade | 4 | Basic |
+----------------------------------------------+
Code
$user_id = 5; // jade
$parent_id = 4;
// call the function to insert the earnings
self::insertEarnings($user_id,$parent_id);
private function insertEarnings($user_id,$parent_id) {
if ($parent_id > 0) {
$user_parent = $parent_id;
$has_parent = true;
// start iteration
while($has_parent == true){
$account = User::where('id',$user_parent)->first();
$amount = 0;
if ($account->rank == "Junior" ) {
$amount = 100;
} elseif ($account->rank == "Premium") {
$amount = 150;
// for example this user/parent does not exist the amount(150) for him will be added to the next rank which is the Advance
} elseif ($account->rank == "Advanced") {
$amount = 200;
} elseif ($account->rank == "Senior") {
$amount = 250;
// set to false to stop the iteration
$has_parent = false;
}
$earnings = new Earnings;
$earnings->user_id = $account->id;
$earnings->amount = $amount;
$earnings->save();
$next_parent = User::where('id',$user_parent)->first();
$user_parent = $next_parent->parent_id;
if($user_parent == 0){
$has_parent = false;
}
}
}
}
The $user_id is not used in this example, but there's a use to that that didn't included in the question because that is not the main problem.
Related
I have a loop which will get the parent of a user but only up to the max user rank which is Senior.
My question is how to add the amount assigned to a user rank if he is not/skipped in the loop or no record found for that rank.
The code below is working and inserting the earnings to each rank, because the parents ranks are present in the database. But what if some is not, I want to add the amount of that user who is not in the loop-to the next rank.
Imagine that it is looping through the parent until it gets to Senior, that's how it works.
The rank are in order
Junior
Premium
Advanced
Senior
Ranks with their corresponding amount value
Junior - 100
Premium - 150
Advanced - 200
Senior - 250
Users table
+------+------------+-------------+------------+
| id | username | parent_id | rank |
+------+------------+-------------+------------+
| 1 | john | NULL | Senior |
| 2 | jane | 1 | Advanced |
| 3 | josh | 2 | Premium |
| 4 | joey | 3 | Junior |
| 5 | jade | 4 | Basic |
+----------------------------------------------+
Code
$user_id = 5; // jade
$parent_id = 4;
// call the function to insert the earnings
self::insertEarnings($user_id,$parent_id);
private function insertEarnings($user_id,$parent_id) {
if ($parent_id > 0) {
$user_parent = $parent_id;
$has_parent = true;
// start iteration
while($has_parent == true){
$account = User::where('id',$user_parent)->first();
$amount = 0;
if ($account->rank == "Junior" ) {
$amount = 100;
} elseif ($account->rank == "Premium") {
$amount = 150;
// for example this user/parent does not exist the amount(150) for him will be added to the next rank which is the Advance
} elseif ($account->rank == "Advanced") {
$amount = 200;
} elseif ($account->rank == "Senior") {
$amount = 250;
// set to false to stop the iteration
$has_parent = false;
}
$earnings = new Earnings;
$earnings->user_id = $account->id;
$earnings->amount = $amount;
$earnings->save();
$next_parent = User::where('id',$user_parent)->first();
$user_parent = $next_parent->parent_id;
if($user_parent == 0){
$has_parent = false;
}
}
}
}
Edit:
The $user_id is not used in this example, but there's a use to that that didn't included in the question because that is not the main problem.
I have two tables in my MySQL database:
1 named "stock"
id | product | qty
----------------------
1 | 1 | 15
----------------------
2 | 1 | 20
And the second one named "orders"
id | product | qty | stock_id
----------------------------
1 | 1 | 7 | 1
-----------------------------
2 | 1 | 8 | 1
So, before register a new "order", I need to verify which "stock.id" has free product to sell, with SUM all existent orders.qty and subtract it to stock.qty, for this example I'm going to insert a new order of 10 pieces of product with id '1' ($new_order = '10' (pieces):
for each stock.id { SUM(orders.qty) as total | then verify if 'total' >= $new_order | if(total >= $new_order){select that stock.id} if don't { continue looking for an stock.id with free product for sale } }
Hoping to make myself known, I need your help to structure MySql query from PHP for that function.
UPDATE
I've solved with this double query:
<?
$queryL = "SELECT id,unidades,producto FROM stock WHERE `producto` = '$producto'";
$resultL = $mysqli->query($queryL);
/* array asociativo */
while($rowL = mysqli_fetch_array($resultL, MYSQLI_ASSOC))
{
$id_lote = $rowL['id'];
$unidades = $rowL['unidades'];
$queryD = "SELECT SUM(cantidad) as total FROM `pedidos` WHERE `lote` = $id_lote";
$resultD = $mysqli->query($queryD);
/* array asociativo */
if($rowD = mysqli_fetch_array($resultD, MYSQLI_ASSOC)){
$ventas = $rowD['total'];
$disponible = $unidades - $ventas;
if($disponible >= $cantidad){ $lote = $id_lote; }
}
}
?>
Can someone help me simplifying this?
I'm in the process of finding an efficient way to track returning users.
List of options I went over so far:
save (update) login count per user, per day/week/month
save (update) which users have logged in, in a Text field (bad choice?), per day/week/month
deduce returning users via other database resources (user-added records from several tables)
I think this last option is most efficient, since I won't need to create a separate logging table.
However, a logging table seems more accurate, period-wise, right?
Update:
Accuracy still has the priority for this, so I went with the first option, together with some logic in PHP.
I've opted to store the login counts per week (of the year), like: 201433.
Question: regarding the PHP code, is there a way to combine the two queries, and leave out the nested loop (efficiency)?
Database Table:
+----+--------+--------+-----------+
| id | userId | logins | year_week |
+----+--------+--------+-----------+
| 1 | 1 | 4 | 201432 |
| 2 | 1 | 3 | 201433 |
| 3 | 2 | 2 | 201433 |
+----+--------+--------+-----------+
Queries:
SELECT
userId,
SUM(logins) as total
FROM
User_Logins
GROUP BY
userId
ORDER BY
userId
-----------
// get first year_week
SELECT
userId,
year_week
FROM
User_Logins
GROUP BY
userId
ORDER BY
userId
Query results:
+--------+-------+
| userId | total |
+--------+-------+
| 1 | 7 |
| 2 | 2 |
+--------+-------+
+--------+-----------+
| userId | year_week |
+--------+-----------+
| 1 | 201432 |
| 2 | 201433 |
+--------+-----------+
PHP code:
$returningUsers = 0;
$userLogins = $this->model->firstQuery();
$userLoginWeeks = $this->model->secondQuery();
$today = new DateTime();
function weeksPassed($today, $year, $week)
{
$today->setISODate($today->format('Y'), $today->format('W'));
// year and week from user first login
$yearWeek = new DateTime();
$yearWeek->setISODate($year, $week);
$daysPassed = $today->diff($yearWeek)->days;
$weeksPassed = $daysPassed / 7;
return $weeksPassed;
}
if ($userLogins && $userLoginWeeks)
{
foreach ($userLoginWeeks as $userLoginWeek)
{
$userId = $userLoginWeek->userId;
$year_week = $userLoginWeek->year_week;
$year = (int) substr($year_week, 0, 4);
$week = (int) substr($year_week, 4);
$weeksPassed = weeksPassed($today, $year, $week);
$totalLogins = 0;
// Look up user logins from other query
foreach ($userLogins as $logins)
{
if ($logins->userId == $userId)
{
$totalLogins = $logins->total;
break;
}
}
$avgLogins = $totalLogins;
// Average calculated over weeks that have passed since first login
if ($weeksPassed > 0)
{
$avgLogins = $totalLogins / $weeksPassed;
}
// if average >= 1 per week => returning user
if ($avgLogins >= 1)
{
$returningUsers++;
}
}
}
return $returningUsers;
I am in a bit of a pinch. I am using WHMCS and building a custom report but am running into trouble with one of my queries. Here is an overview:
I have 2 tables; tblinvoices which has the subtotal, tax, total, etc. of the invoice and tblinvoiceitems which has the individual line items that appear on the invoice. I am wanting to run a query that returns all of the individual line items and their price which I have been able to do. I run into problems when I do 'GROUP BY' and group the results by invoice numder, then it only returns the first line item for each invoice. I want to group them by invoice number so it only has 1 line in the report. Here is my query:
$query = "SELECT date_format(tblinvoices.datepaid,'%m-%d-%Y') AS datepaid,
tblinvoices.userid,
tblinvoices.id,
tblinvoices.subtotal,
tblinvoices.credit,
tblinvoices.tax,
tblinvoices.tax2,
tblinvoices.total,
tblinvoices.taxrate,
tblinvoices.taxrate2,
tblinvoiceitems.description,
tblinvoiceitems.amount,
tblinvoices.status,
FROM tblinvoices
INNER JOIN tblinvoiceitems ON tblinvoices.id = tblinvoiceitems.invoiceid
GROUP BY tblinvoices.id";
$result = mysql_query($query);
# Math Operations
$statement = array();
$count = 0;
if ($result !== false) {
while ($data = mysql_fetch_object($result)) {
$invoiceid = $data->id;
$datepaid = $data->datepaid;
$description = $data->description;
$item_amount = $data->item_amount;
$subtotal = $data->subtotal;
$credit = $data->credit;
$tax = $data->tax;
$tax2 = $data->tax2;
$total = $data->total;
if ($export != true) {
$client_link = '<a href=clientssummary.php?userid='.$data->userid.'>'.$data->userid;
$invoice_link = '<a href=invoices.php?action=edit&id='.$data->id.'>'.$data->id;
}
else {
$client_link = $data->userid;
$invoice_link = $data->id;
}
if (strpos($description, 'Setup') !== false) {
$setup = $item_amount;
}
else {
$setup = 0;
}
if (strpos($description, 'Addon') !== false) {
$addon = $item_amount;
}
else {
$addon = 0;
}
if (strpos($description, 'Tax Guide: No => Yes') !== false) {
$taxguide = $item_amount;
}
else {
$taxguide = 0;
}
if (strpos($description, 'Reading Rack Bundle') !== false) {
$reading = $item_amount;
}
else {
$reading = 0;
}
if (strpos($description, 'Toolkit Bundle') !== false) {
$toolkit = $item_amount;
}
else {
$toolkit = 0;
}
$hosting = $subtotal - $setup - $addon - $taxguide - $reading - $toolkit;
$statement[$invoiceid."_".$count] = array($datepaid,$client_link,$promo,$dtn,$company,$state,$invoice_link,$setup,$addon,$taxguide,$reading,$toolkit,$hosting,$subtotal,$credit,$tax+$tax2,$total);
$count++;
}
}
foreach ($headings AS $k=>$v) {
$reportdata["tableheadings"][] = $v;
}
//ksort($statement);
foreach ($statement AS $invoiceid=>$entry) {
$reportdata["tablevalues"][] = array(
$entry[0], // datepaid
$entry[1], // clientid
$entry[2], // promocode
$entry[3], // dtn
$entry[4], // companyname
$entry[5], // state
$entry[6], // invoiceid
formatCurrency($entry[7]), // setup
formatCurrency($entry[8]), // addon
formatCurrency($entry[9]), // taxguide
formatCurrency($entry[10]), // reading
formatCurrency($entry[11]), // toolkit
formatCurrency($entry[12]), // hosting
formatCurrency($entry[13]), // subtotal
formatCurrency($entry[14]), // credit
formatCurrency($entry[15]), // tax
formatCurrency($entry[16]) // total
);
}
mysql_free_result($result);
I will be happy to provide any additional information/code if it helps. I though this might be a more general type question...thanks!
With the result you are describing your result set would look like:
userid | id | subtotal | credit | tax | status | desc | amount
______________________________________________________________
1 | 1 | 20 | 0 | .7 | 1 | item1| 10
1 | 1 | 20 | 0 | .7 | 1 | item2| 10
1 | 2 | 30 | 0 | 2.1 | 1 | item3| 15
1 | 2 | 30 | 0 | 2.1 | 1 | item3| 15
1 | 3 | 10 | 0 | .7 | 0 | item1| 10
1 | 4 | 1 | 0 | .07 | 0 | item4| 1
Is this what you are looking for?
So try group by invoice.id and invoice.userid, and then maybe invoice.subtotal....
May run into some issues if you later decide to aggregate anything but this should do it.
| id | url | title | menu_id |
------+--------+--------+----------
| 1 | http://| link 1 | 1 |
| 2 | http://| link 2 | 2 |
| 3 | http://| link 3 | 3 |
| 4 | http://| link 4 | 4 |
Hi, I was wondering if its possible using PHP to reorder the above to something like below. I am trying to generate a menu which can easily be reordered by clicking an up or down arrow. I have no idea where to start. Any help would be much appreciated.
| id | url | title | menu_id |
------+--------+--------+----------
| 1 | http://| link 1 | 2 |
| 2 | http://| link 2 | 4 |
| 3 | http://| link 3 | 3 |
| 4 | http://| link 4 | 1 |
I went with using the following code
$menu_id = $_GET['page_id'];
$page_order = $_GET['page_order'];
if ($_GET['do'] == 'up') {
mysql_query("UPDATE menu SET menu_order = '$page_order' +1 WHERE id != '$menu_id' AND menu_order < '$page_order'");
mysql_query("UPDATE menu SET menu_order = menu_order -1 WHERE id = '$menu_id'");
} else if ($_GET['do'] == 'down') {
mysql_query("UPDATE menu SET menu_order = '$page_order' -1 WHERE id != '$menu_id'");
mysql_query("UPDATE menu SET menu_order = menu_order +1 WHERE id = '$menu_id'");
}
It's definitely possible, but you have to do a little bit of extra logic, it's not something that can be done in one query.
Think about the steps when you click an up/down arrow. For example, let's say that you start with the items in the order 1, 2, 3, 4 and then you click the up arrow on #3. Two things have to happen to change the order to 1, 3, 2, 4:
3's position changes to 2 (it gets decreased by 1)
2's position changes to 3 (it gets increased by 1)
So you have to change the position for the item that they clicked up on, as well as the one that was previously in its new position. Clicking a down arrow is almost the same, but with the increase/decrease reversed.
I had the same problem, and solved it with an if statement query. Here is step by step instructions:
1.
get the position of the item before updating mysql.
$query = "SELECT * FROM table WHERE id=1;
$result = mysql_query($query);
$item = mysql_fetch_array($result);
$old_position = $item["position"];
we had a form in the page so we get the new position from $_POST data.
$new_position = $_POST["position"];
we determine if we moved the item up or down
if ($new_position > $old_position) { //moved it down
$query = "UPDATE table SET position = position-1 WHERE position >= {$old_pozisyon} AND position <= {$new_pozisyon} and id <> {$id}";
}
and we do the same for the other condition but we make position+1 this time. Hope this helps
#DaveE has the right idea but results in all sorting data being either one higher or lower (depending on direction) for the other rows. Here's my PHP/MySQL:
if ($direction == 'up') {
$q1 = "UPDATE table SET sort = ($sort +1) WHERE id != $pgid AND sort = ($sort -1);";
if($r = mysqli_query($q1, $dbsvr)) {
$q2 = "UPDATE table SET sort = (sort -1) WHERE id = $pgid;";
$r = mysqli_query($q2, $dbsvr);
}
} else if ($direction == 'down') {
$q3 = "UPDATE table SET sort = ($sort -1) WHERE id != $pgid AND sort = ($sort +1);";
if($r = mysqli_query($q3, $dbsvr)) {
$q4 = "UPDATE table SET sort = (sort +1) WHERE id = $pgid;";
$r = mysqli_query($q4, $dbsvr);
}
} else {
echo 'no direction';
}