api_group_version = "3"; $this->api_mess_version = "3"; // new date change $this->api_family_version = "3"; $this->app_version = "1"; // 1= old app; 2=new app; date related $this->setDefaultTimeStamp(); } private function validateExpense($expenseArray){ $error = ""; if(empty($expenseArray)){ $error = "5"; } if($error == ""){ if (!array_key_exists('title', $expenseArray) || !array_key_exists('currency', $expenseArray) || !array_key_exists('language', $expenseArray) || !array_key_exists('expense_type', $expenseArray)) { $error = "6"; } } if($error == ""){ if(strlen(trim($expenseArray["title"])) < 1 || mb_strlen(trim($expenseArray["title"]),'UTF-8') > 50){ $error = "7"; } else if(strlen(trim($expenseArray["currency"])) < 1 || mb_strlen(trim($expenseArray["currency"]),'UTF-8') > 3){ if(mb_strlen(trim($expenseArray["currency"]), 'UTF-8') > 3){ $expenseArray["currency"] = substr(trim($expenseArray["currency"], 'UTF-8'), 0,3); } else { $error = "7"; } } else if( mb_strlen(trim($expenseArray["description"]),'UTF-8') > 150){ $error = "7"; } else if(strlen(trim($expenseArray["language"])) < 1 || mb_strlen(trim($expenseArray["language"]),'UTF-8') > 3){ $error = "7"; } else if(strlen(trim($expenseArray["expense_type"])) != 1){ $error = "7"; }else if(!empty($expenseArray["user_id"]) && !is_numeric($expenseArray["user_id"])){ $error = "7"; } } return $error; } private function validateParticipant($ParticipantArray){ $error = ""; if(empty($ParticipantArray)){ $error = "8"; } if($error == ""){ foreach($ParticipantArray as $key=>$value){ if (!array_key_exists('participant_id', $value) || !array_key_exists('name',$value) || !array_key_exists('is_creator', $value)) { $error = "9"; break; } $nameArray[$key] = $value["name"]; $idArray[$key] = $value["participant_id"]; //check name length if(strlen(trim($value["name"])) < 1 || mb_strlen(trim($value["name"]), 'UTF-8') > PARTICIPENT_NAME_LENGTH){ if(mb_strlen(trim($value["name"]), 'UTF-8') > PARTICIPENT_NAME_LENGTH){ $value["name"] = substr(trim($value["name"], 'UTF-8'), 0,PARTICIPENT_NAME_LENGTH); } else { $error = "10"; break; } } else if(strlen($value["name"]) > strlen(str_replace(",","",$value["name"])) || strlen($value["name"]) > strlen(str_replace("|","",$value["name"]))){ $error = "10"; break; } //check participant id format $arrayVal = explode("_", $value["participant_id"]); if(count($arrayVal) != 2){ $error = "11"; break; } else if(strlen(trim($arrayVal[0])) < 1 || strlen(trim($arrayVal[1])) < 1){ $error = "11"; break; } } //check name duplicacy if($error == ""){ $previousLength = count($nameArray); $nameArray = array_unique($nameArray); if($previousLength != count($nameArray)){ $error = "12"; } } //check id duplicacy if($error == ""){ $previousLength = count($idArray); $idArray = array_unique($idArray); if($previousLength != count($idArray)){ $error = "12"; } } } return $error; } private function validateExpenseList($GroupExpenseArray,$ParticipantArray,$isDeleteOperation = false){ $error = ""; /*if(empty($GroupExpenseArray)){ $error = "13"; }*/ if(!empty($GroupExpenseArray)){ if($error == ""){ $participantIdList = array(); foreach($ParticipantArray as $key1=>$value1){ $participantIdList[$key1] = $value1["participant_id"]; } foreach($GroupExpenseArray as $key=>$value){ if (!array_key_exists('id', $value) || !array_key_exists('what',$value) || !array_key_exists('expense_date', $value) || !array_key_exists('amount', $value) || !array_key_exists('paid_by_participant_id', $value) || !array_key_exists('is_reimbursement', $value) || !array_key_exists('participant_amount', $value) || !array_key_exists('isDetails', $value) || !array_key_exists('type', $value)) { $error = "14"; break; } //check id format is correct or not $arrayVal = explode("_", $value["id"]); if(count($arrayVal) != 2){ $error = "15"; break; } else if(strlen(trim($arrayVal[0])) < 1 || strlen(trim($arrayVal[1])) < 1){ $error = "15"; break; } $arrayVal = explode("-", $value["id"]); if(count($arrayVal) != 3){ $error = "16"; break; } else if(strlen(trim($arrayVal[0])) < 1 || strlen(trim($arrayVal[1])) < 1 || strlen(trim($arrayVal[1])) > 5 || strlen(trim($arrayVal[2])) < 1){ $error = "16"; break; } //check the participant defined in expense exist in participant list or not if(!$isDeleteOperation) { $paidBy = $value["paid_by_participant_id"]; if(!in_array($paidBy, $participantIdList)){ $error = "17"; break; } } $totalAmt = 0; $partAmtArray = explode(",",$value["participant_amount"]); foreach($partAmtArray as $index=>$item){ $partAmtDetailArray = explode("|",$item); /* echo $partAmtDetailArray[0]; echo "
";
				 	print_r($participantIdList);
				 	exit; */
				 	
				if(!$isDeleteOperation) {
                  if(!in_array($partAmtDetailArray[0], $participantIdList)){
                     $error = "18";					 	 
                     break 2;
                   }
                }
					 
					 $totalAmt = $totalAmt + $partAmtDetailArray[2];
				 }
				//check total amount match with the part amount or not
				if(number_format($totalAmt, 2) != number_format($value["amount"], 2)){
				    
				    $var1 = number_format($totalAmt, 2);
				    $var2 = number_format($value["amount"], 2);
				    
				  
				    
				    $diff = $var1-$var2;
				    
				    
				    
				    if($diff < 0){
				        $diff = $diff * (-1);
				    }
				   
				    $diff = number_format($diff, 2);
				    
				    if($diff > 0.02){
				    
					   $error = "19";
					   break;
				    }
				}
				 
				
				//check legth is ok or not
				
				if(strlen(trim($value["what"])) < 1 || mb_strlen(trim($value["what"]),'UTF-8') > 25){
				    
				    
				    if(mb_strlen(trim($value["what"]), 'UTF-8')  > 25){
				        $value["what"] =  substr(trim($value["what"], 'UTF-8'), 0, 25);
				        
				    } else {
				        
				        $error = "20";
				        break;
				    }
				    
					
				}



			}
			
			 
		}
		
	}
		
		return $error;
	}

    public function getAccessKey() {

        $status = "+000";
        $status_desc = "SUCCESS";
        $error = "";
        $secretKey = "";

        $object = $this->request->input('json_decode');

        if(!empty($object)){
            $data = $this->objectToArray($object);
        }




        //check maintenance mood
        if(MAINTENANCE_MOOD){
            $status = "35";
            $status_desc = "Service is in maintenance mood. Please try again later.";
            $error = $status;
        } else if(empty($data)){
            $status = "31";
            $status_desc = "Invalid JSON input sent";

        } else if(!isset($data["device_id"])) {
            $status = "14";
            $status_desc = "Invalid parameter sent";
        }else  if(empty($data["device_id"]) ){

            $status = "33";
            $status_desc = "Invalid device id";
        } else {

            $data['device_id'] = $this->request->data('device_id');
            $data['created_on']  =  $this->getSystemCurrentTimeStamp();
            $secretKey = $data['secret_key'] = $this->getSecretKey(32);

            $this->loadModel('AccessKey');

            if(empty($this->AccessKey->saveAccessKey($data))){
                $status = "+000";
                $status_desc = "SUCCESS";

            }
        }

        $input["status"] = $status;
        $input["status_desc"] = $status_desc;
        $input["api_version"] = $this->api_group_version;
        $input["access_key"] = $secretKey;


        if(!empty($error) || $status !="+000") {
            $input["input"] = $data;

            $this->loadModel('LogAppCrashes');
            $crash["unique_url"] = "";
            $crash["error_code"] = $status;
            $crash["error_desc"] = $status_desc;
            $crash["request"] = serialize($data);
            $crash["response"] = serialize($secretKey);
            $crash["crash_date"] =  $this->getSystemCurrentTimeStamp();
            $crash["ip"] = $this->getClientIp();
            $crash["device_info"] = $this->getUserAgent();
            $this->LogAppCrashes->insertLogAppCrashes($crash);
        }

        $this->set(array(
            'response' => $input,
            '_serialize' => array('response')
        ));

    }
	 
	
	public function uploadGroupExpense() { 	 
		
		$object = $this->request->input('json_decode');
		
		if(!empty($object)){
			$data = $this->objectToArray($object);
		}		
	 
		$this->processUpload($data,false); 
		
	}

	public function addGroupExpense() {
		$object = $this->request->input('json_decode');
	
		if(!empty($object)){
			$data = $this->objectToArray($object);
		}
		$this->processUpload($data,true);
	}

	private function processUpload($data,$isTokenRequired) {
		$status = "+000";
        $status_desc = "Expense Data format is not correct!";
		$unique_url = "";
		$latestExpenseData = array();
		$archieved = false;
		$error = "";
        $expense_id = "";

		//check maintenance mood
		if(MAINTENANCE_MOOD) {
		    $status = "35";
		    $status_desc = "Service is in maintenance mood. Please try again later.";
		    $error = $status;
		} else if(empty($data)) {
			$status = "31";
			$status_desc = "Invalid JSON input sent";
		} else {


			$expenseArray = $data["Expense"];
			$ParticipantArray = $data["Participant"];

			$GroupExpenseArray = $this->setDefaultWhat($data["GroupExpense"]);

			if(isset($data["app_version"])){
				$this->app_version = $data["app_version"];
			}
		
			//echo $expenseArray["unique_url"];exit;
			if(!empty($expenseArray["unique_url"]) && $expenseArray["unique_url"] != 'null' && !empty($expenseArray["id"])){
				if(!$this->isValidExpenseUniqueURL($expenseArray["unique_url"],"1")){
					$error = "31";
				} else {
		
					$result = $this->Expense->getGroupExpenseInfoByURL($expenseArray["unique_url"]);
					if(!empty($result)){
						$error = "32";
					} else {
						$archieved = true;
					}
		
				}
			}

			//validate token
			if($isTokenRequired){
				if(!isset($data["access_token"]) || 
						!isset($data["device_id"]) || 
						!isset($data["random_number"])){

                    if(isset($data["access_token"]) &&
                        isset($data["device_id"])  ){


                            $this->loadModel('AccessKey');
                           $data['random_number'] = $this->AccessKey->getAccessToken($data["device_id"]);

                       // $data["random_number"] = get from database by device id and order by created date desc

                        if(!$this->isValidToken($data["access_token"],$data["device_id"],$data["random_number"])){
                            //echo "some";exit;
                            $error = "57"; // token is not valid
                        } else {
                            try{
                                $this->AccessKey->deleteAccessKey($data["device_id"]);
                            } catch(Exception $ex){

                            }

                        }
                    } else {
                        $error = "56"; //token is not given
                        //device id, random number, secret key =>  token
                    }
				} else if(!$this->isValidToken($data["access_token"],$data["device_id"],$data["random_number"])){
					$error = "57"; // token is not valid
				}
			}

			if($error == "") {
                $expenseArray['user_id'] = $data['user_id'];
                $expenseArray['create_user'] = $data['create_user'];
				$error = $this->validateExpense($expenseArray);
                // validate user id
                if($error == "" && (!empty($expenseArray['user_id'] || !empty($expenseArray['create_user'] )))){
                    $user = [];
                    if (!empty($expenseArray['user_id'])) {
                        $user = $this->User->getUserByUserId($expenseArray['user_id']);
                    } elseif (!empty($expenseArray['create_user'])) {
                        $user = $this->User->getUserByProfileId($expenseArray['create_user']);
                    }

                    if (empty($user) || empty($user['User'])) {
                        $error = "7";
                        $status = $error;
                        $status_desc = "User not found!";
                    }
                }
			}


		
			if($error == "") {			
				$error = $this->validateParticipant($ParticipantArray);

				if($error == "") {
					$error = $this->validateExpenseList($GroupExpenseArray,$ParticipantArray);
					if($error == ""){
						$expenseArray["participants"] = $ParticipantArray;
		
						// $expense_id = "sdfsf";
						$expenseArray["source"] = $this->getSource(new MobileDetectComponent());
						$expenseArray["ip"] = $this->getClientIp();
						$expenseArray["user_agent"] = $this->getUserAgent();
						$expenseArray["secret_key"] = $this->getSecretKey(5);

                        if(!empty($user['User'])){
                            $expenseArray['create_user'] = $user['User']['profile_id'];
                            $expenseArray['user_id'] =  $user['User']['id'];
                        }else{
                            $expenseArray['create_user'] = "system";
                            $expenseArray['user_id'] = null;
                        }

						if($this->app_version == "1") {
							$expenseArray["create_date"] = $this->getExpenseCreationDate($expenseArray["create_date"]);
						}

						$expenseIdStr = $this->Expense->createExpense($expenseArray,true,$archieved);
						if($expenseIdStr != "") {
							$expenseIdStrArr = explode(",",$expenseIdStr);
                            $imageUploadResponses = null;
							if(!empty($GroupExpenseArray)){
								foreach($GroupExpenseArray as $key=>$value) {
									$idPartsArray = explode("-",$GroupExpenseArray[$key]["id"]);
									$GroupExpenseArray[$key]["id"] = $idPartsArray[0]."-".$idPartsArray[1]."-".$expenseIdStrArr[0];
		
								}

								//start check the expense date format and decide
								if($this->app_version == "1") {
									foreach($GroupExpenseArray as $key=>$value){
										$value["expense_date_old"] = $value["expense_date"];
										$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);

                                        $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$expenseIdStrArr[1],$this->app_name);
                                        $value['images'] = $imageUploadResponse['images'];

										$GroupExpenseArray[$key] = $value;
                                        $imageUploadResponses[$key] = $imageUploadResponse['response'];
									}
								}
                                else {
		
									foreach($GroupExpenseArray as $key=>$value){
										$value["expense_date_old"] = $this->getStrToIntDate($value["expense_date"]);
                                        $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$expenseIdStrArr[1],$this->app_name);
                                        $value['images'] = $imageUploadResponse['images'];
										$GroupExpenseArray[$key] = $value;
                                        $imageUploadResponses[$key] = $imageUploadResponse['response'];
									}
		
								}

								$error = $this->GroupExpense->addMultipleGroupExpense($GroupExpenseArray,$expenseIdStrArr[0]);
							}
		
							if($error != "") {
								$status = "22";
								$status_desc = "WeXpense Data Saving Failed!";
							}
                            else {
								$latestExpenseData = $this->Expense->getGroupExpenseInfoByURL($expenseIdStrArr[1]);
                                if(!empty($user['User'])) {

                                    $this->loadModel('GroupSetting');
                                    $mode = isset($data['GroupSetting']['is_restricted_mode'])?$data['GroupSetting']['is_restricted_mode']:0;
                                    $request = [
                                        'is_restricted_mode' => $mode,
                                        'expense_id' => $latestExpenseData['Expense']['id'],
                                        'unique_url' => $expenseIdStrArr[1]
                                    ];
                                    $groupSettingData = $this->GroupSetting->saveGroupSetting($request);
                                    if(!empty($groupSettingData['GroupSetting'])) {
                                        $latestExpenseData['GroupSetting'] = [
                                            "categories" => $groupSettingData ['GroupSetting']['categories'],
                                             "version" => $groupSettingData ['GroupSetting']['version'],
                                             "is_restricted_mode" => $groupSettingData ['GroupSetting']['is_restricted_mode']
                                        ];
                                    }
                                    $permission_request = [
                                        'expense_id' => $latestExpenseData['Expense']['id'],
                                        'unique_url' => $expenseIdStrArr[1],
                                        'profile_id' => $user['User']['profile_id'],
                                        'user_id' => $user['User']['id'],
                                        "role"  => OWNER

                                    ];
                                    $PermissionTable = ClassRegistry::init('PermissionTable');
                                    $permission = $PermissionTable->addPermission($permission_request);
                                    if(!empty($permission)) {
                                       $latestExpenseData['Permissions'] =  [[
                                           'profile_id' => $user['User']['profile_id'],
                                           "role"  => OWNER
                                       ]];
                                   }

                                }
								$unique_url = $expenseIdStrArr[1];
								$expense_id = $expenseIdStrArr[0];
								if(empty($latestExpenseData)) {
									$status = "34";
									$status_desc = "Data successfully inserted but can not retrieve latest data.Please try to reload again with unique URL.";
								}
                                else {
									if($this->app_version == "1" ){
										//reset expense date for old apps
										$groupExpensesList = $latestExpenseData["GroupExpense"];
										if( !empty($groupExpensesList)){
											foreach($groupExpensesList as $key=>$value){
												$groupExpensesList[$key]["expense_date"] = $value["expense_date"];
												//$groupExpensesList[$key]["expense_date_new"] = "";
											}
											$latestExpenseData["GroupExpense"] = $groupExpensesList;
										}
									}

									//insert/update access info
									$data["id"] = $latestExpenseData["Expense"]["id"];
									$data["unique_url"] = $latestExpenseData["Expense"]["unique_url"];
									$this->insertAccessInfo($data);

									$status = "+000";
									$status_desc = "SUCCESS";
								}
							}

							// add data to user group table and update myProfileUser firebase version
							if( isset($data['user_id'])
								&& !empty($data['user_id'])
								&& isset($data['unique_url'])
								&& !empty($data['unique_url'])
							) {
								$this->addUserGroupDuringExpenseCreate(
									$data['user_id'],
									$data["unique_url"], 
									"GroupExpense");
							}
		
						}
                        else {
							$status = "22";
							$status_desc = "Expense or Participant Data Saving Failed!";
						}
							
					} else {
						$status = $error;
						$status_desc = "WeXpense Data format is not valid";
					}
		
				}
                else {
					$status = $error;
					$status_desc = "Participant Data format is not valid";
				}
					
			}
            else{
                $status = $error;
                $status_desc = $status_desc;
            }


		}
		//validate expense(exist record,valid expense id format,length etc)
		
		
		//all the participant_id in expense should be available in participant list
		
		//summation of part-amount should be equal to paid amount
		
		//insert into expense
		
		
		//	$data = $this->Expense->getGroupExpenseInfoByURL("1o30356");
		//$data = array("key1"=>"value1");
		//$input = $data;
		
		//echo "
";
		//print_r($_POST);exit;
		
//		var_dump([$status,$status_desc]);exit;
		$input["status"] = $status;
		$input["status_desc"] = $status_desc;
		$input["api_version"] = $this->api_group_version;
		$input["data"] = $latestExpenseData;
		if(!empty($error) || $status !="+000" ) {
            $input["input"] = $data;
            $this->loadModel('LogAppCrashes');
            $crash["unique_url"] = $unique_url;
            $crash["error_code"] = $status;
            $crash["error_desc"] = $status_desc;
            $crash["request"] = serialize($data);
            $crash["response"] = serialize($latestExpenseData);
            $crash["crash_date"] = $this->getSystemCurrentTimeStamp();
            $crash["ip"] = $this->getClientIp();
            $crash["device_info"] = $this->getUserAgent();
            $this->LogAppCrashes->insertLogAppCrashes($crash);
        }

	//	$input["input"] = $data;
		$input["expense_id"] = $expense_id;
		$input["unique_url"] = $unique_url;

        if(isset($imageUploadResponses) && !empty($imageUploadResponses)){
            $input['image_upload_response'] = $imageUploadResponses;
        }


		
		/* $fp = fopen("rajib.txt","w+");
		 fwrite($fp,implode("=",$input));
		 fclose($fp); */
			
		$this->set(array(
				'response' => $input,
				'_serialize' => array('response')
		));
	}
	
	
	private function getSecretKey($length = 10){
		
		$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
	    $charactersLength = strlen($characters);
	    $randomString = '';
	    for ($i = 0; $i < $length; $i++) {
	        $randomString .= $characters[rand(0, $charactersLength - 1)];
	    }
	    
		return $randomString;

	}
	
	private function isParticipantInvolveInExpense($participantId,$expenseList){
		$result = false;
		
		if(!empty($expenseList)){
			foreach($expenseList as $key=>$value){
				if(trim($value["paid_by_participant_id"]) == trim($participantId)){
					$result = true;
					break;
				}	
				
				$participantAmtArray = explode(",",$value["participant_amount"]);
				foreach($participantAmtArray as $index=>$item){
					$participantAmtDetailsArray = explode("|",$item);
					if(trim($participantAmtDetailsArray[0]) == trim($participantId)){
						$result = true;
						break 2;
					}
				}
			}			
		}
		
		return $result;
	}
	
	private function isValidGroupExpense($paidByParticipantId,$amountString,$mergedParticipantIdList){
		$result = true;
		
		if(!empty($mergedParticipantIdList)){
		 
			if(!in_array(trim($paidByParticipantId),$mergedParticipantIdList)){
				// echo "hello";
			 	$result = false;
			} else {		 	
				$participantAmtArray = explode(",",$amountString);
				foreach($participantAmtArray as $index=>$item){
					$participantAmtDetailsArray = explode("|",$item);
					if(!in_array(trim($participantAmtDetailsArray[0]),$mergedParticipantIdList) ){
						$result = false;
						break;
					}
				}		 	
			 }
		} else {
			$result = false;
		}
		
		/*echo $paidByParticipantId;
		echo "
"; print_r($mergedParticipantIdList); echo "
"; echo $result;exit;*/ return $result; } private function getReplacedValWithParticipantId($value,$mapRemoteAndWebId) { if(array_key_exists($value["paid_by_participant_id"], $mapRemoteAndWebId)){ $value["paid_by_participant_id"] = $mapRemoteAndWebId[$value["paid_by_participant_id"]]; } $amountStrArray = explode(",",$value["participant_amount"]); foreach($amountStrArray as $index=>$item){ $amountStrDetailArray = explode("|",$item); if(array_key_exists($amountStrDetailArray[0], $mapRemoteAndWebId)){ $amountStrDetailArray[0] = $mapRemoteAndWebId[$amountStrDetailArray[0]]; } $amountStrArray[$index] = implode("|",$amountStrDetailArray); } $value["participant_amount"] = implode(",",$amountStrArray); return $value; } private function setExpenseLogInfo($dbExpense,$newExpense,$participantList,$oldCurrency,$newCurrency,$indicator){ //$indicator = 1 means edited, $indicator = 2 means deleted if(!empty($participantList)){ $newExpense["previous_desc"] = $this->getGeneratedLog($dbExpense,$participantList,$oldCurrency); //take from db expense if($indicator == 1){ $newExpense["new_desc"] = $this->getGeneratedLog($newExpense,$participantList,$newCurrency); ;// take from $newExpense; } else if($indicator == 2){ $newExpense["new_desc"] = "deleted"; } $newExpense["previous_paid_by"] = $participantList[$dbExpense["paid_by_participant_id"]]["name"]; } return $newExpense; } private function getGeneratedLog($expenseObj,$participantList,$currency) { $logStr = ""; $logStr .= "[Title:".$expenseObj["what"]."],"; $logStr .= "[PaidBy:".$participantList[$expenseObj["paid_by_participant_id"]]["name"]."],"; $logStr .= "[Date:".$expenseObj["expense_date"]."],"; $logStr .= "[Amount:".$expenseObj["amount"].' '.$currency."],"; $logStr .= "[Involves:"; $participantAmtStrArray = explode(",",$expenseObj["participant_amount"]); foreach($participantAmtStrArray as $key=>$value) { $dataArray = explode("|",$value); if($key == 0){ $logStr .= $participantList[$dataArray[0]]["name"]."=".$dataArray[2]; } else { $logStr .= ",".$participantList[$dataArray[0]]["name"]."=".$dataArray[2]; } } $logStr .= "]"; return $logStr; } public function downloadExpenseCount() { $status = "+000"; $status_desc = "SUCCESS"; $expenseType = 0; $object = $this->request->input('json_decode'); if(!empty($object)){ $data = $this->objectToArray($object); } $version = ""; //check maintenance mood if(MAINTENANCE_MOOD){ $status = "35"; $status_desc = "Service is in maintenance mood. Please try again later."; $error = $status; } else if(empty($data)){ $status = "31"; $status_desc = "Invalid JSON input sent"; } else if(empty($data) || $data["unique_url"] == ""){ $status = "33"; $status_desc = "Invalid Unique URL"; } else { if(isset($data["app_version"])) { $this->app_version = $data["app_version"]; } $expenseType = substr($data["unique_url"], 0, 1); $version = $this->getVersion($expenseType); if($expenseType == "1" || $expenseType == "2" ){ $latestExpenseData = $this->Expense->getGroupExpenseInfoByURL($data["unique_url"]); if (empty($latestExpenseData)) { $this->loadModel('Backup'); $this->Backup->restore($data["unique_url"]); $latestExpenseData = $this->Expense->getGroupExpenseInfoByURL($data["unique_url"]); } $owner = false; if(!empty($latestExpenseData['Expense']) && !empty($data['user_id'])){ $user = $this->User->getUserByUserId($data['user_id']); if(!empty($user['User'])){ $owner = ($latestExpenseData['Expense']['user_id'] == $user['User']['id']) || ($latestExpenseData['Expense']['create_user'] == $user['User']['profile_id']); } } if(!$owner) { $permission = $this->Permission->PermissionByUserId($data["unique_url"], $data['user_id']); if ($permission == NO_PERMIT) { $this->set(array( 'response' => ['status' => $this->permission_status, 'status_desc' => "You are not authorized to this page.Please Provide valid user id."], '_serialize' => array('response') )); return; } } $this->loadModel('GroupSetting'); $groupSettingData = $this->GroupSetting->getGroupSettingByURL($data["unique_url"],true); if(!empty($groupSettingData)){ $latestExpenseData['groupsettings'] = $groupSettingData; } $this->loadModel('PermissionTable'); $permissionlist = []; $permissions = $this->PermissionTable->getPermissionByUrl($data["unique_url"],true); $addPermissions = array_column($permissions, 'profile_id'); // get owner/creator info if(!empty($latestExpenseData['Expense']['user_id'])) { $user = $this->User->getUserByUserId($latestExpenseData['Expense']['user_id']); }else{ $user = $this->User->getUserByProfileId($latestExpenseData['Expense']['create_user']); } if (!in_array($user['User']['profile_id'], $addPermissions)) { $permissionlist[] = ['profile_id' => $user['User']['profile_id'], 'role' => OWNER]; } if(!empty($permissions || !empty($permissionlist))){ $permissionlist = array_merge($permissionlist ?? [], $permissions); $latestExpenseData['Permissions'] = $permissionlist; } //reset expense date for old apps $groupExpensesList = $latestExpenseData["GroupExpense"]; if($this->app_version == "1" && !empty($groupExpensesList)){ foreach($groupExpensesList as $key=>$value){ $groupExpensesList[$key]["expense_date"] = $value["expense_date"]; //$groupExpensesList[$key]["expense_date_new"] = ""; } $latestExpenseData["GroupExpense"] = $groupExpensesList; } } else if($expenseType == "6" || $expenseType == "7"){ $demoResult = $this->DemoExpense->getDemoGroupExpenseInfoByURL($data["unique_url"]); $latestExpenseData["Expense"] = $demoResult["DemoExpense"]; $latestExpenseData["Participant"] = $demoResult["DemoParticipant"]; $latestExpenseData["GroupExpense"] = $demoResult["DemoGroupExpense"]; //reset expense date for old apps $groupExpensesList = $latestExpenseData["GroupExpense"]; if($this->app_version == "1" && !empty($groupExpensesList)){ foreach($groupExpensesList as $key=>$value){ $groupExpensesList[$key]["expense_date"] = $value["expense_date"]; //$groupExpensesList[$key]["expense_date_new"] = ""; } $latestExpenseData["GroupExpense"] = $groupExpensesList; } if($expenseType == "7"){ $latestExpenseData["Meal"] = $demoResult["DemoMeal"]; //reset expense date for old apps $mealList = $latestExpenseData["Meal"]; if($this->app_version == "1" && !empty($mealList)){ foreach($mealList as $key=>$value){ $mealList[$key]["date"] = $value["date"]; //$mealList[$key]["date_new"] = ""; } $latestExpenseData["Meal"] = $mealList; } } } else if($expenseType == "3" ){ $latestExpenseData = $this->Expense->getFamilyExpenseInfoByURL($data["unique_url"]); if (empty($latestExpenseData)) { $this->loadModel('Backup'); $this->Backup->restore($data["unique_url"]); $latestExpenseData = $this->Expense->getFamilyExpenseInfoByURL($data["unique_url"]); } $owner = false; if(!empty($latestExpenseData['Expense']) && !empty($data['user_id'])){ $user = $this->User->getUserByUserId($data['user_id']); if(!empty($user['User'])){ $owner = ($latestExpenseData['Expense']['user_id'] == $user['User']['id']) || ($latestExpenseData['Expense']['create_user'] == $user['User']['profile_id']); } } if(!$owner) { $permission = $this->Permission->PermissionByUserId($data["unique_url"], $data['user_id']); if ($permission == NO_PERMIT) { $this->set(array( 'response' => ['status' => $this->permission_status, 'status_desc' => "You are not authorized to this page.Please Provide valid user id."], '_serialize' => array('response') )); return; } } //reset expense date for old apps $familyExpensesList = $latestExpenseData["FamilyExpense"]; if($this->app_version == "1" && !empty($familyExpensesList)){ foreach($familyExpensesList as $key=>$value){ $familyExpensesList[$key]["expense_date"] = $value["expense_date"]; //$familyExpensesList[$key]["expense_date_new"] = ""; } $latestExpenseData["FamilyExpense"] = $familyExpensesList; } $this->loadModel('GroupSetting'); $groupSettingData = $this->GroupSetting->getGroupSettingByURL($data["unique_url"],true); if(!empty($groupSettingData)){ $latestExpenseData['groupsettings'] = $groupSettingData; } $this->loadModel('PermissionTable'); $permissionlist = []; $permissions = $this->PermissionTable->getPermissionByUrl($data["unique_url"],true); $addPermissions = array_column($permissions, 'profile_id'); // get owner/creator info if(!empty($latestExpenseData['Expense']['user_id'])) { $user = $this->User->getUserByUserId($latestExpenseData['Expense']['user_id']); }else{ $user = $this->User->getUserByProfileId($latestExpenseData['Expense']['create_user']); } if (!in_array($user['User']['profile_id'], $addPermissions)) { $permissionlist[] = ['profile_id' => $user['User']['profile_id'], 'role' => OWNER]; } if(!empty($permissions || !empty($permissionlist))){ $permissionlist = array_merge($permissionlist ?? [], $permissions); $latestExpenseData['Permissions'] = $permissionlist; } } else if($expenseType == "8"){ $demoResult = $this->DemoExpense->getDemoFamilyExpenseInfoByURL($data["unique_url"]); $latestExpenseData["Expense"] = $demoResult["DemoExpense"]; $latestExpenseData["FamilyExpense"] = $demoResult["DemoFamilyExpense"]; } if(empty($latestExpenseData)){ $status = "32"; $status_desc = "Data not exist for the given unique URL"; } else { //insert/update access info $data["id"] = $latestExpenseData["Expense"]["id"]; $data["unique_url"] = $latestExpenseData["Expense"]["unique_url"]; $this->insertAccessInfo($data); } } $input["status"] = $status; $input["status_desc"] = $status_desc; $input["api_version"] = $version; if( $status =="+000" ) { //add user group if user_id exist in request // add data to user group table and update myProfileUser firebase version if( isset($data['user_id']) && !empty($data['user_id']) && isset($data['unique_url']) && !empty($data['unique_url']) && ($expenseType == "1" || $expenseType == "2" || $expenseType == "3")) { $appType = "GroupExpense"; if($expenseType == "2") { $appType = "MessExpense"; } else if ($expenseType == "3") { $appType = "FamilyExpense"; } $this->addUserGroupDuringExpenseCreate( $data['user_id'], $data["unique_url"], $appType); } } else { $input["input"] = $data; $this->loadModel('LogAppCrashes'); $crash["unique_url"] = $data["unique_url"]; $crash["error_code"] = $status; $crash["error_desc"] = $status_desc; $crash["request"] = serialize($data); $crash["response"] = serialize($latestExpenseData); $crash["crash_date"] = $this->getSystemCurrentTimeStamp(); $crash["ip"] = $this->getClientIp(); $crash["device_info"] = $this->getUserAgent(); $crash["expense_type"] = $expenseType; $this->LogAppCrashes->insertLogAppCrashes($crash); } //$input["input"] = $data; $input["data"] = $latestExpenseData; $this->set(array( 'response' => $input, '_serialize' => array('response') )); } private function getVersion($expense_type){ if($expense_type == "1" || $expense_type == "6"){ return $this->api_group_version; } else if($expense_type == "2" || $expense_type == "7"){ return $this->api_mess_version; } else if($expense_type == "3" || $expense_type == "8"){ return $this->api_family_version; } return ""; } //Rules of Synchronization: /*#EditExpense * * 1. Web and remote application version should be same * 2. Expense related data should be modified then only it will update web Database.If nothing has been * changed in remoate applicaiton, the value should be empty.(optional) * * * * #AddGroupExpenseList = * 1. The participants who are involved in a particular group expense should be available * in merged participant list(merge between web and remote participant list). * * * #EditGroupExpenseList * 1. The record should be available in web database. * 2. Web and remote application version should be same for a particular record. = * 3. The participant who are involved in the record, should be available in merged * participant list(merge between web and remote participant list). * * * * * * #DeleteGroupExpenseList * 1. The record should be available in web database * 2. Web and remote application version should be same for a particular record. * * * * * #AddParticipantList * 1. The name of the participant can not be duplicat in web database * * * * * #EditParticipantList * 1. The record should be available in web database * 2. Web and remote application version should be same for a particular record. * 3. The name of the participant can not be duplicat in web database * 4. The name of the participant can not be available in give AddParticipantList(optional) * * * #DeleteParticipantList * 1. The record should be available in web database. * 2. Web and remote application version should be same for a particular record. * 3. The participant who created the account, can not be deleted. * 4. The participant can not be exist in any web group expense as well as given add and edit group expense list( after as well as,not mendatory) * * * * * * * * * * * */ public function synGroupExpense() { //actions // new participant should be Shimul,Masbha;id should be 221 and 222 // The name "Ashraf" will be modified to Somen // The participants soup should be deleted $status = "+000"; $status_desc = "SUCCESS"; $error = ""; $latestExpenseData = array(); $conflictArray = array(); $object = $this->request->input('json_decode'); if(!empty($object)){ $data = $this->objectToArray($object); } //check maintenance mood if(MAINTENANCE_MOOD){ $status = "35"; $status_desc = "Service is in maintenance mood. Please try again later."; $error = $status; } else if(empty($data)){ $status = "31"; $status_desc = "Invalid JSON input sent"; } else if(empty($data["unique_url"]) || $data["unique_url"] == ""){ $status = "33"; $status_desc = "Invalid Unique URL"; }else if(isset($data["api_version"]) && !empty($data["api_version"]) && $this->isForceUpgradeRequire($data["api_version"], $this->api_group_version)) { $status = $this->force_upgrade_status; $status_desc = "Client require force upgrade!"; } else { $result = $this->Expense->getGroupExpenseInfoByURL($data["unique_url"]); $owner = false; if(!empty($data['user_id'])){ $user = $this->User->getUserByUserId($data['user_id']); if(!empty($user['User'])){ $owner = ($result['Expense']['user_id'] == $user['User']['id']) || ($result['Expense']['create_user'] == $user['User']['profile_id']); } } if(!$owner) { $permission = $this->Permission->PermissionByUserId($data["unique_url"], $data['user_id']); if ($permission == NO_PERMIT) { $this->set(array( 'response' => ['status' => $this->permission_status, 'status_desc' => "You are not authorized to this page.Please Provide valid user id."], '_serialize' => array('response') )); return; } } //check backup or archive data if(empty($result)){ $this->loadModel('Backup'); $this->Backup->restore($data["unique_url"]); $result = $this->Expense->getGroupExpenseInfoByURL($data["unique_url"]); } if(empty($result)){ $status = "32"; $status_desc = "Data not exist for the given unique URL"; } else { //Conflict Array $conflictArray["Expense"] = NULL; $conflictArray["addParticipant"] = NULL; $conflictArray["modifyParticipant"] = NULL; $conflictArray["deleteParticipant"] = NULL; $conflictArray["addGroupExpense"] = NULL; $conflictArray["modifyGroupExpense"] = NULL; $conflictArray["deleteGroupExpense"] = NULL; //get DB information $dbExpense = $result["Expense"]; $dbGroupExpenseList = $result["GroupExpense"]; $dbParticipantList = $result["Participant"]; //set data $currency = $dbExpense["currency"]; //get user's input $expenseArray = array(); if(isset($data["Expense"]) && !empty($data["Expense"])){ $expenseArray = $data["Expense"]; } $addParticipantArray = array(); $modifyParticipantArray = array(); $deleteParticipantArray = array(); $addGroupExpenseArray = array(); $modifyGroupExpenseArray = array(); $deleteGroupExpenseArray = array(); if (isset($data["addParticipant"]) && !empty($data["addParticipant"])) { $addParticipantArray = $data["addParticipant"]; } if (isset($data["modifyParticipant"]) && !empty($data["modifyParticipant"])) { $modifyParticipantArray = $data["modifyParticipant"]; } if (isset($data["deleteParticipant"]) && !empty($data["deleteParticipant"])) { $deleteParticipantArray = $data["deleteParticipant"]; } if (isset($data["addGroupExpense"]) && !empty($data["addGroupExpense"])) { $addGroupExpenseArray = $this->setDefaultWhat($data["addGroupExpense"]); } if (isset($data["modifyGroupExpense"]) && !empty($data["modifyGroupExpense"])) { $modifyGroupExpenseArray = $this->setDefaultWhat($data["modifyGroupExpense"]); } if (isset($data["deleteGroupExpense"]) && !empty($data["deleteGroupExpense"])) { $deleteGroupExpenseArray = $this->setDefaultWhat($data["deleteGroupExpense"]); } $mergedParticipantIdList= array(); $mergedParticipantNameList = array(); if(isset($data["app_version"])){ $this->app_version = $data["app_version"]; } //Filter expense if(!empty($expenseArray) && $expenseArray["version"] < $dbExpense["version"] ){ $conflictArray["Expense"] = $expenseArray; $expenseArray = NULL; } else if(!empty($expenseArray) ){ $expenseArray["version"] = $expenseArray["version"]+1; $currency = $expenseArray["currency"]; if($expenseArray["version"] > 999){ $expenseArray["version"] = 1; } } //make assosiative array for group expense /* $dbGroupExpenseList = $result["GroupExpense"]; $dbParticipantList = $result["Participant"]; */ //set assosiative participant //Filter participant List if(!empty($dbParticipantList)){ foreach($dbParticipantList as $key=>$value){ $dbAsParticipantList[$value["participant_id"]] = $value; $dbParticipantNameList[$key] = $value["name"]; array_push($mergedParticipantIdList,trim($value["participant_id"])); array_push($mergedParticipantNameList,trim($value["name"])); } //reset delete participant list if(!empty($deleteParticipantArray)){ if(empty($dbAsParticipantList)){ $deleteParticipantArrayFinal = $deleteParticipantArray; } else{ $i = 0; foreach($deleteParticipantArray as $key=>$value){ if(array_key_exists($value["participant_id"],$dbAsParticipantList) && $value["version"] == $dbAsParticipantList[$value["participant_id"]]["version"] && $value["is_creator"] != "1"){ //For delete,check the participant id has entry in db expense list,or given expense lsit //if exist,remove it from delete list if(!$this->isParticipantInvolveInExpense($value["participant_id"],$dbGroupExpenseList)){ $deleteParticipantArrayFinal[$i++] = $value;// Final ready if (($key = array_search(trim($value["participant_id"]), $mergedParticipantIdList)) !== false) { $mergedParticipantIdList = array_diff($mergedParticipantIdList, array($value["participant_id"])); $mergedParticipantNameList = array_diff($mergedParticipantNameList, array($value["name"])); } } } else { $conflictArray["deleteParticipant"][] = $value["participant_id"]; } } } } //echo "
";
					//print_r($mergedParticipantNameList);exit;
						
					//reset edit participant list
					if(!empty($modifyParticipantArray) && !empty($dbAsParticipantList)){
						$i = 0;
						foreach($modifyParticipantArray as $key=>$value){
							if(array_key_exists($value["participant_id"],$dbAsParticipantList)
							&& $value["version"] == $dbAsParticipantList[$value["participant_id"]]["version"]
							&& !in_array($value["name"],$mergedParticipantNameList)){
								//For edit, check any participant already exist id DB or not which is mentioned in edit
								//if exist, just ignor the participant,otherwise edit it
				
								$modifyParticipantArrayFinal[$i++] = $value; // Final ready
							} else {
								$conflictArray["modifyParticipant"][] = $value["participant_id"];
							}
						}
							
					}
						
				} else {
					//if there are not data in database then just assign final
					$modifyParticipantArrayFinal = NULL;
					$deleteParticipantArrayFinal = NULL;
				}   
				
				//Filter Group Expense List
				if(!empty($dbGroupExpenseList)){
					
					foreach($dbGroupExpenseList as $key=>$value){
						$dbAsGroupExpenseList[$value["id"]] = $value;
					}
					
					//reset edit group expense list
					if(!empty($modifyGroupExpenseArray)){
						if(empty($dbAsGroupExpenseList)){
							$modifyGroupExpenseArrayFinal = $modifyGroupExpenseArray;
						} else{
							$i = 0;
							
							//prepare log participant list to show modified participant name in logs
							if(!empty($dbAsParticipantList)){
								foreach($dbAsParticipantList as $key=>$value){
									$logParticipantList[$key] = $value;
								}
							}
							if(!empty($modifyParticipantArrayFinal)){
								foreach($modifyParticipantArrayFinal as $key=>$value){
									$logParticipantList[$value["participant_id"]] = $value;
								}
							}
							
							if(!empty($addParticipantArray)){
								foreach($addParticipantArray as $key=>$value){
									$logParticipantList[$value["participant_id"]] = $value;
								}
							}
							
							
							
							//set logs for modify						
							foreach($modifyGroupExpenseArray as $key=>$value){
								 if(array_key_exists($value["id"],$dbAsGroupExpenseList) 
								 	&& $value["version"] == $dbAsGroupExpenseList[$value["id"]]["version"]){
								 		
								 	$value = $this->setExpenseLogInfo($dbAsGroupExpenseList[$value["id"]],$value,$logParticipantList,$dbExpense["currency"],$currency,1);	
								 		
								 	$modifyGroupExpenseArrayFinal[$value["id"]] = $value; // Final ready
								 } else {
								 	
								 	$conflictArray["modifyGroupExpense"][] = $modifyGroupExpenseArray[$key]["id"];
								 }
							}
						}
					}


					//reset delete group expense list					
					if(!empty($deleteGroupExpenseArray)){
						if(empty($dbAsGroupExpenseList)){
							$deleteGroupExpenseArrayFinal = $deleteGroupExpenseArray;
						}
                        else{
							$i = 0;
							foreach($deleteGroupExpenseArray as $key=>$value){
								 if(array_key_exists($value["id"],$dbAsGroupExpenseList) 
								 && $value["version"] == $dbAsGroupExpenseList[$value["id"]]["version"]){
								 	$value = $this->setExpenseLogInfo($dbAsGroupExpenseList[$value["id"]],$value,$dbAsParticipantList,$dbExpense["currency"],$currency,2);
								 	$deleteGroupExpenseArrayFinal[$i++] = $value;// Final ready
								 } else {
								 	$conflictArray["deleteGroupExpense"][] = $value["id"];
								 	
								 }
							}
						}
					}

				} else {
					//if there are not data in database then just assign final
					$modifyGroupExpenseArrayFinal = NULL;
					$deleteGroupExpenseArrayFinal = NULL;
				}
				

				//For add participant,check any item exist in dbParticipant or not
				 
				if(!empty($addParticipantArray)){ 					
					foreach($addParticipantArray as $key=>$value){
						if(!in_array($value["name"],$dbParticipantNameList)){
					 		$addParticipantArrayFinal[] = $value;
					 		array_push($mergedParticipantIdList,trim($value["participant_id"]));	
					 		 
					 	} else {
					 		$conflictArray["addParticipant"][] = $value["participant_id"];
					 	}
					}
				}
				 
 				
				//Filter add group expense final list with merged participant list				
				if(!empty($addGroupExpenseArray)){
					foreach($addGroupExpenseArray as $key=>$value){
						if($this->isValidGroupExpense($value["paid_by_participant_id"],$value["participant_amount"],$mergedParticipantIdList)){
							
							//check if the expense already has been added
							$idArray = explode("-",$value["id"]);
							if(count($idArray) == 4){
								$uniqueDeviceExpenseID = $idArray[3];
								if(!$this->isItemAlreadyAdded($dbAsGroupExpenseList,$uniqueDeviceExpenseID) ){
									$value["syn_add_unique_id"] = $uniqueDeviceExpenseID;
									$addGroupExpenseArrayFinal[] = $value;
								}
								 
							} else {
								$addGroupExpenseArrayFinal[] = $value;
							}
							
							
							
						} else {
							$conflictArray["addGroupExpense"][] = $value["id"];
						}
					}
				}
				
				
				//Filter edit group expense final list with merged participant list	
				if(!empty($modifyGroupExpenseArrayFinal)){
					foreach($modifyGroupExpenseArrayFinal as $key=>$value){
						if($this->isValidGroupExpense($value["paid_by_participant_id"],$value["participant_amount"],$mergedParticipantIdList)){
							$modifyGroupExpenseArraySuperFinal[] = $value;
						} else {
							$conflictArray["modifyGroupExpense"][] = $value["id"];
						}
					}
				}


				//generate and replace participant id
				if(!empty($addParticipantArrayFinal)){
					
					$maxParticipant = 0;
					$mapRemoteAndWebId = array();
					//get max id
					foreach($dbParticipantList as $key=>$value){
						$ParticipantIdArray = explode("_",$value["participant_id"]);
						if(trim($ParticipantIdArray[0]) > $maxParticipant){
							$maxParticipant = trim($ParticipantIdArray[0]);
						}
					}
					
					//generate map
					for($i=0;$i$item){
							 
							if(trim($item) == trim($addParticipantArrayFinal[$i]["participant_id"])){
								 
								$mergedParticipantIdList[$si] = $maxParticipant."_0";
								//list($addGroupExpenseArrayFinal, $modifyGroupExpenseArraySuperFinal)
								break;
							}
						}
						
						$addParticipantArrayFinal[$i]["participant_id"] = $maxParticipant."_0";
					}
					 
					
				}
				
 					
					//replace all add expense and edit expense with the generated IDs
					if(!empty($addGroupExpenseArrayFinal)){
						$maxGroupSerialNo = 0;
						
						for($i=0;$igetReplacedValWithParticipantId($value,$mapRemoteAndWebId);
						    if($i == 0){
						    	$firstPaidByParticipantId = $addGroupExpenseArrayFinal[0]["paid_by_participant_id"];
						    	
						    }
						
						    $participantIdArray = explode("-",$addGroupExpenseArrayFinal[$i]["id"]);
					    	if($participantIdArray[0] == $firstPaidByParticipantId){
					    		if($maxGroupSerialNo < intval($participantIdArray[1])){
					    			$maxGroupSerialNo = intval($participantIdArray[1]);
					    		}
					    	}
						}
						
						
					}

					
					if(!empty($modifyGroupExpenseArraySuperFinal)){
						
						foreach($modifyGroupExpenseArraySuperFinal as $key=>$value){							
							//$value = $modifyGroupExpenseArraySuperFinal[$i];
							$modifyGroupExpenseArraySuperFinal[$key] = $this->getReplacedValWithParticipantId($value,$mapRemoteAndWebId);
						
						}
					}
					
					
					
					//Reset add group expense Id with the genered ID
					if(!empty($addGroupExpenseArrayFinal)){			
						
						if(!empty($dbGroupExpenseList)){
							foreach($dbGroupExpenseList as $key=>$value){
								$value_array = explode("-",$value["id"]);
								
								$current_user_array = explode("-",$addGroupExpenseArrayFinal[0]["id"]);
								
								if($maxGroupSerialNo < intval($value_array[1]) && $current_user_array[0] == $value_array[0]){
									$maxGroupSerialNo = intval($value_array[1]);
								}
							}
						}
						
						
						for($i=0;$ivalidateExpense($expenseArray);
		}
		
		 //check add,edit,delete participant list
		 if($error == ""){

		 	if(!empty($addParticipantArrayFinal)){
		 		$error = $this->validateParticipant($addParticipantArrayFinal);
		 	}
		 	
		 	if($error == "" && !empty($modifyParticipantArrayFinal)){
		 		$error = $this->validateParticipant($modifyParticipantArrayFinal);
		 	}
		 	
		 	if($error == "" && !empty($deleteParticipantArrayFinal)){
		 		$error = $this->validateDeleteParticipant($deleteParticipantArrayFinal);
		 	}

		 	if($error == ""){
		 		//set merged participant object
		 		foreach($mergedParticipantIdList as $key=>$value){
		 			$participantObjList[$key]["id"] = $value;
		 			$participantObjList[$key]["participant_id"] = $value;
		 			
		 		}
		 		
		 		//check add,edit and delete expense list
                if(!empty($addGroupExpenseArrayFinal)){
		 			$error = $this->validateExpenseList($addGroupExpenseArrayFinal,$participantObjList);
		 		 }
		 		if($error == "" && !empty($modifyGroupExpenseArraySuperFinal)){
		 			//Set logs for the modify expense activity
		 			
		 			$error = $this->validateExpenseList($modifyGroupExpenseArraySuperFinal,$participantObjList);
		 		}
		 		if($error == "" && !empty($deleteGroupExpenseArrayFinal)){
		 			//set logs for expense delete activity
		 			$error = $this->validateExpenseList($deleteGroupExpenseArrayFinal,$participantObjList,true);
		 		}

//		 		echo "
";
//		 		print_r($deleteParticipantArrayFinal);exit;
		 		if($error == ""){
		 			//start from here!
		 			if(!empty($expenseArray)){
		 				$expenseArray["participants"] = $addParticipantArrayFinal;
		 				$expenseArray["source"] = $this->getSource(new MobileDetectComponent());
                        if($permission != VIEW_PERMIT){
                            $response = $this->Expense->modifyExpense($expenseArray);
                        }
		 			}

		 			if(empty($response)){
		 				//$dbExpense
		 				
		 				//add multiple participants
		 			
		 				if(!empty($addParticipantArrayFinal) && $permission != VIEW_PERMIT){
		 					$error = $this->Participant->addMultipleParticipant($addParticipantArrayFinal,$dbExpense["id"]);
		 				}
		 				
		 				
		 				//edit multiple participants
		 				if($error == "" && !empty($modifyParticipantArrayFinal) && $permission != VIEW_PERMIT){
		 					$error = $this->Participant->modifyMultipleParticipant($modifyParticipantArrayFinal);
		 				}

		 				//add group expense
		 				if($error == "" &&  !empty($addGroupExpenseArrayFinal) && $permission != VIEW_PERMIT){

                             $imageUploadResponses = null;
		 					//start check the expense date format and decide
		 					 
		 					if($this->app_version == "1"){	
		 						foreach($addGroupExpenseArrayFinal as $key=>$value){
		 							$value["expense_date_old"] = $value["expense_date"];
		 							$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);
                                    $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$data['unique_url'],$this->app_name);
                                    $value['images'] = $imageUploadResponse['images'];
		 							$addGroupExpenseArrayFinal[$key] = $value;
                                    $imageUploadResponses[$key] =  $imageUploadResponse['response'];
		 						}
		 					}
                            else {
		 						foreach($addGroupExpenseArrayFinal as $key=>$value){

		 							if(!$this->isValidNewExpenseDate($value["expense_date"])){ //remove later
		 								
		 								$tmpArray = explode("-",$value["expense_date"]);
		 								if(count($tmpArray) == "1"){		 								
		 									$value["expense_date_old"] = $value["expense_date"];
		 									$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);
		 								}
                                        else {
		 									$error = "22";
		 									break;
		 								}		 								 
		 							}
                                    else {
		 								$value["expense_date_old"] = $this->getStrToIntDate($value["expense_date"]);
		 							}

                                    $imageUploadResponse = $this->ImageUpload->AddImageBucket($value['addImages'],$value['id'],$data['unique_url'],$this->app_name);
                                    $value['images'] = $imageUploadResponse['images'];
		 							$addGroupExpenseArrayFinal[$key] = $value;
                                    $imageUploadResponses[$key] =  $imageUploadResponse['response'];
		 						}

		 					}

		 					if(empty($error))
		 					$error = $this->GroupExpense->addMultipleGroupExpense($addGroupExpenseArrayFinal,$dbExpense["id"]);
		 				}


		 				//edit group expense
		 				if($error == "" &&  !empty($modifyGroupExpenseArraySuperFinal) && $permission != VIEW_PERMIT){
		 					//start check the expense date format and decide		 					 
		 					if($this->app_version == "1"){	
		 						foreach($modifyGroupExpenseArraySuperFinal as $key=>$value){
		 							$value["expense_date_old"] = $value["expense_date"];
		 							$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);
                                    $modifyGroupExpenseArraySuperFinal[$key] = $value;
		 						}
		 					} else {
		 						foreach($modifyGroupExpenseArraySuperFinal as $key=>$value){

		 							if(!$this->isValidNewExpenseDate($value["expense_date"])){ //remove later
		 									
		 								$tmpArray = explode("-",$value["expense_date"]);
		 								if(count($tmpArray) == "1"){
		 									$value["expense_date_old"] = $value["expense_date"];
		 									$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);
		 								} else {
		 									$error = "22";
		 									break;
		 								}
		 							} else {
		 								$value["expense_date_old"] = $this->getStrToIntDate($value["expense_date"]);
		 							}

                                    $dbimages = $this->GroupExpense->getImagesById($value['id']);

                                    $deleted_image_response = $this->ImageUpload->DeleteSingleImageBucket($dbimages['GroupExpense']['images'],$value['id'],$data["unique_url"],$this->app_name,$value['deleteImages']);

                                    $upload_image_response = $this->ImageUpload->ModifyImageBucket($deleted_image_response['images'],$value['id'],$data["unique_url"],$this->app_name,$value['addImages']);

                                    $value['images'] =  $upload_image_response['images'];

                                    $modifyGroupExpenseArraySuperFinal[$key] = $value;

                                    if(!empty($upload_image_response['response']['message'])){
                                        $conflictArray["modifyGroupExpense"][$value['id']][] = $upload_image_response['response']['message'];
                                    }
		 						}
		 					}
		 					
		 					if(empty($error))
		 					$error = $this->GroupExpense->modifyMultipleGroupExpense($modifyGroupExpenseArraySuperFinal,$dbExpense["id"]);
		 				}

		 				//delete group expense
		 				if($error == "" &&  !empty($deleteGroupExpenseArrayFinal) && $permission != VIEW_PERMIT){

		 					$error = $this->GroupExpense->deleteMultipleGroupExpense($deleteGroupExpenseArrayFinal,$dbExpense["id"]);

                            if(empty($error)) {
                                 $imageDeleteResponse = $this->ImageUpload->DeleteImageBucket($deleteGroupExpenseArrayFinal, $data['unique_url'],$this->app_name);
                             }

		 				}
		 					
		 				//delete multiple participant
		 				if($error == "" &&  !empty($deleteParticipantArrayFinal) && $permission != VIEW_PERMIT){
		 					$error = $this->Participant->deleteMultipleParticipant($deleteParticipantArrayFinal);
		 				}
		 				
		 				 

		 				if($error != ""){
		 					$status = "22";
		 					$status_desc = "Participant or expense Update fails";
		 				}
                        else {
		 					$latestExpenseData = $this->Expense->getGroupExpenseInfoByURL($dbExpense["unique_url"]);
                            if (!empty($latestExpenseData['Expense'])) {
                                $latestExpenseData['Expense']['version'] = $latestExpenseData['Expense']['version'] + 1;
                                $this->Expense->save($latestExpenseData);
                            }

                            $this->loadModel('GroupSetting');
                            $groupSettingData = $this->GroupSetting->getGroupSettingByURL($dbExpense["unique_url"],true);
                            if(!empty($groupSettingData)){
                                $latestExpenseData['groupsettings'] = $groupSettingData;
                            }

                            $this->loadModel('PermissionTable');
                            $permissions = $this->PermissionTable->getPermissionByUrl($dbExpense["unique_url"]);

                            if(!empty($groupSettingData) && $groupSettingData['is_restricted_mode'] == 1){
                                $permitted_users = $permissions;
                            }else{
                                $userGroup = ClassRegistry::init('UserGroup');
                                $user_groups = $userGroup->find('all', [
                                    'conditions' => [
                                        'UserGroup.unique_url' => $dbExpense["unique_url"]
                                    ],
                                    'fields' => ['UserGroup.user_id']
                                ]);
                                $permitted_users = array_map(function ($item) {
                                    return [
                                        'user_id' => $item['UserGroup']['user_id']
                                    ];
                                }, $user_groups);
                            }

                            $permissions = array_map(function ($permission) {
                                unset($permission['user_id']);
                                return $permission;
                            }, $permissions);
                            $addPermissions = array_column($permissions, 'profile_id');
                            if (!in_array($latestExpenseData['Expense']['create_user'], $addPermissions)) {
                                $permissionlist[] =  ['profile_id'=>$latestExpenseData['Expense']['create_user'],'role'=>OWNER];
                            }

                            if(!empty($permissions || !empty($permissionlist))){
                                $permissionlist = array_merge($permissionlist ?? [], $permissions);
                                $latestExpenseData['Permissions'] = $permissionlist;
                            }

		 					if(empty($latestExpenseData)){
		 						$status = "25";
		 						$status_desc = "Expense  Data Updated but data fetching failed!";
		 					}
                            else {
		 						$status = "+000";
		 						$status_desc = "SUCCESS";
		 						
		 						//insert/update access info
		 						$data["id"] = $latestExpenseData["Expense"]["id"];
		 						$data["unique_url"] = $latestExpenseData["Expense"]["unique_url"];
		 						$this->insertAccessInfo($data);
		 						
		 						//reset expense date for old apps
		 						$groupExpensesList = $latestExpenseData["GroupExpense"];
		 						if($this->app_version == "1" && !empty($groupExpensesList)){
		 							foreach($groupExpensesList as $key=>$value){
		 								$groupExpensesList[$key]["expense_date"] = $value["expense_date"];
		 								//$groupExpensesList[$key]["expense_date_new"] = "";
		 							}
		 							$latestExpenseData["GroupExpense"] = $groupExpensesList;
		 						}
		 					}
		 					
		 				}
		 				
		 			}
                    else {
		 				$status = "22";
		 				$status_desc = "Expense Data Update Failed!";
		 			}		 			 
		 			
		 		}
                else {
		 			$status = $error;
		 			$status_desc = "Data format is not valid";
		 		}
		 		
		 	}
            else {
		 		$status = $error;
		 		$status_desc = "Participant Data format is not valid";
		 	}
		 	
		 } else {
		 	$status = $error;
		 	$status_desc = "Expense Data format is not valid";
		 }
		 
		 
	}

    if($status == $this->force_upgrade_status) {
        $status = "+000"; // return succees without execution
    }

	$input["status"] = $status;
	$input["status_desc"] = $status_desc;
	$input["api_version"] = $this->api_group_version;
	
	if(!empty($error) || $status !="+000") {
		$input["input"] = $data;

		$this->loadModel('LogAppCrashes');
		$crash["unique_url"] = $data["unique_url"];
		$crash["error_code"] = $status;
		$crash["error_desc"] = $status_desc;
		$crash["request"] = serialize($data);
		$crash["response"] = serialize($latestExpenseData);
		$crash["crash_date"] = $this->getSystemCurrentTimeStamp();
		$crash["ip"] = $this->getClientIp();
		$crash["device_info"] = $this->getUserAgent();
		$crash["expense_type"] = 1;
		$this->LogAppCrashes->insertLogAppCrashes($crash);
	}

    if($permission == VIEW_PERMIT && !empty($data['Expense'])){
        $permission_conflict["Expense"] = $data['Expense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['addGroupExpense'])){
        $permission_conflict["addGroupExpense"] = $data['addGroupExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['modifyGroupExpense'])){
        $permission_conflict["modifyGroupExpense"] = $data['modifyGroupExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['deleteGroupExpense'])){
        $permission_conflict["deleteGroupExpense"] = $data['deleteGroupExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['addParticipant'])){
        $permission_conflict["addParticipant"] = $data['addParticipant'];
    }
    if($permission == VIEW_PERMIT && !empty($data['modifyParticipant'])){
        $permission_conflict["modifyParticipant"] = $data['modifyParticipant'];
    }
    if($permission == VIEW_PERMIT && !empty($data['deleteParticipant'])){
        $permission_conflict["deleteParticipant"] = $data['deleteParticipant'];
    }
	$input["data"] = $latestExpenseData;
	$input["conflict"] = $conflictArray;
    if($permission == VIEW_PERMIT){
      $input["permission_conflict"] = $permission_conflict;
    }

    if(isset($imageDeleteResponse) && !empty(array_filter($imageDeleteResponse))) {
        $input["remove_image_response"] = $imageDeleteResponse;
    }
    if(isset($imageUploadResponses) && !empty(array_filter($imageUploadResponses))) {
        $input["upload_image_response"] = $imageUploadResponses;
    }
    if(isset($upload_image_response['response'])&& !empty($upload_image_response['response'])){
        $input['modify_group_expense']['add_images'] = $upload_image_response['response'];
    }
    if(isset($deleted_image_response['response']) && !empty($deleted_image_response['response'])){
        $input['modify_group_expense']['delete_images'] = $deleted_image_response['response'];
    }

     $conflict = (!empty($permitted_users) && empty($conflictArray['Expense'])
        && empty($conflictArray['addParticipant'])
        && empty($conflictArray['modifyParticipant'])
        && empty($conflictArray['deleteParticipant'])
        && empty($conflictArray['addGroupExpense'])
        && empty($conflictArray['modifyGroupExpense'])
        && empty($conflictArray['deleteGroupExpense']));
     $expense_validate =  (!empty($addGroupExpenseArray) || !empty($modifyGroupExpenseArray)|| !empty($deleteGroupExpenseArray));

    if($conflict && $expense_validate){
           $users = array_column($permitted_users, 'user_id');
           $users = array_diff($users, array($data['user_id']));
           $title = $dbExpense["title"];
           $operation = '';
           $expense['unique_url'] = $dbExpense["unique_url"];
           if(!empty($addGroupExpenseArray)){
               $expense['expenses']['add'] =  array_map(function ($addGroupExpense) {
                   return $addGroupExpense['id'];
               }, array_slice($addGroupExpenseArray,0,2));
               $operation = 'added ';

           }
           if(!empty($modifyGroupExpenseArray)){
              $expense['expenses']['update'] = array_map(function ($modifyGroupExpense) {
                  return $modifyGroupExpense['id'];
              }, array_slice($modifyGroupExpenseArray,0,2));
              if(empty($operation)){
                  $operation = $operation.'updated ';
              }else{
                  $operation = $operation.',updated ';
              }
              
          }
           if(!empty($deleteGroupExpenseArray)){
               $expense['expenses']['delete'] = array_map(function ($deleteGroupExpense) {
                   return $deleteGroupExpense['id'];
               }, array_slice($deleteGroupExpenseArray,0,2));
               if(empty($operation)){
                   $operation = $operation.'deleted ';
               }else{
                   $operation = $operation.',deleted ';
               }
           }
           $body = "Expenses have been {$operation}in {$dbExpense["title"]} group.";
           $expense['expenses'] = json_encode($expense['expenses']);
           $expense['title'] = $title;
           $expense['body'] = $body;
           if(!empty($users)) {
             $this->Notification->send($users, $expense);
           }
    }

	 $this->set(array(
				'response' => $input,
				'_serialize' => array('response')
		)); 
		  
	}

	
	private function insertAccessInfo($data){
		//insert data into the table access_infos
		$accessInfoData["id"] = $data["id"];
		$accessInfoData["unique_url"] = $data["unique_url"];
		$accessInfoData["access_time"] = $this->getSystemCurrentTimeStamp();
		
		$error = $this->AccessInfo->saveAccessInfo($accessInfoData);
	}





}