diff --git a/ENI2/Controls/EasyPeasyControl.xaml.cs b/ENI2/Controls/EasyPeasyControl.xaml.cs index f672e70e..0b1380de 100644 --- a/ENI2/Controls/EasyPeasyControl.xaml.cs +++ b/ENI2/Controls/EasyPeasyControl.xaml.cs @@ -6,7 +6,10 @@ using bsmd.database.EasyPeasy; using ENI2.Util; using Microsoft.Win32; using System; +using System.Collections.ObjectModel; +using System.Globalization; using System.IO; +using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; @@ -42,7 +45,10 @@ namespace ENI2.Controls private void buttonClear_Click(object sender, RoutedEventArgs e) { - this._vm = EasyPeasyState.CreateDefault(); + this._vm = EasyPeasyState.CreateDefault(); + if (_vm.ProofInformationT2LT2LF?.GoodsShipmentForT2LT2LF?.GoodsItemsForT2LT2LF == null) + _vm.ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.GoodsItemsForT2LT2LF = new ObservableCollection(); + this.DataContext = this._vm; } @@ -99,6 +105,11 @@ namespace ENI2.Controls { var ser = new XmlSerializer(typeof(ProofRequest)); _vm = (ProofRequest)ser.Deserialize(fs); + // after loading/creating _vm + if (_vm.ProofInformationT2LT2LF?.GoodsShipmentForT2LT2LF?.GoodsItemsForT2LT2LF == null) + _vm.ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.GoodsItemsForT2LT2LF = new ObservableCollection(); + + this.DataContext = _vm; } } @@ -142,7 +153,9 @@ namespace ENI2.Controls if (Clipboard.ContainsText()) { var text = Clipboard.GetText(); - PasteGoodsItems(text); + + if(!TryPaste_EspHsPkgsGross(text)) + PasteGoodsItems(text); e.Handled = true; } } @@ -200,6 +213,121 @@ namespace ENI2.Controls return res.ToArray(); } + private bool TryPaste_EspHsPkgsGross(string text) + { + if (_vm?.ProofInformationT2LT2LF?.GoodsShipmentForT2LT2LF == null) return false; + + // Normalize and split lines + var lines = text.Replace("\r\n", "\n").Replace('\r', '\n') + .Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + if (lines.Length == 0) return false; + + // Determine next item number + var list = _vm.ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.GoodsItemsForT2LT2LF; + int nextItemNo = list.Any() ? list.Max(x => x.GoodsItemNumber) + 1 : 1; + + bool anyAdded = false; + bool countrySeen = false; + + foreach (var raw in lines) + { + var line = raw; // do not Trim() entirely; keep leading tab as empty first cell + var cells = line.Split('\t'); // keeps empty entries + + // Expected: + // - 4 cells: [ESP or ""], [HS], [Pkgs], [Gross] + // - 3 cells: [HS], [Pkgs], [Gross] + string hs = null, pkgs = null, gross = null; + + if (cells.Length >= 4) + { + string c0 = cells[0]?.Trim(); + // Optionally capture the first token like "ESP" (country tag), + // only once and only if alphabetic (won't throw if numeric) + if (!countrySeen && !string.IsNullOrWhiteSpace(c0) && c0.All(ch => char.IsLetter(ch))) + { + // If you decide later this should set a field, uncomment: + // if (string.IsNullOrWhiteSpace(_vm.Country)) _vm.Country = c0; + countrySeen = true; + } + + hs = (cells.Length > 1 ? cells[1] : null); + pkgs = (cells.Length > 2 ? cells[2] : null); + gross = (cells.Length > 3 ? cells[3] : null); + } + else if (cells.Length == 3) + { + hs = cells[0]; + pkgs = cells[1]; + gross = cells[2]; + } + else + { + // Not enough data for this format; skip the row + continue; + } + + if (string.IsNullOrWhiteSpace(hs)) continue; + + var item = new GoodsItemForT2LT2LF + { + GoodsItemNumber = nextItemNo++, + DescriptionOfGoods = "" // per spec + }; + item.Commodity.HarmonizedSystemSubHeadingCode = hs.Trim(); + + if (TryParseIntFlexible(pkgs, out var pk)) + item.Packaging.NumberOfPackages = pk; + + if (TryParseDecimalFlexible(gross, out var g)) + { + item.GoodsMeasure.GrossMass = g; + var net = g - 1m; + if (net < 0m) net = 0m; + item.GoodsMeasure.NetMass = net; + } + + list.Add(item); + anyAdded = true; + } + + return anyAdded; + } + + + + #endregion + + #region static utils + + // this will go somewhere else later + + // Try parse decimal with current culture, invariant, and comma/dot flip + private static bool TryParseDecimalFlexible(string s, out decimal value) + { + s = (s ?? "").Trim(); + // 1) current culture + if (decimal.TryParse(s, NumberStyles.Number, CultureInfo.CurrentCulture, out value)) return true; + // 2) invariant + if (decimal.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out value)) return true; + // 3) flip comma/dot and retry (helps when clipboard mixes locales) + string flipped = s.Contains(",") ? s.Replace(",", ".") : s.Replace(".", ","); + if (decimal.TryParse(flipped, NumberStyles.Number, CultureInfo.CurrentCulture, out value)) return true; + if (decimal.TryParse(flipped, NumberStyles.Number, CultureInfo.InvariantCulture, out value)) return true; + value = 0m; + return false; + } + + private static bool TryParseIntFlexible(string s, out int value) + { + s = (s ?? "").Trim(); + // Extract leading integer if something like "12 pcs" + var digits = new string(s.TakeWhile(ch => char.IsDigit(ch) || ch == '-' || ch == '+').ToArray()); + if (string.IsNullOrEmpty(digits)) digits = s; + return int.TryParse(digits, NumberStyles.Integer, CultureInfo.CurrentCulture, out value) + || int.TryParse(digits, NumberStyles.Integer, CultureInfo.InvariantCulture, out value); + } + #endregion } diff --git a/bsmd.database/EasyPeasy.cs b/bsmd.database/EasyPeasy.cs index a499a78e..2138de05 100644 --- a/bsmd.database/EasyPeasy.cs +++ b/bsmd.database/EasyPeasy.cs @@ -2,7 +2,7 @@ // Description: Collection of classes for the customs XML upload app using System; -using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Xml.Serialization; namespace bsmd.database.EasyPeasy @@ -44,7 +44,7 @@ namespace bsmd.database.EasyPeasy public LocationOfGoods LocationOfGoods { get; set; } [XmlElement("GoodsItemsForT2LT2LF")] - public List GoodsItemsForT2LT2LF { get; set; } = new List(); + public ObservableCollection GoodsItemsForT2LT2LF { get; set; } = new ObservableCollection(); public TransportDocuments TransportDocuments { get; set; } } @@ -88,4 +88,5 @@ namespace bsmd.database.EasyPeasy public string Type { get; set; } public string ReferenceNumber { get; set; } } + }