unit uDetallesFacturaProveedorController; interface uses Classes, uDADataTable, uControllerDetallesArticulos, uBizDetallesFacturaProveedor, uIDataModuleFacturasProveedor, uBizContactos, uBizArticulos; const CAMPO_REFERENCIA_FABRICANTE = 'REFERENCIA_FABRICANTE'; type IDetallesFacturaProveedorController = interface(IControllerDetallesArticulos) ['{49F6199E-E031-42F5-AEA5-E70C3E3479A1}'] procedure AnadirArticulos(ADetalles: IDAStronglyTypedDataTable; AProveedor: IBizProveedor; const ANuevaFila :Boolean = True; const ACantidad: Integer = 1); overload; procedure ActualizarDetalles(ADetalles: IDAStronglyTypedDataTable; AProveedor: IBizProveedor); procedure AnadirDetalleFacturaAsociadaAbono(ADetalles: IBizDetallesFacturaProveedor; AReferencia: String; AFecha: String); procedure DesglosarPorteDetalles(ImportePorte: Currency; ADetalles: IDAStronglyTypedDataTable); function DarTotalPorteTotal(ADetalles: IDAStronglyTypedDataTable): Double; function CalcularTotalesIVA(DataTable: TDADataTable): TImporteIVADetallesArray; function CalcularSumaIVA(ListaIVAs: TImporteIVADetallesArray): Double; end; TDetallesFacturaProveedorController = class(TControllerDetallesArticulos, IDetallesFacturaProveedorController) private FDataModule : IDataModuleFacturasProveedor; protected procedure RellenarOtros(ADetalles: IDAStronglyTypedDataTable; AArticulos: IBizArticulo); overload; override; procedure RellenarImportes(ADetalles: IDAStronglyTypedDataTable; AArticulos: IBizArticulo); override; procedure AsignarController; override; //Si sobreescribimos este método podremos tener en cuenta otras columnas para el calculo del importe total de un concepto function CalcularImporteTotalConcepto(DataTable: TDADataTable): Double; override; procedure ValidarCampos(DataTable: TDADataTable); override; procedure DesglosarPorteDetalles(ImportePorte: Currency; ADetalles: IDAStronglyTypedDataTable); function DarTotalPorteTotal(ADetalles: IDAStronglyTypedDataTable): Double; function CalcularTotalesIVA(DataTable: TDADataTable): TImporteIVADetallesArray; function CalcularSumaIVA(ListaIVAs: TImporteIVADetallesArray): Double; public function DarListaTiposDetalle: TStringList; override; procedure AnadirArticulos(ADetalles: IDAStronglyTypedDataTable; AProveedor: IBizProveedor; const ANuevaFila :Boolean = True; const ACantidad: Integer = 1); overload; procedure ActualizarDetalles(ADetalles: IDAStronglyTypedDataTable; AProveedor: IBizProveedor); overload; procedure AnadirDetalleFacturaAsociadaAbono(ADetalles: IBizDetallesFacturaProveedor; AReferencia: String; AFecha: String); constructor Create; override; destructor Destroy; override; end; implementation { TDetallesFacturaProveedorController } uses DB, uDAInterfaces, Variants, uDataModuleFacturasProveedor, uArticulosFacturaProveedorController, uControllerDetallesBase, Dialogs, SysUtils, uDialogUtils, uCalculosUtils, schArticulosClient_Intf, schFacturasProveedorClient_Intf, uDataModuleTiposIVA; function TDetallesFacturaProveedorController.CalcularTotalesIVA(DataTable: TDADataTable): TImporteIVADetallesArray; var ListaIVAs: TImporteIVADetallesArray; AuxPosicionIni : Integer; AIndex : Integer; bEncontrado : Boolean; begin if (DataTable.State in dsEditModes) then DataTable.Post; ValidarCampos(DataTable); DataTable.DisableControls; AuxPosicionIni := DataTable.FieldByName(CAMPO_POSICION).AsInteger; try DataTable.First; while not DataTable.EOF do begin bEncontrado := False; for AIndex := 0 to Length(ListaIVAs) - 1 do begin if ListaIVAs[AIndex].ID = DataTable.FieldByName('ID_TIPO_IVA').AsInteger then begin bEncontrado := True; ListaIVAs[AIndex].ImporteIVA := ListaIVAs[AIndex].ImporteIVA + DataTable.FieldByName('IMPORTE_IVA').AsFloat; Break; end; end; if not bEncontrado then begin if (DataTable.FieldByName('IMPORTE_IVA').AsFloat > 0) then begin AIndex := Length(ListaIVAs); SetLength(ListaIVAs, AIndex + 1); ListaIVAs[AIndex].ID := DataTable.FieldByName('ID_TIPO_IVA').AsInteger; ListaIVAs[AIndex].IVA := DataTable.FieldByName('IVA').AsFloat; ListaIVAs[AIndex].ImporteIVA := DataTable.FieldByName('IMPORTE_IVA').AsFloat; end; end; DataTable.Next; end; finally //Dejamos el puntero en la misma posición que la que partió DataTable.First; DataTable.Locate(CAMPO_POSICION, AuxPosicionIni, []); DataTable.EnableControls; end; Result := ListaIVAs; end; procedure TDetallesFacturaProveedorController.ActualizarDetalles(ADetalles: IDAStronglyTypedDataTable; AProveedor: IBizProveedor); var AArticulos : IBizArticulo; begin if Assigned(ADetalles) then begin try AArticulos := (FArticulosController.BuscarTodos(AProveedor) as IBizArticulo); ActualizarDetalles(ADetalles, AArticulos); EliminarArticulosProveedor(ADetalles); ShowInfoMessage('Se han eliminado todos los artículos que no pertenecen al nuevo proveedor seleccionado, y los que pertenecen sus descuentos han sido adaptados al proveedor seleccionado'); finally AArticulos := Nil; end; end; end; procedure TDetallesFacturaProveedorController.AnadirArticulos(ADetalles: IDAStronglyTypedDataTable; AProveedor: IBizProveedor; const ANuevaFila :Boolean; const ACantidad: Integer); var AArticulos: IBizArticulo; begin if Assigned(ADetalles) then begin try AArticulos := (FArticulosController.BuscarTodosPorProveedor as IBizArticulo); //Si nueva fila es false, quiere decir que se sustituye un determinado artículo, por ello la lista a seleccionar no debe ser multiselect if ANuevaFila then begin AArticulos := (FArticulosController as IArticulosFacturaProveedorController).ElegirArticulos(AArticulos, 'Elija los artículos que desea añadir a esta factura de Proveedor', True, AProveedor); Add(ADetalles, AArticulos, ACantidad) end else begin AArticulos := (FArticulosController as IArticulosFacturaProveedorController).ElegirArticulos(AArticulos, 'Elija el artículo que desea añadir a esta factura de Proveedor', False, AProveedor); RellenarDetalle(ADetalles, AArticulos, ACantidad); end; finally AArticulos := Nil; end; end; end; procedure TDetallesFacturaProveedorController.AnadirDetalleFacturaAsociadaAbono( ADetalles: IBizDetallesFacturaProveedor; AReferencia, AFecha: String); begin AnadirConceptoInicial(ADetalles, 'ABONO DE FACTURA ' + AReferencia + ' con fecha ' + AFecha); end; procedure TDetallesFacturaProveedorController.AsignarController; begin FArticulosController := TArticulosFacturaProveedorController.Create; end; function TDetallesFacturaProveedorController.CalcularImporteTotalConcepto(DataTable: TDADataTable): Double; var AResult : Double; begin AResult := CalcularLineaConcepto(DataTable); if not DataTable.Editing then DataTable.Edit; DataTable.FieldByName('IMPORTE_IVA').AsFloat := AResult * (DataTable.FieldByName('IVA').AsFloat/100); Result := AResult; // No se suma el IVA al total del detalle end; function TDetallesFacturaProveedorController.CalcularSumaIVA( ListaIVAs: TImporteIVADetallesArray): Double; var aSuma : Double; I : integer; begin aSuma := 0; for I := 0 to Length(ListaIVAs) - 1 do aSuma := aSuma + ListaIVAs[I].ImporteIVA; Result := aSuma; end; constructor TDetallesFacturaProveedorController.Create; begin inherited; FDataModule := TDataModuleFacturasProveedor.Create(Nil); end; function TDetallesFacturaProveedorController.DarListaTiposDetalle: TStringList; begin Result := TStringList.Create; Result.Values[TIPO_DETALLE_CONCEPTO] := TIPO_DETALLE_CONCEPTO; Result.Values[TIPO_DETALLE_TITULO] := TIPO_DETALLE_TITULO; // Result.Values[TIPO_DETALLE_TITULO_OPCIONAL] := TIPO_DETALLE_TITULO_OPCIONAL; Result.Values[TIPO_DETALLE_SUBTOTAL] := TIPO_DETALLE_SUBTOTAL; // Result.Values[TIPO_DETALLE_DESCUENTO] := TIPO_DETALLE_DESCUENTO; // Result.Values[TIPO_DETALLE_SALTO] := TIPO_DETALLE_SALTO; end; function TDetallesFacturaProveedorController.DarTotalPorteTotal(ADetalles: IDAStronglyTypedDataTable): Double; begin Result := DarTotalPorte(ADetalles); end; procedure TDetallesFacturaProveedorController.DesglosarPorteDetalles(ImportePorte: Currency; ADetalles: IDAStronglyTypedDataTable); begin DesglosarPorte(ImportePorte, ADetalles); ActualizarTotales(ADetalles); end; destructor TDetallesFacturaProveedorController.Destroy; begin FDataModule := Nil; inherited; end; procedure TDetallesFacturaProveedorController.RellenarOtros(ADetalles: IDAStronglyTypedDataTable; AArticulos: IBizArticulo); var AField: TDAField; begin if Assigned(AArticulos) then ADetalles.DataTable.FieldByName(CAMPO_DESCUENTO).AsFloat := AArticulos.DESCUENTO else ADetalles.DataTable.FieldByName(CAMPO_DESCUENTO).AsFloat := 0; //Sobreescribimos el id del articulo por el campo ID_ARTICULO que nos hemos tenido que crear para //almacenar el codigo de artículo ya que ID esta destinado a ID_ARTICULO||ID_PROVEEDOR, para identificar de forma //unica los articulos desglosados por proveedor. AField := AArticulos.DataTable.FindField(CAMPO_ID_ARTICULOS); if Assigned(AField) then ADetalles.DataTable.FieldByName(CAMPO_ID_ARTICULOS).AsVariant := AField.AsVariant; AField := AArticulos.DataTable.FindField(fld_ArticulosREFERENCIA_FABR); if Assigned(AField) then ADetalles.DataTable.FieldByName(fld_FacturasProveedor_DetallesREFERENCIA_FABRICANTE).AsVariant := AField.AsVariant; end; procedure TDetallesFacturaProveedorController.ValidarCampos(DataTable: TDADataTable); var AField: TDAField; begin inherited; ValidarCamposLineaConcepto(DataTable); //Validamos la existencia de todos los campos IVA AField := DataTable.FindField('ID_TIPO_IVA'); if not Assigned(AField) then raise Exception.Create('Campo ' + 'ID_TIPO_IVA' + ' no encontrado (validarCampos)'); AField := DataTable.FindField('IVA'); if not Assigned(AField) then raise Exception.Create('Campo ' + 'IVA' + ' no encontrado (validarCampos)'); AField := DataTable.FindField('IMPORTE_IVA'); if not Assigned(AField) then raise Exception.Create('Campo ' + 'IMPORTE_IVA' + ' no encontrado (validarCampos)'); end; procedure TDetallesFacturaProveedorController.RellenarImportes(ADetalles: IDAStronglyTypedDataTable; AArticulos: IBizArticulo); begin if Assigned(AArticulos) then begin ADetalles.DataTable.FieldByName(CAMPO_IMPORTE_UNIDAD).AsVariant := AArticulos.PRECIO_COSTE; ADetalles.DataTable.FieldByName(CAMPO_IMPORTE_PORTE).AsVariant := AArticulos.PRECIO_PORTE end else begin ADetalles.DataTable.FieldByName(CAMPO_IMPORTE_UNIDAD).AsVariant := Null; ADetalles.DataTable.FieldByName(CAMPO_IMPORTE_PORTE).AsVariant := Null end; end; end.