using MisIngredientesVue.Core.Services; using Newtonsoft.Json; using QRCoder; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Xml.Serialization; namespace MisIngredientesVue.Core.Models { public class Cfdi : RepositoryEntityWithTenantId { //Folio fiscal [Required] [JsonIgnore] [IgnoreRelationship] public string Uuid { get { if (!string.IsNullOrEmpty(_uuid)) return _uuid; if (Xml != null && Xml.Complemento?.Any?.Length > 0) _uuid = Xml.Complemento.Any[0].Attributes["UUID"]?.Value; if (string.IsNullOrEmpty(_uuid)) { try { _uuid = XmlAsString.Substring(XmlAsString.IndexOf("UUID=\"") + 6); _uuid = _uuid.Substring(0, _uuid.IndexOf("\"")); } catch { } } if (!string.IsNullOrEmpty(_uuid)) return _uuid; return "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; } set { _uuid = value; if (Xml != null && Xml.Complemento != null && Xml.Complemento.Any.Length > 0) Xml.Complemento.Any[0].Attributes["UUID"].Value = _uuid; } } private string _uuid = string.Empty; [Display(Name = "RFC")] [ScaffoldColumn(false)] public string Rfc { get; set; } [NotMapped] public string QrCode { get { var integer = Total.ToString(); var mantissa = "0"; if (integer.Contains(".")) { mantissa = integer.Split('.')[1]; integer = integer.Split('.')[0]; } return Convert.ToBase64String(Utils.WriteQRCode(string.Format("?re={0}&rr={1}&tt={2}.{3}&id={4}", Xml?.Emisor?.Rfc, Xml?.Receptor?.Rfc, integer.PadLeft(10, '0'), mantissa.PadRight(6, '0'), Uuid ))); } } //Permite llevar la cuenta de las versiones, cuando se cancela una factura se genera una nueva versión [ScaffoldColumn(false)] public string Version { get; set; } public string FormaPago { get; set; } public string MetodoPago { get; set; } [Display(Name = "Serie")] [NotMapped] public string Serie { get { if (Xml != null) _serie = Xml.Serie; return _serie; } set { _serie = value; if (Xml != null) Xml.Serie = _serie; } } private string _serie; [Display(Name = "Folio")] public string Folio { get { if (Xml != null) _folio = Xml.Folio; return _folio; } set { _folio = value; if (Xml != null) Xml.Folio = _folio; } } private string _folio; [Required] [JsonIgnore] [NotMapped] public string XmlAsString { get; set; } [ScaffoldColumn(false)] [JsonIgnore] [NotMapped] public Comprobante Xml { get { if (__xml == null) { if (!string.IsNullOrEmpty(XmlAsString)) { __xml = Utils.DeserializeObjectFromXmlString(XmlAsString); } } return __xml; } set { __xml = value; } } private Comprobante __xml; [ScaffoldColumn(false)] [JsonIgnore] public string CadenaOriginalComplementoCertificacion { get; set; } [ScaffoldColumn(false)] [JsonIgnore] [NotMapped] public string SelloSat { get { if (Xml != null && Xml.Complemento?.Any?.Length > 0) { var selloSATVal = Xml.Complemento.Any[0].Attributes["SelloSAT"] != null ? Xml.Complemento.Any[0].Attributes["SelloSAT"]?.Value : Xml.Complemento.Any[0].Attributes["selloSAT"]?.Value; if (string.IsNullOrEmpty(selloSATVal)) { try { selloSATVal = XmlAsString.Substring(XmlAsString.IndexOf("SelloSAT=\"") + 10); selloSATVal = selloSATVal.Substring(0, selloSATVal.IndexOf("\"")); } catch { } } return selloSATVal; } return @"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; } } //Sello del CFDI [ScaffoldColumn(false)] [JsonIgnore] [NotMapped] public string SelloCfdi { get { if (Xml != null && Xml.Complemento?.Any?.Length > 0) { var selloCfdVal = Xml.Complemento.Any[0].Attributes["SelloCFD"] != null ? Xml.Complemento.Any[0].Attributes["SelloCFD"]?.Value : Xml.Complemento.Any[0].Attributes["selloCFD"]?.Value; if (string.IsNullOrEmpty(selloCfdVal)) { try { selloCfdVal = XmlAsString.Substring(XmlAsString.IndexOf("SelloCFD=\"") + 10); selloCfdVal = selloCfdVal.Substring(0, selloCfdVal.IndexOf("\"")); } catch { } } return selloCfdVal; } return @"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; } } //No. Certificado del SAT [ScaffoldColumn(false)] [JsonIgnore] [NotMapped] public string NoCertificadoSat { get { if (Xml != null && Xml.Complemento?.Any?.Length > 0) { var certificadoSAT = Xml.Complemento.Any[0].Attributes["NoCertificadoSAT"] != null ? Xml.Complemento.Any[0].Attributes["NoCertificadoSAT"]?.Value : Xml.Complemento.Any[0].Attributes["noCertificadoSAT"]?.Value; if (string.IsNullOrEmpty(certificadoSAT)) { try { certificadoSAT = XmlAsString.Substring(XmlAsString.IndexOf("NoCertificadoSAT=\"") + 18); certificadoSAT = certificadoSAT.Substring(0, certificadoSAT.IndexOf("\"")); } catch { } } return certificadoSAT; } return "XXXXXXXXXXXXXXXXXXXX"; } } //Fecha y Hora de certificación [ScaffoldColumn(false)] [JsonIgnore] [NotMapped] public string FechaTimbrado { get { if (Xml != null && Xml.Complemento?.Any?.Length > 0) { var fechaTimbrado = Xml.Complemento.Any[0].Attributes["FechaTimbrado"] != null ? Xml.Complemento.Any[0].Attributes["FechaTimbrado"]?.Value : Xml.Complemento.Any[0].Attributes["fechaTimbrado"]?.Value; if (string.IsNullOrEmpty(fechaTimbrado)) { try { fechaTimbrado = XmlAsString.Substring(XmlAsString.IndexOf("FechaTimbrado=\"") + 15); fechaTimbrado = fechaTimbrado.Substring(0, fechaTimbrado.IndexOf("\"")); } catch { } } return fechaTimbrado; } return "XXXX-XX-XXTXX:XX:XX"; } } [DataType(DataType.Currency)] [Display(Name = "Subtotal")] [ScaffoldColumn(false)] public int Subtotal { get; set; } [DataType(DataType.Currency)] [Display(Name = "Total")] [ScaffoldColumn(false)] public int Total { get; set; } [Display(Name = "Comentarios")] public string Comments { get; set; } [NotMapped] public string LogoBase64 { get; set; } public List Orders { get; set; } public bool CanAddPayment { get { return FormaPago == "99" && MetodoPago == "PPD"; } } public Pagos Pagos { get { if (_pagos != null) return _pagos; if (Xml != null && Xml.Complemento != null && Xml.Complemento.Any.Length > 0) { foreach (var complemento in Xml.Complemento.Any) { if (complemento.Name == "Pagos" || complemento.Name.EndsWith(":Pagos")) { _pagos = Utils.DeserializeObjectFromXmlString(complemento.OuterXml); return _pagos; } } } return null; } } private Pagos _pagos = null; [NotMapped] public bool ShowPromissoryNote { get; set; } } public class Utf8StringWriter : StringWriter { public override Encoding Encoding { get { return Encoding.UTF8; } } } public class Utils { public static byte[] WriteQRCode(string content) { using (var memStream = new MemoryStream()) { var qrGenerator = new QRCodeGenerator(); var qrCodeData = qrGenerator.CreateQrCode(content, QRCodeGenerator.ECCLevel.Q); QRCode qrCode = new QRCode(qrCodeData); Bitmap qrCodeImage = qrCode.GetGraphic(20); qrCodeImage.Save(memStream, ImageFormat.Png); return memStream.ToArray(); } //var converter = new ImageConverter(); //return (byte[])converter.ConvertTo(qrCodeImage, typeof(byte[])); //var writer = new ZXing.BarcodeWriter //{ // Format = BarcodeFormat.QR_CODE, // Options = new QrCodeEncodingOptions // { // Width = 100, // Height = 100, // } //}; //var qrCodeImage = writer.Write(content); //var converter = new ImageConverter(); //return (byte[])converter.ConvertTo(qrCodeImage, typeof(byte[])); } public static string AddSpacesToString(string str, int everyNCharacters) { if (string.IsNullOrEmpty(str)) return str; var totalCounter = everyNCharacters; while (totalCounter < str.Length) { str = str.Insert(totalCounter, " "); totalCounter += everyNCharacters + 1; } return str; } public static string CurrencyToWords(decimal? c) { if (c == null) return "---"; var cs = "" + c; if (!cs.Contains(".")) return NumberToWords((int)c).Trim() + " 00/100"; else { var dec = cs.Split('.')[1]; if (dec.Length == 1) dec += "0"; if (dec.Length > 2) dec = dec.Substring(0, 2); return NumberToWords(Convert.ToInt32(cs.Split('.')[0])) + " " + dec.PadLeft(2, '0') + "/100"; } } public static string NumberToWords(int number) { if (number == 0) return "CERO"; if (number < 0) return "MENOS " + NumberToWords(Math.Abs(number)); string words = ""; if ((number / 1000000) > 0) { if (number >= 2000000) words += NumberToWords(number / 1000000) + " MILLONES "; else words += NumberToWords(number / 1000000) + " MILLÓN "; number %= 1000000; } if ((number / 1000) > 0) { var thousands = NumberToWords(number / 1000) + " MIL "; if (thousands.StartsWith("UN MIL")) thousands = "MIL "; words += thousands; number %= 1000; } if ((number / 100) > 0) { var hundreds = ""; if (number == 100) hundreds = "CIEN "; else if (number > 100 && number < 200) hundreds = "CIENTO "; else if (number >= 500 && number < 600) hundreds = "QUINIENTOS "; else if (number >= 700 && number < 800) hundreds = "SETECIENTOS "; else if (number >= 900 && number < 1000) hundreds = "NOVECIENTOS "; else hundreds = NumberToWords(number / 100) + "CIENTOS "; words += hundreds; number %= 100; } if (number > 0) { if (words != "" && !words.EndsWith("CIENTO ") && !words.EndsWith("IENTOS ") && !words.EndsWith("MIL ") && !words.EndsWith("MILLÓN ") && !words.EndsWith("MILLONES ")) words += "Y "; var unitsMap = new[] { "CERO", "UN", "DOS", "TRES", "CUATRO", "CINCO", "SEIS", "SIETE", "OCHO", "NUEVE", "DIEZ", "ONCE", "DOCE", "TRECE", "CATORCE", "QUINCE", "DIECISÉIS", "DIECISIETE", "DIECIOCHO", "DIECINUEVE", "VEINTE", "VEINTIÚN", "VEINTIDÓS", "VEINTITRÉS", "VEINTICUATRO", "VEINTICINCO", "VEINTISÉIS", "VEINTISIETE", "VEINTIOCHO", "VEINTINUEVE" }; var tensMap = new[] { "CERO", "DIEZ", "VEINTE", "TREINTA", "CUARENTA", "CINCUENTA", "SESENTA", "SETENTA", "OCHENTA", "NOVENTA" }; if (number < 30) words += unitsMap[number]; else { words += tensMap[number / 10]; if ((number % 10) > 0) words += " Y " + unitsMap[number % 10]; } } return words; } public static T DeserializeObjectFromXmlString(string xml) { using (var stringReader = new System.IO.StringReader(xml)) { using (System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(stringReader)) { var xmlSerializer = new XmlSerializer(typeof(T)); return (T)Convert.ChangeType(xmlSerializer.Deserialize(xmlReader), typeof(T)); } } } public static string SerializeObjectToXmlString(T obj, XmlSerializerNamespaces ns) { string result = string.Empty; using (System.IO.StringWriter stringWriter = new Utf8StringWriter()) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); if (ns != null) xmlSerializer.Serialize(stringWriter, obj, ns); else xmlSerializer.Serialize(stringWriter, obj); result = stringWriter.ToString(); } return result; } public static string RemoveWhiteSpacesFromXmlString(string xml) { var doc = new System.Xml.XmlDocument(); doc.PreserveWhitespace = false; doc.LoadXml(xml); return doc.InnerXml; } } }