api_family_version = "3"; // new date change $this->app_version = "1"; $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){ $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 validateExpenseList($FamilyExpenseArray){ $error = ""; if(!empty($FamilyExpenseArray)){ if($error == ""){ foreach($FamilyExpenseArray as $key=>$value){ if (!array_key_exists('id', $value) || !array_key_exists('what',$value) || !array_key_exists('category',$value) || !array_key_exists('expense_date', $value) || !array_key_exists('amount', $value)) { // echo "
";
					// print_r($value);exit;
					$error = "14";
					break;
				}
				
				//check id format is correct or not
				$arrayVal = explode("-", $value["id"]);
				 
				if(count($arrayVal) != 3){
				 //	echo "
";print_r($arrayVal);exit;
					$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 legth is ok or not
				
				if(strlen(trim($value["what"])) < 1 || mb_strlen(trim($value["what"]),'UTF-8') > 25){
					$error = "20";
					break;
				}
			
				//check category legth is ok or not				
				if(strlen(trim($value["category"])) < 1 ){
					$error = "20";
					break;
				}
			}
			
			 
		}
		
	}
		
		return $error;
	}
	
	private function validateMealList($MealArray,$ParticipantArray){
		$error = "";
		
		//$isMessExpenseExist = false;
		$participantIdList = array();
		//check if: Invalid key or column name found for meal array
		foreach($MealArray as $key=>$value){			
			if (!array_key_exists('date', $value)
			|| !array_key_exists('meal_amount',$value)
			 ) {						
				$error = "41";
				break;
			}				
		}
		
		/*if( $error == "" && !empty($GroupExpenseArray)){
			foreach($GroupExpenseArray as $index=>$item){
				if($item["expense_type"] == "2"){
					$isMessExpenseExist = true;
					break;
				}
			}
		}*/
		
	
		if( $error == "" && !empty($ParticipantArray)){			
			foreach($ParticipantArray as $key1=>$value1){
				$participantIdList[$key1] = $value1["participant_id"];
			}		
		}
		//check if: Meal Expense has been added but there is not meal defined yet
		/*if( $error == "" && $isMessExpenseExist == true && empty($MealArray)){
			$error = "42";
			 break;
		}*/
		
		//check if: Invalid participant id found in meal which is not available in participant list
		if( $error == "" ){
			foreach($MealArray as $index=>$item){
				$MealSingleArray = explode(",",$item["meal_amount"]);
				
				foreach($MealSingleArray as $key=>$value){
					
					$MealSingleDetailsArray = explode("|",$value);
				
					if(count($MealSingleDetailsArray) != 4){
						$error = "43";//Meal format is not valid		 	 
						break 2;
					}else if(!in_array($MealSingleDetailsArray[0], $participantIdList)){
						$error = "44";//Invalid participant id found in meal which is not available in participant list					 	 
						break 2;
					} else if($MealSingleDetailsArray[1] < 0 || $MealSingleDetailsArray[2] < 0
						|| $MealSingleDetailsArray[3] < 0){
						$error = "45";//Invalid meal number found 
						break 2;
					}

				}
			}	
		
		}
	
		
		return $error;
	}
	
	 
	
	public function uploadFamilyExpense() {
		$object = $this->request->input('json_decode');
		
		if(!empty($object)){
			$data = $this->objectToArray($object);
		}
		
		$this->processFamilyExpense($data,false);
	}
	
	public function addFamilyExpense() {
		$object = $this->request->input('json_decode');
		
		if(!empty($object)){
			$data = $this->objectToArray($object);
		}
		$this->processFamilyExpense($data,true);
	}
	
	private function processFamilyExpense($data,$isTokenRequired){	
		$status = "+000";
		$status_desc = "Expense Data format is not correct!";
		$unique_url = "";
		$latestExpenseData = array();
		$archieved = false;
		$error = "";
		
		//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"];
			$familyIncomeArray = $data["FamilyIncome"];
			$familyExpenseArray = $data["FamilyExpense"];
				
			if(isset($data["app_version"])){
				$this->app_version = $data["app_version"];
			}
				
			if(!empty($expenseArray["unique_url"]) && $expenseArray["unique_url"] != 'null'  && !empty($expenseArray["id"])){
				if(!$this->isValidExpenseUniqueURL($expenseArray["unique_url"],"2")) {
					$error = "31";
				} else {
					$result = $this->Expense->getFamilyExpenseInfoByURL($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 {
                            $this->AccessKey->deleteAccessKey($data["device_id"]);
                        }
                    } 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->validateExpenseList($familyIncomeArray,$familyExpenseArray);
		
				if($error == ""){
					$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"]);
					}
		
					/* echo "
";
					 print_r($expenseArray);exit;
					 */
					$expenseIdStr = $this->Expense->createExpense($expenseArray,true,$archieved);
		
					if($expenseIdStr != ""){
						$expenseIdStrArr = explode(",",$expenseIdStr);
						$index = 0;
                        $FinalFamilyExpenseArray = array();
						if(!empty($familyExpenseArray)){
							foreach($familyExpenseArray as $key=>$value){
								$idPartsArray = explode("-",$familyExpenseArray[$key]["id"]);
								$FinalFamilyExpenseArray[$index] = $value;
								$FinalFamilyExpenseArray[$index]["id"] ="1-".$idPartsArray[1]."-".$expenseIdStrArr[0];
								$FinalFamilyExpenseArray[$index]["record_type"] = "1";
								$FinalFamilyExpenseArray[$index]["is_reimbursement"] = "0";
		
								$index++;
							}
						}
							
						if(!empty($familyIncomeArray)){
							foreach($familyIncomeArray as $key=>$value){
								$idPartsArray = explode("-",$familyIncomeArray[$key]["id"]);
								$FinalFamilyExpenseArray[$index] = $value;
								$FinalFamilyExpenseArray[$index]["id"] ="2-".$idPartsArray[1]."-".$expenseIdStrArr[0];
								$FinalFamilyExpenseArray[$index]["record_type"] = "2";
								$FinalFamilyExpenseArray[$index]["is_reimbursement"] = "0";
								$index++;
							}
						}

						//start check the expense date format and decide
						if(!empty($FinalFamilyExpenseArray)) {
                            $imageUploadResponses = null;
								
							if($this->app_version == "1"){
								foreach($FinalFamilyExpenseArray 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'];
									$FinalFamilyExpenseArray[$key] = $value;
                                    $imageUploadResponses[$key] = $imageUploadResponse['response'];
								}
							} else {
		
								foreach($FinalFamilyExpenseArray 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'];
									$FinalFamilyExpenseArray[$key] = $value;
                                    $imageUploadResponses[$key] = $imageUploadResponse['response'];
								}
									
							}
								
						}

//                        $FinalFamilyExpenseArray =  $this->ImageUpload->imageUpload($FinalFamilyExpenseArray,$expenseIdStrArr[1]);

						$error = $this->FamilyExpense->addMultipleFamilyExpense(
								$FinalFamilyExpenseArray,
								$expenseIdStrArr[0]);
							
						if($error != ""){
							$status = "22";
							$status_desc = "MyXpense Data Saving Failed!";
						} else {
		
		
							$unique_url = $expenseIdStrArr[1];
							$expense_id = $expenseIdStrArr[0];
							$latestExpenseData = $this->Expense->getFamilyExpenseInfoByURL($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
                                    ]];
                                }

                            }
		
							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{
								//$unique_url = $expenseIdStrArr[1];
								$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
								$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;
								}		
							}		
						}

                        // 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"], 
								"FamilyExpense");
                        }

					} else {
						$status = "22";
						$status_desc = "Expense  Data Saving Failed!";
					}
					 
				} else {
					$status = $error;
					$status_desc = "MyXpense Data format is not valid";
				}
					
			} else {
				$status = $error;
				$status_desc = $status_desc;
			}
		}
		
		$input["status"] = $status;
		$input["status_desc"] = $status_desc;
		$input["api_version"] = $this->api_family_version;
		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();
            $crash["expense_type"] = 3;
            $this->LogAppCrashes->insertLogAppCrashes($crash);
        } 

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

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

		$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 isParticipantInvolveInMeal($participantId,$mealList){
		$result = false;
		
		if(!empty($expenseList)){
			foreach($mealList as $key=>$value){ 
				
				$participantMealArray = explode(",",$value["meal_amount"]);
				foreach($participantMealArray as $index=>$item){
					$participantMealDetailsArray = explode("|",$item);
					if(trim($participantMealDetailsArray[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;
		}
		
		 
		return $result;
	}
	
	private function isValidMeal($meal_amount,$mergedParticipantIdList){
		
		$result = true;
		
		if(!empty($mergedParticipantIdList)){ 
			 		 	
			$mealAmtArray = explode(",",$meal_amount);
			foreach($mealAmtArray as $index=>$item){
				$mealAmtDetailsArray = explode("|",$item);
				if(!in_array(trim($mealAmtDetailsArray[0]),$mergedParticipantIdList) ){
					$result = false;
					break;
				}
			}			  
		} else {
			$result = false;
		}		
		 
		return $result;
		
	}
	
	private function isMealDateExistInDB($date,$dbMealList){
		
		$result = false;
		
		if(!empty($dbMealList)){ 
			foreach($dbMealList as $index=>$item){				 
				if($date == $item["date"]){
					$result = true;
					break;
				}
			}			  
		}		
		 
		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 getReplacedValWithParticipantIdForMeal($value,$mapRemoteAndWebId){
		
 	
		$mealStrArray = explode(",",$value["meal_amount"]);
		foreach($mealStrArray as $index=>$item){
			$mealStrDetailArray = explode("|",$item);
			
			if(array_key_exists($mealStrDetailArray[0], $mapRemoteAndWebId)){
				$mealStrDetailArray[0] = $mapRemoteAndWebId[$mealStrDetailArray[0]];								
			}
			$mealStrArray[$index] = implode("|",$mealStrDetailArray);
		}
		
		$value["meal_amount"] = implode(",",$mealStrArray);
		
		 return $value;
						
	}
	
	
	 
 
	//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)
	 * 
	 * 
	 * 
	 * #AddExpenseList
	= *  
	 * 
	 * 
	 * #EditExpenseList
	 * 1. The record should be available in web database.
	 * 2. Web and remote application version should be same for a particular record.
	=  
	 * 
	 * 
	 * 
	 * 
	 * 
	 * #DeleteExpenseList
	 * 1. The record should be available in web database
	 * 2. Web and remote application version should be same for a particular record.
	 * 
	 * 
	 * 
	 * 
	  
	 * 
	 */
	
	public function synFamilyExpense() {
	 
		$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_family_version)) {

            $status = $this->force_upgrade_status;
            $status_desc = "Client require force upgrade!";

        } else {
			$result = $this->Expense->getFamilyExpenseInfoByURL($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->getFamilyExpenseInfoByURL($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["modifyGroupExpense"] = NULL;
				$conflictArray["deleteGroupExpense"] = NULL;
				 
				$conflictArray["modifyGroupIncome"] = NULL;
				$conflictArray["deleteGroupIncome"] = NULL;
				
				$addFamilyExpenseArrayF = array();
				$addFamilyIncomeArrayF = array();
				
				//get DB information
				$dbExpense = $result["Expense"];
				$dbFamilyExpenseList = $result["FamilyExpense"];
				 
				
				//set data
				$currency =  $dbExpense["currency"];
				
				//get user's input
				$expenseArray = array();
				 if(isset($data["Expense"]) && !empty($data["Expense"])){
					$expenseArray = $data["Expense"];		
				 }
                $addFamilyExpenseArray = array();
                $modifyFamilyExpenseArray = array();
                $deleteFamilyExpenseArray = array();

                $addFamilyIncomeArray = array();
                $modifyFamilyIncomeArray = array();
                $deleteFamilyIncomeArray = array();

                if (isset($data["addFamilyExpense"]) && !empty($data["addFamilyExpense"])) {
                    $addFamilyExpenseArray = $this->setDefaultWhat($data["addFamilyExpense"]);
                }
                if (isset($data["modifyFamilyExpense"]) && !empty($data["modifyFamilyExpense"])) {
                    $modifyFamilyExpenseArray = $this->setDefaultWhat($data["modifyFamilyExpense"]);
                }
                if (isset($data["deleteFamilyExpense"]) && !empty($data["deleteFamilyExpense"])) {
                    $deleteFamilyExpenseArray = $this->setDefaultWhat($data["deleteFamilyExpense"]);
                }
                if (isset($data["addFamilyIncome"]) && !empty($data["addFamilyIncome"])) {
                    $addFamilyIncomeArray = $this->setDefaultWhat($data["addFamilyIncome"]);
                }
                if (isset($data["modifyFamilyIncome"]) && !empty($data["modifyFamilyIncome"])) {
                    $modifyFamilyIncomeArray = $this->setDefaultWhat($data["modifyFamilyIncome"]);
                }
                if (isset($data["deleteFamilyIncome"]) && !empty($data["deleteFamilyIncome"])) {
                    $deleteFamilyIncomeArray = $this->setDefaultWhat($data["deleteFamilyIncome"]);
                }
				
				if(isset($data["app_version"])){
					$this->app_version = $data["app_version"];
				}
				
				
			 
				if(!empty($addFamilyExpenseArray)){
					foreach($addFamilyExpenseArray as $key=>$value){
						$value["record_type"] = "1";
						$addFamilyExpenseArray[$key] = $value;
					}
				}
				
				if(!empty($modifyFamilyExpenseArray)){
					foreach($modifyFamilyExpenseArray as $key=>$value){
						$value["record_type"] = "1";
						$modifyFamilyExpenseArray[$key] = $value;
					}
				}
				
				if(!empty($deleteFamilyExpenseArray)){
					foreach($deleteFamilyExpenseArray as $key=>$value){
						$value["record_type"] = "1";
						$deleteFamilyExpenseArray[$key] = $value;
					}
				}
				
				if(!empty($addFamilyIncomeArray)){
					foreach($addFamilyIncomeArray as $key=>$value){
						$value["record_type"] = "2";
						$addFamilyIncomeArray[$key] = $value;
					}
				}
				
				if(!empty($modifyFamilyIncomeArray)){
					foreach($modifyFamilyIncomeArray as $key=>$value){
						$value["record_type"] = "2";
						$modifyFamilyIncomeArray[$key] = $value;
					}
				}
				
				if(!empty($deleteFamilyIncomeArray)){
					foreach($deleteFamilyIncomeArray as $key=>$value){
						$value["record_type"] = "2";
						$deleteFamilyIncomeArray[$key] = $value;
					}
				}
				
				
			 
				
				//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;
					}
				}
				 
				
				//Filter Group Expense List 
				if(!empty($dbFamilyExpenseList)){
					$maxSeriaExpNo = 0;
					$maxSeriaIncNo = 0;
					foreach($dbFamilyExpenseList as $key=>$value){
						$dbAsFamilyExpenseList[$value["id"]] = $value;							
						 
						$idArray = explode("-",$value["id"]);
						if($value["record_type"] == "1"){
							if(intval($idArray[1]) > $maxSeriaExpNo){
								$maxSeriaExpNo = intval($idArray[1]);
							}
						} else if($value["record_type"] == "2"){
							if(intval($idArray[1]) > $maxSeriaIncNo){
								$maxSeriaIncNo = intval($idArray[1]);
							}
						}
						
					}
					
					 

					
					//$dbAsFamilyExpenseList
					/* echo "
";
					print_r($addFamilyIncomeArray);exit; */
					//combine add,modify and delete income and expense list
					
					$modifyFamilyExpenseFinalArray = array_merge($modifyFamilyExpenseArray, $modifyFamilyIncomeArray);
					$deleteFamilyExpenseFinalArray = array_merge($deleteFamilyExpenseArray, $deleteFamilyIncomeArray);
					 
					//for modify and delete, check version and db record exist or not
					if(!empty($modifyFamilyExpenseFinalArray)){
						foreach($modifyFamilyExpenseFinalArray as $key=>$value){
							if(array_key_exists($value["id"],$dbAsFamilyExpenseList) &&
								 $value["version"] == $dbAsFamilyExpenseList[$value["id"]]["version"]){
								$modifyFamilyExpenseSuperFinalArray[$value["id"]] = $value;
							} else {
								if($value["record_type"] == "2"){
									$conflictArray["modifyGroupIncome"][] = $value["id"];
								} else {
									$conflictArray["modifyGroupExpense"][] = $value["id"];
								}
								
							}
						}
						
					}
					
					if(!empty($deleteFamilyExpenseFinalArray)){						
						foreach($deleteFamilyExpenseFinalArray as $key=>$value){
							if(array_key_exists($value["id"],$dbAsFamilyExpenseList) &&
								 $value["version"] == $dbAsFamilyExpenseList[$value["id"]]["version"]){
								$deleteFamilyExpenseSuperFinalArray[$value["id"]] = $value;
							} else {
								if($value["record_type"] == "2"){
									$conflictArray["deleteGroupIncome"][] = $value["id"];
								} else {
									$conflictArray["deleteGroupExpense"][] = $value["id"];
								}
								
							}
						}
					}
					
					 
				} else {
					//$addFamilyExpenseFinalArray = array_merge($addFamilyExpenseArray, $addFamilyIncomeArray);
					//if there are not data in database then just assign final
					$modifyFamilyExpenseSuperFinalArray = NULL;
					$deleteFamilyExpenseSuperFinalArray = NULL;
				}
				
				
				
				//Replace all family expense ids with formated id
				if(!empty($addFamilyExpenseArray)){
				    foreach($addFamilyExpenseArray as $key=>$value){
				        
				        
				        //check if the expense already has been added
				        $idArray = explode("-",$value["id"]);
				        if(count($idArray) == 4){
				            $uniqueDeviceExpenseID = $idArray[3];
				            if(!$this->isItemAlreadyAdded($dbAsFamilyExpenseList,$uniqueDeviceExpenseID) ){
				                
				                $maxSeriaExpNo++;
				                $value["id"] = "1"."-".sprintf("%05d", $maxSeriaExpNo)."-".$dbExpense["id"];
				                $value["syn_add_unique_id"] = $uniqueDeviceExpenseID;
				                $addFamilyExpenseArrayF[$key] = $value;
				            }
				            
				        } else {
				            $maxSeriaExpNo++;
				            $value["id"] = "1"."-".sprintf("%05d", $maxSeriaExpNo)."-".$dbExpense["id"];
				            $addFamilyExpenseArrayF[$key] = $value;
				        }
				        
				        
				        
				    }
				}
				
				
				
				//Replace all family income ids with formated id
				if(!empty($addFamilyIncomeArray)){
				    
				    
				    
				    foreach($addFamilyIncomeArray as $key=>$value){
				        
				        //check if the expense already has been added
				        $idArray = explode("-",$value["id"]);
				        
				        /* echo "
";
				         print_r($idArray);exit; */
				        if(count($idArray) == 4){
				            $uniqueDeviceExpenseID = $idArray[3];
				            
				            
				            if(!$this->isItemAlreadyAdded($dbAsFamilyExpenseList,$uniqueDeviceExpenseID) ){
				                
				                $maxSeriaIncNo++;
				                $value["id"] = "2"."-".sprintf("%05d", $maxSeriaIncNo)."-".$dbExpense["id"];
				                $value["syn_add_unique_id"] = $uniqueDeviceExpenseID;
				                $addFamilyIncomeArrayF[$key] = $value;
				                
				            }
				            
				        } else {
				            $maxSeriaIncNo++;
				            $value["id"] = "2"."-".sprintf("%05d", $maxSeriaIncNo)."-".$dbExpense["id"];
				            $addFamilyIncomeArrayF[$key] = $value;
				        }
				    }
				}
				
				
				$addFamilyExpenseFinalArray = array_merge($addFamilyExpenseArrayF, $addFamilyIncomeArrayF);
		  			
		}
	}


	if($status == "+000") {

		if(!empty($expenseArray)){
			$error = $this->validateExpense($expenseArray);
		}
		
		 //check add,edit,delete participant list
		 if($error == ""){
		 	 
			//check add,edit and delete expense list
			if(!empty($addFamilyExpenseFinalArray)){
				$error = $this->validateExpenseList($addFamilyExpenseFinalArray);
			}
		 		
	 		if($error == "" && !empty($modifyFamilyExpenseSuperFinalArray)){
	 			//Set logs for the modify expense activity		 			
	 			$error = $this->validateExpenseList($modifyFamilyExpenseSuperFinalArray);
	 		}
	 		if($error == "" && !empty($deleteFamilyExpenseSuperFinalArray)){
	 			//set logs for expense delete activity
	 			$error = $this->validateExpenseList($deleteFamilyExpenseSuperFinalArray);
	 		}
	 		if($error == ""){
 	 			if(!empty($expenseArray)){
 	 				$expenseArray["source"] = $this->getSource(new MobileDetectComponent());
                    if($permission != VIEW_PERMIT) {
                        $response = $this->Expense->modifyExpense($expenseArray);
                    }
	 			}
	 			
	 			if(empty($response)){
	 				//$dbExpense
	 				
	 				 
	 				//add group expense
	 				if($error == "" &&  !empty($addFamilyExpenseFinalArray) && $permission != VIEW_PERMIT){
                        $imageUploadResponses = null;
	 					if($this->app_version == "1"){
	 						foreach($addFamilyExpenseFinalArray 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'];
                                $addFamilyExpenseFinalArray[$key] = $value;
                                $imageUploadResponses[$key] =  $imageUploadResponse['response'];

	 						}
	 					} else {
	 						foreach($addFamilyExpenseFinalArray 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'];
                                $addFamilyExpenseFinalArray[$key] = $value;
                                $imageUploadResponses[$key] =  $imageUploadResponse['response'];

	 						}
	 					}
	 					
	 					
	 					if(empty($error))
	 					$error = $this->FamilyExpense->addMultipleFamilyExpense($addFamilyExpenseFinalArray,$dbExpense["id"]);
	 				}
	 				
	 				//edit group expense
	 				if($error == "" &&  !empty($modifyFamilyExpenseSuperFinalArray) && $permission != VIEW_PERMIT){
	 					
	 					if($this->app_version == "1"){
	 						foreach($modifyFamilyExpenseSuperFinalArray as $key=>$value){
	 							$value["expense_date_old"] =  $value["expense_date"];
	 							$value["expense_date"] = $this->getIntToStrDate($value["expense_date"]);

	 							$modifyFamilyExpenseSuperFinalArray[$key] = $value;
	 						}
	 					} else {
	 						foreach($modifyFamilyExpenseSuperFinalArray 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->FamilyExpense->getImagesById($value['id']);
                                $deleted_image_response = $this->ImageUpload->DeleteSingleImageBucket($dbimages['FamilyExpense']['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'];

	 							$modifyFamilyExpenseSuperFinalArray[$key] = $value;

                                if(!empty($upload_image_response['response']['message'])){
                                    $conflictArray["modifyFamilyExpense"][$value['id']][] = $upload_image_response['response']['message'];
                                }
	 						}
	 					}
	 					
	 					if(empty($error))
	 					$error = $this->FamilyExpense->modifyMultipleFamilyExpense($modifyFamilyExpenseSuperFinalArray,$dbExpense["id"]);
	 				}
	 					

	 				//delete group expense
	 				if($error == "" &&  !empty($deleteFamilyExpenseSuperFinalArray) && $permission != VIEW_PERMIT){
	 					$error = $this->FamilyExpense->deleteMultipleFamilyExpense($deleteFamilyExpenseSuperFinalArray,$dbExpense["id"]);
                        if(empty($error)) {
                            $imageDeleteResponse = $this->ImageUpload->DeleteImageBucket($deleteFamilyExpenseSuperFinalArray, $data['unique_url'],$this->app_name);
                        }
	 				}
	 				
	 				 
	 			 				
	 				if($error != ""){
	 					$status = "22";
	 					$status_desc = "MyXpense Update fails";
	 				} else {
	 					$latestExpenseData = $this->Expense->getFamilyExpenseInfoByURL($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
	 						$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;
	 						}
	 					}
	 					
	 				}
	 				
	 			} else {
	 				$status = "22";
	 				$status_desc = "Expense  Data Update Failed!";
	 			} 
	 		}
             else {
	 			$status = $error;
 				$status_desc = "MyXpense 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_family_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"] = 3;
		$this->LogAppCrashes->insertLogAppCrashes($crash);
	}

	//$input["input"] = $data;
	$input["data"] = $latestExpenseData;
	$input["conflict"] = $conflictArray;

    if($permission == VIEW_PERMIT && !empty($data['Expense'])){
        $permission_conflict["Expense"] = $data['Expense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['modifyFamilyExpense'])){
        $permission_conflict["modifyFamilyExpense"] = $data['modifyFamilyExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['addFamilyExpense'])){
        $permission_conflict["addFamilyExpense"] = $data['addFamilyExpense'];
    }
    if($permission == VIEW_PERMIT && !empty($data['deleteFamilyExpense'])){
        $permission_conflict["deleteFamilyExpense"] = $data['deleteFamilyExpense'];
    }
    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'];
    }
    if($permission == VIEW_PERMIT && !empty($data['addFamilyIncome'])){
        $permission_conflict["addFamilyIncome"] = $data['addFamilyIncome'];
    }
    if($permission == VIEW_PERMIT && !empty($data['modifyFamilyIncome'])){
        $permission_conflict["modifyFamilyIncome"] = $data['modifyFamilyIncome'];
    }
    if($permission == VIEW_PERMIT && !empty($data['deleteFamilyIncome'])){
        $permission_conflict["deleteFamilyIncome"] = $data['deleteFamilyIncome'];
    }
    if($permission == VIEW_PERMIT){
        $input["permission_conflict"] = $permission_conflict;
    }
    if(isset($imageUploadResponses) && !empty(array_filter($imageUploadResponses))){
        $input["image_upload_response"] = $imageUploadResponses;
    }
    if(isset($imageDeleteResponse) && !empty(array_filter($imageDeleteResponse))){
        $input["image_delete_response"] = $imageDeleteResponse;
    }
    if(isset($upload_image_response['response'])&& !empty($upload_image_response['response'])){
        $input['modify_family_expense']['add_images'] = $upload_image_response['response'];
    }
    if(isset($deleted_image_response['response']) && !empty($deleted_image_response['response'])){
        $input['modify_family_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($addFamilyExpenseArray) || !empty($modifyFamilyExpenseArray)|| !empty($deleteFamilyExpenseArray));

        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($addFamilyExpenseArray)){
                $expense['expenses']['add'] =  array_map(function ($addFamilyExpense) {
                    return $addFamilyExpense['id'];
                }, array_slice($addFamilyExpenseArray,0,2));
                $operation = 'added ';
            }
            if(!empty($modifyFamilyExpenseArray)){
                $expense['expenses']['update'] = array_map(function ($modifyFamilyExpense) {
                    return $modifyFamilyExpense['id'];
                }, array_slice($modifyFamilyExpenseArray,0,2));
                if(empty($operation)){
                    $operation = $operation.'updated ';
                }else{
                    $operation = $operation.',updated ';
                }
            }
            if(!empty($deleteFamilyExpenseArray)){
                $expense['expenses']['delete'] = array_map(function ($deleteFamilyExpense) {
                    return $deleteFamilyExpense['id'];
                }, array_slice($deleteFamilyExpenseArray,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')));   

	/*	 print_r($input);
		 exit;*/
		  
	}
	
	
	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);
	}



}