src/ApplicationBundle/Controller/DashboardController.php line 4389

Open in your IDE?
  1. <?php
  2. namespace ApplicationBundle\Controller;
  3. use ApplicationBundle\Constants\GeneralConstant;
  4. use ApplicationBundle\Constants\HumanResourceConstant;
  5. use ApplicationBundle\Entity\DashboardWidget;
  6. use ApplicationBundle\Entity\Employee;
  7. use ApplicationBundle\Entity\EmployeeDetails;
  8. use ApplicationBundle\Entity\SysUser;
  9. use ApplicationBundle\Interfaces\SessionCheckInterface;
  10. use ApplicationBundle\Modules\Accounts\Accounts;
  11. use ApplicationBundle\Modules\Authentication\Constants\UserConstants; use ApplicationBundle\Modules\Api\Constants\ApiConstants;
  12. use ApplicationBundle\Modules\HumanResource\HumanResource;
  13. use ApplicationBundle\Modules\Inventory\Inventory;
  14. use ApplicationBundle\Modules\Purchase\Supplier;
  15. use ApplicationBundle\Modules\Sales\Client;
  16. use ApplicationBundle\Modules\System\MiscActions;
  17. use ApplicationBundle\Modules\System\System;
  18. use ApplicationBundle\Modules\User\Company;
  19. use ApplicationBundle\Modules\User\Position;
  20. use ApplicationBundle\Modules\User\Users;
  21. use CompanyGroupBundle\Entity\CompanyGroup;
  22. use CompanyGroupBundle\Entity\EntityApplicantApplicationList;
  23. use CompanyGroupBundle\Entity\EntityApplicantDetails;
  24. use CompanyGroupBundle\Entity\EntityTicket;
  25. use Symfony\Component\BrowserKit\Client as BrowserClientKit;
  26. use Symfony\Component\Debug\Exception\FlattenException;
  27. use Symfony\Component\HttpFoundation\JsonResponse;
  28. use Symfony\Component\HttpFoundation\Request;
  29. use Symfony\Component\HttpFoundation\Response;
  30. use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
  31. use Symfony\Component\Routing\Generator\UrlGenerator;
  32. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  33. class DashboardController extends GenericController implements SessionCheckInterface
  34. {
  35.     private function getPublicDocumentEntityManager($appId)
  36.     {
  37.         $emGoc $this->getDoctrine()->getManager('company_group');
  38.         $emGoc->getConnection()->connect();
  39.         $goc $emGoc
  40.             ->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup")
  41.             ->findOneBy(
  42.                 array(
  43.                     'appId' => $appId
  44.                 )
  45.             );
  46.         if (!$goc) {
  47.             return array(nullnull);
  48.         }
  49.         $connector $this->container->get('application_connector');
  50.         $connector->resetConnection(
  51.             'default',
  52.             $goc->getDbName(),
  53.             $goc->getDbUser(),
  54.             $goc->getDbPass(),
  55.             $goc->getDbHost(),
  56.             $reset true
  57.         );
  58.         return array($this->getDoctrine()->getManager(), $goc);
  59.     }
  60.     private function buildAllocationAwareTransactionSourceSql(array $filters = [])
  61.     {
  62.         $conn $this->getDoctrine()->getManager()->getConnection();
  63.         $conditions = [];
  64.         if (!empty($filters['document_type'])) {
  65.             $conditions[] = 't.document_type = ' . (int) $filters['document_type'];
  66.         }
  67.         if (!empty($filters['company_id'])) {
  68.             $conditions[] = 't.company_id = ' . (int) $filters['company_id'];
  69.         }
  70.         if (!empty($filters['start_date'])) {
  71.             $conditions[] = "t.ledger_hit_date >= " $conn->quote(date('Y-m-d'strtotime((string) $filters['start_date'])) . ' 00:00:00');
  72.         }
  73.         if (!empty($filters['end_date'])) {
  74.             $conditions[] = "t.ledger_hit_date <= " $conn->quote(date('Y-m-d'strtotime((string) $filters['end_date'])) . ' 23:59:59.999');
  75.         }
  76.         if (!empty($filters['client_head_ids'])) {
  77.             $conditions[] = 'td.accounts_head_id IN (' implode(','array_map('intval', (array) $filters['client_head_ids'])) . ')';
  78.         }
  79.         if (isset($filters['approved'])) {
  80.             $conditions[] = 't.approved = ' . (int) $filters['approved'];
  81.         } else {
  82.             $conditions[] = 't.approved = 1';
  83.         }
  84.         if (isset($filters['ledger_hit'])) {
  85.             $conditions[] = 't.ledger_hit = ' . (int) $filters['ledger_hit'];
  86.         } else {
  87.             $conditions[] = 't.ledger_hit = 1';
  88.         }
  89.         $whereSql = empty($conditions) ? '1=1' implode(' AND '$conditions);
  90.         return "(
  91.             SELECT td.transaction_details_id AS transaction_details_id,
  92.                    td.transaction_id,
  93.                    td.accounts_head_id,
  94.                    td.position,
  95.                    td.amount AS allocation_amount,
  96.                    td.ledger_hit_date,
  97.                    t.document_hash,
  98.                    t.company_id,
  99.                    t.document_type,
  100.                    1 AS has_allocation
  101.             FROM acc_transaction_details td
  102.             JOIN acc_transactions t ON t.transaction_id = td.transaction_id
  103.             JOIN transaction_detail_allocations tda ON tda.transaction_detail_id = td.transaction_details_id
  104.             WHERE " $whereSql "
  105.             UNION ALL
  106.             SELECT td.transaction_details_id AS transaction_details_id,
  107.                    td.transaction_id,
  108.                    td.accounts_head_id,
  109.                    td.position,
  110.                    td.amount AS allocation_amount,
  111.                    td.ledger_hit_date,
  112.                    t.document_hash,
  113.                    t.company_id,
  114.                    t.document_type,
  115.                    0 AS has_allocation
  116.             FROM acc_transaction_details td
  117.             JOIN acc_transactions t ON t.transaction_id = td.transaction_id
  118.             WHERE " $whereSql "
  119.               AND NOT EXISTS (
  120.                   SELECT 1
  121.                   FROM transaction_detail_allocations tda
  122.                   WHERE tda.transaction_detail_id = td.transaction_details_id
  123.               )
  124.         )";
  125.     }
  126.     public function doLoginAsAction(Request $request)
  127.     {
  128.         $session $request->getSession();
  129.         if ($request->isMethod('POST')) {
  130.             $session->set(UserConstants::USER_CURRENT_POSITION$request->request->get('position'));
  131.             $curr_position_id $request->request->get('position');
  132.             if ($session->get(UserConstants::USER_LOGIN_ID) != 0) {
  133.                 $loginID $this->get('user_module')->addUserLoginLog(
  134.                     $session->get(UserConstants::USER_ID),
  135.                     $request->server->get("REMOTE_ADDR"),
  136.                     $request->request->get('position'),
  137.                     '',
  138.                     '',
  139.                     '',
  140.                     $session->get(UserConstants::USER_LOGIN_ID)
  141.                 );
  142.             } else $loginID $this->get('user_module')->addUserLoginLog(
  143.                 $session->get(UserConstants::USER_ID),
  144.                 $request->server->get("REMOTE_ADDR"),
  145.                 $request->request->get('position'),
  146.                 '',
  147.                 '',
  148.                 '',
  149.                 0
  150.             );
  151.             if ($session->get(UserConstants::ALL_MODULE_ACCESS_FLAG) == 1)
  152.                 $prohibit_list_array = [];
  153.             else if ($curr_position_id != 0)
  154.                 $prohibit_list_array Position::getUserProhibitRouteArray($this->getDoctrine()->getManager(), $curr_position_id$session->get(UserConstants::USER_ID));
  155.             $session->set(UserConstants::USER_LOGIN_ID$loginID);
  156.             $session->set(UserConstants::USER_PROHIBIT_LISTjson_encode($prohibit_list_array));
  157.             $session->set(UserConstants::USER_ROUTE_LISTjson_encode(Position::getUserRouteArray($this->getDoctrine()->getManager(), $request->request->get('position'), $session->get(UserConstants::USER_ID))));
  158.             return $this->redirectToRoute("dashboard");
  159.         }
  160.         $message "";
  161.         $PositionList = array();
  162.         $PL json_decode($session->get(UserConstants::USER_POSITION_LIST), true);
  163.         foreach ($PL as &$positionID) {
  164.             $PositionList[$positionID] = Position::getPositionName($this->getDoctrine()->getManager(), $positionID);
  165.         }
  166.         return $this->render(
  167.             '@Authentication/pages/views/login_position.html.twig',
  168.             array(
  169.                 "message" => $message,
  170.                 'page_title' => 'Users',
  171.                 'position_list' => $PositionList
  172.             )
  173.         );
  174.     }
  175.     //    protected $twig;
  176.     //    protected $debug;
  177.     //
  178.     //    /**
  179.     //     * @param bool $debug Show error (false) or exception (true) pages by default
  180.     //     */
  181.     //    public function __construct(Environment $twig, $debug)
  182.     //    {
  183.     //        $this->twig = $twig;
  184.     //        $this->debug = $debug;
  185.     //    }
  186.     public function TestSmsAction(Request $request)
  187.     {
  188.         $em $this->getDoctrine()->getManager();
  189.         $session $request->getSession();
  190.         $em $this->getDoctrine()->getManager();
  191.         $userAppId $session->get('userAppId');
  192.         $companyId $session->get('userCompanyId');
  193.         if (GeneralConstant::SMS_ENABLED == 1) {
  194.             $company $em->getRepository('ApplicationBundle\\Entity\\Company')->findOneBy(
  195.                 array(
  196.                     'id' => $companyId///material
  197.                 )
  198.             );
  199.             if ($company->getSmsNotificationEnabled() == 1) {
  200.                 $smsData = [];
  201.                 $smsSettings json_decode($company->getSmsSettings(), true);
  202.                 if ($smsSettings != null && !empty($smsSettings)) {
  203.                     $method = isset($smsSettings['method']) ? $smsSettings['method'] : 'GET';
  204.                     $destination_url = isset($smsSettings['destination_url']) ? $smsSettings['destination_url'] : 'http://172.105.70.96:1234';
  205.                     $user_name = isset($smsSettings['user_name']) ? $smsSettings['user_name'] : 'test';
  206.                     $user_name_var = isset($smsSettings['user_name_var']) ? $smsSettings['user_name_var'] : 'Username';
  207.                     $password_var = isset($smsSettings['password_var']) ? $smsSettings['password_var'] : 'Password';
  208.                     $password = isset($smsSettings['password']) ? $smsSettings['password'] : '';
  209.                     $from_number_var = isset($smsSettings['from_number_var']) ? $smsSettings['from_number_var'] : 'From';
  210.                     $from_number = isset($smsSettings['from_number']) ? $smsSettings['from_number'] : '';
  211.                     $to_number_var = isset($smsSettings['to_number_var']) ? $smsSettings['to_number_var'] : 'To';
  212.                     $to_number $request->query->has('To') ? $request->query->get('To') : '01911706483';
  213.                     $text_var = isset($smsSettings['text_var']) ? $smsSettings['text_var'] : 'Message';
  214.                     $text $request->query->has('Message') ? $request->query->get('Message') : 'Test message';
  215.                     return new JsonResponse(System::sendSms(
  216.                         1,
  217.                         $method,
  218.                         $destination_url,
  219.                         $user_name_var,
  220.                         $user_name,
  221.                         $password_var,
  222.                         $password,
  223.                         $from_number_var,
  224.                         $from_number,
  225.                         $to_number_var,
  226.                         $to_number,
  227.                         $text_var,
  228.                         $text,
  229.                         $viewlink ""
  230.                     ));
  231.                 }
  232.             }
  233.             return new JsonResponse(
  234.                 [
  235.                     'companyId' => $companyId,
  236.                     'companyName' => $company->getName(),
  237.                     'enabled' => $company->getSmsNotificationEnabled(),
  238.                     //                    'smsSettings'=>$smsSettings
  239.                 ]
  240.             );
  241.         }
  242.         return new JsonResponse(
  243.             [
  244.                 'success' => false
  245.             ]
  246.         );
  247.     }
  248.     public function SyncCompanyProductToEntityProductAction(Request $request)
  249.     {
  250.         $gocId $request->query->has('gocId') ? $request->query->get('gocId') : 0;
  251.         $companyId $request->query->has('companyId') ? $request->query->get('companyId') : 1;
  252.         $genQueryArray = [];
  253.         $em_goc $this->getDoctrine()->getManager('company_group');
  254.         $em_goc->getConnection()->connect();
  255.         $em $this->getDoctrine()->getManager();
  256.         if ($request->query->has('forceRefresh')) {
  257.             $genQueryArray = [];
  258.             $query "
  259.             TRUNCATE `entity_brand_company`;
  260.             TRUNCATE `entity_item_group`;
  261.             TRUNCATE `entity_products`;
  262.             TRUNCATE `entity_product_categories`;
  263.             TRUNCATE `entity_product_specifications`;
  264.             TRUNCATE `entity_product_sub_categories`;
  265.             TRUNCATE `entity_specification_types`;
  266.             TRUNCATE `entity_unit_type`;
  267.             SELECT * from `entity_unit_type`;";
  268.             $stmt $em_goc->getConnection()->executeStatement($query);
  269.             
  270.             //            $Transactions = $stmt;
  271.             $get_kids_sql 'select * from acc_accounts_head where accounts_head_id not in (select distinct parent_id from acc_accounts_head) ;';
  272.             //UPDATE company SET sales=0, expense=0, payable=0 ,net_worth=0, monthly_growth=0 WHERE 1;';
  273.             $stmt $em->getConnection()->executeStatement($get_kids_sql);
  274.             
  275.             $query $stmt;
  276.         } else
  277.             $genQueryArray = ['globalId' => [0null]];
  278.         //1st step get all company item ids and then check for global id null if its null then the
  279.         // item group is not present in entity so add it
  280.         $company_wise_entities = [
  281.             'Currencies',
  282.             'UnitType',
  283.             'SpecType',
  284.             'BrandCompany',
  285.             'InvItemGroup',
  286.             'InvProductCategories',
  287.             'InvProductSubCategories',
  288.             'InvProductSpecifications',
  289.             'InvSpecificationTypes',
  290.             'InvProducts'
  291.         ];
  292.         $entity_wise_entities = [
  293.             'EntityCurrencies',
  294.             'EntityUnitType',
  295.             'EntitySpecType',
  296.             'EntityBrandCompany',
  297.             'EntityItemGroup',
  298.             'EntityProductCategories',
  299.             'EntityProductSubCategories',
  300.             'EntityProductSpecifications',
  301.             'EntitySpecificationTypes',
  302.             'EntityProducts'
  303.         ];
  304.         ////ITEMGROUPS
  305.         foreach ($company_wise_entities as $k => $cwa) {
  306.             $dataOnCompany $em
  307.                 ->getRepository("ApplicationBundle\\Entity\\" $cwa)
  308.                 ->findBy(
  309.                     $genQueryArray
  310.                 );
  311.             $match_cid_gid_itemgroup = [];  //[cid=>gid]
  312.             $match_cid_gid_itemgroup = [];  //[cid=>gid]
  313.             foreach ($dataOnCompany as $data) {
  314.                 $newClass "\\CompanyGroupBundle\\Entity\\" $entity_wise_entities[$k];
  315.                 $new = new $newClass();
  316.                 //                $new = new \CompanyGroupBundle\Entity\EntityItemGroup();
  317.                 $getters array_filter(get_class_methods($data), function ($method) {
  318.                     return 'get' === substr($method03);
  319.                 });
  320.                 foreach ($getters as $getter) {
  321.                     if ($getter == 'getGlobalId')
  322.                         continue;
  323.                     //                    if ($getter == 'getId')
  324.                     //                        continue;
  325.                     $setMethod str_replace('get''set'$getter);
  326.                     if (method_exists($new$setMethod))
  327.                         $new->{$setMethod}($data->{$getter}()); // `foo!`
  328.                 }
  329.                 $em_goc->persist($new);
  330.                 $em_goc->flush();
  331.                 if ($cwa == 'Currencies') {
  332.                     $data->setGlobalId($new->getCurrencyId());
  333.                     $new->setGlobalId($new->getCurrencyId());
  334.                 } else {
  335.                     $data->setGlobalId($new->getId());
  336.                     $new->setGlobalId($new->getId());
  337.                 }
  338.                 $em->flush();
  339.                 $em_goc->flush();
  340.                 //                $match_cid_gid_itemgroup[$data->getId()] = $new->getId();
  341.             }
  342.         }
  343.         return new JsonResponse(
  344.             array(
  345.                 'data' => $entity_wise_entities
  346.             )
  347.         );
  348.     }
  349.     public function SyncEntityProductToCompanyProductAction(Request $request)
  350.     {
  351.         $gocId $request->query->has('gocId') ? $request->query->get('gocId') : 0;
  352.         $companyId $request->query->has('companyId') ? $request->query->get('companyId') : 1;
  353.         $genQueryArray = [];
  354.         $em_goc $this->getDoctrine()->getManager('company_group');
  355.         $em_goc->getConnection()->connect();
  356.         $em $this->getDoctrine()->getManager();
  357.         if ($request->query->has('forceRefresh')) {
  358.             $genQueryArray = [];
  359.             $query "
  360.             TRUNCATE `brand_company`;
  361.             TRUNCATE `inv_item_group`;
  362.             TRUNCATE `inv_products`;
  363.             TRUNCATE `inv_product_categories`;
  364.             TRUNCATE `inv_product_specifications`;
  365.             TRUNCATE `inv_product_sub_categories`;
  366.             TRUNCATE `inv_specification_types`;
  367.             TRUNCATE `unit_type`;
  368.             SELECT * from `unit_type`;";
  369.             $stmt $em->getConnection()->executeStatement($query);
  370.             
  371.             //            $Transactions = $stmt;
  372.             $get_kids_sql 'select * from acc_accounts_head where accounts_head_id not in (select distinct parent_id from acc_accounts_head) ;';
  373.             //UPDATE company SET sales=0, expense=0, payable=0 ,net_worth=0, monthly_growth=0 WHERE 1;';
  374.             $stmt $em->getConnection()->fetchAllAssociative($get_kids_sql);
  375.             
  376.             $query $stmt;
  377.         } else {
  378.             //            $genQueryArray = ['globalId' => [0, null]];
  379.         }
  380.         //1st step get all company item ids and then check for global id null if its null then the
  381.         // item group is not present in entity so add it
  382.         $company_wise_entities = [
  383.             'Currencies',
  384.             'UnitType',
  385.             'SpecType',
  386.             'BrandCompany',
  387.             'InvItemGroup',
  388.             'InvProductCategories',
  389.             'InvProductSubCategories',
  390.             'InvProductSpecifications',
  391.             'InvSpecificationTypes',
  392.             'InvProducts'
  393.         ];
  394.         $entity_wise_entities = [
  395.             'EntityCurrencies',
  396.             'EntityUnitType',
  397.             'EntitySpecType',
  398.             'EntityBrandCompany',
  399.             'EntityItemGroup',
  400.             'EntityProductCategories',
  401.             'EntityProductSubCategories',
  402.             'EntityProductSpecifications',
  403.             'EntitySpecificationTypes',
  404.             'EntityProducts'
  405.         ];
  406.         foreach ($entity_wise_entities as $k => $ewa) {
  407.             $dataOnEntity $em_goc
  408.                 ->getRepository("CompanyGroupBundle\\Entity\\" $ewa)
  409.                 ->findBy(
  410.                     $genQueryArray
  411.                 );
  412.             $match_cid_gid_itemgroup = [];  //[cid=>gid]
  413.             $match_cid_gid_itemgroup = [];  //[cid=>gid]
  414.             foreach ($dataOnEntity as $data) {
  415.                 $newClass "\\ApplicationBundle\\Entity\\" $company_wise_entities[$k];
  416.                 $rec_exists 0;
  417.                 $new $em
  418.                     ->getRepository("ApplicationBundle\\Entity\\" $company_wise_entities[$k])
  419.                     ->findOneBy(
  420.                         array(
  421.                             'globalId' => $data->getGlobalId()
  422.                         )
  423.                     );
  424.                 if ($new) {
  425.                     $rec_exists 1;
  426.                 } else
  427.                     $new = new $newClass();
  428.                 //                $new = new \CompanyGroupBundle\Entity\EntityItemGroup();
  429.                 $getters array_filter(get_class_methods($data), function ($method) {
  430.                     return 'get' === substr($method03);
  431.                 });
  432.                 foreach ($getters as $getter) {
  433.                     if ($getter == 'getId')
  434.                         continue;
  435.                     $setMethod str_replace('get''set'$getter);
  436.                     if (method_exists($new$setMethod)) {
  437.                         if ($ewa == 'EntityProducts') {
  438.                             if ($rec_exists == 1) {
  439.                                 if (in_array($setMethod, [
  440.                                     'setPurchasePrice',
  441.                                     'setPurchasePriceWoExpense',
  442.                                     'setQty',
  443.                                     'setReorderLevel',
  444.                                     'setBookingQty',
  445.                                     'setNonSalesInvoicedQty',
  446.                                     'setNonSalesReturnReceivedQty',
  447.                                     'setBookingQty',
  448.                                     'setPhysicalQty',
  449.                                 ])) {
  450.                                     continue;
  451.                                 }
  452.                             }
  453.                         }
  454.                         $new->{$setMethod}($data->{$getter}()); // `foo!`
  455.                     }
  456.                 }
  457.                 if ($rec_exists == 0)
  458.                     $em->persist($new);
  459.                 $em->flush();
  460.                 if ($ewa == 'EntityCurrencies') {
  461.                     $new->setGlobalId($data->getCurrencyId());
  462.                 } else {
  463.                     $new->setGlobalId($data->getId());
  464.                 }
  465.                 $em->flush();
  466.                 //                $match_cid_gid_itemgroup[$data->getId()] = $new->getId();
  467.             }
  468.         }
  469.         return new JsonResponse(
  470.             array(
  471.                 'data' => $company_wise_entities
  472.             )
  473.         );
  474.     }
  475.     public function getAppGeneralDashboardDataAction(Request $request)
  476.     {
  477.         $dataFor 'client';
  478.         $personId 0;
  479.         if ($request->query->has('dataFor'))
  480.             $dataFor $request->query->get('dataFor');
  481.         if ($request->request->has('dataFor'))
  482.             $dataFor $request->request->get('dataFor');
  483.         if ($request->query->has('personId'))
  484.             $personId $request->query->get('personId');
  485.         if ($request->request->has('personId'))
  486.             $personId $request->request->get('personId');
  487.         if ($personId == 0)
  488.             return new JsonResponse(
  489.                 array(
  490.                     'success' => false,
  491.                     'data' => [],
  492.                 )
  493.             );
  494.         $session $request->getSession();
  495.         $em $this->getDoctrine()->getManager();
  496.         $userAppId $session->get('userAppId');
  497.         $companyId $session->get('userCompanyId');
  498.         $dataToConnectList = [];
  499.         $appIdList $session->get('appIdList');
  500.         $companyIdListByAppId $session->get('companyIdListByAppId');
  501.         $companyNameListByAppId $session->get('companyNameListByAppId');
  502.         $companyImageListByAppId $session->get('companyImageListByAppId');
  503.         $gocEnabled 0;
  504.         if ($this->container->hasParameter('entity_group_enabled'))
  505.             $gocEnabled $this->container->getParameter('entity_group_enabled');
  506.         $connector $this->container->get('application_connector');
  507.         $connector->resetConnection(
  508.             'default',
  509.             $session->get('gocDbName'),
  510.             $session->get('gocDbUser'),
  511.             $session->get('gocDbPass'),
  512.             $session->get('gocDbHost'),
  513.             $reset true
  514.         );
  515.         $em $this->getDoctrine()->getManager();
  516.         $data = [];
  517.         if ($dataFor == 'client') {
  518.             //get order_count, order_amount,bill_count, bill_amount, collection_amount, due_amount
  519.             $data = [
  520.                 'order_count' => 0,
  521.                 'order_amount' => 0,
  522.                 'invoice_count' => 0,
  523.                 'invoice_amount' => 0,
  524.                 'collection_amount' => 0,
  525.                 'due_amount' => 0,
  526.                 'client_count' => 1,
  527.             ];
  528.             $clientIds = [$personId];
  529.             //order count and amount
  530.             $get_sql "SELECT count(sales_order_id) order_count, sum(so_amount) order_amount
  531. FROM sales_order WHERE approved=1 and sales_order.company_id=" $companyId "  and sales_order.client_id in (" implode(','$clientIds) . ");";
  532.             $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  533.             
  534.             $entries $stmt;
  535.             if (!empty($entries)) {
  536.                 $data['order_count'] = $entries[0]['order_count'];
  537.                 $data['order_amount'] = $entries[0]['order_amount'];
  538.             }
  539.             //invoice
  540.             $get_sql "SELECT count(sales_invoice_id) invoice_count, sum(invoice_amount) invoice_amount
  541. FROM sales_invoice WHERE approved=1 and sales_invoice.company_id=" $companyId "  and sales_invoice.client_id in (" implode(','$clientIds) . ");";
  542.             $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  543.             
  544.             $entries $stmt;
  545.             if (!empty($entries)) {
  546.                 $data['invoice_count'] = $entries[0]['invoice_count'];
  547.                 $data['invoice_amount'] = $entries[0]['invoice_amount'];
  548.             }
  549.             //now collection
  550.             $allocationSourceSql $this->buildAllocationAwareTransactionSourceSql(array(
  551.                 'document_type' => 6,
  552.                 'company_id' => $companyId,
  553.                 'start_date' => null,
  554.                 'end_date' => null,
  555.                 'approved' => 1,
  556.                 'ledger_hit' => 1,
  557.             ));
  558.             $get_sql "SELECT SUM(CASE WHEN alloc_rows.position = 'cr' THEN alloc_rows.allocation_amount ELSE 0 END) positive_amount,
  559. SUM(CASE WHEN alloc_rows.position = 'dr' THEN alloc_rows.allocation_amount ELSE 0 END) negative_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type, acc_clients.client_due, acc_clients.client_id
  560.  FROM " $allocationSourceSql " alloc_rows
  561.    join acc_clients on acc_clients.accounts_head_id=alloc_rows.accounts_head_id or acc_clients.advance_head_id=alloc_rows.accounts_head_id
  562.   join client_type on acc_clients.type=client_type.client_type_id
  563.   WHERE acc_clients.company_id=" $companyId " and acc_clients.client_id in (" implode(','$clientIds) . ") ";
  564.             $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  565.             
  566.             $entries $stmt;
  567.             $clientTypes = [];
  568.             $clientTypeNames = [];
  569.             $alreadyCids = [];
  570.             foreach ($entries as $entry) {
  571.                 $data['collection_amount'] += (* ($entry['positive_amount'] - $entry['negative_amount']));
  572.                 if (!in_array($entry['client_id'], $alreadyCids)) {
  573.                     $data['due_amount'] += ($entry['client_due']);
  574.                     $alreadyCids[] = $entry['client_id'];
  575.                 }
  576.             }
  577.         }
  578.         if ($dataFor == 'sales_user') {
  579.             //get order_count, order_amount,bill_count, bill_amount, collection_amount, due_amount
  580.             $data = [
  581.                 'order_count' => 0,
  582.                 'order_amount' => 0,
  583.                 'invoice_count' => 0,
  584.                 'invoice_amount' => 0,
  585.                 'collection_amount' => 0,
  586.                 'due_amount' => 0,
  587.                 'client_count' => 0,
  588.             ];
  589.             $clientIds = [];
  590.             $salesPersonIds = [];
  591.             $allSalespersonFlag 1//temp
  592.             if ($allSalespersonFlag != 1) {
  593.                 $query $em->getRepository('ApplicationBundle\\Entity\\Employee')->findOneBy(
  594.                     array(
  595.                         'userId' => $personId
  596.                     )
  597.                 );
  598.                 if ($query)
  599.                     $salesPersonIds[] = $query->getEmployeeId();
  600.             }
  601.             //Client count
  602.             $get_sql "SELECT  client_id
  603. FROM acc_clients WHERE  acc_clients.company_id=" $companyId " ";
  604.             if ($allSalespersonFlag != 1)
  605.                 $get_sql .= " and acc_clients.sales_person_id in (" implode(','$salesPersonIds) . ");";
  606.             else
  607.                 $get_sql .= " ;";
  608.             $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  609.             
  610.             $entries $stmt;
  611.             if (!empty($entries)) {
  612.                 foreach ($entries as $entry) {
  613.                     $data['client_count'] += 1;
  614.                     $clientIds[] = $entry['client_id'];
  615.                 }
  616.             }
  617.             //order count and amount
  618.             if (!empty($clientIds)) {
  619.                 $get_sql "SELECT count(sales_order_id) order_count, sum(so_amount) order_amount
  620. FROM sales_order WHERE approved=1 and sales_order.company_id=" $companyId "  and sales_order.client_id in (" implode(','$clientIds) . ");";
  621.                 $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  622.                 
  623.                 $entries $stmt;
  624.                 if (!empty($entries)) {
  625.                     $data['order_count'] = $entries[0]['order_count'];
  626.                     $data['order_amount'] = $entries[0]['order_amount'];
  627.                 }
  628.                 //invoice
  629.                 $get_sql "SELECT count(sales_invoice_id) invoice_count, sum(invoice_amount) invoice_amount
  630. FROM sales_invoice WHERE approved=1 and sales_invoice.company_id=" $companyId "  and sales_invoice.client_id in (" implode(','$clientIds) . ");";
  631.                 $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  632.                 
  633.                 $entries $stmt;
  634.                 if (!empty($entries)) {
  635.                     $data['invoice_count'] = $entries[0]['invoice_count'];
  636.                     $data['invoice_amount'] = $entries[0]['invoice_amount'];
  637.                 }
  638.                 //now collection
  639.                 $allocationSourceSql $this->buildAllocationAwareTransactionSourceSql(array(
  640.                     'document_type' => 6,
  641.                     'approved' => 1,
  642.                     'ledger_hit' => 1,
  643.                 ));
  644.                 $get_sql "SELECT SUM(CASE WHEN alloc_rows.position = 'cr' THEN alloc_rows.allocation_amount ELSE 0 END) positive_amount,
  645. SUM(CASE WHEN alloc_rows.position = 'dr' THEN alloc_rows.allocation_amount ELSE 0 END) negative_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type, acc_clients.client_due, acc_clients.client_id
  646.  FROM " $allocationSourceSql " alloc_rows
  647.    join acc_clients on acc_clients.accounts_head_id=alloc_rows.accounts_head_id or acc_clients.advance_head_id=alloc_rows.accounts_head_id
  648.   join client_type on acc_clients.type=client_type.client_type_id
  649.   WHERE acc_clients.company_id=" $companyId " and acc_clients.client_id in (" implode(','$clientIds) . ") ";
  650.                 $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  651.                 
  652.                 $entries $stmt;
  653.                 $clientTypes = [];
  654.                 $clientTypeNames = [];
  655.                 $alreadyCids = [];
  656.                 foreach ($entries as $entry) {
  657.                     $data['collection_amount'] += (* ($entry['positive_amount'] - $entry['negative_amount']));
  658.                     if (!in_array($entry['client_id'], $alreadyCids)) {
  659.                         $data['due_amount'] += ($entry['client_due']);
  660.                         $alreadyCids[] = $entry['client_id'];
  661.                     }
  662.                 }
  663.             }
  664.         }
  665.         if ($dataFor == 'user') {
  666.             //get order_count, payment_amount,
  667.         }
  668.         return new JsonResponse(
  669.             array(
  670.                 'success' => true,
  671.                 'data' => $data,
  672.                 'dataFor' => $dataFor,
  673.                 'personId' => $personId,
  674.             )
  675.         );
  676.     }
  677.     public function getManagementDashboardDataAction(Request $request)
  678.     {
  679.         $session $request->getSession();
  680.         $data = array(
  681.             'cash_and_bank_position' => [],
  682.             'order_and_client_count' => [],
  683.             'expense_vs_revenue' => [],
  684.             'receivable_position' => [],
  685.             'payable_position' => [],
  686.             'expense_position' => [],
  687.             'inventory_position' => [],
  688.             'production_position' => [],
  689.             'sales_position' => [],
  690.             'collection_position' => [],
  691.             'market_return_position' => [],
  692.             'top_selling_item_position' => [],
  693.             'top_selling_client_position' => [],
  694.         );
  695.         $em $this->getDoctrine()->getManager();
  696.         $reportsToGet = [
  697.             'cash_and_bank_position',
  698.             'order_and_client_count',
  699.             'expense_vs_revenue',
  700.             'receivable_position',
  701.             'payable_position',
  702.             'expense_position',
  703.             'inventory_position',
  704.             'production_position',
  705.             'sales_position',
  706.             'collection_position',
  707.             'market_return_position',
  708.             'top_selling_item_position',
  709.             'top_selling_client_position',
  710.         ];
  711.         //        $periodType='day'; //day,month,week,year,quarter etc
  712.         $periodType 'month'//day,month,week,year,quarter etc
  713.         if ($request->request->has('reportsToGet')) {
  714.             if ($request->request->get('reportsToGet') != 'all' && !in_array('all'$request->request->get('reportsToGet'))) {
  715.                 $reportsToGet $request->request->get('reportsToGet');
  716.             }
  717.         }
  718.         if ($request->request->has('periodType')) {
  719.             $periodType $request->request->get('periodType');
  720.         }
  721.         $userAppId $session->get('userAppId');
  722.         $dataToConnectList = [];
  723.         $appIdList $session->get('appIdList');
  724.         $companyIdListByAppId $session->get('companyIdListByAppId');
  725.         $companyNameListByAppId $session->get('companyNameListByAppId');
  726.         $companyImageListByAppId $session->get('companyImageListByAppId');
  727.         $gocEnabled 0;
  728.         if ($this->container->hasParameter('entity_group_enabled'))
  729.             $gocEnabled $this->container->getParameter('entity_group_enabled');
  730.         $thisPeriodStartDate '';
  731.         $lastPeriodStartDate '';
  732.         $thisPeriodEndDate '';
  733.         $lastPeriodEndDate '';
  734.         $today = new \DateTime();
  735.         if ($periodType == 'month') {
  736.             $thisPeriodEndDate $today->format('Y-m-d');
  737.             $thisPeriodStartDate $today->format('Y-m-') . '01';
  738.             $currDate = new \DateTime($thisPeriodStartDate);
  739.             $currDate->modify('-1 day');
  740.             $lastPeriodEndDate $currDate->format('Y-m-d');
  741.             $lastPeriodStartDate $currDate->format('Y-m-') . '01';
  742.         } else if ($periodType == 'week') {
  743.             $thisPeriodEndDate $today->format('Y-m-d');
  744.             $thisWeekStartDate date("Y-m-d"strtotime("previous saturday"));
  745.             $thisPeriodStartDate date("Y-m-d"strtotime("previous saturday"));
  746.             $currDate = new \DateTime($thisPeriodStartDate);
  747.             $currDate->modify('-1 day');
  748.             $lastPeriodEndDate $currDate->format('Y-m-d');
  749.             $currDate->modify('-6 day');
  750.             $lastPeriodStartDate $currDate->format('Y-m-d');
  751.         } else if ($periodType == 'quarter') {
  752.             $thisPeriodEndDate $today->format('Y-m-d');
  753.             $thisWeekStartDate date("Y-m-d"strtotime("previous saturday"));
  754.             $thisPeriodStartDate date("Y-m-d"strtotime("previous saturday"));
  755.             $currDate = new \DateTime($thisPeriodStartDate);
  756.             $currDate->modify('-1 day');
  757.             $lastPeriodEndDate $currDate->format('Y-m-d');
  758.             $currDate->modify('-6 day');
  759.             $lastPeriodStartDate $currDate->format('Y-m-d');
  760.         } else if ($periodType == 'year') {
  761.             $thisPeriodEndDate $today->format('Y-m-d');
  762.             //            $thisWeekStartDate = date("Y-m-d", strtotime("previous saturday"));
  763.             $thisPeriodStartDate = ($today->format('Y')) . '-01-01';
  764.             $currDate = new \DateTime($thisPeriodStartDate);
  765.             $currDate->modify('-1 day');
  766.             $lastPeriodEndDate $currDate->format('Y-m-d');
  767.             $lastPeriodStartDate = ($currDate->format('Y')) . '-01-01';;
  768.         }
  769.         $companyListData = [];
  770.         foreach ($appIdList as $appId) {
  771.             //queryonly if mor ethan one app id
  772.             $skip 0;
  773.             if ($appId == $userAppId) {
  774.                 $connector $this->container->get('application_connector');
  775.                 $connector->resetConnection(
  776.                     'default',
  777.                     $session->get('gocDbName'),
  778.                     $session->get('gocDbUser'),
  779.                     $session->get('gocDbPass'),
  780.                     $session->get('gocDbHost'),
  781.                     $reset true
  782.                 );
  783.                 $em $this->getDoctrine()->getManager();
  784.             } else {
  785.                 $dataToConnect System::changeDoctrineManagerByAppId($this->getDoctrine()->getManager('company_group'), $gocEnabled$appId);
  786.                 $dataToConnectList[] = $dataToConnect;
  787.                 if (!empty($dataToConnect)) {
  788.                     $connector $this->container->get('application_connector');
  789.                     $connector->resetConnection(
  790.                         'default',
  791.                         $dataToConnect['dbName'],
  792.                         $dataToConnect['dbUser'],
  793.                         $dataToConnect['dbPass'],
  794.                         $dataToConnect['dbHost'],
  795.                         $reset true
  796.                     );
  797.                     $em $this->getDoctrine()->getManager();
  798.                 } else {
  799.                     $skip 1;
  800.                 }
  801.             }
  802.             if ($skip == 1)
  803.                 continue;
  804.             //                $companyListData[] = Company::getCompanyListWithImage($em);
  805.             //                $get_sql = "SELECT * FROM company ";
  806.             //                $stmt = $em->getConnection()->executeStatement($get_sql);
  807.             //                
  808.             //                $entries = $stmt;
  809.             //                $companyListData[] = $entries;
  810.             //                foreach ($companyIdListByAppId as $app_company_index)
  811.             if (isset($companyIdListByAppId[$appId])) {
  812.                 foreach ($companyIdListByAppId[$appId] as $app_company_index) {
  813.                     //exp vs rev
  814.                     if (in_array('expense_vs_revenue'$reportsToGet)) {
  815.                         $acHeadList = [];
  816.                         $companyId explode('_'$app_company_index)[1];
  817.                         $acHeadDataById = [];
  818.                         $thisBalanceDataByAcHead = [];
  819.                         $lastBalanceDataByAcHead = [];
  820.                         $mon_names = ["""January""February""March""April""May""June""July""August""September""October""November""December"];
  821.                         $limit 12;
  822.                         $get_kids_sql "SELECT expense, revenue, `date` summ_date
  823.                           FROM monthly_summary
  824.                             where monthly_summary.company_id=$companyId
  825.                             AND ( monthly_summary.branch_id=0 or monthly_summary.branch_id is null) ";
  826.                         //                               GROUP BY monthly_summary.`date`
  827.                         $get_kids_sql .= " ORDER BY monthly_summary.`date` DESC  limit " $limit;
  828.                         $stmt $em->getConnection()->fetchAllAssociative($get_kids_sql);
  829.                         
  830.                         $pl $stmt;
  831.                         $curr_date = new \DateTime();
  832.                         $curr_mon = ($curr_date->format('m'));
  833.                         $curr_year = ($curr_date->format('Y'));
  834.                         $object_list = [];
  835.                         $debug_list = [];
  836.                         $list = [];
  837.                         $timeStampList = [];
  838.                         //        $first
  839.                         foreach ($pl as $key => $entry) {
  840.                             $qryDate = new \DateTime($entry['summ_date']);
  841.                             $qrMon $qryDate->format('m');;
  842.                             $qrYr $qryDate->format('Y');;
  843.                             $object_list[$qrYr '_' $qrMon] = $entry;
  844.                         }
  845.                         for ($k 0$k 11$k++) {
  846.                             $debug_list[$k] = $curr_year '_' $curr_mon;
  847.                             $currTimeStamp strtotime($curr_year "-" $curr_mon '-1');
  848.                             $currTimeStampMili $currTimeStamp 1000;
  849.                             $cashAddition 0;
  850.                             $bankAddition 0;
  851.                             if (isset($object_list[$curr_year '_' $curr_mon])) {
  852.                                 $entry $object_list[$curr_year '_' $curr_mon];
  853.                                 $list['monthList'][] = $mon_names[$curr_mon];
  854.                                 $list['revenue'][] = round($entry['revenue']);
  855.                                 $list['tsCommaRevenue'][] = [$currTimeStampMiliround($entry['revenue'])];
  856.                                 $list['expense'][] = round($entry['expense']);
  857.                                 $list['tsCommaExpense'][] = [$currTimeStampMiliround($entry['expense'])];
  858.                             } else {
  859.                                 $list['monthList'][] = $mon_names[($curr_mon)];
  860.                                 $list['revenue'][] = 0;
  861.                                 $list['expense'][] = 0;
  862.                                 $list['tsCommaRevenue'][] = [$currTimeStampMili0];
  863.                                 $list['tsCommaExpense'][] = [$currTimeStampMili0];
  864.                             }
  865.                             $curr_mon--;
  866.                             if ($curr_mon <= 0) {
  867.                                 $curr_mon 12;
  868.                                 $curr_year--;
  869.                             }
  870.                             //new end
  871.                         }
  872.                         $data['expense_vs_revenue'][$app_company_index] = $list;
  873.                     }
  874.                     //cash and bank position
  875.                     if (in_array('cash_and_bank_position'$reportsToGet)) {
  876.                         $acHeadList = [];
  877.                         $companyId explode('_'$app_company_index)[1];
  878.                         $acHeadDataById = [];
  879.                         $thisBalanceDataByAcHead = [];
  880.                         $lastBalanceDataByAcHead = [];
  881.                         $bank_settings $em->getRepository('ApplicationBundle\\Entity\\AccSettings')->findOneBy(array(
  882.                             'name' => 'bank_parents',
  883.                             //                        'CompanyId'=>$companyId
  884.                         ));
  885.                         $bank_id_list = [];
  886.                         if ($bank_settings)
  887.                             $bank_id_list json_decode($bank_settings->getData());
  888.                         $bank_child_id_list = [];
  889.                         $likeQuery '';
  890.                         foreach ($bank_id_list as $p) {
  891.                             $likeQuery .= "OR path_tree like '%/" $p "%/' ";
  892.                         }
  893.                         $get_sql "SELECT * FROM acc_accounts_head WHERE acc_accounts_head.company_id=" $companyId " AND  accounts_head_id not in (select distinct parent_id from acc_accounts_head)and (1=0 " $likeQuery ") ";
  894.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  895.                         
  896.                         $entries $stmt;
  897.                         foreach ($entries as $entry) {
  898.                             $has_payments 1;
  899.                             $bank_child_id_list[] = $entry['accounts_head_id'];
  900.                             $acHeadList[] = $entry['accounts_head_id'];
  901.                             $acHeadDataById[$entry['accounts_head_id']]['name'] = $entry['name'];
  902.                         }
  903.                         $cash_settings $em->getRepository('ApplicationBundle\\Entity\\AccSettings')->findOneBy(array(
  904.                             'name' => 'cash_parents'
  905.                             //                        'CompanyId'=>$companyId
  906.                         ));
  907.                         $cash_id_list = [];
  908.                         if ($cash_settings)
  909.                             $cash_id_list json_decode($cash_settings->getData());
  910.                         $cash_child_id_list = [];
  911.                         $likeQuery '';
  912.                         foreach ($cash_id_list as $p) {
  913.                             $likeQuery .= "OR path_tree like '%/" $p "%/' ";
  914.                         }
  915.                         $get_sql "SELECT * FROM acc_accounts_head WHERE acc_accounts_head.company_id=" $companyId " AND accounts_head_id not in (select distinct parent_id from acc_accounts_head)and (1=0 " $likeQuery ") ";
  916.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  917.                         
  918.                         $entries $stmt;
  919.                         foreach ($entries as $entry) {
  920.                             $has_payments 1;
  921.                             $cash_child_id_list[] = $entry['accounts_head_id'];
  922.                             $acHeadList[] = $entry['accounts_head_id'];
  923.                             $acHeadDataById[$entry['accounts_head_id']]['name'] = $entry['name'];
  924.                         }
  925.                         $thisBalance_data Accounts::GetBalanceOnDate($em$thisPeriodEndDate, []);
  926.                         $lastBalance_data Accounts::GetBalanceOnDate($em$lastPeriodEndDate, []);
  927.                         foreach ($acHeadList as $acHead) {
  928.                             $thisBalanceDataByAcHead[$acHead]['balance'] = $thisBalance_data[$acHead]['end_balance']['balance'];
  929.                             $lastBalanceDataByAcHead[$acHead]['balance'] = $lastBalance_data[$acHead]['end_balance']['balance'];
  930.                         }
  931.                         $thisReportData = array(
  932.                             'accountsHeadList' => $acHeadList,
  933.                             'acHeadDataById' => $acHeadDataById,
  934.                             'cash_child_id_list' => $cash_child_id_list,
  935.                             'bank_child_id_list' => $bank_child_id_list,
  936.                             'thisBalanceDataByAcHead' => $thisBalanceDataByAcHead,
  937.                             'lastBalanceDataByAcHead' => $lastBalanceDataByAcHead,
  938.                         );
  939.                         $data['cash_and_bank_position'][$app_company_index] = $thisReportData;
  940.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  941.                     }
  942.                     //Expense Position
  943.                     if (in_array('expense_position'$reportsToGet)) {
  944.                         $acHeadList = [];
  945.                         $companyId explode('_'$app_company_index)[1];
  946.                         $acHeadDataById = [];
  947.                         $thisBalanceDataByAcHead = [];
  948.                         $lastBalanceDataByAcHead = [];
  949.                         $get_sql "SELECT * FROM acc_accounts_head WHERE acc_accounts_head.company_id=" $companyId "
  950.                         AND acc_accounts_head.head_level= 2 ";
  951.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  952.                         
  953.                         $entries $stmt;
  954.                         foreach ($entries as $entry) {
  955.                             $has_payments 1;
  956.                             $cash_child_id_list[] = $entry['accounts_head_id'];
  957.                             $acHeadList[] = $entry['accounts_head_id'];
  958.                             $acHeadDataById[$entry['accounts_head_id']]['name'] = $entry['name'];
  959.                         }
  960.                         $thisBalance_data Accounts::GetPeriodicDataByType($em$type 'exp'$level_to_group_by 1$parent_id_list = [], $expand_level 1$thisPeriodStartDate$thisPeriodEndDate'_during_', [], [], [], false);
  961.                         $lastBalance_data Accounts::GetPeriodicDataByType($em$type 'exp'$level_to_group_by 1$parent_id_list = [], $expand_level 1$lastPeriodStartDate$lastPeriodEndDate'_during_', [], [], [], false);
  962.                         $skipHeadIds = [];
  963.                         foreach ($thisBalance_data as $parentHead => $balanceData) {
  964.                             foreach ($balanceData['data'] as $acHead => $headData) {
  965.                                 if (!in_array($acHead$acHeadList))
  966.                                     continue;
  967.                                 $thisBalanceDataByAcHead[$acHead]['balance'] = $headData['head_balance'];
  968.                                 if (isset($lastBalance_data[$parentHead])) {
  969.                                     if (isset($lastBalance_data[$parentHead]['data'][$acHead]))
  970.                                         $lastBalanceDataByAcHead[$acHead]['balance'] = $lastBalance_data[$parentHead]['data'][$acHead]['head_balance'];
  971.                                     else
  972.                                         $lastBalanceDataByAcHead[$acHead]['balance'] = 0;
  973.                                 } else
  974.                                     $lastBalanceDataByAcHead[$acHead]['balance'] = 0;
  975.                                 $skipHeadIds[] = $acHead;
  976.                             }
  977.                         }
  978.                         foreach ($lastBalance_data as $parentHead => $balanceData) {
  979.                             foreach ($balanceData['data'] as $acHead => $headData) {
  980.                                 if (in_array($acHead$skipHeadIds))
  981.                                     continue;
  982.                                 if (!in_array($acHead$acHeadList))
  983.                                     continue;
  984.                                 $lastBalanceDataByAcHead[$acHead]['balance'] = $headData['head_balance'];
  985.                                 if (isset($thisBalance_data[$parentHead])) {
  986.                                     if (isset($thisBalance_data[$parentHead]['data'][$acHead]))
  987.                                         $thisBalanceDataByAcHead[$acHead]['balance'] = $thisBalance_data[$parentHead]['data'][$acHead]['head_balance'];
  988.                                     else
  989.                                         $thisBalanceDataByAcHead[$acHead]['balance'] = 0;
  990.                                 } else
  991.                                     $thisBalanceDataByAcHead[$acHead]['balance'] = 0;
  992.                                 $skipHeadIds[] = $acHead;
  993.                             }
  994.                         }
  995.                         $thisReportData = array(
  996.                             'accountsHeadList' => $acHeadList,
  997.                             //                            'thisBalance_data' => $thisBalance_data,
  998.                             'confirmedHeadList' => $skipHeadIds,
  999.                             'acHeadDataById' => $acHeadDataById,
  1000.                             'thisBalanceDataByAcHead' => $thisBalanceDataByAcHead,
  1001.                             'lastBalanceDataByAcHead' => $lastBalanceDataByAcHead,
  1002.                         );
  1003.                         $data['expense_position'][$app_company_index] = $thisReportData;
  1004.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1005.                     }
  1006.                     //Payable Position
  1007.                     if (in_array('payable_position'$reportsToGet)) {
  1008.                         $acHeadList = [];
  1009.                         $companyId explode('_'$app_company_index)[1];
  1010.                         $acHeadDataById = [];
  1011.                         $thisBalanceDataByAcHead = [];
  1012.                         $lastBalanceDataByAcHead = [];
  1013.                         $filter_settings $em->getRepository('ApplicationBundle\\Entity\\AccSettings')->findOneBy(array(
  1014.                             'name' => 'payable_parents',
  1015.                             //                        'CompanyId'=>$companyId
  1016.                         ));
  1017.                         $filter_head_parents_id_list = [];
  1018.                         if ($filter_settings)
  1019.                             $filter_head_parents_id_list json_decode($filter_settings->getData());
  1020.                         $likeQuery '';
  1021.                         foreach ($filter_head_parents_id_list as $p) {
  1022.                             $likeQuery .= "OR path_tree like '%/" $p "%/' ";
  1023.                         }
  1024.                         $get_sql "SELECT * FROM acc_accounts_head WHERE acc_accounts_head.company_id=" $companyId "
  1025.                          and (1=0 " $likeQuery ") ";
  1026.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1027.                         
  1028.                         $entries $stmt;
  1029.                         foreach ($entries as $entry) {
  1030.                             $has_payments 1;
  1031.                             $acHeadList[] = $entry['accounts_head_id'];
  1032.                             $acHeadDataById[$entry['accounts_head_id']]['name'] = $entry['name'];
  1033.                         }
  1034.                         //                        $get_sql = "SELECT * FROM acc_accounts_head WHERE acc_accounts_head.company_id=" . $companyId . "
  1035.                         //                        AND acc_accounts_head.head_level= 2 and acc_accounts_head.type='lib'";
  1036.                         //
  1037.                         //                        $stmt = $em->getConnection()->executeStatement($get_sql);
  1038.                         //                        
  1039.                         //                        $entries = $stmt;
  1040.                         //
  1041.                         //                        foreach ($entries as $entry) {
  1042.                         //                            $has_payments = 1;
  1043.                         //                            $cash_child_id_list[] = $entry['accounts_head_id'];
  1044.                         //                            $acHeadList[] = $entry['accounts_head_id'];
  1045.                         //                            $acHeadDataById[$entry['accounts_head_id']]['name'] = $entry['name'];
  1046.                         //                        }
  1047.                         $thisBalance_data Accounts::GetPeriodicDataByType($em$type 'lib'$level_to_group_by 2$parent_id_list = [], $expand_level 1$thisPeriodStartDate$thisPeriodEndDate'_during_', [], [], [], false);
  1048.                         $lastBalance_data Accounts::GetPeriodicDataByType($em$type 'lib'$level_to_group_by 2$parent_id_list = [], $expand_level 1$lastPeriodStartDate$lastPeriodEndDate'_during_', [], [], [], false);
  1049.                         $skipHeadIds = [];
  1050.                         foreach ($thisBalance_data as $parentHead => $balanceData) {
  1051.                             foreach ($balanceData['data'] as $acHead => $headData) {
  1052.                                 if (!(in_array($acHead$acHeadList)))
  1053.                                     continue;
  1054.                                 if ($headData['head_level'] > 4)
  1055.                                     continue;
  1056.                                 //                                $thisBalanceDataByAcHead[$acHead]['balance'] = $headData['head_balance'];
  1057.                                 $thisBalanceDataByAcHead[$acHead]['balance'] = $headData['end_balance']['balance'];
  1058.                                 if (isset($lastBalance_data[$parentHead])) {
  1059.                                     if (isset($lastBalance_data[$parentHead]['data'][$acHead]))
  1060.                                         //                                        $lastBalanceDataByAcHead[$acHead]['balance'] = $lastBalance_data[$parentHead]['data'][$acHead]['head_balance'];
  1061.                                         $lastBalanceDataByAcHead[$acHead]['balance'] = $lastBalance_data[$parentHead]['data'][$acHead]['end_balance']['balance'];
  1062.                                     else
  1063.                                         $lastBalanceDataByAcHead[$acHead]['balance'] = 0;
  1064.                                 } else
  1065.                                     $lastBalanceDataByAcHead[$acHead]['balance'] = 0;
  1066.                                 $skipHeadIds[] = $acHead;
  1067.                             }
  1068.                         }
  1069.                         foreach ($lastBalance_data as $parentHead => $balanceData) {
  1070.                             foreach ($balanceData['data'] as $acHead => $headData) {
  1071.                                 if (in_array($acHead$skipHeadIds))
  1072.                                     continue;
  1073.                                 if (!in_array($acHead$acHeadList))
  1074.                                     continue;
  1075.                                 if ($headData['head_level'] > 4)
  1076.                                     continue;
  1077.                                 $lastBalanceDataByAcHead[$acHead]['balance'] = $headData['end_balance']['balance'];
  1078.                                 if (isset($thisBalance_data[$parentHead])) {
  1079.                                     if (isset($thisBalance_data[$parentHead]['data'][$acHead]))
  1080.                                         $thisBalanceDataByAcHead[$acHead]['balance'] = $thisBalance_data[$parentHead]['data'][$acHead]['end_balance']['balance'];
  1081.                                     else
  1082.                                         $thisBalanceDataByAcHead[$acHead]['balance'] = 0;
  1083.                                 } else
  1084.                                     $thisBalanceDataByAcHead[$acHead]['balance'] = 0;
  1085.                                 $skipHeadIds[] = $acHead;
  1086.                             }
  1087.                         }
  1088.                         $thisReportData = array(
  1089.                             'accountsHeadList' => $acHeadList,
  1090.                             //                            'thisBalance_data' => $thisBalance_data,
  1091.                             'confirmedHeadList' => $skipHeadIds,
  1092.                             'acHeadDataById' => $acHeadDataById,
  1093.                             'thisBalanceDataByAcHead' => $thisBalanceDataByAcHead,
  1094.                             'lastBalanceDataByAcHead' => $lastBalanceDataByAcHead,
  1095.                         );
  1096.                         $data['payable_position'][$app_company_index] = $thisReportData;
  1097.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1098.                     }
  1099.                     //Receivable Position
  1100.                     if (in_array('receivable_position'$reportsToGet)) {
  1101.                         $acHeadList = [];
  1102.                         $companyId explode('_'$app_company_index)[1];
  1103.                         $acHeadDataById = [];
  1104.                         $thisBalanceDataByAcHead = [];
  1105.                         $lastBalanceDataByAcHead = [];
  1106.                         //                        $filter_settings = $em->getRepository('ApplicationBundle\\Entity\\AccSettings')->findOneBy(array(
  1107.                         //                            'name' => 'receivable_parents',
  1108.                         ////                        'CompanyId'=>$companyId
  1109.                         //                        ));
  1110.                         //                        $filter_head_parents_id_list = [];
  1111.                         //                        if ($filter_settings)
  1112.                         //                            $filter_head_parents_id_list = json_decode($filter_settings->getData());
  1113.                         //                        $likeQuery = '';
  1114.                         //                        foreach ($filter_head_parents_id_list as $p) {
  1115.                         //                            $likeQuery .= "OR path_tree like '%/" . $p . "%/' ";
  1116.                         //                        }
  1117.                         //                        $get_sql = "SELECT * FROM acc_accounts_head WHERE acc_accounts_head.company_id=" . $companyId . "
  1118.                         //                         and (1=0 " . $likeQuery . ") ";
  1119.                         $get_sql "SELECT acc_accounts_head.*  FROM acc_accounts_head
  1120.  WHERE acc_accounts_head.company_id=" $companyId "
  1121.                          and  ( acc_accounts_head.accounts_head_id in (select distinct accounts_head_id from acc_clients)
  1122.                           OR acc_accounts_head.accounts_head_id in (select distinct advance_head_id from acc_clients)
  1123.                          ) ";
  1124.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1125.                         
  1126.                         $entries $stmt;
  1127.                         $account_head_ids_by_client_type = [];
  1128.                         foreach ($entries as $entry) {
  1129.                             $has_payments 1;
  1130.                             $acHeadList[] = $entry['accounts_head_id'];
  1131.                             $acHeadDataById[$entry['accounts_head_id']]['name'] = $entry['name'];
  1132.                         }
  1133.                         $get_sql "SELECT acc_clients.*  FROM acc_clients
  1134.  WHERE acc_clients.company_id=" $companyId;
  1135.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1136.                         
  1137.                         $entries $stmt;
  1138.                         $clientTypeListArray Client::ClientTypeList($em, [$companyId], true);
  1139.                         $clientTypesOfHeads = [];
  1140.                         foreach ($entries as $entry) {
  1141.                             if (!isset($account_head_ids_by_client_type[$entry['type']]))
  1142.                                 $account_head_ids_by_client_type[$entry['type']] = [];
  1143.                             $account_head_ids_by_client_type[$entry['type']][] = $entry['accounts_head_id'];
  1144.                             $clientTypesOfHeads[$entry['accounts_head_id']] = $entry['type'];
  1145.                             if ($entry['accounts_head_id'] != $entry['advance_head_id']) {
  1146.                                 $account_head_ids_by_client_type[$entry['type']][] = $entry['advance_head_id'];
  1147.                                 $clientTypesOfHeads[$entry['advance_head_id']] = $entry['type'];
  1148.                             }
  1149.                         }
  1150.                         //                        $get_sql = "SELECT * FROM acc_accounts_head WHERE acc_accounts_head.company_id=" . $companyId . "
  1151.                         //                        AND acc_accounts_head.head_level= 2 and acc_accounts_head.type='lib'";
  1152.                         //
  1153.                         //                        $stmt = $em->getConnection()->executeStatement($get_sql);
  1154.                         //                        
  1155.                         //                        $entries = $stmt;
  1156.                         //
  1157.                         //                        foreach ($entries as $entry) {
  1158.                         //                            $has_payments = 1;
  1159.                         //                            $cash_child_id_list[] = $entry['accounts_head_id'];
  1160.                         //                            $acHeadList[] = $entry['accounts_head_id'];
  1161.                         //                            $acHeadDataById[$entry['accounts_head_id']]['name'] = $entry['name'];
  1162.                         //                        }
  1163.                         $thisBalance_data Accounts::GetPeriodicDataByType($em$type 'ast'$level_to_group_by 2$parent_id_list = [], $expand_level 1$thisPeriodStartDate$thisPeriodEndDate'_during_', [], [], [], true);
  1164.                         $lastBalance_data Accounts::GetPeriodicDataByType($em$type 'ast'$level_to_group_by 2$parent_id_list = [], $expand_level 1$lastPeriodStartDate$lastPeriodEndDate'_during_', [], [], [], true);
  1165.                         $skipHeadIds = [];
  1166.                         $thisBalanceDataByClientType = [];
  1167.                         $lastBalanceDataByClientType = [];
  1168.                         foreach ($clientTypeListArray as $ct) {
  1169.                             $thisBalanceDataByClientType[$ct['id']] = 0;
  1170.                             $lastBalanceDataByClientType[$ct['id']] = 0;
  1171.                         }
  1172.                         foreach ($thisBalance_data as $parentHead => $balanceData) {
  1173.                             foreach ($balanceData['data'] as $acHead => $headData) {
  1174.                                 if (!(in_array($acHead$acHeadList)))
  1175.                                     continue;
  1176.                                 //                                if ($headData['head_level'] > 4)
  1177.                                 //                                    continue;
  1178.                                 $thisBalanceDataByAcHead[$acHead]['balance'] = $headData['end_balance']['balance'];
  1179.                                 if (isset($lastBalance_data[$parentHead])) {
  1180.                                     if (isset($lastBalance_data[$parentHead]['data'][$acHead]))
  1181.                                         $lastBalanceDataByAcHead[$acHead]['balance'] = $lastBalance_data[$parentHead]['data'][$acHead]['end_balance']['balance'];
  1182.                                     else
  1183.                                         $lastBalanceDataByAcHead[$acHead]['balance'] = 0;
  1184.                                 } else
  1185.                                     $lastBalanceDataByAcHead[$acHead]['balance'] = 0;
  1186.                                 if (!isset($thisBalanceDataByClientType[$clientTypesOfHeads[$acHead]]))
  1187.                                     $thisBalanceDataByClientType[$clientTypesOfHeads[$acHead]] = $headData['end_balance']['balance'];
  1188.                                 else
  1189.                                     $thisBalanceDataByClientType[$clientTypesOfHeads[$acHead]] += $headData['end_balance']['balance'];
  1190.                                 if (!isset($lastBalanceDataByClientType[$clientTypesOfHeads[$acHead]]))
  1191.                                     $lastBalanceDataByClientType[$clientTypesOfHeads[$acHead]] = 0;
  1192.                                 else
  1193.                                     $lastBalanceDataByClientType[$clientTypesOfHeads[$acHead]] += $lastBalance_data[$parentHead]['data'][$acHead]['end_balance']['balance'];
  1194.                                 $skipHeadIds[] = $acHead;
  1195.                             }
  1196.                         }
  1197.                         foreach ($lastBalance_data as $parentHead => $balanceData) {
  1198.                             foreach ($balanceData['data'] as $acHead => $headData) {
  1199.                                 if (in_array($acHead$skipHeadIds))
  1200.                                     continue;
  1201.                                 if (!in_array($acHead$acHeadList))
  1202.                                     continue;
  1203.                                 //                                if ($headData['head_level'] > 4)
  1204.                                 //                                    continue;
  1205.                                 $lastBalanceDataByAcHead[$acHead]['balance'] = $headData['end_balance']['balance'];
  1206.                                 if (isset($thisBalance_data[$parentHead])) {
  1207.                                     if (isset($thisBalance_data[$parentHead]['data'][$acHead]))
  1208.                                         $thisBalanceDataByAcHead[$acHead]['balance'] = $thisBalance_data[$parentHead]['data'][$acHead]['end_balance']['balance'];
  1209.                                     else
  1210.                                         $thisBalanceDataByAcHead[$acHead]['balance'] = 0;
  1211.                                 } else
  1212.                                     $thisBalanceDataByAcHead[$acHead]['balance'] = 0;
  1213.                                 if (!isset($lastBalanceDataByClientType[$clientTypesOfHeads[$acHead]]))
  1214.                                     $lastBalanceDataByClientType[$clientTypesOfHeads[$acHead]] = $headData['end_balance']['balance'];
  1215.                                 else
  1216.                                     $lastBalanceDataByClientType[$clientTypesOfHeads[$acHead]] += $headData['end_balance']['balance'];
  1217.                                 if (!isset($thisBalanceDataByClientType[$clientTypesOfHeads[$acHead]]))
  1218.                                     $thisBalanceDataByClientType[$clientTypesOfHeads[$acHead]] = 0;
  1219.                                 $skipHeadIds[] = $acHead;
  1220.                             }
  1221.                         }
  1222.                         $thisReportData = array(
  1223.                             //                            'accountsHeadList' => $acHeadList,
  1224.                             //                            'thisBalance_data' => $thisBalance_data,
  1225.                             //                            'confirmedHeadList' => $skipHeadIds,
  1226.                             //                            'acHeadDataById' => $acHeadDataById,
  1227.                             'thisBalance_data' => $thisBalance_data,
  1228.                             'lastBalance_data' => $lastBalance_data,
  1229.                             'thisBalanceDataByAcHead' => $thisBalanceDataByAcHead,
  1230.                             'lastBalanceDataByAcHead' => $lastBalanceDataByAcHead,
  1231.                             'clientTypeListArray' => $clientTypeListArray,
  1232.                             'thisBalanceDataByClientType' => $thisBalanceDataByClientType,
  1233.                             'lastBalanceDataByClientType' => $lastBalanceDataByClientType,
  1234.                         );
  1235.                         $data['receivable_position'][$app_company_index] = $thisReportData;
  1236.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1237.                     }
  1238.                     //Sales Position
  1239.                     if (in_array('sales_position'$reportsToGet)) {
  1240.                         $acHeadList = [];
  1241.                         $companyId explode('_'$app_company_index)[1];
  1242.                         $acHeadDataById = [];
  1243.                         $thisBalanceDataByClientType = [];
  1244.                         $lastBalanceDataByClientType = [];
  1245.                         $get_sql "SELECT sum(sales_invoice.invoice_amount) sales_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type
  1246.   FROM sales_invoice
  1247.   join acc_clients on acc_clients.client_id=sales_invoice.client_id
  1248.   join client_type on acc_clients.type=client_type.client_type_id
  1249.    WHERE sales_invoice.company_id=" $companyId " AND sales_invoice.approved=1
  1250.                           AND sales_invoice_date between '" $thisPeriodStartDate " 00:00:00' and '" $thisPeriodEndDate " 23:59:59.999'
  1251.                           GROUP BY client_type.client_type_id
  1252.                           ";
  1253.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1254.                         
  1255.                         $entries $stmt;
  1256.                         $clientTypes = [];
  1257.                         $clientTypeNames = [];
  1258.                         $get_sql_1 $get_sql;
  1259.                         foreach ($entries as $entry) {
  1260.                             $has_payments 1;
  1261.                             $thisBalanceDataByClientType[$entry['client_type_id']] = $entry;
  1262.                             $lastBalanceDataByClientType[$entry['client_type_id']]['sales_amount'] = 0//just for the lulz
  1263.                             if (!in_array($entry['client_type_id'], $clientTypes)) {
  1264.                                 $clientTypes[] = $entry['client_type_id'];
  1265.                                 $clientTypeNames[$entry['client_type_id']] = $entry['name'];
  1266.                             }
  1267.                         }
  1268.                         $get_sql "SELECT sum(sales_invoice.invoice_amount) sales_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type
  1269.   FROM sales_invoice
  1270.   join acc_clients on acc_clients.client_id=sales_invoice.client_id
  1271.   join client_type on acc_clients.type=client_type.client_type_id
  1272.    WHERE sales_invoice.company_id=" $companyId " AND sales_invoice.approved=1
  1273.                           AND sales_invoice_date between '" $lastPeriodStartDate " 00:00:00' and '" $lastPeriodEndDate " 23:59:59.999'
  1274.                           GROUP BY client_type.client_type_id
  1275.                           ";
  1276.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1277.                         
  1278.                         $entries $stmt;
  1279.                         foreach ($entries as $entry) {
  1280.                             $has_payments 1;
  1281.                             $lastBalanceDataByClientType[$entry['client_type_id']] = $entry;
  1282.                             if (!isset($thisBalanceDataByClientType[$entry['client_type_id']]))
  1283.                                 $thisBalanceDataByClientType[$entry['client_type_id']]['sales_amount'] = 0//just for the lulz
  1284.                             if (!in_array($entry['client_type_id'], $clientTypes)) {
  1285.                                 $clientTypes[] = $entry['client_type_id'];
  1286.                                 $clientTypeNames[$entry['client_type_id']] = $entry['name'];
  1287.                             }
  1288.                         }
  1289.                         $skipHeadIds = [];
  1290.                         $thisReportData = array(
  1291.                             'clientTypes' => $clientTypes,
  1292.                             //                            'get_sql_1' => $get_sql_1,
  1293.                             //                            'get_sql' => $get_sql,
  1294.                             'clientTypeNames' => $clientTypeNames,
  1295.                             'thisBalanceDataByClientType' => $thisBalanceDataByClientType,
  1296.                             'lastBalanceDataByClientType' => $lastBalanceDataByClientType,
  1297.                         );
  1298.                         $data['sales_position'][$app_company_index] = $thisReportData;
  1299.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1300.                     }
  1301.                     //Collection Position
  1302.                     if (in_array('collection_position'$reportsToGet)) {
  1303.                         $acHeadList = [];
  1304.                         $companyId explode('_'$app_company_index)[1];
  1305.                         $acHeadDataById = [];
  1306.                         $thisBalanceDataByClientType = [];
  1307.                         $lastBalanceDataByClientType = [];
  1308.                         $allocationSourceSql $this->buildAllocationAwareTransactionSourceSql(array(
  1309.                             'document_type' => 6,
  1310.                             'start_date' => $thisPeriodStartDate,
  1311.                             'end_date' => $thisPeriodEndDate,
  1312.                             'approved' => 1,
  1313.                             'ledger_hit' => 1,
  1314.                         ));
  1315.                         $get_sql "SELECT SUM(CASE WHEN alloc_rows.position = 'cr' THEN alloc_rows.allocation_amount ELSE 0 END) positive_amount,
  1316. SUM(CASE WHEN alloc_rows.position = 'dr' THEN alloc_rows.allocation_amount ELSE 0 END) negative_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type
  1317.  FROM " $allocationSourceSql " alloc_rows
  1318.    join acc_clients on acc_clients.accounts_head_id=alloc_rows.accounts_head_id or acc_clients.advance_head_id=alloc_rows.accounts_head_id
  1319.   join client_type on acc_clients.type=client_type.client_type_id
  1320.   WHERE acc_clients.company_id=" $companyId "
  1321.                               GROUP BY client_type.client_type_id";
  1322.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1323.                         
  1324.                         $entries $stmt;
  1325.                         $clientTypes = [];
  1326.                         $clientTypeNames = [];
  1327.                         foreach ($entries as $entry) {
  1328.                             $has_payments 1;
  1329.                             $thisBalanceDataByClientType[$entry['client_type_id']] = $entry;
  1330.                             $lastBalanceDataByClientType[$entry['client_type_id']]['collection_amount'] = 0//just for the lulz
  1331.                             $thisBalanceDataByClientType[$entry['client_type_id']]['collection_amount'] = $entry['positive_amount'] - $entry['negative_amount'];
  1332.                             if (!in_array($entry['client_type_id'], $clientTypes)) {
  1333.                                 $clientTypes[] = $entry['client_type_id'];
  1334.                                 $clientTypeNames[$entry['client_type_id']] = $entry['name'];
  1335.                             }
  1336.                         }
  1337.                         $allocationSourceSql $this->buildAllocationAwareTransactionSourceSql(array(
  1338.                             'document_type' => 6,
  1339.                             'start_date' => $lastPeriodStartDate,
  1340.                             'end_date' => $lastPeriodEndDate,
  1341.                             'approved' => 1,
  1342.                             'ledger_hit' => 1,
  1343.                         ));
  1344.                         $get_sql "SELECT SUM(CASE WHEN alloc_rows.position = 'cr' THEN alloc_rows.allocation_amount ELSE 0 END) positive_amount,
  1345. SUM(CASE WHEN alloc_rows.position = 'dr' THEN alloc_rows.allocation_amount ELSE 0 END) negative_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type
  1346.  FROM " $allocationSourceSql " alloc_rows
  1347.    join acc_clients on acc_clients.accounts_head_id=alloc_rows.accounts_head_id or acc_clients.advance_head_id=alloc_rows.accounts_head_id
  1348.   join client_type on acc_clients.type=client_type.client_type_id
  1349.   WHERE acc_clients.company_id=" $companyId "
  1350.                               GROUP BY client_type.client_type_id";
  1351.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1352.                         
  1353.                         $entries $stmt;
  1354.                         foreach ($entries as $entry) {
  1355.                             $has_payments 1;
  1356.                             $lastBalanceDataByClientType[$entry['client_type_id']] = $entry;
  1357.                             $lastBalanceDataByClientType[$entry['client_type_id']]['collection_amount'] = $entry['positive_amount'] - $entry['negative_amount'];
  1358.                             if (!isset($thisBalanceDataByClientType[$entry['client_type_id']]))
  1359.                                 $thisBalanceDataByClientType[$entry['client_type_id']]['collection_amount'] = 0//just for the lulz
  1360.                             if (!in_array($entry['client_type_id'], $clientTypes)) {
  1361.                                 $clientTypes[] = $entry['client_type_id'];
  1362.                                 $clientTypeNames[$entry['client_type_id']] = $entry['name'];
  1363.                             }
  1364.                         }
  1365.                         $skipHeadIds = [];
  1366.                         $thisReportData = array(
  1367.                             'clientTypes' => $clientTypes,
  1368.                             'clientTypeNames' => $clientTypeNames,
  1369.                             'thisBalanceDataByClientType' => $thisBalanceDataByClientType,
  1370.                             'lastBalanceDataByClientType' => $lastBalanceDataByClientType,
  1371.                         );
  1372.                         $data['collection_position'][$app_company_index] = $thisReportData;
  1373.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1374.                     }
  1375.                     //Return Position
  1376.                     if (in_array('market_return_position'$reportsToGet)) {
  1377.                         $acHeadList = [];
  1378.                         $companyId explode('_'$app_company_index)[1];
  1379.                         $acHeadDataById = [];
  1380.                         $thisBalanceDataByClientType = [];
  1381.                         $lastBalanceDataByClientType = [];
  1382.                         $get_sql "SELECT sum(irr_item.received_total_sales_price) return_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type
  1383.   FROM irr_item
  1384.   join item_received_replacement on item_received_replacement.irr_id=irr_item.irr_id
  1385.   join acc_clients on acc_clients.client_id=item_received_replacement.client_id
  1386.   join client_type on acc_clients.type=client_type.client_type_id
  1387.    WHERE item_received_replacement.company_id=" $companyId " AND item_received_replacement.approved=1
  1388.                           AND item_received_replacement.irr_date between '" $thisPeriodStartDate " 00:00:00' and '" $thisPeriodEndDate " 23:59:59.999'
  1389.                           GROUP BY client_type.client_type_id
  1390.                           ";
  1391.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1392.                         
  1393.                         $entries $stmt;
  1394.                         $clientTypes = [];
  1395.                         $clientTypeNames = [];
  1396.                         $get_sql_1 $get_sql;
  1397.                         foreach ($entries as $entry) {
  1398.                             $has_payments 1;
  1399.                             $thisBalanceDataByClientType[$entry['client_type_id']] = $entry;
  1400.                             $lastBalanceDataByClientType[$entry['client_type_id']]['return_amount'] = 0//just for the lulz
  1401.                             if (!in_array($entry['client_type_id'], $clientTypes)) {
  1402.                                 $clientTypes[] = $entry['client_type_id'];
  1403.                                 $clientTypeNames[$entry['client_type_id']] = $entry['name'];
  1404.                             }
  1405.                         }
  1406.                         $get_sql "SELECT sum(irr_item.received_total_sales_price) return_amount,client_type.client_type_id, client_type.name, acc_clients.client_id, acc_clients.type
  1407.   FROM irr_item
  1408.   join item_received_replacement on item_received_replacement.irr_id=irr_item.irr_id
  1409.   join acc_clients on acc_clients.client_id=item_received_replacement.client_id
  1410.   join client_type on acc_clients.type=client_type.client_type_id
  1411.    WHERE item_received_replacement.company_id=" $companyId " AND item_received_replacement.approved=1
  1412.                           AND item_received_replacement.irr_date between '" $lastPeriodStartDate " 00:00:00' and '" $lastPeriodEndDate " 23:59:59.999'
  1413.                           GROUP BY client_type.client_type_id
  1414.                           ";
  1415.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1416.                         
  1417.                         $entries $stmt;
  1418.                         foreach ($entries as $entry) {
  1419.                             $has_payments 1;
  1420.                             $lastBalanceDataByClientType[$entry['client_type_id']] = $entry;
  1421.                             if (!isset($thisBalanceDataByClientType[$entry['client_type_id']]))
  1422.                                 $thisBalanceDataByClientType[$entry['client_type_id']]['return_amount'] = 0//just for the lulz
  1423.                             if (!in_array($entry['client_type_id'], $clientTypes)) {
  1424.                                 $clientTypes[] = $entry['client_type_id'];
  1425.                                 $clientTypeNames[$entry['client_type_id']] = $entry['name'];
  1426.                             }
  1427.                         }
  1428.                         $skipHeadIds = [];
  1429.                         $thisReportData = array(
  1430.                             'clientTypes' => $clientTypes,
  1431.                             //                            'get_sql_1' => $get_sql_1,
  1432.                             //                            'get_sql' => $get_sql,
  1433.                             'clientTypeNames' => $clientTypeNames,
  1434.                             'thisBalanceDataByClientType' => $thisBalanceDataByClientType,
  1435.                             'lastBalanceDataByClientType' => $lastBalanceDataByClientType,
  1436.                         );
  1437.                         $data['market_return_position'][$app_company_index] = $thisReportData;
  1438.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1439.                     }
  1440.                     //order and client count
  1441.                     if (in_array('order_and_client_count'$reportsToGet)) {
  1442.                         $acHeadList = [];
  1443.                         $companyId explode('_'$app_company_index)[1];
  1444.                         $acHeadDataById = [];
  1445.                         $thisBalanceDataByAcHead = [];
  1446.                         $lastBalanceDataByAcHead = [];
  1447.                         $today = new \DateTime();
  1448.                         $get_sql "SELECT count(sales_order_id) total_so_count, sum(so_amount) total_so_amount, sum(invoice_amount) total_invoice_amount FROM sales_order WHERE sales_order.company_id=" $companyId " and  sales_order.sales_order_date between '" $thisPeriodStartDate " 00:00:00' and '" $thisPeriodEndDate " 23:59:59.999' ";
  1449.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1450.                         
  1451.                         $entries1 $stmt;
  1452.                         $get_sql "SELECT count(client_id) total_clients FROM acc_clients WHERE acc_clients.company_id=" $companyId;
  1453.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1454.                         
  1455.                         $entries2 $stmt;
  1456.                         $currCompanyData Company::getCompanyData($em$session->get(UserConstants::USER_COMPANY_ID$companyId));
  1457.                         $allocationSourceSql $this->buildAllocationAwareTransactionSourceSql(array(
  1458.                             'document_type' => 6,
  1459.                             'company_id' => $companyId,
  1460.                             'start_date' => $thisPeriodStartDate,
  1461.                             'end_date' => $thisPeriodEndDate,
  1462.                             'approved' => 1,
  1463.                             'ledger_hit' => 1,
  1464.                         ));
  1465.                         $get_sql "SELECT SUM(CASE WHEN alloc_rows.position = 'cr' THEN alloc_rows.allocation_amount ELSE ((-1)*alloc_rows.allocation_amount) END) total_collection_amount, alloc_rows.document_hash FROM " $allocationSourceSql " alloc_rows
  1466.                         join acc_clients on acc_clients.accounts_head_id=alloc_rows.accounts_head_id or acc_clients.advance_head_id=alloc_rows.accounts_head_id
  1467.                         WHERE acc_clients.company_id=" $companyId " ";
  1468.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1469.                         
  1470.                         $entries3 $stmt;
  1471.                         //
  1472.                         //                        $get_sql = "SELECT (select  c.balance last_balance from inv_closing_balance c
  1473.                         //where c.product_id=a.product_id and c.warehouse_id=a.warehouse_id and c.action_tag_id=a.action_tag_id order by date desc limit 1) stock_amount
  1474.                         //from inv_closing_balance a
  1475.                         //                        where a.warehouse_id in (select distinct id from warehouse
  1476.                         //                        WHERE  warehouse.company_id=" . $companyId . ") and  a.date between '" . $thisPeriodStartDate . " 00:00:00' and '" . $thisPeriodEndDate . " 23:59:59.999' ";
  1477.                         $get_sql "SELECT a.* , (select  c.balance last_balance from inv_closing_balance c
  1478. where date <='" $thisPeriodEndDate " 00:00:00' and c.product_id=a.product_id and c.warehouse_id=a.warehouse_id and c.action_tag_id=a.action_tag_id order by date desc limit 1) last_balance
  1479. from inv_closing_balance a
  1480. where a.warehouse_id in (select distinct id from warehouse
  1481.                       WHERE  warehouse.company_id=" $companyId ") ";
  1482.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1483.                         
  1484.                         $entries4 $stmt;
  1485.                         $currCompanyData Company::getCompanyData($em$session->get(UserConstants::USER_COMPANY_ID$companyId));
  1486.                         $total_stock_amount 0;
  1487.                         foreach ($entries4 as $ent) {
  1488.                             $total_stock_amount += $ent['last_balance'];
  1489.                         }
  1490.                         $thisReportData = array(
  1491.                             //                            'total_stock_amount' => empty($entries3) ? 0 : $entries4[0]['total_stock_amount'],
  1492.                             'total_stock_amount' => $total_stock_amount,
  1493.                             'total_collection_amount' => empty($entries3) ? $entries3[0]['total_collection_amount'],
  1494.                             'total_so_count' => empty($entries1) ? $entries1[0]['total_so_count'],
  1495.                             'total_so_amount' => empty($entries1) ? $entries1[0]['total_so_amount'],
  1496.                             'total_invoice_amount' => empty($entries1) ? $entries1[0]['total_invoice_amount'],
  1497.                             'total_receivable' => $currCompanyData->getReceivable(),
  1498.                             'total_payable' => $currCompanyData->getPayable(),
  1499.                             'total_clients' => empty($entries2) ? $entries2[0]['total_clients'],
  1500.                         );
  1501.                         $data['order_and_client_count'][$app_company_index] = $thisReportData;
  1502.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1503.                     }
  1504.                     //Inventory Position
  1505.                     if (in_array('inventory_position'$reportsToGet)) {
  1506.                         $acHeadList = [];
  1507.                         $companyId explode('_'$app_company_index)[1];
  1508.                         $acHeadDataById = [];
  1509.                         $thisBalanceDataByActionTag = [];
  1510.                         $lastBalanceDataByActionTag = [];
  1511.                         $warehouseList Inventory::warehouse_action_list($em$companyId$method 'object');
  1512.                         $get_sql "SELECT a.* , (select  c.balance last_balance from inv_closing_balance c
  1513. where date <='" $thisPeriodEndDate " 00:00:00' and c.product_id=a.product_id and c.warehouse_id=a.warehouse_id and c.action_tag_id=a.action_tag_id order by date desc limit 1) last_balance
  1514. from inv_closing_balance a
  1515. where a.warehouse_id in (select distinct id from warehouse
  1516.                        WHERE  warehouse.company_id=" $companyId ") ";
  1517.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1518.                         
  1519.                         $entries $stmt;
  1520.                         $confirmed_action_ids = [];
  1521.                         $confirmed_action_names = [];
  1522.                         $get_sql_1 $get_sql;
  1523.                         foreach ($entries as $entry) {
  1524.                             $has_payments 1;
  1525.                             if (isset($thisBalanceDataByActionTag[$entry['action_tag_id']]))
  1526.                                 $thisBalanceDataByActionTag[$entry['action_tag_id']]['inventory_amount'] += $entry['last_balance'];
  1527.                             else
  1528.                                 $thisBalanceDataByActionTag[$entry['action_tag_id']]['inventory_amount'] = $entry['last_balance'];
  1529.                             if (!isset($lastBalanceDataByActionTag[$entry['action_tag_id']]))
  1530.                                 $lastBalanceDataByActionTag[$entry['action_tag_id']]['inventory_amount'] = 0;
  1531.                             if (!in_array($entry['action_tag_id'], $confirmed_action_ids)) {
  1532.                                 $confirmed_action_ids[] = $entry['action_tag_id'];
  1533.                                 $confirmed_action_names[$entry['action_tag_id']] = $warehouseList[$entry['action_tag_id']]['name'];
  1534.                             }
  1535.                         }
  1536.                         $get_sql "SELECT a.* , (select  c.balance last_balance from inv_closing_balance c
  1537. where date <='" $lastPeriodEndDate " 00:00:00' and c.product_id=a.product_id and c.warehouse_id=a.warehouse_id and c.action_tag_id=a.action_tag_id order by date desc limit 1) last_balance
  1538. from inv_closing_balance a
  1539. where a.warehouse_id in (select distinct id from warehouse
  1540.                        WHERE  warehouse.company_id=" $companyId ") ";
  1541.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1542.                         
  1543.                         $entries $stmt;
  1544.                         foreach ($entries as $entry) {
  1545.                             $has_payments 1;
  1546.                             if (isset($lastBalanceDataByActionTag[$entry['action_tag_id']]))
  1547.                                 $lastBalanceDataByActionTag[$entry['action_tag_id']]['inventory_amount'] += $entry['last_balance'];
  1548.                             else
  1549.                                 $lastBalanceDataByActionTag[$entry['action_tag_id']]['inventory_amount'] = $entry['last_balance'];
  1550.                             if (!isset($thisBalanceDataByActionTag[$entry['action_tag_id']]))
  1551.                                 $thisBalanceDataByActionTag[$entry['action_tag_id']]['inventory_amount'] = 0;
  1552.                             if (!in_array($entry['action_tag_id'], $confirmed_action_ids)) {
  1553.                                 $confirmed_action_ids[] = $entry['action_tag_id'];
  1554.                                 $confirmed_action_names[$entry['action_tag_id']] = $warehouseList[$entry['action_tag_id']]['name'];
  1555.                             }
  1556.                         }
  1557.                         $skipHeadIds = [];
  1558.                         $thisReportData = array(
  1559.                             //                            'clientTypes' => $clientTypes,
  1560.                             //                            'get_sql_1' => $get_sql_1,
  1561.                             //                            'get_sql' => $get_sql,
  1562.                             'confirmed_action_ids' => $confirmed_action_ids,
  1563.                             'confirmed_action_names' => $confirmed_action_names,
  1564.                             'thisBalanceDataByActionTag' => $thisBalanceDataByActionTag,
  1565.                             'lastBalanceDataByActionTag' => $lastBalanceDataByActionTag,
  1566.                         );
  1567.                         $data['inventory_position'][$app_company_index] = $thisReportData;
  1568.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1569.                     }
  1570.                     //Production Position
  1571.                     if (in_array('production_position'$reportsToGet)) {
  1572.                         $acHeadList = [];
  1573.                         $companyId explode('_'$app_company_index)[1];
  1574.                         $acHeadDataById = [];
  1575.                         $thisBalanceDataByIgId = [];
  1576.                         $lastBalanceDataByIgId = [];
  1577.                         $itemGroups = [];
  1578.                         $itemGroupNames = [];
  1579.                         $get_sql "SELECT sum((case WHEN inv_products.curr_sales_price!=0 then inv_products.curr_sales_price else inv_products.curr_purchase_price END )*production_entry_item.produced_qty) production_amount,inv_item_group.id item_group_id ,inv_item_group.name item_group_name ,inv_products.id product_id
  1580.   FROM production_entry_item
  1581.   join production on production_entry_item.production_id=production.production_id
  1582.   join inv_products on production_entry_item.product_id=inv_products.id
  1583.   join inv_item_group on inv_item_group.id=inv_products.ig_id
  1584.    WHERE production.company_id=" $companyId " AND production.approved=1
  1585.                           AND production.production_date between '" $thisPeriodStartDate " 00:00:00' and '" $thisPeriodEndDate " 23:59:59.999'
  1586.                           GROUP BY inv_item_group.id
  1587.                           ";
  1588.                         //                        $get_sql = "SELECT sum(product_mrp.average_price*production_entry_item.produced_qty) production_amount,inv_item_group.id item_group_id ,inv_item_group.name item_group_name ,inv_products.id product_id
  1589.                         //  FROM production_entry_item
  1590.                         //  join production on production_entry_item.production_id=production.production_id
  1591.                         //  join inv_products on production_entry_item.product_id=inv_products.id
  1592.                         //  join product_mrp on production_entry_item.product_id=product_mrp.product_id
  1593.                         //  join inv_item_group on inv_item_group.id=inv_products.ig_id
  1594.                         //   WHERE production.company_id=" . $companyId . " AND production.approved=1
  1595.                         //                          AND production.production_date between '" . $thisPeriodStartDate . " 00:00:00' and '" . $thisPeriodEndDate . " 23:59:59.999'
  1596.                         //                          GROUP BY inv_item_group.id
  1597.                         //                          ";
  1598.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1599.                         
  1600.                         $entries $stmt;
  1601.                         $get_sql_1 $get_sql;
  1602.                         foreach ($entries as $entry) {
  1603.                             $has_payments 1;
  1604.                             $thisBalanceDataByIgId[$entry['item_group_id']] = $entry;
  1605.                             $lastBalanceDataByIgId[$entry['item_group_id']]['production_amount'] = 0//just for the lulz
  1606.                             if (!in_array($entry['item_group_id'], $clientTypes)) {
  1607.                                 $itemGroups[] = $entry['item_group_id'];
  1608.                                 $itemGroupNames[$entry['item_group_id']] = $entry['item_group_name'];
  1609.                             }
  1610.                         }
  1611.                         $get_sql "SELECT sum(production_entry_item.price*production_entry_item.produced_qty) production_amount,inv_item_group.id item_group_id ,inv_item_group.name item_group_name ,inv_products.id product_id
  1612.   FROM production_entry_item
  1613.   join production on production_entry_item.production_id=production.production_id
  1614.   join inv_products on production_entry_item.product_id=inv_products.id
  1615.   join inv_item_group on inv_item_group.id=inv_products.ig_id
  1616.    WHERE production.company_id=" $companyId " AND production.approved=1
  1617.                           AND production.production_date between '" $lastPeriodStartDate " 00:00:00' and '" $lastPeriodEndDate " 23:59:59.999'
  1618.                           GROUP BY inv_item_group.id
  1619.                           ";
  1620.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1621.                         
  1622.                         $entries $stmt;
  1623.                         foreach ($entries as $entry) {
  1624.                             $has_payments 1;
  1625.                             $lastBalanceDataByIgId[$entry['item_group_id']] = $entry;
  1626.                             if (!isset($thisBalanceDataByIgId[$entry['item_group_id']]))
  1627.                                 $thisBalanceDataByIgId[$entry['item_group_id']]['production_amount'] = 0//just for the lulz
  1628.                             if (!in_array($entry['item_group_id'], $clientTypes)) {
  1629.                                 $itemGroups[] = $entry['item_group_id'];
  1630.                                 $itemGroupNames[$entry['item_group_id']] = $entry['item_group_name'];
  1631.                             }
  1632.                         }
  1633.                         $skipHeadIds = [];
  1634.                         $thisReportData = array(
  1635.                             'itemGroups' => $itemGroups,
  1636.                             //                            'get_sql_1' => $get_sql_1,
  1637.                             //                            'get_sql' => $get_sql,
  1638.                             'itemGroupNames' => $itemGroupNames,
  1639.                             'thisBalanceDataByIgId' => $thisBalanceDataByIgId,
  1640.                             'lastBalanceDataByIgId' => $lastBalanceDataByIgId,
  1641.                         );
  1642.                         $data['production_position'][$app_company_index] = $thisReportData;
  1643.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1644.                     }
  1645.                     //Top Products
  1646.                     if (in_array('top_selling_item_position'$reportsToGet)) {
  1647.                         $acHeadList = [];
  1648.                         $companyId explode('_'$app_company_index)[1];
  1649.                         $acHeadDataById = [];
  1650.                         $thisBalanceDataByRelId = [];
  1651.                         $lastBalanceDataByRelId = [];
  1652.                         $clientIds = [];
  1653.                         $clientNames = [];
  1654.                         $productIds = [];
  1655.                         $productNames = [];
  1656.                         $get_sql "SELECT sum(sales_invoice_item.qty*sales_invoice_item.current_purchase_price) sales_amount, inv_products.id product_id, inv_products.name product_name, acc_clients.client_id, acc_clients.type
  1657.   FROM sales_invoice_item
  1658.   join sales_invoice on sales_invoice_item.sales_invoice_id=sales_invoice.sales_invoice_id
  1659.   join inv_products on sales_invoice_item.product_id=inv_products.id
  1660.   join acc_clients on acc_clients.client_id=sales_invoice.client_id
  1661.    WHERE sales_invoice.company_id=" $companyId " AND sales_invoice.approved=1
  1662.                           AND sales_invoice_date between '" $thisPeriodStartDate " 00:00:00' and '" $thisPeriodEndDate " 23:59:59.999'
  1663.                           GROUP BY sales_invoice_item.product_id
  1664.                           ORDER BY sales_amount DESC
  1665.                           LIMIT 10
  1666.                           ";
  1667.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1668.                         
  1669.                         $entries $stmt;
  1670.                         $get_sql_1 $get_sql;
  1671.                         for ($k 0$k 10$k++) {
  1672.                             $has_payments 1;
  1673.                             if (!isset($entries[$k]))
  1674.                                 $entries[$k] = array(
  1675.                                     'sales_amount' => '',
  1676.                                     'product_name' => '',
  1677.                                     'client_name' => '',
  1678.                                 );
  1679.                             $has_payments 1;
  1680.                             $thisBalanceDataByRelId[$k] = $entries[$k];
  1681.                         }
  1682.                         $get_sql "SELECT sum(sales_invoice_item.qty*sales_invoice_item.current_purchase_price) sales_amount, inv_products.id product_id, inv_products.name product_name, acc_clients.client_id, acc_clients.type
  1683.   FROM sales_invoice_item
  1684.   join sales_invoice on sales_invoice_item.sales_invoice_id=sales_invoice.sales_invoice_id
  1685.   join inv_products on sales_invoice_item.product_id=inv_products.id
  1686.   join acc_clients on acc_clients.client_id=sales_invoice.client_id
  1687.    WHERE sales_invoice.company_id=" $companyId " AND sales_invoice.approved=1
  1688.                           AND sales_invoice_date between '" $lastPeriodStartDate " 00:00:00' and '" $lastPeriodEndDate " 23:59:59.999'
  1689.                           GROUP BY sales_invoice_item.product_id
  1690.                           ORDER BY sales_amount DESC
  1691.                           LIMIT 10
  1692.                           ";
  1693.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1694.                         
  1695.                         $entries $stmt;
  1696.                         for ($k 0$k 10$k++) {
  1697.                             $has_payments 1;
  1698.                             if (!isset($entries[$k]))
  1699.                                 $entries[$k] = array(
  1700.                                     'sales_amount' => '',
  1701.                                     'product_name' => '',
  1702.                                     'client_name' => '',
  1703.                                 );
  1704.                             $lastBalanceDataByRelId[$k] = $entries[$k];
  1705.                         }
  1706.                         $skipHeadIds = [];
  1707.                         $thisReportData = array(
  1708.                             //                            'clientTypes' => $clientTypes,
  1709.                             ////                            'get_sql_1' => $get_sql_1,
  1710.                             ////                            'get_sql' => $get_sql,
  1711.                             //                            'clientTypeNames' => $clientTypeNames,
  1712.                             'thisBalanceDataByRelId' => $thisBalanceDataByRelId,
  1713.                             'lastBalanceDataByRelId' => $lastBalanceDataByRelId,
  1714.                         );
  1715.                         $data['top_selling_item_position'][$app_company_index] = $thisReportData;
  1716.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1717.                     }
  1718.                     //Top Products
  1719.                     if (in_array('top_selling_client_position'$reportsToGet)) {
  1720.                         $acHeadList = [];
  1721.                         $companyId explode('_'$app_company_index)[1];
  1722.                         $acHeadDataById = [];
  1723.                         $thisBalanceDataByRelId = [];
  1724.                         $lastBalanceDataByRelId = [];
  1725.                         $clientIds = [];
  1726.                         $clientNames = [];
  1727.                         $productIds = [];
  1728.                         $productNames = [];
  1729.                         $get_sql "SELECT sum(sales_invoice.invoice_amount) sales_amount,  acc_clients.client_id, acc_clients.client_name client_name
  1730.   FROM sales_invoice
  1731.   join acc_clients on acc_clients.client_id=sales_invoice.client_id
  1732.    WHERE sales_invoice.company_id=" $companyId " AND sales_invoice.approved=1
  1733.                           AND sales_invoice_date between '" $thisPeriodStartDate " 00:00:00' and '" $thisPeriodEndDate " 23:59:59.999'
  1734.                           GROUP BY sales_invoice.client_id
  1735.                           ORDER BY sales_amount DESC
  1736.                           LIMIT 10
  1737.                           ";
  1738.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1739.                         
  1740.                         $entries $stmt;
  1741.                         $get_sql_1 $get_sql;
  1742.                         for ($k 0$k 10$k++) {
  1743.                             $has_payments 1;
  1744.                             if (!isset($entries[$k]))
  1745.                                 $entries[$k] = array(
  1746.                                     'sales_amount' => '',
  1747.                                     'product_name' => '',
  1748.                                     'client_name' => '',
  1749.                                 );
  1750.                             $has_payments 1;
  1751.                             $thisBalanceDataByRelId[$k] = $entries[$k];
  1752.                         }
  1753.                         $get_sql "SELECT sum(sales_invoice.invoice_amount) sales_amount,  acc_clients.client_id, acc_clients.client_name client_name
  1754.   FROM sales_invoice
  1755.   join acc_clients on acc_clients.client_id=sales_invoice.client_id
  1756.    WHERE sales_invoice.company_id=" $companyId " AND sales_invoice.approved=1
  1757.                           AND sales_invoice_date between '" $lastPeriodStartDate " 00:00:00' and '" $lastPeriodEndDate " 23:59:59.999'
  1758.                           GROUP BY sales_invoice.client_id
  1759.                           ORDER BY sales_amount DESC
  1760.                           LIMIT 10
  1761.                           ";
  1762.                         $stmt $em->getConnection()->fetchAllAssociative($get_sql);
  1763.                         
  1764.                         $entries $stmt;
  1765.                         for ($k 0$k 10$k++) {
  1766.                             $has_payments 1;
  1767.                             if (!isset($entries[$k]))
  1768.                                 $entries[$k] = array(
  1769.                                     'sales_amount' => '',
  1770.                                     'product_name' => '',
  1771.                                     'client_name' => '',
  1772.                                 );
  1773.                             $lastBalanceDataByRelId[$k] = $entries[$k];
  1774.                         }
  1775.                         $skipHeadIds = [];
  1776.                         $thisReportData = array(
  1777.                             //                            'clientTypes' => $clientTypes,
  1778.                             ////                            'get_sql_1' => $get_sql_1,
  1779.                             ////                            'get_sql' => $get_sql,
  1780.                             //                            'clientTypeNames' => $clientTypeNames,
  1781.                             'thisBalanceDataByRelId' => $thisBalanceDataByRelId,
  1782.                             'lastBalanceDataByRelId' => $lastBalanceDataByRelId,
  1783.                         );
  1784.                         $data['top_selling_client_position'][$app_company_index] = $thisReportData;
  1785.                         //                    $companyListData[] = Company::getCompanyListWithImage($em);
  1786.                     }
  1787.                 }
  1788.             }
  1789.         }
  1790.         return new JsonResponse(
  1791.             array(
  1792.                 'success' => true,
  1793.                 'data' => $data,
  1794.                 'companyListData' => $companyListData,
  1795.                 'dataToConnectList' => $dataToConnectList,
  1796.                 'periodType' => $periodType,
  1797.                 'queriedReportsToGet' => $request->request->get('reportsToGet'),
  1798.                 'reportsToGet' => $reportsToGet,
  1799.                 'thisPeriodStartDate' => $thisPeriodStartDate,
  1800.                 'thisPeriodEndDate' => $thisPeriodEndDate,
  1801.                 'lastPeriodStartDate' => $lastPeriodStartDate,
  1802.                 'lastPeriodEndDate' => $lastPeriodEndDate,
  1803.                 'companyIdListByAppId' => $companyIdListByAppId,
  1804.                 'companyNameListByAppId' => $companyNameListByAppId,
  1805.                 'companyImageListByAppId' => $companyImageListByAppId,
  1806.                 'appIdList' => $appIdList,
  1807.             )
  1808.         );
  1809.     }
  1810.     public function indexAction(Request $request$cgHash '')
  1811.     {
  1812.         $session $request->getSession();
  1813.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  1814.         if ($systemType == '_ERP_') {
  1815.             //do nothing its default to dashboard index
  1816.         } else if ($systemType == '_BUDDYBEE_') {
  1817.             if ($cgHash != '')
  1818.                 $session->set('codeHash'$cgHash);
  1819.         }
  1820.         // Generic::debugMessage($session);
  1821.         $ROUTE_LIST json_decode($session->get(UserConstants::USER_ROUTE_LIST), true);
  1822.         if ($ROUTE_LIST == null)
  1823.             $ROUTE_LIST = [];
  1824.         $CurrentRoute $request->attributes->get('_route');
  1825.         if ($session->get(UserConstants::USER_ROUTE_LIST) == || in_array('management_dashboard'$ROUTE_LIST)) {
  1826.             // User is not authorized. send him to dashboard
  1827.             //                    $controller->addFlash(
  1828.             //                        'error',
  1829.             //                        'Sorry Couldnot insert Data.'
  1830.             //                    );
  1831.             //                    return $this->render('ApplicationBundle:pages/dashboard:advanced_management_dashboard.html.twig',
  1832.             if ($session->has('isMobile'))
  1833.                 if ($session->get('isMobile') == true) {
  1834.                     return $this->render(
  1835.                         '@Application/pages/dashboard/index_finance_mobile.html.twig',
  1836.                         array(
  1837.                             'page_title' => 'Finance Dashboard',
  1838.                             'dashboardDataForUser' => []
  1839.                         )
  1840.                     );
  1841.                 }
  1842.             return $this->render(
  1843.                 '@Application/pages/dashboard/advanced_management_dashboard.html.twig',
  1844.                 array(
  1845.                     'page_title' => 'Dashboard'
  1846.                 )
  1847.             );
  1848.         }
  1849.         if ($session->has('isMobile'))
  1850.             if ($session->get('isMobile') == true) {
  1851.                 if ($systemType == '_CENTRAL_') {
  1852.                     $defaultRoute 'central_landing';
  1853.                     return $this->redirectToRoute($defaultRoute);
  1854.                 }
  1855.                 elseif ($systemType == '_SOPHIA_') {
  1856.                     $defaultRoute 'sofia_dashboard_admin';
  1857.                     return $this->redirectToRoute($defaultRoute);
  1858.                 }else
  1859.                     return $this->render(
  1860.                         '@Application/pages/dashboard/index_finance_mobile.html.twig',
  1861.                         array(
  1862.                             'page_title' => 'Finance Dashboard',
  1863.                             'dashboardDataForUser' => []
  1864.                         )
  1865.                     );
  1866.             }
  1867.         else {
  1868.                 //check if user has a default route if yes redirect to it
  1869.                 if ($session->get(UserConstants::USER_TYPE) == UserConstants::USER_TYPE_SUPPLIER)
  1870.                     $defaultRoute 'supplier_dashboard';
  1871.                 else if ($session->get(UserConstants::USER_TYPE) == UserConstants::USER_TYPE_CLIENT)
  1872.                     $defaultRoute 'client_dashboard';
  1873.                 else if ($session->get(UserConstants::USER_TYPE) == UserConstants::USER_TYPE_APPLICANT) {
  1874.                     if ($systemType == '_CENTRAL_') {
  1875.                         $defaultRoute 'central_landing';
  1876.                     }
  1877.                     elseif ($systemType == '_SOPHIA_') {
  1878.                         $defaultRoute 'sofia_dashboard_admin';
  1879.                     } else
  1880.                         $defaultRoute 'applicant_dashboard';
  1881.                 } else
  1882.                     $defaultRoute $session->get(UserConstants::USER_DEFAULT_ROUTE);
  1883.                 //            if(in_array($defaultRoute, $ROUTE_LIST))
  1884.                 if ($defaultRoute != '' && $defaultRoute != null)
  1885.                     return $this->redirectToRoute($defaultRoute);
  1886.                 else
  1887.                     return $this->redirectToRoute('sales_dashboard');
  1888. //                return $this->render(
  1889. //                    'ApplicationBundle:pages/dashboard:index.html.twig',
  1890. //                    array(
  1891. //                        'page_title' => 'Dashboard',
  1892. //                        'allocation_filters' => [],
  1893. //                        'allocationFilters' => [],
  1894. //                        'allocation_tag_types' => [],
  1895. //                        'allocation_tag_values_by_type' => [],
  1896. //                        'project_list' => [],
  1897. //                        'branch_list' => [],
  1898. //                        'cost_centers' => []
  1899. //                    )
  1900. //                );
  1901.             }
  1902.     }
  1903.     public function indexSupplierAction(Request $request)
  1904.     {
  1905.         $session $request->getSession();
  1906.         $supplierId 3;
  1907.         if ($request->query->has('supplierId')) //for debug now
  1908.         {
  1909.             $session->set('supplierId'$request->query->get('supplierId'));
  1910.         }
  1911.         $supplierId $session->get('supplierId');  //////////////////////LATER
  1912.         $em $this->getDoctrine()->getManager();
  1913.         $companyId $this->getLoggedUserCompanyId($request);
  1914.         $userId $request->getSession()->get(UserConstants::USER_ID);
  1915.         $SD Supplier::GetSupplierProfileDetails($em$supplierId'SI');
  1916.         $dashboardDataForUser = [];
  1917.         return $this->render(
  1918.             '@Application/pages/dashboard/index_supplier.html.twig',
  1919.             array(
  1920.                 'page_title' => 'Supplier Dashboard',
  1921.                 'dashboardDataForUser' => $dashboardDataForUser,
  1922.                 'data' => $SD,
  1923.                 'igList' => Inventory::ItemGroupList($em$companyId)
  1924.             )
  1925.         );
  1926.     }
  1927.     public function indexClientAction(Request $request)
  1928.     {
  1929.         $session $request->getSession();
  1930.         $clientId 3;
  1931.         if ($request->query->has('clientId')) //for debug now
  1932.         {
  1933.             $session->set('clientId'$request->query->get('clientId'));
  1934.         }
  1935.         $clientId $session->get('clientId');  //////////////////////LATER
  1936.         $em $this->getDoctrine()->getManager();
  1937.         $companyId $this->getLoggedUserCompanyId($request);
  1938.         $userId $request->getSession()->get(UserConstants::USER_ID);
  1939.         $SD Client::GetClientProfileDetails($em$clientId'CI');
  1940.         $dashboardDataForUser = [];
  1941.         return $this->render(
  1942.             '@Application/pages/dashboard/index_client.html.twig',
  1943.             array(
  1944.                 'page_title' => 'Client Dashboard',
  1945.                 'dashboardDataForUser' => $dashboardDataForUser,
  1946.                 'data' => $SD,
  1947.                 'igList' => Inventory::ItemGroupList($em$companyId)
  1948.             )
  1949.         );
  1950.     }
  1951.     public function indexFinanceAction(Request $request)
  1952.     {
  1953.         $session $request->getSession();
  1954.         $dashboardDataForUser = [];
  1955.         $em $this->getDoctrine()->getManager();
  1956.         $companyId $this->getLoggedUserCompanyId($request);
  1957.         $userId $request->getSession()->get(UserConstants::USER_ID);
  1958.         $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  1959.             array(
  1960.                 'CompanyId' => $companyId,
  1961.                 'userId' => $userId,
  1962.                 'status' => GeneralConstant::ACTIVE
  1963.             ),
  1964.             array(
  1965.                 'sequence' => 'ASC'
  1966.             )
  1967.         );
  1968.         if (empty($dbQuery))   ///now get the defaults
  1969.             $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  1970.                 array(
  1971.                     'CompanyId' => $companyId,
  1972.                     //                    'userId'=>$userId,
  1973.                     'defaultBoxFlag' => 1,
  1974.                     'status' => GeneralConstant::ACTIVE
  1975.                 ),
  1976.                 array(
  1977.                     'sequence' => 'ASC'
  1978.                 )
  1979.             );
  1980.         foreach ($dbQuery as $entry) {
  1981.             $dashboardDataForUser[] = array(
  1982.                 'id' => $entry->getId(),
  1983.                 'widgetId' => $entry->getId(),
  1984.                 'widgetSequence' => $entry->getSequence(),
  1985.                 'widgetStatus' => $entry->getStatus(),
  1986.                 'widgetData' => json_decode($entry->getData(), true),
  1987.                 'defaultBoxFlag' => $entry->getDefaultBoxFlag(),
  1988.                 'widgetSizeTiny' => $entry->getSizeTiny(),
  1989.                 'widgetSizeSmall' => $entry->getSizeSmall(),
  1990.                 'widgetSizeMedium' => $entry->getSizeMedium(),
  1991.                 'widgetSizeLarge' => $entry->getSizeLarge(),
  1992.                 'refreshInterval' => $entry->getRefreshInterval(),
  1993.             );
  1994.         }
  1995.         if ($session->has('isMobile')) {
  1996.             if ($session->get('isMobile') == true) {
  1997.                 return $this->render(
  1998.                     '@Application/pages/dashboard/index_finance_mobile.html.twig',
  1999.                     array(
  2000.                         'page_title' => 'Finance Dashboard',
  2001.                         'dashboardDataForUser' => $dashboardDataForUser
  2002.                     )
  2003.                 );
  2004.             } else {
  2005.             }
  2006.         }
  2007.         return $this->render(
  2008.             '@Accounts/pages/finance_dashboard.html.twig',
  2009.             array(
  2010.                 'page_title' => 'Finance Dashboard',
  2011.                 'dashboardDataForUser' => $dashboardDataForUser,
  2012.                 'dashboardAnalytics' => $this->buildFinanceDashboardAnalytics($em)
  2013.             )
  2014.         );
  2015.     }
  2016.     /**
  2017.      * Lean, fail-safe analytics for the Finance cp-shell dashboard. Guarded scalar DQL â€”
  2018.      * a schema/tenant quirk degrades to 0 rather than 500-ing the dashboard.
  2019.      */
  2020.     private function buildFinanceDashboardAnalytics($em)
  2021.     {
  2022.         $scalar = function ($dql$params = []) use ($em) {
  2023.             try {
  2024.                 $v $em->createQuery($dql)->setParameters($params)->getSingleScalarResult();
  2025.                 return $v === null $v;
  2026.             } catch (\Throwable $e) {
  2027.                 return 0;
  2028.             }
  2029.         };
  2030.         $salesInv     = (int) $scalar("SELECT COUNT(i) FROM ApplicationBundle:SalesInvoice i WHERE (i.deleteFlag = 0 OR i.deleteFlag IS NULL)");
  2031.         $expenseInv   = (int) $scalar("SELECT COUNT(e) FROM ApplicationBundle:ExpenseInvoice e WHERE (e.deleteFlag = 0 OR e.deleteFlag IS NULL)");
  2032.         $banks        = (int) $scalar("SELECT COUNT(b) FROM ApplicationBundle:BankAccounts b");
  2033.         $salesPending = (int) $scalar("SELECT COUNT(i) FROM ApplicationBundle:SalesInvoice i WHERE i.approved <> :a AND (i.deleteFlag = 0 OR i.deleteFlag IS NULL)", ['a' => GeneralConstant::APPROVED]);
  2034.         $expPending   = (int) $scalar("SELECT COUNT(e) FROM ApplicationBundle:ExpenseInvoice e WHERE e.approved <> :a AND (e.deleteFlag = 0 OR e.deleteFlag IS NULL)", ['a' => GeneralConstant::APPROVED]);
  2035.         // â”€â”€ Money figures (outstanding + this-month), fail-safe â”€â”€
  2036.         // Receivable/Payable come from the GL (transactions Ã— each leg's FX rate to base), NOT the
  2037.         // invoice sub-ledger (i.dueAmount) nor the stored current_balance. Both of those drift when a
  2038.         // payment is booked as a journal/contra voucher instead of an invoice-linked receipt â€” verified
  2039.         // on a live tenant where the sub-ledger read 38,519 but the GL truth was 2,927. Receivable
  2040.         // (client) heads are debit-nature (dr−cr); payable (supplier) heads credit-nature (cr−dr).
  2041.         // NULLIF(rate,0)→1 keeps base-currency legs (no rate) unconverted.
  2042.         $rawScalar = function ($sql) use ($em) {
  2043.             try { $v $em->getConnection()->fetchOne($sql); return ($v === null || $v === false) ? 0.0 : (float) $v; }
  2044.             catch (\Throwable $e) { return 0.0; }
  2045.         };
  2046.         $arOutstanding $rawScalar(
  2047.             "SELECT COALESCE(SUM(td.amount * COALESCE(NULLIF(td.currency_multiply_rate,0),1) * (CASE WHEN td.position='dr' THEN 1 ELSE -1 END)),0)
  2048.                FROM acc_transaction_details td
  2049.               WHERE td.accounts_head_id IN (SELECT accounts_head_id FROM acc_clients WHERE accounts_head_id IS NOT NULL)");
  2050.         $apOutstanding $rawScalar(
  2051.             "SELECT COALESCE(SUM(td.amount * COALESCE(NULLIF(td.currency_multiply_rate,0),1) * (CASE WHEN td.position='cr' THEN 1 ELSE -1 END)),0)
  2052.                FROM acc_transaction_details td
  2053.               WHERE td.accounts_head_id IN (SELECT accounts_head_id FROM acc_suppliers WHERE accounts_head_id IS NOT NULL)");
  2054.         $monthStart = (new \DateTime('first day of this month 00:00:00'))->format('Y-m-d H:i:s');
  2055.         $salesThisMonth   = (float) $scalar("SELECT COALESCE(SUM(i.invoiceAmount),0) FROM ApplicationBundle:SalesInvoice i WHERE i.createdAt >= :d AND (i.deleteFlag = 0 OR i.deleteFlag IS NULL)", ['d' => $monthStart]);
  2056.         $expenseThisMonth = (float) $scalar("SELECT COALESCE(SUM(e.invoiceAmount),0) FROM ApplicationBundle:ExpenseInvoice e WHERE e.createdAt >= :d AND (e.deleteFlag = 0 OR e.deleteFlag IS NULL)", ['d' => $monthStart]);
  2057.         // â”€â”€ Reuse the company cash-flow builder for the mini trend + current cash â”€â”€
  2058.         $cashFlow = ['hasData' => false];
  2059.         try { $cashFlow $this->buildCompanyCashFlow($em12); } catch (\Throwable $e) { $cashFlow = ['hasData' => false]; }
  2060.         // Base (functional) currency so the money tiles are labelled, not bare numbers.
  2061.         $baseCurrency '';
  2062.         try { $baseCurrency = (string) \ApplicationBundle\Modules\Accounts\Service\CompanyCurrencyResolver::getFunctionalCurrencyCode($em1); } catch (\Throwable $e) { $baseCurrency ''; }
  2063.         return [
  2064.             'base_currency' => $baseCurrency,
  2065.             'kpis' => [
  2066.                 ['label' => 'Sales Invoices',   'value' => $salesInv,   'note' => 'Receivables'],
  2067.                 ['label' => 'Expense Invoices''value' => $expenseInv'note' => 'Payables'],
  2068.                 ['label' => 'Bank Accounts',    'value' => $banks,      'note' => 'Cash & bank'],
  2069.                 ['label' => 'Pending AR',       'value' => $salesPending'note' => 'Sales invoices to approve'],
  2070.                 ['label' => 'Pending AP',       'value' => $expPending,   'note' => 'Expense invoices to approve'],
  2071.             ],
  2072.             'money' => [
  2073.                 ['label' => 'Current Cash',       'value' => isset($cashFlow['closingBalance']) ? $cashFlow['closingBalance'] : 0'note' => 'Cash & bank balance',   'accent' => 'a'],
  2074.                 ['label' => 'Receivable Due',     'value' => round($arOutstanding2),  'note' => 'Outstanding from customers''accent' => 'b'],
  2075.                 ['label' => 'Payable Due',        'value' => round($apOutstanding2),  'note' => 'Outstanding to suppliers',   'accent' => 'c'],
  2076.                 ['label' => 'Invoiced (mo)',      'value' => round($salesThisMonth2), 'note' => 'Sales billed this month',     'accent' => 'b'],
  2077.                 ['label' => 'Expensed (mo)',      'value' => round($expenseThisMonth2), 'note' => 'Expenses this month',       'accent' => 'c'],
  2078.             ],
  2079.             'cashFlow' => $cashFlow,
  2080.             'pending_items' => [
  2081.                 ['label' => 'Sales Invoices',   'value' => $salesPending'note' => 'Receivable approvals'],
  2082.                 ['label' => 'Expense Invoices''value' => $expPending,   'note' => 'Payable approvals'],
  2083.             ],
  2084.         ];
  2085.     }
  2086.     public function indexSalesAction(Request $request)
  2087.     {
  2088.         $session $request->getSession();
  2089.         $dashboardDataForUser = [];
  2090.         $em $this->getDoctrine()->getManager();
  2091.         $companyId $this->getLoggedUserCompanyId($request);
  2092.         $userId $request->getSession()->get(UserConstants::USER_ID);
  2093.         $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2094.             array(
  2095.                 'CompanyId' => $companyId,
  2096.                 'userId' => $userId,
  2097.                 'status' => GeneralConstant::ACTIVE
  2098.             ),
  2099.             array(
  2100.                 'sequence' => 'ASC'
  2101.             )
  2102.         );
  2103.         if (empty($dbQuery))   ///now get the defaults
  2104.             $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2105.                 array(
  2106.                     'CompanyId' => $companyId,
  2107.                     //                    'userId'=>$userId,
  2108.                     'defaultBoxFlag' => 1,
  2109.                     'status' => GeneralConstant::ACTIVE
  2110.                 ),
  2111.                 array(
  2112.                     'sequence' => 'ASC'
  2113.                 )
  2114.             );
  2115.         foreach ($dbQuery as $entry) {
  2116.             $dashboardDataForUser[] = array(
  2117.                 'id' => $entry->getId(),
  2118.                 'widgetId' => $entry->getId(),
  2119.                 'widgetSequence' => $entry->getSequence(),
  2120.                 'widgetStatus' => $entry->getStatus(),
  2121.                 'widgetData' => json_decode($entry->getData(), true),
  2122.                 'defaultBoxFlag' => $entry->getDefaultBoxFlag(),
  2123.                 'widgetSizeTiny' => $entry->getSizeTiny(),
  2124.                 'widgetSizeSmall' => $entry->getSizeSmall(),
  2125.                 'widgetSizeMedium' => $entry->getSizeMedium(),
  2126.                 'widgetSizeLarge' => $entry->getSizeLarge(),
  2127.                 'refreshInterval' => $entry->getRefreshInterval(),
  2128.             );
  2129.         }
  2130.         if ($session->has('isMobile')) {
  2131.             if ($session->get('isMobile') == true) {
  2132.                 return $this->render(
  2133.                     '@Application/pages/dashboard/index_finance_mobile.html.twig',
  2134.                     array(
  2135.                         'page_title' => 'Finance Dashboard',
  2136.                         'dashboardDataForUser' => $dashboardDataForUser
  2137.                     )
  2138.                 );
  2139.             } else {
  2140.             }
  2141.         }
  2142.         return $this->render(
  2143.             '@Sales/pages/sales_dashboard.html.twig',
  2144.             array(
  2145.                 'page_title' => 'Sales Dashboard',
  2146.                 'dashboardDataForUser' => $dashboardDataForUser,
  2147.                 'dashboardAnalytics' => $this->buildSalesDashboardAnalytics($em)
  2148.             )
  2149.         );
  2150.     }
  2151.     /**
  2152.      * Fail-safe analytics for the Sales cp-shell dashboard â€” KPIs + 6-month order-value trend +
  2153.      * a health snapshot. Every metric/query is guarded so a schema/tenant quirk degrades to
  2154.      * empty rather than 500-ing the dashboard.
  2155.      */
  2156.     private function buildSalesDashboardAnalytics($em)
  2157.     {
  2158.         $scalar = function ($dql$params = []) use ($em) {
  2159.             try {
  2160.                 $v $em->createQuery($dql)->setParameters($params)->getSingleScalarResult();
  2161.                 return $v === null $v;
  2162.             } catch (\Throwable $e) {
  2163.                 return 0;
  2164.             }
  2165.         };
  2166.         $soTotal    = (int) $scalar("SELECT COUNT(s) FROM ApplicationBundle:SalesOrder s WHERE (s.deleteFlag = 0 OR s.deleteFlag IS NULL)");
  2167.         $soApproved = (int) $scalar("SELECT COUNT(s) FROM ApplicationBundle:SalesOrder s WHERE s.approved = :a AND (s.deleteFlag = 0 OR s.deleteFlag IS NULL)", ['a' => GeneralConstant::APPROVED]);
  2168.         $soValue    = (float) $scalar("SELECT SUM(s.soAmount) FROM ApplicationBundle:SalesOrder s WHERE s.approved = :a AND (s.deleteFlag = 0 OR s.deleteFlag IS NULL)", ['a' => GeneralConstant::APPROVED]);
  2169.         $soPending  max($soTotal $soApproved0);
  2170.         $opps       = (int) $scalar("SELECT COUNT(o) FROM ApplicationBundle:Opportunity o WHERE (o.deleteFlag = 0 OR o.deleteFlag IS NULL)");
  2171.         $clients    = (int) $scalar("SELECT COUNT(c) FROM ApplicationBundle:AccClients c");
  2172.         // â”€â”€ 6-month order-value trend (guarded raw SQL â€” flat/empty on any quirk) â”€â”€
  2173.         $monthKeys = [];
  2174.         $monthLabels = [];
  2175.         for ($i 5$i >= 0$i--) {
  2176.             $m = new \DateTime('first day of this month');
  2177.             if ($i 0) {
  2178.                 $m->modify('-' $i ' month');
  2179.             }
  2180.             $monthKeys[] = $m->format('Y-m');
  2181.             $monthLabels[] = $m->format('M');
  2182.         }
  2183.         $trend = function ($sql) use ($em) {
  2184.             try {
  2185.                 return $em->getConnection()->fetchAllAssociative($sql);
  2186.             } catch (\Throwable $e) {
  2187.                 return [];
  2188.             }
  2189.         };
  2190.         $seriesFromRows = function (array $rows, array $keys) {
  2191.             $map = [];
  2192.             foreach ($rows as $r) {
  2193.                 $map[$r['month']] = (float) $r['total'];
  2194.             }
  2195.             $out = [];
  2196.             foreach ($keys as $k) {
  2197.                 $out[] = isset($map[$k]) ? round($map[$k], 2) : 0;
  2198.             }
  2199.             return $out;
  2200.         };
  2201.         $orderRows $trend("
  2202.             SELECT DATE_FORMAT(sales_order_date, '%Y-%m') AS month,
  2203.                    COALESCE(SUM(CAST(COALESCE(NULLIF(so_amount,''),0) AS DECIMAL(15,2))),0) AS total
  2204.             FROM sales_order
  2205.             WHERE status = 1 AND (delete_flag = 0 OR delete_flag IS NULL)
  2206.               AND sales_order_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2207.             GROUP BY DATE_FORMAT(sales_order_date, '%Y-%m') ORDER BY month ASC");
  2208.         $approvedRows $trend("
  2209.             SELECT DATE_FORMAT(sales_order_date, '%Y-%m') AS month,
  2210.                    COALESCE(SUM(CAST(COALESCE(NULLIF(so_amount,''),0) AS DECIMAL(15,2))),0) AS total
  2211.             FROM sales_order
  2212.             WHERE status = 1 AND approved = 1 AND (delete_flag = 0 OR delete_flag IS NULL)
  2213.               AND sales_order_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2214.             GROUP BY DATE_FORMAT(sales_order_date, '%Y-%m') ORDER BY month ASC");
  2215.         $coverage $soTotal round(($soApproved $soTotal) * 1001) : 0;
  2216.         // â”€â”€ Intelligent helper â€” surface the most useful next action â”€â”€
  2217.         if ($soPending 0) {
  2218.             $salesHelper = ['type' => 'warn''text' => $soPending ' sales order' . ($soPending == '' 's') . ' awaiting approval â€” sign off to release delivery.'];
  2219.         } elseif ($opps 0) {
  2220.             $salesHelper = ['type' => 'ok''text' => $opps ' opportunit' . ($opps == 'y' 'ies') . ' in the pipeline and nothing stuck in approval â€” keep them moving.'];
  2221.         } else {
  2222.             $salesHelper null;
  2223.         }
  2224.         return [
  2225.             'helper' => $salesHelper,
  2226.             'kpis' => [
  2227.                 ['label' => 'Sales Orders',     'value' => $soTotal,        'note' => 'Active orders'],
  2228.                 ['label' => 'Approved Value',   'value' => round($soValue), 'note' => 'Approved SO value'],
  2229.                 ['label' => 'Opportunities',    'value' => $opps,           'note' => 'In the pipeline'],
  2230.                 ['label' => 'Clients',          'value' => $clients,        'note' => 'Customer base'],
  2231.                 ['label' => 'Pending Approval''value' => $soPending,      'note' => 'Awaiting sign-off'],
  2232.             ],
  2233.             'pending_items' => [
  2234.                 ['label' => 'Sales Orders''value' => $soPending'note' => 'Waiting for approval'],
  2235.             ],
  2236.             'hero' => [
  2237.                 'labels' => $monthLabels,
  2238.                 'series' => [
  2239.                     ['label' => 'Order Value''values' => $seriesFromRows($orderRows$monthKeys),    'color' => '#2b5fb8''fill' => 'rgba(43,95,184,0.14)'],
  2240.                     ['label' => 'Approved',    'values' => $seriesFromRows($approvedRows$monthKeys), 'color' => '#4BAA6B''fill' => 'rgba(75,170,107,0.14)'],
  2241.                 ],
  2242.             ],
  2243.             'hero_summary' => [
  2244.                 'subhead' => 'Order value over the last 6 months',
  2245.             ],
  2246.             'snapshot' => [
  2247.                 'label' => 'Sales Health',
  2248.                 'ring_value' => $coverage,
  2249.                 'ring_note' => 'Approved of all orders',
  2250.                 'metrics' => [
  2251.                     ['label' => 'Approved Value''value' => number_format(round($soValue)), 'note' => 'Signed-off SO value'],
  2252.                     ['label' => 'Pending Orders''value' => $soPending'note' => 'Awaiting approval'],
  2253.                     ['label' => 'Opportunities',  'value' => $opps,      'note' => 'Open pipeline'],
  2254.                 ],
  2255.             ],
  2256.         ];
  2257.     }
  2258.     public function indexPurchaseAction(Request $request)
  2259.     {
  2260.         $em $this->getDoctrine()->getManager();
  2261.         $companyId $this->getLoggedUserCompanyId($request);
  2262.         $dashboardDataForUser $this->loadDashboardWidgetsForUser($request);
  2263.         $dashboardAnalytics $this->buildPurchaseDashboardAnalytics($em$companyId);
  2264.         return $this->render(
  2265.             '@Purchase/pages/supply_chain_dashboard.html.twig',
  2266.             array(
  2267.                 'page_title' => 'Purchasing Dashboard',
  2268.                 'dashboardMode' => 'purchase',
  2269.                 'dashboardDataForUser' => $dashboardDataForUser,
  2270.                 'dashboardAnalytics' => $dashboardAnalytics
  2271.             )
  2272.         );
  2273.     }
  2274.     public function indexDistributionAction(Request $request)
  2275.     {
  2276.         $session $request->getSession();
  2277.         $dashboardDataForUser = [];
  2278.         $em $this->getDoctrine()->getManager();
  2279.         $companyId $this->getLoggedUserCompanyId($request);
  2280.         $userId $request->getSession()->get(UserConstants::USER_ID);
  2281.         $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2282.             array(
  2283.                 'CompanyId' => $companyId,
  2284.                 'userId' => $userId,
  2285.                 'status' => GeneralConstant::ACTIVE
  2286.             ),
  2287.             array(
  2288.                 'sequence' => 'ASC'
  2289.             )
  2290.         );
  2291.         if (empty($dbQuery))   ///now get the defaults
  2292.             $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2293.                 array(
  2294.                     'CompanyId' => $companyId,
  2295.                     //                    'userId'=>$userId,
  2296.                     'defaultBoxFlag' => 1,
  2297.                     'status' => GeneralConstant::ACTIVE
  2298.                 ),
  2299.                 array(
  2300.                     'sequence' => 'ASC'
  2301.                 )
  2302.             );
  2303.         foreach ($dbQuery as $entry) {
  2304.             $dashboardDataForUser[] = array(
  2305.                 'id' => $entry->getId(),
  2306.                 'widgetId' => $entry->getId(),
  2307.                 'widgetSequence' => $entry->getSequence(),
  2308.                 'widgetStatus' => $entry->getStatus(),
  2309.                 'widgetData' => json_decode($entry->getData(), true),
  2310.                 'defaultBoxFlag' => $entry->getDefaultBoxFlag(),
  2311.                 'widgetSizeTiny' => $entry->getSizeTiny(),
  2312.                 'widgetSizeSmall' => $entry->getSizeSmall(),
  2313.                 'widgetSizeMedium' => $entry->getSizeMedium(),
  2314.                 'widgetSizeLarge' => $entry->getSizeLarge(),
  2315.                 'refreshInterval' => $entry->getRefreshInterval(),
  2316.             );
  2317.         }
  2318.         return $this->render(
  2319.             '@Distribution/pages/distribution_dashboard.html.twig',
  2320.             array(
  2321.                 'page_title' => 'Distribution Dashboard',
  2322.                 'dashboardDataForUser' => $dashboardDataForUser,
  2323.                 'dashboardAnalytics' => $this->buildDistributionDashboardAnalytics($em)
  2324.             )
  2325.         );
  2326.     }
  2327.     /**
  2328.      * Lean, fail-safe analytics for the Distribution cp-shell dashboard. Guarded scalar DQL â€”
  2329.      * a schema/tenant quirk degrades to 0 rather than 500-ing the dashboard.
  2330.      */
  2331.     private function buildDistributionDashboardAnalytics($em)
  2332.     {
  2333.         $scalar = function ($dql$params = []) use ($em) {
  2334.             try {
  2335.                 $v $em->createQuery($dql)->setParameters($params)->getSingleScalarResult();
  2336.                 return $v === null $v;
  2337.             } catch (\Throwable $e) {
  2338.                 return 0;
  2339.             }
  2340.         };
  2341.         $doTotal    = (int) $scalar("SELECT COUNT(d) FROM ApplicationBundle:DeliveryOrder d WHERE (d.deleteFlag = 0 OR d.deleteFlag IS NULL)");
  2342.         $doApproved = (int) $scalar("SELECT COUNT(d) FROM ApplicationBundle:DeliveryOrder d WHERE d.approved = :a AND (d.deleteFlag = 0 OR d.deleteFlag IS NULL)", ['a' => GeneralConstant::APPROVED]);
  2343.         $doPending  max($doTotal $doApproved0);
  2344.         $confirms   = (int) $scalar("SELECT COUNT(c) FROM ApplicationBundle:DeliveryConfirmation c");
  2345.         $receipts   = (int) $scalar("SELECT COUNT(r) FROM ApplicationBundle:DeliveryReceipt r");
  2346.         $challans   = (int) $scalar("SELECT COUNT(s) FROM ApplicationBundle:ServiceChallan s");
  2347.         return [
  2348.             'kpis' => [
  2349.                 ['label' => 'Delivery Orders',   'value' => $doTotal,   'note' => 'All dispatch orders'],
  2350.                 ['label' => 'Confirmations',     'value' => $confirms,  'note' => 'Delivery confirmed'],
  2351.                 ['label' => 'Delivery Receipts''value' => $receipts,  'note' => 'Received by customer'],
  2352.                 ['label' => 'Service Challans',  'value' => $challans,  'note' => 'Dispatch challans'],
  2353.                 ['label' => 'Pending Dispatch',  'value' => $doPending'note' => 'Awaiting sign-off'],
  2354.             ],
  2355.             'pending_items' => [
  2356.                 ['label' => 'Delivery Orders''value' => $doPending'note' => 'Waiting for approval'],
  2357.             ],
  2358.         ];
  2359.     }
  2360.     public function indexProjectsAction(Request $request)
  2361.     {
  2362.         $em $this->getDoctrine()->getManager();
  2363.         return $this->render(
  2364.             '@Project/pages/projects_dashboard.html.twig',
  2365.             array(
  2366.                 'page_title' => 'Projects Dashboard',
  2367.                 'dashboardAnalytics' => $this->buildProjectsDashboardAnalytics($em),
  2368.             )
  2369.         );
  2370.     }
  2371.     /**
  2372.      * Lean, fail-safe analytics for the Projects cp-shell home. Guarded scalar DQL â€” a
  2373.      * schema/tenant quirk degrades each metric to 0 rather than 500-ing the landing page.
  2374.      * Project.deleteFlag is nullable-with-no-default, so every count uses (=0 OR IS NULL).
  2375.      */
  2376.     private function buildProjectsDashboardAnalytics($em)
  2377.     {
  2378.         $scalar = function ($dql$params = []) use ($em) {
  2379.             try {
  2380.                 $v $em->createQuery($dql)->setParameters($params)->getSingleScalarResult();
  2381.                 return $v === null $v;
  2382.             } catch (\Throwable $e) {
  2383.                 return 0;
  2384.             }
  2385.         };
  2386.         $list = function ($dql$params = [], $max 6) use ($em) {
  2387.             try {
  2388.                 $q $em->createQuery($dql)->setParameters($params)->setMaxResults($max);
  2389.                 return $q->getArrayResult();
  2390.             } catch (\Throwable $e) { return []; }
  2391.         };
  2392.         $today date('Y-m-d');
  2393.         $total     = (int) $scalar("SELECT COUNT(p) FROM ApplicationBundle:Project p WHERE (p.deleteFlag = 0 OR p.deleteFlag IS NULL)");
  2394.         $active    = (int) $scalar("SELECT COUNT(p) FROM ApplicationBundle:Project p WHERE p.status = :s AND (p.deleteFlag = 0 OR p.deleteFlag IS NULL)", ['s' => GeneralConstant::ACTIVE]);
  2395.         $baselines = (int) $scalar("SELECT COUNT(b) FROM ApplicationBundle:ProjectConfigBaseline b");
  2396.         // â”€â”€ Project confirmation status mix (0/null budgeting, 2 confirmed-not-impacted, 1 impacted) â”€â”€
  2397.         $budgeting = (int) $scalar("SELECT COUNT(p) FROM ApplicationBundle:Project p WHERE (p.projectConfirmationStatus = 0 OR p.projectConfirmationStatus IS NULL) AND (p.deleteFlag = 0 OR p.deleteFlag IS NULL)");
  2398.         $confirmed = (int) $scalar("SELECT COUNT(p) FROM ApplicationBundle:Project p WHERE p.projectConfirmationStatus = 2 AND (p.deleteFlag = 0 OR p.deleteFlag IS NULL)");
  2399.         $impacted  = (int) $scalar("SELECT COUNT(p) FROM ApplicationBundle:Project p WHERE p.projectConfirmationStatus = 1 AND (p.deleteFlag = 0 OR p.deleteFlag IS NULL)");
  2400.         // â”€â”€ Milestone health â”€â”€
  2401.         $msTotal     = (int) $scalar("SELECT COUNT(m) FROM ApplicationBundle:ProjectMilestone m");
  2402.         $msDone       = (int) $scalar("SELECT COUNT(m) FROM ApplicationBundle:ProjectMilestone m WHERE m.actualDate IS NOT NULL");
  2403.         $msOverdue   = (int) $scalar("SELECT COUNT(m) FROM ApplicationBundle:ProjectMilestone m WHERE m.actualDate IS NULL AND m.plannedDate IS NOT NULL AND m.plannedDate < :t", ['t' => $today]);
  2404.         $msUpcoming  = (int) $scalar("SELECT COUNT(m) FROM ApplicationBundle:ProjectMilestone m WHERE m.actualDate IS NULL AND m.plannedDate >= :t", ['t' => $today]);
  2405.         $msBilling   = (float) $scalar("SELECT COALESCE(SUM(m.billingAmount),0) FROM ApplicationBundle:ProjectMilestone m");
  2406.         $msInvoiced  = (float) $scalar("SELECT COALESCE(SUM(m.billingAmount),0) FROM ApplicationBundle:ProjectMilestone m WHERE m.invoicedDate IS NOT NULL");
  2407.         $pctComplete $msTotal round($msDone $msTotal 100) : 0;
  2408.         // â”€â”€ Upcoming milestones (not yet done, soonest first) â”€â”€
  2409.         $upRows $list("SELECT m.milestoneName AS name, m.plannedDate AS planned, m.billingAmount AS amount
  2410.                             FROM ApplicationBundle:ProjectMilestone m
  2411.                            WHERE m.actualDate IS NULL AND m.plannedDate >= :t
  2412.                            ORDER BY m.plannedDate ASC", ['t' => $today], 5);
  2413.         $upcoming = [];
  2414.         foreach ($upRows as $r) {
  2415.             $upcoming[] = [
  2416.                 'name'    => $r['name'] ?: 'Milestone',
  2417.                 'date'    => $r['planned'] instanceof \DateTimeInterface $r['planned']->format('Y-m-d') : (is_string($r['planned']) ? substr($r['planned'], 010) : ''),
  2418.                 'amount'  => number_format((float) ($r['amount'] ?? 0), 2'.'','),
  2419.             ];
  2420.         }
  2421.         // â”€â”€ CoPilot surface counts â”€â”€
  2422.         $surfaces = [
  2423.             ['label' => 'Requirements',    'value' => (int) $scalar("SELECT COUNT(r) FROM ApplicationBundle:ProjectRequirement r"), 'icon' => 'checklist',    'route' => 'project_requirement_list'],
  2424.             ['label' => 'Devices',         'value' => (int) $scalar("SELECT COUNT(d) FROM ApplicationBundle:ProjectDevice d"),      'icon' => 'memory',       'route' => 'project_device_list'],
  2425.             ['label' => 'Interfaces',      'value' => (int) $scalar("SELECT COUNT(i) FROM ApplicationBundle:ProjectInterface i"),   'icon' => 'cable',        'route' => 'project_interface_list'],
  2426.             ['label' => 'Config Baselines','value' => $baselines,                                                                    'icon' => 'layers',       'route' => 'project_config_baseline_list'],
  2427.         ];
  2428.         // â”€â”€ Sales target vs achievement (current year) â€” fail-safe â”€â”€
  2429.         $tva null;
  2430.         try {
  2431.             $sts = new \ApplicationBundle\Modules\ProjectSalesReport\Service\SalesTargetService($em);
  2432.             $year date('Y');
  2433.             $perf $sts->fprPerformance(\ApplicationBundle\Modules\ProjectSalesReport\Support\SalesTargetCore::YEARLY$year);
  2434.             $tgt = (float) $perf['totals']['target'];
  2435.             $ach = (float) $perf['totals']['achieved'];
  2436.             $tva = [
  2437.                 'period'   => $year,
  2438.                 'target'   => number_format($tgt0'.'','),
  2439.                 'achieved' => number_format($ach0'.'','),
  2440.                 'pct'      => $perf['totals']['achievement_pct'],       // null when no target set
  2441.                 'bar'      => $tgt min(100round($ach $tgt 100)) : 0,
  2442.                 'has_target' => $tgt 0,
  2443.             ];
  2444.         } catch (\Throwable $e) { $tva null; }
  2445.         // â”€â”€ Smart helper â”€â”€
  2446.         if ($msOverdue 0) {
  2447.             $helper = ['type' => 'warn''text' => $msOverdue ' milestone' . ($msOverdue == '' 's') . ' overdue â€” the planned date has passed with no completion recorded. Review delivery on these first.'];
  2448.         } elseif ($msUpcoming 0) {
  2449.             $helper = ['type' => 'ok''text' => $msUpcoming ' milestone' . ($msUpcoming == '' 's') . ' coming up and nothing overdue â€” delivery is on track.'];
  2450.         } else {
  2451.             $helper null;
  2452.         }
  2453.         return [
  2454.             'kpis' => [
  2455.                 ['label' => 'Total Projects''value' => $total,      'note' => 'All non-deleted projects'],
  2456.                 ['label' => 'Active',          'value' => $active,     'note' => 'Currently active'],
  2457.                 ['label' => 'Milestones Due',  'value' => $msUpcoming'note' => 'Upcoming, not yet done'],
  2458.                 ['label' => 'Overdue',         'value' => $msOverdue,  'note' => 'Past planned date'],
  2459.             ],
  2460.             'status_mix' => [
  2461.                 ['label' => 'Budgeting''value' => $budgeting'color' => '#c98a00'],
  2462.                 ['label' => 'Confirmed''value' => $confirmed'color' => '#1976d2'],
  2463.                 ['label' => 'Impacted',  'value' => $impacted,  'color' => '#2e7d32'],
  2464.             ],
  2465.             'status_total' => $budgeting $confirmed $impacted,
  2466.             'milestones' => [
  2467.                 'total' => $msTotal'done' => $msDone'overdue' => $msOverdue'upcoming' => $msUpcoming,
  2468.                 'pct_complete' => $pctComplete,
  2469.                 'billing_total' => number_format($msBilling2'.'','),
  2470.                 'invoiced_total' => number_format($msInvoiced2'.'','),
  2471.                 'outstanding_total' => number_format(max(0$msBilling $msInvoiced), 2'.'','),
  2472.             ],
  2473.             'surfaces' => $surfaces,
  2474.             'upcoming' => $upcoming,
  2475.             'target_vs_achievement' => $tva,
  2476.             'helper' => $helper,
  2477.             'pending_items' => [
  2478.                 ['label' => 'Open Projects',      'value' => $active,    'note' => 'Active delivery'],
  2479.                 ['label' => 'Overdue Milestones''value' => $msOverdue'note' => 'Past planned date'],
  2480.                 ['label' => 'Due Soon',           'value' => $msUpcoming,'note' => 'Upcoming milestones'],
  2481.             ],
  2482.         ];
  2483.     }
  2484.     public function indexProductionAction(Request $request)
  2485.     {
  2486.         $session $request->getSession();
  2487.         $dashboardDataForUser = [];
  2488.         $em $this->getDoctrine()->getManager();
  2489.         $companyId $this->getLoggedUserCompanyId($request);
  2490.         $userId $request->getSession()->get(UserConstants::USER_ID);
  2491.         $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2492.             array(
  2493.                 'CompanyId' => $companyId,
  2494.                 'userId' => $userId,
  2495.                 'status' => GeneralConstant::ACTIVE
  2496.             ),
  2497.             array(
  2498.                 'sequence' => 'ASC'
  2499.             )
  2500.         );
  2501.         if (empty($dbQuery))   ///now get the defaults
  2502.             $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2503.                 array(
  2504.                     'CompanyId' => $companyId,
  2505.                     //                    'userId'=>$userId,
  2506.                     'defaultBoxFlag' => 1,
  2507.                     'status' => GeneralConstant::ACTIVE
  2508.                 ),
  2509.                 array(
  2510.                     'sequence' => 'ASC'
  2511.                 )
  2512.             );
  2513.         foreach ($dbQuery as $entry) {
  2514.             $dashboardDataForUser[] = array(
  2515.                 'id' => $entry->getId(),
  2516.                 'widgetId' => $entry->getId(),
  2517.                 'widgetSequence' => $entry->getSequence(),
  2518.                 'widgetStatus' => $entry->getStatus(),
  2519.                 'widgetData' => json_decode($entry->getData(), true),
  2520.                 'defaultBoxFlag' => $entry->getDefaultBoxFlag(),
  2521.                 'widgetSizeTiny' => $entry->getSizeTiny(),
  2522.                 'widgetSizeSmall' => $entry->getSizeSmall(),
  2523.                 'widgetSizeMedium' => $entry->getSizeMedium(),
  2524.                 'widgetSizeLarge' => $entry->getSizeLarge(),
  2525.                 'refreshInterval' => $entry->getRefreshInterval(),
  2526.             );
  2527.         }
  2528.         return $this->render(
  2529.             '@Production/pages/production_dashboard.html.twig',
  2530.             array(
  2531.                 'page_title' => 'Production Dashboard',
  2532.                 'dashboardDataForUser' => $dashboardDataForUser,
  2533.                 'dashboardAnalytics' => $this->buildProductionDashboardAnalytics($em),
  2534.             )
  2535.         );
  2536.     }
  2537.     /**
  2538.      * Lean, fail-safe analytics for the Production cp-shell dashboard. Guarded scalar DQL â€”
  2539.      * a missing entity/column degrades to 0 rather than 500-ing the page.
  2540.      */
  2541.     private function buildProductionDashboardAnalytics($em)
  2542.     {
  2543.         $scalar = function ($dql) use ($em) {
  2544.             try {
  2545.                 $v $em->createQuery($dql)->getSingleScalarResult();
  2546.                 return $v === null $v;
  2547.             } catch (\Throwable $e) {
  2548.                 return 0;
  2549.             }
  2550.         };
  2551.         $entries   = (int) $scalar("SELECT COUNT(p) FROM ApplicationBundle:Production p");
  2552.         $boms      = (int) $scalar("SELECT COUNT(b) FROM ApplicationBundle:ProductionBom b");
  2553.         $schedules = (int) $scalar("SELECT COUNT(s) FROM ApplicationBundle:ProductionSchedule s");
  2554.         $lines     = (int) $scalar("SELECT COUNT(l) FROM ApplicationBundle:ProductionLine l");
  2555.         return [
  2556.             'kpis' => [
  2557.                 ['label' => 'Production Entries''value' => $entries,   'note' => 'All production runs'],
  2558.                 ['label' => 'Bills of Material',  'value' => $boms,      'note' => 'Defined BOMs'],
  2559.                 ['label' => 'Schedules',          'value' => $schedules'note' => 'Planned runs'],
  2560.                 ['label' => 'Production Lines',   'value' => $lines,     'note' => 'Configured lines'],
  2561.             ],
  2562.             'pending_items' => [],
  2563.         ];
  2564.     }
  2565.     public function indexInventoryAction(Request $request)
  2566.     {
  2567.         $em $this->getDoctrine()->getManager();
  2568.         $companyId $this->getLoggedUserCompanyId($request);
  2569.         $dashboardDataForUser $this->loadDashboardWidgetsForUser($request);
  2570.         $dashboardAnalytics $this->buildInventoryDashboardAnalytics($em$companyId);
  2571.         return $this->render(
  2572.             '@Inventory/pages/inventory_dashboard.html.twig',
  2573.             array(
  2574.                 'page_title' => 'Inventory Dashboard',
  2575.                 'dashboardMode' => 'inventory',
  2576.                 'dashboardDataForUser' => $dashboardDataForUser,
  2577.                 'dashboardAnalytics' => $dashboardAnalytics
  2578.             )
  2579.         );
  2580.     }
  2581.     private function loadDashboardWidgetsForUser(Request $request)
  2582.     {
  2583.         $dashboardDataForUser = [];
  2584.         $em $this->getDoctrine()->getManager();
  2585.         $companyId $this->getLoggedUserCompanyId($request);
  2586.         $userId $request->getSession()->get(UserConstants::USER_ID);
  2587.         $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2588.             array(
  2589.                 'CompanyId' => $companyId,
  2590.                 'userId' => $userId,
  2591.                 'status' => GeneralConstant::ACTIVE
  2592.             ),
  2593.             array(
  2594.                 'sequence' => 'ASC'
  2595.             )
  2596.         );
  2597.         if (empty($dbQuery)) {
  2598.             $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  2599.                 array(
  2600.                     'CompanyId' => $companyId,
  2601.                     'defaultBoxFlag' => 1,
  2602.                     'status' => GeneralConstant::ACTIVE
  2603.                 ),
  2604.                 array(
  2605.                     'sequence' => 'ASC'
  2606.                 )
  2607.             );
  2608.         }
  2609.         foreach ($dbQuery as $entry) {
  2610.             $dashboardDataForUser[] = array(
  2611.                 'id' => $entry->getId(),
  2612.                 'widgetId' => $entry->getId(),
  2613.                 'widgetSequence' => $entry->getSequence(),
  2614.                 'widgetStatus' => $entry->getStatus(),
  2615.                 'widgetData' => json_decode($entry->getData(), true),
  2616.                 'defaultBoxFlag' => $entry->getDefaultBoxFlag(),
  2617.                 'widgetSizeTiny' => $entry->getSizeTiny(),
  2618.                 'widgetSizeSmall' => $entry->getSizeSmall(),
  2619.                 'widgetSizeMedium' => $entry->getSizeMedium(),
  2620.                 'widgetSizeLarge' => $entry->getSizeLarge(),
  2621.                 'refreshInterval' => $entry->getRefreshInterval(),
  2622.             );
  2623.         }
  2624.         return $dashboardDataForUser;
  2625.     }
  2626.     private function buildPurchaseDashboardAnalytics($em$companyId)
  2627.     {
  2628.         $conn $em->getConnection();
  2629.         $monthKeys = [];
  2630.         $monthLabels = [];
  2631.         for ($i 5$i >= 0$i--) {
  2632.             $month = new \DateTime('first day of this month');
  2633.             if ($i 0) {
  2634.                 $month->modify('-' $i ' month');
  2635.             }
  2636.             $monthKeys[] = $month->format('Y-m');
  2637.             $monthLabels[] = $month->format('M');
  2638.         }
  2639.         $poTrendRows $conn->fetchAllAssociative("
  2640.             SELECT DATE_FORMAT(purchase_order_date, '%Y-%m') AS month, COALESCE(SUM(CAST(COALESCE(NULLIF(po_amount, ''), 0) AS DECIMAL(15,2))), 0) AS total
  2641.             FROM purchase_order
  2642.             WHERE company_id = :companyId
  2643.               AND status = 1
  2644.               AND approved = 1
  2645.               AND purchase_order_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2646.             GROUP BY DATE_FORMAT(purchase_order_date, '%Y-%m')
  2647.             ORDER BY month ASC
  2648.         ", ['companyId' => $companyId]);
  2649.         $invoiceTrendRows $conn->fetchAllAssociative("
  2650.             SELECT DATE_FORMAT(purchase_invoice_date, '%Y-%m') AS month, COALESCE(SUM(CAST(COALESCE(NULLIF(invoice_amount, ''), 0) AS DECIMAL(15,2))), 0) AS total
  2651.             FROM purchase_invoice
  2652.             WHERE company_id = :companyId
  2653.               AND status = 1
  2654.               AND approved = 1
  2655.               AND purchase_invoice_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2656.             GROUP BY DATE_FORMAT(purchase_invoice_date, '%Y-%m')
  2657.             ORDER BY month ASC
  2658.         ", ['companyId' => $companyId]);
  2659.         $paidTrendRows $conn->fetchAllAssociative("
  2660.             SELECT DATE_FORMAT(purchase_invoice_date, '%Y-%m') AS month, COALESCE(SUM(CAST(COALESCE(NULLIF(paid_amount, ''), invoice_amount, 0) AS DECIMAL(15,2))), 0) AS total
  2661.             FROM purchase_invoice
  2662.             WHERE company_id = :companyId
  2663.               AND status = 1
  2664.               AND approved = 1
  2665.               AND purchase_invoice_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2666.             GROUP BY DATE_FORMAT(purchase_invoice_date, '%Y-%m')
  2667.             ORDER BY month ASC
  2668.         ", ['companyId' => $companyId]);
  2669.         $requisitionTrendRows $conn->fetchAllAssociative("
  2670.             SELECT DATE_FORMAT(purchase_requisition_date, '%Y-%m') AS month, COUNT(*) AS total
  2671.             FROM purchase_requisition
  2672.             WHERE company_id = :companyId
  2673.               AND status = 1
  2674.               AND purchase_requisition_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2675.             GROUP BY DATE_FORMAT(purchase_requisition_date, '%Y-%m')
  2676.             ORDER BY month ASC
  2677.         ", ['companyId' => $companyId]);
  2678.         $seriesFromRows = function (array $rows, array $monthKeys) {
  2679.             $series array_fill_keys($monthKeys0);
  2680.             foreach ($rows as $row) {
  2681.                 $month $row['month'] ?? null;
  2682.                 if ($month !== null && array_key_exists($month$series)) {
  2683.                     $series[$month] = (float) $row['total'];
  2684.                 }
  2685.             }
  2686.             return array_values($series);
  2687.         };
  2688.         $purchaseOrderTotal = (float) $conn->fetchOne("
  2689.             SELECT COALESCE(SUM(CAST(COALESCE(NULLIF(po_amount, ''), 0) AS DECIMAL(15,2))), 0)
  2690.             FROM purchase_order
  2691.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2692.         ", ['companyId' => $companyId]);
  2693.         $purchaseInvoiceTotal = (float) $conn->fetchOne("
  2694.             SELECT COALESCE(SUM(CAST(COALESCE(NULLIF(invoice_amount, ''), 0) AS DECIMAL(15,2))), 0)
  2695.             FROM purchase_invoice
  2696.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2697.         ", ['companyId' => $companyId]);
  2698.         $purchasePaidTotal = (float) $conn->fetchOne("
  2699.             SELECT COALESCE(SUM(CAST(COALESCE(NULLIF(paid_amount, ''), invoice_amount, 0) AS DECIMAL(15,2))), 0)
  2700.             FROM purchase_invoice
  2701.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2702.         ", ['companyId' => $companyId]);
  2703.         $purchaseRequisitionCount = (int) $conn->fetchOne("
  2704.             SELECT COUNT(*)
  2705.             FROM purchase_requisition
  2706.             WHERE company_id = :companyId AND status = 1
  2707.         ", ['companyId' => $companyId]);
  2708.         $purchaseOrderCount = (int) $conn->fetchOne("
  2709.             SELECT COUNT(*)
  2710.             FROM purchase_order
  2711.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2712.         ", ['companyId' => $companyId]);
  2713.         $purchaseInvoiceCount = (int) $conn->fetchOne("
  2714.             SELECT COUNT(*)
  2715.             FROM purchase_invoice
  2716.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2717.         ", ['companyId' => $companyId]);
  2718.         $pendingPurchaseRequisitionCount = (int) $conn->fetchOne("
  2719.             SELECT COUNT(*)
  2720.             FROM purchase_requisition
  2721.             WHERE company_id = :companyId AND status = 1 AND COALESCE(approved, 0) = 0
  2722.         ", ['companyId' => $companyId]);
  2723.         $pendingPurchaseOrderCount = (int) $conn->fetchOne("
  2724.             SELECT COUNT(*)
  2725.             FROM purchase_order
  2726.             WHERE company_id = :companyId AND status = 1 AND COALESCE(approved, 0) = 0
  2727.         ", ['companyId' => $companyId]);
  2728.         $pendingPurchaseInvoiceCount = (int) $conn->fetchOne("
  2729.             SELECT COUNT(*)
  2730.             FROM purchase_invoice
  2731.             WHERE company_id = :companyId AND status = 1 AND COALESCE(approved, 0) = 0
  2732.         ", ['companyId' => $companyId]);
  2733.         $supplierCount = (int) $conn->fetchOne("
  2734.             SELECT COUNT(DISTINCT supplier_id)
  2735.             FROM purchase_order
  2736.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2737.         ", ['companyId' => $companyId]);
  2738.         $topSuppliers $conn->fetchAllAssociative("
  2739.             SELECT po.supplier_id, s.supplier_name, COALESCE(SUM(CAST(COALESCE(NULLIF(po.po_amount, ''), 0) AS DECIMAL(15,2))), 0) AS total
  2740.             FROM purchase_order po
  2741.             LEFT JOIN acc_suppliers s ON s.supplier_id = po.supplier_id
  2742.             WHERE po.company_id = :companyId AND po.status = 1 AND po.approved = 1
  2743.             GROUP BY po.supplier_id, s.supplier_name
  2744.             ORDER BY total DESC
  2745.             LIMIT 5
  2746.         ", ['companyId' => $companyId]);
  2747.         $topSupplierTotal 0;
  2748.         foreach ($topSuppliers as $row) {
  2749.             $topSupplierTotal += (float) $row['total'];
  2750.         }
  2751.         $funnelBase max($purchaseRequisitionCount$purchaseOrderCount$purchaseInvoiceCount1);
  2752.         $paidCoverage $purchaseInvoiceTotal ? ($purchasePaidTotal $purchaseInvoiceTotal) * 100 0;
  2753.         return array(
  2754.             'kpis' => array(
  2755.                 array('label' => 'Purchase Orders''value' => $purchaseOrderCount'note' => 'Approved and active''icon' => 'shopping-cart''color' => 'blue'),
  2756.                 array('label' => 'Invoice Value''value' => $purchaseInvoiceTotal'note' => 'Billed through the period''icon' => 'file-text''color' => 'green'),
  2757.                 array('label' => 'Paid Value''value' => $purchasePaidTotal'note' => 'Settled to suppliers''icon' => 'check-circle''color' => 'teal'),
  2758.                 array('label' => 'Outstanding Due''value' => max($purchaseInvoiceTotal $purchasePaidTotal0), 'note' => 'Open supplier liability''icon' => 'hourglass-half''color' => 'red'),
  2759.                 array('label' => 'Suppliers''value' => $supplierCount'note' => 'Active vendor base''icon' => 'building''color' => 'amber'),
  2760.                 array('label' => 'Open Requisitions''value' => $pendingPurchaseRequisitionCount'note' => 'Waiting for movement''icon' => 'tasks''color' => 'slate'),
  2761.             ),
  2762.             'pending_total' => $pendingPurchaseRequisitionCount $pendingPurchaseOrderCount $pendingPurchaseInvoiceCount,
  2763.             'pending_items' => array(
  2764.                 array('label' => 'Requisitions''value' => $pendingPurchaseRequisitionCount'note' => 'Needs buy-side review'),
  2765.                 array('label' => 'Purchase Orders''value' => $pendingPurchaseOrderCount'note' => 'Waiting for approval'),
  2766.                 array('label' => 'Purchase Invoices''value' => $pendingPurchaseInvoiceCount'note' => 'Pending matching'),
  2767.             ),
  2768.             'hero' => array(
  2769.                 'labels' => $monthLabels,
  2770.                 'series' => array(
  2771.                     array('label' => 'PO Value''values' => $seriesFromRows($poTrendRows$monthKeys), 'color' => '#3D7DB8''fill' => 'rgba(61,125,184,0.14)'),
  2772.                     array('label' => 'Invoice Value''values' => $seriesFromRows($invoiceTrendRows$monthKeys), 'color' => '#4BAA6B''fill' => 'rgba(75,170,107,0.14)'),
  2773.                     array('label' => 'Paid Value''values' => $seriesFromRows($paidTrendRows$monthKeys), 'color' => '#2F9E91''fill' => 'rgba(47,158,145,0.14)'),
  2774.                 ),
  2775.             ),
  2776.             'hero_summary' => array(
  2777.                 'headline' => $purchaseInvoiceTotal round($paidCoverage1) . '%' '0%',
  2778.                 'headline_label' => 'Payment coverage',
  2779.                 'subhead' => 'Paid ' round($paidCoverage1) . '% of billed value',
  2780.             ),
  2781.             'snapshot' => array(
  2782.                 'label' => 'Procurement Health',
  2783.                 'ring_value' => round($paidCoverage1),
  2784.                 'ring_note' => 'Invoice coverage',
  2785.                 'metrics' => array(
  2786.                     array('label' => 'Requisition to PO''value' => $purchaseRequisitionCount round(($purchaseOrderCount $purchaseRequisitionCount) * 1001) . '%' '0%''note' => 'Flow conversion'),
  2787.                     array('label' => 'Average PO Size''value' => $purchaseOrderCount number_format($purchaseOrderTotal $purchaseOrderCount0'.'',') : '0''note' => 'Approved order value'),
  2788.                     array('label' => 'Due Ratio''value' => $purchaseInvoiceTotal round((max($purchaseInvoiceTotal $purchasePaidTotal0) / $purchaseInvoiceTotal) * 1001) . '%' '0%''note' => 'Open liability share'),
  2789.                     array('label' => 'Supplier Concentration''value' => $purchaseOrderTotal round(($topSupplierTotal $purchaseOrderTotal) * 1001) . '%' '0%''note' => 'Top-5 spend share'),
  2790.                 ),
  2791.             ),
  2792.             'lower_cards' => array(
  2793.                 array(
  2794.                     'title' => 'Pipeline Atlas',
  2795.                     'subtitle' => 'Requisition to payment flow',
  2796.                     'type' => 'pipeline',
  2797.                     'items' => array(
  2798.                         array('label' => 'Requisitions''value' => $purchaseRequisitionCount'note' => 'Planning demand'),
  2799.                         array('label' => 'Purchase Orders''value' => $purchaseOrderCount'note' => 'Committed spend'),
  2800.                         array('label' => 'Purchase Invoices''value' => $purchaseInvoiceCount'note' => 'Vendor billing'),
  2801.                         array('label' => 'Settled''value' => (int) $conn->fetchOne("SELECT COUNT(*) FROM purchase_invoice WHERE company_id = :companyId AND status = 1 AND approved = 1 AND CAST(COALESCE(NULLIF(paid_amount, ''), 0) AS DECIMAL(15,2)) > 0", ['companyId' => $companyId]), 'note' => 'Cash released'),
  2802.                     ),
  2803.                     'base' => $funnelBase,
  2804.                 ),
  2805.                 array(
  2806.                     'title' => 'Supplier Mix',
  2807.                     'subtitle' => 'Concentration by approved spend',
  2808.                     'type' => 'bars',
  2809.                     'items' => array_map(function ($row) use ($topSupplierTotal) {
  2810.                         $total = (float) $row['total'];
  2811.                         return array(
  2812.                             'label' => $row['supplier_name'] ?: ('Supplier #' $row['supplier_id']),
  2813.                             'value' => $total,
  2814.                             'bar' => $topSupplierTotal round(($total $topSupplierTotal) * 1001) : 0,
  2815.                             'note' => 'Approved spend share',
  2816.                         );
  2817.                     }, $topSuppliers),
  2818.                 ),
  2819.                 array(
  2820.                     'title' => 'Spend Lens',
  2821.                     'subtitle' => 'Analytical ratios that matter',
  2822.                     'type' => 'ratios',
  2823.                     'items' => array(
  2824.                         array('label' => 'Payment Coverage''value' => round($paidCoverage1) . '%''bar' => $paidCoverage'note' => 'Cash settled vs billed'),
  2825.                         array('label' => 'Requisition Coverage''value' => $purchaseRequisitionCount round(($purchaseOrderCount $purchaseRequisitionCount) * 1001) . '%' '0%''bar' => $purchaseRequisitionCount ? (($purchaseOrderCount $purchaseRequisitionCount) * 100) : 0'note' => 'POs created from requests'),
  2826.                         array('label' => 'Open Due''value' => number_format(max($purchaseInvoiceTotal $purchasePaidTotal0), 0'.'','), 'bar' => $purchaseInvoiceTotal ? ((max($purchaseInvoiceTotal $purchasePaidTotal0) / $purchaseInvoiceTotal) * 100) : 0'note' => 'Balance still outstanding'),
  2827.                     ),
  2828.                 ),
  2829.             ),
  2830.             'months' => $monthLabels
  2831.         );
  2832.     }
  2833.     private function buildInventoryDashboardAnalytics($em$companyId)
  2834.     {
  2835.         $conn $em->getConnection();
  2836.         $monthKeys = [];
  2837.         $monthLabels = [];
  2838.         for ($i 5$i >= 0$i--) {
  2839.             $month = new \DateTime('first day of this month');
  2840.             if ($i 0) {
  2841.                 $month->modify('-' $i ' month');
  2842.             }
  2843.             $monthKeys[] = $month->format('Y-m');
  2844.             $monthLabels[] = $month->format('M');
  2845.         }
  2846.         $receivedRows $conn->fetchAllAssociative("
  2847.             SELECT DATE_FORMAT(stock_received_note_date, '%Y-%m') AS month, COUNT(*) AS total
  2848.             FROM stock_received_note
  2849.             WHERE company_id = :companyId
  2850.               AND status = 1
  2851.               AND approved = 1
  2852.               AND stock_received_note_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2853.             GROUP BY DATE_FORMAT(stock_received_note_date, '%Y-%m')
  2854.             ORDER BY month ASC
  2855.         ", ['companyId' => $companyId]);
  2856.         $transferRows $conn->fetchAllAssociative("
  2857.             SELECT DATE_FORMAT(stock_transfer_date, '%Y-%m') AS month, COUNT(*) AS total
  2858.             FROM stock_transfer
  2859.             WHERE company_id = :companyId
  2860.               AND status = 1
  2861.               AND approved = 1
  2862.               AND stock_transfer_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2863.             GROUP BY DATE_FORMAT(stock_transfer_date, '%Y-%m')
  2864.             ORDER BY month ASC
  2865.         ", ['companyId' => $companyId]);
  2866.         $consumptionRows $conn->fetchAllAssociative("
  2867.             SELECT DATE_FORMAT(stock_consumption_note_date, '%Y-%m') AS month, COUNT(*) AS total
  2868.             FROM stock_consumption_note
  2869.             WHERE company_id = :companyId
  2870.               AND status = 1
  2871.               AND approved = 1
  2872.               AND stock_consumption_note_date >= DATE_SUB(CURDATE(), INTERVAL 5 MONTH)
  2873.             GROUP BY DATE_FORMAT(stock_consumption_note_date, '%Y-%m')
  2874.             ORDER BY month ASC
  2875.         ", ['companyId' => $companyId]);
  2876.         $seriesFromRows = function (array $rows, array $monthKeys) {
  2877.             $series array_fill_keys($monthKeys0);
  2878.             foreach ($rows as $row) {
  2879.                 $month $row['month'] ?? null;
  2880.                 if ($month !== null && array_key_exists($month$series)) {
  2881.                     $series[$month] = (float) $row['total'];
  2882.                 }
  2883.             }
  2884.             return array_values($series);
  2885.         };
  2886.         $skuCount = (int) $conn->fetchOne("
  2887.             SELECT COUNT(*)
  2888.             FROM inv_products
  2889.             WHERE company_id = :companyId AND status = 1
  2890.         ", ['companyId' => $companyId]);
  2891.         $totalUnits = (float) $conn->fetchOne("
  2892.             SELECT COALESCE(SUM(CAST(COALESCE(NULLIF(qty, ''), 0) AS DECIMAL(15,2))), 0)
  2893.             FROM inv_products
  2894.             WHERE company_id = :companyId AND status = 1
  2895.         ", ['companyId' => $companyId]);
  2896.         $stockValue = (float) $conn->fetchOne("
  2897.             SELECT COALESCE(SUM(CAST(COALESCE(NULLIF(qty, ''), 0) AS DECIMAL(15,2)) * CAST(COALESCE(NULLIF(curr_purchase_price, ''), 0) AS DECIMAL(15,2))), 0)
  2898.             FROM inv_products
  2899.             WHERE company_id = :companyId AND status = 1
  2900.         ", ['companyId' => $companyId]);
  2901.         $lowStockCount = (int) $conn->fetchOne("
  2902.             SELECT COUNT(*)
  2903.             FROM inv_products
  2904.             WHERE company_id = :companyId
  2905.               AND status = 1
  2906.               AND CAST(COALESCE(NULLIF(qty, ''), 0) AS DECIMAL(15,2)) <= CAST(COALESCE(NULLIF(reorder_level, ''), 0) AS DECIMAL(15,2))
  2907.               AND CAST(COALESCE(NULLIF(reorder_level, ''), 0) AS DECIMAL(15,2)) > 0
  2908.         ", ['companyId' => $companyId]);
  2909.         $zeroStockCount = (int) $conn->fetchOne("
  2910.             SELECT COUNT(*)
  2911.             FROM inv_products
  2912.             WHERE company_id = :companyId AND status = 1 AND CAST(COALESCE(NULLIF(qty, ''), 0) AS DECIMAL(15,2)) <= 0
  2913.         ", ['companyId' => $companyId]);
  2914.         $overstockCount = (int) $conn->fetchOne("
  2915.             SELECT COUNT(*)
  2916.             FROM inv_products
  2917.             WHERE company_id = :companyId
  2918.               AND status = 1
  2919.               AND CAST(COALESCE(NULLIF(reorder_level, ''), 0) AS DECIMAL(15,2)) > 0
  2920.               AND CAST(COALESCE(NULLIF(qty, ''), 0) AS DECIMAL(15,2)) > (CAST(COALESCE(NULLIF(reorder_level, ''), 0) AS DECIMAL(15,2)) * 3)
  2921.         ", ['companyId' => $companyId]);
  2922.         $warehouseCount = (int) $conn->fetchOne("
  2923.             SELECT COUNT(*)
  2924.             FROM warehouse
  2925.             WHERE company_id = :companyId AND status = 1
  2926.         ", ['companyId' => $companyId]);
  2927.         $receivedPending = (int) $conn->fetchOne("
  2928.             SELECT COUNT(*)
  2929.             FROM stock_received_note
  2930.             WHERE company_id = :companyId AND status = 1 AND COALESCE(approved, 0) = 0
  2931.         ", ['companyId' => $companyId]);
  2932.         $transferPending = (int) $conn->fetchOne("
  2933.             SELECT COUNT(*)
  2934.             FROM stock_transfer
  2935.             WHERE company_id = :companyId AND status = 1 AND COALESCE(approved, 0) = 0
  2936.         ", ['companyId' => $companyId]);
  2937.         $consumptionPending = (int) $conn->fetchOne("
  2938.             SELECT COUNT(*)
  2939.             FROM stock_consumption_note
  2940.             WHERE company_id = :companyId AND status = 1 AND COALESCE(approved, 0) = 0
  2941.         ", ['companyId' => $companyId]);
  2942.         $receivedCount = (int) $conn->fetchOne("
  2943.             SELECT COUNT(*)
  2944.             FROM stock_received_note
  2945.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2946.         ", ['companyId' => $companyId]);
  2947.         $transferCount = (int) $conn->fetchOne("
  2948.             SELECT COUNT(*)
  2949.             FROM stock_transfer
  2950.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2951.         ", ['companyId' => $companyId]);
  2952.         $consumptionCount = (int) $conn->fetchOne("
  2953.             SELECT COUNT(*)
  2954.             FROM stock_consumption_note
  2955.             WHERE company_id = :companyId AND status = 1 AND approved = 1
  2956.         ", ['companyId' => $companyId]);
  2957.         $warehouseMap = \ApplicationBundle\Modules\Inventory\Inventory::WarehouseList($em$companyId);
  2958.         $warehouseRows $conn->fetchAllAssociative("
  2959.             SELECT warehouse_id, COALESCE(SUM(CAST(COALESCE(NULLIF(qty, ''), 0) AS DECIMAL(15,2))), 0) AS total_qty,
  2960.                    COALESCE(SUM(CAST(COALESCE(NULLIF(qty, ''), 0) AS DECIMAL(15,2)) * CAST(COALESCE(NULLIF(curr_purchase_price, ''), 0) AS DECIMAL(15,2))), 0) AS total_value
  2961.             FROM inventory_storage
  2962.             WHERE company_id = :companyId
  2963.             GROUP BY warehouse_id
  2964.             ORDER BY total_value DESC
  2965.             LIMIT 5
  2966.         ", ['companyId' => $companyId]);
  2967.         $productRows $conn->fetchAllAssociative("
  2968.             SELECT s.product_id, p.name, p.reorder_level,
  2969.                    COALESCE(SUM(CAST(COALESCE(NULLIF(s.qty, ''), 0) AS DECIMAL(15,2))), 0) AS total_qty,
  2970.                    COALESCE(SUM(CAST(COALESCE(NULLIF(s.qty, ''), 0) AS DECIMAL(15,2)) * CAST(COALESCE(NULLIF(s.curr_purchase_price, ''), 0) AS DECIMAL(15,2))), 0) AS total_value
  2971.             FROM inventory_storage s
  2972.             LEFT JOIN inv_products p ON p.id = s.product_id
  2973.             WHERE s.company_id = :companyId
  2974.             GROUP BY s.product_id, p.name, p.reorder_level
  2975.             ORDER BY total_value DESC
  2976.             LIMIT 5
  2977.         ", ['companyId' => $companyId]);
  2978.         $movementBalance $receivedCount $consumptionCount;
  2979.         $healthIndex $skuCount max(0100 round(($lowStockCount $skuCount) * 100)) : 0;
  2980.         $reorderPressure $skuCount round(($lowStockCount $skuCount) * 1001) : 0;
  2981.         $stockCoverage $warehouseCount round($totalUnits $warehouseCount1) : 0;
  2982.         $topWarehouseTotal 0;
  2983.         foreach ($warehouseRows as $row) {
  2984.             $topWarehouseTotal += (float) $row['total_value'];
  2985.         }
  2986.         $topProductTotal 0;
  2987.         foreach ($productRows as $row) {
  2988.             $topProductTotal += (float) $row['total_value'];
  2989.         }
  2990.         return array(
  2991.             'kpis' => array(
  2992.                 array('label' => 'SKUs''value' => $skuCount'note' => 'Active item master''icon' => 'cube''color' => 'blue'),
  2993.                 array('label' => 'On-hand Units''value' => $totalUnits'note' => 'Current quantity snapshot''icon' => 'cubes''color' => 'green'),
  2994.                 array('label' => 'Stock Value''value' => $stockValue'note' => 'Book value at purchase cost''icon' => 'database''color' => 'teal'),
  2995.                 array('label' => 'Low Stock SKUs''value' => $lowStockCount'note' => 'At or below reorder point''icon' => 'exclamation-triangle''color' => 'red'),
  2996.                 array('label' => 'Warehouses''value' => $warehouseCount'note' => 'Active storage nodes''icon' => 'warehouse''color' => 'amber'),
  2997.                 array('label' => 'Pending Docs''value' => $receivedPending $transferPending $consumptionPending'note' => 'Awaiting approval''icon' => 'hourglass-half''color' => 'slate'),
  2998.             ),
  2999.             'pending_total' => $receivedPending $transferPending $consumptionPending,
  3000.             'pending_items' => array(
  3001.                 array('label' => 'Stock Received''value' => $receivedPending'note' => 'Incoming goods'),
  3002.                 array('label' => 'Stock Transfer''value' => $transferPending'note' => 'Warehouse movement'),
  3003.                 array('label' => 'Consumption Notes''value' => $consumptionPending'note' => 'Consumption posting'),
  3004.             ),
  3005.             'hero' => array(
  3006.                 'labels' => $monthLabels,
  3007.                 'series' => array(
  3008.                     array('label' => 'Received''values' => $seriesFromRows($receivedRows$monthKeys), 'color' => '#3D7DB8''fill' => 'rgba(61,125,184,0.14)'),
  3009.                     array('label' => 'Transfers''values' => $seriesFromRows($transferRows$monthKeys), 'color' => '#D4A843''fill' => 'rgba(212,168,67,0.14)'),
  3010.                     array('label' => 'Consumed''values' => $seriesFromRows($consumptionRows$monthKeys), 'color' => '#C05350''fill' => 'rgba(192,83,80,0.14)'),
  3011.                 ),
  3012.             ),
  3013.             'hero_summary' => array(
  3014.                 'headline' => $healthIndex '%',
  3015.                 'headline_label' => 'Health index',
  3016.                 'subhead' => 'Low stock pressure at ' $reorderPressure '%',
  3017.             ),
  3018.             'snapshot' => array(
  3019.                 'label' => 'Stock Health',
  3020.                 'ring_value' => $healthIndex,
  3021.                 'ring_note' => 'Health index',
  3022.                 'metrics' => array(
  3023.                     array('label' => 'Low Stock Pressure''value' => $reorderPressure '%''note' => 'At or under reorder'),
  3024.                     array('label' => 'Movement Balance''value' => $movementBalance'note' => 'Received minus consumed'),
  3025.                     array('label' => 'Avg Units / Warehouse''value' => $stockCoverage'note' => 'Distribution breadth'),
  3026.                     array('label' => 'Zero Stock SKUs''value' => $zeroStockCount'note' => 'Immediate attention'),
  3027.                 ),
  3028.             ),
  3029.             'lower_cards' => array(
  3030.                 array(
  3031.                     'title' => 'Reorder Radar',
  3032.                     'subtitle' => 'What needs intervention now',
  3033.                     'type' => 'radar',
  3034.                     'items' => array(
  3035.                         array('label' => 'Low Stock''value' => $lowStockCount'bar' => $skuCount ? (($lowStockCount $skuCount) * 100) : 0'note' => 'At reorder threshold'),
  3036.                         array('label' => 'Zero Stock''value' => $zeroStockCount'bar' => $skuCount ? (($zeroStockCount $skuCount) * 100) : 0'note' => 'Unavailable items'),
  3037.                         array('label' => 'Overstock''value' => $overstockCount'bar' => $skuCount ? (($overstockCount $skuCount) * 100) : 0'note' => 'Potential capital lock-up'),
  3038.                         array('label' => 'Movement Balance''value' => $movementBalance'bar' => max(0min(10050 + ($movementBalance 5))), 'note' => 'Inbound vs consumption'),
  3039.                     ),
  3040.                 ),
  3041.                 array(
  3042.                     'title' => 'Warehouse Atlas',
  3043.                     'subtitle' => 'Value concentration by store',
  3044.                     'type' => 'bars',
  3045.                     'items' => array_map(function ($row) use ($warehouseMap$topWarehouseTotal) {
  3046.                         $warehouseId = (int) $row['warehouse_id'];
  3047.                         $warehouseName = isset($warehouseMap[$warehouseId]['name']) ? $warehouseMap[$warehouseId]['name'] : ('Warehouse #' $warehouseId);
  3048.                         $total = (float) $row['total_value'];
  3049.                         return array(
  3050.                             'label' => $warehouseName,
  3051.                             'value' => $total,
  3052.                             'bar' => $topWarehouseTotal round(($total $topWarehouseTotal) * 1001) : 0,
  3053.                             'note' => 'Stock value share',
  3054.                         );
  3055.                     }, $warehouseRows),
  3056.                 ),
  3057.                 array(
  3058.                     'title' => 'Value Lens',
  3059.                     'subtitle' => 'Highest value stock pockets',
  3060.                     'type' => 'products',
  3061.                     'items' => array_map(function ($row) use ($topProductTotal) {
  3062.                         $total = (float) $row['total_value'];
  3063.                         $reorderLevel = isset($row['reorder_level']) ? (float) $row['reorder_level'] : 0;
  3064.                         return array(
  3065.                             'label' => $row['name'] ?: ('SKU #' $row['product_id']),
  3066.                             'value' => $total,
  3067.                             'bar' => $topProductTotal round(($total $topProductTotal) * 1001) : 0,
  3068.                             'note' => 'Reorder level ' number_format($reorderLevel0'.'','),
  3069.                         );
  3070.                     }, $productRows),
  3071.                 ),
  3072.             ),
  3073.             'months' => $monthLabels
  3074.         );
  3075.     }
  3076.     public function indexServiceAction(Request $request)
  3077.     {
  3078.         $session $request->getSession();
  3079.         $dashboardDataForUser = [];
  3080.         $em $this->getDoctrine()->getManager();
  3081.         $companyId $this->getLoggedUserCompanyId($request);
  3082.         $userId $request->getSession()->get(UserConstants::USER_ID);
  3083.         $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  3084.             array(
  3085.                 'CompanyId' => $companyId,
  3086.                 'userId' => $userId,
  3087.                 'status' => GeneralConstant::ACTIVE
  3088.             ),
  3089.             array(
  3090.                 'sequence' => 'ASC'
  3091.             )
  3092.         );
  3093.         if (empty($dbQuery))   ///now get the defaults
  3094.             $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  3095.                 array(
  3096.                     'CompanyId' => $companyId,
  3097.                     //                    'userId'=>$userId,
  3098.                     'defaultBoxFlag' => 1,
  3099.                     'status' => GeneralConstant::ACTIVE
  3100.                 ),
  3101.                 array(
  3102.                     'sequence' => 'ASC'
  3103.                 )
  3104.             );
  3105.         foreach ($dbQuery as $entry) {
  3106.             $dashboardDataForUser[] = array(
  3107.                 'id' => $entry->getId(),
  3108.                 'widgetId' => $entry->getId(),
  3109.                 'widgetSequence' => $entry->getSequence(),
  3110.                 'widgetStatus' => $entry->getStatus(),
  3111.                 'widgetData' => json_decode($entry->getData(), true),
  3112.                 'defaultBoxFlag' => $entry->getDefaultBoxFlag(),
  3113.                 'widgetSizeTiny' => $entry->getSizeTiny(),
  3114.                 'widgetSizeSmall' => $entry->getSizeSmall(),
  3115.                 'widgetSizeMedium' => $entry->getSizeMedium(),
  3116.                 'widgetSizeLarge' => $entry->getSizeLarge(),
  3117.                 'refreshInterval' => $entry->getRefreshInterval(),
  3118.             );
  3119.         }
  3120.         return $this->render(
  3121.             '@Application/pages/dashboard/index_sales.html.twig',
  3122.             array(
  3123.                 'page_title' => 'Sales Dashboard',
  3124.                 'dashboardDataForUser' => $dashboardDataForUser
  3125.             )
  3126.         );
  3127.     }
  3128.     public function modifyDashboardAction(Request $request)
  3129.     {
  3130.         $session $request->getSession();
  3131.         $em $this->getDoctrine()->getManager();
  3132.         $companyId $this->getLoggedUserCompanyId($request);
  3133.         $userId $request->getSession()->get(UserConstants::USER_ID);
  3134.         if ($request->isMethod('post')) {
  3135.             //update dashboard data
  3136.             if ($request->request->has('widgetId')) {
  3137.                 foreach ($request->request->get('widgetId') as $k => $v) {
  3138.                     if ($v != 0) {
  3139.                         //exists sso edit
  3140.                         $widget $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findOneBy(
  3141.                             array(
  3142.                                 'id' => $v,
  3143.                             )
  3144.                         );
  3145.                     } else
  3146.                         $widget = new DashboardWidget();
  3147.                     $widget->setData($request->request->get('widgetData')[$k]);
  3148.                     $widget->setSequence($request->request->get('widgetSequence')[$k]);
  3149.                     $widget->setStatus($request->request->has('widgetStatus') ? $request->request->get('widgetStatus')[$k] : GeneralConstant::ACTIVE);
  3150.                     $widget->setUserId($userId);
  3151.                     $widget->setCompanyId($companyId);
  3152.                     $widget->setDefaultBoxFlag($request->request->has('defaultBoxFlag') ? $request->request->get('defaultBoxFlag')[$k] : 0);
  3153.                     if ($v == 0)
  3154.                         $em->persist($widget);
  3155.                     $em->flush();
  3156.                 }
  3157.             }
  3158.         }
  3159.         $dashboardDataForUser = [];
  3160.         $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  3161.             array(
  3162.                 'CompanyId' => $companyId,
  3163.                 'userId' => $userId,
  3164.                 'status' => GeneralConstant::ACTIVE
  3165.             )
  3166.         );
  3167.         if (empty($dbQuery))   ///now get the defaults
  3168.             $dbQuery $em->getRepository("ApplicationBundle\\Entity\\DashboardWidget")->findBy(
  3169.                 array(
  3170.                     'CompanyId' => $companyId,
  3171.                     //                    'userId'=>$userId,
  3172.                     'defaultBoxFlag' => 1,
  3173.                     'status' => GeneralConstant::ACTIVE
  3174.                 )
  3175.             );
  3176.         foreach ($dbQuery as $entry) {
  3177.             $dashboardDataForUser[] = array(
  3178.                 'id' => $entry->getId(),
  3179.                 'widgetId' => $entry->getId(),
  3180.                 'widgetSequence' => $entry->getSequence(),
  3181.                 'widgetStatus' => $entry->getStatus(),
  3182.                 'widgetData' => $entry->getData(),
  3183.                 'defaultBoxFlag' => $entry->getDefaultBoxFlag(),
  3184.                 'widgetSizeTiny' => $entry->getSizeTiny(),
  3185.                 'widgetSizeSmall' => $entry->getSizeSmall(),
  3186.                 'widgetSizeMedium' => $entry->getSizeMedium(),
  3187.                 'widgetSizeLarge' => $entry->getSizeLarge(),
  3188.                 'refreshInterval' => $entry->getRefreshInterval(),
  3189.             );
  3190.         }
  3191.         //1st try to see if any exists
  3192.         return $this->render(
  3193.             '@Application/pages/dashboard/index_sales.html.twig',
  3194.             array(
  3195.                 'page_title' => 'Modify Dashboard'
  3196.             )
  3197.         );
  3198.     }
  3199.     public function ChangeCompanyDashboardAction(Request $request$id 1)
  3200.     {
  3201.         $session $request->getSession();
  3202.         if ($request->query->has('sys_admin_panel'))
  3203.             return $this->redirectToRoute('system_admin_dashboard');
  3204.         else {
  3205.             $session->set(UserConstants::USER_COMPANY_ID$id);
  3206.             return $this->redirectToRoute('dashboard');
  3207.         }
  3208.     }
  3209.     public function ChangeLeftPanelDisplayStatusAction(Request $request)
  3210.     {
  3211.         $session $request->getSession();
  3212.         $curr_status 1;
  3213.         if ($session->has('HIDE_LEFT_PANEL'))
  3214.             $curr_status $session->get('HIDE_LEFT_PANEL');
  3215.         if ($curr_status == 1)
  3216.             $curr_status 0;
  3217.         else
  3218.             $curr_status 1;
  3219.         $session->set('HIDE_LEFT_PANEL'$curr_status);
  3220.         //            return $this->redirectToRoute('dashboard');
  3221.         return new Response($curr_status);
  3222.     }
  3223.     public function PermissionDeniedAction(Request $request)
  3224.     {
  3225.         $session $request->getSession();
  3226.         // Generic::debugMessage($session);
  3227.         return $this->render(
  3228.             '@System/pages/permission_denied.html.twig',
  3229.             array(
  3230.                 'page_title' => 'Permission Denied'
  3231.             )
  3232.         );
  3233.     }
  3234.     public function MyDocumentsAction(Request $request)
  3235.     {
  3236.         $session $request->getSession();
  3237.         $em $this->getDoctrine()->getManager();
  3238.         $data MiscActions::getDocumentsByUserId($em$session->get(UserConstants::USER_ID));
  3239.         // DOC-001: the view calls path(item.documentViewPathName); if an entity's
  3240.         // registered view-route name is stale/unregistered, path() throws and the
  3241.         // whole page 500s the moment a user owns a document of that type. Validate
  3242.         // each route against the router and fall back to a safe one.
  3243.         $routes $this->container->get('router')->getRouteCollection();
  3244.         if (is_array($data)) {
  3245.             foreach ($data as $k => $item) {
  3246.                 $rn = isset($item['documentViewPathName']) ? $item['documentViewPathName'] : '';
  3247.                 if ($rn === '' || $routes->get($rn) === null) {
  3248.                     $data[$k]['documentViewPathName'] = 'dashboard';
  3249.                 }
  3250.             }
  3251.         }
  3252.         return $this->render(
  3253.             '@Application/pages/dashboard/my_documents.html.twig',
  3254.             array(
  3255.                 'page_title' => 'My Documents',
  3256.                 'data' => $data
  3257.             )
  3258.         );
  3259.     }
  3260.     //     public function MyDocumentsListForAppAction(Request $request)
  3261.     //     {
  3262.     //         $session = $request->getSession();
  3263.     //         $em = $this->getDoctrine()->getManager();
  3264.     //         $absoluteUrlList = [];
  3265.     //         foreach (GeneralConstant::$Entity_list_details as $e => $d) {
  3266.     //             if (isset($d['entity_print_route_path_name']))
  3267.     //                 $absoluteUrlList[$e] = $this->generateUrl($d['entity_print_route_path_name'], [], UrlGenerator::ABSOLUTE_URL);
  3268.     //         }
  3269.     //         $data = MiscActions::getDocumentsByUserIdForApp($em, $session->get(UserConstants::USER_ID), 1, $absoluteUrlList);
  3270.     //         // Generic::debugMessage($session);
  3271.     //         return new JsonResponse(array(
  3272.     //             'data' => $data
  3273.     //         ));
  3274.     // //        return $this->render('ApplicationBundle:pages/dashboard:my_documents.html.twig',
  3275.     // //            array(
  3276.     // //                'page_title' => 'My Documents',
  3277.     // //                'data' => $data
  3278.     // //            )
  3279.     // //        );
  3280.     //     }
  3281.     public function MyDocumentsListForAppAction(Request $request)
  3282.     {
  3283.         $session $request->getSession();
  3284.         $em $this->getDoctrine()->getManager();
  3285.         // Build absolute URL list
  3286.         $absoluteUrlList = [];
  3287.         foreach (GeneralConstant::$Entity_list_details as $e => $d) {
  3288.             if (isset($d['entity_print_route_path_name'])) {
  3289.                 $absoluteUrlList[$e] = $this->generateUrl($d['entity_print_route_path_name'], [], UrlGenerator::ABSOLUTE_URL);
  3290.             }
  3291.         }
  3292.         // Extract pagination parameters from the request
  3293.         $page $request->query->get('page''_UNSET_');
  3294.         $offset $request->query->get('offset'0);
  3295.         $limit $request->query->get('limit'10); // default limit is 10
  3296.         // Call the document list method with pagination
  3297.         return new JsonResponse(
  3298.             MiscActions::getDocumentsByUserIdForApp(
  3299.                 $em,
  3300.                 $session->get(UserConstants::USER_ID),
  3301.                 1,
  3302.                 $absoluteUrlList,
  3303.                 $page,
  3304.                 $offset,
  3305.                 $limit
  3306.             )
  3307.         );
  3308.     }
  3309.     public function ShowExceptionAction(Request $requestFlattenException $exceptionDebugLoggerInterface $logger null)
  3310.     {
  3311.         $session $request->getSession();
  3312.         $em $this->getDoctrine()->getManager();
  3313.         // Generic::debugMessage($session);
  3314.         //        $currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
  3315.         //        $showException = $request->attributes->get('showException', $this->debug); // As opposed to an additional parameter, this maintains BC
  3316.         $code $exception->getStatusCode();
  3317.         //        $data = MiscActions::getDocumentsByUserId($em, $session->get(UserConstants::USER_ID));
  3318.         return $this->render(
  3319.             '@Application/pages/error/error_' $code '.html.twig',
  3320.             array(
  3321.                 'page_title' => 'Sorry',
  3322.                 //                'data' => $data
  3323.             )
  3324.         );
  3325.     }
  3326.     public function NotificationAction(Request $request)
  3327.     {
  3328.         $session $request->getSession();
  3329.         //'error', 'success', 'alert', 'information', 'warning', 'confirm'
  3330.         $themes = array(
  3331.             'error' => 'bg-red',
  3332.             'success' => 'bg-green',
  3333.             'alert' => 'bg-purple',
  3334.             'information' => 'bg-grey',
  3335.             'warning' => 'bg-orange',
  3336.             'confirm' => 'bg-blue',
  3337.         );
  3338.         $fa = array(
  3339.             'error' => 'fa fa-ban',
  3340.             'success' => 'fa fa-check',
  3341.             'alert' => 'fa fa-envelope',
  3342.             'information' => 'fa fa-comments',
  3343.             'warning' => 'fa fa-warning',
  3344.             'confirm' => 'fa fa-crosshairs',
  3345.         );
  3346.         // Generic::debugMessage($session);
  3347.         // â”€â”€ DB-first notification list â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
  3348.         // History is sourced from entity_notification (persistent DB), not the
  3349.         // socket server's in-memory cache which is lost on restart / missing the
  3350.         // /get_all_notification endpoint entirely.
  3351.         $cgEm   $this->getDoctrine()->getManager('company_group');
  3352.         $userId = (int) $request->getSession()->get(UserConstants::USER_ID0);
  3353.         $companyId = (int) $request->getSession()->get(UserConstants::USER_COMPANY_ID0);
  3354.         $filterUnread $request->query->get('filter') === 'unread';
  3355.         $qb $cgEm->getRepository('CompanyGroupBundle\\Entity\\EntityNotification')
  3356.             ->createQueryBuilder('n')
  3357.             ->where('n.userId = :uid')
  3358.             ->setParameter('uid'$userId);
  3359.         if ($filterUnread) {
  3360.             $qb->andWhere('n.seenFlag = 0');
  3361.         }
  3362.         $notifications $qb
  3363.             ->orderBy('n.notificationTs''DESC')
  3364.             ->setMaxResults(100)
  3365.             ->getQuery()
  3366.             ->getResult();
  3367.         $unreadCount = (int) $cgEm->getConnection()->fetchOne(
  3368.             'SELECT COUNT(*) FROM entity_notification WHERE user_id = :uid AND seen_flag = 0',
  3369.             ['uid' => $userId]
  3370.         );
  3371.         return $this->render(
  3372.             '@Application/pages/dashboard/notification.html.twig',
  3373.             array(
  3374.                 'page_title'    => 'Notifications',
  3375.                 'dt'            => $notifications,
  3376.                 'unreadCount'   => $unreadCount,
  3377.                 'filterUnread'  => $filterUnread,
  3378.                 'themes'        => $themes,
  3379.                 'fa'            => $fa,
  3380.             )
  3381.         );
  3382.     }
  3383.     public function NotificationDetailAction(Request $request$id 0)
  3384.     {
  3385.         $em $this->getDoctrine()->getManager('company_group');
  3386.         $notification $em->getRepository('CompanyGroupBundle\\Entity\\EntityNotification')->find($id);
  3387.         if (!$notification) {
  3388.             return $this->render(
  3389.                 '@Application/pages/dashboard/notification_detail.html.twig',
  3390.                 array(
  3391.                     'page_title' => 'Notification Detail',
  3392.                     'notification' => null,
  3393.                     'detailError' => 'Notification not found.',
  3394.                 )
  3395.             );
  3396.         }
  3397.         if ((int) $notification->getSeenFlag() !== 1) {
  3398.             $notification->setSeenFlag(1);
  3399.         }
  3400.         if ((int) $notification->getReadFlag() !== 1) {
  3401.             $notification->setReadFlag(1);
  3402.         }
  3403.         $em->flush();
  3404.         return $this->render(
  3405.             '@Application/pages/dashboard/notification_detail.html.twig',
  3406.             array(
  3407.                 'page_title' => 'Notification Detail',
  3408.                 'notification' => $notification,
  3409.                 'detailError' => '',
  3410.             )
  3411.         );
  3412.     }
  3413.     public function EditAccountAction(Request $request)
  3414.     {
  3415.         $session $request->getSession();
  3416.         //'error', 'success', 'alert', 'information', 'warning', 'confirm'
  3417.         $themes = array(
  3418.             'error' => 'bg-red',
  3419.             'success' => 'bg-green',
  3420.             'alert' => 'bg-purple',
  3421.             'information' => 'bg-aqua',
  3422.             'warning' => 'bg-orange',
  3423.             'confirm' => 'bg-blue',
  3424.         );
  3425.         $fa = array(
  3426.             'error' => 'fa fa-ban',
  3427.             'success' => 'fa fa-check',
  3428.             'alert' => 'fa fa-envelope',
  3429.             'information' => 'fa fa-comments',
  3430.             'warning' => 'fa fa-warning',
  3431.             'confirm' => 'fa fa-crosshairs',
  3432.         );
  3433.         $em $this->getDoctrine()->getManager();
  3434.         $g_path '';
  3435.         if ($request->isMethod('POST')) {
  3436.             $post $request->request;
  3437.             $path "";
  3438.             foreach ($request->files as $uploadedFile) {
  3439.                 if ($uploadedFile != null) {
  3440.                     $fileName md5(uniqid()) . '.' $uploadedFile->guessExtension();
  3441.                     $path $fileName;
  3442.                     $upl_dir $this->container->getParameter('kernel.root_dir') . '/../web/uploads/FileUploads/' $request->request->get('userId') . '/';
  3443.                     if (!file_exists($upl_dir)) {
  3444.                         mkdir($upl_dir0777true);
  3445.                     }
  3446.                     $file $uploadedFile->move($upl_dir$path);
  3447.                 }
  3448.             }
  3449.             if ($path != "")
  3450.                 $file_path 'uploads/FileUploads/' $request->request->get('userId') . '/' $path;
  3451.             $g_path $this->container->getParameter('kernel.root_dir') . '/../web/uploads/FileUploads/' $request->request->get('userId') . '/' $path;
  3452.             //            $img_file = file_get_contents($g_path);
  3453.             //            $image_data=base64_encode($img_file);
  3454.             //            $encoded_data=System::encryptSignature($image_data,$request->request->get('approvalHash'));
  3455.             $query_here $this->getDoctrine()
  3456.                 ->getRepository('ApplicationBundle\\Entity\\SysUser')
  3457.                 ->findOneBy(
  3458.                     array('userId' => $request->request->get('userId'))
  3459.                 );
  3460.             if ($query_here) {
  3461.                 $new $query_here;
  3462.                 if ($path != "") {
  3463.                     if ($request->request->has('check_pp')) {
  3464.                         $new->setImage($file_path);
  3465.                         $session->set(UserConstants::USER_IMAGE$new->getImage());
  3466.                     } else
  3467.                         $new->setImage('');
  3468.                 }
  3469.                 $new->setName($request->request->get('name'));
  3470.                 $session->set(UserConstants::USER_NAME$request->request->get('name'));
  3471.                 //now password
  3472.                 if ($request->request->get('oldPass') != '') {
  3473.                     //1st check if old pass valid
  3474.                     if (!$this->container->get('app.legacy_password_service')->verifyWithSalt($new->getPassword(), $request->request->get('oldPass'), $new->getSalt())) {
  3475.                         $this->addFlash(
  3476.                             'error',
  3477.                             'Your Old Password Was Wrong'
  3478.                         );
  3479.                     } else {
  3480.                         //old pass valid so now check if neww passes matches
  3481.                         if ($request->request->get('newPass') == $request->request->get('newPassAgain')) {
  3482.                             $new->setSalt(uniqid(mt_rand()));
  3483.                             $password $this->container->get('app.legacy_password_service')->hashWithSalt($request->request->get('newPass'), $new->getSalt());
  3484.                             $new->setPassword($password);
  3485.                             $em->flush();
  3486.                         } else {
  3487.                             $this->addFlash(
  3488.                                 'error',
  3489.                                 'Passwords Did not Match'
  3490.                             );
  3491.                         }
  3492.                     }
  3493.                 }
  3494.             } else {
  3495.                 //                    $new=new EncryptedSignature();
  3496.                 //                    $new->setData($encoded_data);
  3497.                 //                    $new->setUserId($request->request->get('userId'));
  3498.                 //                    $em->persist($new);
  3499.             }
  3500.             $em->flush();
  3501.             //            now deleting the file
  3502.         }
  3503.         $user_data Users::getUserInfoByLoginId($em$this->getLoggedUserLoginId($request));
  3504.         // Generic::debugMessage($session);
  3505.         return $this->render(
  3506.             '@System/pages/settings/edit_account.html.twig',
  3507.             array(
  3508.                 'page_title' => 'Edit Account',
  3509.                 'user_data' => $user_data,
  3510.                 //                'dt'=>json_decode(System::GetAllNotification($request->getSession()->get(UserConstants::USER_ID)),true),
  3511.                 'themes' => $themes,
  3512.                 'fa' => $fa,
  3513.             )
  3514.         );
  3515.     }
  3516.     public function indexApplicantAction(Request $request)
  3517.     {
  3518.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  3519.         $twig_file '@Application/pages/login/applicant_login.html.twig';
  3520.         $session $request->getSession();
  3521.         if ($systemType == '_BUDDYBEE_') {
  3522.             if ($session->get('buddybeeAdminLevel'0) > 1)
  3523.                 return $this->redirectToRoute("buddybee_admin_dashboard", []);
  3524.             elseif ($session->get('isConsultant') == 1)
  3525.                 return $this->redirectToRoute("consultant_dashboard", []);
  3526.             else
  3527.                 return $this->redirectToRoute("student_dashboard", []);
  3528.         } elseif ($systemType == '_CENTRAL_') {
  3529.             return $this->render(
  3530.                 '@Application/pages/dashboard/index_applicant.html.twig',
  3531.                 array(
  3532.                     'page_title' => 'Applicant Dashboard'
  3533.                 )
  3534.             );
  3535.         } else
  3536.             return $this->render(
  3537.                 '@Application/pages/dashboard/consultant_dashboard.html.twig',
  3538.                 array(
  3539.                     'page_title' => 'Applicant Dashboard'
  3540.                 )
  3541.             );
  3542.     }
  3543.     public function indexCentralLandingAction(Request $request)
  3544.     {
  3545.         $session $request->getSession();
  3546.         $userAccessList $session->get('userAccessList', []);
  3547.         $companyNames array_map(function ($company) {
  3548.             return $company['companyName'];
  3549.         }, $userAccessList);
  3550.         if ($request->isMethod('POST')) {
  3551.             $employeeId $request->request->get('employee_id');
  3552.             $companyName $request->request->get('company_name');
  3553.             if ($employeeId && $companyName) {
  3554.                 return new JsonResponse([
  3555.                     'status' => 'success',
  3556.                     'message' => 'Data received successfully',
  3557.                     'employee_id' => $employeeId,
  3558.                     'company_name' => $companyName,
  3559.                 ]);
  3560.             } else {
  3561.                 return new JsonResponse([
  3562.                     'status' => 'error',
  3563.                     'message' => 'Employee ID or Company Name is missing',
  3564.                 ]);
  3565.             }
  3566.         }
  3567.         // If the request is not a POST request, render the normal page
  3568.         return $this->render(
  3569.             '@Application/pages/dashboard/index_central_landing.html.twig',
  3570.             [
  3571.                 'page_title' => 'Central Landing',
  3572.                 'companyNames' => $companyNames
  3573.             ]
  3574.         );
  3575.     }
  3576.     public function HummanResourceAction()
  3577.     {
  3578.         $em $this->getDoctrine()->getManager();
  3579.         $currentTime = new \Datetime();
  3580.         $currDate $currentTime->format('Y-m-d');
  3581.         $queryBuilder $em->createQueryBuilder();
  3582.         $queryBuilder->select('A.employeeId''A.entry''A.lastIn''A.lastOut''A.currentLocation','A.createdAt''E.name','E.image','D.positionName')
  3583.             ->from('ApplicationBundle\\Entity\\EmployeeAttendance''A')
  3584.             ->where('A.createdAt >=  :date')
  3585.             ->andWhere('A.createdAt <=  :date_end')
  3586.             ->leftJoin('ApplicationBundle\\Entity\\Employee''E''WITH''A.employeeId = E.employeeId')
  3587.             ->leftJoin('ApplicationBundle\\Entity\\SysDepartmentPosition''D''WITH''E.positionId = D.positionId')
  3588.             ->setParameter('date'$currDate)
  3589.             ->setParameter('date_end'$currDate ' 23:59:59')
  3590.             ->orderBy('A.createdAt''DESC'// latest records first
  3591.             ->setMaxResults(5); // limit to 5 records
  3592.         $data $queryBuilder->getQuery()->getResult();
  3593.         $formattedData array_map(function($item) {
  3594.             return [
  3595.                 'employeeId' => $item['employeeId'],
  3596.                 'entry' => $item['entry'] ? $item['entry']->format('Y-m-d H:i:s') : null,
  3597.                 'lastIn' => $item['lastIn'] ? $item['lastIn']->format('Y-m-d H:i:s') : null,
  3598.                 'lastOut' => $item['lastOut'] ? $item['lastOut']->format('Y-m-d H:i:s') : null,
  3599.                 'currentLocation' => $item['currentLocation'],
  3600.                 'createdAt' => $item['createdAt'] ? $item['createdAt']->format('Y-m-d H:i:s') : null,
  3601.                 'name' => $item['name'],
  3602.                 'image' => $item['image'],
  3603.                 'positionName' => $item['positionName'],
  3604.             ];
  3605.         }, $data);
  3606.         $totalEmployees $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3607.             ->createQueryBuilder('E')
  3608.             ->select('COUNT(E.emp_status)')
  3609.             ->where('E.emp_status = 1')
  3610.             ->getQuery()
  3611.             ->getSingleScalarResult();
  3612.         $maleCount $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3613.             ->createQueryBuilder('E')
  3614.             ->select('COUNT(E.id)')
  3615.             ->where('E.sex = 1')
  3616.             ->getQuery()
  3617.             ->getSingleScalarResult();
  3618.         $femaleCount $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3619.             ->createQueryBuilder('E')
  3620.             ->select('COUNT(E.id)')
  3621.             ->where('E.sex = 2')
  3622.             ->getQuery()
  3623.             ->getSingleScalarResult();
  3624.         $fullTime $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3625.             ->createQueryBuilder('E')
  3626.             ->select('COUNT(E.id)')
  3627.             ->where('E.empType = 1')
  3628.             ->getQuery()
  3629.             ->getSingleScalarResult();
  3630.         $partTime $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3631.             ->createQueryBuilder('E')
  3632.             ->select('COUNT(E.id)')
  3633.             ->where('E.empType = 2')
  3634.             ->getQuery()
  3635.             ->getSingleScalarResult();
  3636.         $intern $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3637.             ->createQueryBuilder('E')
  3638.             ->select('COUNT(E.id)')
  3639.             ->where('E.empType = 3')
  3640.             ->getQuery()
  3641.             ->getSingleScalarResult();
  3642.         $temporary $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3643.             ->createQueryBuilder('E')
  3644.             ->select('COUNT(E.id)')
  3645.             ->where('E.empType = 4')
  3646.             ->getQuery()
  3647.             ->getSingleScalarResult();
  3648.         $contractual $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  3649.             ->createQueryBuilder('E')
  3650.             ->select('COUNT(E.id)')
  3651.             ->where('E.empType = 5')
  3652.             ->getQuery()
  3653.             ->getSingleScalarResult();
  3654.         return $this->render(
  3655.             '@Application/pages/dashboard/humanResource.html.twig',
  3656.             [
  3657.                 'page_title' => 'Human Resource Dashboard',
  3658.                 'attendanceDetails' => $formattedData,
  3659.                 'totalEmployee' => $totalEmployees,
  3660.                 'maleCount' => $maleCount,
  3661.                 'femaleCount' => $femaleCount,
  3662.                 'fullTime' => $fullTime,
  3663.                 'partTime' => $partTime,
  3664.                 'temporary' => $temporary,
  3665.                 'contractual' => $contractual,
  3666.                 'intern' => $intern,
  3667.             ]
  3668.         );
  3669.     }
  3670.     public function projectCashFlowReportAction(Request $request)
  3671.     {
  3672.         $em $this->getDoctrine()->getManager();
  3673.         $context $request->query->get('context''finance'); // 'finance' | 'projects' â€” only tweaks the active nav item
  3674.         $cashFlow = ['hasData' => false];
  3675.         try {
  3676.             $cashFlow $this->buildCompanyCashFlow($em12);
  3677.         } catch (\Throwable $e) {
  3678.             $cashFlow = ['hasData' => false'error' => $e->getMessage()];
  3679.         }
  3680.         return $this->render(
  3681.             '@Application/pages/dashboard/cash_flow_report.html.twig',
  3682.             array(
  3683.                 'page_title' => 'Cash Flow Report',
  3684.                 'cashFlow'   => $cashFlow,
  3685.                 'context'    => $context,
  3686.             )
  3687.         );
  3688.     }
  3689.     /**
  3690.      * Company cash-flow: real monthly cash inflow / outflow / net + running balance over the
  3691.      * last N months, derived from posted GL movements on the Cash &amp; Cash Equivalents head
  3692.      * subtree (marker _CACEP_ + path_tree descendants) â€” the same definition the financial
  3693.      * statements use. Base-currency amounts (amount x currency_multiply_rate). Fail-safe.
  3694.      */
  3695.     private function buildCompanyCashFlow($em$monthsBack 12)
  3696.     {
  3697.         $conn $em->getConnection();
  3698.         $cashMarker = \ApplicationBundle\Constants\AccountsConstant::CASH_AND_CASH_EQUIVALENT_PARENT;
  3699.         $result = [
  3700.             'hasData' => false,
  3701.             'labels' => [], 'inflow' => [], 'outflow' => [], 'net' => [], 'balance' => [],
  3702.             'totalInflow' => 0'totalOutflow' => 0'totalNet' => 0,
  3703.             'openingBalance' => 0'closingBalance' => 0'rows' => [],
  3704.         ];
  3705.         // 1. Resolve cash &amp; bank head ids: heads marked _CACEP_ plus their path_tree descendants.
  3706.         $marked $conn->fetchAllAssociative(
  3707.             'SELECT accounts_head_id FROM acc_accounts_head WHERE marker_hash LIKE ?',
  3708.             ['%' $cashMarker '%']
  3709.         );
  3710.         $ids = [];
  3711.         $likeParts = [];
  3712.         $params = [];
  3713.         foreach ($marked as $m) {
  3714.             $hid = (int) $m['accounts_head_id'];
  3715.             $ids[$hid] = $hid;
  3716.             $likeParts[] = 'path_tree LIKE ?';
  3717.             $params[] = '%/' $hid '/%';
  3718.         }
  3719.         if (!empty($likeParts)) {
  3720.             foreach ($conn->fetchAllAssociative('SELECT accounts_head_id FROM acc_accounts_head WHERE ' implode(' OR '$likeParts), $params) as $d) {
  3721.                 $ids[(int) $d['accounts_head_id']] = (int) $d['accounts_head_id'];
  3722.             }
  3723.         }
  3724.         $cashHeadIds array_values($ids);
  3725.         if (empty($cashHeadIds)) {
  3726.             return $result// hasData=false â†’ the page shows a friendly "no cash heads marked" notice
  3727.         }
  3728.         $inClause  implode(','array_map('intval'$cashHeadIds));
  3729.         $baseExpr  "td.amount * COALESCE(NULLIF(td.currency_multiply_rate, ''), 1)";
  3730.         $drCond    "(LOWER(td.position) LIKE 'dr%' OR LOWER(td.position) = 'debit')";
  3731.         $start = new \DateTime('first day of this month 00:00:00');
  3732.         $start->modify('-' . ($monthsBack 1) . ' months');
  3733.         $startStr $start->format('Y-m-d 00:00:00');
  3734.         // Opening cash balance (Dr - Cr) before the window.
  3735.         $openRow $conn->fetchAssociative(
  3736.             "SELECT SUM(CASE WHEN $drCond THEN $baseExpr ELSE -($baseExpr) END) bal
  3737.              FROM acc_transaction_details td
  3738.              JOIN acc_transactions t ON t.transaction_id = td.transaction_id
  3739.              WHERE td.accounts_head_id IN ($inClause) AND td.ledger_hit = 1 AND t.transaction_date < ?",
  3740.             [$startStr]
  3741.         );
  3742.         $opening = (float) ($openRow['bal'] ?? 0);
  3743.         // Monthly movements inside the window.
  3744.         $rows $conn->fetchAllAssociative(
  3745.             "SELECT DATE_FORMAT(t.transaction_date, '%Y-%m') ym,
  3746.                     SUM(CASE WHEN $drCond THEN $baseExpr ELSE 0 END) inflow,
  3747.                     SUM(CASE WHEN NOT $drCond THEN $baseExpr ELSE 0 END) outflow
  3748.              FROM acc_transaction_details td
  3749.              JOIN acc_transactions t ON t.transaction_id = td.transaction_id
  3750.              WHERE td.accounts_head_id IN ($inClause) AND td.ledger_hit = 1 AND t.transaction_date >= ?
  3751.              GROUP BY ym",
  3752.             [$startStr]
  3753.         );
  3754.         $byMonth = [];
  3755.         foreach ($rows as $r) {
  3756.             $byMonth[$r['ym']] = ['in' => (float) $r['inflow'], 'out' => (float) $r['outflow']];
  3757.         }
  3758.         $running $opening;
  3759.         $cursor = clone $start;
  3760.         for ($i 0$i $monthsBack$i++) {
  3761.             $ym $cursor->format('Y-m');
  3762.             $in  = isset($byMonth[$ym]) ? $byMonth[$ym]['in']  : 0.0;
  3763.             $out = isset($byMonth[$ym]) ? $byMonth[$ym]['out'] : 0.0;
  3764.             $net $in $out;
  3765.             $running += $net;
  3766.             $result['labels'][]  = $cursor->format('M Y');
  3767.             $result['inflow'][]  = round($in2);
  3768.             $result['outflow'][] = round($out2);
  3769.             $result['net'][]     = round($net2);
  3770.             $result['balance'][] = round($running2);
  3771.             $result['rows'][]    = ['label' => $cursor->format('M Y'), 'inflow' => round($in2), 'outflow' => round($out2), 'net' => round($net2), 'balance' => round($running2)];
  3772.             $result['totalInflow']  += $in;
  3773.             $result['totalOutflow'] += $out;
  3774.             $cursor->modify('+1 month');
  3775.         }
  3776.         $result['hasData']        = true;
  3777.         $result['openingBalance'] = round($opening2);
  3778.         $result['closingBalance'] = round($running2);
  3779.         $result['totalNet']       = round($result['totalInflow'] - $result['totalOutflow'], 2);
  3780.         $result['totalInflow']    = round($result['totalInflow'], 2);
  3781.         $result['totalOutflow']   = round($result['totalOutflow'], 2);
  3782.         return $result;
  3783.     }
  3784.     public function PerformanceReviewDashboardAction()
  3785.     {
  3786.         return $this->render(
  3787.             '@Application/pages/dashboard/performance_review_dashboard.html.twig',
  3788.             array(
  3789.                 'page_title' => 'Performance Review Dashboard'
  3790.             )
  3791.         );
  3792.     }
  3793.     public function RecruitmentDashboardAction(Request $request)
  3794.     {
  3795.         $em $this->getDoctrine()->getManager();
  3796.         $em_goc $this->getDoctrine()->getManager('company_group');
  3797.         $companyId $this->getLoggedUserCompanyId($request);
  3798.         $company_data Company::getCompanyData($em$companyId);
  3799.         // 1. Total Job Posts
  3800.         $totalJobPosts $em->getRepository('ApplicationBundle\\Entity\\JobRecruitment')
  3801.             ->createQueryBuilder('j')
  3802.             ->select('COUNT(j.jobRecruitmentId)')
  3803.             ->where('j.approved = 1')
  3804.             ->getQuery()
  3805.             ->getSingleScalarResult();
  3806.         // 2. Active Job Posts
  3807.         $activeJobPosts $em->getRepository('ApplicationBundle\\Entity\\JobRecruitment')
  3808.             ->createQueryBuilder('j')
  3809.             ->select('COUNT(j.jobRecruitmentId)')
  3810.             ->where('j.approved = 1')
  3811.             ->andWhere('j.jobOpeningStatus = 2'// Assuming 2 is Active
  3812.             ->getQuery()
  3813.             ->getSingleScalarResult();
  3814.         // 3. Total Applicants
  3815.         $totalApplicants $em_goc->getRepository("CompanyGroupBundle\\Entity\\EntityApplicantApplicationList")
  3816.             ->createQueryBuilder('a')
  3817.             ->select('COUNT(a.id)')
  3818.             ->where('a.CompanyId = :companyId')
  3819.             ->andWhere('a.appId = :appId')
  3820.             ->setParameter('companyId'$companyId)
  3821.             ->setParameter('appId'$company_data->getAppId())
  3822.             ->getQuery()
  3823.             ->getSingleScalarResult();
  3824.         // 4. Simple recent activity for dashboard
  3825.         $recentJobs $em->getRepository('ApplicationBundle\\Entity\\JobRecruitment')
  3826.             ->findBy(['approved' => 1], ['createdAt' => 'DESC'], 5);
  3827.         // 5. Jobs with applicant counts
  3828.         $jobsWithApplicantCount $em->getRepository('ApplicationBundle\\Entity\\JobRecruitment')
  3829.             ->createQueryBuilder('j')
  3830.             ->select('j.jobRecruitmentId''j.title''j.applicationClosingDate''j.jobOpeningStatus')
  3831.             ->where('j.approved = 1')
  3832.             ->orderBy('j.createdAt''DESC')
  3833.             ->setMaxResults(8)
  3834.             ->getQuery()
  3835.             ->getResult();
  3836.         foreach ($jobsWithApplicantCount as &$job) {
  3837.             $count $em_goc->getRepository("CompanyGroupBundle\\Entity\\EntityApplicantApplicationList")
  3838.                 ->createQueryBuilder('a')
  3839.                 ->select('COUNT(a.id)')
  3840.                 ->where('a.jobPostId = :jobId')
  3841.                 ->setParameter('jobId'$job['jobRecruitmentId'])
  3842.                 ->getQuery()
  3843.                 ->getSingleScalarResult();
  3844.             $job['applicantCount'] = $count;
  3845.         }
  3846.         return $this->render(
  3847.             '@Application/pages/dashboard/recruitment_dashboard.html.twig',
  3848.             array(
  3849.                 'page_title' => 'Recruitment Dashboard',
  3850.                 'totalJobPosts' => $totalJobPosts,
  3851.                 'activeJobPosts' => $activeJobPosts,
  3852.                 'totalApplicants' => $totalApplicants,
  3853.                 'recentJobs' => $recentJobs,
  3854.                 'jobsWithApplicantCount' => $jobsWithApplicantCount,
  3855.                 'jobOpeningStatusArr' => HumanResourceConstant::$jobOpeningStatus
  3856.             )
  3857.         );
  3858.     }
  3859.     public function TalentManagementDashboardAction()
  3860.     {
  3861.         return $this->render(
  3862.             '@Application/pages/dashboard/talent_management_dashboard.html.twig',
  3863.             array(
  3864.                 'page_title' => 'Talent Management Dashboard'
  3865.             )
  3866.         );
  3867.     }
  3868.     public function CreateCompanyAction(Request $request)
  3869.     {
  3870.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  3871.         $appId $request->get('app_id'0);
  3872.         $post $request;
  3873.         $session $request->getSession();
  3874.         if ($request->isMethod('POST')) {
  3875.             if ($systemType == '_CENTRAL_') {
  3876.                 $em_goc $this->getDoctrine()->getManager('company_group');
  3877.                 $em_goc->getConnection()->connect();
  3878.                 $connected $em_goc->getConnection()->isConnected();
  3879.                 $gocDataList = [];
  3880.                 if ($connected) {
  3881.                     $goc null;
  3882.                     $serverList MiscActions::getServerListById(                     $this->container->getParameter('database_user'),                     $this->container->getParameter('database_password'),                     $this->container->hasParameter('server_access_list') ?$this->container->getParameter('server_access_list') :[]                 );
  3883.                     $companyGroupHash $post->get('company_short_code''');
  3884.                     $defaultUsageDate = new \DateTime();
  3885.                     $defaultUsageDate->modify('+1 year');
  3886.                     $usageValidUpto = new \DateTime($post->get('usage_valid_upto_dt_str'$defaultUsageDate->format('Y-m-d')));
  3887.                     $companyGroupServerId $post->get('server_id'1);
  3888.                     $companyGroupServerAddress $serverList[$companyGroupServerId]['absoluteUrl'];
  3889.                     $companyGroupServerPort $serverList[$companyGroupServerId]['port'];
  3890.                     $companyGroupServerHash $serverList[$companyGroupServerId]['serverMarker'];
  3891.                     //                $dbUser=
  3892.                     if ($appId != 0)
  3893.                         $goc $this->getDoctrine()->getManager('company_group')
  3894.                             ->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup")
  3895.                             ->findOneBy(array(
  3896.                                 'appId' => $appId
  3897.                             ));
  3898.                     if (!$goc)
  3899.                         $goc = new CompanyGroup();
  3900.                     if ($appId == 0) {
  3901.                         $biggestAppIdCg $this->getDoctrine()->getManager('company_group')
  3902.                             ->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup")
  3903.                             ->findOneBy(array( //                            'appId' => $appId
  3904.                             ), array(
  3905.                                 'appId' => 'desc'
  3906.                             ));
  3907.                         if ($biggestAppIdCg)
  3908.                             $appId $biggestAppIdCg->getAppId();
  3909.                     }
  3910.                     $goc->setName($post->get('company_name'));
  3911.                     $goc->setCompanyGroupHash($companyGroupHash);
  3912.                     $goc->setAppId($appId);
  3913.                     $goc->setActive(1);
  3914.                     $goc->setAddress($post->get('address'));
  3915.                     $goc->setShippingAddress($post->get('s_address'));
  3916.                     $goc->setBillingAddress($post->get('b_address'));
  3917.                     $goc->setMotto($post->get('motto'));
  3918.                     $goc->setInitiateFlag($post->get('initiate_flag'3));
  3919.                     $goc->setInvoiceFooter($post->get('i_footer'));
  3920.                     $goc->setGeneralFooter($post->get('g_footer'));
  3921.                     $goc->setCompanyReg($post->get('company_reg'''));
  3922.                     $goc->setCompanyTin($post->get('company_tin'''));
  3923.                     $goc->setCompanyBin($post->get('company_bin'''));
  3924.                     $goc->setCompanyTl($post->get('company_tl'''));
  3925.                     $goc->setCompanyType($post->get('company_type'''));
  3926.                     $goc->setCurrentSubscriptionPackageId($post->get('package'1));
  3927.                     $goc->setUsageValidUptoDate($usageValidUpto);
  3928.                     $goc->setUsageValidUptoDateTs($usageValidUpto->format('U'));
  3929.                     //                $goc->setCu($post->get('package', ''));
  3930.                     $goc->setAdminUserAllowed($post->get('number_of_admin_user'1));
  3931.                     $goc->setUserAllowed($post->get('number_of_user'2));
  3932.                     $goc->setSubscriptionMonth($post->get('subscription_month'1));
  3933.                     $goc->setCompanyDescription($post->get('company_description'''));
  3934.                     $goc->setDbUser($post->get('db_user'));
  3935.                     $goc->setDbPass($post->get('db_pass'));
  3936.                     $goc->setDbHost($post->get('db_host'));
  3937.                     $goc->setOwnerId($session->get(UserConstants::USER_ID));
  3938.                     $goc->setCompanyGroupServerId($companyGroupServerId);
  3939.                     $goc->setCompanyGroupServerAddress($companyGroupServerAddress);
  3940.                     $goc->setCompanyGroupServerPort($companyGroupServerPort);
  3941.                     $goc->setCompanyGroupServerHash($companyGroupServerHash);
  3942.                     foreach ($request->files as $uploadedFile) {
  3943.                         if ($uploadedFile != null) {
  3944.                             $fileName 'company_image' $appId '.' $uploadedFile->guessExtension();
  3945.                             $path $fileName;
  3946.                             $upl_dir $this->container->getParameter('kernel.root_dir') . '/../web/uploads/CompanyImage/';
  3947.                             if ($goc->getImage() != null && $goc->getImage() != '' && file_exists($this->container->getParameter('kernel.root_dir') . '/../web' $goc->getImage())) {
  3948.                                 unlink($this->container->getParameter('kernel.root_dir') . '/../web' $goc->getImage());
  3949.                             }
  3950.                             if (!file_exists($upl_dir)) {
  3951.                                 mkdir($upl_dir0777true);
  3952.                             }
  3953.                             $file $uploadedFile->move($upl_dir$path);
  3954.                             if ($path != "")
  3955.                                 $goc->setImage('/uploads/CompanyImage/' $path);
  3956.                         }
  3957.                     }
  3958.                     $em_goc->persist($goc);
  3959.                     $em_goc->flush();
  3960.                     $goc->setDbName('cg_' $appId '_' $companyGroupHash);
  3961.                     $goc->setDbUser($serverList[$companyGroupServerId]['dbUser']);
  3962.                     $goc->setDbPass($serverList[$companyGroupServerId]['dbPass']);
  3963.                     $goc->setDbHost('localhost');
  3964.                     $em_goc->flush();
  3965.                     $centralUser $this->getDoctrine()->getManager('company_group')
  3966.                         ->getRepository("CompanyGroupBundle\\Entity\\EntityApplicantDetails")
  3967.                         ->findOneBy(array(
  3968.                             'applicantId' => $session->get(UserConstants::USER_ID0)
  3969.                         ));
  3970.                     if ($centralUser) {
  3971.                         $userAppIds json_decode($centralUser->getUserAppIds(), true);
  3972.                         $userTypesByAppIds json_decode($centralUser->getUserTypesByAppIds(), true);
  3973.                         if ($userAppIds == null$userAppIds = [];
  3974.                         if ($userTypesByAppIds == null$userTypesByAppIds = [];
  3975.                         $userAppIds array_merge($userAppIdsarray_diff([$appId], $userAppIds));
  3976.                         if (!isset($userTypesByAppIds[$appId])) {
  3977.                             $userTypesByAppIds[$appId] = [];
  3978.                         }
  3979.                         $userTypesByAppIds[$appId] = array_merge($userTypesByAppIds[$appId], array_diff([UserConstants::USER_TYPE_SYSTEM], $userTypesByAppIds[$appId]));
  3980.                         $centralUser->setUserAppIds(json_encode($userAppIds));
  3981.                         $centralUser->setUserTypesByAppIds(json_encode($userTypesByAppIds));
  3982.                         $em_goc->flush();
  3983.                     }
  3984.                     $accessList $session->get('userAccessList', []);
  3985.                     $d = array(
  3986.                         'userType' => UserConstants::USER_TYPE_SYSTEM,
  3987.                         'globalId' => $session->get(UserConstants::USER_ID0),
  3988.                         'serverId' => $companyGroupServerId,
  3989.                         'serverUrl' => $companyGroupServerAddress,
  3990.                         'serverPort' => $companyGroupServerPort,
  3991.                         'systemType' => '_ERP_',
  3992.                         'companyId' => 1,
  3993.                         'appId' => $appId,
  3994.                         'companyLogoUrl' => $goc->getImage(),
  3995.                         'companyName' => $goc->getName(),
  3996.                         'authenticationStr' => $this->get('url_encryptor')->encrypt(
  3997.                             json_encode(
  3998.                                 array(
  3999.                                     'globalId' => $session->get(UserConstants::USER_ID0),
  4000.                                     'appId' => $appId,
  4001.                                     'authenticate' => 1,
  4002.                                     'userType' => UserConstants::USER_TYPE_SYSTEM
  4003.                                 )
  4004.                             )
  4005.                         ),
  4006.                         'userCompanyList' => []
  4007.                     );
  4008.                     $accessList[] = $d;
  4009. //                    MiscActions::UpdateCompanyListInSession($em_goc, $centralUser->getApplicantId(), 1, 1, 1, $d);
  4010.                     //temporary solution
  4011.                     MiscActions::UpdateCompanyListInSession($em_goc$session->get(UserConstants::USER_ID), 111$d);
  4012.                     $session->set('userAccessList'$accessList);
  4013.                 }
  4014.                 return new JsonResponse(array(
  4015.                     'success' => true,
  4016.                     "message" => "Company Created Successfully",
  4017.                     'user_access_data' => $d,
  4018.                     'app_id' => $appId
  4019.                 ));
  4020.             }
  4021.         }
  4022.         return $this->render('@HoneybeeWeb/pages/create_company.html.twig', array(
  4023.             'page_title' => 'Company',
  4024.             'serverList' => GeneralConstant::$serverListById
  4025.         ));
  4026.     }
  4027.     public function checkBinTinAction(Request $request)
  4028.     {
  4029.         $em_goc $this->getDoctrine()->getManager('company_group');
  4030.         $type  $request->request->get('type');
  4031.         $value trim($request->request->get('value'));
  4032.         $repo $em_goc->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup");
  4033.         if ($type === 'tin') {
  4034.             $company $repo->findOneBy(array(
  4035.                 'company_tin' => $value
  4036.             ));
  4037.         } elseif ($type === 'bin') {
  4038.             $company $repo->findOneBy(array(
  4039.                 'company_bin' => $value
  4040.             ));
  4041.         } elseif ($type === 'reg') {
  4042.             $company $repo->findOneBy(array(
  4043.                 'company_reg' => $value
  4044.             ));
  4045.         } else {
  4046.             return new JsonResponse(['exists' => false]);
  4047.         }
  4048.         return new JsonResponse([
  4049.             'exists' => $company true false
  4050.         ]);
  4051.     }
  4052.     public function createTicketAction(Request $request)
  4053.     {
  4054.         $em_goc $this->getDoctrine()->getManager('company_group');
  4055.         if ($request->isMethod('POST')) {
  4056.             $ticket = new EntityTicket();
  4057.             $ticket->setTitle($request->request->get('title'0));
  4058.             $ticket->setEmail($request->request->get('email'));
  4059.             $ticket->setTicketBody($request->request->get('ticketBody'));
  4060.             $em_goc->persist($ticket);
  4061.             $em_goc->flush();
  4062.         }
  4063.         return new JsonResponse(array(
  4064.             "success" => 'true',
  4065.             "message" => "Ticket Created Successfully",
  4066.         ));
  4067.     }
  4068.     public function GetSessionDataForAppAction(
  4069.         Request $request,
  4070.                 $remoteVerify 0,
  4071.                 $version 'latest',
  4072.                 $identifier '_default_',
  4073.                 $refRoute '',
  4074.                 $apiKey '_ignore_'
  4075.     )
  4076.     {
  4077.         $message "";
  4078.         $gocList = [];
  4079.         $session $request->getSession();
  4080.         if ($request->request->has('token')) {
  4081.             $em_goc $this->getDoctrine()->getManager('company_group');
  4082.             $to_set_session_data MiscActions::GetSessionDataFromToken($em_goc$request->request->get('token'))['sessionData'];
  4083.             if ($to_set_session_data != null) {
  4084.                 foreach ($to_set_session_data as $k => $d) {
  4085.                     //check if mobile
  4086.                     $session->set($k$d);
  4087.                 }
  4088.             }
  4089.         }
  4090.         if ($request->request->has('sessionData')) {
  4091.             $to_set_session_data $request->request->get('sessionData');
  4092.             foreach ($to_set_session_data as $k => $d) {
  4093.                 //check if mobile
  4094.                 $session->set($k$d);
  4095.             }
  4096.         }
  4097.         if ($version !== 'latest') {
  4098.             $session_data = array(
  4099.                 'oAuthToken' => $session->get('oAuthToken'),
  4100.                 'locale' => $session->get('locale'),
  4101.                 'firebaseToken' => $session->get('firebaseToken'),
  4102.                 'token' => $session->get('token'),
  4103.                 UserConstants::USER_EMPLOYEE_ID => $session->get(UserConstants::USER_EMPLOYEE_ID),
  4104.                 UserConstants::USER_ID => $session->get(UserConstants::USER_ID),
  4105.                 UserConstants::LAST_SETTINGS_UPDATED_TS => $session->get(UserConstants::LAST_SETTINGS_UPDATED_TS),
  4106.                 UserConstants::USER_LOGIN_ID => $session->get(UserConstants::USER_LOGIN_ID),
  4107.                 UserConstants::USER_EMAIL => $session->get(UserConstants::USER_EMAIL),
  4108.                 UserConstants::USER_TYPE => $session->get(UserConstants::USER_TYPE),
  4109.                 UserConstants::USER_IMAGE => $session->get(UserConstants::USER_IMAGE),
  4110.                 UserConstants::USER_DEFAULT_ROUTE => $session->get(UserConstants::USER_DEFAULT_ROUTE),
  4111.                 UserConstants::USER_NAME => $session->get(UserConstants::USER_NAME),
  4112.                 UserConstants::USER_COMPANY_ID => $session->get(UserConstants::USER_COMPANY_ID),
  4113.                 UserConstants::USER_COMPANY_ID_LIST => $session->get(UserConstants::USER_COMPANY_ID_LIST),
  4114.                 UserConstants::USER_COMPANY_NAME_LIST => $session->get(UserConstants::USER_COMPANY_NAME_LIST),
  4115.                 UserConstants::USER_COMPANY_IMAGE_LIST => $session->get(UserConstants::USER_COMPANY_IMAGE_LIST),
  4116.                 UserConstants::USER_APP_ID => $session->get(UserConstants::USER_APP_ID),
  4117.                 UserConstants::USER_POSITION_LIST => $session->get(UserConstants::USER_POSITION_LIST),
  4118.                 UserConstants::USER_CURRENT_POSITION => $session->get(UserConstants::USER_CURRENT_POSITION),
  4119.                 UserConstants::ALL_MODULE_ACCESS_FLAG => $session->get(UserConstants::ALL_MODULE_ACCESS_FLAG),
  4120.                 UserConstants::USER_GOC_ID => $session->get(UserConstants::USER_GOC_ID),
  4121.                 UserConstants::USER_NOTIFICATION_ENABLED => GeneralConstant::NOTIFICATION_ENABLED == ? ($this->getParameter('notification_enabled') == 0) : 0,
  4122.                 UserConstants::USER_NOTIFICATION_SERVER => $this->getParameter('notification_server'),
  4123.                 UserConstants::PRODUCT_NAME_DISPLAY_TYPE => $session->get(UserConstants::PRODUCT_NAME_DISPLAY_TYPE),
  4124.                 UserConstants::APPLICATION_SECRET => $session->get(UserConstants::APPLICATION_SECRET),
  4125.                 //new addition
  4126.                 'appIdList' => $session->get('appIdList'),
  4127.                 'branchIdList' => $session->get('branchIdList'null),
  4128.                 'branchId' => $session->get('branchId'null),
  4129.                 'companyIdListByAppId' => $session->get('companyIdListByAppId'),
  4130.                 'companyNameListByAppId' => $session->get('companyNameListByAppId'),
  4131.                 'companyImageListByAppId' => $session->get('companyImageListByAppId'),
  4132.                 'userAccessList' => $session->get('userAccessList'),
  4133.                 'csToken' => $session->get('csToken'),
  4134.             );
  4135.         } else {
  4136.             $session_data = array(
  4137.                 'oAuthToken' => $session->get('oAuthToken'),
  4138.                 'locale' => $session->get('locale'),
  4139.                 'firebaseToken' => $session->get('firebaseToken'),
  4140.                 'token' => $session->get('token'),
  4141.                 UserConstants::USER_EMPLOYEE_ID => $session->get(UserConstants::USER_EMPLOYEE_ID),
  4142.                 UserConstants::USER_ID => $session->get(UserConstants::USER_ID),
  4143.                 UserConstants::LAST_SETTINGS_UPDATED_TS => $session->get(UserConstants::LAST_SETTINGS_UPDATED_TS),
  4144.                 UserConstants::USER_LOGIN_ID => $session->get(UserConstants::USER_LOGIN_ID),
  4145.                 UserConstants::USER_EMAIL => $session->get(UserConstants::USER_EMAIL),
  4146.                 UserConstants::USER_TYPE => $session->get(UserConstants::USER_TYPE),
  4147.                 UserConstants::USER_IMAGE => $session->get(UserConstants::USER_IMAGE),
  4148.                 UserConstants::USER_DEFAULT_ROUTE => $session->get(UserConstants::USER_DEFAULT_ROUTE),
  4149.                 UserConstants::USER_NAME => $session->get(UserConstants::USER_NAME),
  4150.                 UserConstants::USER_COMPANY_ID => $session->get(UserConstants::USER_COMPANY_ID),
  4151.                 UserConstants::USER_COMPANY_ID_LIST => $session->get(UserConstants::USER_COMPANY_ID_LIST),
  4152.                 UserConstants::USER_COMPANY_NAME_LIST => $session->get(UserConstants::USER_COMPANY_NAME_LIST),
  4153.                 UserConstants::USER_COMPANY_IMAGE_LIST => $session->get(UserConstants::USER_COMPANY_IMAGE_LIST),
  4154.                 UserConstants::USER_APP_ID => $session->get(UserConstants::USER_APP_ID),
  4155.                 UserConstants::USER_POSITION_LIST => $session->get(UserConstants::USER_POSITION_LIST),
  4156.                 UserConstants::USER_CURRENT_POSITION => $session->get(UserConstants::USER_CURRENT_POSITION),
  4157.                 UserConstants::ALL_MODULE_ACCESS_FLAG => $session->get(UserConstants::ALL_MODULE_ACCESS_FLAG),
  4158.                 UserConstants::USER_GOC_ID => $session->get(UserConstants::USER_GOC_ID),
  4159.                 UserConstants::USER_NOTIFICATION_ENABLED => GeneralConstant::NOTIFICATION_ENABLED == ? ($this->getParameter('notification_enabled') == 0) : 0,
  4160.                 UserConstants::USER_NOTIFICATION_SERVER => $this->getParameter('notification_server'),
  4161.                 UserConstants::PRODUCT_NAME_DISPLAY_TYPE => $session->get(UserConstants::PRODUCT_NAME_DISPLAY_TYPE),
  4162.                 UserConstants::APPLICATION_SECRET => $session->get(UserConstants::APPLICATION_SECRET),
  4163.                 //new addition
  4164.                 'appIdList' => $session->get('appIdList'),
  4165.                 'branchIdList' => $session->get('branchIdList'null),
  4166.                 'branchId' => $session->get('branchId'null),
  4167.                 'companyIdListByAppId' => $session->get('companyIdListByAppId'),
  4168.                 'companyNameListByAppId' => $session->get('companyNameListByAppId'),
  4169.                 'companyImageListByAppId' => $session->get('companyImageListByAppId'),
  4170.                 'userAccessList' => $session->get('userAccessList'),
  4171.                 'csToken' => $session->get('csToken'),
  4172.             );
  4173.         }
  4174.         $response = new JsonResponse(array(
  4175.             "success" => empty($session->get(UserConstants::USER_ID)) ? false true,
  4176.             //            'session'=>$request->getSession(),
  4177.             'session_data' => $session_data,
  4178.             //            'session2'=>$_SESSION,
  4179.         ));
  4180.         $response->headers->set('Access-Control-Allow-Origin''*, null');
  4181.         $response->headers->set('Access-Control-Allow-Methods''POST');
  4182.         //        $response->setCallback('FUNCTION_CALLBACK_NAME');
  4183.         return $response;
  4184.     }
  4185.     public function EmployeeAddUsingQrCodeCentralAction(Request $request)
  4186.     {
  4187.         $session $request->getSession();
  4188.         if ($request->isMethod('post')) {
  4189.             $em_goc $this->getDoctrine()->getManager('company_group');
  4190.             $entityApplicant $em_goc->getRepository("CompanyGroupBundle\\Entity\\EntityApplicantDetails")
  4191.                 ->findOneBy(
  4192.                     array(
  4193.                         'applicantId' => $request->request->get('userId'),
  4194.                     )
  4195.                 );
  4196.             $app $em_goc->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup")
  4197.                 ->findOneBy(
  4198.                     array(
  4199.                         'appId' => $request->request->get('appId'),
  4200.                     )
  4201.                 );
  4202.             $userType $request->request->get('userType');
  4203.             $currAccessData json_decode($entityApplicant->getUserTypesByAppIds(), true);
  4204.             if ($currAccessData == null$currAccessData = [];
  4205.             if (!isset($currAccessData[$request->request->get('appId')]))
  4206.                 $currAccessData[$request->request->get('appId')] = [];
  4207.             $currAccessData[$request->request->get('appId')] = array_merge($currAccessData[$request->request->get('appId')], array_diff([$request->request->get('userType'$userType)], $currAccessData[$request->request->get('appId')]));
  4208.             $entityApplicant->setUserTypesByAppIds(json_encode($currAccessData));
  4209.             $em_goc->flush();
  4210.             $postData = [];
  4211.             $postData['globalId'] = $entityApplicant->getApplicantId();
  4212.             $postData['username'] = $entityApplicant->getUsername();
  4213.             $postData['email'] = $entityApplicant->getEmail();
  4214.             $postData['firstname'] = $entityApplicant->getFirstname();
  4215.             $postData['lastname'] = $entityApplicant->getLastname();
  4216.             $postData['appId'] = $request->request->get('appId');
  4217.             $postData['companyId'] = $request->request->get('companyId');
  4218.             $postData['userType'] = $userType;
  4219.             $urlToCall $app->getCompanyGroupServerAddress() . '/add_employee_by_qr_erp';
  4220.             $userFiles $postData;
  4221.             $curl curl_init();
  4222.             curl_setopt_array($curl, array(
  4223.                 CURLOPT_RETURNTRANSFER => 1,
  4224.                 CURLOPT_POST => 1,
  4225.                 CURLOPT_URL => $urlToCall,
  4226.                 CURLOPT_CONNECTTIMEOUT => 10,
  4227.                 CURLOPT_SSL_VERIFYPEER => false,
  4228.                 CURLOPT_SSL_VERIFYHOST => false,
  4229.                 CURLOPT_HTTPHEADER => array( //              "Accept: multipart/form-data",
  4230.                 ),
  4231.                 //                            ),
  4232.                 CURLOPT_POSTFIELDS => $userFiles
  4233.             ));
  4234.             $retData curl_exec($curl);
  4235.             $errData curl_error($curl);
  4236.             curl_close($curl);
  4237.             if ($errData) {
  4238. //                $returnData['message']='';
  4239.             } else {
  4240.                 $retDataObj json_decode($retDatatrue);
  4241.                 if ($retDataObj['status'] == 'success') {
  4242.                     $newAccess = [
  4243.                         'userType' => 1,
  4244.                         'userTypeName' => 'Admin',
  4245.                         'globalId' => $entityApplicant->getApplicantId(),
  4246.                         'serverId' => $app->getCompanyGroupServerId(),
  4247.                         'serverUrl' => $app->getCompanyGroupServerAddress(),
  4248.                         'serverPort' => $app->getCompanyGroupServerPort(),
  4249.                         'systemType' => '_ERP_',
  4250.                         'companyId' => 1,
  4251.                         'appId' => $app->getAppId(),
  4252.                         'companyLogoUrl' => '/uploads/CompanyImage/company_image' $request->request->get('appId') . '.png',
  4253.                         'companyName' => $app->getName(),
  4254.                         'authenticationStr' => $this->get('url_encryptor')->encrypt(json_encode(
  4255.                                 array(
  4256.                                     'globalId' => $entityApplicant->getApplicantId(),
  4257.                                     'appId' => $app->getAppId(),
  4258.                                     'authenticate' => 1,
  4259.                                     'userType' => $userType,
  4260.                                     'userTypeName' => UserConstants::$userTypeName[$userType]
  4261.                                 )
  4262.                             )
  4263.                         ),
  4264.                         'userCompanyList' => [],
  4265.                     ];
  4266. //            $token = $session->get('token');
  4267. //            $em_goc = $this->getDoctrine()->getManager('company_group');
  4268.                     $to_set_session_data MiscActions::GetSessionDataFromToken($em_goc$session->get(UserConstants::USER_TOKEN''))['sessionData'];
  4269.                     $currentUserAccessListInSession $to_set_session_data['userAccessList'];
  4270.                     $isAlreadyJoined false;
  4271.                     foreach ($currentUserAccessListInSession as $acc) {
  4272.                         if (isset($acc['appId']) && $acc['appId'] == $request->request->get('appId')) {
  4273.                             $isAlreadyJoined true;
  4274.                             break;
  4275.                         }
  4276.                     }
  4277. //                    if(isset($currentUserAccessListInSession[$request->request->get('appId')]))
  4278. //                        $isAlreadyJoined=true;
  4279.                     if ($isAlreadyJoined) {
  4280.                         return new JsonResponse([
  4281.                             'status' => 'false',
  4282.                             'message' => 'Already joined.',
  4283.                             'currentUserAccessListInSession'  => $currentUserAccessListInSession
  4284.                         ]);
  4285.                     }else{
  4286.                         $currentUserAccessListInSession[] = $newAccess;
  4287.                         $session->set('userAccessList'$currentUserAccessListInSession);
  4288.                         $to_set_session_data['userAccessList'] = $currentUserAccessListInSession;
  4289.                         $updatedToken MiscActions::CreateTokenFromSessionData($em_goc,
  4290.                             $to_set_session_data,
  4291.                             1,
  4292.                             1,
  4293.                             11
  4294.                         );
  4295.                         return new JsonResponse([
  4296.                             'status' => 'success',
  4297.                             'message' => 'User successfully added to company.',
  4298.                             'currentUserAccessListInSession'  => $currentUserAccessListInSession
  4299.                         ]);
  4300.                     }
  4301.                 }
  4302.             }
  4303. //            MiscActions::UpdateCompanyListInSession($em_goc, $entityApplicant->getApplicantId(), 1, 1, 1, $newAccess);
  4304.         } else {
  4305.             $company $request->get('company');
  4306.             return new JsonResponse(array(
  4307.                 'status' => 'error',
  4308.                 'message' => 'Something went wrong while onboarding.'
  4309.             ));
  4310.         }
  4311.         return new JsonResponse(array(
  4312.             'status' => 'error',
  4313.             'message' => 'Something went wrong while onboarding.'
  4314.         ));
  4315.     }
  4316.     public function EmployeeAddUsingQrCodeAction(Request $request)
  4317.     {
  4318.         $post $request;
  4319.         $em $this->getDoctrine()->getManager('company_group');
  4320.         $appid $request->query->get('appid'$request->request->get('appid'null));
  4321.         $session $request->getSession();
  4322.         $CurrentRoute $request->attributes->get('_route');
  4323.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  4324.         if ($request->isMethod('POST')) {
  4325.             $userId $request->request->get('userId'null);
  4326.             if ($userId === null) {
  4327.                 $companyId $request->request->get('company',1);
  4328.                 $email $request->request->get('email');
  4329.                 $qrImage $request->files->get('qr_image');
  4330.                 if (!$email) {
  4331.                     return new JsonResponse(['status' => 'error''message' => 'Invalid request'], 400);
  4332.                 }
  4333.                 if ($qrImage) {
  4334.                     $uploadsDir $this->getParameter('kernel.project_dir') . '/public/uploads/';
  4335.                     $fileName 'qr_' $companyId '_' time() . '.png';
  4336.                     $qrImage->move($uploadsDir$fileName);
  4337.                     $qrImagePath $uploadsDir $fileName;
  4338.                     $bodyTemplate '@Application/email/user/applicant_confirm.html.twig';
  4339.                     $bodyData = [
  4340.                         'name' => $email,
  4341.                         'companyData' => $companyId,
  4342.                         'companyName' => $request->request->get('company'),
  4343.                         'userType' => 2,
  4344.                         'appId' => $appid,
  4345.                         //                        'qr_code_url' => '/uploads/' . $fileName
  4346.                     ];
  4347.                     $userAccessList $session->get('userAccessList', []);
  4348.                     $companyName array_map(function ($company) {
  4349.                         return $company['companyName'];
  4350.                     }, $userAccessList);
  4351.                     $new_mail $this->get('mail_module');
  4352.                     $new_mail->sendMyMail([
  4353.                         'senderHash' => '_CUSTOM_',
  4354.                         'forwardToMailAddress' => $email,
  4355.                         'fromAddress' => 'accounts@ourhoneybee.eu',
  4356.                         'userName' => 'accounts@ourhoneybee.eu',
  4357.                         'password' => \ApplicationBundle\Helper\MailerConfig::buddybeePassword(),
  4358.                         'smtpServer' => \ApplicationBundle\Helper\MailerConfig::host(),
  4359.                         'smtpPort' => \ApplicationBundle\Helper\MailerConfig::port(),
  4360.                         'subject' => 'User Registration on HoneyBee Ecosystem under Entity ',
  4361.                         'toAddress' => $email,
  4362.                         'mailTemplate' => $bodyTemplate,
  4363.                         'templateData' => $bodyData,
  4364.                         'companyId' => $companyId,
  4365.                     ]);
  4366.                     return $this->render(
  4367.                         '@Application/pages/dashboard/index_central_landing.html.twig',
  4368.                         [
  4369.                             'page_title' => 'Central Landing',
  4370.                             'companyNames' => $companyName
  4371.                         ]
  4372.                     );
  4373.                 } else {
  4374.                     $userAccessList $session->get('userAccessList', []);
  4375.                     $companyName array_map(function ($company) {
  4376.                         return $company['companyName'];
  4377.                     }, $userAccessList);
  4378.                     return $this->render(
  4379.                         '@Application/pages/dashboard/index_central_landing.html.twig',
  4380.                         [
  4381.                             'page_title' => 'Central Landing',
  4382.                             'companyNames' => $companyName
  4383.                         ]
  4384.                     );
  4385.                 }
  4386.             } else {
  4387.                 if ($systemType == '_CENTRAL_') {
  4388.                     $userAccessList $session->get('userAccessList', []);
  4389.                     $companyName array_map(function ($company) {
  4390.                         return $company['companyName'];
  4391.                     }, $userAccessList);
  4392.                     $modifiedRequest $request->duplicate(
  4393.                         null,
  4394.                         array_merge($request->request->all(), ['appId' => $request->request->get('appid')])
  4395.                     );
  4396.                     $response $this->EmployeeAddUsingQrCodeCentralAction($modifiedRequest);
  4397. //                    if ($CurrentRoute == 'employee_add_by_qr_api')
  4398.                     {
  4399.                         return $response;
  4400.                     }
  4401. //                    return $this->render(
  4402. //                        'ApplicationBundle:pages/dashboard:index_central_landing.html.twig',
  4403. //                        [
  4404. //                            'page_title' => 'Central Landing',
  4405. //                            'companyNames' => $companyName
  4406. //                        ]
  4407. //                    );
  4408.                 }
  4409.             }
  4410.         } else {
  4411.             $company $request->get('company');
  4412.             $em_goc $this->getDoctrine()->getManager('company_group');
  4413.             $company $em_goc->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup")->findOneBy(['appId' => $request->get('appid')]);
  4414.             return $this->render(
  4415.                 '@Application/pages/dashboard/employee_add_by_qr.html.twig',
  4416.                 [
  4417.                     'page_title' => 'Company Invitation',
  4418.                     'company' => $company
  4419.                 ]
  4420.             );
  4421.         }
  4422.     }
  4423.     public function EmployeeOnboardUsingQrAction(Request $request): JsonResponse
  4424.     {
  4425.         $email $request->get('email');
  4426.         $isAjax $request->isXmlHttpRequest();
  4427.         $currentRoute $request->attributes->get('_route');
  4428.         if (!$email) {
  4429.             if ($isAjax) {
  4430.                 return new JsonResponse(['status' => 'error''message' => 'Email is required.']);
  4431.             } else {
  4432.                 throw $this->createNotFoundException("Email is missing.");
  4433.             }
  4434.         }
  4435.         $em_goc $this->getDoctrine()->getManager('company_group');
  4436.         $user $em_goc->getRepository("CompanyGroupBundle\\Entity\\EntityApplicantDetails")->findOneBy(['email' => $email]);
  4437.         if (!$user) {
  4438.             if ($isAjax) {
  4439.                 return new JsonResponse(['status' => 'error''message' => 'Applicant not found.']);
  4440.             } else {
  4441.                 throw $this->createNotFoundException("Applicant not found.");
  4442.             }
  4443.         }
  4444.         $payloadUrl $this->generateUrl('employee_onboard_by_qr_api', [
  4445.             'email' => $user->getEmail(),
  4446.             'applicantId' => $user->getApplicantId(),
  4447.             'employeeQr' => 1
  4448.         ], UrlGeneratorInterface::ABSOLUTE_URL);
  4449.         if ($currentRoute === 'employee_onboard') {
  4450.             return new JsonResponse([
  4451.                 'status' => 'success',
  4452.                 'data' => [
  4453.                     'applicantId' => $user->getApplicantId(),
  4454.                     'username' => $user->getUsername(),
  4455.                     'email' => $user->getEmail(),
  4456.                     'firstName' => $user->getFirstname(),
  4457.                     'lastName' => $user->getLastname(),
  4458.                     'link' => $payloadUrl
  4459.                 ]
  4460.             ]);
  4461.         }
  4462.         if ($isAjax) {
  4463.             return new JsonResponse([
  4464.                 'status' => 'success',
  4465.                 'data' => [
  4466.                     'id' => $user->getApplicantId(),
  4467.                     'email' => $user->getEmail(),
  4468.                     'name' => $user->getFirstname() . ' ' $user->getLastname(),
  4469.                     'dob' => $user->getDob() ? $user->getDob()->format('Y-m-d') : null,
  4470.                 ]
  4471.             ]);
  4472.         }
  4473.         $companies $request->getSession()->get('userAccessList', []);
  4474.         return $this->render('@Application/pages/dashboard/qr_onboard_result.html.twig', [
  4475.             'page_title' => 'Onboarding',
  4476.             'applicant' => $user,
  4477.             'companies' => $companies
  4478.         ]);
  4479.     }
  4480.     public function OnboardUserToCompanyAction(Request $request)
  4481.     {
  4482.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  4483.         $currentRoute $request->attributes->get('_route');
  4484.         if ($systemType !== '_CENTRAL_') {
  4485.             throw new \Exception("This action must be called from CENTRAL system.");
  4486.         }
  4487.         $email $request->request->get('email');
  4488.         $applicantId $request->request->get('applicant_id');
  4489.         $appId $request->request->get('company_id');
  4490.         $userType $request->request->get('user_type');
  4491.         if (!$email || !$appId || !$userType) {
  4492.             $this->addFlash('error''Missing required fields.');
  4493.             return new JsonResponse(['status' => 'error''message' => 'Missing required fields.']);
  4494.         }
  4495.         $em $this->getDoctrine()->getManager('company_group');
  4496.         $applicant $em->getRepository("CompanyGroupBundle\\Entity\\EntityApplicantDetails")->findOneBy(['email' => $email]);
  4497.         if (!$applicant) {
  4498.             $this->addFlash('error''Applicant not found.');
  4499.             return $this->redirectToRoute('central_landing');
  4500.         }
  4501.         $userAppIds json_decode($applicant->getUserAppIds(), true);
  4502.         if (!is_array($userAppIds)) {
  4503.             $userAppIds = [];
  4504.         }
  4505.         if (!in_array($appId$userAppIds)) {
  4506.             $userAppIds[] = $appId;
  4507.             $applicant->setUserAppIds(json_encode($userAppIds));
  4508.         }
  4509.         $userTypesByAppIds json_decode($applicant->getUserTypesByAppIds(), true) ?: [];
  4510.         $userTypesByAppIds[$appId] = array((int)$userType);
  4511.         $applicant->setUserTypesByAppIds(json_encode($userTypesByAppIds));
  4512.         $em->persist($applicant);
  4513.         $em->flush();
  4514.         $companyRepo $this->getDoctrine()->getManager('company_group')->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup");
  4515.         $targetCompany $companyRepo->findOneBy(['appId' => $appId]);
  4516.         if (!$targetCompany) {
  4517.             $this->addFlash('error''Target company not found.');
  4518.             return $this->redirectToRoute('central_landing');
  4519.         }
  4520.         $serverList MiscActions::getServerListById(                     $this->container->getParameter('database_user'),                     $this->container->getParameter('database_password'),                     $this->container->hasParameter('server_access_list') ?$this->container->getParameter('server_access_list') :[]                 );
  4521.         $serverId $targetCompany->getCompanyGroupServerId();
  4522.         $appId $targetCompany->getAppId();
  4523.         if (!isset($serverList[$serverId])) {
  4524.             $this->addFlash('error''Server configuration not found.');
  4525.             return $this->redirectToRoute('central_landing');
  4526.         }
  4527.         // Find correct companyId from session userAccessList using appId
  4528.         $session $request->getSession();
  4529.         $userAccessList $session->get('userAccessList', []);
  4530.         $resolvedCompanyId null;
  4531.         foreach ($userAccessList as $access) {
  4532.             if (isset($access['appId']) && $access['appId'] == $appId) {
  4533.                 $resolvedCompanyId $access['companyId'];
  4534.                 break;
  4535.             }
  4536.         }
  4537.         if (!$resolvedCompanyId) {
  4538.             $this->addFlash('error''Could not resolve companyId from session for the given appId.');
  4539.             return $this->redirectToRoute('central_landing');
  4540.         }
  4541.         $imagePath $this->container->getParameter('kernel.root_dir') . '/../web/' $applicant->getImage();
  4542.         $imageFile null;
  4543.         if ($applicant->getImage() && file_exists($imagePath)) {
  4544.             $mime mime_content_type($imagePath);
  4545.             $name pathinfo($imagePathPATHINFO_BASENAME);
  4546.             $imageFile = new \CURLFile($imagePath$mime$name);
  4547.         }
  4548.         // Prepare userData
  4549.         $userData = [];
  4550.         $getters array_filter(get_class_methods($applicant), function ($method) {
  4551.             return strpos($method'get') === 0;
  4552.         });
  4553.         foreach ($getters as $getter) {
  4554.             if (in_array($getter, ['getCreatedAt''getUpdatedAt''getImage'])) continue;
  4555.             $value $applicant->$getter();
  4556.             $userData[$getter] = $value instanceof \DateTime $value->format('Y-m-d') : $value;
  4557.         }
  4558.         $userData['getUserAppIds'] = json_encode($userAppIds);
  4559.         $userData['getUserTypesByAppIds'] = json_encode($userTypesByAppIds);
  4560.         $postFields = [
  4561.             'userData' => json_encode([$userData]),
  4562.             'appIds' => $appId,
  4563.             'userIds' => $applicantId,
  4564.             'companyId' => $resolvedCompanyId,
  4565.             'userType' => $userType,
  4566.             'imageFile' => $imageFile
  4567.         ];
  4568.         if ($imageFile) {
  4569.             $postFields['file_' $applicant->getApplicantId()] = $imageFile;
  4570.         }
  4571.         $url $serverList[$serverId]['absoluteUrl'] . '/OnBoardCentralUserToErp';
  4572.         $curl curl_init();
  4573.         curl_setopt_array($curl, [
  4574.             CURLOPT_RETURNTRANSFER => 1,
  4575.             CURLOPT_POST => 1,
  4576.             CURLOPT_URL => $url,
  4577.             CURLOPT_POSTFIELDS => $postFields,
  4578.             CURLOPT_CONNECTTIMEOUT => 10,
  4579.             CURLOPT_SSL_VERIFYPEER => false,
  4580.             CURLOPT_SSL_VERIFYHOST => false,
  4581.         ]);
  4582.         $response curl_exec($curl);
  4583.         $curlError curl_error($curl);
  4584.         curl_close($curl);
  4585.         $responseObj json_decode($responsetrue);
  4586.         if ($currentRoute === 'employee_onboard_api') {
  4587.             return new JsonResponse(
  4588.                 $responseObj
  4589.             );
  4590.         }
  4591.         if (!empty($responseObj['success'])) {
  4592.             $this->addFlash('success''Applicant onboarded and synced to ERP.');
  4593.         } else {
  4594.             $this->addFlash('warning''Onboarded, but ERP sync may have failed. Check logs.');
  4595.         }
  4596.         return $this->redirectToRoute('central_landing');
  4597.     }
  4598.     public function OnBoardCentralUserToErpAction(Request $request)
  4599.     {
  4600.         $systemType $this->container->hasParameter('system_type') ? $this->container->getParameter('system_type') : '_ERP_';
  4601.         if ($systemType === '_CENTRAL_') {
  4602.             return new JsonResponse(['success' => false'message' => 'Invalid system type.']);
  4603.         }
  4604.         $userDataJson $request->get('userData');
  4605.         $userDataList json_decode($userDataJsontrue);
  4606.         if (!$userDataList || !is_array($userDataList)) {
  4607.             return new JsonResponse(['success' => false'message' => 'Invalid or missing userData.']);
  4608.         }
  4609.         $userData $userDataList[0] ?? null;
  4610.         if (!$userData || empty($userData['getApplicantId'])) {
  4611.             return new JsonResponse(['success' => false'message' => 'Missing applicant ID.']);
  4612.         }
  4613.         $em_goc $this->getDoctrine()->getManager('company_group');
  4614.         $globalId $userData['getApplicantId'];
  4615.         $appIds $request->get('appIds');
  4616.         $userIds $request->get('userIds');
  4617.         $companyId $request->get('companyId');
  4618.         $company $em_goc->getRepository("CompanyGroupBundle\\Entity\\CompanyGroup")->findOneBy(['appId' => $appIds]);
  4619.         if (!$company) {
  4620.             return new JsonResponse(['success' => false'message' => 'Target company not found.']);
  4621.         }
  4622.         $connector $this->container->get('application_connector');
  4623.         $connector->resetConnection(
  4624.             'default',
  4625.             $company->getDbName(),
  4626.             $company->getDbUser(),
  4627.             $company->getDbPass(),
  4628.             $company->getDbHost(),
  4629.             true
  4630.         );
  4631.         $em $this->getDoctrine()->getManager();
  4632.         $user $em->getRepository('ApplicationBundle\\Entity\\SysUser')->findOneBy([
  4633.             'globalId' => $globalId
  4634.         ]);
  4635.         if (!$user) {
  4636.             $user = new \ApplicationBundle\Entity\SysUser();
  4637.             $user->setGlobalId($globalId);
  4638.         } else {
  4639.             return new JsonResponse([
  4640.                 'status' => 'info',
  4641.                 'message' => 'User is already onboarded',
  4642.                 'userId' => $user->getUserId(),
  4643.                 'redirectUrl' => 'dashboard'
  4644.             ]);
  4645.         }
  4646.         $setterMap = [
  4647.             'getUsername' => 'setUserName',
  4648.             'getEmail' => 'setEmail',
  4649.             'getPassword' => 'setPassword',
  4650.             'getDeviceId' => 'setDeviceId',
  4651.             'getDeviceIdLockedFlag' => 'setDeviceIdLockedFlag',
  4652.             'getLockDeviceIdOnNextLoginFlag' => 'setLockDeviceIdOnNextLoginFlag',
  4653.             'getOAuthUniqueId' => 'setOAuthUniqueId',
  4654.             'getOAuthEmail' => 'setOAuthEmail',
  4655.             'getSyncFlag' => 'setSyncFlag',
  4656.             'getFirstname' => 'setName',
  4657.         ];
  4658.         $user->setUserAppId($appIds);
  4659.         $user->setUserAppIdList(json_encode([$appIds]));
  4660.         $user->setStatus(1);
  4661.         foreach ($setterMap as $getter => $setter) {
  4662.             if (isset($userData[$getter]) && method_exists($user$setter)) {
  4663.                 $user->$setter($userData[$getter]);
  4664.             }
  4665.         }
  4666.         $fullName trim(($userData['getFirstname'] ?? '') . ' ' . ($userData['getLastname'] ?? ''));
  4667.         if (!empty($fullName)) {
  4668.             $user->setName($fullName);
  4669.         }
  4670.         $imagePathToSet '';
  4671.         $uploadedFile $request->files->get('file_' $globalId);
  4672.         if ($uploadedFile) {
  4673.             $uploadDir $this->getParameter('kernel.project_dir') . '/web/uploads/UserImage/';
  4674.             if (!file_exists($uploadDir)) {
  4675.                 mkdir($uploadDir0777true);
  4676.             }
  4677.             $filename 'user_' $globalId '.' $uploadedFile->guessExtension();
  4678.             $uploadedFile->move($uploadDir$filename);
  4679.             $imagePathToSet 'uploads/UserImage/' $filename;
  4680.             $user->setImage($imagePathToSet);
  4681.         }
  4682.         $user->setUserType(1);
  4683.         $em->persist($user);
  4684.         $em->flush();
  4685.         $employee $em->getRepository('ApplicationBundle\\Entity\\Employee')->findOneBy([
  4686.             'userId' => $user->getUserId()
  4687.         ]);
  4688.         if (!$employee) {
  4689.             $employee = new \ApplicationBundle\Entity\Employee();
  4690.             $employee->setUserId($user->getUserId());
  4691.             $employee->setDateOfAddition(new \DateTime());
  4692.         }
  4693.         $employee->setFirstName($userData['getFirstname'] ?? null);
  4694.         $employee->setLastName($userData['getLastname'] ?? null);
  4695.         $employee->setName(trim(($userData['getFirstname'] ?? '') . ' ' . ($userData['getLastname'] ?? '')));
  4696.         $employee->setEmail($userData['getEmail'] ?? null);
  4697.         $employee->setEmmContact($userData['getEmmContact'] ?? null);
  4698.         $employee->setCurrentAddress($userData['getCurrAddr'] ?? null);
  4699.         $employee->setPermanentAddress($userData['getPermAddr'] ?? null);
  4700.         $employee->setCompanyId((int)$companyId);
  4701.         $employee->setDepartmentId($userData['getDept'] ?? null);
  4702.         $employee->setBranchId($userData['getBranch'] ?? null);
  4703.         $employee->setPositionId($userData['getDesg'] ?? null);
  4704.         $employee->setSupervisorId($userData['getSupervisor'] ?? null);
  4705.         if (!empty($imagePathToSet)) {
  4706.             $employee->setImage($imagePathToSet);
  4707.         }
  4708.         $employee->setStatus("1");
  4709.         $employee->setLastModifiedDate(new \DateTime());
  4710.         $em->persist($employee);
  4711.         $em->flush();
  4712.         $employeeDetails $em->getRepository('ApplicationBundle\\Entity\\EmployeeDetails')
  4713.             ->findOneBy(['userId' => $user->getUserId()]);
  4714.         if (!$employeeDetails) {
  4715.             $employeeDetails = new \ApplicationBundle\Entity\EmployeeDetails();
  4716.             $employeeDetails->setUserId($user->getUserId());
  4717.         }
  4718.         $employeeDetails->setId($employee->getEmployeeId());
  4719.         $employeeDetails->setFirstname($userData['getFirstname'] ?? null);
  4720.         $employeeDetails->setLastname($userData['getLastname'] ?? null);
  4721.         $employeeDetails->setUsername($userData['getUsername'] ?? null);
  4722.         $employeeDetails->setEmail($userData['getEmail'] ?? null);
  4723.         $employeeDetails->setPassword($userData['getPassword'] ?? null);
  4724.         $employeeDetails->setNid($userData['getNid'] ?? null);
  4725.         $employeeDetails->setSex($userData['getSex'] ?? null);
  4726.         $employeeDetails->setFather($userData['getFather'] ?? null);
  4727.         $employeeDetails->setMother($userData['getMother'] ?? null);
  4728.         $employeeDetails->setSpouse($userData['getSpouse'] ?? null);
  4729.         $employeeDetails->setChild1($userData['getChild1'] ?? null);
  4730.         $employeeDetails->setChild2($userData['getChild2'] ?? null);
  4731.         $employeeDetails->setPhone($userData['getPhone'] ?? null);
  4732.         $employeeDetails->setOfficialPhone($userData['getOfficailPhone'] ?? null);
  4733.         $employeeDetails->setCurrAddr($userData['getCurrAddr'] ?? null);
  4734.         $employeeDetails->setPermAddr($userData['getPermAddr'] ?? null);
  4735.         $employeeDetails->setEmmContact($userData['getEmmContact'] ?? null);
  4736.         if (!empty($userData['getDob'])) {
  4737.             $employeeDetails->setDob(new \DateTime($userData['getDob']));
  4738.         }
  4739.         if (!empty($userData['getJoiningDate'])) {
  4740.             $employeeDetails->setJoiningDate(new \DateTime($userData['getJoiningDate']));
  4741.         }
  4742.         if (!empty($userData['getEmpValidTill'])) {
  4743.             $employeeDetails->setEmpValidTill(new \DateTime($userData['getEmpValidTill']));
  4744.         }
  4745.         if (!empty($userData['getTinValidTill'])) {
  4746.             $employeeDetails->setTinValidTill(new \DateTime($userData['getTinValidTill']));
  4747.         }
  4748.         if (!empty($userData['getMedInsValidTill'])) {
  4749.             $employeeDetails->setMedInsValidTill(new \DateTime($userData['getMedInsValidTill']));
  4750.         }
  4751.         $employeeDetails->setEmpType($userData['getEmpType'] ?? null);
  4752.         $employeeDetails->setEmpCode($userData['getEmpCode'] ?? null);
  4753.         $employeeDetails->setEmployeeLevel($userData['getEmployeeLevel'] ?? null);
  4754.         $employeeDetails->setTin($userData['getTin'] ?? null);
  4755.         $employeeDetails->setSkill($userData['getSkill'] ?? null);
  4756.         $employeeDetails->setEducationData($userData['getEducationData'] ?? null);
  4757.         $employeeDetails->setWorkExperienceData($userData['getWorkExperienceData'] ?? null);
  4758.         $employeeDetails->setApplicationText($userData['getApplicationText'] ?? null);
  4759.         $employeeDetails->setCurrentEmployment($userData['getCurrentEmployment'] ?? null);
  4760.         $employeeDetails->setEmergencyContactNumber($userData['getEmergencyContactNumber'] ?? null);
  4761.         $employeeDetails->setPostalCode($userData['getPostalCode'] ?? null);
  4762.         $employeeDetails->setCountry($userData['getCountry'] ?? null);
  4763.         if (!empty($imagePathToSet)) {
  4764.             $employeeDetails->setImage($imagePathToSet);
  4765.         }
  4766.         $em->persist($employeeDetails);
  4767.         $em->flush();
  4768.         $uploadedFile $request->files->get('file_' $globalId);
  4769.         return new JsonResponse([
  4770.             'success' => true,
  4771.             'globalId' => $globalId,
  4772.             'appIds' => $appIds,
  4773.             'userIds' => $userIds,
  4774.             'hasFile' => $uploadedFile !== null,
  4775.         ]);
  4776.     }
  4777.     public function getIndustryListForAppAction()
  4778.     {
  4779.         $industryList GeneralConstant::$industryList;
  4780.         return new JsonResponse($industryList);
  4781.     }
  4782.     public function getFeatureListAction()
  4783.     {
  4784.         $featureList GeneralConstant::$featureList;
  4785.         return new JsonResponse($featureList);
  4786.     }
  4787.     public function chooseYourPlanAction()
  4788.     {
  4789.         $plan GeneralConstant::$chooseYourPlan;
  4790.         return new JsonResponse($plan);
  4791.     }
  4792. //    public function getLogindataFromTokenAction(Request $request)
  4793. //    {
  4794. //        $em_goc = $this->getDoctrine()->getManager('company_group');
  4795. //        $sessionData = MiscActions::GetSessionDataFromToken($em_goc, $request->query->get('hbeeSessionToken'))['sessionData'];
  4796. //        return new JsonResponse($sessionData);
  4797. //        $sessionDataa = MiscActions::GetSessionDataFromToken($em_goc, $request->query->get('hbeeSessionToken'))['sessionData'];
  4798. //        return new JsonResponse($sessionDataa);
  4799. //    }
  4800.     public function getLogindataFromTokenAction(Request $request)
  4801.     {
  4802.         $em_goc $this->getDoctrine()->getManager('company_group');
  4803.         $token $request->query->get('hbeeSessionToken');
  4804.         if (!$token) {
  4805.             return new JsonResponse(['error' => 'Missing session token'], 400);
  4806.         }
  4807.         $sessionResult MiscActions::GetSessionDataFromToken($em_goc$token);
  4808.         if (!$sessionResult || !isset($sessionResult['sessionData'])) {
  4809.             return new JsonResponse(['error' => 'Invalid session token or session not found'], 401);
  4810.         }
  4811.         $sessionData $sessionResult['sessionData'];
  4812.         return new JsonResponse($sessionData);
  4813.     }
  4814.    public function packageDetailsAction()
  4815. {
  4816.     $packageDetails GeneralConstant::$packageDetails;
  4817.     return new JsonResponse([
  4818.         'success' => true,
  4819.         'message' => 'Data fetched successfully.',
  4820.         'data' => $packageDetails
  4821.     ]);
  4822. }
  4823.     public function employeeRangeAction()
  4824.     {
  4825.         $employeeRangeForApp GeneralConstant::$employeeRange;
  4826.         return new JsonResponse($employeeRangeForApp);
  4827.     }
  4828.     public function paymentMethodAction()
  4829.     {
  4830.         $paymentMethod GeneralConstant::$paymentMethod;
  4831.         return new JsonResponse($paymentMethod);
  4832.     }
  4833.     public function companyTypeAction()
  4834.     {
  4835.         $companyType GeneralConstant::$companyType;
  4836.         return new JsonResponse(
  4837.             [
  4838.                 'status' => 'success',
  4839.                 'message' => 'Company types retrieved successfully.',
  4840.                 'data' => $companyType,
  4841.             ]
  4842.          );
  4843.     }
  4844.     public function getCountryListAction()
  4845.     {
  4846.         $em_goc $this->getDoctrine()->getManager('company_group');
  4847.         $countryList $em_goc->getRepository('CompanyGroupBundle\\Entity\\EntityCountries')
  4848.             ->createQueryBuilder('C')
  4849.             ->select('C.CountryId''C.code''C.nameEn')
  4850.             ->getQuery()
  4851.             ->getArrayResult();
  4852.         // $formattedList = array_map(function ($country) {
  4853.         //     return [
  4854.         //         'countryId' => $country['countryId'],
  4855.         //         'countryName' => $country['nameEn'],
  4856.         //         'countryCode' => $country['code'],
  4857.         //     ];
  4858.         // }, $countryList);
  4859.         return new JsonResponse([
  4860.             'status' => true,
  4861.             'message' => 'Country list fetched successfully',
  4862.             'data' => $countryList,
  4863.         ]);
  4864.     }
  4865. public function spotLightSearchAction(Request $request,$queryStr ''){
  4866.     
  4867.     $em $this->getDoctrine()->getManager();
  4868.     $data = [];
  4869.     $data_by_id = [];
  4870.     $session $request->getSession();
  4871.     $entityDetails GeneralConstant::$Entity_list_details
  4872.     if ($queryStr == '_DEFAULT_')
  4873.         $queryStr '';
  4874.     if ($request->request->has('query') && $queryStr == '')
  4875.         $queryStr $request->request->get('query');
  4876.     if ($queryStr == '_DEFAULT_')
  4877.         $queryStr '';
  4878.     $queryStr str_ireplace('_FSLASH_''/'$queryStr);
  4879.     //module
  4880.     $filterQryForCriteria "select * from sys_module where 1=1 and module_name  like '%" $queryStr "%'  limit 10";
  4881.     $get_kids_sql $filterQryForCriteria;
  4882.     $stmt $em->getConnection()->fetchAllAssociative($get_kids_sql);
  4883.     
  4884.     $get_kids $stmt;
  4885.     $productId 0;
  4886.     $absoluteUrl $this->generateUrl('dashboard', [], UrlGenerator::ABSOLUTE_URL);
  4887.     if (!empty($get_kids)) {
  4888.         foreach ($get_kids as $product) {
  4889.             $router $this->container->get('router');
  4890.             $routeName $product['module_route'];
  4891.             if ($router->getRouteCollection()->get($routeName)) {
  4892.                 $pa            = array();
  4893.                 $pa['id']      = $product['module_id'];
  4894.                 $pa['name']    = $product['module_name'];
  4895.                 $pa['type']    = 'module';
  4896. //            $pa['url']     = $absoluteUrl . '/' . $product['module_route'];
  4897.                 $pa['url']     = $this->generateUrl($product['module_route'], [], UrlGenerator::ABSOLUTE_URL);
  4898.                 $data[] = $pa;
  4899.             } else {
  4900.                 // treat as non-route
  4901. //                $pa['url'] = $routeName; // or custom fallback
  4902.             }
  4903.         }
  4904.     }
  4905.     // supplier
  4906.     $get_kids $em->getConnection()->fetchAllAssociative(
  4907.         "select * from acc_suppliers where supplier_name like '%" $queryStr "%' limit 10"
  4908.     );
  4909.     $url $this->generateUrl('supplier_profile');
  4910.     if (!empty($get_kids)) {
  4911.         foreach ($get_kids as $product) {
  4912.             $pa           = array();
  4913.             $pa['id']     = $product['supplier_id'];
  4914.             $pa['name']   = $product['supplier_name'];
  4915.             $pa['type']   = 'supplier';
  4916.             $pa['url']    = rtrim($absoluteUrl'/') . '/' ltrim($url'/') . '?ex_s_id=' $product['supplier_id'];
  4917.             $data[] = $pa;
  4918.         }
  4919.     }
  4920.     // client
  4921.     $get_kids $em->getConnection()->fetchAllAssociative(
  4922.         "select * from acc_clients where client_name like '%" $queryStr "%' limit 10"
  4923.     );
  4924.     $url $this->generateUrl('client_profile');
  4925.     if (!empty($get_kids)) {
  4926.         foreach ($get_kids as $product) {
  4927.             $pa           = array();
  4928.             $pa['id']     = $product['client_id'];
  4929.             $pa['name']   = $product['client_name'];
  4930.             $pa['type']   = 'client';
  4931.             $pa['url']    = rtrim($absoluteUrl'/') . '/' trim($url'/') . '/' $product['client_id'];
  4932.             $data[] = $pa;
  4933.         }
  4934.     }
  4935.     // document (approval)
  4936.     $get_kids $em->getConnection()->fetchAllAssociative(
  4937.         "select * from approval where document_hash like '%" $queryStr "%' limit 10"
  4938.     );
  4939.     if (!empty($get_kids)) {
  4940.         foreach ($get_kids as $product) {
  4941.             try {
  4942.                 $viewUrl $this->generateUrl(
  4943.                     $entityDetails[$product['entity']]['entity_view_route_path_name']
  4944.                 );
  4945.                 $pa           = array();
  4946.                 $pa['id']     = $product['id'];
  4947.                 $pa['name']   = $product['document_hash'];
  4948.                 $pa['type']   = 'document';
  4949.                 $pa['url']    = rtrim($absoluteUrl'/') . '/' trim($viewUrl'/') . '/' $product['entity_id'];
  4950.                 $data[] = $pa;
  4951.             } catch (\Exception $e) { /* skip if route undefined */ }
  4952.         }
  4953.     }
  4954.     return new JsonResponse(array(
  4955.         'success' => true,
  4956.         'data'    => $data,
  4957.     ));
  4958. }
  4959.     public function getMlDataAction()
  4960.     {
  4961.         $data GeneralConstant::$dataFromMl;
  4962.         return new JsonResponse($data);
  4963.     }
  4964.     public function UploadDocumentsAction(Request $request)
  4965.     {
  4966.         $session $request->getSession();
  4967.         $em $this->getDoctrine()->getManager();
  4968.         return $this->render(
  4969.             '@Application/pages/dashboard/upload_documents.html.twig',
  4970.             array(
  4971.                 'page_title' => 'Upload Documents',
  4972.             )
  4973.         );
  4974.     }
  4975. }