Advertisement
Guest User

samba pos

a guest
Feb 2nd, 2013
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 33.17 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using NCalc;
  8. using Samba.Domain.Models.Customers;
  9. using Samba.Domain.Models.Menus;
  10. using Samba.Domain.Models.Settings;
  11. using Samba.Domain.Models.Tickets;
  12. using Samba.Infrastructure.Settings;
  13. using Samba.Localization.Properties;
  14. using Samba.Persistance.Data;
  15.  
  16. namespace Samba.Services.Printing
  17. {
  18.     public class TagData
  19.     {
  20.         public TagData(string data, string tag)
  21.         {
  22.             data = ReplaceInBracketValues(data, "\r\n", "<newline>", '[', ']');
  23.  
  24.             data = data.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).Where(x => x.Contains(tag)).FirstOrDefault();
  25.  
  26.             Tag = tag;
  27.             DataString = tag;
  28.             if (string.IsNullOrEmpty(data)) return;
  29.  
  30.             StartPos = data.IndexOf(tag);
  31.             EndPos = StartPos + 1;
  32.  
  33.             while (data[EndPos] != '}') { EndPos++; }
  34.             EndPos++;
  35.             Length = EndPos - StartPos;
  36.  
  37.             DataString = BracketContains(data, '[', ']', Tag) ? GetBracketValue(data, '[', ']') : data.Substring(StartPos, Length);
  38.             DataString = DataString.Replace("<newline>", "\r\n");
  39.             Title = !DataString.StartsWith("[=") ? DataString.Trim('[', ']') : DataString;
  40.             Title = Title.Replace(Tag, "<value>");
  41.             Length = DataString.Length;
  42.             StartPos = data.IndexOf(DataString);
  43.             EndPos = StartPos + Length;
  44.         }
  45.  
  46.         public string DataString { get; set; }
  47.         public string Tag { get; set; }
  48.         public string Title { get; set; }
  49.         public int StartPos { get; set; }
  50.         public int EndPos { get; set; }
  51.         public int Length { get; set; }
  52.  
  53.         public static string ReplaceInBracketValues(string content, string find, string replace, char open, char close)
  54.         {
  55.             var result = content;
  56.             var v1 = GetBracketValue(result, open, close);
  57.             while (!string.IsNullOrEmpty(v1))
  58.             {
  59.                 var value = v1.Replace(find, replace);
  60.                 value = value.Replace(open.ToString(), "<op>");
  61.                 value = value.Replace(close.ToString(), "<cl>");
  62.                 result = result.Replace(v1, value);
  63.                 v1 = GetBracketValue(result, open, close);
  64.             }
  65.             result = result.Replace("<op>", open.ToString());
  66.             result = result.Replace("<cl>", close.ToString());
  67.             return result;
  68.         }
  69.  
  70.         public static bool BracketContains(string content, char open, char close, string testValue)
  71.         {
  72.             if (!content.Contains(open)) return false;
  73.             var br = GetBracketValue(content, open, close);
  74.             return (br.Contains(testValue)) && !br.StartsWith("[=");
  75.         }
  76.  
  77.         public static string GetBracketValue(string content, char open, char close)
  78.         {
  79.             var closePass = 1;
  80.             var start = content.IndexOf(open);
  81.             var end = start;
  82.             if (start > -1)
  83.             {
  84.                 while (end < content.Length - 1 && closePass > 0)
  85.                 {
  86.                     end++;
  87.                     if (content[end] == open && close != open) closePass++;
  88.                     if (content[end] == close) closePass--;
  89.                 }
  90.                 return content.Substring(start, (end - start) + 1);
  91.             }
  92.             return string.Empty;
  93.         }
  94.     }
  95.  
  96.     public static class TicketFormatter
  97.     {
  98.         public static string[] GetFormattedTicket(Ticket ticket, IEnumerable<TicketItem> lines, PrinterTemplate template)
  99.         {
  100.             if (template.MergeLines) lines = MergeLines(lines);
  101.             var orderNo = lines.Count() > 0 ? lines.ElementAt(0).OrderNumber : 0;
  102.             var userNo = lines.Count() > 0 ? lines.ElementAt(0).CreatingUserId : 0;
  103.             var departmentNo = lines.Count() > 0 ? lines.ElementAt(0).DepartmentId : ticket.DepartmentId;
  104.             var header = ReplaceDocumentVars(template.HeaderTemplate, ticket, orderNo, userNo, departmentNo);
  105.             var footer = ReplaceDocumentVars(template.FooterTemplate, ticket, orderNo, userNo, departmentNo);
  106.             var lns = GetFormattedLines(lines, template);
  107.  
  108.             var result = header.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
  109.             result.AddRange(lns);
  110.             result.AddRange(footer.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries));
  111.  
  112.             return result.ToArray();
  113.         }
  114.  
  115.         private static IEnumerable<string> GetFormattedLines(IEnumerable<TicketItem> lines, PrinterTemplate template)
  116.         {
  117.             if (!string.IsNullOrEmpty(template.GroupTemplate))
  118.             {
  119.                 if (template.GroupTemplate.Contains("{PRODUCT GROUP}"))
  120.                 {
  121.                     var groups = lines.GroupBy(GetMenuItemGroup);
  122.                     var result = new List<string>();
  123.                     foreach (var grp in groups)
  124.                     {
  125.                         var grpSep = template.GroupTemplate.Replace("{PRODUCT GROUP}", grp.Key);
  126.                         result.AddRange(grpSep.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries));
  127.                         result.AddRange(grp.SelectMany(x => FormatLines(template, x).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)));
  128.                     }
  129.                     return result;
  130.                 }
  131.  
  132.                 if (template.GroupTemplate.Contains("{PRODUCT TAG}"))
  133.                 {
  134.                     var groups = lines.GroupBy(GetMenuItemTag);
  135.                     var result = new List<string>();
  136.                     foreach (var grp in groups)
  137.                     {
  138.                         var grpSep = template.GroupTemplate.Replace("{PRODUCT TAG}", grp.Key);
  139.                         result.AddRange(grpSep.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries));
  140.                         result.AddRange(grp.SelectMany(x => FormatLines(template, x).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)));
  141.                     }
  142.                     return result;
  143.                 }
  144.  
  145.                 if (template.GroupTemplate.Contains("{ITEM TAG}"))
  146.                 {
  147.                     var groups = lines.GroupBy(x => (x.Tag ?? "").Split('|')[0]);
  148.                     var result = new List<string>();
  149.                     foreach (var grp in groups)
  150.                     {
  151.                         var grpSep = template.GroupTemplate.Replace("{ITEM TAG}", grp.Key);
  152.                         result.AddRange(grpSep.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries));
  153.                         result.AddRange(grp.SelectMany(x => FormatLines(template, x).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)));
  154.                     }
  155.                     return result;
  156.                 }
  157.  
  158.                 if (template.GroupTemplate.Contains("{ORDER NO}"))
  159.                 {
  160.                     var groups = lines.GroupBy(x => x.OrderNumber);
  161.                     var result = new List<string>();
  162.                     foreach (var grp in groups)
  163.                     {
  164.                         var grpSep = template.GroupTemplate.Replace("{ORDER NO}", grp.Key.ToString());
  165.                         result.AddRange(grpSep.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries));
  166.                         result.AddRange(grp.SelectMany(x => FormatLines(template, x).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)));
  167.                     }
  168.                     return result;
  169.                 }
  170.             }
  171.             return lines.SelectMany(x => FormatLines(template, x).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)).ToArray();
  172.         }
  173.  
  174.         private static IEnumerable<TicketItem> MergeLines(IEnumerable<TicketItem> lines)
  175.         {
  176.             var group = lines.Where(x => x.Properties.Count == 0).GroupBy(x => new
  177.                                                 {
  178.                                                     x.MenuItemId,
  179.                                                     x.MenuItemName,
  180.                                                     x.Voided,
  181.                                                     x.Gifted,
  182.                                                     x.Price,
  183.                                                     x.VatIncluded,
  184.                                                     x.VatAmount,
  185.                                                     x.VatTemplateId,
  186.                                                     x.PortionName,
  187.                                                     x.PortionCount,
  188.                                                     x.ReasonId,
  189.                                                     x.CurrencyCode,
  190.                                                     x.Tag
  191.                                                 });
  192.  
  193.             var result = group.Select(x => new TicketItem
  194.                                     {
  195.                                         MenuItemId = x.Key.MenuItemId,
  196.                                         MenuItemName = x.Key.MenuItemName,
  197.                                         ReasonId = x.Key.ReasonId,
  198.                                         Voided = x.Key.Voided,
  199.                                         Gifted = x.Key.Gifted,
  200.                                         Price = x.Key.Price,
  201.                                         VatAmount = x.Key.VatAmount,
  202.                                         VatTemplateId = x.Key.VatTemplateId,
  203.                                         VatIncluded = x.Key.VatIncluded,
  204.                                         CreatedDateTime = x.Last().CreatedDateTime,
  205.                                         CreatingUserId = x.Last().CreatingUserId,
  206.                                         OrderNumber = x.Last().OrderNumber,
  207.                                         TicketId = x.Last().TicketId,
  208.                                         PortionName = x.Key.PortionName,
  209.                                         PortionCount = x.Key.PortionCount,
  210.                                         CurrencyCode = x.Key.CurrencyCode,
  211.                                         Tag = x.Key.Tag,
  212.                                         Quantity = x.Sum(y => y.Quantity)
  213.                                     });
  214.  
  215.             result = result.Union(lines.Where(x => x.Properties.Count > 0)).OrderBy(x => x.CreatedDateTime);
  216.  
  217.             return result;
  218.         }
  219.  
  220.         private static string ReplaceDocumentVars(string document, Ticket ticket, int orderNo, int userNo, int departmentNo)
  221.         {
  222.             string result = document;
  223.             if (string.IsNullOrEmpty(document)) return "";
  224.  
  225.             result = FormatData(result, Resources.TF_TicketDate, () => ticket.Date.ToShortDateString());
  226.             result = FormatData(result, Resources.TF_TicketTime, () => ticket.Date.ToShortTimeString());
  227.             result = FormatData(result, Resources.TF_DayDate, () => DateTime.Now.ToShortDateString());
  228.             result = FormatData(result, Resources.TF_DayTime, () => DateTime.Now.ToShortTimeString());
  229.             result = FormatData(result, Resources.TF_UniqueTicketId, () => ticket.Id.ToString());
  230.             result = FormatData(result, Resources.TF_TicketNumber, () => ticket.TicketNumber);
  231.             result = FormatData(result, Resources.TF_LineOrderNumber, orderNo.ToString);
  232.             result = FormatData(result, Resources.TF_TicketTag, ticket.GetTagData);
  233.             result = FormatDataIf(true, result, "{DEPARTMENT}", () => GetDepartmentName(departmentNo));
  234.  
  235.             var ticketTagPattern = Resources.TF_OptionalTicketTag + "[^}]+}";
  236.  
  237.             while (Regex.IsMatch(result, ticketTagPattern))
  238.             {
  239.                 var value = Regex.Match(result, ticketTagPattern).Groups[0].Value;
  240.                 var tags = "";
  241.                 try
  242.                 {
  243.                     var tag = value.Trim('{', '}').Split(':')[1];
  244.                     tags = tag.Split(',').Aggregate(tags, (current, t) => current +
  245.                         (!string.IsNullOrEmpty(ticket.GetTagValue(t.Trim()))
  246.                         ? (t + ": " + ticket.GetTagValue(t.Trim()) + "\r")
  247.                         : ""));
  248.                     result = FormatData(result.Trim('\r'), value, () => tags);
  249.                 }
  250.                 catch (Exception)
  251.                 {
  252.                     result = FormatData(result, value, () => "");
  253.                 }
  254.             }
  255.  
  256.             const string ticketTag2Pattern = "{TICKETTAG:[^}]+}";
  257.  
  258.             while (Regex.IsMatch(result, ticketTag2Pattern))
  259.             {
  260.                 var value = Regex.Match(result, ticketTag2Pattern).Groups[0].Value;
  261.                 var tag = value.Trim('{', '}').Split(':')[1];
  262.                 var tagValue = ticket.GetTagValue(tag);
  263.                 try
  264.                 {
  265.                     result = FormatData(result, value, () => tagValue);
  266.                 }
  267.                 catch (Exception)
  268.                 {
  269.                     result = FormatData(result, value, () => "");
  270.                 }
  271.             }
  272.  
  273.             var userName = AppServices.MainDataContext.GetUserName(userNo);
  274.  
  275.             var title = ticket.LocationName;
  276.             if (string.IsNullOrEmpty(ticket.LocationName))
  277.                 title = userName;
  278.  
  279.             result = FormatData(result, Resources.TF_TableOrUserName, () => title);
  280.             result = FormatData(result, Resources.TF_UserName, () => userName);
  281.             result = FormatData(result, Resources.TF_TableName, () => ticket.LocationName);
  282.             result = FormatData(result, Resources.TF_TicketNote, () => ticket.Note ?? "");
  283.             result = FormatData(result, Resources.TF_AccountName, () => ticket.CustomerName);
  284.             result = FormatData(result, "{ACC GROUPCODE}", () => ticket.CustomerGroupCode);
  285.  
  286.             if (ticket.CustomerId > 0 && (result.Contains(Resources.TF_AccountAddress) || result.Contains(Resources.TF_AccountPhone) || result.Contains("{ACC NOTE}")))
  287.             {
  288.                 var customer = Dao.SingleWithCache<Customer>(x => x.Id == ticket.CustomerId);
  289.                 result = FormatData(result, Resources.TF_AccountAddress, () => customer.Address);
  290.                 result = FormatData(result, Resources.TF_AccountPhone, () => customer.PhoneNumber);
  291.                 result = FormatData(result, "{ACC NOTE}", () => customer.Note);
  292.             }
  293.  
  294.             if (ticket.CustomerId > 0 && result.Contains("{ACC BALANCE}"))
  295.             {
  296.                 var accBalance = CashService.GetAccountBalance(ticket.CustomerId);
  297.                 result = FormatDataIf(accBalance != 0, result, "{ACC BALANCE}", () => accBalance.ToString("#,#0.00"));
  298.             }
  299.  
  300.             result = RemoveTag(result, Resources.TF_AccountAddress);
  301.             result = RemoveTag(result, Resources.TF_AccountPhone);
  302.  
  303.             var payment = ticket.GetPaymentAmount();
  304.             var remaining = ticket.GetRemainingAmount();
  305.             var discount = ticket.GetDiscountAndRoundingTotal();
  306.             var plainTotal = ticket.GetPlainSum();
  307.             var giftAmount = ticket.GetTotalGiftAmount();
  308.             var vatAmount = GetTaxTotal(ticket.TicketItems, plainTotal, ticket.GetDiscountTotal());
  309.             var taxServicesTotal = ticket.GetTaxServicesTotal();
  310.             var ticketPaymentAmount = ticket.GetPaymentAmount();
  311.  
  312.             result = FormatDataIf(vatAmount > 0 || discount > 0 || taxServicesTotal > 0, result, "{PLAIN TOTAL}", () => plainTotal.ToString("#,#0.00"));
  313.             result = FormatDataIf(discount > 0, result, "{DISCOUNT TOTAL}", () => discount.ToString("#,#0.00"));
  314.             result = FormatDataIf(vatAmount > 0, result, "{TAX TOTAL}", () => vatAmount.ToString("#,#0.00"));
  315.             result = FormatDataIf(taxServicesTotal > 0, result, "{SERVICE TOTAL}", () => taxServicesTotal.ToString("#,#0.00"));
  316.             result = FormatDataIf(vatAmount > 0, result, "{TAX DETAILS}", () => GetTaxDetails(ticket.TicketItems, plainTotal, discount));
  317.             result = FormatDataIf(taxServicesTotal > 0, result, "{SERVICE DETAILS}", () => GetServiceDetails(ticket));
  318.  
  319.             result = FormatDataIf(payment > 0, result, Resources.TF_RemainingAmountIfPaid,
  320.                 () => string.Format(Resources.RemainingAmountIfPaidValue_f, payment.ToString("#,#0.00"), remaining.ToString("#,#0.00")));
  321.  
  322.             result = FormatDataIf(discount > 0, result, Resources.TF_DiscountTotalAndTicketTotal,
  323.                 () => string.Format(Resources.DiscountTotalAndTicketTotalValue_f, (plainTotal).ToString("#,#0.00"), discount.ToString("#,#0.00")));
  324.  
  325.             result = FormatDataIf(giftAmount > 0, result, Resources.TF_GiftTotal, () => giftAmount.ToString("#,#0.00"));
  326.             result = FormatDataIf(discount < 0, result, Resources.TF_IfFlatten, () => string.Format(Resources.IfNegativeDiscountValue_f, discount.ToString("#,#0.00")));
  327.  
  328.             result = FormatData(result, Resources.TF_TicketTotal, () => ticket.GetSum().ToString("#,#0.00"));
  329.  
  330.             result = FormatDataIf(ticketPaymentAmount > 0, result, Resources.TF_TicketPaidTotal, () => ticketPaymentAmount.ToString("#,#0.00"));
  331.             result = FormatData(result, Resources.TF_TicketRemainingAmount, () => ticket.GetRemainingAmount().ToString("#,#0.00"));
  332.  
  333.             result = FormatData(result, "{TOTAL TEXT}", () => HumanFriendlyInteger.CurrencyToWritten(ticket.GetSum()));
  334.             result = FormatData(result, "{TOTALTEXT}", () => HumanFriendlyInteger.CurrencyToWritten(ticket.GetSum(), true));
  335.  
  336.             result = UpdateGlobalValues(result);
  337.  
  338.             return result;
  339.         }
  340.  
  341.         private static string UpdateGlobalValues(string data)
  342.         {
  343.             data = UpdateSettings(data);
  344.             data = UpdateExpressions(data);
  345.  
  346.             return data;
  347.         }
  348.  
  349.         private static string UpdateSettings(string result)
  350.         {
  351.             while (Regex.IsMatch(result, "{SETTING:[^}]+}", RegexOptions.Singleline))
  352.             {
  353.                 var match = Regex.Match(result, "{SETTING:([^}]+)}");
  354.                 var tagName = match.Groups[0].Value;
  355.                 var settingName = match.Groups[1].Value;
  356.                 var tagData = new TagData(result, tagName);
  357.                 var value = !string.IsNullOrEmpty(settingName) ? AppServices.SettingService.ReadSetting(settingName).StringValue : "";
  358.                 var replace = !string.IsNullOrEmpty(value) ? tagData.Title.Replace("<value>", value) : "";
  359.                 result = result.Replace(tagData.DataString, replace);
  360.             }
  361.             return result;
  362.         }
  363.  
  364.         private static string UpdateExpressions(string data)
  365.         {
  366.             while (Regex.IsMatch(data, "\\[=[^\\]]+\\]", RegexOptions.Singleline))
  367.             {
  368.                 var match = Regex.Match(data, "\\[=([^\\]]+)\\]");
  369.                 var tag = match.Groups[0].Value;
  370.                 var expression = match.Groups[1].Value;
  371.                 var e = new Expression(expression);
  372.                 e.EvaluateFunction += delegate(string name, FunctionArgs args)
  373.                                           {
  374.                                               if (name == "Format" || name == "F")
  375.                                               {
  376.                                                   var fmt = args.Parameters.Length > 1
  377.                                                                 ? args.Parameters[1].Evaluate().ToString()
  378.                                                                 : "#,#0.00";
  379.                                                   args.Result = ((double)args.Parameters[0].Evaluate()).ToString(fmt);
  380.                                               }
  381.                                               if (name == "ToNumber" || name == "TN")
  382.                                               {
  383.                                                   double d;
  384.                                                   double.TryParse(args.Parameters[0].Evaluate().ToString(), NumberStyles.Any, CultureInfo.CurrentCulture, out d);
  385.                                                   args.Result = d;
  386.                                               }
  387.                                           };
  388.                 string result;
  389.                 try
  390.                 {
  391.                     result = e.Evaluate().ToString();
  392.                 }
  393.                 catch (EvaluationException)
  394.                 {
  395.                     result = "";
  396.                 }
  397.  
  398.                 data = data.Replace(tag, result);
  399.             }
  400.  
  401.             return data;
  402.         }
  403.  
  404.         private static string GetDepartmentName(int departmentId)
  405.         {
  406.             var dep = AppServices.MainDataContext.Departments.SingleOrDefault(x => x.Id == departmentId);
  407.             return dep != null ? dep.Name : Resources.UndefinedWithBrackets;
  408.         }
  409.  
  410.         private static string GetServiceDetails(Ticket ticket)
  411.         {
  412.             var sb = new StringBuilder();
  413.             foreach (var taxService in ticket.TaxServices)
  414.             {
  415.                 var service = taxService;
  416.                 var ts = AppServices.MainDataContext.TaxServiceTemplates.FirstOrDefault(x => x.Id == service.TaxServiceId);
  417.                 var tsTitle = ts != null ? ts.Name : Resources.UndefinedWithBrackets;
  418.                 sb.AppendLine("<J>" + tsTitle + ":|" + service.CalculationAmount.ToString("#,#0.00"));
  419.             }
  420.             return string.Join("\r", sb);
  421.         }
  422.  
  423.         private static string GetTaxDetails(IEnumerable<TicketItem> ticketItems, decimal plainSum, decimal discount)
  424.         {
  425.             var sb = new StringBuilder();
  426.             var groups = ticketItems.Where(x => x.VatTemplateId > 0).GroupBy(x => x.VatTemplateId);
  427.             foreach (var @group in groups)
  428.             {
  429.                 var iGroup = @group;
  430.                 var tb = AppServices.MainDataContext.VatTemplates.FirstOrDefault(x => x.Id == iGroup.Key);
  431.                 var tbTitle = tb != null ? tb.Name : Resources.UndefinedWithBrackets;
  432.                 var total = @group.Sum(x => x.GetTotalVatAmount());
  433.                 if (discount > 0)
  434.                 {
  435.                     total -= (total * discount) / plainSum;
  436.                 }
  437.                 if (total > 0) sb.AppendLine("<J>" + tbTitle + ":|" + total.ToString("#,#0.00"));
  438.             }
  439.             return string.Join("\r", sb);
  440.         }
  441.  
  442.         private static decimal GetTaxTotal(IEnumerable<TicketItem> ticketItems, decimal plainSum, decimal discount)
  443.         {
  444.             var result = ticketItems.Sum(x => x.GetTotalVatAmount());
  445.             if (discount > 0)
  446.             {
  447.                 result -= (result * discount) / plainSum;
  448.             }
  449.             return result;
  450.         }
  451.  
  452.         private static string FormatData(string data, string tag, Func<string> valueFunc)
  453.         {
  454.             if (!data.Contains(tag)) return data;
  455.  
  456.             var i = 0;
  457.             while (data.Contains(tag) && i < 99)
  458.             {
  459.                 var value = valueFunc.Invoke();
  460.                 var tagData = new TagData(data, tag);
  461.                 if (!string.IsNullOrEmpty(value)) value =
  462.                     !string.IsNullOrEmpty(tagData.Title) && tagData.Title.Contains("<value>")
  463.                     ? tagData.Title.Replace("<value>", value)
  464.                     : tagData.Title + value;
  465.                 var spos = data.IndexOf(tagData.DataString);
  466.                 data = data.Remove(spos, tagData.Length).Insert(spos, value ?? "");
  467.                 i++;
  468.             }
  469.             return data;
  470.         }
  471.  
  472.         private static string FormatDataIf(bool condition, string data, string tag, Func<string> valueFunc)
  473.         {
  474.             if (condition && data.Contains(tag))
  475.             {
  476.                 Func<string> value = valueFunc.Invoke;
  477.                 data = FormatData(data, tag, value);
  478.                 return data;
  479.             }
  480.             return RemoveTag(data, tag);
  481.         }
  482.  
  483.         private static string RemoveTag(string data, string tag)
  484.         {
  485.             var i = 0;
  486.             while (data.Contains(tag) && i < 99)
  487.             {
  488.                 var tagData = new TagData(data, tag);
  489.                 var spos = data.IndexOf(tagData.DataString);
  490.                 data = data.Remove(spos, tagData.Length);
  491.                 i++;
  492.             }
  493.             return data;
  494.         }
  495.  
  496.         private static string FormatLines(PrinterTemplate template, TicketItem ticketItem)
  497.         {
  498.             if (ticketItem.Gifted)
  499.             {
  500.                 if (!string.IsNullOrEmpty(template.GiftLineTemplate))
  501.                 {
  502.                     return template.GiftLineTemplate.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
  503.                         .Aggregate("", (current, s) => current + ReplaceLineVars(s, ticketItem));
  504.                 }
  505.                 return "";
  506.             }
  507.  
  508.             if (ticketItem.Voided)
  509.             {
  510.                 if (!string.IsNullOrEmpty(template.VoidedLineTemplate))
  511.                 {
  512.                     return template.VoidedLineTemplate.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
  513.                         .Aggregate("", (current, s) => current + ReplaceLineVars(s, ticketItem));
  514.                 }
  515.                 return "";
  516.             }
  517.  
  518.             if (!string.IsNullOrEmpty(template.LineTemplate))
  519.                 return template.LineTemplate.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
  520.                     .Aggregate("", (current, s) => current + ReplaceLineVars(s, ticketItem));
  521.             return "";
  522.         }
  523.  
  524.         private static string ReplaceLineVars(string line, TicketItem ticketItem)
  525.         {
  526.             string result = line;
  527.  
  528.             if (ticketItem != null)
  529.             {
  530.                 result = FormatData(result, Resources.TF_LineItemQuantity, () => ticketItem.Quantity.ToString("#,#0.##"));
  531.                 result = FormatData(result, Resources.TF_LineItemName, () => ticketItem.MenuItemName + ticketItem.GetPortionDesc());
  532.                 result = FormatData(result, Resources.TF_LineItemPrice, () => ticketItem.Price.ToString("#,#0.00"));
  533.                 result = FormatData(result, Resources.TF_LineItemTotal, () => ticketItem.GetItemPrice().ToString("#,#0.00"));
  534.                 result = FormatData(result, Resources.TF_LineItemTotalAndQuantity, () => ticketItem.GetItemValue().ToString("#,#0.00"));
  535.                 result = FormatData(result, Resources.TF_LineItemPriceCents, () => (ticketItem.Price * 100).ToString("#,##"));
  536.                 result = FormatData(result, Resources.TF_LineItemTotalWithoutGifts, () => ticketItem.GetTotal().ToString("#,#0.00"));
  537.                 result = FormatData(result, Resources.TF_LineOrderNumber, () => ticketItem.OrderNumber.ToString());
  538.                 result = FormatData(result, Resources.TF_LineGiftOrVoidReason, () => AppServices.MainDataContext.GetReason(ticketItem.ReasonId));
  539.                 result = FormatData(result, "{MENU ITEM GROUP}", () => GetMenuItemGroup(ticketItem));
  540.                 result = FormatData(result, "{MENU ITEM TAG}", () => GetMenuItemTag(ticketItem));
  541.                 result = FormatData(result, "{PRICE TAG}", () => ticketItem.PriceTag);
  542.                 result = FormatData(result, "{ITEM TAG}", () => ticketItem.Tag);
  543.  
  544.                 while (Regex.IsMatch(result, "{ITEM TAG:[^}]+}", RegexOptions.Singleline))
  545.                 {
  546.                     var tags = ticketItem.Tag.Split('|');
  547.                     var match = Regex.Match(result, "{ITEM TAG:([^}]+)}");
  548.                     var tagName = match.Groups[0].Value;
  549.                     int index;
  550.                     int.TryParse(match.Groups[1].Value, out index);
  551.                     var value = tags.Count() > index ? tags[index].Trim() : "";
  552.                     result = result.Replace(tagName, value);
  553.                 }
  554.  
  555.                 if (result.Contains(Resources.TF_LineItemDetails.Substring(0, Resources.TF_LineItemDetails.Length - 1)))
  556.                 {
  557.                     string lineFormat = result;
  558.                     if (ticketItem.Properties.Count > 0)
  559.                     {
  560.                         string label = "";
  561.                         foreach (var property in ticketItem.Properties)
  562.                         {
  563.                             var itemProperty = property;
  564.                             var lineValue = FormatData(lineFormat, Resources.TF_LineItemDetails, () => itemProperty.Name);
  565.                             lineValue = FormatData(lineValue, Resources.TF_LineItemDetailQuantity, () => itemProperty.Quantity.ToString("#.##"));
  566.                             lineValue = FormatData(lineValue, Resources.TF_LineItemDetailPrice, () => itemProperty.CalculateWithParentPrice ? "" : itemProperty.PropertyPrice.Amount.ToString("#,#0.00"));
  567.                             label += lineValue + "\r\n";
  568.                         }
  569.                         result = "\r\n" + label;
  570.                     }
  571.                     else result = "";
  572.                 }
  573.  
  574.                 result = UpdateGlobalValues(result);
  575.                 result = result.Replace("<", "\r\n<");
  576.             }
  577.             return result;
  578.         }
  579.  
  580.         private static string GetMenuItemGroup(TicketItem ticketItem)
  581.         {
  582.             return Dao.SingleWithCache<MenuItem>(x => x.Id == ticketItem.MenuItemId).GroupCode;
  583.         }
  584.  
  585.         private static string GetMenuItemTag(TicketItem ticketItem)
  586.         {
  587.             var result = Dao.SingleWithCache<MenuItem>(x => x.Id == ticketItem.MenuItemId).Tag;
  588.             if (string.IsNullOrEmpty(result)) result = ticketItem.MenuItemName;
  589.             return result;
  590.         }
  591.     }
  592.  
  593.     public static class HumanFriendlyInteger
  594.     {
  595.         static readonly string[] Ones = new[] { "", Resources.One, Resources.Two, Resources.Three, Resources.Four, Resources.Five, Resources.Six, Resources.Seven, Resources.Eight, Resources.Nine };
  596.         static readonly string[] Teens = new[] { Resources.Ten, Resources.Eleven, Resources.Twelve, Resources.Thirteen, Resources.Fourteen, Resources.Fifteen, Resources.Sixteen, Resources.Seventeen, Resources.Eighteen, Resources.Nineteen };
  597.         static readonly string[] Tens = new[] { Resources.Twenty, Resources.Thirty, Resources.Forty, Resources.Fifty, Resources.Sixty, Resources.Seventy, Resources.Eighty, Resources.Ninety };
  598.         static readonly string[] ThousandsGroups = { "", " " + Resources.Thousand, " " + Resources.Million, " " + Resources.Billion };
  599.  
  600.         private static string FriendlyInteger(int n, string leftDigits, int thousands)
  601.         {
  602.             if (n == 0)
  603.             {
  604.                 return leftDigits;
  605.             }
  606.             string friendlyInt = leftDigits;
  607.             if (friendlyInt.Length > 0)
  608.             {
  609.                 friendlyInt += " ";
  610.             }
  611.             if (n < 10)
  612.             {
  613.                 friendlyInt += Ones[n];
  614.             }
  615.             else if (n < 20)
  616.             {
  617.                 friendlyInt += Teens[n - 10];
  618.             }
  619.             else if (n < 100)
  620.             {
  621.                 friendlyInt += FriendlyInteger(n % 10, Tens[n / 10 - 2], 0);
  622.             }
  623.             else if (n < 1000)
  624.             {
  625.                 var t = Ones[n / 100] + " " + Resources.Hundred;
  626.                 if (n / 100 == 1) t = Resources.OneHundred;
  627.                 friendlyInt += FriendlyInteger(n % 100, t, 0);
  628.             }
  629.             else if (n < 10000 && thousands == 0)
  630.             {
  631.                 var t = Ones[n / 1000] + " " + Resources.Thousand;
  632.                 if (n / 1000 == 1) t = Resources.OneThousand;
  633.                 friendlyInt += FriendlyInteger(n % 1000, t, 0);
  634.             }
  635.             else
  636.             {
  637.                 friendlyInt += FriendlyInteger(n % 1000, FriendlyInteger(n / 1000, "", thousands + 1), 0);
  638.             }
  639.  
  640.             return friendlyInt + ThousandsGroups[thousands];
  641.         }
  642.  
  643.         public static string CurrencyToWritten(decimal d, bool upper = false)
  644.         {
  645.             var result = "";
  646.             var fraction = d - Math.Floor(d);
  647.             var value = d - fraction;
  648.             if (value > 0)
  649.             {
  650.                 var start = IntegerToWritten(Convert.ToInt32(value));
  651.                 if (upper) start = start.Replace(" ", "").ToUpper();
  652.                 result += string.Format("{0} {1} ", start, LocalSettings.MajorCurrencyName + GetPlural(value));
  653.             }
  654.  
  655.             if (fraction > 0)
  656.             {
  657.                 var end = IntegerToWritten(Convert.ToInt32(fraction * 100));
  658.                 if (upper) end = end.Replace(" ", "").ToUpper();
  659.                 result += string.Format("{0} {1} ", end, LocalSettings.MinorCurrencyName + GetPlural(fraction));
  660.             }
  661.             return result.Replace("  ", " ").Trim();
  662.         }
  663.  
  664.         private static string GetPlural(decimal number)
  665.         {
  666.             return number == 1 ? "" : LocalSettings.PluralCurrencySuffix;
  667.         }
  668.  
  669.         public static string IntegerToWritten(int n)
  670.         {
  671.             if (n == 0)
  672.             {
  673.                 return Resources.Zero;
  674.             }
  675.             if (n < 0)
  676.             {
  677.                 return Resources.Negative + " " + IntegerToWritten(-n);
  678.             }
  679.  
  680.             return FriendlyInteger(n, "", 0);
  681.         }
  682.  
  683.     }
  684. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement