Untitled
Anonymous
plain_text
04/27/2026 7:36 PM
12.4 KB
15
Indexable
private async obterCustosMaoObra({ filtro }: QueryCustom<BuscarCustosFiltroDto>, agrupamento: string) {
// obter custo por hora de cada propriedade
const custoHoraMaoObra: { safraId: number; propriedadeId: number; competencia: string; custoPorHora: number }[] =
[];
let tipoCalculo: 'geral' | 'competencia' = undefined;
for (const safraId of filtro['safra.id']) {
// se tem valor lançado para a safra inteira
const valorMaoObraSafra = await this.dataSource.getRepository(ValoresMaoObra)
.createQueryBuilder('valorMaoObra')
.leftJoinAndSelect('valorMaoObra.propriedades', 'propriedade')
.leftJoinAndSelect('propriedade.unidadesProdutivas', 'unidadeProdutiva')
.leftJoinAndSelect(
'unidadeProdutiva.culturas',
'cultivo',
'(cultivo.dataEncerramentoProducao >= NOW() OR cultivo.dataEncerramentoProducao IS NULL)',
)
.where('valorMaoObra.safraId = :safraId', { safraId: safraId })
.andWhere(`competencia = '00/0000'`)
.getOne();
if (valorMaoObraSafra) {
tipoCalculo = 'geral';
const valorRateadoSafra: { propriedadeId: number; valor: number }[] = [];
const areaPropriedades = this.obterAreaPropriedades(valorMaoObraSafra.propriedades);
// faz o rateio do valor pela área cada propriedade
for (const propriedade of valorMaoObraSafra.propriedades) {
const areaPropriedade = this.obterAreaPropriedade(propriedade);
valorRateadoSafra.push({
propriedadeId: propriedade.id,
valor: (valorMaoObraSafra.valorTotal / areaPropriedades) * areaPropriedade,
});
}
// busca todas as atividades da safra atual para obter o total de horas
const horasRateadasSafra = await this.obterHorasHomemRateio(`${this.nomeTabela}.safraId = :safraId`, {
safraId: safraId,
});
valorRateadoSafra.forEach((valorSafra) => {
const horasPropriedade = horasRateadasSafra.find(
(horaSafra) => horaSafra.propriedadeId === valorSafra.propriedadeId,
)?.horas;
custoHoraMaoObra.push({
safraId: +safraId,
propriedadeId: valorSafra.propriedadeId,
custoPorHora: horasPropriedade ? valorSafra.valor / horasPropriedade : 0,
competencia: '00/0000',
});
});
} else {
tipoCalculo = 'competencia';
// se tem valor lançado para cada mês
const valorRateadoMes: { propriedadeId: number; competencia: string; valor: number }[] = [];
const horasRateadasMes: { propriedadeId: number; competencia: string; horas: number }[] = [];
const valoresMaoObraMes = await this.dataSource.getRepository(ValoresMaoObra)
.createQueryBuilder('valorMaoObra')
.leftJoinAndSelect('valorMaoObra.propriedades', 'propriedade')
.leftJoinAndSelect('propriedade.unidadesProdutivas', 'unidadeProdutiva')
.leftJoinAndSelect(
'unidadeProdutiva.culturas',
'cultivo',
'(cultivo.dataEncerramentoProducao >= NOW() OR cultivo.dataEncerramentoProducao IS NULL)',
)
.where('valorMaoObra.safraId = :safraId', { safraId: safraId })
.andWhere(`competencia <> '00/0000'`)
.getMany();
// percorre os valores encontrados e busca as atividades do mês da competencia e da safra corrente para obter o total de horas
for (const valorMes of valoresMaoObraMes) {
const areaPropriedades = this.obterAreaPropriedades(valorMes.propriedades);
// faz o rateio do valor pela área cada propriedade
for (const propriedade of valorMes.propriedades) {
const areaPropriedade = this.obterAreaPropriedade(propriedade);
valorRateadoMes.push({
propriedadeId: propriedade.id,
competencia: valorMes.competencia,
valor: (valorMes.valorTotal / areaPropriedades) * areaPropriedade,
});
}
// busca todas as atividades da safra/competência atual para obter o total de horas
const horasRateio = await this.obterHorasHomemRateio(
`${this.nomeTabela}.safraId = :safraId AND
TO_CHAR(${this.nomeTabela}.dataInicial, 'MM/YYYY') = :competencia AND
propriedade.id IN (:...propriedadeIds)`,
{
safraId: safraId,
competencia: valorMes.competencia,
propriedadeIds: valorMes.propriedades.map((p) => p.id),
},
);
horasRateadasMes.push(...horasRateio.map((hora) => ({ ...hora, competencia: valorMes.competencia })));
}
valorRateadoMes.forEach((valorMesAtual) => {
const propriedadeCalculada = custoHoraMaoObra.find(
(custo) =>
custo.propriedadeId === valorMesAtual.propriedadeId &&
custo.safraId === +safraId &&
custo.competencia === valorMesAtual.competencia,
);
// como é feito um cálculo geral para a propriedade, não tem necessidade de adicionar mais de uma vez ao array final
if (!propriedadeCalculada) {
const somatorioHoras = somarArray(
horasRateadasMes
.filter(
(horaMes) =>
horaMes.propriedadeId === valorMesAtual.propriedadeId &&
horaMes.competencia === valorMesAtual.competencia,
)
.map((horaMes) => +horaMes.horas),
);
const somatorioValor = somarArray(
valorRateadoMes
.filter(
(valorMes) =>
valorMes.propriedadeId === valorMesAtual.propriedadeId &&
valorMes.competencia === valorMesAtual.competencia,
)
.map((valor) => +valor.valor),
);
const custoPorHora = somatorioHoras ? somatorioValor / somatorioHoras : 0;
custoHoraMaoObra.push({
safraId: +safraId,
propriedadeId: valorMesAtual.propriedadeId,
custoPorHora: custoPorHora,
competencia: valorMesAtual.competencia,
});
}
});
}
}
// para buscar o total de horas do filtro precisa ratear as horasHomem pela área dos cultivos
const { condicoes, parametros } = this.montarCondicoes(filtro, this.nomeTabela);
const queryBuilder = this.createQueryBuilder(this.nomeTabela)
.select(agrupamento, 'agrupamento')
.addSelect('propriedade.id AS "propriedadeId"')
.addSelect('safra.id AS "safraId"')
.addSelect(
`ROUND(
SUM(
CASE WHEN COALESCE(${this.nomeTabela}."areaTotal", 0) > 0 THEN
${this.nomeTabela}.horasHomem / ${this.nomeTabela}."areaTotal" * cultivo.area
ELSE 0
END
)
, 2)`,
'horasHomem',
)
.leftJoin(`${this.nomeTabela}.unidadesProdutivasCulturas`, 'cultivo')
.leftJoin('cultivo.unidadeProdutiva', 'unidadeProdutiva')
.leftJoin('unidadeProdutiva.propriedade', 'propriedade')
.leftJoin('cultivo.cultura', 'cultura')
.leftJoin('cultivo.variedade', 'variedade')
.leftJoin('cultivo.variedadeClone', 'variedadeClone')
.leftJoin(`${this.nomeTabela}.safra`, 'safra')
.where(`${this.nomeTabela}.organizacaoId = :organizacaoId`, {
organizacaoId: this.getContexto().organizacao,
})
.andWhere(`${this.nomeTabela}.empresaId = :empresaId`, {
empresaId: this.getContexto().empresa,
});
if (condicoes && parametros) {
queryBuilder.andWhere(condicoes, parametros);
}
queryBuilder.groupBy('safra.id').addGroupBy('propriedade.id').addGroupBy(agrupamento);
queryBuilder.orderBy('safra.id', 'ASC').addOrderBy('propriedade.id', 'ASC');
if (tipoCalculo === 'competencia') {
queryBuilder.addSelect(`TO_CHAR(${this.nomeTabela}.dataInicial, 'MM/YYYY')`, 'competencia');
queryBuilder.addGroupBy('competencia');
queryBuilder.addOrderBy('competencia', 'ASC');
}
const lancamentosFiltro = await queryBuilder.getRawMany();
const result: { agrupamento: string; custosMaoObra: number }[] = [];
lancamentosFiltro
.map((lancamento) => {
const custoPorHora =
tipoCalculo === 'geral'
? custoHoraMaoObra.find(
(c) => c.safraId === lancamento.safraId && c.propriedadeId === lancamento.propriedadeId,
)?.custoPorHora
: custoHoraMaoObra.find(
(c) =>
c.safraId === lancamento.safraId &&
c.propriedadeId === lancamento.propriedadeId &&
c.competencia === lancamento.competencia,
)?.custoPorHora;
return {
...lancamento,
custosMaoObra: lancamento.horasHomem * (custoPorHora || 0),
};
})
.forEach((r, i, array) => {
const agrupamentoCalculado = result.find((res) => res.agrupamento === r.agrupamento);
if (!agrupamentoCalculado) {
const custosAgrupamento = somarArray(
array.filter((a) => a.agrupamento === r.agrupamento).map((a) => a.custosMaoObra),
);
result.push({
agrupamento: r.agrupamento,
custosMaoObra: custosAgrupamento,
});
}
});
return result;
}Editor is loading...
Leave a Comment