<?php
declare(strict_types=1);
namespace App\Admin;
use App\Entity\CentroCusto;
use App\Entity\ContaPagar;
use App\Entity\ContaReceber;
use App\Entity\FluxoCaixa;
use App\Entity\PropostaComercial;
use App\Enums\StatusContaFinanceiro;
use App\Enums\PeriodicidadeRecorrenciaEnum;
use App\Enums\TipoContaPagarEnum;
use App\Enums\ContasBancariasEnum;
use App\Enums\UFEnum;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Form\Type\ModelType;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\DoctrineORMAdminBundle\Filter\ChoiceFilter;
use Sonata\DoctrineORMAdminBundle\Filter\DateRangeFilter;
use Sonata\Form\Type\DatePickerType;
use Sonata\Form\Type\DateRangePickerType;
use Sonata\Form\Type\DateTimeRangePickerType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Validator\Constraints as Assert;
use Sonata\Form\Type\CollectionType;
use Sonata\Form\Validator\ErrorElement;
use Sonata\AdminBundle\Route\RouteCollection;
final class ContaPagarAdmin extends AbstractAdmin
{
//protected $perPageOptions = [64, 128, 256, 2000];
protected $datagridValues = [
'_page' => 1,
'_sort_order' => 'ASC',
'_sort_by' => 'vencimento',
//'_per_page' => 2000
];
protected function configureRoutes(RouteCollection $collection)
{
$collection->add('opendocument');
}
//protected $maxPerPage = 2000;
protected function configureDatagridFilters(DatagridMapper $datagridMapper): void
{
$datagridMapper
->add('descricao','doctrine_orm_callback',[
'label'=>'Descrição',
'callback' => array($this, 'filterDescricao'),
])
->add('classificacao',null, array('label'=>'Classificação', 'field_options' => ['expanded' => false, 'multiple' => true]))
->add('fornecedor',null, array('label'=>'Fornecedor'))
->add('colaborador',null, array('label'=>'Credor'))
->add('os',null, array('label'=>'Ordem de Serviço'))
->add('tipoDocumento',null, array(), ChoiceType::class, array(
'choices' => TipoContaPagarEnum::getAssociatedValues()
))
->add('status','doctrine_orm_callback', array(
'label' => 'Situação',
'callback' => function($queryBuilder, $alias, $field, $value) {
if (!$value['value']) {
return;
}
if($value['value']==StatusContaFinanceiro::ABERTO) {
$queryBuilder->andWhere($alias.'.pagoEm is null');
$queryBuilder->andWhere($alias.'.vencimento < :hoje');
$queryBuilder->setParameter('hoje',new \DateTime('now'));
} else if($value['value']==StatusContaFinanceiro::PAGO) {
$queryBuilder->andWhere($alias.'.pagoEm is not null');
} else if($value['value']==StatusContaFinanceiro::ATRASADO) {
$queryBuilder->andWhere($alias.'.pagoEm is null');
$queryBuilder->andWhere($alias.'.vencimento < :hoje');
$queryBuilder->setParameter('hoje',new \DateTime('now'));
}
return true;
}
), ChoiceType::class, array(
'choices' => StatusContaFinanceiro::getAssociatedValues()
))
->add('vencimento', 'doctrine_orm_datetime_range', ['field_type'=> DateRangePickerType::class])
->add('valor')
->add('numeroNota', null, ['label'=>'Nº nota fiscal'])
->add('parcela')
->add('pagoEm', 'doctrine_orm_datetime_range', ['field_type'=> DateRangePickerType::class])
->add('valorPago', null, ['label'=>'Valor pago'])
->add('createdAt', null, ['label'=>'Data de cadastro'])
->add('updatedAt', null, ['label'=>'Data da última atualização'])
->add('isGeral',null, ['label'=>'Despesa Geral'], ChoiceType::class, array(
'choices' => [
'Sim' => 1,
'Não' => 0
]
))
;
}
protected function configureListFields(ListMapper $listMapper): void
{
$this->setTemplate('list', 'ContaPagar/list.html.twig');
$listMapper
->add('status',null, ['label'=>false,'template'=>'ContaPagar/status_list.html.twig'])
->add('descricao', null, ['label'=>'Descrição','template'=>'ContaPagar/descricao_list.html.twig'])
->add('vencimento')
->add('numeroNota', null, ['label'=>'Nº nota fiscal'])
->add('pagoEm', null, ['label'=>'Data do pagamento'])
->add('valor', null, ['label'=>'Valor','template'=>'Generic/currency_list.html.twig'])
->add('valorPago', null, ['label'=>'Valor Bruto','template'=>'Generic/currency_valorPago_list.html.twig'])
->add('classificacao',null, array('label'=>'Classificação'))
->add('_action', null, [
'actions' => [
'show' => [],
'edit' => [],
'delete' => [],
],
]);
}
public function filterDescricao($queryBuilder, $alias, $field, $value)
{
if (!$value['value']) {
return;
}
$value = mb_strtolower($value['value']);
$queryBuilder
//->andWhere("UNACCENT(LOWER($alias.descricao)) LIKE UNACCENT(:nome)" )
->andWhere("LOWER($alias.descricao) LIKE :nome" )
->setParameter('nome', "%$value%");
return true;
}
protected function configureFormFields(FormMapper $formMapper): void
{
/** @var ContaPagar $contaPagar */
$contaPagar = $this->getSubject();
//$imgReq = !is_null($empresa) && is_null($empresa->getId());
$imgReq = false;
$fileFieldOptionsNotaFiscal = [
'data_class' => null,
'required' => false,
'label' => 'Nota Fiscal',
'help' => '',
];
if (!is_null($contaPagar) && $contaPagar->getNotaFiscal() != '') {
$fileFieldOptionsNotaFiscal['help'] = '<a href="/'.$contaPagar->getNotaFiscal().'" target="_blank" class="btn btn-warning"/><i class="fa fa-eye" aria-hidden="true"></i> Visualizar</a>';
}
$fileFieldOptionsComprovantePagamento = [
'data_class' => null,
'required' => false,
'label' => 'Comprovante de Pagamento',
'help' => '',
];
if (!is_null($contaPagar) && $contaPagar->getComprovantePagamento() != '') {
$fileFieldOptionsComprovantePagamento['help'] = '<a href="/'.$contaPagar->getComprovantePagamento().'" target="_blank" class="btn btn-warning"/><i class="fa fa-eye" aria-hidden="true"></i> Visualizar</a>';
}
$fileFieldOptionsDocumentoPagamento = [
'data_class' => null,
'required' => false,
'label' => 'Documento para Pagamento',
'help' => '',
];
if (!is_null($contaPagar) && $contaPagar->getDocumentoPagamento() != '') {
$fileFieldOptionsDocumentoPagamento['help'] = '<a href="/'.$contaPagar->getDocumentoPagamento().'" target="_blank" class="btn btn-warning"/><i class="fa fa-eye" aria-hidden="true"></i> Visualizar</a>';
}
$queryBuilderClassificacao = $this->getModelManager()
->getEntityManager(CentroCusto::class)
->createQueryBuilder('cc')
->select('cc')
->where('cc.classificacao != :classificacao')
->from('App:CentroCusto', 'cc')
->setParameter('classificacao','RECEBIMENTOS')
->orderBy('cc.titulo', 'ASC')
;
$formMapper
->with('Informações I', ['class' => 'col-md-6'])
->add('descricao')
->add('tipoDocumento', ChoiceType::class, [
'label' => 'Tipo de documento',
'placeholder' => '-- Selecione --',
'choices' => TipoContaPagarEnum::getAssociatedValues(),
])
->add('classificacao', ModelType::class, [
'placeholder' => '-- Selecione --',
'label' => 'Classificação',
'required' => true,
'expanded' => false,
'multiple' => false,
'query' => $queryBuilderClassificacao
])
->add('fornecedor', ModelType::class, [
'placeholder' => '-- Selecione --',
'label' => 'Fornecedor',
'required' => false,
'expanded' => false,
'multiple' => false
])
->add('os', ModelType::class, [
'placeholder' => '-- Selecione --',
'label' => 'Ordem de serviço',
'required' => false,
'expanded' => false,
'multiple' => false
])
->add('isGeral',null, ['label'=>'Despesa Geral'])
->add('colaborador', ModelType::class, [
'placeholder' => '-- Selecione --',
'label' => 'Credor(colaborador)',
'required' => false,
'expanded' => false,
'multiple' => false
])
->add('vencimento', DatePickerType::class,['label'=>'Data do vencimento', 'required'=>true])
->add('isRecorrente',null, ['label'=>'É recorrente'])
->add('isValorFixo',null, ['label'=>'É valor fixo'])
->add('periodicidadeRecorrencia', ChoiceType::class, [
'label' => 'Periodicidade Recorrência',
'placeholder' => '-- Selecione --',
'choices' => PeriodicidadeRecorrenciaEnum::getAssociatedValues(),
'required' => false
])
->add('contaBancaria', ChoiceType::class, [
'label' => 'Conta Bancária da movimentação',
'placeholder' => '-- Selecione --',
'choices' => ContasBancariasEnum::getAssociatedValues(),
'required' => false
])
->end()
->with('Informações II', ['class' => 'col-md-6'])
->add('valor', MoneyType::class, [
'label' => 'Valor original',
'currency' => 'BRL',
'grouping' => true,
'required' => true,
'attr' => ['class' => 'maskMoney'],
])
->add('numeroNota', null, ['label'=>'Nº nota fiscal'])
->add('parcelas', null, ['label'=>'Parcelas', 'help'=>'*Caso uma conta seja parcelada', 'attr'=>['type'=>'number', 'min'=>1, 'class'=>'parcelas_conta_receber']])
->add('parcela',null, ['label'=>'Parcela atual', 'help'=>'*Caso seja uma parcela sendo paga', 'attr'=>['type'=>'number', 'min'=>1, 'class'=>'parcela_atual_conta_receber']])
->add('pagoEm', DatePickerType::class,['label'=>'Data do pagamento', 'required'=>false])
->add('valorPago', MoneyType::class, [
'label' => 'Valor pago',
'currency' => 'BRL',
'grouping' => true,
'required' => false,
'attr' => ['class' => 'maskMoney'],
])
->add('notaFiscalFile', FileType::class, [
'constraints' => [new Assert\File([
'mimeTypes' => [
'application/pdf',
'application/x-pdf'
],
'mimeTypesMessage' => 'O sistema só aceita arquivos no formato .pdf'
])],
'label' => 'Nota Fiscal',
'help' => $fileFieldOptionsNotaFiscal['help'],
'required' => false,
])
->add('documentoPagamentoFile', FileType::class, [
'constraints' => [new Assert\File([
'mimeTypes' => [
'application/pdf',
'application/x-pdf'
],
'mimeTypesMessage' => 'O sistema só aceita arquivos no formato .pdf'
])],
'label' => 'Documento para pagamento',
'help' => $fileFieldOptionsDocumentoPagamento['help'],
'required' => false,
])
->add('comprovantePagamentoFile', FileType::class, [
'constraints' => [new Assert\File([
'mimeTypes' => [
'application/pdf',
'application/x-pdf'
],
'mimeTypesMessage' => 'O sistema só aceita arquivos no formato .pdf'
])],
'label' => 'Comprovante de pagamento',
'help' => $fileFieldOptionsComprovantePagamento['help'],
'required' => false,
])
->end()
->with('Split do total do valor a pgar', ['class' => 'col-md-12'])
->add('splits', CollectionType::class, [
'label' => 'Split de valor',
'by_reference' => false,
], [
'edit' => 'inline',
'inline' => 'table'
])
->end()
;
}
protected function configureShowFields(ShowMapper $showMapper): void
{
$showMapper
->add('id')
->add('tipo')
->add('fornecedor.nome')
->add('colaborador')
->add('vencimento')
->add('valor', null, ['label'=>'Valor', 'template'=>'Generic/currency_show.html.twig'])
->add('classificacao',null, ['label'=>'Classificação'])
->add('numeroNota', null, ['label'=>'Nº nota fiscal'])
->add('parcela')
->add('pagoEm', null, ['label'=>'Data do pagamento'])
->add('valorPago', null, ['label'=>'Valor pago', 'template'=>'Generic/currency_show_valor_pago.html.twig'])
->add('createdAt', null, ['label'=>'Data de cadastro'])
->add('updatedAt', null, ['label'=>'Data da última atualização'])
;
}
public function prePersist($object)
{
ini_set('upload_max_filesize', '10M');
$object->setCreatedAt(new \DateTime('now'));
$object->setUpdatedAt(new \DateTime('now'));
// if(!$this->totalSplitCorreto($object)){
// exit('Os valores de split não batem com o valor total');
// }
if($object->getNotaFiscalFile()){
$this->manageFilesUploadPdfNotaFiscal($object);
}
if($object->getComprovantePagamentoFile()){
$this->manageFilesUploadPdfComprovante($object);
}
if($object->getDocumentoPagamentoFile()){
$this->manageFilesUploadPdfDocumentoPagamento($object);
}
// Verifica se é parcelado
if(!empty($object->getParcelas())){
$object->setIsParcelado(true);
$object->setParcela(1);
if(!$object->getIsValorFixo()){
$valorParcela = $object->getValor()/$object->getParcelas();
$valorParcela = round($valorParcela,2);
$object->setValor($valorParcela);
}
}
$object = $this->setConntaPagarSplit($object);
return $object;
}
public function setConntaPagarSplit($object){
foreach ($object->getSplits() as $split) {
$split->setContaPagar($object);
}
return $object;
}
public function preUpdate($object)
{
ini_set('upload_max_filesize', '10M');
$object->setUpdatedAt(new \DateTime('now'));
if($object->getNotaFiscalFile()){
$this->manageFilesUploadPdfNotaFiscal($object);
}
if($object->getComprovantePagamentoFile()){
$this->manageFilesUploadPdfComprovante($object);
}
if($object->getDocumentoPagamentoFile()){
$this->manageFilesUploadPdfDocumentoPagamento($object);
}
$object = $this->setConntaPagarSplit($object);
return $object;
}
public function postPersist($object)
{
parent::postPersist($object); // TODO: Change the autogenerated stub
$this->geraFluxoCaixa($object);
$this->geraParcelas($object);
}
public function postUpdate($object)
{
/** @var ContaPagar $object */
parent::postUpdate($object); // TODO: Change the autogenerated stub
$this->geraFluxoCaixa($object);
}
private function geraFluxoCaixa($object) {
// Criar um fluxo de caixa
$container = $this->getConfigurationPool()->getContainer();
$em = $container->get('doctrine.orm.entity_manager');
if($object->getPagoEm()) {
$fluxoCaixaConta = $em->getRepository(FluxoCaixa::class)->findOneBy(['contaPagar'=>$object]);
if(!$fluxoCaixaConta instanceof FluxoCaixa){
$fluxoCaixa = (new FluxoCaixa())
->setContaPagar($object)
->setTipo('CONTA PAGAR')
->setDataExtrato($object->getPagoEm());
$em->persist($fluxoCaixa);
$em->flush();
}
}
}
public function validate(ErrorElement $errorElement, $object)
{
if(!$this->totalSplitCorreto($object)){
$errorElement->with('splits')->addViolation('Os valores de split não batem com o valor total');
}
}
public function postRemove($object)
{
parent::postRemove($object); // TODO: Change the autogenerated stub
if($object->getNotaFiscalFile()){
if (file_exists($object->getNotaFiscalFile())) {
@unlink($object->getNotaFiscal());
}
}
if($object->getComprovantePagamentoFile()){
if (file_exists($object->getComprovantePagamentoFile())) {
@unlink($object->getComprovantePagamento());
}
}
if($object->getDocumentoPagamentoFile()){
if (file_exists($object->getDocumentoPagamentoFile())) {
@unlink($object->getDocumentoPagamentoFile());
}
}
}
/**
* @param ContaPagar $obj
* @return ContaPagar
*/
private function manageFilesUploadPdfNotaFiscal($obj)
{
$file = $obj->getNotaFiscalFile();
$nameFile = $filename = md5(date('Y-m-d H:i:s:u')).".".$file->getClientOriginalExtension();
$uploadPath = "uploads/notas-fiscais-contas-pagar";
$file->move($uploadPath, $nameFile);
$obj->setNotaFiscalOriginal($uploadPath . "/" . $filename);
$obj->setNotaFiscal($uploadPath . "/" . $filename);
}
/**
* @param ContaPagar $obj
* @return ContaPagar
*/
private function manageFilesUploadPdfComprovante($obj)
{
$file = $obj->getComprovantePagamentoFile();
$nameFile = $filename = md5(date('Y-m-d H:i:s:u')).".".$file->getClientOriginalExtension();
$uploadPath = "uploads/comprovantes-contas-pagar";
$file->move($uploadPath, $nameFile);
$obj->setComprovantePagamento($uploadPath . "/" . $filename);
$obj->setComprovantePagamentoOriginal($uploadPath . "/" . $filename);
}
/**
* @param ContaPagar $obj
* @return ContaPagar
*/
private function manageFilesUploadPdfDocumentoPagamento($obj)
{
$file = $obj->getDocumentoPagamentoFile();
$nameFile = $filename = md5(date('Y-m-d H:i:s:u')).".".$file->getClientOriginalExtension();
$uploadPath = "uploads/documento-pagamento-contas-pagar";
$file->move($uploadPath, $nameFile);
$obj->setDocumentoPagamento($uploadPath . "/" . $filename);
$obj->setDocumentoPagamentoOriginal($uploadPath . "/" . $filename);
}
private function totalSplitCorreto($contaPagar) {
// if(count($contaPagar->getSplits())==0){
// return true;
// }
// $totalSplit = 0;
// foreach ($contaPagar->getSplits() as $split) {
// $totalSplit += $split->getValor();
// }
// $valorOriginal = floatval($contaPagar->getValor());
// $totalSplit = floatval($totalSplit);
// var_dump($valorOriginal);
// echo '<br/>';
// var_dump($totalSplit);
// echo '<br/>';
// echo 'TOTAL: ' . $valorOriginal . '<br/>';
// echo 'TOTAL SPLIT: ' . $totalSplit . '<br/>';
// if($valorOriginal==$totalSplit){
// exit('BATEU!');
// return true;
// }
// exit('OK');
// return false;
return true;
}
private function geraParcelas($contaPagar) {
$container = $this->getConfigurationPool()->getContainer();
$em = $container->get('doctrine.orm.entity_manager');
if($contaPagar instanceof ContaPagar){
for($i=1;$i<$contaPagar->getParcelas();$i++){
$parcela = $i+1;
$contaPagarNew = clone $contaPagar;
// próxima parcela
$dataVencimento = $contaPagarNew->getVencimento()->format('Y-m-d');
$proximoMes = date('Y-m-d', strtotime('+'.$i.' month', strtotime(date($dataVencimento))));
$dateDiaUtil = $this->proximoDiaUtil($proximoMes);
$date = \DateTime::createFromFormat('Y-m-d', $dateDiaUtil);
$contaPagarNew->setVencimento($date);
$contaPagarNew->setParcela($parcela);
$em->persist($contaPagarNew);
$em->flush();
}
}
}
private function proximoDiaUtil($data, $saida = 'Y-m-d') {
// Converte $data em um UNIX TIMESTAMP
$timestamp = strtotime($data);
// Calcula qual o dia da semana de $data
// O resultado será um valor numérico:
// 1 -> Segunda ... 7 -> Domingo
$dia = date('N', $timestamp);
// Se for sábado (6) ou domingo (7), calcula a próxima segunda-feira
if ($dia >= 6) {
$timestamp_final = $timestamp + ((8 - $dia) * 3600 * 24);
} else {
// Não é sábado nem domingo, mantém a data de entrada
$timestamp_final = $timestamp;
}
return date($saida, $timestamp_final);
//echo proximoDiaUtil('2016-09-04');
}
}