clsRetencion.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using sage.ew.cliente;
5 using sage.ew.docsven;
6 using sage.ew.db;
7 using sage.ew.functions;
8 using System.Data;
9 using System.Windows.Forms;
10 using sage.ew.interficies;
11 using sage.ew.articulo;
12 using sage.ew.global;
13 using System.Linq;
14 using System.ComponentModel;
15 using sage.ew.ewbase;
17 
18 namespace sage.ew.docsven
19 {
23  public enum TipoRetencionVentas
24  {
28  Fiscal,
32  NoFiscal
33  };
34 
38  public class Retencion : IDisposable
39  {
40  #region PROPIEDADES PÚBLICAS
41 
42 
46  [DefaultValue(false)]
47  public bool _SobreBase
48  {
49  get { return _lSobreBase; }
50  set { _lSobreBase = value; }
51  }
52  private bool _lSobreBase = false;
53 
54 
58  [DefaultValue(0.0)]
59  public decimal _ImporteRetencion
60  {
61  get { return _nImporteRetencion; }
62  set { _nImporteRetencion = value; }
63  }
64  private decimal _nImporteRetencion = 0.0M;
65 
66 
70  [DefaultValue(0.0)]
71  public decimal _RetencionPorcen
72  {
73  get { return _nRetencionPorcen; }
74  set { _nRetencionPorcen = value; }
75  }
76  private decimal _nRetencionPorcen = 0.0M;
77 
78 
82  [DefaultValue("")]
83  public string _RetencionTipo
84  {
85  get { return _cRetencionTipo; }
86  set { _cRetencionTipo = value; }
87  }
88  private string _cRetencionTipo = "";
89 
90 
94  [DefaultValue(TipoRetencionVentas.Fiscal)]
95  public TipoRetencionVentas _TipoRetFiscNoFisc
96  {
97  get { return _eTipoRetFiscNoFisc; }
98  set { _eTipoRetFiscNoFisc = value; }
99  }
100  private TipoRetencionVentas _eTipoRetFiscNoFisc = TipoRetencionVentas.Fiscal;
101 
102 
106  [DefaultValue(false)]
107  public bool _HayRetencion
108  {
109  get { return _lHayRetencion; }
110  set { _lHayRetencion = value; }
111  }
112  private bool _lHayRetencion = false;
113 
114 
115  #endregion PROPIEDADES PÚBLICAS
116 
117 
118  #region PROPIEDADES PRIVADAS
119 
120 
124  private dynamic _oDocRef = null;
125 
126 
130  private string _lcMonedaEmpresa = Convert.ToString(EW_GLOBAL._GetVariable("wc_moneda"));
131 
132 
136  private string _cAny = Convert.ToString(EW_GLOBAL._GetVariable("wc_any"));
137 
138 
142  private int _lnDecimales = Convert.ToInt32(EW_GLOBAL._GetVariable("wn_decimales"));
143 
144 
148  private bool _lPverde = Convert.ToBoolean(EW_GLOBAL._GetVariable("wl_pverde"));
149 
150 
154  private bool _lRecivainc = Convert.ToBoolean(EW_GLOBAL._GetVariable("wl_recivainc"));
155 
156 
160  private bool _lDivisa = Convert.ToBoolean(EW_GLOBAL._GetVariable("wl_divisaventa"));
161 
162 
166  private Dictionary<String, DataTable> _DicRetEmpCli = new Dictionary<String, DataTable>();
167 
168 
172  private Dictionary<String, DataTable> _DicRetSoporFact = new Dictionary<String, DataTable>();
173 
174 
178  private Dictionary<String, Dictionary<string,object>> _DicIvareperFact = new Dictionary<String, Dictionary<string, object>>();
179 
183  private bool disposedValue = false;
184 
185 
186  #endregion PROPIEDADES PRIVADAS
187 
188 
189  #region CONSTRUCTORES
190 
191 
195  public Retencion()
196  {
197  this._lSobreBase = false;
198  this._nImporteRetencion = 0.0M;
199  this._nRetencionPorcen = 0.0M;
200  this._cRetencionTipo = "";
201  this._eTipoRetFiscNoFisc = TipoRetencionVentas.Fiscal;
202  this._lHayRetencion = false;
203  }
204 
205 
206  #endregion CONSTRUCTORES
207 
208 
209  #region MÉTODOS PÚBLICOS
210 
211 
221  public decimal _Calcular_Retencion(dynamic toDocumento, Dictionary<string,object> toCondicionesRetencion = null)
222  {
223  decimal lnPrcReten = 0.0M, lnTotalBase = 0.0M, lnTotalDocumento = 0.0M, lnTotalPronto = 0.0M, lnImportePortes = 0.0M, lnImporteDivPortes = 0.0M, lnImportePortesIva = 0.0M, lnImporteDivPortesIva = 0.0M;
224  string lcEmpresa = "", lcDivisa = "", lcCliente = "", lcIva_Portes = "", lcTipoIva_Pverde = "";
225  bool llSobreBase = false, llRetNoFisc = false, llIncluirProntoPagoPortes = false, llRecEquivCliente = false;
226  int lnDecimalesMonedaDocu=0;
227 
228  this._oDocRef = toDocumento;
229 
230  Cliente loCliente;
231  DataTable ldtReter = new DataTable(), ldtRetMp = new DataTable();
232  ewMascara loMascaraPorcent = new ewbase.ewMascara(KeyDiccionarioMascara.wc_tpc);
233 
234  // Inicializamos propiedades internas
235  this._lHayRetencion = false;
236  this._lSobreBase = false;
237  this._nImporteRetencion = 0.0M;
238  this._cRetencionTipo = "";
239  this._nRetencionPorcen = 0.0M;
240  this._eTipoRetFiscNoFisc = TipoRetencionVentas.Fiscal;
241 
242  lcEmpresa = toDocumento._Empresa;
243  lcCliente = toDocumento._Cabecera._oCliente._Codigo;
244  lcDivisa = toDocumento._Cabecera._Divisa;
245 
246  // Total base imponible del documento
247  lnTotalBase = toDocumento._Pie._TotalBase;
248 
249  // Total pronto pago del documento
250  lnTotalPronto = toDocumento._Pie._TotalPP;
251 
252  // Total final
253  lnTotalDocumento = toDocumento._Pie._TotalDocumento - toDocumento._Pie._TotalRecFinan; // PE-76353. Restar importe del recargo financiero
254 
255  // Si la retencion es fiscal el calculo del total retencion se hace linea
256  // a linea recorriendo el documento pues pueden haber articulos que tengan
257  // retencion o no. Los suplidos ya no los tiene en cuenta en este cálculo
258  //
259  // Y si la retencion es no fiscal en el _TotalDOcumento, en el momento de llamar
260  // desde el _Calcular_Iva() a este metodo en el que estamos, aun no se han
261  // añadido al _TotalDocumento por que se hace al final de todo, por tanto,
262  // aqui no hay que restar los suplidos del total documento.
263 
264  // Si el documento tiene valor 0 no hace falta que perdamos más el tiempo
265  if (lnTotalBase == 0 && lnTotalDocumento == 0)
266  return 0.0M;
267 
268  // Decimales para redondeo en la moneda del documento
269  lnDecimalesMonedaDocu = toDocumento._Cabecera._oDivisa._Decimales;
270 
271  // Detectar con qué tipo de retención trabaja el cliente: no fiscal, fiscal o sin retención de ningún tipo.
272 
273  // Task 131967, optimizacion de la clase retencoin, nos aprovechamos del objeto de Cliente existente en la cabecera del documento, no hace falta crear un objeto nuevo.
274  // loCliente = new Cliente(lcCliente);
275  loCliente = toDocumento._Cabecera._oCliente;
276 
277  // CCR 205453 - Si tenemos porcentaje de retención no fiscal, calculamos la retención, aunque en la ficha esté desmarcado
278  if ( ( (toDocumento._TipoDocumento == eTipoDocumento.FacturaVenta || toDocumento._TipoDocumento == eTipoDocumento.Factura) &&
279  !string.IsNullOrWhiteSpace(toDocumento._Asi)) ||
280  ( (toDocumento._TipoDocumento == eTipoDocumento.FacturaVenta || toDocumento._TipoDocumento == eTipoDocumento.Factura
281  || toDocumento._TipoDocumento == eTipoDocumento.AlbaranVenta) && toDocumento._Cabecera._TpcRetNoFi != 0 ) )
282  // CCR186750
283  // Albarán de venta facturado y contabilizado (formulario albarán de venta o TPV consultando albarán de venta),
284  // o factura de venta contabilizada (formulario factura de venta, consultando documento factura).
285  //
286  // Podría ser que el documento fuese facturado con retención no fiscal, pero en este momento el cliente ya no tenga la marca
287  // de retención no fiscal en ficha.
288  //
289  // Por tanto, en facturas, siempre que esten contabilizadas, se aplicará o no retención no fiscal de cliente únicamente en
290  // función de si el campo Tpcretnofi de C_ALBVEN esté declarado o no, no miramos marca de aplicar retención de la ficha del
291  // cliente para nada.
292  //
293  // Recordar que en depósito, pedido y presupuesto no tenemos este campo en cabecera (._Cabecera._TpcRetNoFi) por que
294  // tampoco existe en la tabla de cabecera respectiva del documento.
295  //
296  llRetNoFisc = toDocumento._Cabecera._TpcRetNoFi != 0 ;
297  else
298  // En factura de venta no contabilizada, albarán de venta pendiente y resto de documentos de venta, si se aplica o no retención
299  // fiscal dependerá únicamente de la marca que tenga el cliente en su ficha.
300  //
301  // Si es un documento factura y no está contabilizada, funciona como si fuese un documento de venta tipo albarán, se aplicará
302  // retención no fiscal o no en función de lo que tenga el cliente definido en su ficha, aunque haya un _TpcRetNofi != 0 en cabecera.
303  // Que haya un _TpcRetNofi != 0 y un _ASI="" se podria dar si contabilizan la factura teniendo retencion definida en ficha, le
304  // quitan la retencion en ficha, y descontabilizan la factura, en este caso, manda lo que haya en ficha, funciona de esta forma
305  // tanto si es retención fiscal como si es retención no fiscal.
306  //
307  llRetNoFisc = loCliente._RetencionNoFiscal;
308 
309  llRecEquivCliente = loCliente._Recargo;
310 
311  if (llRetNoFisc)
312  {
313  decimal lnCuotaIvaNoSujeto = 0.0M;
314 
315  // Retención NO FISCAL
316  //
317  this._lHayRetencion = true;
318  if (toDocumento._TipoDocumento == eTipoDocumento.AlbaranVenta || toDocumento._TipoDocumento == eTipoDocumento.FacturaVenta || toDocumento._TipoDocumento == eTipoDocumento.Factura)
319  {
320  // Si estoy en un albarán de venta (facturado o no), o factura (contabilizada o no), el % de retención no fiscal está guardado en
321  // la cabecera.
322  //
323  lnPrcReten = toDocumento._Cabecera._TpcRetNoFi;
324  }
325  else
326  {
327  // Si estoy en un documento de venta que no es albarán ni factura, el % de retención no fiscal no está guardado en la cabecera, lo
328  // cogemos de la ficha del cliente.
329  //
330  lnPrcReten = loCliente._RetencionNoFiscalTPC;
331  }
332  this._lSobreBase = (Convert.ToInt32(loCliente._Campo("modretnofi")) == 1);
333 
334  // Control label de retención en el formulario
335  //
336 
337  // Obtener el nº de tipos de iva sujetos.
338  //
339  int lnTiposIvaSujetos = toDocumento._NumTiposIvaSujetos;
340 
341  // Obtener el nº de tipos de iva no sujetos.
342  //
343  int lnTiposIvaNoSujetos = toDocumento._NumTiposIvaNoSujetos;
344 
345  // Cálculo del importe de la retención y relleno los 3 campos que interesa guardar.
346  if (this._lSobreBase)
347  {
348  // En _Pie._TotalBase esta la base imponible antes de pronto pago (suma linias + importe portes si son antes pronto pago), pero la retención no fiscal sobre la base se calcula sobre la suma
349  // de las bases de los tipos de IVA y allí puede haber además los portes si son despues de pronto pago los cuales en este caso no estan contemplados en _Pie._TotalBase, hay que añadirlos pues.
350  //
351  // Si los portes son antes de pronto pago ya estan contemplados en _Pie._TotalBase
352  //
353  // Si los portes son IVA incluido en ningún caso se tienen en cuenta cara el cálculo de la retención no fiscal sobre base (al igual que FOX).
354  // Recordar: documento con iva incluido, los portes siempre son despues de printo pago y iva incluido y el usuairo no puede modificar esta configuración
355  // documenbto sin iva incluido, los portes se pueden escoger antes pronto pago (siempre seran sin iva inc) o despues pronto pago (el usuario escoge si son ivainc o no).
356  //
357  // Si hubiese recargo financiero, tampoco está contemplado en _Pie._TotalBase pero no importa pues la retención no fiscal sobre base no debe tener en cuenta este recargo financiero, no hace falta hacer nada.
358  if ((toDocumento._Pie._Portes._Importe != 0 || toDocumento._Pie._Portes._ImporteDivisa != 0) && toDocumento._Pie._Portes._Incluir_ProntoPago == false && toDocumento._Pie._Portes._Iva_Incluido == false)
359  {
360  lnImportePortes = !string.IsNullOrWhiteSpace(toDocumento._Cabecera._Divisa) && toDocumento._Cabecera._Divisa != this._lcMonedaEmpresa ? toDocumento._Pie._Portes._ImporteDivisa : toDocumento._Pie._Portes._Importe;
361 
362  // Añado a la base de cálculo los portes que son después de pronto pago, al ser NO IVA incluido ya está bien, no hay que hacer nada más.
363  lnTotalBase += lnImportePortes;
364  }
365 
366  // Bug188198 y CCR207431
367  //
368  // Si tenemos tipos de IVA sujetos y no sujetos en el mismo documento, la retencion no fiscal se calcula sobre los tipos de
369  // IVA sujetos solamente, se ignoran los tipos de IVA no sujetos.
370  // Si solo tenemos tipos de IVA sujetos en el documento, la retencion no fiscal se calcula sobre esos tipos de IVA sujetos.
371  // Si solo tenemos tipos de IVA NO sujetos en el documento, la retencion no fiscal se calcula sobre esos tipos de IVA NO sujetos.
372  //
373  if (lnTiposIvaSujetos > 0 && lnTiposIvaNoSujetos > 0)
374  lnTotalBase -= toDocumento._Pie._ObtenerBaseIvaNoSujeto(out lnCuotaIvaNoSujeto);
375 
376  this._nImporteRetencion = FUNCTIONS._Round((lnTotalBase - lnTotalPronto) * lnPrcReten / 100, lnDecimalesMonedaDocu);
377  }
378  else
379  {
380  // Bug188198 y CCR207431
381  //
382  // Si tenemos tipos de IVA sujetos y no sujetos en el mismo documento, la retencion no fiscal se calcula sobre los tipos de
383  // IVA sujetos solamente, se ignoran los tipos de IVA no sujetos.
384  // Si solo tenemos tipos de IVA sujetos en el documento, la retencion no fiscal se calcula sobre esos tipos de IVA sujetos.
385  // Si solo tenemos tipos de IVA NO sujetos en el documento, la retencion no fiscal se calcula sobre esos tipos de IVA NO sujetos.
386  //
387  if (lnTiposIvaSujetos > 0 && lnTiposIvaNoSujetos > 0)
388  {
389  lnTotalDocumento -= toDocumento._Pie._ObtenerBaseIvaNoSujeto(out lnCuotaIvaNoSujeto);
390  lnTotalDocumento -= lnCuotaIvaNoSujeto;
391  }
392  this._nImporteRetencion = FUNCTIONS._Round(lnTotalDocumento * lnPrcReten / 100, lnDecimalesMonedaDocu);
393  }
394 
395  this._cRetencionTipo = $"{(this._lSobreBase ? "Reten.No Fisc./Base" : "Reten.No Fisc./TotalFra.")} ({ loMascaraPorcent.StringFormatNet(lnPrcReten)})";
396  this._nRetencionPorcen = lnPrcReten;
397  this._eTipoRetFiscNoFisc = TipoRetencionVentas.NoFiscal;
398 
399  // Si la retención es NO FISCAL ya hemos acabado, no hace falta hacer nada más.
400  return this._nImporteRetencion;
401  }
402 
403  // A partir de aquí ya estamos siempre en el caso de retención FISCAL
404 
405  // Caso de ser RETENCION FISCAL, hemos de tener en cuenta en el cálculo de las retenciones solamente los articulos que no tienen marcado en su ficha "Sin Retención", tener en cuenta también si hay portes, pronto pago, etc.
406  // Para ello nos recorreremos todas las lineas del documento e iremos acumulando importe de retención teniendo en cuenta todo lo anterior comentado (portes, pronto pago, marca "sin retencion" en ficha artículo, etc.)
407 
408  // En este diccionario obtendremos el % de retencion a aplicar (o aplicado caso de ser factura en el momento de ser facturado), el modo de retención (sobre base/total factura), si el documento tiene recargo de equivalencia, etc.
409  Dictionary<string, object> loDicCurReter;
410  if (toCondicionesRetencion != null)
411  loDicCurReter = toCondicionesRetencion;
412  else
413  {
414  loDicCurReter = new Dictionary<string, object>();
415  loDicCurReter = this.Obtener_Condiciones_Retencion(toDocumento);
416  }
417 
418  lnPrcReten = loDicCurReter.Count > 0 ? Convert.ToDecimal(loDicCurReter["retencion"]) : 0;
419 
420  if (loDicCurReter.Count == 0 || lnPrcReten == 0)
421  {
422  // Task 170566
423  // El cliente podria tener retencion en ficha pero si el tipo de retención es del tipo "Aplicar % en documentos", el usuario podría
424  // cambiar el % en el documento y dejar 0 % de retención con lo que es lo mismo que no tener retención. De ahí que hayamos añadido
425  // la condición " || lnPrcReten == 0) "
426  //
427 
428  // No hay retención, rellenamos los campos y salimos.
429  this._lHayRetencion = false;
430  this._lSobreBase = false;
431  this._nImporteRetencion = 0.0M;
432  this._cRetencionTipo = "";
433  this._nRetencionPorcen = 0.0M;
434  this._eTipoRetFiscNoFisc = TipoRetencionVentas.Fiscal;
435  return 0.0M;
436  }
437 
438  // Obtenidas las condiciones vamos a iterar por las lineas y en función de lo que vayamos encontrando en cada linea acumularemos retencion o no
439  llSobreBase = Convert.ToBoolean(loDicCurReter["modo_ret"]);
440 
441  // Si no se cumple esta esta condición ya no entraremos al bucle de linea a linea para calcular la retencion solo de las lineas que la tengan.
442  if ( (lnTotalBase != 0 || lnTotalDocumento != 0) && lnPrcReten != 0)
443  {
444  string lcNumeroAlb = new string('@', 10);
445  string lcLetraAlb = new string('@', 2);
446 
447  decimal lnTotalRetencion = 0.0M;
448 
449  // Recorremos todas las lineas del documento, podemos estar en un documento factura que tiene datos de varios albaranes de venta, en un documento factura que tenga solo un albarán, en un documento albarán facturado, tenemos varios
450  // casos.
451  // Esencialmente, hay 2 casos diferentes, que haya más de un albarán de venta en el documento o solo uno. Es importante este aspecto pues el registro de portes va asociado al albarán y no a la factura, por lo que caso de que estamos
452  // en una factura de venta con varios albaranes, tendremos que tener en cuenta de a cada cambio de albarán hay que revisar el registro de portes.
453  foreach (Docsven.IDocVentaLin lin in toDocumento._Lineas)
454  {
455  if (lin._Numero != lcNumeroAlb || lin._Letra != lcLetraAlb)
456  {
457  // Cambio del nº de albarán, si estamos en un albarán de venta este número será siempre el mismo pero si estamos en un documento de tipo factura irá cambiando por que podrá haber más de un albarán y a cada documento
458  // iremos redondeando el total retencion acumulado a los decimales de la moneda.
459  lnTotalRetencion = FUNCTIONS._Round(lnTotalRetencion, lnDecimalesMonedaDocu);
460 
461  lnImportePortes = 0.0M;
462  lnImporteDivPortes = 0.0M;
463 
464  this.Obtener_Importe_Portes(lcEmpresa, lin._Numero, lin._Letra, toDocumento, ref lnImportePortes, ref lnImporteDivPortes, ref lnImportePortesIva, ref lnImporteDivPortesIva, ref llIncluirProntoPagoPortes, ref lcIva_Portes);
465 
466  // Si tenemos portes vamos a calcular la retención respectiva.
467  if (lnImportePortes != 0.0M)
468  lnTotalRetencion += this.Retencion_Linea("", lcIva_Portes, lnImportePortes, lnImporteDivPortes, lnImportePortesIva, lnImporteDivPortesIva, 0.0M, "", llRecEquivCliente, loDicCurReter, toDocumento, true, llIncluirProntoPagoPortes, null);
469 
470  lcNumeroAlb = lin._Numero;
471  lcLetraAlb = lin._Letra;
472  }
473 
474  // Calculamos la retención que le toca a la linea del documento en el que estamos.
475  // No procesamos lineas de notas ni linias de suplidos.
476  if (!string.IsNullOrWhiteSpace(lin._TipoIva) && !lin._Suplido)
477  {
478  lcTipoIva_Pverde = "";
479  if (this._lPverde && lin._PuntoVerde != 0)
480  lcTipoIva_Pverde = !string.IsNullOrWhiteSpace(lin._TipoIvaPV) ? lin._TipoIvaPV : lin._TipoIva;
481 
482  Articulo loArticulo = lin._oArticulo;
483  lnTotalRetencion += this.Retencion_Linea(lin._Articulo, lin._TipoIva, lin._Importe, lin._ImporteDivisa, lin._ImporteIva, lin._ImporteDivisaIva, lin._PuntoVerde, lcTipoIva_Pverde, llRecEquivCliente, loDicCurReter, toDocumento, false, true, loArticulo);
484  // Vacio la memoria que haya ocupado la utilización del objeto lin._oArticulo al pasarlo como parámetro en la llamada anterior.
485  lin._oArticulo = null;
486  }
487  }
488 
489  lnTotalRetencion = FUNCTIONS._Round(lnTotalRetencion, lnDecimalesMonedaDocu);
490 
491  this._lSobreBase = llSobreBase;
492  this._nImporteRetencion = lnTotalRetencion;
493  this._cRetencionTipo = $"{(this._lSobreBase ? "Reten./Base" : "Reten./TotalFra.")} ({loMascaraPorcent.StringFormatNet(lnPrcReten)})";
494  this._nRetencionPorcen = lnPrcReten;
495  this._lHayRetencion = true;
496  this._eTipoRetFiscNoFisc = TipoRetencionVentas.Fiscal;
497  }
498  else
499  {
500  // No hay retención
501  this._lHayRetencion = false;
502  this._cRetencionTipo = "";
503  this._nRetencionPorcen = 0.0M;
504  this._nImporteRetencion = 0.0M;
505  this._eTipoRetFiscNoFisc = TipoRetencionVentas.Fiscal;
506  this._lSobreBase = false;
507  }
508 
509  // Retornamos el importe correspondiente a la retención.
510  return this._nImporteRetencion;
511  }
512 
513 
522  public virtual bool _Calcular_Retencion(dynamic toDocumento, out decimal tnImporteRetencion, out decimal tnPorcentajeRetencion, out string tcTipoRetencion)
523  {
524  tnImporteRetencion = this._Calcular_Retencion(toDocumento); //Invoco a la función original
525 
526  tnPorcentajeRetencion = this._nRetencionPorcen;
527  tcTipoRetencion = this._cRetencionTipo;
528 
529  return this._lHayRetencion;
530  }
531 
532 
536  public virtual void _Control_Label_Retencion(dynamic toFormPare, bool tlHayRetencion, bool tlFiscal = true, decimal tnTpc = 0)
537  {
538  this._Control_Label_Retencion(toFormPare, tlHayRetencion, null, tlFiscal, tnTpc);
539 
540  return;
541  }
542 
543 
547  public virtual void _Control_Label_Retencion(dynamic toFormPare, bool tlHayRetencion, bool? tlSobreBase, bool tlFiscal = true, decimal tnTpc = 0)
548  {
549  string lcText = "";
550  Control[] loControls = toFormPare.Controls.Find("lblRetencion", true);
551  if (loControls.Length > 0)
552  {
553  if (tlFiscal)
554  lcText = "Ret.Fiscal";
555  else
556  lcText = "Ret. No Fiscal";
557 
558  lcText += " (" + tnTpc.ToString().Trim() + "%" + (tlSobreBase != null ? ((bool)tlSobreBase ? " Sb" : " St") : "") + ")";
559 
560  loControls[0].Visible = tlHayRetencion;
561  loControls[0].Text = lcText;
562  }
563  loControls = null;
564 
565  }
566 
567 
571  public void Dispose()
572  {
573  // No cambie este código. Coloque el código de limpieza en el anterior Dispose(colocación de bool).
574  Dispose(true);
575  // para que el recolector de elementos no utilizados no llame al finalizador del objeto
576  GC.SuppressFinalize(this);
577  }
578 
579 
583  public void _ReleaseQueryCaches()
584  {
585  foreach (KeyValuePair<string,DataTable> pair in this._DicRetEmpCli)
586  {
587  FUNCTIONS._DisposeDatatable(pair.Value);
588  }
589 
590  foreach (KeyValuePair<string, DataTable> pair in this._DicRetSoporFact)
591  {
592  FUNCTIONS._DisposeDatatable(pair.Value);
593  }
594 
595  foreach (KeyValuePair<string,Dictionary<string,object>> pair in this._DicIvareperFact)
596  {
597  pair.Value.Clear();
598  }
599 
600  this._DicRetEmpCli.Clear();
601  this._DicRetSoporFact.Clear();
602  this._DicIvareperFact.Clear();
603  return;
604  }
605 
606 
607  #endregion MÉTODOS PÚBLICOS
608 
609 
610  #region MÉTODOS PRIVADOS
611 
612 
617  private void Dispose(bool disposing)
618  {
619  if (!disposedValue)
620  {
621  if (disposing)
622  {
623  // Vaciar las caches de consultas.
624  //
625  this._ReleaseQueryCaches();
626  }
627  disposedValue = true;
628  }
629  }
630 
631 
639  private DataTable _Informacion_RetEmpCli(string tcEmpresa, string tcCliente)
640  {
641  DataTable ldtDataTable = new DataTable();
642 
643  if (string.IsNullOrWhiteSpace(tcEmpresa) || string.IsNullOrWhiteSpace(tcCliente))
644  return ldtDataTable;
645 
646  if (!this._DicRetEmpCli.ContainsKey(tcEmpresa+"/"+tcCliente))
647  {
648  // CCR190539, caso estar consultando un documento de un ejercicio anterior desde otro ejercicio.
649  string ldBdGestion = "GESTION";
650  if (!string.IsNullOrWhiteSpace(this._oDocRef._EjercicioDB) && this._oDocRef._EjercicioDB.Trim() != "GESTION" &&
651  this._oDocRef._EjercicioDB.Trim() != this._cAny.Trim())
652  ldBdGestion = this._oDocRef._EjercicioDB.Trim();
653 
654  // Recordar que a pesar de que a partir de Octubre del 2020 el % de retención fiscal viene en un campo del pie del documento
655  // hemos de hacer esta consulta para averiguar si la retención es sobre base o sobre total, asi como verifivar que la retención
656  // en la empresa esté activa, y ninguna de las dos cosas anteriores se guarda en el documento.
657  //
658  string lcSql = "SELECT a.RETENCION, b.MODO_RET, " + DB.SQLFalse() + " AS RECARGO, " + DB.SQLString("", 2) + " AS TIPO_IVA " +
659  "FROM " + DB.SQLDatabase(ldBdGestion, "TIPO_RET") + " a " +
660  "INNER JOIN " + DB.SQLDatabase(ldBdGestion, "RET_EMP") + " b ON a.CODIGO=b.TIPO_RET " +
661  "WHERE b.empresa = " + DB.SQLString(tcEmpresa) + " and b.cuenta = " + DB.SQLString(tcCliente);
662 
663  DB.SQLExec(lcSql, ref ldtDataTable);
664 
665  this._DicRetEmpCli.Add(tcEmpresa+"/"+tcCliente, ldtDataTable);
666  }
667 
668  return this._DicRetEmpCli[tcEmpresa + "/" + tcCliente];
669  }
670 
671 
681  private DataTable _Informacion_RetSoporFact(dynamic toDocumento, string tcFactura)
682  {
683  DataTable ldtDataTable = new DataTable();
684  if (_Informacion_RetSoporFactContabilizada(toDocumento, ref ldtDataTable))
685  return ldtDataTable;
686  else
687  return _Informacion_RetSoporFactTabla(toDocumento._Empresa, tcFactura);
688  }
689 
690 
698  private bool _Informacion_RetSoporFactContabilizada(dynamic toDocumento, ref DataTable tdtDataTable)
699  {
700  // Para saber si estamos en un DTS mirar si el campo ASI tiene valor "CONTABILIZADA"
701  if (!(toDocumento is ewDocVentaFRA) || toDocumento._Asi.Trim() != "CONTABILIZADA")
702  return false;
703 
704  // Obtener los albaranes de la factura
705  Dictionary<string, sage.ew.docventatpv.ewDocVentaTPV> _dicAlbaranes = toDocumento._dicAlbaranes;
706  if (_dicAlbaranes == null || _dicAlbaranes.Count == 0)
707  return false;
708 
709  // Añadir las columnas
710  tdtDataTable.Columns.Add("tipo_ret", typeof(decimal));
711  tdtDataTable.Columns.Add("modo_ret", typeof(Int32));
712 
713  // Obtener la información de la retención
714  DataRow ldrRow = tdtDataTable.NewRow();
715  ldrRow["tipo_ret"] = ((sage.ew.docventatpv.ewDocVentaTPV)_dicAlbaranes.First().Value)._Pie._RetencionPorcen;
716  ldrRow["modo_ret"] = ((sage.ew.docventatpv.ewDocVentaTPV)_dicAlbaranes.First().Value)._Pie._RetencionModo;
717  tdtDataTable.Rows.Add(ldrRow);
718 
719  return true;
720  }
721 
722 
730  private DataTable _Informacion_RetSoporFactTabla(string tcEmpresa, string tcFactura)
731  {
732  DataTable ldtDataTable = new DataTable();
733 
734  if (string.IsNullOrWhiteSpace(tcEmpresa) || string.IsNullOrWhiteSpace(tcFactura))
735  return ldtDataTable;
736 
737  if (!this._DicRetSoporFact.ContainsKey(tcEmpresa + "/" + tcFactura))
738  {
739  // CCR190539, caso estar consultando un documento de un ejercicio anterior desde otro ejercicio.
740  string ldBdGestion = "GESTION";
741  if (!string.IsNullOrWhiteSpace(this._oDocRef._EjercicioDB) && this._oDocRef._EjercicioDB.Trim() != "GESTION" &&
742  this._oDocRef._EjercicioDB.Trim() != this._cAny.Trim())
743  ldBdGestion = this._oDocRef._EjercicioDB.Trim();
744 
745  string lcSql = "SELECT a.* " +
746  "FROM " + DB.SQLDatabase(ldBdGestion, "RETSOPOR") + " a " +
747  "INNER JOIN " + DB.SQLDatabase(ldBdGestion, "TIPO_RET") + " b ON a.CODIGO_RET=b.CODIGO " +
748  "WHERE a.empresa = " + DB.SQLString(tcEmpresa) + " and a.numfra = " + DB.SQLString(tcFactura);
749  DB.SQLExec(lcSql, ref ldtDataTable);
750 
751  this._DicRetSoporFact.Add(tcEmpresa + "/" + tcFactura, ldtDataTable);
752  }
753 
754  return this._DicRetSoporFact[tcEmpresa + "/" + tcFactura];
755  }
756 
757 
765  private Dictionary<string, object> _Informacion_IvareperFact(string tcEmpresa, string tcFactura)
766  {
767  Dictionary<string, object> laCampos = new Dictionary<string, object>();
768 
769  if (string.IsNullOrWhiteSpace(tcEmpresa) || string.IsNullOrWhiteSpace(tcFactura))
770  {
771  laCampos.Add("tipo_iva", "");
772  laCampos.Add("recargo", false);
773  return laCampos;
774  }
775 
776  if (!this._DicIvareperFact.ContainsKey(tcEmpresa + "/" + tcFactura))
777  {
778  // Bug 133253, ojo por que en un albarán facturado el cliente de IVAREPER podria ser diferente si el cliente del albarán tiene cliente factura. Y podríamos tener el caso
779  // de que el cliente del albarán no tenga recargo equivalencia y el cliente factura si lo tenga lo cual haria variar las condiciones, nos ahorramos el filtro por cliente
780  // para que encuentre siempre el registro de IVAREPER
781  //loDicIvareper = DB.SQLValor("IVAREPER", new String[] { "empresa", "cuenta", "numfra" }, new string[] { lcEmpresa, lcCliente, lcNumFra }, new string[] { "tipo_iva", "recargo" });
782 
783  laCampos = DB.SQLValor("IVAREPER", new String[] { "empresa", "numfra" }, new string[] { tcEmpresa, tcFactura }, new string[] { "tipo_iva", "recargo" });
784 
785  this._DicIvareperFact.Add(tcEmpresa + "/" + tcFactura, laCampos);
786  }
787 
788  return this._DicIvareperFact[tcEmpresa + "/" + tcFactura];
789  }
790 
791 
805  private void Obtener_Importe_Portes(string tcEmpresa, string tcNumero, string tcLetra, dynamic toDocumento, ref decimal tnImportePortes, ref decimal tnImporteDivPortes, ref decimal tnImportePortesIva, ref decimal tnImporteDivPortesIva, ref bool tlIncluirProntoPagoPortes, ref string tcIva_Portes)
806  {
807  bool llIvaInc = false;
808 
809  if ( toDocumento._TipoDocumento == eTipoDocumento.Factura ||
810  toDocumento._TipoDocumento == eTipoDocumento.FacturaVenta ||
811  ( toDocumento._TipoDocumento == eTipoDocumento.AlbaranVenta && !string.IsNullOrWhiteSpace(toDocumento._Cabecera._Factura) ) )
812  {
813  // Si es un documento de factura vamos a buscar los portes a la tabla, portes del albarán que estamos procesando
814  Dictionary<string, object> loDicPortes = new Dictionary<string, object>();
815  loDicPortes = DB.SQLREGValor("portes", new string[] { "empresa", "albaran", "letra" }, new string[] { tcEmpresa, tcNumero, tcLetra });
816 
817  bool llInc_Fra = Convert.ToBoolean(loDicPortes["inc_fra"]);
818  if (llInc_Fra)
819  {
820  tlIncluirProntoPagoPortes = Convert.ToBoolean(loDicPortes["inc_pp"]);
821  llIvaInc = Convert.ToBoolean(loDicPortes["iva_inc"]);
822  tcIva_Portes = Convert.ToString(loDicPortes["tipo_iva"]);
823 
824  // Task 131967, optimizacion, nos aprovechamos del diccionario de tipos de iva del documento y nos ahorramos probablemente la consulta.
825  // TipoIVA loTipoIva = new TipoIVA();
826  // loTipoIva._Codigo = tcIva_Portes;
827  // decimal lnTipoIva = 1 + (loTipoIva._IVA / 100);
828 
829  decimal lnTipoIva = 1 + (toDocumento._Informacion_Tipo_Iva(tcIva_Portes)["iva"] / 100);
830 
831  if (llIvaInc)
832  {
833  tnImportePortesIva = Convert.ToDecimal(loDicPortes["importe"]);
834  tnImporteDivPortesIva = Convert.ToDecimal(loDicPortes["importediv"]);
835 
836  tnImportePortes = FUNCTIONS._Round(tnImportePortesIva / lnTipoIva, this._lnDecimales);
837  tnImporteDivPortes = FUNCTIONS._Round(tnImporteDivPortesIva / lnTipoIva, toDocumento._Cabecera._oDivisa._Decimales);
838  }
839  else
840  {
841  tnImportePortes = Convert.ToDecimal(loDicPortes["importe"]);
842  tnImporteDivPortes = Convert.ToDecimal(loDicPortes["importediv"]);
843 
844  tnImportePortesIva = FUNCTIONS._Round(tnImportePortes * lnTipoIva, this._lnDecimales);
845  tnImporteDivPortesIva = FUNCTIONS._Round(tnImporteDivPortes * lnTipoIva, toDocumento._Cabecera._oDivisa._Decimales);
846  }
847  }
848  else
849  {
850  tnImportePortesIva = 0;
851  tnImporteDivPortesIva = 0;
852  tnImportePortes = 0;
853  tnImporteDivPortes = 0;
854  tcIva_Portes = "";
855  }
856  }
857  else
858  {
859  // Task 125111,125112: a partir de ahora todos los documentos de venta podran tener portes.
860  if (toDocumento._TipoDocumento == eTipoDocumento.AlbaranVenta || toDocumento._TipoDocumento == eTipoDocumento.PedidoVenta ||
861  toDocumento._TipoDocumento == eTipoDocumento.PresupuestoVenta || toDocumento._TipoDocumento == eTipoDocumento.DepositoVenta )
862  {
863  if (toDocumento._Pie._Portes._Incluir_EnFactura)
864  {
865  // Si es un documento de albarán vamos a buscar los portes al objeto
866  tlIncluirProntoPagoPortes = toDocumento._Pie._Portes._Incluir_ProntoPago;
867  llIvaInc = toDocumento._Pie._Portes._Iva_Incluido;
868 
869  // Task 131967, optimizacion, nos aprovechamos del diccionario de tipos de iva del documento y nos ahorramos probablemente la consulta.
870 
871  // TipoIVA loTipoIva = new TipoIVA();
872  // loTipoIva._Codigo = tcIva_Portes;
873  // decimal lnTipoIva = 1 + (loTipoIva._IVA / 100);
874 
875  tcIva_Portes = toDocumento._Pie._Portes._Tipo_Iva;
876  decimal lnTipoIva = 1 + (toDocumento._Informacion_Tipo_Iva(tcIva_Portes)["iva"] / 100);
877 
878  if (llIvaInc)
879  {
880  tnImportePortesIva = toDocumento._Pie._Portes._Importe;
881  tnImporteDivPortesIva = toDocumento._Pie._Portes._ImporteDivisa;
882 
883  tnImportePortes = FUNCTIONS._Round(tnImportePortesIva / lnTipoIva, this._lnDecimales);
884  tnImporteDivPortes = FUNCTIONS._Round(tnImporteDivPortesIva / lnTipoIva, toDocumento._Cabecera._oDivisa._Decimales);
885  }
886  else
887  {
888  tnImportePortes = toDocumento._Pie._Portes._Importe;
889  tnImporteDivPortes = toDocumento._Pie._Portes._ImporteDivisa;
890 
891  tnImportePortesIva = FUNCTIONS._Round(tnImportePortes * lnTipoIva, this._lnDecimales);
892  tnImporteDivPortesIva = FUNCTIONS._Round(tnImporteDivPortes * lnTipoIva, toDocumento._Cabecera._oDivisa._Decimales);
893  }
894  }
895  else
896  {
897  tnImportePortesIva = 0;
898  tnImporteDivPortesIva = 0;
899  tnImportePortes = 0;
900  tnImporteDivPortes = 0;
901  tcIva_Portes = "";
902  }
903  }
904  }
905  }
906 
907 
926  private decimal Retencion_Linea(string tcArticulo, string tcTipoIva, decimal tnImporte, decimal tnImporteDivisa, decimal tnImporteIva, decimal tnImporteDivisaIva, decimal tnPuntoVerde, string tcTipoIva_Pverde, bool tlRecEquivCliente, Dictionary<string, object> toDicCurReter, dynamic toDocumento, bool tlLineaPortes = false, bool tlIncluirProntoPago = true, Articulo toArticulo = null)
927  {
928  string lcCliente = toDocumento._Cabecera._Cliente, lcTipo_Iva = "", lcTipoIvaReter = "";
929  decimal lnPrcPronto = toDocumento._Pie._DtoPP, lnImportePverde = 0.0M, lnImportePVerdeIVA = 0.0M, lnImpPronto = 0.0M, lnRetencionLinea = 0.0M, lnPrcIvaPverde = 0.0M, lnRecarreg = 0.0M;
930  decimal lnRetencionReter = 0.0M;
931  bool ll_Divisa = false, llModo_RetReter = false, llRecargoReter = false;
932 
933  ll_Divisa = this._lDivisa;
934  llModo_RetReter = Convert.ToBoolean(toDicCurReter["modo_ret"]);
935  lnRetencionReter = Convert.ToDecimal(toDicCurReter["retencion"]);
936  lcTipoIvaReter = Convert.ToString(toDicCurReter["tipo_iva"]);
937  llRecargoReter = Convert.ToBoolean(toDicCurReter["recargo"]);
938 
939 
940  // Esto será útil en el momento que estemos acumulando la retención sobre los portes, si son después de pronto pago, aunque haya pronto pago, simularemos que no lo hay.
941  if (!tlIncluirProntoPago)
942  lnPrcPronto = 0;
943 
944 
945  bool llAplicarRetencion = false;
946 
947  // Task 131967, optimización no utilizaré el objeto de tipos de iva sino que utilizaré el diccionario propio de tipos de IVA del documento.
948  // TipoIVA loTipoIva = new TipoIVA();
949 
950  if (ll_Divisa == true && !string.IsNullOrWhiteSpace(toDocumento._Cabecera._Divisa) && toDocumento._Cabecera._Divisa != this._lcMonedaEmpresa)
951  // Trabajamos con multidivisa y la moneda del documento es diferente de la moneda de la empresa
952  ll_Divisa = true;
953  else
954  // No trabajamos con multidivisa, o trabajamos con multidivisa pero la moneda del documento es igual a la moneda de la empresa
955  ll_Divisa = false;
956 
957 
958  llAplicarRetencion = true;
959 
960  if (!string.IsNullOrWhiteSpace(tcArticulo))
961  {
962  // Miramos si debe aplicarse retención al artículo.
963 
964  // Task 131967, optimizacion, no creamos el objeto Articulo sino que nos aprovechamos del que hay en la linea del documento.
965  // Articulo loArticulo = new Articulo(tcArticulo);
966  llAplicarRetencion = Convert.ToString(toArticulo._Campo("retencion")) != "N";
967  }
968  else
969  {
970  // Los artículos no codificados con importe siempre se aplicará retención.
971  // Una linea de notas ya no llega a este metodo.
972  // En particular cuando se llame a este método para el calculo de retencion sobre portes (se pasará artículo en blanco y tnImporte y tnImporteDIv)
973  }
974 
975  // En el caso de que el documento tenga tipos de iva sujetos y no sujetos, solo los sujetos se utilizarán para
976  // el cálculo de la retención.
977  //
978  // Los tipos de iva no sujetos solo se utilizarán en el caso de que solo haya tipos de iva no sujetos en el documento.
979  //
980  // Mirar CCR203216 Y CCR184685
981  //
982 
983  // Obtener el nº de tipos de iva sujetos.
984  //
985  int lnTiposIvaSujetos = toDocumento._NumTiposIvaSujetos;
986 
987  // Obtener el nº de tipos de iva no sujetos.
988  //
989  int lnTiposIvaNoSujetos = toDocumento._NumTiposIvaNoSujetos;
990 
991 
992  bool llNoSujeto = toDocumento._Informacion_Tipo_Iva(tcTipoIva)["exento"];
993  if (lnTiposIvaSujetos>0 && lnTiposIvaNoSujetos>0 && llNoSujeto)
994  llAplicarRetencion = false;
995 
996  if (llAplicarRetencion)
997  {
998  lcTipo_Iva = "";
999  if (llRecargoReter && llModo_RetReter == false)
1000  {
1001  if (!string.IsNullOrWhiteSpace(tcTipoIva))
1002  lcTipo_Iva = tcTipoIva;
1003  else
1004  {
1005  if (!string.IsNullOrWhiteSpace(lcTipoIvaReter))
1006  lcTipo_Iva = lcTipoIvaReter;
1007  else
1008  lcTipo_Iva = Convert.ToString(EW_GLOBAL._GetVariable("wc_tipo_iva"));
1009  }
1010  }
1011 
1012  // Importe de punto verde lineal
1013  lnImportePverde = this._lPverde && !string.IsNullOrWhiteSpace(tcArticulo) ? tnPuntoVerde : 0.0M;
1014 
1015  if (llModo_RetReter)
1016  {
1017  // RETENCION SOBRE BASE
1018  //
1019  if (ll_Divisa)
1020  {
1021  // Moneda del documento diferente de la de la empresa.
1022  //
1023  lnImpPronto = 0.0M;
1024  if (lnPrcPronto != 0)
1025  lnImpPronto = tnImporteDivisa * lnPrcPronto / 100;
1026 
1027  // En divisa diferente de la moneda de la empresa no hay punto verde.
1028  //
1029  lnRetencionLinea += (tnImporteDivisa - lnImpPronto) * lnRetencionReter / 100;
1030  }
1031  else
1032  {
1033  // Moneda del documento es la moneda de la empresa.
1034  //
1035  lnImpPronto = 0.0M;
1036  if (lnPrcPronto != 0)
1037  {
1038  lnImpPronto = tnImporte * lnPrcPronto / 100;
1039  lnImpPronto += (lnImportePverde * lnPrcPronto / 100);
1040  }
1041 
1042  lnRetencionLinea += (tnImporte + lnImportePverde - lnImpPronto) * lnRetencionReter / 100;
1043  }
1044  }
1045  else
1046  {
1047  // RETENCION SOBRE TOTAL FACTURA.
1048  //
1049 
1050  if (ll_Divisa)
1051  {
1052  // Moneda del documento diferente de la de la empresa.
1053  //
1054  lnImpPronto = 0.0M;
1055  if (lnPrcPronto != 0)
1056  lnImpPronto = tnImporteDivisaIva * lnPrcPronto / 100;
1057 
1058  // En divisa diferente de la moneda de la empresa no hay punto verde.
1059  //
1060  lnRetencionLinea += (tnImporteDivisaIva - lnImpPronto) * lnRetencionReter / 100;
1061  }
1062  else
1063  {
1064  // Moneda del documento es la moneda de la empresa.
1065  //
1066  lnImpPronto = 0.0M;
1067  if (lnPrcPronto != 0)
1068  lnImpPronto = tnImporteIva * lnPrcPronto / 100;
1069 
1070  lnImportePVerdeIVA = 0.0M;
1071 
1072  if (this._lPverde && lnImportePverde != 0 && !string.IsNullOrWhiteSpace(tcArticulo) && !string.IsNullOrWhiteSpace(tcTipoIva) && !string.IsNullOrWhiteSpace(lcCliente))
1073  {
1074  // Task 131967, optimización no utilizaré el objeto de tipos de iva sino que utilizaré el diccionario propio de tipos de IVA del documento.
1075  // loTipoIva._Codigo = tcTipoIva_Pverde;
1076  // lnPrcIvaPverde = loTipoIva._IVA;
1077  // lnPrcIvaPverde += (tlRecEquivCliente && (this._lRecivainc || toDocumento._Cabecera._IvaInc == false)) ? Convert.ToDecimal(loTipoIva._Campo("recarg")) : 0.0M;
1078 
1079  lnPrcIvaPverde = toDocumento._Informacion_Tipo_Iva(tcTipoIva_Pverde)["iva"];
1080  lnPrcIvaPverde += (tlRecEquivCliente && (this._lRecivainc || toDocumento._Cabecera._IvaInc == false)) ? Convert.ToDecimal(toDocumento._Informacion_Tipo_Iva(tcTipoIva_Pverde)["recarg"]) : 0.0M;
1081 
1082  lnImportePVerdeIVA = (lnImportePverde * (1 + lnPrcIvaPverde / 100));
1083 
1084  if (lnPrcPronto != 0)
1085  lnImpPronto = lnImpPronto + (lnImportePVerdeIVA * lnPrcPronto / 100);
1086  }
1087  lnRetencionLinea += (tnImporteIva + lnImportePVerdeIVA - lnImpPronto) * lnRetencionReter / 100;
1088  }
1089 
1090  if (llRecargoReter)
1091  {
1092  // Si se ha de aplicar la retención también sobre el recargo de equivalencia.
1093  //
1094 
1095  // Task 131967, optimización no utilizaré el objeto de tipos de iva sino que utilizaré el diccionario propio de tipos de IVA del documento.
1096  // loTipoIva._Codigo = lcTipo_Iva;
1097  // lnRecarreg = loTipoIva._Recargo;
1098  lnRecarreg = toDocumento._Informacion_Tipo_Iva(lcTipo_Iva)["recarg"];
1099 
1100  if (lnRecarreg != 0)
1101  {
1102  // Si el documento se hizo con precios SIN IVA, los campos PRECIOIVA, PRECIOIVADIV, IMPORTEIVA, IMPORTEIVADIV ya tiene el PRECIO+IVA+RECARGO
1103  // Si el documento se hizo con precios CON IVA y tenemos activado el OPCFLAG de recargo equivalencia incluido en precios IVA INCLUIDO
1104  // los campos PRECIOIVA, PRECIOIVADIV, IMPORTEIVA, IMPORTEIVADIV ya tiene el PRECIO+IVA+RECARGO, SINO SON SOLO PRECIO+IVA
1105 
1106  // En estos dos casos no hace falta calcular la retencion de la parte de recargo de equivalencia de la linea pues ya se hizo más arriba al estar
1107  // incluido el recargo en el PRECIOIVA,IMPORTEIVA.
1108 
1109  // Esto es solo para el caso de retención sobre total factura.
1110 
1111  // Si estamos en una linea de PORTES entonces sí que hay que calcular la retención del recargo pues en los portes cuando son IVA INCLUIDO
1112  // siempre se entiende que no hay recargo de equivalencia incluido y hay que añadirlo
1113  if (tlLineaPortes == false && (toDocumento._Cabecera._IvaInc == false || (toDocumento._Cabecera._IvaInc == true && this._lRecivainc)))
1114  {
1115 
1116  }
1117  else
1118  {
1119  if (ll_Divisa)
1120  {
1121  // Moneda del documento diferente de la de la empresa
1122  lnImpPronto = 0.0M;
1123  if (lnPrcPronto != 0)
1124  lnImpPronto = tnImporteDivisa * lnPrcPronto / 100;
1125 
1126  lnRetencionLinea += (tnImporteDivisa - lnImpPronto) * lnRecarreg / 100 * lnRetencionReter / 100;
1127  }
1128  else
1129  {
1130  lnImpPronto = 0.0M;
1131  if (lnPrcPronto != 0)
1132  lnImpPronto = tnImporte * lnPrcPronto / 100;
1133 
1134  // lnRetencionLinea += (tnImporte + lnImportePverde - lnImpPronto) * lnRecarreg / 100 * lnRetencionReter / 100;
1135  lnRetencionLinea += (tnImporte - lnImpPronto) * lnRecarreg / 100 * lnRetencionReter / 100;
1136 
1137  if (this._lPverde && lnImportePverde != 0)
1138  {
1139  // Task 131967, optimización no utilizaré el objeto de tipos de iva sino que utilizaré el diccionario propio de tipos de IVA del documento.
1140  //loTipoIva._Codigo = tcTipoIva_Pverde;
1141  //lnRecarreg = loTipoIva._Recargo;
1142  lnRecarreg = toDocumento._Informacion_Tipo_Iva(tcTipoIva_Pverde)["recarg"]; ;
1143 
1144  lnImpPronto = 0.0M;
1145  if (lnPrcPronto != 0)
1146  lnImpPronto = (lnImportePverde * lnPrcPronto / 100);
1147 
1148  lnRetencionLinea += (lnImportePverde - lnImpPronto) * lnRecarreg / 100 * lnRetencionReter / 100;
1149  }
1150  }
1151  }
1152  }
1153  }
1154  }
1155  }
1156  return lnRetencionLinea;
1157  }
1158 
1159 
1168  private Dictionary<string, object> Obtener_Condiciones_Retencion(dynamic toDocumento)
1169  {
1170  bool llEsFactura = false, llRecargo = false;
1171  string lcNumFra = "", lcTipo_Iva = "";
1172  DataTable ldtRetSopor = null, ldtReter = null;
1173  Dictionary<string, object> loDicCurReter = new Dictionary<string, object>();
1174 
1175  string lcEmpresa = toDocumento._Empresa;
1176  string lcCliente = toDocumento._Cabecera._oCliente._Codigo;
1177 
1178  if (string.IsNullOrWhiteSpace(lcEmpresa) || string.IsNullOrWhiteSpace(lcCliente))
1179  return loDicCurReter;
1180 
1181  // Miramos si hay que aplicar Retención FISCAL
1182  //
1183  // Recordar que a pesar de que a partir de Octubre del 2020 el % de retención fiscal viene en un campo del pie del documento
1184  // hemos de hacer esta consulta para averiguar si la retención es sobre base o sobre total, asi como verificar que la retención
1185  // en la empresa esté activa, y ninguna de las dos cosas anteriores se guarda en el documento.
1186  //
1187  // Llamamos a esté método que mira un diccionario cache interno que hemos implementado para cachear la consulta por empresa,proveedor
1188  // en la optimización realizada en la Task 171939
1189  ldtReter = this._Informacion_RetEmpCli(lcEmpresa, lcCliente);
1190  if (ldtReter.Rows.Count > 0)
1191  _lHayRetencion = true;
1192 
1193  // Reviso si estamos en una factura
1194  if ((toDocumento._TipoDocumento == eTipoDocumento.Factura ||
1195  toDocumento._TipoDocumento == eTipoDocumento.FacturaVenta ||
1196  toDocumento._TipoDocumento == eTipoDocumento.AlbaranVenta) &&
1197  !string.IsNullOrWhiteSpace(toDocumento._Cabecera._Factura) && !string.IsNullOrWhiteSpace(toDocumento._Asi))
1198  {
1199  // Tanto si se trabaja con series de facturas como si no, en este campo tenemos el nº de factura correcto.
1200  llEsFactura = true;
1201  lcNumFra = toDocumento._Cabecera._Factura;
1202  }
1203 
1204  // Si es una factura o albarán facturado obtenemos los datos del registro de RETSOPOR
1205  if (llEsFactura)
1206  {
1207  ldtRetSopor = this._Informacion_RetSoporFact(toDocumento, lcNumFra);
1208  if (ldtReter.Rows.Count == 0)
1209  {
1210  DataRow loRow = ldtReter.NewRow();
1211  loRow["recargo"] = false;
1212  loRow["tipo_iva"] = "";
1213  ldtReter.Rows.Add(loRow);
1214  }
1215  ldtReter.Rows[0]["retencion"] = ldtRetSopor.Rows.Count > 0 ? Convert.ToDecimal(ldtRetSopor.Rows[0]["tipo_ret"]) : 0.0M;
1216  ldtReter.Rows[0]["modo_ret"] = ldtRetSopor.Rows.Count > 0 ? (Convert.ToInt32(ldtRetSopor.Rows[0]["modo_ret"]) == 1 ? true : false) : false;
1217 
1218  Dictionary<string, object> loDicIvareper = this._Informacion_IvareperFact(lcEmpresa, lcNumFra);
1219  lcTipo_Iva = Convert.ToString(loDicIvareper["tipo_iva"]);
1220  llRecargo = Convert.ToDecimal(loDicIvareper["recargo"]) != 0.0M;
1221  }
1222 
1223  if (ldtReter.Rows.Count == 0)
1224  // Esto pasará si no se detecta retencion en la ficha del cliente ni esté facturado.
1225  return loDicCurReter;
1226 
1227  if (string.IsNullOrWhiteSpace(lcTipo_Iva))
1228  {
1229  // Task 131967, optimización, aprovecho el objeto cliente de la cabecera del documento en vez de crear uno nuevo y me ahorro unas consultas
1230  // Cliente loCliente = new Cliente(lcCliente);
1231  Cliente loCliente = toDocumento._Cabecera._oCliente;
1232  lcTipo_Iva = loCliente._TipoIVA;
1233  llRecargo = loCliente._Recargo;
1234  }
1235 
1236  ldtReter.Rows[0]["tipo_iva"] = lcTipo_Iva;
1237  ldtReter.Rows[0]["recargo"] = llRecargo;
1238 
1239  // Task 170566.
1240  // Si no estamos en una factura el % de retención fiscal sale del pie del propio documento, la resta de condiciones por el mismo procedimiento
1241  // que se ha hecho hasta ahora. Cogemos la retención de la propiedad _RetencionPorcen que es la que enlaza con el campo PORCEN_RET de C_ALBVEN
1242  // o C_PEDIVE, C_PRESUV, etc.) que guarda el % de retención fiscal por documento. No confundir con la propiedad _RetencionDocPorcen (de solo
1243  // lectura, campo informativo) que devuelve el % de retención aplicado en el documento, ya sea fiscal o no fiscal.
1244  //
1245  if (!llEsFactura)
1246  {
1247  ldtReter.Rows[0]["retencion"] = toDocumento._Pie._RetencionPorcen;
1248 
1249  if ( toDocumento._TipoDocumento != eTipoDocumento.PedidoVenta &&
1250  toDocumento._TipoDocumento != eTipoDocumento.PresupuestoVenta &&
1251  toDocumento._TipoDocumento != eTipoDocumento.DepositoVenta)
1252  {
1253  // Albarán de venta pendiente de facturar o factura de venta no contabilizada el modo de calculo de la retención (sobre base/sobre total) se
1254  // extrae del pie del documento al igual que el % de retencion. En pedidos, prespuestos y depósito hereda siempre la que hay en la ficha del
1255  // cliente. Y en factura de venta contabilizada el % y el modo cálculo se extrae de tabla GESTION!RETSOPOR
1256  //
1257  ldtReter.Rows[0]["modo_ret"] = (Convert.ToInt32(toDocumento._Pie._RetencionModo) == 1); // Si es sobre base tiene .T., sobre total .F., como en la ficha cliente.
1258  }
1259  }
1260 
1261 
1262 
1263  loDicCurReter.Add("retencion", Convert.ToDecimal(ldtReter.Rows[0]["retencion"]));
1264  loDicCurReter.Add("modo_ret", Convert.ToBoolean(ldtReter.Rows[0]["modo_ret"]));
1265  loDicCurReter.Add("tipo_iva", lcTipo_Iva);
1266  loDicCurReter.Add("recargo", llRecargo);
1267 
1268  return loDicCurReter;
1269  }
1270 
1271 
1272  #endregion MÉTODOS PRIVADOS
1273  }
1274 }
override object _Campo(string tcNombreCampo)
Override del metodo _Campo para los mantenimientos
Definition: clsEwBase.cs:3443
Clase Artículo
Definition: articulo.cs:33
Clase documento de venta TPV
Definition: DocVentaTpv.cs:47
virtual void _Control_Label_Retencion(dynamic toFormPare, bool tlHayRetencion, bool tlFiscal=true, decimal tnTpc=0)
Mostrar/ocultar el label/textbox de retención
void _ReleaseQueryCaches()
Al salir del documento eliminar todos los datos de las caches de consultas.
ewMascara()
Crea una nueva instancia de la classe ewMascara.
Definition: clsEwBase.cs:6261
string _TipoIVA
Nos permitirá indicar el código de TIPO DE IVA aplicado a este cliente
decimal _RetencionNoFiscalTPC
Nos permitirá aplicar el % de retención no fiscal que trabaja el cliente En caso que el usuario no ha...
Classe documento Factura de venta
Definition: DocsVentaFra.cs:61
virtual bool _Calcular_Retencion(dynamic toDocumento, out decimal tnImporteRetencion, out decimal tnPorcentajeRetencion, out string tcTipoRetencion)
Devuelve el importe de la retención del documento actual
KeyDiccionarioMascara
Clave para diccionario de máscaras
Classe de negocio para el cálculo de retenciones en documento de venta.
Definition: clsRetencion.cs:38
TipoRetencionVentas
Enumeración para identificar los tipos de retención en ventas
Definition: clsRetencion.cs:23
Proporciona características adicionales de las máscaras de Eurowin
Definition: clsEwBase.cs:6212
eTipoDocumento
Detalle los tipos de documento posibles de ventas y compras
Definition: docsvenenum.cs:32
Classe base dels documents.
Definition: DocsVen.cs:684
bool _Recargo
Nos permitirá asignar si un cliente permite trabajar con retención fiscal
bool _RetencionNoFiscal
Nos permitirá asignar si un cliente permite trabajar con retención fiscal
Interficie de les linies
Definition: DocsVen.cs:907
decimal _Calcular_Retencion(dynamic toDocumento, Dictionary< string, object > toCondicionesRetencion=null)
Devuelve el importe de la retención (fiscal o no fiscal) correspondiente al documento de venta recibi...
virtual void _Control_Label_Retencion(dynamic toFormPare, bool tlHayRetencion, bool? tlSobreBase, bool tlFiscal=true, decimal tnTpc=0)
Mostrar/ocultar el label/textbox de retención
void Dispose()
Este código se agrega para implementar correctamente el patrón descartable.