unit uEditorFacturaCliente; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, uEditorDBItem, DB, uDADataTable, JvAppStorage, JvAppRegistryStorage, JvComponent, JvFormPlacement, ImgList, PngImageList, StdActns, ActnList, ComCtrls, TBX, TB2Item, TB2Dock, TB2Toolbar, ExtCtrls, JvExControls, JvNavigationPane, uViewFacturaCliente, uCustomView, uViewBase, uViewTotales, StdCtrls, pngimage, AppEvnts, JvComponentBase, uBizFacturasCliente, uBizTiposIVA, uIEditorFacturaCliente, uFacturasClienteController, uViewDetallesBase, uViewDetallesFacturaCliente, dxLayoutLookAndFeels, JvExComCtrls, JvStatusBar, uViewDetallesDTO, uViewDetallesArticulos, uTiposIVAController, uDAInterfaces, cxControls, cxContainer, cxEdit, cxTextEdit, cxDBEdit, Grids, DBGrids, cxCheckBox, uViewListaSubCuentas; type TfEditorFacturaCliente = class(TfEditorDBItem, IEditorFacturaCliente) frViewFacturaCliente1: TfrViewFacturaCliente; frViewTotales1: TfrViewTotales; frViewDetallesFacturaCliente1: TfrViewDetallesFacturaCliente; pagContabilidad: TTabSheet; frViewListaSubcuentas1: TfrViewListaSubcuentas; procedure FormShow(Sender: TObject); procedure frViewClienteFactura1edtlNombrePropertiesEditValueChanged(Sender: TObject); procedure dsDataTableDataChange(Sender: TObject; Field: TField); procedure CustomEditorClose(Sender: TObject; var Action: TCloseAction); procedure frViewClienteFacturaedtlNombrePropertiesChange(Sender: TObject); procedure pgPaginasChanging(Sender: TObject; var AllowChange: Boolean); procedure frViewTotales1edtDescuentoPropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); procedure frViewTotales1bTiposIVAClick(Sender: TObject); procedure frViewTotales1eIVAPropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); procedure frViewTotales1ePortePropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); procedure frViewTotales1ePorteEditing(Sender: TObject; var CanEdit: Boolean); procedure OnRecargoEquivalenciaPropertiesValidate(Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); procedure frViewDetallesFacturaCliente1actQuitarPreciosExecute( Sender: TObject); procedure frViewDetallesFacturaCliente1actQuitarPreciosUpdate( Sender: TObject); //Importante en este punto se deben de quitar los eventos que puedan afectar a la tabla una vez se cierre el editor. private procedure RecalcularPortePorUnidad; protected FController : IFacturasClienteController; FFactura: IBizFacturaCliente; FTiposIVAController : ITiposIVAController; FTiposIVA: IBizTipoIVA; FViewFactura: IViewFacturaCliente; function GetController : IFacturasClienteController; procedure SetController (const Value : IFacturasClienteController); function GetFactura: IBizFacturaCliente; procedure SetFactura(const Value: IBizFacturaCliente); function GetViewFactura: IViewFacturaCliente; procedure SetViewFactura(const Value: IViewFacturaCliente); property ViewFacturaCliente: IViewFacturaCliente read GetViewFactura write SetViewFactura; procedure OnClienteChanged(Sender: TObject); procedure GuardarInterno; override; procedure EliminarInterno; override; procedure ImprimirInterno; override; procedure PrevisualizarInterno; override; procedure PonerTitulos(const ATitulo: string = ''); override; function PuedoImprimir: Boolean; override; public destructor Destroy; override; property Controller : IFacturasClienteController read GetController write SetController; property Factura: IBizFacturaCliente read GetFactura write SetFactura; constructor Create(AOwner: TComponent); override; end; implementation {$R *.dfm} {$INCLUDE ..\..\..\FactuGES.inc} uses uBizContactos, uDataModuleUsuarios, uFactuGES_App, uSubCuentasController, uDetallesFacturaClienteController, uDialogUtils, uDataTableUtils, uViewClienteFactura, uBizDireccionesContacto, uClientesController; // uGenerarAlbaranesCliFacCliUtils; { TfEditorFacturaCliente } { **************************** TfEditorFacturaCliente **************************** } constructor TfEditorFacturaCliente.Create(AOwner: TComponent); begin inherited; pgPaginas.ActivePageIndex := 0; ViewFacturaCliente := frViewFacturaCliente1; FTiposIVAController := TTiposIVAController.Create; {$IFDEF CONTABILIDAD} frViewListaSubcuentas1.TipoSubCuenta := tVentas; {$ENDIF} end; procedure TfEditorFacturaCliente.CustomEditorClose(Sender: TObject; var Action: TCloseAction); begin inherited; dsDataTable.DataTable := NIL; frViewTotales1.DADataSource.DataTable := NIL; frViewTotales1.cbRecargoEquivalencia.Properties.OnValidate := nil; Factura := NIL; FTiposIVA := NIL; FTiposIVAController := Nil; FController := NIL; FViewFactura := NIL; end; destructor TfEditorFacturaCliente.Destroy; begin inherited; end; procedure TfEditorFacturaCliente.dsDataTableDataChange(Sender: TObject; Field: TField); begin inherited; if Assigned(FFactura) and (not (FFactura.DataTable.Fetching) or not (FFactura.DataTable.Opening) or not (FFactura.DataTable.Closing)) then PonerTitulos; end; procedure TfEditorFacturaCliente.EliminarInterno; var ACadena : String; begin if (Application.MessageBox('Atención, si elimina facturas/abonos de cliente podría producir huecos el la lista de facturas, ¿Desea continuar?', 'Atención', MB_YESNO) = IDYES) then begin if Factura.TIPO = CTE_TIPO_FACTURA then ACadena := '¿Desea borrar esta factura de cliente?' else ACadena := '¿Desea borrar este abono a cliente?'; if (Application.MessageBox(PChar(ACadena), 'Atención', MB_YESNO) = IDYES) then begin //Es el caso de querer borrar una factura pendiente cuyos recibos tienen devoluciones if not FController.Eliminar(Factura) then Application.MessageBox('La factura no ha podido ser eliminada porque tiene recibos con pagos o devoluciones emitidas.', 'Atención', MB_OK); inherited; end; end; end; procedure TfEditorFacturaCliente.FormShow(Sender: TObject); begin inherited; if not Assigned(FViewFactura) then raise Exception.Create('No hay ninguna vista asignada'); if not Assigned(Factura) then raise Exception.Create('No hay ninguna factura asignada'); frViewTotales1.cbRecargoEquivalencia.Properties.OnValidate := OnRecargoEquivalenciaPropertiesValidate; Factura.DataTable.Active := True; end; procedure TfEditorFacturaCliente.frViewClienteFactura1edtlNombrePropertiesEditValueChanged(Sender: TObject); begin inherited; with (Sender as TcxDBTextEdit) do Enabled := (FFactura.ID <> 0) end; procedure TfEditorFacturaCliente.frViewClienteFacturaedtlNombrePropertiesChange( Sender: TObject); begin inherited; PonerTitulos; end; procedure TfEditorFacturaCliente.frViewDetallesFacturaCliente1actQuitarPreciosExecute( Sender: TObject); begin inherited; FController.DetallesController.QuitarPrecioDetalles(FFactura.Detalles); end; procedure TfEditorFacturaCliente.frViewDetallesFacturaCliente1actQuitarPreciosUpdate( Sender: TObject); begin if not Assigned(frViewDetallesFacturaCliente1.DADataSource.DataTable) then (Sender as TAction).Enabled := False else (Sender as TAction).Enabled := (not ReadOnly) and (not frViewDetallesFacturaCliente1.DADataSource.DataTable.IsEmpty) end; procedure TfEditorFacturaCliente.frViewTotales1bTiposIVAClick(Sender: TObject); begin inherited; FTiposIVAController.VerTodos(FTiposIVA); end; procedure TfEditorFacturaCliente.OnRecargoEquivalenciaPropertiesValidate( Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); begin inherited; if frViewTotales1.cbRecargoEquivalencia.Checked then Factura.RECARGO_EQUIVALENCIA := 1 else Factura.RECARGO_EQUIVALENCIA := 0; end; procedure TfEditorFacturaCliente.frViewTotales1edtDescuentoPropertiesValidate( Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); begin inherited; Factura.DESCUENTO := DisplayValue; end; procedure TfEditorFacturaCliente.frViewTotales1eIVAPropertiesValidate( Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); begin inherited; Factura.Edit; Factura.ID_TIPO_IVA := FTiposIVA.ID; // ((frViewTotales1.dsTiposIVA.DataTable) as IBizTipoIVA).ID; end; procedure TfEditorFacturaCliente.frViewTotales1ePorteEditing(Sender: TObject; var CanEdit: Boolean); begin inherited; if FFactura.TIPO = CTE_TIPO_ABONO then CanEdit := False; end; procedure TfEditorFacturaCliente.frViewTotales1ePortePropertiesValidate( Sender: TObject; var DisplayValue: Variant; var ErrorText: TCaption; var Error: Boolean); begin inherited; if not VarIsNull(DisplayValue) and (Length(DisplayValue) > 0) then FFactura.IMPORTE_PORTE := DisplayValue else FFactura.IMPORTE_PORTE := 0; // RecalcularPortePorUnidad; No se desglosa el importe del porte por articulo end; function TfEditorFacturaCliente.GetController: IFacturasClienteController; begin Result := FController; end; function TfEditorFacturaCliente.GetFactura: IBizFacturaCliente; begin Result := FFactura; end; function TfEditorFacturaCliente.GetViewFactura: IViewFacturaCliente; begin Result := FViewFactura; end; procedure TfEditorFacturaCliente.GuardarInterno; var bEsNuevo : Boolean; begin inherited; ShowHourglassCursor; //frViewDetallesFacturaCliente1.SaveGridStatus; // Para guardar estado del grid frViewDetallesFacturaCliente1.BeginUpdate; // Para que no se mueva el foco try bEsNuevo := FFactura.EsNuevo; {$IFDEF CONTABILIDAD} FFactura.Edit; FFactura.ID_SUBCUENTA := frViewListaSubCuentas1.IdSubCuenta; FController.SetIgnorarContabilidad(FFactura, frViewListaSubCuentas1.eContabilizar.EditValue); {$ENDIF} FController.Guardar(FFactura); finally frViewDetallesFacturaCliente1.EndUpdate; //frViewDetallesFacturaCliente1.RestoreGridStatus; HideHourglassCursor; end; if bEsNuevo then begin if FFactura.TIPO = CTE_TIPO_FACTURA then ShowInfoMessage('La factura se ha dado de alta con el código ' + FFactura.REFERENCIA) else begin ShowInfoMessage('El abono se ha dado de alta con el código ' + FFactura.REFERENCIA); //Preguntamos is desea hacer una orden de devolución asociada // if (Application.MessageBox('¿Desea crear una orden de devolución para el abono?', 'Atención', MB_YESNO) = IDYES) then // GenerarAlbaranCli(FFactura); end; end; Modified := False; end; procedure TfEditorFacturaCliente.ImprimirInterno; var AVerLogotipo: Boolean; begin inherited; AVerLogotipo:= False; if(AppFactuGES.EmpresaActiva.IVA > 0) then AVerLogotipo := (Application.MessageBox('¿Desea imprimir el documento con logotipo?', 'Atención', MB_YESNO) = IDYES); FController.Print(FFactura, False, aVerLogotipo); end; procedure TfEditorFacturaCliente.OnClienteChanged(Sender: TObject); var // FDetallesController : IDetallesFacturaClienteController; AClientesController : IClientesController; ADireccion : IBizDireccionesContacto; APrimerCliente : Boolean; begin FFactura.Cliente := frViewFacturaCliente1.frViewClienteFactura1.Cliente; Controller.DetallesController.PrecioPunto := FFactura.Cliente.PRECIO_PUNTO; if not (FFactura.DataTable.State in dsEditModes) then FFactura.DataTable.Edit; //En el caso de Acana no se cambia para que el IVA y la FORMA DE PAGO por defecto sea el de la empresa. // Actualizar IVA y RE a partir del tipo de IVA del cliente. { Factura.IVA := FTiposIVA.IVA; //((frViewTotales1.dsTiposIVA.DataTable) as IBizTipoIVA).IVA; if FFactura.Cliente.RECARGO_EQUIVALENCIA = 1 then Factura.RE := FTiposIVA.RE else Factura.RE := 0; } // En el caso de tener direcciones asociadas, se debe dar la posibilidad de elegir la dirección principal o las secundarias para la factura AClientesController := TClientesController.Create; try case FFactura.Cliente.Direcciones.RecordCount of 0 : //No hay direcciones secundarias asociadas else ADireccion := AClientesController.ElegirDireccion(FFactura.Cliente, 'Seleccione la dirección del cliente que quiere utilizar como dirección fiscal de esta factura.'); end; // Si hay dirección de envio, copiarla a la factura y poner el coste del porte if Assigned(ADireccion) then begin if not ADireccion.IDIsNull then try FFactura.Edit; FFactura.IMPORTE_PORTE := ADireccion.PORTE; FController.CopiarDireccion(ADireccion, FFactura); finally ADireccion := NIL; end; end finally AClientesController := Nil; end; if Assigned(FFactura) then begin APrimerCliente := (FFactura.Cliente.ID = 0); if (ShowConfirmMessage('Cambio forma de pago y tipo de IVA', '¿Desea actualizar la forma de pago y el tipo de IVA a la asignada en la ficha del cliente seleccionado?') = IDYES) then FController.ActualizarFormaDePago(FFactura, FFactura.Cliente.ID_FORMA_PAGO); if (not APrimerCliente) and (FFactura.Detalles.RecordCount > 0) then begin if (ShowConfirmMessage('Actualizar los descuentos de las líneas', '¿Desea actualizar las líneas de detalle con el descuento del cliente?' + #10#13 + 'Sólo se cambiarán las líneas que tengan cantidades.') = IDYES) then begin FController.DetallesController.ActualizarDetalles(FFactura.Detalles, FFactura.Cliente); ShowInfoMessage('Se han actualizado las líneas con el descuento del cliente seleccionado'); end; end; end; end; procedure TfEditorFacturaCliente.pgPaginasChanging(Sender: TObject; var AllowChange: Boolean); var ACadena : String; begin inherited; if (not Assigned(FFactura)) or (FFactura.ID_CLIENTE = ID_NULO) then begin if FFactura.TIPO = CTE_TIPO_FACTURA then ACadena := 'Antes debe elegir un cliente para esta factura' else ACadena := 'Antes debe elegir un cliente para este abono'; ShowWarningMessage(ACadena); AllowChange := False; end; end; procedure TfEditorFacturaCliente.PonerTitulos(const ATitulo: string); var FTitulo : String; begin FTitulo := ATitulo; if (FTitulo = '') and Assigned(Factura) then begin if Factura.EsNuevo then if Factura.TIPO = CTE_TIPO_FACTURA then FTitulo := 'Nueva factura de cliente' else FTitulo := 'Nuevo abono a cliente' else if Factura.TIPO = CTE_TIPO_FACTURA then FTitulo := 'Factura de cliente' + ' - ' + FFactura.Cliente.Nombre else FTitulo := 'Abono a cliente' + ' - ' + FFactura.Cliente.Nombre end; inherited PonerTitulos(FTitulo); Self.Caption := FTitulo + ' (' + AppFactuGES.EmpresaActiva.NOMBRE + ')'; end; function TfEditorFacturaCliente.PuedoImprimir: Boolean; begin Result := inherited PuedoImprimir and (not Factura.Cliente.IDIsNull); end; procedure TfEditorFacturaCliente.PrevisualizarInterno; var AVerLogotipo: Boolean; begin inherited; AVerLogotipo:= False; if(AppFactuGES.EmpresaActiva.IVA > 0) then AVerLogotipo := (Application.MessageBox('¿Desea previsualizar el documento con logotipo?', 'Atención', MB_YESNO) = IDYES); FController.Preview(FFactura, False, AVerLogotipo); end; procedure TfEditorFacturaCliente.RecalcularPortePorUnidad; begin //Esta lógica se llamará en el editor porque es para facilitar el rellenado de información del documento //no puede ir en la clase de negocio porque no es una lógica que tenga sentido fuera del editor. if Assigned(Controller) and Assigned(Controller.DetallesController) then Controller.DetallesController.DesglosarPorteDetalles(FFactura.IMPORTE_PORTE, FFactura.Detalles) end; procedure TfEditorFacturaCliente.SetController(const Value: IFacturasClienteController); begin FController := Value; if Assigned(FController) then begin ViewFacturaCliente.Controller := FController; frViewDetallesFacturaCliente1.Controller := Controller.DetallesController; end; end; procedure TfEditorFacturaCliente.SetFactura(const Value: IBizFacturaCliente); begin FFactura := Value; if Assigned(FFactura) then begin dsDataTable.DataTable := FFactura.DataTable; frViewTotales1.DADataSource.DataTable := FFactura.DataTable; FTiposIVA := FTiposIVAController.BuscarTodos; frViewTotales1.dsTiposIVA.DataTable := FTiposIVA.DataTable; FTiposIVA.DataTable.Active := True; if Assigned(FViewFactura) then begin frViewFacturaCliente1.frViewClienteFactura1.Cliente := FFactura.Cliente; frViewFacturaCliente1.frViewClienteFactura1.OnClienteChanged := OnClienteChanged; FViewFactura.Factura := FFactura; frViewDetallesFacturaCliente1.Detalles := FFactura.Detalles; frViewDetallesFacturaCliente1.Factura := FFactura; //Para poder sacar los descuento del articulos segun el cliente seleccionado Controller.DetallesController.PrecioPunto := FFactura.Cliente.PRECIO_PUNTO; end; {$IFDEF CONTABILIDAD} frViewListaSubCuentas1.eContabilizar.EditValue := FFactura.IGNORAR_CONTABILIDAD; frViewListaSubCuentas1.ElegirSubCuenta(FFactura.ID_SUBCUENTA); {$ENDIF} end else begin frViewFacturaCliente1.frViewClienteFactura1.OnClienteChanged := NIL; frViewFacturaCliente1.frViewClienteFactura1.Cliente := NIL; dsDataTable.DataTable := NIL; frViewTotales1.DADataSource.DataTable := NIL; frViewTotales1.dsTiposIVA.DataTable := NIL; end end; procedure TfEditorFacturaCliente.SetViewFactura(const Value: IViewFacturaCliente); begin FViewFactura := Value; if Assigned(FViewFactura) and Assigned(Factura) then FViewFactura.Factura := Factura; end; end.