diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 403ab622..d9a05733 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -11,10 +11,11 @@ $routes->options('(:any)', function() { }); $routes->group('sheet', function ($routes) { - $routes->get('(:any)', 'GoogleSheetController::editor/$1'); - $routes->get('(:any)/fetch', 'GoogleSheetController::fetch/$1'); - $routes->post('(:any)/save', 'GoogleSheetController::save/$1'); - $routes->get('(:any)/download', 'GoogleSheetController::download/$1'); + $routes->post('create', 'GoogleSheetController::create'); + $routes->get('(:segment)/fetch', 'GoogleSheetController::fetch/$1'); + $routes->post('(:segment)/save', 'GoogleSheetController::save/$1'); + $routes->get('(:segment)/download', 'GoogleSheetController::download/$1'); + $routes->get('(:segment)', 'GoogleSheetController::editor/$1'); }); diff --git a/app/Controllers/GoogleSheetController.php b/app/Controllers/GoogleSheetController.php index e51f81ab..cfdd98fc 100644 --- a/app/Controllers/GoogleSheetController.php +++ b/app/Controllers/GoogleSheetController.php @@ -6,6 +6,35 @@ use CodeIgniter\Controller; class GoogleSheetController extends Controller { protected GoogleSheetLib $sheetLib; + public $config = [ + + 'permissions' => [ + 'editors' => [ + 'vitvelz@gmail.com', 'velz1990@gmail.com','venkateshraman786@gmail.com' + // 'group:rfq-editors@company.com' + ], + 'viewers' => [], + ], + + 'protections' => [ + [ + 'range' => 'RFQ Page!B12:C12', + 'users' => [ //allowed users to edit this cell range + 'velz1990@gmail.com','vitvelz@gmail.com','firebase-adminsdk-mcdfe@nhance-ee8d1.iam.gserviceaccount.com' + ], + 'groups' => [] + ], + [ + 'range' => 'Claims Page!A1', + 'users' => [ + 'velz1990@gmail.com','venkateshraman786@gmail.com','firebase-adminsdk-mcdfe@nhance-ee8d1.iam.gserviceaccount.com' + ], + 'groups' => [] + ] + ], + + 'parentFolderId' => '19uySI-PSFQfFpZvMSnBtirXbwfCTXFBL', // RFQ folder +]; public function __construct() { @@ -23,10 +52,16 @@ class GoogleSheetController extends Controller /* ---------- FETCH ---------- */ public function fetch(string $sheetId) { - // $data = $this->sheetLib->read($sheetId); + $data = $this->sheetLib->read($sheetId); // print_rr($data);die; - // return $this->response->setJSON($data); - echo 'Hi'; + return $this->response->setJSON($data); + // echo 'Hi'; + } + + public function sample(string $sheetId) + { + echo $sheetId; + } /* ---------- SAVE ---------- */ @@ -63,4 +98,39 @@ class GoogleSheetController extends Controller ) ->setBody($content); } + + public function create() + { + try { + $config = config('RfqConfig'); + // #$lib = new RfqGoogleSheetLib(); + + // $templateId = $this->request->getPost('templateId'); + // if (!$templateId) { + // throw new \Exception('Template ID missing'); + // } + + // $newSheetId = $this->sheetLib->copyTemplate( + // $templateId, + // 'RFQ_' . date('Ymd_His'), + // $this->config['parentFolderId'] + // ); + $newSheetId = '1GXNDNXoWriClb5HCqPYd2GAY1T8aie_Hos0yAOoTaC0'; + // $this->sheetLib->applyPermissions($newSheetId, $this->config['permissions']); + $this->sheetLib->applyProtections($newSheetId, $this->config['protections']); + + return $this->response->setJSON([ + 'status' => 'success', + 'url' => $this->sheetLib->sheetUrl($newSheetId) + ]); + + } catch (\Throwable $e) { + return $this->response + ->setStatusCode(500) + ->setJSON([ + 'status' => 'error', + 'message' => $e->getMessage() + ]); + } + } } diff --git a/app/Controllers/LeadsController.php b/app/Controllers/LeadsController.php index 2c2d9bcf..cfe01bbe 100644 --- a/app/Controllers/LeadsController.php +++ b/app/Controllers/LeadsController.php @@ -302,8 +302,8 @@ class LeadsController extends BaseController public function viewLeadsList() { - $data['tab_name'] = 'Leads'; - $data['page_name'] = 'Leads'; + $data['tab_name'] = 'Opportunities'; + $data['page_name'] = 'Opportunities'; // Set basic data $data['issuer'] = $this->issuer; @@ -372,7 +372,7 @@ class LeadsController extends BaseController 'lead_type' => [ 'rules' => 'integer', - 'errors' => ['required' => 'Lead Type is required'] + 'errors' => ['required' => 'Opportunity Type is required'] ], 'issuer' => [ 'rules' => 'required', @@ -934,10 +934,10 @@ class LeadsController extends BaseController } if (count($insertCount) > 0) { - return $this->respond(['status' => true, 'lead_id' => $insert, 'message' => 'New Lead created successfully', 'data' => $data], 200); + return $this->respond(['status' => true, 'lead_id' => $insert, 'message' => 'New Opportunity created successfully', 'data' => $data], 200); } - return $this->respond(['status' => false, 'lead_id' => $insert, 'message' => "Failed to create Lead", 'data' => $data], 200); + return $this->respond(['status' => false, 'lead_id' => $insert, 'message' => "Failed to create Opportunity", 'data' => $data], 200); } private function updateOldLead($id, $data) @@ -946,9 +946,9 @@ class LeadsController extends BaseController $this->insertMultiFilesData($data[0]['multi_file_data'], $id, $data[0]['lead_form_type']); $this->insertLeadStatus($id, $data[0]['status'], 3); - return $this->respond(['status' => true, 'lead_id' => $id, 'message' => "Lead updated successfully", 'data' => $data], 200); + return $this->respond(['status' => true, 'lead_id' => $id, 'message' => "Opportunity updated successfully", 'data' => $data], 200); } - return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Lead", 'data' => $data], 200); + return $this->respond(['status' => false, 'lead_id' => $id, 'message' => "Failed to update Opportunity", 'data' => $data], 200); } // Get the Single Lead data for edit uisng ajax (do not delete) @@ -1305,7 +1305,7 @@ class LeadsController extends BaseController if (!$lead_data) { // Handle case where lead doesn't exist - throw new \Exception('Lead not found'); + throw new \Exception('Opportunity not found'); } // 4. Conditional query - only fetch if needed @@ -1494,7 +1494,7 @@ class LeadsController extends BaseController $lead_id = $data['lead_id'] ?? null; if (!$lead_id) { - return $this->respond(['status' => false, 'message' => 'Lead ID is required'], 400); + return $this->respond(['status' => false, 'message' => 'Opportunity ID is required'], 400); } $rfq_created = $this->RFQModel->where('lead_id', $lead_id)->where('is_active', 1)->countAllResults(); @@ -2796,7 +2796,7 @@ class LeadsController extends BaseController $file_name_with_path = WRITEPATH . "/uploads/lead_files/" . $lead_data['file_name']; if (!$lead_data) { - return ['status' => 'failed', 'message' => 'Lead data not found']; + return ['status' => 'failed', 'message' => 'Opportunity data not found']; } try{ @@ -5583,7 +5583,7 @@ class LeadsController extends BaseController // dd($file_name_with_path); if (!$lead_data) { - return ['status' => 'failed', 'message' => 'Lead data not found']; + return ['status' => 'failed', 'message' => 'Opportunity data not found']; } if ($lead_data['file_name']) { @@ -6579,7 +6579,7 @@ class LeadsController extends BaseController return $this->respond([ 'status' => false, 'code' => 400, - 'message' => 'Lead ID is required' + 'message' => 'Opportunity ID is required' ], 400); } diff --git a/app/Controllers/SalesController.php b/app/Controllers/SalesController.php index 3de595f8..a830542e 100644 --- a/app/Controllers/SalesController.php +++ b/app/Controllers/SalesController.php @@ -88,7 +88,7 @@ class SalesController extends BaseController } // Otherwise fetch ALL sales managers in this branch - elseif (in_array($role,[1,2,3,4,5])) { + elseif (in_array($role,[1,5])) { $data['users'] = $db->table('user_profiles up') ->select('up.id, up.first_name, up.last_name, up.nhance_branch_id') @@ -793,7 +793,7 @@ class SalesController extends BaseController // dd($logged_user_id, $nhance_branch_id, $role, $team_id ); - if (in_array($role,[5])) { + if (in_array($role,[1,5])) { $sales_manager_ids = array_column( $db->table('user_profiles up') @@ -822,36 +822,46 @@ class SalesController extends BaseController public function branchLevelDashboard($branchId,$sales_manager_ids) { - $data['tab_name'] = 'Dashboard'; - $data['page_name'] = 'Dashboard'; // Hardcoded branch ID as requested // $branchId = 1; try { - // 1. Lead Statistics - $stats = $this->leadModel->getLeadStats(); // Using existing model method - - // 2. Activity Statistics - $activityStats = [ - 'total' => $this->activityModel->countAllResults(), - 'completed' => $this->activityModel->where('status', 'completed')->countAllResults(), - 'pending' => $this->activityModel->where('status', 'pending')->countAllResults(), - ]; - - // 3. Team Performance (Aggregating activity counts per user) - $db = \Config\Database::connect(); - // Final safe check - if (empty($sales_manager_ids)) { + $sales_manager_ids = array_values(array_map('intval', $sales_manager_ids)); + + // Final safe check + if (empty($sales_manager_ids)) { // No valid IDs — skip queries or return empty - $teamPerformance = []; - $recentActivities = []; - $leadsOverview = []; - } else { + $total_leads = 0; + $total_activity = 0; + $total_completed_activity = 0; + $total_pending_activity = 0; + $pending_activities = []; + $recent_activities = []; + $teamPerformance = []; + + $leadsOverview = []; + } else { - if (empty($sales_manager_ids) || !is_array($sales_manager_ids)) { - $sales_manager_ids = array_filter((array) $sales_manager_ids); // removes null, "", 0 - } + if (empty($sales_manager_ids) || !is_array($sales_manager_ids)) { + $sales_manager_ids = array_filter((array) $sales_manager_ids); // removes null, "", 0 + } + + // 1. Lead Statistics + $total_leads = $this->leadModel->whereIn('assigned_to', $sales_manager_ids)->countAllResults(); // Use countAllResults, NOT countAll + // echo $this->leadModel->getLastQuery();die(); + + // 2. Total activity + $total_activity = $this->activityModel->whereIn('assigned_to', $sales_manager_ids)->countAllResults(); + // 3. Completed activity + $total_completed_activity = $this->activityModel->whereIn('assigned_to', $sales_manager_ids)->where('status', 'completed')->countAllResults(); + + // 4. Pending activity + $total_pending_activity = $this->activityModel->whereIn('assigned_to', $sales_manager_ids)->where('status', 'pending')->countAllResults(); + + $db = \Config\Database::connect(); + + // 5. Team Performance $teamPerformance = $db->table('user_profiles as u') ->select('u.first_name, u.last_name, u.profile as role, (SELECT COUNT(*) FROM sales_activities WHERE assigned_to = u.id) as total_acts, @@ -861,25 +871,25 @@ class SalesController extends BaseController ->where('u.is_active', 1) ->get()->getResultArray(); - // 4. Recent Activities (Joining for Lead Names) - $recentActivities = $this->activityModel->select('sales_activities.*, sales_actual_leads.company_name') + // 6. Recent Activities (Joining for Lead Names) + $recent_activities = $this->activityModel->select('sales_activities.*, sales_actual_leads.company_name') ->join('sales_actual_leads', 'sales_actual_leads.lead_id = sales_activities.lead_id') ->orderBy('sales_activities.scheduled_date', 'DESC') ->limit(6) ->findAll(); - $sales_manager_ids = array_values(array_map('intval', $sales_manager_ids)); - $recentActivities = $db->table('sales_activities sa') - ->select('sa.activity_id,sa.lead_id,sa.activity_type,sa.scheduled_date,sa.status,sa.assigned_to,sal.company_name,up.first_name AS assigned_to_name') - ->join('(SELECT lead_id, MAX(company_name) AS company_name FROM sales_actual_leads GROUP BY lead_id) sal','sal.lead_id = sa.lead_id','left') + // 7. Pending Activities (List) + $pending_activities = $db->table('sales_activities sa') + ->select('sa.activity_id,sa.lead_id,sa.activity_type,sa.scheduled_date,sa.status,sa.assigned_to,sal.company_name,up.first_name AS assigned_to_name,sa.notes') ->join('user_profiles up', 'up.id = sa.assigned_to', 'left') + ->join('sales_actual_leads sal', 'sal.lead_id = sa.lead_id', 'left') // ✅ ADD THIS ->orderBy('sa.scheduled_date', 'DESC') - ->limit(6) ->whereIn('sa.assigned_to', $sales_manager_ids) + ->where('sa.status', 'pending') ->get()->getResultArray(); - // 5. All Leads Overview - $leadsOverview = $db->table('sales_actual_leads sal') + // 8. All Leads Overview + $leadsOverview = $db->table('sales_actual_leads sal') ->select('sal.lead_id,sal.company_name,sal.status,up.first_name AS assigned_to, COUNT(DISTINCT sa.activity_id) AS activities, COUNT(DISTINCT l.id) AS opportunities @@ -888,39 +898,34 @@ class SalesController extends BaseController ->join('sales_activities sa', 'sa.lead_id = sal.lead_id', 'left') ->join('leads l', 'l.actual_lead_id = sal.lead_id', 'left') ->groupBy('sal.lead_id, sal.company_name, sal.status, up.first_name') - ->having('COUNT(DISTINCT sa.activity_id) + COUNT(DISTINCT l.id) >', 0) // ← this line + // ->having('COUNT(DISTINCT sa.activity_id) + COUNT(DISTINCT l.id) >', 0) // ← this line ->orderBy('sal.created_at', 'DESC') ->whereIn('sal.assigned_to', $sales_manager_ids) ->get() ->getResultArray(); - } - // 6. activityBreakdown - $total = $db->table('sales_activities')->countAll(); - + // 9. Activity BrakDown $activityBreakdown = $db->table('sales_activities') - ->select("activity_type, COUNT(*) AS total, ROUND(COUNT(*) * 100.0 / {$total}, 0) AS percentage", false) + ->select("activity_type, COUNT(*) AS total, ROUND(COUNT(*) * 100.0 / {$total_activity}, 0) AS percentage", false) + ->whereIn('assigned_to', $sales_manager_ids) ->groupBy('activity_type') ->orderBy('total', 'DESC') ->get() ->getResultArray(); - - $teamPerformance = array_filter($teamPerformance, function($row) { - return ($row['total_acts'] + $row['done_acts']) > 0; - }); - - + } $data = [ - 'total_leads' => $stats['total'], - 'total_activities' => $activityStats['total'], - 'completed_acts' => $activityStats['completed'], - 'pipeline_value' => '15.0L', // Hardcoded placeholder from PDF [cite: 14] - 'team' => $teamPerformance, - 'recent_acts' => $recentActivities, - 'leads_overview' => $leadsOverview, + 'total_leads' => $total_leads, + 'total_acts' => $total_activity, + 'total_completed_acts' => $total_completed_activity, + 'total_pending_acts'=> $total_pending_activity, + 'pipeline_value' => '15.0L', // Hardcoded placeholder from PDF [cite: 14] + 'team' => $teamPerformance, + 'recent_acts' => $recent_activities, + 'pending_acts' => $pending_activities, + 'leads_overview' => $leadsOverview, 'activity_breakdown'=> $activityBreakdown, - 'tab_name' => "Sales Dashboard", - 'page_name' => "Sales Dashboard" + 'tab_name' => "Sales Dashboard", + 'page_name' => "Sales Dashboard" ]; // dd($data); diff --git a/app/Controllers/TestingController.php b/app/Controllers/TestingController.php index aaf62878..daae4293 100644 --- a/app/Controllers/TestingController.php +++ b/app/Controllers/TestingController.php @@ -1002,7 +1002,7 @@ class TestingController extends BaseController // 'dashboard' => 1 'dashboard' => $database_id ], - 'exp' => time() + (10 * 60) // 10 minutes + 'exp' => time() + (10 * 60), // 10 minutes ]; if(!empty($policy_id)){ diff --git a/app/Libraries/GoogleSheetLib.php b/app/Libraries/GoogleSheetLib.php index 5bdb9464..a04ab1e9 100644 --- a/app/Libraries/GoogleSheetLib.php +++ b/app/Libraries/GoogleSheetLib.php @@ -4,6 +4,7 @@ use Google_Client; use Google_Service_Sheets; use Google_Service_Drive; use Google_Service_Sheets_ValueRange; +use Google_Service_Sheets_BatchUpdateSpreadsheetRequest; class GoogleSheetLib { @@ -11,13 +12,14 @@ class GoogleSheetLib protected Google_Service_Sheets $sheets; protected Google_Service_Drive $drive; + public function __construct() { $this->client = new Google_Client(); // Service account JSON $this->client->setAuthConfig( - ROOTPATH . 'gdrive-demo-394007-5b1d856b0c5b.json' + ROOTPATH . 'nhance-ee8d1-e3c5269b1ec7.json' ); // IMPORTANT for service account @@ -32,11 +34,12 @@ class GoogleSheetLib // Init services $this->sheets = new Google_Service_Sheets($this->client); $this->drive = new Google_Service_Drive($this->client); + } /* ===================== READ ===================== */ - public function read(string $spreadsheetId, string $range = 'Sheet1') + public function read(string $spreadsheetId, string $range = 'RFQ Page') { $response = $this->sheets ->spreadsheets_values @@ -77,4 +80,205 @@ class GoogleSheetLib return $response->getBody()->getContents(); } + + + /* ================= COPY TEMPLATE ================= */ + + public function copyTemplate(string $templateId, string $name, string $folderId): string + { + $file = $this->drive->files->copy( + $templateId, + new \Google_Service_Drive_DriveFile([ + 'name' => $name, + 'parents' => [$folderId], + + ]),[ + 'supportsAllDrives' => true, + 'fields' => 'id, name, parents' + ] + ); + + return $file->id; + } + + /* ================= PERMISSIONS ================= */ + + public function applyPermissions(string $fileId, array $permissions) + { + foreach ($permissions['editors'] as $email) { + $this->createPermission($fileId, $email, 'writer'); + } + + foreach ($permissions['viewers'] as $email) { + $this->createPermission($fileId, $email, 'reader'); + } + } + + private function createPermission(string $fileId, string $email, string $role) + { + $type = str_starts_with($email, 'group:') ? 'group' : 'user'; + $email = str_replace('group:', '', $email); + + $this->drive->permissions->create( + $fileId, + new \Google_Service_Drive_Permission([ + 'type' => $type, + 'role' => $role, + 'emailAddress' => $email + ]), + ['sendNotificationEmail' => false,'supportsAllDrives' => true] + ); + } + + /* ================= PROTECTIONS ================= */ + + public function applyProtectionsold(string $spreadsheetId, array $ranges) + { + $spreadsheet = $this->sheets->spreadsheets->get($spreadsheetId); + $sheetId = $spreadsheet->getSheets()[0]->getProperties()->getSheetId(); + + $requests = []; + + foreach ($ranges as $range) { + [$sheetName, $a1] = explode('!', $range); + + $requests[] = [ + 'addProtectedRange' => [ + 'protectedRange' => [ + 'range' => [ + 'sheetId' => $sheetId + ], + 'warningOnly' => false + ] + ] + ]; + } + + $this->sheets->spreadsheets->batchUpdate( + $spreadsheetId, + new Google_Service_Sheets_BatchUpdateSpreadsheetRequest([ + 'requests' => $requests + ]) + ); + } + + + public function applyProtections(string $spreadsheetId, array $protections) +{ + // Fetch spreadsheet metadata + $spreadsheet = $this->sheets->spreadsheets->get( + $spreadsheetId, + ['fields' => 'sheets(properties(sheetId,title,gridProperties))'] + ); + + // Map sheet names + $sheetMap = []; + foreach ($spreadsheet->getSheets() as $sheet) { + $props = $sheet->getProperties(); + $sheetMap[$props->getTitle()] = [ + 'sheetId' => $props->getSheetId(), + 'rowCount' => $props->getGridProperties()->getRowCount(), + 'colCount' => $props->getGridProperties()->getColumnCount(), + ]; + } + + $requests = []; + + foreach ($protections as $protection) { + + $rangeStr = $protection['range']; + + if (!str_contains($rangeStr, '!')) { + throw new \Exception("Invalid range format: {$rangeStr}"); + } + + [$sheetName, $a1] = explode('!', $rangeStr, 2); + + if (!isset($sheetMap[$sheetName])) { + throw new \Exception("Sheet not found: {$sheetName}"); + } + + $sheetMeta = $sheetMap[$sheetName]; + + $gridRange = $this->convertA1ToGridRange( + $a1, + $sheetMeta['sheetId'], + $sheetMeta['rowCount'], + $sheetMeta['colCount'] + ); + + $protectedRange = [ + 'range' => $gridRange, + 'description' => 'RFQ Protected Area', + 'warningOnly' => false, + 'editors' => [ + 'users' => $protection['users'] ?? [], + 'groups' => $protection['groups'] ?? [] + ] + ]; + + $requests[] = [ + 'addProtectedRange' => [ + 'protectedRange' => $protectedRange + ] + ]; + } + + if (!empty($requests)) { + $batch = new \Google_Service_Sheets_BatchUpdateSpreadsheetRequest([ + 'requests' => $requests + ]); + + $this->sheets->spreadsheets->batchUpdate($spreadsheetId, $batch); + } + + return true; +} + + /* ================= URL ================= */ + + public function sheetUrl(string $sheetId): string + { + return "https://docs.google.com/spreadsheets/d/{$sheetId}/edit"; + } + + + private function convertA1ToGridRange($a1, $sheetId, $maxRows, $maxCols) +{ + if (preg_match('/^([A-Z]+)(\d+)(?::([A-Z]+)(\d+))?$/i', $a1, $m)) { + + $startCol = $this->colToIndex($m[1]); + $startRow = intval($m[2]) - 1; + + if (!empty($m[3])) { + $endCol = $this->colToIndex($m[3]) + 1; + $endRow = intval($m[4]); + } else { + $endCol = $startCol + 1; + $endRow = $startRow + 1; + } + + return [ + 'sheetId' => $sheetId, + 'startRowIndex' => $startRow, + 'endRowIndex' => $endRow, + 'startColumnIndex' => $startCol, + 'endColumnIndex' => $endCol + ]; + } + + throw new \Exception("Unsupported A1 format: {$a1}"); +} + +private function colToIndex($letters) +{ + $letters = strtoupper($letters); + $index = 0; + for ($i = 0; $i < strlen($letters); $i++) { + $index = $index * 26 + (ord($letters[$i]) - 64); + } + return $index - 1; +} + + } diff --git a/app/Views/cd_master_add_modal.php b/app/Views/cd_master_add_modal.php index 2d9c0143..9ff01a91 100644 --- a/app/Views/cd_master_add_modal.php +++ b/app/Views/cd_master_add_modal.php @@ -68,6 +68,7 @@
+
@@ -126,12 +127,15 @@ console.log(res) if(res.status == true){ - toastr.warning(res.message, 'warning'); + + $('#cd_ac_no_for_cd_master_errorr').text(res.message); + // toastr.warning(res.message, 'warning'); // $('#cd_ac_no').val(''); $('#cd_master_btn_Submit').prop('disabled',true); return; } $('#cd_master_btn_Submit').prop('disabled',false); + $('#cd_ac_no_for_cd_master_errorr').text(''); }, error: function (xhr, status, error) { console.error(xhr.responseText); diff --git a/app/Views/gsheet_editor.php b/app/Views/gsheet_editor.php index 93f40957..e3c9f316 100644 --- a/app/Views/gsheet_editor.php +++ b/app/Views/gsheet_editor.php @@ -16,6 +16,28 @@ + + +
+ +
@@ -26,9 +48,9 @@ const sheetId = ""; alert('second'); /* ---------- LOAD ---------- */ -fetch('' + `/sheet/${sheetId}/fetch`) - .then(r => r.json()) +fetch('' + `sheet/${sheetId}/fetch`) .then(r => r.json()) + // .then(r => r.json()) .then(render); function render(data) { diff --git a/app/Views/layout/header.php b/app/Views/layout/header.php index 67198829..f5109843 100755 --- a/app/Views/layout/header.php +++ b/app/Views/layout/header.php @@ -2073,7 +2073,7 @@ /assets/images/leads_sb.png" alt="Logo" height="20"> - Leads + Opportunities diff --git a/app/Views/lead_filter.php b/app/Views/lead_filter.php index 07cf83bb..620d4a08 100644 --- a/app/Views/lead_filter.php +++ b/app/Views/lead_filter.php @@ -39,7 +39,7 @@
- + - + $value) { @@ -739,7 +739,7 @@ hide_list_show_add(); - var page_title = 'Edit Lead'; + var page_title = 'Edit Opportunity'; $('#page_title').text(page_title); $('#leads_primarykey').val(res.data.id); diff --git a/app/Views/leads_form_handler.php b/app/Views/leads_form_handler.php index 01960410..69b7b665 100644 --- a/app/Views/leads_form_handler.php +++ b/app/Views/leads_form_handler.php @@ -954,7 +954,7 @@ if (isset($selected_lead_type)) { hide_list_show_add(); - $('#page_title').text('Edit Lead'); + $('#page_title').text('Edit Opportunity'); $('#leads_primarykey').val(data.id || ''); $('#actual_lead_id').val(data.actual_lead_id || 0); $('#policy_start_date').val(data.policy_end_date || ''); @@ -1129,7 +1129,7 @@ if (isset($selected_lead_type)) { } } - $('#page_title').text('Edit Lead'); + $('#page_title').text('Edit Opportunity'); $('#leads_primarykey').val(data.id || ''); $('#actual_lead_id').val(data.actual_lead_id || 0); $('#policy_start_date').val(data.policy_end_date || ''); diff --git a/app/Views/leads_list.php b/app/Views/leads_list.php index 98b9f232..7ad9f74a 100644 --- a/app/Views/leads_list.php +++ b/app/Views/leads_list.php @@ -151,7 +151,7 @@ table.dataTable tbody td {
-

Leads List

+

Opportunities List

@@ -165,7 +165,7 @@ table.dataTable tbody td {
S.No  
-
Lead Type  
+
Opportunity Type  
Issuer  
Client Type  
Client / Branch  
@@ -257,7 +257,7 @@ table.dataTable tbody td {
@@ -283,7 +284,7 @@ - + @@ -352,7 +353,7 @@ - + @@ -502,7 +503,8 @@
- + +
@@ -934,7 +936,7 @@ function renderCard(opps) { } function renderTimeline(acts) { const cont = document.getElementById('timelineContainer'); - const activityIcons = { Call: "📞", Email: "✉️", Meeting: "📅", Visit: "🚗",Demo: "🎬", Share: "📄", Todo: "✓" }; + const activityIcons = { Call: "📞", Email: "✉️", Meeting: "📅", Visit: "🚗",Demo: "🖥️", Share: "📄", Todo: "✓" }; if (acts.length === 0) { cont.classList.add('no-line'); @@ -1044,7 +1046,8 @@ document.getElementById('addLeadForm').onsubmit = async (e) => { let companyRegex = /^[A-Za-z\s]+$/; let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - let phoneRegex = /^\+?[0-9\s]{10,20}$/; // Phone regex (+, numbers, spaces allowed, 10-20 length) + // let phoneRegex = /^\+?[0-9\s]{0,10}$/; // Phone regex (+, numbers, spaces allowed, 10-20 length) + let phoneRegex = /^\d{10}$/; // 1. HELPER FUNCTION: Shows Toastr and focuses the specific field function showError(message, fieldName) { @@ -1081,7 +1084,8 @@ document.getElementById('addLeadForm').onsubmit = async (e) => { } if (phone && !phoneRegex.test(phone)) { - return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + // return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + return showError("Phone number can contain only numbers (10 digits)", 'phone'); } if (!data.status) { @@ -1170,7 +1174,8 @@ document.getElementById('editLeadForm').onsubmit = async (e) => { let companyRegex = /^[A-Za-z\s]+$/; let emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - let phoneRegex = /^\+?[0-9\s]{10,20}$/; + // let phoneRegex = /^\+?[0-9\s]{10,20}$/; + let phoneRegex = /^\d{10}$/; let gstRegex = /^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][0-9A-Z]Z[0-9A-Z]$/; // 1. HELPER FUNCTION: Shows Toastr and focuses the specific field @@ -1208,7 +1213,8 @@ document.getElementById('editLeadForm').onsubmit = async (e) => { } if (phone && !phoneRegex.test(phone)) { - return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + // return showError("Phone number can contain only +, numbers and spaces (10–20 digits).", 'phone'); + return showError("Phone number can contain only numbers (10 digits)", 'phone'); } if (gst && !gstRegex.test(gst)) { diff --git a/gdrive-demo-394007-5b1d856b0c5b.json b/gdrive-demo-394007-5b1d856b0c5b.json deleted file mode 100644 index d2c85363..00000000 --- a/gdrive-demo-394007-5b1d856b0c5b.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "service_account", - "project_id": "gdrive-demo-394007", - "private_key_id": "5b1d856b0c5b13e52b5210d381ce7ae02204f666", - "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9tqkwe8XEuvDJ\ngDAKHn7FzFgkmor9sEZPkjofVJ1dK0RpD1mMVw38BzzMsEo8Y8aojNKj9FcgJPI+\nMiSwvoHDVGxPuyz2Q7o8BS7WdM83Sn69CBGn+0s+YjsyQ5pQBeu1YZ3erjckyA1M\nX0a0qXSFRm7dN0pwDIk0SP9/pl5iAKEtakuXn/Q+lSIpHz6OUgQy8bCjn91poMtF\nhL1YR/7k8ZttjQiFSCTzQ6e3IJmVbqY9UZ2hc4zVicLVSLM2x17M1CCVrsXoceOj\nQoYEeCqP2qJjGA29CB66xpXetuOFcll/ZHiNBhSekOBbJIKFG8WfTKaFn4hu2HX6\nzbJLse5FAgMBAAECggEAXK8qxWcS3eQ+0xLvZWI0qUoGHgvqr7o4/5L/FmNuZiBH\nUdSP+UJmsKSQjafq/Mn6OkpidntfPXMPbldtGXRZTSanq+RUORQpnj0h/uAehHK+\nrHeOuLTKs/Wl2g6xCzt5RqokSLBwfGXIKXG6x3SqWppoe2cR1OArAAJR4PlUzyeM\nP0HkZcVMDrXkshpbi/7yk1Yol5CTJjUrXT4cH2eFSih+eu5UxI/uEdxu86XnaB+V\nBDS94nSQffaMem3YLRSQpPWMHJts3NM2eoxpVy3NqbyHH0Jzr47T5+pdnk5AZX8v\nMu7L0FYgUmGli8W9/jV43lUi9z147EpNC1ugySICGQKBgQDeT3i9mBO1HQB+3y05\n4ao9YKWtR7RHTIiMBkekRs58xxWIq75+bsJtLMy0GsHOJHbpdfDU2AtcasYXVm/L\nc960AR7Qm0mdhQi5CG7XfFTvkc+RhsFoCAYOnbdInr1D+s7NsyOgdYvzh9HYIiJ/\nm8MzeGQia/4tlO+UNq7UK0sfowKBgQDadpe0OCynXEiziSY/aBT9mrjplXJSJUeR\nX5/pUrBV++mYt+LJU0Q+4op0Qf+PUJwp72O1v3T9h4ox2BcrYUMI17dJZ5HG46BG\n6Sjh+mZzLCTN9L6AVgRzK/5CUpsL+oPpClzGQK+1uJ+YKZD086YBuQi2JiG6uBxk\n7VLzATZ49wKBgQC3ZHgGb95SGoq+Hv4AMdluqLwEJpLh/pDmcofHTWIqLVHmXUfY\npSZfSgXUzf3zQMGX9mOmMlOs+ahQuE2hWQTvGb2B+ZjRCV4Yxowp17d5qp/BPZlv\naK8Wf6Ujk1AvNEhGCPHq/Q1m6TSDSCWNf8GYREjW3J/immrJqhKvlMd0YQKBgQCM\nf2CpQsdVCwCmljnG5YU6ZFsvvjE7q0YPtFP/lnJZmh1tXjW4DJkDaGZqxlc5MDp+\nrbqOlIcE1jqGO9cKyw51jWYPC1CxfIsDj8f/LS7eOzGgUxqBJtDN0SlANigI2CAl\nq8hmqAtY71eUYIcdQeUtjnaPzo46q1V3gzmplsoVmQKBgDCzaBbFY1bKW+xPPC98\nutYS7cGYtTq241zafSXx/qmpZB2QwFsR3rmZ9msCEBb3TY4Ew+hUi7+SP3ycSU1s\nkwIO/9DaZhFBRA9jbwbu4zdB2Niamfo79epqJ8vhJ6TA2d5xRSGbHWkGymWV/e0p\na74mh5hQ0lqI4MSeArFrJwwF\n-----END PRIVATE KEY-----\n", - "client_email": "gsheet@gdrive-demo-394007.iam.gserviceaccount.com", - "client_id": "108808196910972902964", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gsheet%40gdrive-demo-394007.iam.gserviceaccount.com", - "universe_domain": "googleapis.com" -} diff --git a/nhance-app-google-drive.json b/nhance-app-google-drive.json deleted file mode 100644 index 9a5f94aa..00000000 --- a/nhance-app-google-drive.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "service_account", - "project_id": "nhance-app-4fedb", - "private_key_id": "e764472bb4a0c9226d172f7aebdd2eb785c5fca8", - "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCzyKk6yQqLZHnL\n8+qRwMHtIhV3kR6bYuCol7LTU/aRyTZpFafewJ/6y5bMvvHaRSaohuuTjDhp5H+w\nf7DAiWO06C/YdgZ/tv3dPM8FnkOEnwxUXVgJskK+srJ4g6zsYkT+0DNI0qMJRW5m\n0jv+HKPJ0axCAPcUZUVtraV/HFHF7pJp4oWMFD5X7Jhv7kbW3TetJofSN3SvRvr8\nyfCiVGzqgF0Gx0Tgd25GTMOuRXTGoTlQeDHFMm19g8YY1de0Ol9WqFey6E8e6a/h\nw8KHGdywgsI+q5yF0EIUdxKc6U9Bea25k0YnKHSCsJjJTVlKW+xlxR6wA1yuBb66\n2dAhEzldAgMBAAECggEACEssKpb5dadVPdt+PJ2r58CueD1JfRL8i/p98hhjY9bo\niJEXSFDfI6aYFp22ZYKfWNK3wMimr5SuPIB5F6C4gn3b+y95ERPQtg/AkyDgB39M\nBjZNW4EnabAWFWlc2FJknjnd+JcmLnhoy+h/gpnKoOkbYISDFKQWJfJtRvLE/1on\nhKvnhEkO++93HZp6KPYA21BQIWt6q6gYjjjwxQIHE0Vg30bZC8ciNVaVlmOnpoKW\nlsQ3+TL+b6vDsSxez4hSqWlua7wWL6JgKvyGw6FGiDLGjvTEvVQ0cvfykCDmO5td\nWvVihTMOMXEMx+iVAUOXJLrSPOFGXxSHL9jilqCn0QKBgQDu4P64sE5T15rA+83B\neRMyQUfLru/oxyQ7pAbgRk4nwQj1mXcdD3/RpHF6jg0rt0msRjkzkqyWiJN0qsZ9\nlQY7h0I8pu8dxFhbd7LLcPaNV+OpNAokG06dBK8qhuMcZBlRfvJ3ye5L/Dk0Z7A4\nPw6/OxySns+kzfxtPdpJTNeqFQKBgQDAq2BXm+MsjqjZm2Z1LFMgZcjRLUu4ylMC\n9W3jqd35dBypcafAJ3TqhPLsx+HyWuC+GLMWohx3XGU7oZabGg1zuWAS8A4hnogZ\nk47OT3OYHDaT65HFmSAGJy1UFVvESUdiVzPqO3Xn9dYvRIw6By2b09w+kD1oxmE0\nvAh5UFAMKQKBgHg06plfxxqzzWE9lS290qYgaZOaxYla5OXKRdeIKX4hynNktab/\nDLAfUyd74i7UfhNeBxznu0fJFILKCTZazpcYGoHQ81UEX/4vPt7XSoqX5q1XzZ6b\nyzSCje8Vj6XSzVbQTg1vpSXBl7vCTdAQE0ix40/48L6bFWKXlIf8Ti59AoGAd8UR\nKuT5H6W/SSbVVlmrgyRC5eWmgMUlPV2cZj4egwevGZZRlZ3xjCgBazgGOUZNF177\nVUKJN5n0RFF68ggL/LhsBNm9ryCBsoSL7axuS0yekO2LvK4nvit0fiSY2zhCa9uR\npjY4YW3tK40NLrVvoMLe0vWPdyZ7HvEUw3UtjaECgYAMoonkNACD7EyWesAQzjpD\ntAL5ByXtFkMqMMr8ELLoDU2D5+qzb6gu0+GuYzGvxtYQHz2L+cP7yonn8IRBrAO1\njZCi2Mn1qOYecSGBnv6rotcagMALXwExkymjjVxPLiOae7A01sxSFDpqtRBww2JA\ngFsHNMpkQ1KmZu7LW0q1fg==\n-----END PRIVATE KEY-----\n", - "client_email": "only-drive-access@nhance-app-4fedb.iam.gserviceaccount.com", - "client_id": "116214376249781337850", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/only-drive-access%40nhance-app-4fedb.iam.gserviceaccount.com", - "universe_domain": "googleapis.com" -} diff --git a/nhance-ee8d1-e3c5269b1ec7.json b/nhance-ee8d1-e3c5269b1ec7.json new file mode 100644 index 00000000..afafcff4 --- /dev/null +++ b/nhance-ee8d1-e3c5269b1ec7.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "nhance-ee8d1", + "private_key_id": "e3c5269b1ec7d22e7a297f5273edf3eda6010c0a", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC4+7yRGBAow7GR\nrcBSwXVkBd7U001YC8nZ6GmbfhZSktn4pd4C7r/VGmJMcHdo4CVkt+omY9hEWy3Y\n2k7xvwTBJOxo+A4GENduzUpRucVD5UNs4CKajVmI97FV+2wgeLYR9lLswrSXkQvo\nCRDi/w0EwQ7ZdfPyYfuUUBSdAytiwtGHEJaHBQ4qanNvstFu6FJcCkaq+Sbn6Ool\nHN7lgS/V5NhuBakNOm8EBBaN8Xp13afjHvyFEHalnY8xpNNXNVlBljYIPzYFxXFN\nFL/Iz7XX8dBD0tVwfQGDpD5OCPh8FeIg39dgbRxU3Q+Awv3CX9eoEW1j3bPYo7Lw\nmh8K3fohAgMBAAECggEAEQXPCfxQmSrwOPg0zEjHDTyb3DKGGdw0p772YChy7gfB\nudrfR2s1SWtWo8y7tSTfVaZPcvEmnzYgZ3LB56EAIBs0pP1viO/20aVgBlpI99Q6\ntEobiEs9DViOpkHVs71EzMb1Emcugde6sUOLg5NPkHu8BDErERSJBFJ3bliy0heN\nwAwYKXCB3ro3ryUE5+pRS6ibt8vLEBbk3T3bEW8A1wfWnUo0V+Wf5KXsCO8BvD8Z\nE/i0JgpAkZksWs+keBSLbdWBONNV1GrbxezoZXA8aPPlcaD0bZdLDlszXguq8DGO\nbjr0SI7Hx78/jAQhiFkdNMkLvZMIoU7VVnQSibsBKwKBgQD04PMi6CO6kpKG/ZDw\nR6tuAU8DkUgSjvOquUeGkguyfhK/G5fg3w8yCpLAPoh8ZEGL4zZy+ZoAsHWLv44O\nmXjTOKut5o1puswM8vPobDAinddCWs6U6VWKkkRw27AuyKcnLCpvnRBg/Iw+lSTQ\nzG0KCd8Zn2+a0Cjo9hlF6F2pAwKBgQDBYmvV+cADTRjhostukDK71aKsRhMu1OH4\nRK2uX3f9rde1aSnIcp0PDzn24V7I9skT6zhOCPTF6SEFH35eO3z7kOA26hokOMb2\nz7Bh+EDnx5zQmWwcj0yNwbCeTl7gKWz2o3AuMc8zK6I2+buYJJnjoazUyqQtKhqz\nnPs3woY9CwKBgDHjwqVR9jWEtyWZc3YApAR9b8OiTbS6OxqFNPVNu+RZmygkTwUZ\nbNcdIFjaZKQzKMd/OxChmaaaTNhz5lVDH0KpQRDk79qim//nX5nysLvcvIZgScY8\n45ifxCHaIELnzmZEsUCcF0IrMcduS1nezDhHWpS1zt8TmcIcoXmEpdBRAoGAEtKs\nomAz415evJ+m43Ufqw7JTbFobpeEAzFUInPibwu7wkmhKoSVawDVaIVZP4Bd5BVy\nHo5anOTrNN9y4mMx8B6S5GV28+2e2CkxBuguESFpzxgP4NvF3MpskYwZSgJeO8d+\nxNBOVbG6kVVPgCiX3gM/mlq7DjZZ8P+nqC7D+C8CgYAMeN/ByvGaYSN5bVVntOcT\noDiMWfBBToc9irhNSZsCwghXmNugPKguDbRTi7n/Iqf/HljwUx0HBtXkIgZvDDiW\nQrGSCozd9g2WFx/2OSJv4GU+eUM1GFr0mLFDaAUNzvjwHTkG+2STof8VowaGRx68\n7Z50l5hXKv3i0n5ykhPWUg==\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-mcdfe@nhance-ee8d1.iam.gserviceaccount.com", + "client_id": "105441165052433248287", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-mcdfe%40nhance-ee8d1.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +}