unit uCalculosUtils; interface uses uDADataTable, uDAInterfaces; const CAMPO_ID = 'ID'; CAMPO_POSICION = 'POSICION'; CAMPO_TIPO = 'TIPO_DETALLE'; CAMPO_ID_ARTICULOS = 'ID_ARTICULO'; CAMPO_CONCEPTO = 'CONCEPTO'; CAMPO_CANTIDAD = 'CANTIDAD'; CAMPO_IMPORTE_UNIDAD = 'IMPORTE_UNIDAD'; CAMPO_IMPORTE_TOTAL = 'IMPORTE_TOTAL'; CAMPO_DESCUENTO = 'DESCUENTO'; CAMPO_INCREMENTO = 'INCREMENTO'; CAMPO_DECREMENTO = 'DECREMENTO'; CAMPO_IMPORTE_PORTE = 'IMPORTE_PORTE'; CAMPO_VISIBLE = 'VISIBLE'; CAMPO_VALORADO = 'VALORADO'; function CalcularLineaConcepto (const ADataTable : TDADataTable; const NumDecimales: Smallint = 2): Double; procedure ValidarCamposLineaConcepto(DataTable: TDADataTable); procedure DesglosarPorte(ImportePorte: Currency; ADetalles: IDAStronglyTypedDataTable); function DarTotalPorte(ADetalles: IDAStronglyTypedDataTable): Double; function CalcularImporteNeto (const ImporteUnidad: Double = 0; const Incremento: Double = 0; const Decremento: Double = 0; const NumDecimales: Smallint = 2): Double; implementation uses SysUtils, DB, Variants, cxControls, uNumUtils; function CalcularImporteNeto (const ImporteUnidad: Double = 0; const Incremento: Double = 0; const Decremento: Double = 0; const NumDecimales: Smallint = 2): Double; var ValorAIncrementar: Double; ImporteNeto1: Double; ValorADecrementar: Double; begin //Se solicita cambio de calculo 06/10/2021 po Mónica //Importe-unidad(100) incremento(10%) valor_a_incrementar (10) = Importe_neto1(110) //Importe_neto1(110) decremento(10%) valor_a_decrementar(11) = Importe_neto2(99) ValorAIncrementar := ImporteUnidad * (Incremento/100); ImporteNeto1 := ImporteUnidad + ValorAIncrementar; ValorADecrementar := ImporteNeto1 * (Decremento/100); Result := RoundCurrency((ImporteNeto1 - ValorADecrementar), NumDecimales) end; function CalcularLineaConcepto (const ADataTable : TDADataTable; const NumDecimales: Smallint = 2): Double; var AField: TDAField; ImporteTotal, ImporteNeto, Incremento, Decremento, Descuento, ImportePorte : Double; begin with ADataTable do begin Incremento := 0; Decremento := 0; Descuento := 0; ImportePorte := 0; ImporteNeto := FieldByName(CAMPO_IMPORTE_UNIDAD).AsFloat; //Validamos la existencia del campo incremento, por si no está activo en otros módulos que no sean (presupuestos y contratos) AField := FindField(CAMPO_INCREMENTO); if Assigned(AField) then if (not VarIsNull(AField.AsVariant)) then Incremento := AField.AsFloat; //Validamos la existencia del campo decremento, por si no está activo en otros módulos que no sean (presupuestos y contratos) AField := FindField(CAMPO_DECREMENTO); if Assigned(AField) then if (not VarIsNull(AField.AsVariant)) then Decremento := AField.AsFloat; ImporteNeto := CalcularImporteNeto(ImporteNeto, Incremento, Decremento, NumDecimales); if (not VarIsNull(FieldByName(CAMPO_DESCUENTO).AsVariant)) then Descuento := ImporteNeto * (FieldByName(CAMPO_DESCUENTO).AsFloat/100); if (not VarIsNull(FieldByName(CAMPO_IMPORTE_PORTE).AsVariant)) then ImportePorte := FieldByName(CAMPO_CANTIDAD).asFloat * FieldByName(CAMPO_IMPORTE_PORTE).AsFloat; ImporteTotal := (RoundCurrency((ImporteNeto - Descuento), NumDecimales) * FieldByName(CAMPO_CANTIDAD).asFloat) + ImportePorte; end; Result := ImporteTotal; end; procedure ValidarCamposLineaConcepto(DataTable: TDADataTable); var AField: TDAField; begin //Validamos la existencia de todos los campos necesarios AField := DataTable.FindField(CAMPO_DESCUENTO); if not Assigned(AField) then raise Exception.Create('Campo ' + CAMPO_DESCUENTO + ' no encontrado (validarCampos)'); AField := DataTable.FindField(CAMPO_IMPORTE_PORTE); if not Assigned(AField) then raise Exception.Create('Campo ' + CAMPO_IMPORTE_PORTE + ' no encontrado (validarCampos)'); end; procedure DesglosarPorte(ImportePorte: Currency; ADetalles: IDAStronglyTypedDataTable); var Unidades: Double; ImporteUnidad: Currency; ImporteSobrante: Currency; ABookmark : TBookmark; begin ImporteUnidad := 0; ImporteSobrante := 0; ABookmark := ADetalles.DataTable.GetBookMark; try ADetalles.DataTable.DisableControls; ADetalles.DataTable.DisableEventHandlers; ADetalles.DataTable.First; Unidades := 0; while not ADetalles.DataTable.eof do begin if (ADetalles.DataTable.FieldByName(CAMPO_ID_ARTICULOS).AsInteger > 0) then Unidades := Unidades + ADetalles.DataTable.FieldByName(CAMPO_CANTIDAD).AsFloat; ADetalles.DataTable.Next; end; if Unidades > 0 then begin ImporteUnidad := StrToCurr(FormatFloat('0000000000.00', (ImportePorte / Unidades))); ImporteSobrante := ((ImportePorte / Unidades) - ImporteUnidad) * Unidades; end; ADetalles.DataTable.First; while not ADetalles.DataTable.eof do begin if (ADetalles.DataTable.FieldByName(CAMPO_ID_ARTICULOS).AsInteger > 0) then begin ADetalles.DataTable.Edit; ADetalles.DataTable.FieldByName(CAMPO_IMPORTE_PORTE).AsCurrency := ImporteUnidad; ADetalles.DataTable.Post; end; ADetalles.DataTable.Next; end; ADetalles.DataTable.Edit; ADetalles.DataTable.FieldByName(CAMPO_IMPORTE_PORTE).AsCurrency := ImporteUnidad + ImporteSobrante; ADetalles.DataTable.Post; finally ADetalles.DataTable.EnableEventHandlers; ADetalles.DataTable.GotoBookmark(ABookmark); ADetalles.DataTable.FreeBookmark(ABookmark); ADetalles.DataTable.EnableControls; end; end; function DarTotalPorte(ADetalles: IDAStronglyTypedDataTable): Double; var ImporteTotal: Currency; AuxPosicionIni : Integer; begin AuxPosicionIni := ADetalles.DataTable.FieldByName(CAMPO_POSICION).AsInteger; ShowHourglassCursor; try ADetalles.DataTable.DisableControls; ADetalles.DataTable.DisableEventHandlers; ADetalles.DataTable.First; ImporteTotal := 0; while not ADetalles.DataTable.eof do begin if (ADetalles.DataTable.FieldByName(CAMPO_ID_ARTICULOS).AsInteger > 0) then ImporteTotal := ImporteTotal + (ADetalles.DataTable.FieldByName(CAMPO_CANTIDAD).AsFloat * ADetalles.DataTable.FieldByName(CAMPO_IMPORTE_PORTE).AsFloat); ADetalles.DataTable.Next; end; finally ADetalles.DataTable.Locate(CAMPO_POSICION, IntToStr(AuxPosicionIni), []); ADetalles.DataTable.EnableEventHandlers; ADetalles.DataTable.EnableControls; HideHourglassCursor; end; Result := ImporteTotal; end; end.