<?php
namespace App\Controller;
use App\Constant;
use App\Entity\Idempiere\AdOrg;
use App\Entity\Idempiere\AdRole;
use App\Entity\Idempiere\AdUser;
use App\Entity\Idempiere\AdWindowAccess;
use App\Entity\Idempiere\CBpartner;
use App\Entity\Idempiere\CBpartnerLocation;
use App\Entity\Idempiere\CDoctype;
use App\Entity\Idempiere\CPaymentterm;
use App\Entity\Idempiere\MPricelist;
use App\Entity\Idempiere\MWarehouse;
use App\Entity\Idempiere\SmMarca;
use App\Entity\Idempiere\SmSalestemplate;
use App\Entity\Idempiere\SmSalestemplateline;
use App\Form\IdempiereType\SalesTemplateLineType;
use App\Form\IdempiereType\SalesTemplateType;
use App\LocalSalesTemplate\Application\useCase\GetLocalSalesTemplateBySalesTemplate;
use App\LocalSalesTemplate\Infrastructure\Persistence\Doctrine\Order\LocalSalesTemplateRepository;
use App\Repository\Idempiere\AdOrginfoRepository;
use App\Repository\Idempiere\AdOrgRepository;
use App\Repository\Idempiere\AdSequenceRepository;
use App\Repository\Idempiere\AdUserRepository;
use App\Repository\Idempiere\CBpartnerLocationRepository;
use App\Repository\Idempiere\CBpartnerRepository;
use App\Repository\Idempiere\CDoctypeRepository;
use App\Repository\Idempiere\CPaymenttermRepository;
use App\Repository\Idempiere\MPricelistRepository;
use App\Repository\Idempiere\MWarehouseRepository;
use App\Repository\Idempiere\SmMarcaRepository;
use App\Repository\Idempiere\SmSalestemplateRepository;
use App\Service\SalesTemplateService;
use App\Shared\Infraestructure\Idempiere\IdempiereRestClient;
use DateTime;
use Doctrine\ORM\Exception\ORMException;
use Doctrine\Persistence\ManagerRegistry;
use Psr\Log\LoggerInterface;
use Jaxon\AjaxBundle\Jaxon;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @Route("/plantilla")
*/
Class SalesTemplateController extends BaseController
{
public int $windowID = 1000174;
public int $processID = 273;
private SalesTemplateService $salesTemplateService;
private AdWindowAccess $windowAccess;
public function __construct(
RequestStack $requestStack, Security $security,
SalesTemplateService $salesTemplateService,
ManagerRegistry $manager,
private LocalSalesTemplateRepository $repo
)
{
parent::__construct($requestStack, $security);
/** @var AdRole */
$role = $this->session->get('role', null);
$windowAccess = $this->WindowAccess($manager, $this->windowID, $role->getId());
if( is_null($windowAccess) || !$windowAccess->isActive() )
return $this->redirectToRoute('app_dashboard');
$this->windowAccess = $windowAccess;
$this->salesTemplateService = $salesTemplateService;
}
/**
* Ruta para eliminar una plantilla
* @Route("/{id}/borrar", name="app_salestemplate_delete")
*
* @param SmSalestemplate $SalesTemplate Sales Template
* @param ManagerRegistry $manager Doctrine Manager
*
* @return Response HTTP Response
*/
public function delete(SmSalestemplate $SalesTemplate, ManagerRegistry $manager): Response
{
/**
* Session Var
*/
$session = $this->requestStack->getSession();
/** @var AdUser */
$user = $this->security->getUser();
/** @var AdRole */
// $role = $this->session->get('role');
$role = $session->get('role');
$access = $this->WindowAccess($manager, $this->windowID, $role->getId());
if( is_null($access) || !$access->isActive() || !$access->isReadWrite() )
return $this->redirectToRoute('app_dashboard');
######################################################################
try {
$SalesTemplate->setIsactive(false);
$em = $manager->getManagerForClass(SmSalestemplate::class);
$em->persist($SalesTemplate);
$em->flush();
} catch (ORMException $e) {
return new JsonResponse(['status' => 'error', 'msg' => $e]);
}
return $this->redirectToRoute('app_salestemplate');
}
/**
* Ruta para editar una plantilla
* @Route("/{id}/editar", name="app_salestemplate_edit")
*
* @param SmSalestemplate $SalesTemplate Sales Template
* @param Request $request HTTP Request
* @param ManagerRegistry $manager Doctrine Manager
* @param Jaxon $jaxon Jaxon Request Handler
* @param TranslatorInterface $translator Translator
*
* @return Response HTTP Response
*/
public function edit(
SmSalestemplate $SalesTemplate
, Request $request
, ManagerRegistry $manager
, Jaxon $jaxon
, TranslatorInterface $translator
): Response
{
return $this->redirectToRoute('app_salestemplate_view', ['id' => $SalesTemplate->getId()]);
/**
* Session Var
*/
// 1.-Ubicar el localsalestemplate asociado
$useCase = new GetLocalSalesTemplateBySalesTemplate($this->repo);
$local = $useCase->execute($SalesTemplate->getId());
if (!$local) {
dd(
$local
, "No se puede editar no viene de plantilla local"
, $SalesTemplate
);
}
// 2.-Verificar que la plantilla solo este en "NA"
// 3.-Poner la plantilla en "DR" solo si esta "NA"
/** @var AdUser */
$user = $this->security->getUser();
/** @var AdRole */
$role = $this->session->get('role');
$access = $this->WindowAccess($manager, $this->windowID, $role->getId());
if( is_null($access) || !$access->isActive() || !$access->isReadWrite() )
return $this->redirectToRoute('app_dashboard');
######################################################################
$form = $this->createForm(SalesTemplateType::class, $SalesTemplate, [
'action' => $this->generateUrl('app_salestemplate_edit', ['id' => $SalesTemplate->getId()]),
'method' => 'POST'
]);
//
$ROrg = new AdOrgRepository($manager);
$form->add('ad_org', EntityType::class, [
'class' => AdOrg::class,
'label' => 'Organization',
'choices' => $ROrg->findBy(['ad_org_id' => $SalesTemplate->getAdOrgId()]),
'choice_label' => 'name',
'row_attr' => [
'class' => 'd-none'
]
]);
//
$RMarca = new SmMarcaRepository($manager);
$form->add('sm_marca', EntityType::class, [
'class' => SmMarca::class,
'label' => 'Brand',
'choices' => $RMarca->findBy(['sm_marca_id' => $SalesTemplate->getSmMarcaId()]),
'choice_label' => 'name',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
//
$RBPartner = new CBpartnerRepository($manager);
$form->add('c_bpartner', EntityType::class, [
'class' => CBpartner::class,
'choices' => $RBPartner->findBy(['c_bpartner_id' => $SalesTemplate->getCBpartnerId()]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'Customer.S',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
//
$RBPartner = new CBpartnerLocationRepository($manager);
$form->add('c_bpartner_location', EntityType::class, [
'class' => CBpartnerLocation::class,
'choices' => $RBPartner->findBy(['c_bpartner_location_id' => $SalesTemplate->getCBpartnerLocationId()]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'Address.S',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
$form->add('bill_location', EntityType::class, [
'class' => CBpartnerLocation::class,
'choices' => $RBPartner->findBy(['c_bpartner_location_id' => $SalesTemplate->getBillLocationId()]),
'choice_label' => 'name',
// HTML Attribute
'label' => 'Address.Invoice',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
//
$RDoctype = new CDoctypeRepository($manager);
$form->add('c_doctype', EntityType::class, [
'class' => CDoctype::class,
'choices' => $RDoctype->findBy(['c_doctype_id' => $SalesTemplate->getCDoctypeId()]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'DocType',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
//
$RPaymentterm = new CPaymenttermRepository($manager);
$form->add('c_paymentterm', EntityType::class, [
'class' => CPaymentterm::class,
'choices' => $RPaymentterm->findBy(['c_paymentterm_id' => $SalesTemplate->getCPaymenttermId()]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'Payment.Term',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
//
$RPricelist = new MPricelistRepository($manager);
$form->add('m_pricelist', EntityType::class, [
'class' => MPricelist::class,
'choices' => $RPricelist->findBy(['m_pricelist_id' => $SalesTemplate->getMPricelistId()]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'PriceList',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
//
$RWarehouse = new MWarehouseRepository($manager);
$form->add('m_warehouse', EntityType::class, [
'class' => MWarehouse::class,
'label' => 'Warehouse',
'choices' => $RWarehouse->findBy([
'ad_org_id' => $SalesTemplate->getAdOrgId(),
'isactive' => 'Y',
'isdefault' => 'Y'
]),
'choice_label' => 'name',
'row_attr' => [
'class' => 'd-none'
]
]);
//
$RUser = new AdUserRepository($manager);
$form->add('salesrep', EntityType::class, [
'class' => AdUser::class,
'choices' => $RUser->findBy(['ad_user_id' => $SalesTemplate->getSalesrepId()]),
'choice_label' => 'name',
// HTML Attribute
'label' => 'Sales.Rep',
'attr' => [
'class' => 'form-control',
'readonly' => true
]
]);
######################################################################
$form->handleRequest($request);
if ( $form->isSubmitted() && $form->isValid() ) {
try {
$SalesTemplate
->setUpdated( new DateTime('now') )
->setUpdatedby( $user->getId() );
$em = $manager->getManagerForClass(SmSalestemplate::class);
$em->persist($SalesTemplate);
$em->flush();
} catch (ORMException $e) {
return new JsonResponse(['status' => 'FAIL', 'msg' => $e]);
}
}
######################################################################
$SalesTemplateLine = new SmSalestemplateline();
$SalesTemplateLine->setParent( $SalesTemplate );
$formline = $this->createForm(SalesTemplateLineType::class, $SalesTemplateLine, [
'action' => $this->generateUrl('app_salestemplateline_new'),
'method' => 'POST'
]);
######################################################################
return $this->renderForm('modules/idempiere/salestemplate/editV2.html.twig', [
'title' => "{$translator->trans('Sales.Templates')} | {$SalesTemplate->getDocumentno()}",
'modulo' => $translator->trans('Sales.Templates'),
'breadcrumb' => $SalesTemplate->getDocumentno(),
'salestemplate' => $SalesTemplate,
'form' => $form,
'formline' => $formline,
'docstatus' => $this->docstatus,
'docaction' => $this->docaction,
'priorityrule' => $this->priorityrule,
'jaxonCss' => $jaxon->css(),
'jaxonJs' => $jaxon->js(),
'jaxonScript' => $jaxon->script()
]);
}
/**
* Ruta para ver una lista con las plantillas de venta
* @Route("/", name="app_salestemplate")
*
* @param Request $request HTTP Request
* @param ManagerRegistry $manager Doctrine Manager
* @param TranslatorInterface $translator Translator
*
* @return Response HTTP Response
*/
public function list(Request $request, TranslatorInterface $translator, ManagerRegistry $manager): Response
{
/** @var AdOrg */
$organization = $this->session->get('organization');
$RUser = new AdUserRepository($manager);
$RMarca = new SmMarcaRepository($manager);
/** @var AdUser */
$user = $this->security->getUser();
$userPartner = $user->getCBpartner();
$isSalesRep = $userPartner && $userPartner->IsSalesRep();
return $this->render('modules/idempiere/salestemplate/index.html.twig', [
'title' => $translator->trans('Sales.Templates'),
'modulo' => $translator->trans('Sales.Templates'),
'docstatus' => $this->docstatus,
'salesreps' => $isSalesRep ? [$user] : $RUser->findSalesrep('', $organization->getId()),
'marcas' => $RMarca->findBy(['isactive' => 'Y'], ['name' => 'ASC']),
'access' => $this->windowAccess
]);
}
/**
* Ruta para crear una plantilla
* @Route("/nuevo", name="app_salestemplate_new")
*
* @param Request $request HTTP Request
* @param Jaxon $jaxon Jaxon Request Handler
* @param ManagerRegistry $manager Doctrine Manager
* @param TranslatorInterface $translator Tranlator
*
* @return Response HTTP Response
*/
public function new(Request $request, Jaxon $jaxon, ManagerRegistry $manager, TranslatorInterface $translator): Response
{
if (!$this->windowAccess->isReadWrite())
return $this->redirectToRoute('app_dashboard');
/**
* Get Parameters
*/
$BPartner = $request->query->get('bpartner', null);
/** @var AdUser */
$user = $this->security->getUser();
$UserBP = $user->getCBpartner();
$IsSalesRep = false;
if ( !is_null($UserBP) )
$IsSalesRep = $UserBP->IsSalesRep();
##########################################################################
# TODO: Configure option to use local tables
if ( true ) {
$params = [];
if (!is_null($BPartner))
$params['bpartner'] = $BPartner;
return $this->redirectToRoute('app_t_salestemplate_new', $params);
}
/**
* Build Form
*/
$SalesTemplate = new SmSalestemplate();
$SalesTemplate->setIsactive(true);
$form = $this->createForm(SalesTemplateType::class, $SalesTemplate, [
'action' => $this->generateUrl('app_salestemplate_new'),
'method' => 'POST'
]);
//
/** @var AdOrg */
$organization = $this->session->get('organization');
$ROrg = new AdOrgRepository($manager);
$form->add('ad_org', EntityType::class, [
'class' => AdOrg::class,
'choices' => $ROrg->findBy(['ad_org_id' => $organization->getId()]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'Organization',
'attr' => [
'class' => 'form-control'
]
]);
//
$RDoctype = new CDoctypeRepository($manager);
$form->add('c_doctype', EntityType::class, [
'class' => CDoctype::class,
'choices' => $RDoctype->findBy(['c_doctype_id' => 1000241]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'DocType',
'attr' => [
'class' => 'form-control'
]
]);
//
$RUser = new AdUserRepository($manager);
$form->add('salesrep', EntityType::class, [
'class' => AdUser::class,
'choices' => $IsSalesRep ? $RUser->findBy(['ad_user_id' => $user->getId()]) : $RUser->findSalesrep('', $organization->getId()),
'choice_label' => 'name',
// HTML Attribute
'label' => 'Sales.Rep',
'attr' => [
'class' => 'form-control',
'readonly' => $IsSalesRep
]
]);
//
$RPricelist = new MPricelistRepository($manager);
$form->add('m_pricelist', EntityType::class, [
'class' => MPricelist::class,
'choices' =>
$RPricelist
->createQueryBuilder('pl')
->where("pl.ad_org_id = :org_id AND pl.issopricelist = 'Y' AND pl.isactive = 'Y' AND pl.name NOT LIKE '%Costos Iniciales%'")
->setParameter('org_id', $organization->getId())
->getQuery()
->getResult(),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'PriceList',
'attr' => [
'class' => 'form-control'
]
]);
//
$RWarehouse = new MWarehouseRepository($manager);
$form->add('m_warehouse', EntityType::class, [
'class' => MWarehouse::class,
'choices' => $RWarehouse->findBy([
'ad_org_id' => $organization->getId(),
'isactive' => 'Y'
]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'Warehouse',
'attr' => [
'class' => 'form-control'
]
]);
//
$RPaymentterm = new CPaymenttermRepository($manager);
$form->add('c_paymentterm', EntityType::class, [
'class' => CPaymentterm::class,
'choices' => $RPaymentterm->findBy([
'ad_client_id' => $organization->getAdClientId(),
'paymenttermusage'=> ['B', 'S'],
'isactive' => 'Y'
]),
'choice_label' => 'name',
// HTLM Attribute
'label' => 'PaymentTerm',
'attr' => [
'class' => 'form-control'
]
]);
##########################################################################
/**
* Validate Form Request
*/
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$RSalesTemplate = new SmSalestemplateRepository(($manager));
$RSequence = new AdSequenceRepository($manager);
$date = new \DateTime("now");
$id = $RSequence->findNextSequence($RSalesTemplate->sequence);
/** @var SmSalestemplate */
$SalesTemplate = $form->getData();
$SalesTemplate
->setAdClientId( $organization->getAdClientId() )
->setCreated( $date )
->setCreatedBy( $user->getId() );
//
$ROrgInfo = new AdOrginfoRepository($manager);
$OrgInfo = $ROrgInfo->findOneBy(['ad_org_id' => $SalesTemplate->getAdOrg()->getId()]);
$SalesTemplate->setSmMarcaId($OrgInfo->getSmMarcaId());
//
$SalesTemplate
->setIsquatation('Y')
->setIsapproved('N')
->setIsapproved2('N')
->setIsapproved3('N')
// ->setPriorityrule('5')
->setAdUserId( $SalesTemplate->getSalesrep()->getId() );
//
$SalesTemplate->setDocumentno(
$RSequence->findNextSequence(
$SalesTemplate->getCDoctype()->getAdSequence(),
$SalesTemplate
)
);
//
$RBPartner = new CBpartnerRepository($manager);
$Partner = $RBPartner->find(
$request->request->get('bpartner_id', Constant::C_BPartner_ID)
);
$SalesTemplate->setCBpartner( $Partner );
//
$RBPLocation = new CBpartnerLocationRepository($manager);
$BPLocation = $RBPLocation->find(
$request->request->get('address', Constant::C_BPartner_Location_ID)
);
$SalesTemplate->setCBpartnerLocation( $BPLocation );
//
$SalesTemplate
->setDocstatus('DR')
->setDocaction('CO')
->setSmSalestemplateId( $id )
->setSmSalestemplateUu( $RSequence->findNextUU() )
->setProcessed('N')
->setProcessing('N')
->setProcessedon(0)
->setTotallines(0)
->setUpdated( $date )
->setUpdatedBy( $user->getId() );
//
try {
$em = $manager->getManagerForClass(SmSalestemplate::class);
$em->persist($SalesTemplate);
$em->flush();
return $this->redirect(
$this->generateUrl('app_salestemplate_edit', ['id' => $SalesTemplate->getId()])
);
} catch (ORMException $e) {
return new JsonResponse(['status' => 'fail', 'msg' => $e]);
}
}
##########################################################################
return $this->renderForm('modules/idempiere/salestemplate/new.html.twig', [
'title' => $translator->trans('New.Template'),
'modulo' => $translator->trans('Template'),
'breadcrumb' => 'Nuevo',
'form' => $form,
'jaxonCss' => $jaxon->css(),
'jaxonJs' => $jaxon->js(),
'jaxonScript' => $jaxon->script()
]);
}
/**
* Ruta para previsualizar el request antes de procesar
* @Route("/{id}/preview-process", name="app_salestemplate_preview_process")
*
* @param SmSalestemplate $SalesTemplate Plantilla de Venta
*
* @return JsonResponse
*/
public function previewProcess(SmSalestemplate $SalesTemplate): JsonResponse
{
$baseUrl = rtrim((string)($_ENV['IDEMPIERE_BASE_URL'] ?? ''), '/');
$endpoint = $baseUrl . '/api/v1/processes/processsalestemplate';
$payload = ['SM_SalesTemplate_ID' => $SalesTemplate->getId()];
return new JsonResponse([
'endpoint' => $endpoint,
'body' => $payload,
]);
}
/**
* Ruta para procesar los plantilla
* @Route("/{id}/procesar", name="app_salestemplate_process")
*
* @param SmSalestemplate $SalesTemplate Plantilla de Venta
* @param IdempiereRestClient $idempiereClient iDempiere REST client
*
* @return JsonResponse
*/
public function process(SmSalestemplate $SalesTemplate, IdempiereRestClient $idempiereClient, LoggerInterface $logger): JsonResponse
{
$res = $idempiereClient->post(
'/api/v1/processes/sm_salestemplate_process',
[
'record-id' => $SalesTemplate->getId(),
'table-id' => 1000391,
]
);
$logger->info('iDempiere process response', [
'salestemplate_id' => $SalesTemplate->getId(),
'documentno' => $SalesTemplate->getDocumentno(),
'http_status' => $res['status'],
'raw' => $res['body'],
]);
$decoded = json_decode((string)($res['body'] ?? ''), true);
$rpr = is_array($decoded['RunProcessResponse'] ?? null) ? $decoded['RunProcessResponse'] : null;
if ($rpr !== null) {
$isError = filter_var($rpr['@IsError'] ?? false, FILTER_VALIDATE_BOOLEAN);
$errorMsg = (string)($rpr['Summary'] ?? $rpr['summary'] ?? $rpr['Error'] ?? 'Error procesando plantilla.');
} else {
$isError = (bool)($decoded['isError'] ?? $decoded['IsError'] ?? ($res['status'] >= 400));
$errorMsg = (string)($decoded['summary'] ?? $decoded['detail'] ?? $decoded['Error'] ?? 'Error procesando plantilla.');
}
if ($isError) {
$response = [
'status' => 'error',
'msg' => $errorMsg,
];
} else {
$response = [
'status' => 'success',
'url' => $this->generateUrl('app_salestemplate_view', ['id' => $SalesTemplate->getId()]),
'documentno' => $SalesTemplate->getDocumentno(),
'msg' => $rpr !== null ? (string)($rpr['Summary'] ?? $rpr['summary'] ?? '') : (string)($decoded['summary'] ?? ''),
];
}
return new JsonResponse($response);
}
/**
* Ruta para ver un plantilla
* @Route("/{id}", name="app_salestemplate_view")
*
* @param SmSalestemplate $SalesTemplate Sales Template
* @param Jaxon $jaxon Jaxon Request Handler
* @param TranslatorInterface $translator Translator
*
* @return Response HTTP Response
*/
public function view(SmSalestemplate $SalesTemplate, Jaxon $jaxon, TranslatorInterface $translator): Response
{
$useCase = new GetLocalSalesTemplateBySalesTemplate($this->repo);
$local = $useCase->execute($SalesTemplate->getId());
if($local) {
$local = $this->repo->get($local->id);
}
$edit = false;
if($local) {
$edit = $local->getId();
}
return $this->render('modules/idempiere/salestemplate/view.html.twig', [
'title' => "{$translator->trans('Sales.Templates')} | {$SalesTemplate->getDocumentno()}",
'modulo' => $translator->trans('Sales.Templates'),
'breadcrumb' => $SalesTemplate->getDocumentno(),
'salestemplate' => $SalesTemplate,
'docstatus' => $this->docstatus,
'priorityrule' => $this->priorityrule,
'jaxonCss' => $jaxon->css(),
'jaxonJs' => $jaxon->js(),
'jaxonScript' => $jaxon->script(),
'edit' => $edit
]);
}
}
?>