Symfony2 ->set doesn't update the database - php

I need to create a web application for a touristic agency which promotes auctions online of travels. I've been asked to create a code which allows a user to bid one time before the auction starts, in fact the auction can be seen online while it is not started yet and can receive only one bid from every bidder before it starts. When the auction starts the bidders are allowed to bid only one other time. I know, it's pretty odd. However, with my code I can insert the first bid smoothly but when it comes to update the bid with a new and last price it simply doesn't update the data. I don't know why because it perfectly retrieves the object of the bid and the doctrine's names of each field are right. The fields' names are the following:
- setAmount (how much you bid which changes every time you bid),
- setFirstbid (which turns to 1 one you bid the first time),
- setLastBid (which turns to 1 when you bid the second and last time).
It simply won't update these three fields.
This is the code:
public function createAction(Request $request, ProductInfo $productInfo)
{
** I first get the user info **
$user_fos = $this->get("security.context")->getToken()->getUser();
$id_user = $user_fos->getId();
$id_product = $productInfo->getId();
$user = $this->getDoctrine()->getRepository("CasaUserBundle:User")->find($id_user);
$em = $this->getDoctrine()->getManager();
** I set the bid **
$entity = new BidsInfo();
** I get info about the auction I want to bid for **
$
entity_prod =$this->getDoctrine()->getRepository("ReverseAuctionReverseAuctionBundle:ProductInfo")->find($productInfo);
$form = $this->createCreateForm($entity, $productInfo);
$form->handleRequest($request);
$dati = $form->getData();
** With the following function I verify how many times the bidder has bid and then if he is allowed to bid **
$how_many_bids = $this->getDoctrine()->getRepository("ReverseAuctionReverseAuctionBundle:BidsInfo")->CheckPermit($id_product, $id_user, $dati->getBAmount());
** I check the form validation and if I'm allowed to bid **
if ($form->isValid() && $how_many_bids[0]!=0) {
try{
$em->beginTransaction();
** this is the first bid which works pretty well **
if($how_many_bids[0] == 1){
$entity->setUserInfo($user);
** How much he bids **
$entity->setBAmount($dati->bAmount);
$entity->setProductInfo($productInfo);
$entity->setBidfirst(1);
$entity->setBidfinal(0);
$em->persist($entity);
** the following is the second bid which doesn't work with the updating process **
}else if($how_many_bids[0] == 2){
** I get the bidder's object **
$bid_getid = $em->getRepository("ReverseAuctionReverseAuctionBundle:BidsInfo")->findOneBy(array('UserInfo' => $id_user, 'ProductInfo' => $id_product));
** It doesn't store the following data **
$biduser->setBAmount($dati->bAmount);
$biduser->setBidfirst(1);
$biduser->setBidfinal(1);
$em->flush();
$em->commit();
}else{
throw new Exception("No data found!");
}
$em->flush();
$em->commit();
} catch (Exception $ex) {
$em->rollback();
throw $ex;
}
Do you have any clue why it doesn't store data when I update the bid? It seems setBAmount, setBidFinal and setBidFirst don't work when I update them.

Related

Parallel transactions on database lead to incorrect result, laravel

My application is implemented with php/laravel and MySQL database. In this system, users can deposit money to wallet. I have a wallet_balance column in the users table. When users deposit funds into their wallet, I update that column as follows:
public function topup(Request $request)
{
$user = auth()->user();
$deposit_amount = $request->deposit_amount;
//e.g.
//$deposit_amount = 100
//$user->wallet_balance = 50
$user->wallet_balance = $user->wallet_balance + $deposit_amount;
$user->save();
// After saving I expect $user->wallet_balance to be 150 which works perfectly.
}
There are some services that users are charged where money is deducted from their wallet (in another function). For example:
public function chargeService(Request $request)
{
$user = User::findOrFail($request->user_id);
$service_fee = $request->service_fee;
//$service_fee = 30
//$user->wallet_balance = 150
$user->wallet_balance = $user->wallet_balance - $service_fee;
$user->save();
// After saving I expect $user->wallet_balance to be 120 which works perfectly.
}
After the two transactions, the user's wallet balance should be 120. However, on very rare cases the two transactions might happen concurrently. That means in the deposit transaction, the initial wallet balance is 50 and also for the service fee transaction the initial wallet balance is 50 (because they queried the database at the same time before any of the two updated the wallet balance). Here is the danger. The first transaction will have the resulting wallet balance as 150 (50 + 100), and the second will have it as 20 (50 - 30). This leaves the wallet balance of the user as either 150 or 20, depending on which operation updates the user's wallet balance last.
Now, my question is, how can I approach my wallet system so as to avoid this stinking issue. I will appreciate so much guys.
You can suggest a better way to phrase the question.
The main issue you're facing is that the User state that is loaded in PHP doesn't reflect what's in your database. You should either execute a query against the database:
$params = ['fee' => 30, 'user_id' => $request->user_id];
DB::statement('UPDATE users SET wallet_balance=wallet_balance-:fee WHERE id=:user_id', $params);
or lock the record for updating:
try {
DB::beginTransaction();
// it is important to get the state from the
// database at the time of locking
$user = User::query()->lockForUpdate()->findOrFail($request->user_id);
$user->wallet_balance = $user->wallet_balance - $service_fee;
$user->save();
DB::commit();
} catch (Throwable $e) {
DB::rollBack();
}
You have to lock the row of table using raw mysql query and i dont know if eloquent has some features for that type of query but you can dig in.
Have a look at this article to get a clear picture https://medium.com/#ibraheemabukaff/locking-rows-in-mysql-e84fd3bbb8cd

Codeigniter Unilevel MLM earning Distribution

I am here to have some help from you.
I am making a Unilevel MLM using Codeigniter
and now I can sucessfully add new member
But the problem is I need to distribute the earnings to other level
after a new member is successfully Added
See pic below:
Distribution of earnings
I need to distribute like the image above.
I hope you can help me with this guys.
Okay, I have a solution for you. The process i used is based on my understanding of the question.
So this is it, first i checked for a registration post, if a post request is made, i use the referral id from the post to fetch the number of registrations tied to that referral id that has not been given awarded the 100 earning. If the count of the result of this query is equal to 4, i loop through all of them and give them the earning of 100 and update their paid status to reflect that they have been paid then i insert the record, else i just insert the record.
So too much text, lets see the code
//this is the controller code
//first check for post of registration
if($_POST){
//kindly do your form validation here
$register = array(
"name" => $this->input->post('name'),
"refid" => $this->input->post('refID')
);
//during post, get the referral id from the post
$refID = $this->input->post('refID');
//before registering, use referral id to get the referred that have not been given earnings yet
$thereffered = $this->referral_m->getReferred($refID);
//check for the number of registration
if(count($thereffered) == 4){
//then get their ids and give them their earnings and update them to paid
foreach($thereffered as $referred){
$earnings = array(
"userID" => $referred->id,
"amount" => 100
);
$paid = array(
"paid" => 1
);
//give earning
$this->referral_m->giveEarning($earnings); //this adds the user id to earning table and give it an amount of 100
$this->referral_m->updateUser($paid, $referred->id); //this updates the user with the paid status
}
//then proceed to register the new record
$this->referral_m->register($register);
}else{
//register the new record
$this->referral_m->register($register);
}
//redirect after registration
redirect();
}else{
//load view here
}
This is how the model looks like
function getReferred($refID){
return $this->db->get_where('referral', array("refid" => $refID, "paid" => '0'))->result();
}
function giveEarning($record){
$this->db->insert('earnings', $record);
}
function register($array){
$this->db->insert('referral', $array);
}
function updateUser($array, $id){
$this->db->where('id', $id);
$this->db->update('referral', $array);
}
From the model, you would discover that i created 2 database tables, I assume you already have those tables created, just use the logic to update your code. If you find any difficulty, kindly comment lets sort it out

Does saving a bean delete the record's connection to it email in SuiteCRM?

I run an instance of SuiteCRM v7.7
OS: CENT OS
PHP Version: 5.5.36
DB: MySQL v5.5.50
I've written a scheduled job that, every set interval, it will access Leads records and compare two fields with each other (account_id and account_id_c). It makes sure that they are both equal.
Upon import of a list of leads, these fields should be empty and when the job runs, it'll find the records with empty account_id and account_id_c fields and then find the IDs for the account_name listed in the record. Once the account is located, it inserts the account ids into account_id and account_id_c fields.
Once the fields match, the bean is saved, and so it goes.
Here's a look at my scripting for the scheduled job:
$job_strings[] = 'checkCurrentLeadCompany';
function checkCurrentLeadCompany(){
$bean = BeanFactory::getBean('Leads');
$order_by = "last_name";
$where = "leads.account_id IS NULL OR leads.account_id = ''";
$importedLeadList = $bean ->get_full_list($order_by,$where);
function importedLeads($importedLeadList){
foreach ($importedLeadList as $record) {
$accountBean = BeanFactory :: getBean('Accounts');
$accountRecord = $accountBean -> retrieve_by_string_fields(
array(
'name' => $record -> account_name
)
);
if(isset($accountRecord) || $accountRecord != NULL || $accountRecord != ''){//checks to see if a record populates the variable
$record -> account_id = $accountRecord -> id;
$record -> account_id_c = $accountRecord -> id;
}
else{
//If there is no account available, create the account and proceed.
$newRecord = createAccount($record -> account_name);
$record -> account_id = $newRecord -> id;
$record -> account_id_c = $newRecord -> id;
}
$record->save();
}
}
function createAccount($accountName, $content){
$newAccount = BeanFactory :: newBean('Accounts');
$newAccount -> name = $accountName;
$newAccount ->save();
return $newAccount;
}
if(!isset($importedLeadList)){
//no need to do anything.
}
else{
importedLeads($importedLeadList);
}
return true;
}
The funny thing: every time this script runs, the relationship between the lead record and its email address gets broken. In the database, the "deleted" field in the linking table, email_addr_bean_rel, gets set to 1. I don't know why.
Can anybody give me any insight as to why this happens?
I came across the same problem with Contacts.
After hours of trying to stash the email addresses before saving the contact and then re-link them to the contact (which didn't work) I took a look at the 'Person' class that 'Contact' extends.
The 'save' method looks for the existence of a GLOBAL var called 'resavingRelatedBeans'. If you set this just before saving the Contact bean (remember to unset it after) it doesn't mess up the currently associated email addresses. So now I have:
$GLOBALS['resavingRelatedBeans']=true;
$contactRec->save();
$GLOBALS['resavingRelatedBeans']=null;

CakePHP how to add data from another field of a related model

This is one of my first applications out of tutorials so I don't know how to express my issue well.
Well I have these 2 tables:
User ( id, code )
Hours ( id, user_id, created)
I want to know how I can add an entry to the Hours table using the user_code.
I tried to grab the data of the User table with the code value and then findBy and pass for the patchEntity but it did not work.
I don't have a whole lot of information to work with, but I'll give it a go.
I want to know how I can add an entry to the Hours table using the
user_code
You mention using patchEntity, so that's updating information that's already there. Assuming user_code is the 'code' column you're talking about there, first find the user by his code:
$users_tbl = TableRegistry::get('Users');
// find the user
$user = $users_tbl->findByCode($user_code)->first();
if ($user) {
// replace '$this->request->data() with whatever patch data you wanted
$users_tbl->patchEntity($user, $this->request->data(), [
'associated' => ['Hours']
]
if ($users_tbl->save($user)) {
// success!
} else {
// error!
}
} else {
// error!
}
It will also depend on how you have the data you passed in (where my '$this->request->data() is, or whatever your array might be) - it needs to match the right column names and be in the correct format listed here.
However, this is updating the data. Just adding the data, you can load the hours table and add a new entry with the user_id acquired from the user search:
$hours_tbl = TableRegistry::get('Hours');
$hours = $hours_tbl->newEntity([
'user_id' => $user->id // $user populated from same method earlier
]);
/* assumed 'id' was autoincrementing and 'created' was populated
through Timestamp behavior */
if ($hours_tbl->save($hours)) {
// yay!
} else {
// boo
}

How to perform update for each users in table at different time stamp in codeigniter?

For a CRM System In Codeigniter I Have A Admin module which add the balance to reselle. Now reseller has an option to view his own users and he can add to remove balance. Now if have a radio button on editing that balance is either Yes or No.Here i know the logic but don't know how to implement the below: One the reseller edits a user and sets the balance to yes i want to count 30 days, after 30 days the balance would be reset to no. So i think i should fetch all the users and check when thier balance was set to yes. if its already 30 days then i have a update cron job file which will reset the balance to No. Now i dont know how to do this? how could i check each user? i am very confused about the code and logic. Below is my code to edit the User.
public function edit ($id = NULL)
{
$usertype=$this->session->userdata('usertype');
if($usertype ==="reseller")
{
// Fetch a user or set a new one
if ($id) {
$this->data['user'] = $this->user_m->get($id);
count($this->data['user']) || $this->data['errors'][] = 'User could not be found';
}
else {
$this->data['user'] = $this->user_m->get_new();
}
// Set up the form
$rules = $this->user_m->rules_admin;
$id || $rules['password']['rules'] .= '|required';
$this->form_validation->set_rules($rules);
// Process the form
if ($this->form_validation->run() == TRUE) {
$data = $this->user_m->array_from_post(array('sip_id','sip_pass','name','email', 'password','phone','status','created','balance'));
$data['password'] = $this->user_m->hash($data['password']);
$this->user_m->save($data, $id);
redirect('reseller/user');
}
// Load the view
$this->data['subview'] = 'reseller/user/edit';
$this->load->view('reseller/_layout_main', $this->data);
}
else{
$this->load->view('permission');
}
}
the Reseller:
The User Table:
Trigger example for your database (MySQL):
CREATE TRIGGER resetBalance
BEFORE UPDATE ON your_table_name
IF new.balance = "yes" THEN
SET NEW.reset = ADDDATE(curdate(), INTERVAL 30 DAY);
End IF
UPDATE:
Let's say, you have a field in your db called balance, where you store the value yes or no. (I would prefer here a boolean type.)
And let's say, that you have a field called reset, where you save the resetdate for the balance. The reset field should be a datetime.
If you make an update to any balance field and the «new» entry of the balance field is yes, the database will insert in the reset field the current date + 30 days.
New means the new entry which you save in the db, there is also an old value. That is the value, which was before updating in the column.
That's all.
In your cron, you just check the reset field, do some logic or what ever and delete the value in the reset field.
UPDATE 2:
I just saw, that you have a created and modified field in your db. Here is also the best way to use triggers.
Before Insert:
set new.created = NOW();
Before Update:
set new.modified = NOW();
UPDATE 3:
Today is trigger-day ;-))
Let's say you have a tblUsers and a tblResellers. In the tblResellers you would like to set a reset date, based on a balance field in tblUsers. Then you should create a Trigger in tblResellers like this:
BEGIN
set #userBalance = (SELECT balance FROM tblUsers WHERE id = old.userid);
IF #userBalance = "yes" THEN
SET NEW.reset = ADDDATE(curdate(), INTERVAL 30 DAY);
ELSE
SET NEW.reset = "";
END IF;
END
In the second row, I define a variable «userBalance» which gets its value from tblUsers. In the where clause I use a field from tblResellers (userid), which is corresponding with an ID in tblUsers.
The rows above are easy: Checking the value of userBalance, make some decisions and set the reset date.
I think this trigger will match not all your needs, but you get a feeling of how to do it. If you change the code, make it step by step, to debug triggers is a little bit tricky.

Categories