unit uBizFacturasCliente; interface uses uDAInterfaces, uDADataTable, Classes, uBizContacto, DB, uBizImportesDetalleBase, uBizImportesCabeceraBase, uDBSelectionList, uExceptions, uBizInformesBase, schFacturasClienteClient_Intf; const BIZ_FACTURASCLIENTE = 'Client.FacturasCliente'; BIZ_DETALLESFACTURASCLIENTE = 'Client.DetallesFacturasCliente'; SITUACION_PENDIENTE = 'N'; SITUACION_PAGADO = 'S'; CTE_NORMAL = 'N'; CTE_ABONO = 'A'; CTE_PROFORMA = 'P'; CTE_IVA1 = 16; CTE_IVA2 = 1.16; type IBizDetallesFacturasCliente = interface(IDetallesFacturasCliente) ['{A628B3DE-2EF0-4A6E-AAFD-8BE582BDEE9A}'] procedure CopyFrom(ADetallesFacturas : IBizDetallesFacturasCliente); procedure cambiarSigno; end; IBizFacturasCliente = interface(IFacturasCliente) ['{CE8B2685-0FA5-404C-B8FA-90618A815BFF}'] function GetDetalles: IBizDetallesFacturasCliente; procedure SetDetalles(Value: IBizDetallesFacturasCliente); property Detalles: IBizDetallesFacturasCliente read GetDetalles write SetDetalles; function GetCliente: IBizContacto; procedure SetCliente(Value: IBizContacto); property Cliente: IBizContacto read GetCliente write SetCliente; procedure Show; procedure setReferencia(const ClaseFactura: String); procedure CopyFrom(AFacturaCliente : IBizFacturasCliente; ShowMensaje: Boolean = True); procedure cambiarSigno; end; TBizDetallesFacturasCliente = class(TDetallesFacturasClienteDataTableRules, IBizDetallesFacturasCliente, IBizImportesDetalle, IBizPuntosDetalle, IBizVisibleDetalle, IParche) // PARCHE *********************** private FIsAppend : Boolean; FPosicionNueva : Integer; FPuedoLanzarEvento : Boolean; // PARCHE *********************** protected procedure SetCANTIDADValue(const aValue: Integer); override; procedure SetIMPORTEUNIDADValue(const aValue: Currency); override; procedure SetIMPORTETOTALValue(const aValue: Currency); override; procedure OnNewRecord(Sender: TDADataTable); override; procedure BeforeInsert(Sender: TDADataTable); override; procedure AfterPost(Sender: TDADataTable); override; procedure AfterInsert(Sender: TDADataTable); override; procedure AfterDelete(Sender: TDADataTable); override; procedure BeforeDelete(Sender: TDADataTable); override; // PARCHE *********************** procedure ActivarEventos; procedure DesactivarEventos; procedure Refrescar; function PuedoLanzarEvento : Boolean; public procedure RecalcularImporte; function DarSumaTotalImportes : Currency; constructor Create(aDataTable: TDADataTable); override; procedure CopyFrom(ADetallesFacturas : IBizDetallesFacturasCliente); procedure CambiarSigno; end; TBizFacturasCliente = class(TFacturasClienteDataTableRules, IBizFacturasCliente, IBizImportesCabecera, ISelectedRowList, IApplyUpdateFailedException, IBizInformesAware) private FCliente : IBizContacto; FDetalles: IBizDetallesFacturasCliente; FDetallesLink: TDADataSource; FSelectedRows : TSelectedRowList; protected procedure ShowApplyUpdateFailed (const Error: EDAApplyUpdateFailed); function GetDetalles: IBizDetallesFacturasCliente; procedure SetDetalles(Value: IBizDetallesFacturasCliente); function GetCliente: IBizContacto; procedure SetCliente(Value: IBizContacto); procedure OnNewRecord(Sender: TDADataTable); override; function GetSelectedRows : TSelectedRowList; procedure BeforeDelete(Sender: TDADataTable); override; procedure AfterDelete(Sender: TDADataTable); override; procedure OnPostError(DataTable: TDADataTable; Error: EDatabaseError; var Action: TDataAction); override; procedure BeforeApplyUpdates(Sender : TDADataTable; const Delta : IDADelta); public procedure RecalcularImporte; property Cliente: IBizContacto read GetCliente write SetCliente; property Detalles: IBizDetallesFacturasCliente read GetDetalles write SetDetalles; constructor Create(aDataTable: TDADataTable); override; destructor Destroy; override; procedure Show; virtual; procedure Preview; procedure Print; property SelectedRows : TSelectedRowList read GetSelectedRows; procedure CopyFrom(AFacturaCliente : IBizFacturasCliente; ShowMensaje: Boolean = True); procedure cambiarSigno; procedure setReferencia(const ClaseFactura: String); end; procedure ValidarFacturaCliente (const AFacturaCliente : IBizFacturasCliente); implementation uses Windows, Dialogs, uDACDSDataTable, SysUtils, uEditorUtils, Variants, Math, uDataModuleContactos, Controls, Forms, LiteralesFacturasCliente, uDataModuleBase, uDataTableUtils, uDataModuleFacturasCliente, cxControls; var FMasterDeleting : Boolean; FCancelInsert : Boolean; procedure ValidarFacturaCliente (const AFacturaCliente : IBizFacturasCliente); begin if (FloatToStr(AFacturaCliente.FECHAFACTURA) = '0') then raise Exception.Create(msgLitFechaObligatorio); if not Assigned(AFacturaCliente.Cliente) or (AFacturaCliente.Cliente.DataTable.IsEmpty) then raise Exception.Create(msgLitClienteObligatorio); end; constructor TBizFacturasCliente.Create(aDataTable: TDADataTable); begin inherited; FCliente := NIL; FDetallesLink := TDADataSource.Create(NIL); FSelectedRows := TSelectedRowList.Create(aDataTable); aDataTable.OnBeforeApplyUpdates := BeforeApplyUpdates; end; destructor TBizFacturasCliente.Destroy; begin FCliente := NIL; FDetalles := NIL; FDetallesLink.Free; FSelectedRows.Free; inherited; end; function TBizFacturasCliente.GetCliente: IBizContacto; begin ShowHourglassCursor; try if not Assigned(FCliente) or ((CODIGOCONTACTO <> FCliente.Codigo) and not (FCliente.DataTable.State in dsEditModes)) then begin FCliente := dmContactos.GetContacto(CODIGOCONTACTO); if not FCliente.DataTable.Active then FCliente.DataTable.Active := True; if not FCliente.DataTable.IsEmpty then // Está vacío si la factura es nueva y no tiene cliente begin FCliente.Edit; FCliente.NOMBRE := NOMBRE; FCliente.NIFCIF := NIFCIF; FCliente.CALLE := CALLE; FCliente.CODIGOPOSTAL := CODIGOPOSTAL; FCliente.PROVINCIA := PROVINCIA; FCliente.POBLACION := POBLACION; FCliente.Post; end; end; Result := FCliente; finally HideHourglassCursor; end; end; function TBizFacturasCliente.GetDetalles: IBizDetallesFacturasCliente; begin Result := FDetalles; end; procedure TBizFacturasCliente.CopyFrom(AFacturaCliente : IBizFacturasCliente; ShowMensaje: Boolean = True); begin if not (State in dsEditModes) then Edit; ShowHourglassCursor; Application.ProcessMessages; try CODIGO := dmFacturasCliente.GetNextAutoinc; FECHAALTA := Date; USUARIO := 'eeee'; //dmUsuarios.LoginInfo.UserID; CLASEFACTURA := AFacturaCliente.CLASEFACTURA; if (CLASEFACTURA = CTE_NORMAL) or (CLASEFACTURA = CTE_ABONO) then setReferencia(CTE_NORMAL) else setReferencia(CTE_PROFORMA); // REFERENCIA := AFacturaCliente.REFERENCIA; FECHAFACTURA := AFacturaCliente.FECHAFACTURA; PAGADA := AFacturaCliente.PAGADA; BASEIMPONIBLE := AFacturaCliente.BASEIMPONIBLE; IVA := AFacturaCliente.IVA; OBSERVACIONES := AFacturaCliente.OBSERVACIONES; FORMAPAGO := AFacturaCliente.FORMAPAGO; CODIGOCONTACTO := AFacturaCliente.CODIGOCONTACTO; Cliente := AFacturaCliente.Cliente; if not (AFacturaCliente.DataTable.FieldByName(fld_FacturasClienteCODIGOOBRA).AsVariant = null) then CODIGOOBRA := AFacturaCliente.CODIGOOBRA; if not (AFacturaCliente.DataTable.FieldByName(fld_FacturasClienteFECHAVENCIMIENTO).AsVariant = null) then FECHAVENCIMIENTO := AFacturaCliente.FECHAVENCIMIENTO; Detalles.CopyFrom(AFacturaCliente.Detalles); RecalcularImporte; Post; if ShowMensaje then MessageBox(0, 'Se ha duplicado correctamente la factura elegida.', 'Factura duplicada', MB_ICONWARNING or MB_OK); finally HideHourglassCursor; end; end; procedure TBizFacturasCliente.OnNewRecord(Sender: TDADataTable); begin inherited; USUARIO := dmBase.Usuario; FECHAALTA := dmBase.Fecha; FECHAFACTURA := dmBase.Fecha; CODIGO := dmFacturasCliente.GetNextAutoinc; IVA := CTE_IVA1; end; procedure TBizFacturasCliente.Preview; begin dmFacturasCliente.Preview(Self.CODIGO); end; procedure TBizFacturasCliente.SetCliente(Value: IBizContacto); var bEnEdicion : Boolean; begin ShowHourglassCursor; try bEnEdicion := (DataTable.State in dsEditModes); if not bEnEdicion then Edit; FCliente := Value; if Assigned(FCliente) then begin CODIGOCONTACTO := FCliente.CODIGO; NOMBRE := FCliente.NOMBRE; NIFCIF := FCliente.NIFCIF; CALLE := FCliente.CALLE; CODIGOPOSTAL := FCliente.CODIGOPOSTAL; PROVINCIA := FCliente.PROVINCIA; POBLACION := FCliente.POBLACION; if not bEnEdicion then Post; end finally HideHourglassCursor; end; end; procedure TBizFacturasCliente.SetDetalles(Value: IBizDetallesFacturasCliente); begin FDetalles := Value; FDetallesLink.DataTable := Self.DataTable; FDetalles.DataTable.MasterSource := FDetallesLink; end; procedure TBizFacturasCliente.Show; begin ShowEditor(IBizFacturasCliente, Self, etItem); end; procedure TBizDetallesFacturasCliente.ActivarEventos; begin FPuedoLanzarEvento := True; end; procedure TBizDetallesFacturasCliente.AfterDelete(Sender: TDADataTable); var ACabecera : IBizImportesCabecera; begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if (not FMasterDeleting) and (not FCancelInsert) then begin ReasignarPosiciones(Self.DataTable); if Assigned(DataTable.MasterSource) and Supports(DataTable.MasterSource.DataTable, IBizImportesCabecera, ACabecera) then ACabecera.RecalcularImporte; end; FCancelInsert := False; end; procedure TBizDetallesFacturasCliente.AfterInsert(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; FIsAppend := DataTable.EOF; Post; Edit; // Para volver a dejarlo en modo de edición end; procedure TBizDetallesFacturasCliente.AfterPost(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if POSICION < 0 then AsignarPosicion(Self.DataTable, FIsAppend); if NUMCONCEPTO < 0 then AsignarNumConcepto(Self.DataTable); FIsAppend := False; end; procedure TBizDetallesFacturasCliente.BeforeDelete(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if (DataTable.State in dsEditModes) then DataTable.Cancel; if not FMasterDeleting then FCancelInsert := not (DataTable.MasterSource.DataTable.FieldByName('CODIGO').AsInteger = CODIGOFACTURA); end; procedure TBizDetallesFacturasCliente.BeforeInsert(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; if Assigned(DataTable.MasterSource) and (DataTable.MasterSource.DataTable.State in dsEditModes) then DataTable.MasterSource.DataTable.Post; if GetRecordCount = 0 then FPosicionNueva := -1 else FPosicionNueva := POSICION * (-1); end; procedure TBizDetallesFacturasCliente.CambiarSigno; begin ShowHourglassCursor; try DataTable.First; while not DataTable.EOF do begin // DataTable.DisableEventHandlers; if not (DataTable.State in dsEditModes) then DataTable.Edit; if not DataTable.FieldByName(fld_DetallesFacturasClienteIMPORTEUNIDAD).IsNull then IMPORTEUNIDAD := (-1)* IMPORTEUNIDAD; // if not ADetallesPedido.DataTable.FieldByName(fld_DetallesPedidosProveedorIMPORTETOTAL).IsNull then // IMPORTETOTAL := ADetallesPedido.IMPORTETOTAL; // DataTable.EnableEventHandlers; // DataTable.Post; DataTable.Next; end; finally HideHourglassCursor; end; end; procedure TBizDetallesFacturasCliente.CopyFrom(ADetallesFacturas : IBizDetallesFacturasCliente); begin ShowHourglassCursor; try ADetallesFacturas.First; while not ADetallesFacturas.EOF do begin Append; DataTable.DisableControls; DataTable.DisableEventHandlers; try TIPO := ADetallesFacturas.TIPO; DESCRIPCION := ADetallesFacturas.DESCRIPCION; CANTIDAD := ADetallesFacturas.CANTIDAD; IMPORTEUNIDAD := ADetallesFacturas.IMPORTEUNIDAD; IMPORTETOTAL := ADetallesFacturas.IMPORTETOTAL; POSICION := ADetallesFacturas.POSICION; finally DataTable.EnableControls; DataTable.EnableEventHandlers; end; Post; ADetallesFacturas.Next; end; finally HideHourglassCursor; end; end; constructor TBizDetallesFacturasCliente.Create(aDataTable: TDADataTable); begin inherited; FPosicionNueva := 1; // Los conceptos empiezan a contar en 1 // PARCHE ******************* FPuedoLanzarEvento := True; end; function TBizDetallesFacturasCliente.DarSumaTotalImportes: Currency; begin Result := DarTotalDetalles(Self.DataTable, True, False); end; procedure TBizDetallesFacturasCliente.DesactivarEventos; begin FPuedoLanzarEvento := False; end; procedure TBizDetallesFacturasCliente.OnNewRecord(Sender: TDADataTable); begin inherited; // PARCHE ******************* if not PuedoLanzarEvento then Exit; POSICION := FPosicionNueva; NUMCONCEPTO := -1; TIPO := TIPODETALLE_CONCEPTO; Self.DataTable.DisableEventHandlers; try CANTIDAD := 1; finally Self.DataTable.EnableEventHandlers; end; end; function TBizFacturasCliente.GetSelectedRows: TSelectedRowList; begin Result := FSelectedRows; end; procedure TBizFacturasCliente.ShowApplyUpdateFailed(const Error: EDAApplyUpdateFailed); begin if (Pos(AUF_FKVIOLATION, Error.Message) > 0) then MessageBox(0, PChar(msgLitErrorBorrar), 'Atención', MB_ICONWARNING or MB_OK); end; procedure TBizFacturasCliente.BeforeDelete(Sender: TDADataTable); begin inherited; FMasterDeleting := True; // Para que los detalles de borren de golpe y no recalcule posiciones ni totales end; procedure TBizFacturasCliente.AfterDelete(Sender: TDADataTable); begin inherited; FMasterDeleting := False; end; procedure TBizFacturasCliente.Print; begin dmFacturasCliente.Print(Self.CODIGO); end; procedure TBizFacturasCliente.OnPostError(DataTable: TDADataTable; Error: EDatabaseError; var Action: TDataAction); begin inherited; Action := daAbort; if (Pos('Nombre', Error.Message) > 0) then MessageBox(0, PChar(msgLitClienteObligatorio), 'Atención', MB_ICONWARNING or MB_OK) else if (Pos('Fecha', Error.Message) > 0) then MessageBox(0, PChar(msgLitFechaObligatorio), 'Atención', MB_ICONWARNING or MB_OK) else raise Error; end; procedure TBizFacturasCliente.BeforeApplyUpdates(Sender: TDADataTable; const Delta: IDADelta); var i : integer; begin for i := 0 to Delta.Count - 1 do case Delta.Changes[i].ChangeType of ctInsert, ctUpdate : ValidarFacturaCliente(Self); //ctDelete : end; end; function TBizDetallesFacturasCliente.PuedoLanzarEvento: Boolean; begin Result := FPuedoLanzarEvento; end; procedure TBizDetallesFacturasCliente.RecalcularImporte; begin RecalcularImporteDetalle(Self.DataTable, True, False); end; procedure TBizFacturasCliente.RecalcularImporte; begin RecalcularImportesCabecera(Self.DataTable, Detalles.DataTable); end; procedure TBizDetallesFacturasCliente.Refrescar; begin DataTable.Refresh; end; procedure TBizDetallesFacturasCliente.SetCANTIDADValue(const aValue: Integer); begin if aValue = 0 then DataTable.Fields[idx_DetallesFacturasClienteCANTIDAD].AsVariant := Null else inherited; end; procedure TBizDetallesFacturasCliente.SetIMPORTETOTALValue(const aValue: Currency); begin if aValue = 0 then DataTable.Fields[idx_DetallesFacturasClienteIMPORTETOTAL].AsVariant := Null else inherited; end; procedure TBizDetallesFacturasCliente.SetIMPORTEUNIDADValue(const aValue: Currency); begin if aValue = 0 then DataTable.Fields[idx_DetallesFacturasClienteIMPORTEUNIDAD].AsVariant := Null else inherited; end; procedure TBizFacturasCliente.setReferencia(const ClaseFactura: String); begin if not (Self.DataTable.State in dsEditModes) then Self.DataTable.Edit; if ClaseFactura = CTE_PROFORMA then Self.REFERENCIA := dmFacturasCliente.DarNuevaReferencia(CTE_PROFORMA) else Self.REFERENCIA := dmFacturasCliente.DarNuevaReferencia(CTE_NORMAL); end; { TBizClaseFacturaFieldRules } procedure TBizFacturasCliente.CambiarSigno; begin if not (State in dsEditModes) then Edit; ShowHourglassCursor; Application.ProcessMessages; try Detalles.CambiarSigno; RecalcularImporte; finally HideHourglassCursor; end; end; {procedure TBizFacturasCliente.SetCLASEFACTURAValue(const aValue: String); begin showmessage('Antiguo valor' + CLASEFACTURA); showmessage('Nuevo valor' + aValue); inherited; end;} { TBizFacturasObra } {procedure TBizFacturasObra.Show; begin inherited; ShowEditor(IBizFacturasObra, Self, etItem); end;} initialization FMasterDeleting := False; RegisterDataTableRules(BIZ_DETALLESFACTURASCLIENTE, TBizDetallesFacturasCliente); RegisterDataTableRules(BIZ_FACTURASCLIENTE, TBizFacturasCliente); // RegisterDataTableRules(BIZ_FACTURASOBRA, TBizFacturasObra); finalization end.