<?php
namespace App\Controller\BackOffice\Accounting\Report;
use App\Controller\BaseController;
use App\COREapi\CoreApi;
use App\COREapi\Factory\ReportQueryBuilder;
use App\Entity\QBInvoice;
use App\Entity\Quote;
use App\Entity\QuoteItem;
use App\Entity\User;
use App\ExportExcel\PhpSpreadsheet\ExportExcelBase;
use App\Form\Accounting\Report\CIPVSearchType;
use App\Repository\QBInvoiceRepository;
use Symfony\Component\Form\FormErrorIterator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\ConstraintViolation;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @Route("/backoffice/accounting/reports/cipv")
* @Security("is_granted('ROLE_ACCOUNTING_ALL')")
*/
class CIPVReportController extends BaseController
{
/**
* @Route("/", name="accounting_reports_cipv_index", methods={"GET","POST"})
*/
public function index(Request $request): Response
{
$form = $this->createForm(CIPVSearchType::class);
$form->handleRequest($request);
$params['form'] = $form->createView();
//Parameters for default view
$params['excelSearchPath'] = "";
$params['tableSearchBy'] = "";
$params['parentMenu'] = 'Accounting Reports';
$params['viewTitle'] = 'CIPV Report';
$params['viewPluralTitle'] = 'CIPV Report';
$params['roleCreate'] = '';
$params['routeDataTable'] = 'accounting_reports_cipv_table';
$params['routeExcelReport'] = 'accounting_reports_cipv_excel_report';
$params['routeNew'] = '';
// $params['tableHeader'] = array("Amount", "Client Name", "Agent", "Supplier City", "Supplier",
// "Check-In","Check-Out","Confirmation #","Invoice #", "Agency",
// "Pending Comm...","Balance Due to...","Amount Due From client less Comm","Quote #");
// $params['tableColumnsDef'] = array("total", "clientFullName","agentName","supplierCity","supplierName",
// "checkIn","checkOut","confirmationNumber", "invoiceNumber", "customerAccountName",
// "pendingCommFromSupp", "balanceDueToSuppUSD","amountDueFromClientLessComm","quoteNumber","action");
$params['tableHeader'] = array("Name", "OLG Agent",
"Supplier City", "Supplier",
"Check-In","Check-Out",
"Confirmation #","Invoice #", "Agency", "Booking Status","Invoice Status","Canc. Policy Penalty Date","Canc. Policy");
$params['tableColumnsDef'] = array("clientFullName","agentName","supplierCity","supplierName",
"checkIn","checkOut","confirmationNumber", "invoiceNumber", "customerAccountName", 'reservationStatus', 'accountingStatus','cancellationPolicyPenaltyDate','cancellationPolicy' ,"action");
// $params['tableFooter'] = array('<th></th>', '<th colspan="11"></th>', '<th></th>','<th></th>','<th></th>');
$params['totalRows'] = 30;
$params['orderByColumn'] = 4;
$params['orderByColumnD'] = 'desc';
try {
if ($form->isSubmitted()) {
if (!$form->isValid()) {
/**
* @var FormErrorIterator $formErrors
* @var ConstraintViolation $cause
*/
$formErrors = $form->getErrors(true);
$errors = $formErrors->getChildren();
$cause = $errors->getCause();
throw new \Exception("Form is not valid. " . $errors->getMessage() . " " . $cause->getPropertyPath() . " " . $cause->getInvalidValue());
}
$search = $request->request->all();
if ($search && key_exists('cipv_search', $search)) {
unset($search['cipv_search']['_token']);
$search = $this->removeNullElemslOnTheArrayToSearchOnDoctrine($search);
$params = array_merge($params, $search);
$params['excelSearchPath'] = $this->excelSearchPath($search['cipv_search']);
$params['tableSearchBy'] = $search['cipv_search'];
} else {
unset($search);
}
}
} catch (\Exception $e) {
$request->getSession()->getFlashBag()->add('error', $e->getMessage());
}
// dd($params);
return $this->render('backOffice/accounting/report/CIPV/index.html.twig', $params);
}
/**
* TABLE AJAX GENERATOR
* @Route("/list/table/", name="accounting_reports_cipv_table",methods={"GET","POST"})
* @param Request $request
* @param \Symfony\Component\Asset\Packages $assetsManager
* @param QBInvoiceRepository $qbInvoiceRepository
* @param CoreApi $coreApi
* @return Response
* @Security("is_granted('IS_AUTHENTICATED_FULLY')")
*/
public function tableIndexAction(Request $request, \Symfony\Component\Asset\Packages $assetsManager, QBInvoiceRepository $qbInvoiceRepository,CoreApi $coreApi)
{
$result = $this->getDataTable($request, $assetsManager, $qbInvoiceRepository,true,$coreApi);
return new Response(json_encode($result), Response::HTTP_OK, ['content-type' => 'application/json']);
}
/**
* Excel Report
* @Route("/report/excel", name="accounting_reports_cipv_excel_report", methods={"GET"})
*/
public function excelReportAction(Request $request, \Symfony\Component\Asset\Packages $assetsManager, QBInvoiceRepository $qbInvoiceRepository,CoreApi $coreApi)
{
try {
$logo = $this->getParameter('ovn_logo_directory') . "/overseas-xpress-logo-scondary.png";
//Get report data
$reportInfo = $this->getDataTable($request, $assetsManager, $qbInvoiceRepository, false, $coreApi);
//reorder the date to match the columns
$resortedInfo = [];
$orderedReportColumns = array("clientFullName","agentName","supplierCity","supplierName",
"checkIn","checkOut","confirmationNumber", "invoiceNumber", "customerAccountName", 'reservationStatus', 'accountingStatus','cancellationPolicyPenaltyDate','cancellationPolicy');
foreach($reportInfo['data'] as $reportRow){
$orderedRow = array();
foreach($orderedReportColumns as $nextColumn){
$orderedRow[] = $reportRow[$nextColumn];
}
$resortedInfo[] = $orderedRow;
}
$reportInfo['data'] = $resortedInfo;
$headerTable=array("Name", "OLG Agent",
"Supplier City", "Supplier",
"Check-In","Check-Out",
"Confirmation #","Invoice #", "Agency", "Booking Status","Invoice Status","Canc. Policy Penalty Date","Canc. Policy");
$reportInfo = array_merge($reportInfo,['headerTable' => $headerTable]);
$reportName = "CIPV Report";
$today = new \DateTime('now');
$todayStr=$today->format('Y-M-d');
$filename = $reportName.' '.$todayStr. ".xlsx";
$spreadsheet = new ExportExcelBase(
reportInfo: $reportInfo,
reportName: $filename,
logo: $logo,
subject: $reportName,
category: 'Accounting Report',
description: 'Accounting Report '.$reportName
);
return $spreadsheet->create();
} catch (\Exception $e) {
//TODO HOW TO HANDLE THIS??
exit(0);
}
}
private function getDataTable(Request $request, \Symfony\Component\Asset\Packages $assetsManager, QBInvoiceRepository $qbInvoiceRepository, $isView = true,CoreApi $coreApi)
{
$countOfSkippedItems = 0;
$offset = $request->get('start');
$limit = $request->get('length');
//Default sort: Here add the columns
$sort = array("createdAt" => "desc");
$params=array();
//Search Fields: Add here all the fields to do the SQL search...
// $params['supplierCity'] = $request->get('supplierCity');
// $params['supplierName'] = $request->get('supplierName');
$params['confirmationNumber'] = $request->get('confirmationNumber');
//Range Types. Ex. "06/18/2021 - 06/23/2021"
$params['checkIn'] = $request->get('checkIn');
$params['checkOut'] = $request->get('checkOut');
$params['clientFullName'] = $request->get('clientFullName');
$params['accountingStatus'] = $request->get('accountingStatus');
$params['reservationStatus'] = $request->get('reservationStatus');
//Search Fields: Add here all the fields to do the SQL search...
$paramsInvoice['invoiceNumber'] = $request->get('invoiceNumber');
$paramsInvoice['isVoid'] = 0;
//Search Fields: Add here all the fields to do the SQL search...
$paramsUser['agentName'] = $request->get('agentName');
//End Search Fields
//Remove the null elems
$searchBy = $this->removeNullElemslOnTheArrayToSearchOnDoctrine($params);
$dateRanges = ['checkIn' => 0, 'checkOut' => 0];
$em = $this->getDoctrine()->getManager();
//----------------------------------------------------------------------------------------------------------------------
//Search by Invoice Number
$searchByInvoice = $this->removeNullElemslOnTheArrayToSearchOnDoctrine($paramsInvoice);
$rowsQBInvoice = null;
if ($searchByInvoice) {
//Do the search first by the invoice
$reportQueryBuilderInvoice = new ReportQueryBuilder($em, QBInvoice::class);
$different = null;
$like = array('invoiceNumber' => 0);
$extraSqlInvoice = null;
$rowsInvoiceResponse = $reportQueryBuilderInvoice->findByCriteria(
$searchByInvoice, array(), null, null, true, $like, $different,null,null,$extraSqlInvoice);
foreach ($rowsInvoiceResponse as $invoice) {
$rowsQBInvoice[] = $invoice->getId();
}
}
//----------------------------------------------------------------------------------------------------------------------
//Search by Agent Name
$searchByAgent = $this->removeNullElemslOnTheArrayToSearchOnDoctrine($paramsUser);
$rowsAgent = null;
if ($searchByAgent) {
$searchByAgent['id']=$searchByAgent['agentName'];
unset($searchByAgent['agentName']);
//Do the search
$reportQueryBuilderAgent = new ReportQueryBuilder($em, User::class);
$different = null;
$like = array();
$rowsAgentResponse = $reportQueryBuilderAgent->findByCriteria(
$searchByAgent, array(), null, null, true,
$like, $different,null,null);
foreach ($rowsAgentResponse as $user) {
$rowsAgent[] = $user->getId();
}
}
//----------------------------------------------------------------------------------------------------------------------
$different = null;
$like = array('confirmationNumber'=>0);
$andIn = [];
$extraSQL="";
if(key_exists('clientFullName',$searchBy)){
$searchBy['clientFullName']=strtolower($searchBy['clientFullName']);
$extraSQL ="(lower(n.clientName) like '%".$searchBy['clientFullName']."%' or lower(n.clientLastName) like '%".$searchBy['clientFullName']."%')";
unset($searchBy['clientFullName']);
}
if(key_exists('accountingStatus',$searchBy)){
$searchBy['accountingStatus']=strtolower($searchBy['accountingStatus']);
}
if(key_exists('reservationStatus',$searchBy)){
$searchBy['reservationStatus']=strtolower($searchBy['reservationStatus']);
}
if ($rowsQBInvoice) {
$invoiceList = implode(",",$rowsQBInvoice);
$searchBy['qbInvoice'] = $invoiceList;
$andIn = array_merge($andIn,array('qbInvoice' => $invoiceList));
}
$rowsQuote=null;
if ($rowsAgent) {
$searchByQuote['agent'] = implode(", ", $rowsAgent);
//Do the search
$reportQueryBuilderQuote = new ReportQueryBuilder($em, Quote::class);
$different = null;
$like = array();
$rowsQuoteResponse = $reportQueryBuilderQuote->findByCriteria(
$searchByQuote, array(), null, null, true,
$like, $different);
foreach ($rowsQuoteResponse as $quote) {
$rowsQuote[] = $quote->getId();
}
}
if ($rowsQuote) {
$quoteList = implode(",",$rowsQuote);
$searchBy['quote'] = $quoteList;
$andIn = array_merge($andIn,array('quote' => $quoteList));
}
//Do the search on QuoteItem
$reportQueryBuilder = new ReportQueryBuilder($em, QuoteItem::class);
//Get total
// $totalArray = $reportQueryBuilder->findByCriteriaTotalByColumns(array('retailTotal'),$searchBy, $like, $different, $andIn, $dateRanges,$extraSQL);
// $footerTotalQCAmount = $totalArray['retailTotal'];
// $footerTotalAmountDueFromClientLessComm =0; //TODO: CHECK WHERE THIS DATA COMES
// if($isView){
// $footerTotalQCAmount = '$'.number_format($totalArray['retailTotal'], 2, ',', '.');
// $footerTotalAmountDueFromClientLessComm ='$'.number_format($footerTotalAmountDueFromClientLessComm, 2, ',', '.');
// }
$recordsTotal = $reportQueryBuilder->findByCriteriaCount($searchBy, $like, $different, $andIn, $dateRanges,$extraSQL);
// if ($request->get('order')) {
//This corresponds with the columns on the view (header)
// $column =
// array("retailTotal", "clientName","agentName","supplierCity","supplierName",
// "checkIn","checkOut","confirmationNumber", "invoiceNumber", "customerAccountName",
// "pendingCommFromSupp", "balanceDueToSuppUSD","amountDueFromClientLessComm","quoteNumber");
//
// $search = $column[$request->get('order')[0]["column"]];
// $order = strtoupper($request->get('order')[0]["dir"]);
// $sort = array($search => $order);
// }
$inners=null;
if ($request->get('order')) {
//This corresponds with the columns on the view (header)
$column = array("clientFullName","agentName","supplierCity","supplierName",
"checkIn","checkOut","confirmationNumber", "invoiceNumber", "customerAccountName", "reservationStatus", 'accountingStatus','cancellationPolicyPenaltyDate','cancellationPolicy');
$search = $column[$request->get('order')[0]["column"]];//index of column
$order = strtoupper($request->get('order')[0]["dir"]);//asc or desc
$sort = [];
if(in_array($search,["clientFullName","agentName","invoiceNumber", "customerAccountName", "reservationStatus", "accountingStatus"])){
// if(in_array($search,["clientFullName","agentName","invoiceNumber", "customerAccountName", "reservationStatus", "accountingStatus","cancellationPolicyPenaltyDate","cancellationPolicy"])){
if ($search == "clientFullName") {
$sort = array("clientName" => $order);
}
if ($search == "agentName") {
$alias = 'j';
if ($inners) {
$alias .= count($inners);
}
$innerSingle["type"]='leftJoin';
$innerSingle["table"] = "quote";
$innerSingle["condition"] = $alias . ".id=n.quoteId'";
$inners[] = $innerSingle;
$alias2 = $alias.count($inners);
$innerSingle["type"]='leftJoin';
$innerSingle["table"] = $alias.".agent";
$innerSingle["noAddAlias"] = true;
$innerSingle["condition"] = $alias2 . ".id=j.agentId'";
$innerSingle["orderBy"]['field'] = $alias2 . '.firstName';
$innerSingle["orderBy"]['order'] = $order;
$inners[] = $innerSingle;
}
if ($search == "accountingStatus") {
$sort[] = array("accountingStatus" => $order);
}
if ($search == "reservationStatus") {
$sort[] = array("reservationStatus" => $order);
}
if ($search == "invoiceNumber") {
$alias = 'j';
if ($inners) {
$alias .= count($inners);
}
$innerSingle["type"]='leftJoin';
$innerSingle["table"] = "qbInvoice";
$innerSingle["condition"] = $alias . ".id=n.qbInvoice'";
$innerSingle["orderBy"]['field'] = $alias . '.invoiceNumber';
$innerSingle["orderBy"]['order'] = $order;
$inners[] = $innerSingle;
}
if ($search == "customerAccountName") {
$alias = 'j';
if ($inners) {
$alias .= count($inners);
}
$innerSingle["type"]='leftJoin';
$innerSingle["table"] = "quote";
$innerSingle["condition"] = $alias . ".id=n.quoteId'";
$inners[] = $innerSingle;
$alias2 = $alias.count($inners);
$innerSingle["type"]='leftJoin';
$innerSingle["table"] = $alias.".customerAccount";
$innerSingle["noAddAlias"] = true;
$innerSingle["condition"] = $alias2 . ".id=j.customerAccountId'";
$innerSingle["orderBy"]['field'] = $alias2 . '.name';
$innerSingle["orderBy"]['order'] = $order;
$inners[] = $innerSingle;
}
}
else{
//Order default
$sort = array($search => $order);
}
}
$data = array();
// The query to search by specifics fields. $limit, $offset
if($rows = $reportQueryBuilder->findByCriteria(
$searchBy, $sort, null, null, true, $like, $different, $andIn, $dateRanges,$extraSQL,$inners)){
$suppliers=$coreApi->getActivitySupplierList();
$hotels=$coreApi->getHotelList();
$penaltyStartDate = $penaltyEndDate = null;
if($request->get('penaltyDateRange') !== null && strlen($request->get('penaltyDateRange')>0)){
$dates = explode('-', $request->get('penaltyDateRange'));
$penaltyStartDate = \DateTime::createFromFormat('m/d/Y H:i:s', trim($dates[0])." 00:00:00");
$penaltyEndDate = \DateTime::createFromFormat('m/d/Y H:i:s', trim($dates[1])." 23:59:59");
}
/**
* @var $quoteItem QuoteItem
*/
foreach ($rows as $key => $quoteItem) {
//error_log(print_r($key,true).PHP_EOL,3, '/var/www/app/var/log/brian.log');
$supplier=$this->getSupplierInfo($suppliers, $hotels, $quoteItem);
$values = array();
$values["cancellationPolicyPenaltyDate"] = "";
$values["cancellationPolicy"] = "";
try {
if ($cancellationPolicy = $quoteItem->getCancellationPolicy()) {
if (!array_key_exists("penaltyDate", $cancellationPolicy)) {
$cancellationPolicy = reset($cancellationPolicy);
}
if(array_key_exists("penaltyDate", $cancellationPolicy) && $cancellationPolicy['penaltyDate'] == null ){
continue;
}
$values["cancellationPolicy"] = $quoteItem->makeCancellationPolicyLabel($cancellationPolicy);
if (is_array($cancellationPolicy) && key_exists('penaltyDate', $cancellationPolicy)) {
$penaltyDate = $cancellationPolicy['penaltyDate'];
if (is_string($cancellationPolicy['penaltyDate'])) {
$penaltyDate = new \DateTime($cancellationPolicy['penaltyDate']);
}
if($penaltyDate == null){
continue;
}
if ($penaltyStartDate != null && ($penaltyDate < $penaltyStartDate || $penaltyDate > $penaltyEndDate)) {
continue;
}
$values["cancellationPolicyPenaltyDate"] = $penaltyDate->format("Y-m-d");
}
} else if ($quoteItem->getCancellationPolicy() == null && $penaltyStartDate != null) {
continue;
}
} catch (\Exception $e) {
//error_log($e->getMessage().PHP_EOL,3, '/var/www/app/var/log/CIPV_error.log');
}
// $values["total"] = $quoteItem->getRetailTotal();
$values["clientFullName"] = $quoteItem->getClientFullName();
$values["agentName"] = $quoteItem->getQuote()->getCreatedBy()?$quoteItem->getQuote()->getCreatedBy()->getName():"";
$values["supplierCity"] = $supplier["cityName"];
$values["supplierName"] = $supplier["name"];
$values["checkIn"] = $quoteItem->getCheckIn() ? $quoteItem->getCheckIn()->format("Y-m-d") : "";
$values["checkOut"] = $quoteItem->getCheckOut() ? $quoteItem->getCheckOut()->format("Y-m-d") : "";
$values["confirmationNumber"] = $quoteItem->getConfirmationNumber();
$values["invoiceNumber"] = $quoteItem->getQbInvoice()?$quoteItem->getQbInvoice()->getInvoiceNumber():"";
$values["customerAccountName"] = $quoteItem->getQuote()->getCustomerAccount()?$quoteItem->getQuote()->getCustomerAccount()->getName():"";
$values["reservationStatus"] = $quoteItem->getReservationStatus();
$values["accountingStatus"] = $quoteItem->getAccountingStatus();
// $values["pendingCommFromSupp"] = 0;
// $values["balanceDueToSuppUSD"] = 0;
// $values["amountDueFromClientLessComm"] = 0;
// $values["quoteNumber"] = $quoteItem->getQuote()->getQuoteNumber();
if($isView){
// $values["total"] = '$'.number_format($values["total"], 2, ',', '.');
// $values["pendingCommFromSupp"] = '$'.number_format($values["pendingCommFromSupp"], 2, ',', '.');
// $values["balanceDueToSuppUSD"] = '$'.number_format($values["balanceDueToSuppUSD"], 2, ',', '.');
// $values["amountDueFromClientLessComm"] = '$'.number_format($values["amountDueFromClientLessComm"], 2, ',', '.');
$url = $this->generateUrl('quality_control_index', array('quoteItemId' => $quoteItem->getId()));
$values["action"] = '<a href="' . $url . '" class="text-blue-color-custom" title="Go to QC"><i class="fas fa-external-link-alt"></i></a>';
}
$data[] = $values;
}
}
$recordsTotal = count($data);
$data = array_slice($data,$offset,$limit);
return array(
"recordsTotal" => $recordsTotal,
"recordsFiltered" => $recordsTotal,
"data" => $data,
// "footerTotalQCAmount" => $footerTotalQCAmount,
// "footerTotalAmountDueFromClientLessComm" => $footerTotalAmountDueFromClientLessComm
);
}
}