<?php
if (!defined('BASEPATH')) {
exit('No direct script access allowed');
}
class CirPublisher extends ADMIN_Controller
{
public function __construct()
{
parent::__construct();
$this->load->helper(['form', 'url','AdobePdfService']);
$this->load->library(['form_validation', 'pdf','email_worker','sendMail']);
$this->load->model(['cir_model', 'item_price_model', 'header_model', 'frontend/Graph_model']);
$this->CirPublish = Modules::load('admin/cir_publish/CirPublish');
}
private function check_or_create_temp_directory($dir)
{
if (!file_exists($dir)) {
mkdir($dir, 0777, true);
}
}
private function convertImageToBase64($path)
{
if (file_exists($path)) {
return base_url($path);
//return 'data:image/png;base64,' . base64_encode(file_get_contents($path));
}
return '';
}
public function index()
{
$this->login_check();
$head['title'] = 'CostMasters Admin - CIR Report Publish';
$head['description'] = 'CIR report generation page.';
$head['keywords'] = 'CIR, report, PDF';
$head['profile'] = $this->header_model->profile($this->user_id);
$data['report'] = $this->cir_model->get_reports();
$this->load->view('parts/header', $head);
$this->load->view('cir_publish/generate_cir', $data);
$this->load->view('parts/footer');
}
public function generate_cir_pdf()
{
$month = $this->input->post('month');
$year = $this->input->post('year');
$date = $this->input->post('last_updation');
// Set default values if not provided
if (empty($month) || empty($year)) {
$lastMonth = new DateTime('first day of last month');
$date = $lastMonth->format('Y-m-d');
$month = $lastMonth->format('F');
$year = $lastMonth->format('Y');
}
// Validate inputs
if (!$month || !$year) {
return $this->redirectWithError('Please select both month and year.');
}
$cir_check_data = [
'subscribe_month' => $this->input->post('month'),
'subscribe_year' => $this->input->post('year')
];
if ($this->cir_model->check_report($cir_check_data)) {
return $this->redirectWithError('CIR report is already published!');
}
// Fetch report data
$report_data = $this->item_price_model->get_cir_report_data($month, $year);
if (empty($report_data)) {
return $this->redirectWithError('No data found for the selected month and year.');
}
// Generate HTML content
$htmlContent = $this->generatePdfHtmlContent($month, $year, $report_data);
if (empty($htmlContent)) {
log_message('error', 'HTML content is empty');
return;
}
// Save HTML file
$currentTime = date('H-i-s');
$htmlFilePath = "./uploads/genrated_cir_reports/cir_report_{$month}_{$year}_{$currentTime}.html";
file_put_contents($htmlFilePath, mb_convert_encoding($htmlContent, 'UTF-8', 'auto'));
//die;
// Generate approval/rejection tokens
$approvalToken = bin2hex(random_bytes(16));
$rejectionToken = bin2hex(random_bytes(16));
$monthName = date("M", strtotime("{$month} 1")); // Get abbreviated month name (e.g., Jan, Feb, etc.)
$yearShort = substr($year, -2); // Get the last two digits of the year
$pdfFileName = "CIR {$monthName} {$yearShort}.pdf";
// Insert CIR report status
$this->db->insert('approval_reports_status', [
'month' => $month,
'year' => $year,
'cir_pdf_path' => $pdfFileName,
'approval_token' => $approvalToken,
'rejection_token' => $rejectionToken,
'created_at' => $date
]);
// Generate PDF via Adobe PDF Service
$adobeService = new AdobePdfService();
$inputUrl = base_url($htmlFilePath);
$pagelayout = ['pageWidth' => 13.40, 'pageHeight' => 7.50];
$pdfUrl = $adobeService->generateAndCompressPdf($inputUrl, $pagelayout);
if (!$pdfUrl) {
return $this->redirectWithError('PDF generation failed.');
}
// Save generated PDF
$generatedPdfPath = "./uploads/genrated_cir_reports/{$pdfFileName}";
file_put_contents($generatedPdfPath, file_get_contents($pdfUrl));
// Send Approval Email
$this->sendApprovalEmail($month, $year, $approvalToken, $rejectionToken, $generatedPdfPath);
// Validate Report Data
$groupedData = $this->groupItemsByCategory($report_data);
$items_with_zero_values = $this->checkItemsForZeroValues($groupedData, $month, $year);
if (!empty($items_with_zero_values)) {
log_message('error', 'Missing CIR data: ' . print_r($items_with_zero_values, true));
$this->session->set_flashdata('message', 'CIR PDF generated and sent for admin approval. However, some commodities have missing data.');
} else {
$this->session->set_flashdata('message', 'CIR PDF generated and sent for admin approval.');
}
redirect('admin/publish_cir');
}
private function redirectWithError($message)
{
$this->session->set_flashdata('error', $message);
redirect('admin/cir-publish');
}
private function groupItemsByCategory($report_data)
{
$groupedData = [];
foreach ($report_data as $item) {
if (isset($item['cat_id'], $item['item_name'])) {
$groupedData[$item['cat_id']][] = ['item_name' => $item['item_name']];
}
}
return $groupedData;
}
private function checkItemsForZeroValues($groupedData, $month, $year)
{
$items_with_zero_values = [];
foreach ($groupedData as $cat_id => $items) {
foreach ($items as $item) {
$monthly_avg_data = $this->item_price_model->get_combined_last_three_years_monthly_average($month, $year, $cat_id, $item['item_name']);
if ($this->isAllZero($monthly_avg_data)) {
$items_with_zero_values[$cat_id][] = $item['item_name'];
}
}
}
return $items_with_zero_values;
}
private function isAllZero($monthly_avg_data)
{
foreach ($monthly_avg_data as $yearly_data) {
if (is_array($yearly_data) && array_filter($yearly_data)) {
return false;
}
}
return true;
}
private function sendApprovalEmail($month, $year, $approvalToken, $rejectionToken, $pdfFilePath)
{
$approvalLink = base_url("admin/approve_cir/{$approvalToken}");
$rejectionLink = base_url("admin/reject_cir/{$rejectionToken}");
$user_name = "Admin";
$email = ADMIN_EMAIL;
$subject = "CIR of {$month}_{$year} for Approval";
$body = "
<!DOCTYPE html>
<html>
<head>
<style>
/* General styles */
body {
font-family: Arial, sans-serif;
line-height: 1.5;
margin: 0;
padding: 0;
background-color: #f9f9f9;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
padding: 10px 20px 20px 20px;
border: 1px solid #ddd;
float: left;
}
.button {
padding: 10px 20px;
color: white;
text-decoration: none;
font-size: 14px;
display: inline-block;
}
.approve-btn {
background-color: #28A745;
}
.reject-btn {
background-color: #DC3545;
}
/* MSO-specific styles */
/*[if mso]>
<style>
.button {
display: inline-block !important;
mso-padding-alt: 0;
}
</style>
<![endif]*/
</style>
</head>
<body>
<div class='email-container'>
<h3>Greetings of the day!</h3>
<p>The Cost Intelligence Report for {$month} {$year} is now available and attached for your review.</p>
<p>Click below to approve or reject the report:</p>
<table width='100%' border='0' cellspacing='0' cellpadding='0'>
<tr style='display: inline-table;'>
<td>
<a href='{$approvalLink}' class='button approve-btn'
style='padding: 10px 20px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 5px;'>
Approve Report
</a>
</td>
<td align='left' style='padding: 10px;'>
<a href='{$rejectionLink}' class='button reject-btn'
style='padding: 10px 20px; background-color: #f44336; color: white; text-decoration: none; border-radius: 5px;'>
Reject Report
</a>
</td>
</tr>
</table>
<p>Best Regards,<br>Team CostMasters</p>
</div>
</body>
</html>
";
// Validate the PDF file path
if (!file_exists($pdfFilePath)) {
log_message('error', "PDF file does not exist: {$pdfFilePath}");
return false;
}
try {
$this->sendmail->sendAttachmentTo($email, $user_name, $subject, $body, $pdfFilePath);
log_message('info', "Approval email sent to {$email} for CIR of {$month} {$year}.");
} catch (Exception $e) {
log_message('error', "Failed to send approval email: " . $e->getMessage());
}
}
public function approve_cir($approvalToken)
{
$status = $this->item_price_model->get_pdf_status_by_token($approvalToken);
if ($status && $status->cir_status === 'pending') {
$this->item_price_model->update_pdf_status($status->id, 'approved');
$this->handlePdfUpload($status);
$this->session->set_flashdata('message', "<div id='success_msg' class='custom-success'><p>The CIR report has been successfully approved and uploaded.</p></div>");
} else {
$this->session->set_flashdata('message', "<div id='errmsg' class='custom-error'><p>Invalid approval link or the report has already been processed.</p></div>");
}
$this->load->view('cir_publish/cir_approval_status');
}
private function handlePdfUpload($status)
{
$month = $status->month;
$year = $status->year;
$pdf_report = './uploads/genrated_cir_reports/' . $status->cir_pdf_path;
if ($this->CirPublish) {
try {
$result = $this->CirPublish->do_upload_with_data($month, $year, $status->created_at, $pdf_report);
$this->session->set_flashdata('message', "<div id='success_msg' class='custom-success'><p>CIR report generated and sent for admin approval.</p></div>" . $result);
} catch (Exception $e) {
log_message('error', 'Error uploading PDF report: ' . $e->getMessage());
$this->session->set_flashdata('message', "<div id='errmsg' class='custom-error'><p>Failed to upload PDF report: " . $e->getMessage() . "</p></div>");
}
} else {
log_message('error', 'CIR module is not loaded.');
$this->session->set_flashdata('error', 'CIR module failed to load.');
}
}
public function reject_cir($rejectionToken)
{
$status = $this->item_price_model->get_pdf_status_by_rejection_token($rejectionToken);
if ($status && $status->cir_status === 'pending') {
$this->item_price_model->update_pdf_status($status->id, 'rejected');
$this->session->set_flashdata('message', "<div id='success_msg' class='custom-success' style='color:#4CAF50'><p>PDF report has been rejected.</p></div>");
} else {
$this->session->set_flashdata('message', "<div id='errmsg' class='custom-error'><p>Invalid rejection link or the report has already been processed.</p></div>");
}
// Load the view with the flash message
$this->load->view('cir_publish/cir_approval_status');
}
private function generate_pdf_header($month, $year)
{
$base_url = base_url(); // Assuming you're using CodeIgniter, or set the base URL manually
$monthName = date("M", strtotime("{$month} 1")); // Get abbreviated month name (e.g., Jan, Feb, etc.)
$yearShort = substr($year, -2); // Get the last two digits of the year
$title = "CIR {$monthName} {$yearShort}.pdf";
return '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>' . $title .'</title>
<link rel="stylesheet" href="'. $base_url.'/assets/admin/css/generate-cir.css" async>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://code.highcharts.com/highcharts.js" async></script>
</head>
';
}
private function generatePdfHtmlContent($month, $year, $reportData)
{
// Convert images to base64 for embedding
$logo = $this->convertImageToBase64('assets/images/cmlogo-white.png') ?? '';
$backgroundBase64 = $this->convertImageToBase64('assets/images/cir_bg.jpg') ?? '';
$subscriptiondata = $this->db->get('subscription_price_details')->result_array();
// Generate the other parts of the content (excluding the header)
$content = [
$this->generate_first_page_html($logo, $backgroundBase64, $month, $year),
$this->generate_second_page_html($logo),
$this->generate_table_html($logo, $reportData),
$this->generate_commodity_graphs($logo, $backgroundBase64, $reportData, $month, $year),
$this->generate_subscription_page_html($logo, $subscriptiondata),
$this->generate_terms_conditions_html($logo),
$this->generate_contact_us_html($logo, $backgroundBase64)
];
// Assemble the entire PDF content with the header at the top
return $this->assemble_pdf_content($content,$month, $year);
}
private function assemble_pdf_content($content_parts,$month, $year)
{
// Define the common styles for the PDF
$html = '<style>
.pdf-page {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.page-break {
page-break-after: always;
}
</style>';
// Generate the header only once
$header = $this->generate_pdf_header($month, $year);
$html .= '<div>' . $header . '</div>'; // Add header at the top
// Add the content sections
$total_parts = count($content_parts); // Get the total number of content parts
foreach ($content_parts as $index => $part) {
$html .= '<div class="pdf-page">' . $part . '</div>';
// Only add the page break if this is not the last part
if ($index < $total_parts - 1) {
$html .= '<div class="page-break"></div>';
}
}
return $html;
}
private function generate_first_page_html($logoBase64,$backgroundBase64,$month, $year)
{
// // Get the full path to the logo image
$html = '<body style="background-color: #f4f4f9; margin: 0;">
<div class="cir_main">
<!-- Main Content Section -->
<section class="header">
<div class="left_side"></div>
<div class="logo">
<img src="' . $logoBase64 . '">
</div>
</section>
<div class="content cost_report" style="background-image: url('. $backgroundBase64 .'); background-size: cover; background-repeat: no-repeat; color: #fafafa; display: flex; justify-content: center; align-items: center; min-height: 588px;max-height:588px; position: relative;">
<div class="cost-content">
<h1 class="gradient-text" style="font-weight: bold; font-family: Arial, sans-serif; background: linear-gradient(to right, #6d4e78, #6d4e78); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-shadow: 2px 4px 5px rgba(0, 0, 0, 0.3); font-size: 64px; margin-bottom: 10px;">Cost Intelligence Report</h1>
<h3 class="styled-date" style="font-size: 3em; font-family: Georgia, serif; font-weight: bold; color: #BF0000; text-shadow: 2px 0px 0 #fff, 4px 4px 10px rgba(0, 0, 0, 0.5); letter-spacing: 2px; text-align: center;">' . htmlspecialchars($month) . ' ' . htmlspecialchars($year) . '</h3>
</div>
</div>
</div>
<section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section>
</body>
</html>';
return $html;
}
private function generate_second_page_html($logoBase64)
{
// Get the full path to the logo and slide images
$image64 = $this->convertImageToBase64('assets/images/slide2.png');
// Build HTML content with inline styles
$html = '
<body style="font-family: Arial, sans-serif; margin: 0; padding: 0; box-sizing: border-box;">
<div class="cir_main">
<!-- Header Section -->
<section class="header">
<div class="left_side">
<h3 class="header_title">CostMasters Service at a glance</h3>
</div>
<div class="logo">
<img src="' . $logoBase64 . '">
</div>
</section>
<!-- Main Content Section -->
<div class="content slide2" style="background-image: url('. $image64 .'); background-size: 100% 98%; background-repeat: no-repeat; color: #fff; display: flex; justify-content: start; align-items: self-end; min-height: 604.5px;max-height:604.5px; position: relative;"> </div>
</div>
<section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section>
</body>
</html>';
return $html;
}
private function organize_data_by_category($report_data)
{
$categories = [];
foreach ($report_data as $row) {
if (!isset($categories[$row['cat_id']])) {
$categories[$row['cat_id']] = [];
}
if (!in_array($row['item_name'], $categories[$row['cat_id']])) {
$categories[$row['cat_id']][] = $row['item_name'];
}
}
return $categories;
}
private function sort_categories($categories)
{
$predefinedCategories = [
'Steel',
'Non Ferrous Metals',
'Ferro Alloys',
'Alloy Steel',
'Plastics',
'Fuel - Energy',
'Rubber',
'Currency - Banking',
'Manpower',
'Misc.'
];
// Sort categories based on predefined sequence
uksort($categories, function ($key1, $key2) use ($predefinedCategories) {
$index1 = array_search($key1, $predefinedCategories);
$index2 = array_search($key2, $predefinedCategories);
$index1 = $index1 === false ? PHP_INT_MAX : $index1;
$index2 = $index2 === false ? PHP_INT_MAX : $index2;
return $index1 - $index2;
});
return $categories;
}
private function generate_table_html($logoBase64,$report_data)
{
$categories = $this->organize_data_by_category($report_data);
// Check if there's any data to display
if (empty($categories)) {
return '<div>No data available for the selected month and year.</div>';
}
$categories = $this->sort_categories($categories);
// Dynamically divide pages
$totalCategories = count($categories);
$categoriesPerPage = 3; // Limit the number of categories on the first page
// Calculate the number of categories for each page
$firstPageCategories = min($categoriesPerPage, $totalCategories); // Maximum of 3 categories on the first page
$remainingCategories = $totalCategories - $firstPageCategories;
// Prepare HTML for the pages
$html1 = $this->generate_page_html($categories, $logoBase64, 0, $firstPageCategories, 'Index Page 1 of 2' ,'1.3px 7PX');
if ($remainingCategories > 0) {
$html2 = '<div style="page-break-after: always;"></div>';
$html2 .= '<div id="page-2" class="page">' . $this->generate_page_html($categories, $logoBase64, $firstPageCategories, $totalCategories, 'Index Page 2 of 2','0.3px 7PX') . '</div>';
} else {
$html2 = ''; // No second page if all categories fit on the first page
}
// Return combined HTML
return $html1 . $html2;
}
private function render_next_page_button($catIds, $displayedCategories)
{
$remainingCategories = array_diff($catIds, $displayedCategories);
if (!empty($remainingCategories)) {
$html = '<button class="next-page">Next Page</button>';
$html .= '<div class="buttons">';
foreach ($remainingCategories as $category) {
$html .= '<a href="#page-2" class="btn">' . htmlspecialchars($category) . '</a>';
}
$html .= '</div>'; // Close next_box
return $html;
}
return '';
}
private function generate_page_html($categories, $logoBase64, $startIndex, $endIndex, $pageTitle,$paddingli)
{
$html = '<body>
<div class="cir_main" id="category_list">
<section class="header">
<div class="left_side">
<h3 class="header_title">' . $pageTitle . ' <span class="ver_line" id="' . $pageTitle . ' " data-id="' . $pageTitle . ' "></h3>
</div>
<div class="logo">
<img src="' . $logoBase64 . '">
</div>
</section>
<div class="content-commodities" style="background-image: linear-gradient(180deg, #efe9f9, #7c519f5c);">
<div class="ferrous_container">';
$catIds = array_keys($categories);
$displayedCategories = [];
$columns = $this->distribute_categories_to_columns($categories, $catIds, $startIndex, $endIndex, $displayedCategories);
// Render Columns
$html .= $this->render_columns($columns, $startIndex, $endIndex, $catIds, $displayedCategories,$paddingli);
$html .= '</div></div><section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section></body></html>';
return $html;
}
private function render_columns($columns, $startIndex, $endIndex, $catIds, $displayedCategories, $paddingli)
{
$html = '';
$columnCount = count($columns); // Total number of columns to be rendered
$lastColumnIndex = $columnCount - 1; // The index of the last column
$nextPageRendered = false;
$categoryCounters = []; // Track counters for each category
foreach ($columns as $columnIndex => $columnData) {
if (!empty($columnData)) {
$html .= '<div class="column">';
$currentCategory = null;
foreach ($columnData as $data) {
$catId = $data['cat_id'];
// Initialize the counter for a new category
if (!isset($categoryCounters[$catId])) {
$categoryCounters[$catId] = 1;
}
// Add a new category header if switching categories
if ($currentCategory !== $catId) {
if ($currentCategory !== null) {
$html .= '</div>'; // Close previous category
}
$html .= '<div class="ferrous_head">' . htmlspecialchars($catId) . '</div>';
$html .= '<div class="listing_space">';
$currentCategory = $catId;
}
// Add the item with a counter
$html .= '<div style="padding: ' . $paddingli . ';">
<span style="display:inline-block;width:23px;">' . $categoryCounters[$catId] . '. </span>
<a href="#' . rawurlencode($data['item']) . '">' . htmlspecialchars($data['item']) . '</a>
</div>';
// Increment the counter for this category
$categoryCounters[$catId]++;
}
$html .= '</div>'; // Close last category
// Check if we're in the last column of the first page
if ($columnIndex === $lastColumnIndex && $startIndex === 0) {
$html .= '<div class="next_box">' . $this->render_next_page_button($catIds, $displayedCategories) . '</div>';
$nextPageRendered = true;
}
$html .= '</div>'; // Close current column
}
}
// Render Next Page Button after the 3rd column on the first page
if ($columnCount >= 3 && $startIndex === 0 && !$nextPageRendered) {
$html .= '<div class="column next_box">' . $this->render_next_page_button($catIds, $displayedCategories) . ' </div>';
$nextPageRendered = true;
}
return $html;
}
private function distribute_categories_to_columns($categories, $catIds, $startIndex, $endIndex, &$displayedCategories)
{
$itemsPerColumn = 20;
$totalColumns = 4;
$columns = array_fill(0, $totalColumns, []);
$currentColumn = 0;
$currentItemCount = 0;
for ($i = $startIndex; $i < $endIndex && $i < count($catIds); $i++) {
$cat_id = $catIds[$i];
$items = $categories[$cat_id];
foreach ($items as $item) {
if ($currentItemCount >= $itemsPerColumn) {
$currentColumn++;
$currentItemCount = 0;
if ($currentColumn >= $totalColumns) {
break 2; // Stop when all columns are filled
}
}
$columns[$currentColumn][] = ['cat_id' => $cat_id, 'item' => $item];
$currentItemCount++;
$displayedCategories[] = $cat_id;
}
}
return $columns;
}
private function generate_commodities_title_html($logoBase64,$backgroundBase64, $catName)
{
$html = '<body style="margin:0;">
<div class="cir_main">
<!-- Main Content Section -->
<section class="header">
<div class="left_side"></div>
<div class="logo">
<img src="' . $logoBase64 . '">
</div>
</section>
<div class="content cost_report" style="background-image: url('. $backgroundBase64 .'); background-size: cover; background-repeat: no-repeat; color: #fafafa; display: flex; justify-content: center; align-items: center;min-height: 588px;max-height:588px; position: relative;">
<div class="cost-content">
<h1 class="gradient-text">' . htmlspecialchars($catName) . '</h1>
</div>
</div>
<section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section>
</body>
</html>';
return $html;
}
private function generate_header($category, $item, $logoBase64)
{
return '<section class="header">
<div class="left_side">
<h3 class="header_title">' . htmlspecialchars($category) . ' <span class="ver_line" id="' . htmlspecialchars($item) . '" data-id="' . htmlspecialchars($item) . '"> | </span> ' . htmlspecialchars($item) . '</h3>
</div>
<div class="logo">
<img src="' . $logoBase64 . '">
</div>
</section>';
}
private function get_date_range($month, $year)
{
$selected_date = date('Y-m-01', strtotime("$year-$month-01"));
$f_start_date = ($month >= 4) ? "$year-04-01" : ($year - 1) . '-04-01';
$monthName = !empty($month) ? date('n', strtotime($month)) : null;
$start_date_of_month = date('Y-m-01', mktime(0, 0, 0, $monthName, 1, $year));
$last_day_of_month = date('t', mktime(0, 0, 0, $monthName, 1, $year));
$selected_end_date = "$year-" . str_pad($monthName, 2, '0', STR_PAD_LEFT) . '-' . str_pad($last_day_of_month, 2, '0', STR_PAD_LEFT);
// 11 months back from the selected date for price list calculation
$price_list_end_date = date('Y-m-01', mktime(0, 0, 0, $monthName - 11, 1, $year));
return [
'selected_start_date' => $selected_date,
'f_start_date' => $f_start_date,
'selected_end_date' => $selected_end_date,
'price_list_end_date' => $price_list_end_date
];
}
private function collect_trend_data($month, $year, $catName, $items, $dateRange)
{
$trend_data_all = []; // Initialize an array to collect trend data for all items
$special_commodities = [];
// [
// 'WPI - All Commodities',
// 'WPI - Wood & Products',
// 'WPI -Paper & Products',
// 'WPI -Rubber and Plastic Products',
// 'IIP - General Index',
// 'CPI - General Index',
// 'GDP'
// ];
foreach ($items as $item) {
// Fetch trend data
$trend_data = $this->Graph_model->get_combined_year_trend_price_one(
$dateRange['price_list_end_date'],
$dateRange['selected_end_date'],
$catName,
$item,
$special_commodities
);
// Fetch average price data
$average_three_years = $this->item_price_model->get_combined_last_three_year_average(
$dateRange['selected_end_date'],
$catName,
$item
);
$last_four_years_monthly_avg = $this->item_price_model->get_combined_last_three_years_monthly_average(
$month,
$year,
$catName,
$item
);
$monthly_avg_for_year = $this->Graph_model->get_combined_price_data_dynamic(
$dateRange['price_list_end_date'],
$dateRange['selected_end_date'],
$catName,
$item,
$special_commodities
);
// // Debugging check for a specific item
// if (html_entity_decode($item) == 'Scrap - Casting Degi') {
// echo '<pre>';
// print_r($monthly_avg_for_year);
// print_r($last_four_years_monthly_avg);
// echo '</pre>';
// die; // Stop execution for debugging
// }
$price_exis = $this->item_price_model->static_price_exis(
$dateRange['selected_start_date'],
$dateRange['selected_end_date'],
$catName,
$item
);
$price_unit = $this->Graph_model->left_uom(
$dateRange['price_list_end_date'],
$dateRange['selected_end_date'],
$catName,
$item
);
// Store the collected data for each item
$trend_data_all[$item] = [
'trend_data' => $trend_data ?? 0,
'average_three_years' => $average_three_years ?? 0,
'monthly_avg_for_year' => $monthly_avg_for_year ?? 0,
'price_exis' => $price_exis ?? 0,
'price_unit' => $price_unit ?? 0,
'monthly_four_year_average' => $last_four_years_monthly_avg ?? 0
];
}
return $trend_data_all;
}
private function generate_commodity_graphs($logoBase64,$backgroundBase64,$report_data, $month, $year)
{
$categories = $this->organize_data_by_category($report_data);
// Check if there's any data to display
if (empty($categories)) {
return '<div>No data available for the selected month and year.</div>';
}
$categories = $this->sort_categories($categories);
$dateRange = $this->get_date_range($month, $year);
$monthName = !empty($month) ? date('n', strtotime($month)) : null;
$html = '';
foreach ($categories as $catName => $items) {
$html .= $this->generate_commodities_title_html($logoBase64,$backgroundBase64, $catName);
$trend_data_all = $this->collect_trend_data($month,$year,$catName, $items, $dateRange);
$html .= '<div style="page-break-after: always;"></div>';
$html .= $this->generate_graph_result_html($logoBase64, $catName, $items, $monthName, $year, $trend_data_all, $catName);
}
return $html; // Return the complete HTML content
}
private function generate_graph_result_html($logoBase64, $category, $items, $monthName, $year, $trend_data_all, $catName)
{
$WatermarkBase64 = $this->convertImageToBase64('assets/images/csbg.png') ?? '';
$html = '<body style="margin:0;">';
// Validate data presence
if (empty($items)) {
return $html . '<div class="content">No items available</div></body>';
}
$total_items = count($items); // Get the total number of items
// print_r($trend_data_all); die;
foreach ($items as $index => $item) {
// Retrieve the trend data for the current item
$tend_list = $trend_data_all[$item]['trend_data'] ?? [];
// print_r($tree_list); die;
$average_list = $trend_data_all[$item]['average_three_years'] ?? [];
$price_list = $trend_data_all[$item]['monthly_avg_for_year'] ?? [];
$price_exis_list = $trend_data_all[$item]['price_exis'][0]['chart_exis_duty'] ?? '';
if (is_array($price_exis_list)) {
$price_exis_list = array_map('trim', $price_exis_list); // Trim values if needed
$price_exis_list = implode(', ', $price_exis_list);
}
if (!empty($price_exis_list) && is_string($price_exis_list)) {
$price_exis_list = str_replace(
['"Till 30th June 2017 prices are incl of ED', '"w.e.f 1st July 2017', '"Basic Price','Till 30th June 2017 prices are incl of ED, w.e.f 1st July 2017, Basic Price-GST extra','w.e.f 1st July 2017, Basic Price-GST extra'],
'Basic Price - GST Extra',
$price_exis_list
);
}
$price_unit_list = $trend_data_all[$item]['price_unit'][0]['chart_price_unit'] ?? '';
if (is_array($price_unit_list)) {
$price_unit_list = implode(', ', $price_unit_list);
}
$four_years_monthly_avg_list = $trend_data_all[$item]['monthly_four_year_average'] ?? [];
$html .= '<div class="cir_main" id="graph_result">';
$html .= '<div class="costmaster_bg" ><img src="'.$WatermarkBase64.'" class="image_watermark" ></div>';
$html .= $this->generate_header($category, $item, $logoBase64);
$html .= $this->generate_content($item, $tend_list, $monthName, $year, $average_list, $price_list, $price_exis_list, $price_unit_list, $four_years_monthly_avg_list,$catName);
$html .= $this->generate_footer(). '</div>'; // End of container
if ($index < $total_items - 1) {
$html .= '<div style="page-break-after: always;"></div>';
}
}
// Close the main container and body
$html .= '<div class="costmaster"></div></body>';
return $html;
}
private function generate_footer()
{
$username = $this->session->userdata('logged_in'); // Logged in user's username
$organization = $this->session->userdata('organization') ?? 'Costmasters';
return '<section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section>';
}
private function generate_content($item, $tend_list, $monthName, $year, $average_list, $price_list, $price_exis_list, $price_unit_list, $four_years_monthly_avg_list, $catName)
{
$monthAbbreviation = DateTime::createFromFormat('!m', $monthName)->format('M');
// Build the content for the graph
return '
<section class="center_part">
<div class="left">
<h3 class="cirdec">CIR ' . $monthAbbreviation . ' - ' . $year . '</h3>
<div class="Trend_box">'
. $this->generate_trend_table($item, $price_list, $tend_list, $monthName, $year) .
'</div>
<div class="trend_graph Trend_box">
<div class="name" style="text-align:center;">YOY Change</div>'
. $this->generate_bargraph($item, $average_list) .
'</div>
</div>
<div class="center">'
. $this->generate_linecharts($item, $price_exis_list, $price_unit_list, $four_years_monthly_avg_list) .
'</div>
<div class="right">
<div class="Trend_box">'
. $this->generate_price_table($item, $monthName, $year, $price_list, $price_unit_list, $catName) .
'</div>
</div>
</section>';
}
private function generate_trend_table($item, $price_list, $trendata, $monthName, $year)
{
if (empty($trendata)) {
return '<p>No trend data available for ' . htmlspecialchars($item) . '.</p>';
}
$min_cost = isset($trendata['min_avg']) ? $trendata['min_avg'] : 0;
$max_cost = isset($trendata['max_avg']) ? $trendata['max_avg'] : 0;
$avg_cost = isset($trendata['yearly_avg']) ? $trendata['yearly_avg'] : 0;
$price_data = array_slice($price_list, -2);
$trend_last_arr = isset($price_data[0]['chart_item_cost2']) ? $price_data[0]['chart_item_cost2'] : null;
$trend_first_arr = isset($price_data[1]['chart_item_cost2']) ? $price_data[1]['chart_item_cost2'] : null;
$difference = $trend_first_arr - $trend_last_arr ;
$percent_change = ($trend_last_arr != 0) ? round(($difference / $trend_last_arr) * 100, 1) : 0;
// Helper function to determine arrow based on percentage change
$get_arrow = function($percent) {
$threshold = 0.05; // Floating-point precision fix
if (abs($percent) < $threshold) {
return ['caret-right', 'neutral']; // No significant change
} elseif ($percent > 0) {
return ['caret-up', 'uparrow']; // Increase
} else {
return ['caret-down', 'downarrow']; // Decrease
}
};
// Calculate for min, max, and avg using percentage-based comparison
$calculate_diff_percent = function($cost, $base_cost) use ($get_arrow) {
$percent = ($base_cost != 0) ? round((($cost - $base_cost) / $base_cost) * 100, 1) : 0;
[$arrow_icon, $text_color] = $get_arrow($percent);
return [
'percent' => $percent,
'arrow_icon' => $arrow_icon,
'text_color' => $text_color
];
};
$min_data = $calculate_diff_percent($trend_first_arr, $min_cost);
$max_data = $calculate_diff_percent($trend_first_arr, $max_cost);
$avg_data = $calculate_diff_percent($trend_first_arr, $avg_cost);
// Function to format percent values
$format_percent = function($percent) {
return (abs($percent) < 0.05 || $percent == 0 || $percent == -0) ? '0.0' : number_format($percent, 1);
};
return '
<table id="tbltrend" style="width: 100%;">
<thead>
<tr>
<th class="name" colspan="3" style="text-align:center;">Trend</th>
</tr>
</thead>
<tbody>
<tr>
<td>Month Var</td>
<td></td>
<td style="width:70px;">
<div class="arrow_flex">
<span class="' . $get_arrow($percent_change)[0] . ' ' . $get_arrow($percent_change)[1] . '"></span>
' . $format_percent($percent_change) . '%</div>
</td>
</tr>
<tr>
<td>Year Avg</td>
<td>' . number_format($avg_cost, 1) . '</td>
<td style="width:70px;">
<div class="arrow_flex">
<span class="' . $avg_data['arrow_icon'] . ' ' . $avg_data['text_color'] . '"></span>
' . $format_percent($avg_data['percent']) . '%</div>
</td>
</tr>
<tr>
<td>Year Max</td>
<td>' . number_format($max_cost, 1) . '</td>
<td style="width:70px;">
<div class="arrow_flex">
<span class="' . $max_data['arrow_icon'] . ' ' . $max_data['text_color'] . '"></span>
' . $format_percent($max_data['percent']) . '%</div>
</td>
</tr>
<tr>
<td>Year Min</td>
<td>' . number_format($min_cost, 1) . '</td>
<td style="width:70px;">
<div class="arrow_flex">
<span class="' . $min_data['arrow_icon'] . ' ' . $min_data['text_color'] . '"></span>
' . $format_percent($min_data['percent']) . '%</div>
</td>
</tr>
</tbody>
</table>';
}
private function get_color_scheme($defaultColors,$years)
{
$colorScheme = [];
foreach ($years as $index => $year) {
$colorScheme[$year] = $defaultColors[$index % count($defaultColors)];
}
return $colorScheme;
}
private function generate_bargraph($item, $average_list)
{
// Ensure there's data to plot
if (empty($average_list) || empty($average_list['avg_price_commodity']) || empty($average_list['year'])) {
return '<p>No data available for ' . htmlspecialchars($item) . '.</p>';
}
// Ensure data arrays match in length
if (count($average_list['avg_price_commodity']) !== count($average_list['year'])) {
return '<p>Data inconsistency found for ' . htmlspecialchars($item) . '.</p>';
}
// Generate dynamic chart ID and sanitize
$chartId = html_entity_decode("barChart_" . htmlspecialchars($item));
// Define default colors for each bar
$default_colors = ['#92d050', '#544FC5', '#2CAFFE'];
$colors = $this->get_color_scheme($default_colors, $average_list['year']);
$seriesData = [];
// Prepare series data with corresponding colors
foreach ($average_list['avg_price_commodity'] as $index => $value) {
// Round values greater than 1000 up
$value = ($value > 1000) ? ceil(floatval($value)) : round(floatval($value), 2);
$seriesData[] = [
'y' => ($value == 0) ? null : $value, // Use null for zero values
'color' => $colors[$average_list['year'][$index]]
];
}
// Prepare X-axis labels with color indicators
$labels = array_map(function ($year) use ($colors, $average_list) {
$isLastIndex = $year === end($average_list['year']);
$firstYear = explode('-', $year)[0];
$label = $isLastIndex ? (substr($firstYear, -2)) . '-YTD' : $year;
return '<div style="display: flex; justify-content: start; gap: 2.7px; align-items: center; width: 100px;">
<div style="width: 10px; height: 10px; background-color: ' . $colors[$year] . ';"></div>
<p style="margin: 0;">FY-' . $label . '</p>
</div>';
}, $average_list['year']);
// Calculate min and max values for Y-axis
$yValues = array_column($seriesData, 'y');
if (!empty($yValues)) {
$yMin = min($yValues) - 2;
$yMax = max($yValues) + 2;
$range = $yMax - $yMin;
// If the minimum value is greater than 1000, adjust the gap to 10000
if ($yMin > 1000 && $yMin <= 5000) {
$yMin = floor($yMin / 500) * 500; // Round down to nearest 500
$yMax = ceil($yMax / 500) * 500; // Round up to nearest 500
$tickInterval = 500; // Set tick interval to 500
}else if ($yMin > 5000) {
$yMin = floor($yMin / 10000) * 10000; // Round down to nearest 10000
$yMax = ceil($yMax / 10000) * 10000; // Round up to nearest 10000
$tickInterval = 10000; // Set tick interval to 10000
} else {
if ($range <= 2) {
$yMin = max(0, $yMin);
$yMax += 1;
}
if ($yMin < 0) {
$yMin -= 1;
}
$tickInterval = round(($yMax - $yMin) / 4, 0);
if ($tickInterval < 0.25) {
$tickInterval = 0.5;
}
}
$tickInterval = round(($yMax - $yMin) / 4, 0);
if ($tickInterval < 0.25) {
$tickInterval = 0.5;
}
// // Debugging output
// echo "<pre>";
// print_r([
// "yMin" => $yMin,
// "yMax" => $yMax,
// "Range" => $range,
// "Tick Interval" => $tickInterval,
// "Y Values" => $yValues
// ]);
// echo "</pre>";
// die();
}
$labelsJson = json_encode($labels);
$seriesDataJson = json_encode($seriesData);
// Return the HTML and JavaScript for the chart
return '<div class="yoy_box">
<div id="' . $chartId . '" style="height:265px;"></div></div>
<script>
document.addEventListener("DOMContentLoaded", function() {
Highcharts.chart("' . $chartId . '", {
chart: {
type: "column",
marginTop: 40
},
title: {
text: ""
},
xAxis: {
categories: ' . $labelsJson . ',
title: {
text: null
},
labels: {
useHTML: true,
style: {
fontSize: "10px",
fontWeight: "normal"
},
rotation: 0
},
lineWidth: 1
},
yAxis: {
min: ' . $yMin . ',
max: ' . $yMax . ',
tickInterval: ' . $tickInterval . ',
title: {
text: "",
align: "high"
},
labels: {
overflow: "justify"
},
allowDecimals: true,
opposite: false
},
tooltip: {
pointFormat: "{series.name}: <b>{point.y:.2f}</b> units"
},
plotOptions: {
column: {
animation: false,
dataLabels: {
enabled: true,
padding: 7,
allowOverlap: false,
formatter: function() {
// Only show non-null values
return (this.y !== null) ? this.y : null;
},
style: {
fontSize : "16px",
fontWeight: "normal"
},
defer: false,
verticalAlign: "top",
inside: false,
y: -25
}
}
},
legend: {
enabled: false
},
credits: {
enabled: false
},
series: [{
name: "",
data: ' . $seriesDataJson . '
}]
});
});
</script>';
}
private function generate_linecharts($item, $price_exis_list, $price_unit_list, $four_years_monthly_avg_list)
{
$price_Exis = !empty($price_exis_list) ? htmlspecialchars($price_exis_list) : '';
if (empty($four_years_monthly_avg_list)) {
return '<p>No data available for ' . htmlspecialchars($item) . '.</p>';
}
$seriesData = [];
$defaultColors = ['#92d050', '#544FC5', '#2CAFFE'];
$markerTypes = ['circle', 'diamond', 'triangle'];
$colors = $this->get_color_scheme($defaultColors, array_keys($four_years_monthly_avg_list));
$years = array_keys($four_years_monthly_avg_list);
$lastOneYears = array_slice($years, -2);
$index = 0;
foreach ($four_years_monthly_avg_list as $year => $prices) {
$validPrices = array_map(function($price) {
return (is_numeric($price)) ? round(floatval($price), ($price > 1000 ? 0 : 2)) : null;
}, $prices);
if (array_sum($validPrices) !== 0) {
$isLastTwoYears = in_array($year, $lastOneYears);
$seriesData[] = [
'name' => $year,
'data' => $validPrices,
'color' => $colors[$year],
'dataLabels' => [
'enabled' => $isLastTwoYears,
'format' => "{y}",
'verticalAlign' => $year === $lastOneYears[0] ? "bottom" : "top",
'style' => ['fontSize' => '16px', 'color' => '#000', 'fontWeight' => '500', 'textOutline' => 'none'],
'allowOverlap' => true
],
'connectNulls' => true,
'marker' => [
'symbol' => $markerTypes[$index % count($markerTypes)],
'enabled' => true
],
];
$index++;
}
}
$allPrices = array_merge(...array_values($four_years_monthly_avg_list));
if (!empty($allPrices)) {
$yMin = min($allPrices);
$yMax = max($allPrices);
$yMin = ($yMin - 1);
$range = $yMax - $yMin;
if ($range <= 2) {
$yMin = max($yMin - 1, min($allPrices));
$yMax = $yMax + 1;
}
$tickInterval = round(($yMax - $yMin) / 8, 0);
if ($tickInterval < 0.25) {
$tickInterval = 0.50;
}
}
$labels = ["Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar"];
$canvasId = html_entity_decode("highchart_" . htmlspecialchars($item));
$seriesJson = json_encode($seriesData);
$labelsJson = json_encode($labels);
return '<div class="main_graph">
<div style="height:510px;width:750px;" id="' . $canvasId . '"></div>
</div>
<div class="bottom_position">
<div class="bottom_home_icon">
<div class="bottom_text">' . $price_Exis . '</div>
<div class="home_icon">
<a href="#category_list" data-canvas="' . $canvasId . '">
<i class="fa fa-home" style="font-size: 14px;color: #fff;"></i>
</a>
</div>
</div>
</div>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
Highcharts.chart("' . $canvasId . '", {
chart: { type: "line",marginRight:"10"},
title: { text: "" },
tooltip: { enabled: false },
xAxis: { categories: ' . $labelsJson . ', labels: { style: { fontSize: "16px" } }, tickInterval: 1 },
yAxis: {
min: ' . $yMin . ',
max: ' . $yMax . ',
tickInterval: ' . $tickInterval . ',
title: { text: "' . $price_unit_list . '", style: { fontSize: "16px", fontWeight: "bold", color: "#462467" } },
labels: { style: { fontSize: "16px" } },
lineWidth: 1
},
credits: { enabled: false },
legend: { align: "center", verticalAlign: "top", layout: "horizontal", itemStyle: { fontSize: "16px", fontWeight: "bold" } },
plotOptions: { line: { animation: false, lineWidth: 3 }, series: { lineWidth: 3, dataLabels: { enabled: true, format: "{y}", style: { fontSize: "16px", color: "#000", fontWeight: "500" } } } },
series: ' . $seriesJson . '
});
});
</script>';
}
private function generate_price_table($item, $monthName, $year, $price_list, $price_unit_list,$catName)
{
// Ensure the price unit is taken from the first price entry
$priceUnit = !empty($price_unit_list) ? $price_unit_list : '';
// Sort the price list by 'chart_date' in descending order
usort($price_list, function ($a, $b) {
return strtotime($b['chart_date']) - strtotime($a['chart_date']);
});
// print_r($catName); die;
if($catName == 'Currency - Banking'){
$price_unit = $priceUnit;
}else{
$price_unit = 'Price ' . $priceUnit . '';
}
$output = '<table style="width: 100%;">
<thead>
<tr>
<th class="name" colspan="2" style="text-align:center;">
' . $price_unit . '</th>
</tr>
</thead>
<tbody>';
// Loop through the sorted price list and add rows with alternating styles
foreach ($price_list as $index => $price) {
// Convert chart_date into the format 'd-m-Y' or 'M\'y'
$formattedDate = date('M \'y', strtotime($price['chart_date']));
$roundedPrice = is_numeric($price['chart_item_cost2']) ? sprintf('%.2f', round($price['chart_item_cost2'], 2)) : '0.00';
// foreach ($items as $item) {
// if (html_entity_decode($item) == 'Aluminium - ADC 12') {
// echo '<pre>';
// print_r($roundedPrice);
// echo '</pre>';
// die; // Stop for debugging
// }
// // }
$output .= '<tr>
<td>' . htmlspecialchars($formattedDate) . '</td>
<td style="text-align:right;">' . htmlspecialchars($roundedPrice) . '</td>
</tr>';
}
$output .= '</tbody>
</table>';
return $output;
}
private function generate_subscription_page_html($logoBase64, $data)
{
$html = '
<body>
<div class="cir_main">
<section class="header">
<div class="left_side">
<h3 class="header_title">Subscription Charges</h3>
</div>
<div class="logo">
<img src="' . htmlspecialchars($logoBase64) . '" alt="Logo">
</div>
</section>
<table class="price_list">
<thead>
<tr>
<th rowspan="3" class="table-header">Item #</th>
<th rowspan="3" class="table-header">Qty.</th>
<th rowspan="3" class="table-header">Description (Annual Subscription)</th>
<th rowspan="3" class="table-header">Unit Price-INR</th>
<th rowspan="3" class="table-header">Combo Discount</th>
<th colspan="5" class="subscription-cost-header">Subscription Cost</th>
</tr>
<tr>
<th rowspan="2" class="subscription-cost">Single User</th>
<th colspan="4" class="multiuser-price-header">Multiuser Price Slab</th>
</tr>
<tr>
<th class="multiuser-price">Per User Cost up to 3 add-on Users</th>
<th class="multiuser-price">Per User Cost for 4th and 5th User</th>
<th class="multiuser-price">Per User Cost from 6th to 10th User</th>
<th class="multiuser-price">Per User Cost from 11th User Onwards</th>
</tr>
</thead>
<tbody>';
// Loop through the $data array to populate the table rows
foreach ($data as $index => $subscription) {
$html .= '
<tr>
<td class="table-cell">' . ($index + 1) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['qty']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['description']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['unit_price']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['discount']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['single_user']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['multiuser_3']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['multiuser_5']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['multiuser_10']) . '</td>
<td class="table-cell">' . htmlspecialchars($subscription['multiuser_11']) . '</td>
</tr>';
}
$html .= '
</tbody>
</table>
<div class="footer-note">
<span class="gst-note">GST as extra applicable *</span>
<span class="price-change-note">Prices are subject to change without any prior notice *</span>
</div>
<section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section>
</div>
</body>
</html>';
// Return the generated HTML
return $html;
}
private function generate_terms_conditions_html($logoBase64)
{
$html = '<body>
<div class="cir_main">
<!-- Header Section -->
<section class="header">
<div class="left_side">
<h3 class="header_title">Disclaimer</h3>
</div>
<div class="logo">
<img src="' . $logoBase64 . '">
</div>
</section>
<!-- Main Content Section -->
<div class="content slide2" style="padding: 10px;min-height:584px;max-height:584px;position:relative;">
<div class="">
<h3>Terms of Use</h3>
<ul>
<li>Objective of this endeavor is to provide relevant information for strategic decision-making & not meant for influencing commercial transactions. Our liability is restricted to providing information and not the resultant.</li>
<li>You will not share, publish, upload, transmit, reproduce, redistribute or in any other manner make available the statistical information compiled and provided by CostMasters, without the express prior permission of CostMasters. On being permitted, the user shall always mention the source of the statistical information i.e. CostMasters.</li>
<li>Any incidence of single copy being used by multiple users will result in immediate cancellation of supply of statistical information without any refund for the remaining period.</li>
<li>Depending on availability of data from respective sources, commodities may increase and decrease from time to time at sole discretion of CostMasters.</li>
<li>User indemnifies CostMasters from any damage resulting from misinterpretation or use of data. CostMasters" legal liability is strictly restricted to the subscription amount paid by the user.</li>
<li>In case of any taxes or levies imposed by tax authorities during the period of subscription, the user will have to bear and pay the balance amount, enabling us to ensure continuous services.</li>
<li>Although all the efforts are being made to ensure diligence and accuracy of data, still some errors may occur, which will be corrected from time to time.</li>
<li>In case of hardware or software malfunction, we will try our best to restore the services in the minimum possible time. User will have to bear with us during such unavoidable circumstances.</li>
</ul>
</div>
</div>
<!-- Closing the content div -->
</div>
<!-- Closing the container div -->
<section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section>
</body>
</html>';
return $html;
}
private function generate_contact_us_html($logoBase64,$backgroundBase64)
{
$html = '<body>
<div class="cir_main">
<section class="header">
<div class="left_side">
</div>
<div class="logo">
<img src="' . $logoBase64 . '">
</div>
</section>
<div class="content cost_report" style="background-image: url('. $backgroundBase64 .'); background-size: cover; background-repeat: no-repeat; color: #fafafa; display: flex; justify-content: center; align-items: center; min-height: 588px;max-height:588px; position: relative;">
<div class="cost-content">
<h1 class="gradient-text">Contact Us</h1>
<div class="contact_box">
<div class="cs_number">
<button>
<i class="fa fa-phone" style="color: #1c1b1b; font-size: 18px;margin-left: 6px;"></i>
<a href="tel:+91 76966700077">+91 76966700077</a>
</button>
</div>
<div class="cs_mail">
<div class="mail_flex_box">
<div class="simple_mail">
<button>
<i class="fa fa-envelope" style="font-size: 18px;color: #000000;margin: 0px 15px 6px 6px;"></i>
<a href="mailto:cir@costmasters.in">cir@costmasters.in</a>
</button>
</div>
<div class="simple_mail">
<button>
<i class="fa fa-envelope" style="font-size: 18px;color: #100303;margin: 0px 15px 6px 6px;"></i>
<a href="mailto:sales@costmasters.in">sales@costmasters.in</a>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<section class="footer">
<a href="https://www.costmasters.in/" target="_blank">www.costmasters.in</a>
</section>
</body>
</html>';
return $html;
}
}
|