Simpler erster ChatGPT Wurf :-)

This commit is contained in:
Daniel Schick 2025-09-10 15:29:32 +02:00
parent 5bd3199d1a
commit f1d7543240
10 changed files with 356 additions and 22 deletions

View File

@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ENI2.Controls"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
d:DesignHeight="650" d:DesignWidth="800" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded">
<DockPanel>
@ -23,19 +23,19 @@
<!-- Top-level fields -->
<UniformGrid Columns="4" Rows="3" Margin="0,0,0,12">
<TextBlock Text="DelegateIdentificationType" />
<TextBox Text="{Binding DelegateIdentificationType, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding DelegateIdentificationType, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="TraderIdentificationType" />
<TextBox Text="{Binding TraderIdentificationType, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding TraderIdentificationType, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="LRN" />
<TextBox Text="{Binding LRN, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding LRN, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="TraderIdentificationNumber" />
<TextBox Text="{Binding TraderIdentificationNumber, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding TraderIdentificationNumber, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="Country" />
<TextBox Text="{Binding Country, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Country, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="DelegateIdentificationNumber" />
<TextBox Text="{Binding DelegateIdentificationNumber, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding DelegateIdentificationNumber, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
</UniformGrid>
<!-- ProofInformation -->
@ -43,29 +43,29 @@
<StackPanel Margin="8">
<UniformGrid Columns="4" Rows="4" Margin="0,0,0,12">
<TextBlock Text="CompetentCustomsOffice"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.CompetentCustomsOffice, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.CompetentCustomsOffice, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="DeclarationType"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.DeclarationType, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.DeclarationType, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="DeclarationDate (yyyy-MM-ddTHH:mm:ss)"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.DeclarationDate, StringFormat={}{0:yyyy-MM-ddTHH:mm:ss}, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.DeclarationDate, StringFormat={}{0:yyyy-MM-ddTHH:mm:ss}, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="TotalGrossMassKg"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.TotalGrossMassKg, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.TotalGrossMassKg, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="RequestedValidityOfTheProof.NumberOfDays"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.RequestedValidityOfTheProof.NumberOfDays, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.RequestedValidityOfTheProof.NumberOfDays, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
<TextBlock Text="RequestType"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.RequestType, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.RequestType, UpdateSourceTrigger=PropertyChanged}" Margin="2" />
</UniformGrid>
<GroupBox Header="LocationOfGoods">
<UniformGrid Columns="6" Margin="8">
<TextBlock Text="TypeOfLocation"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.LocationOfGoods.TypeOfLocation}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.LocationOfGoods.TypeOfLocation}" Margin="2" />
<TextBlock Text="QualifierOfIdentification"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.LocationOfGoods.QualifierOfIdentification}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.LocationOfGoods.QualifierOfIdentification}" Margin="2" />
<TextBlock Text="UNLocode"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.LocationOfGoods.UNLocode}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.LocationOfGoods.UNLocode}" Margin="2" />
</UniformGrid>
</GroupBox>
@ -76,7 +76,7 @@
<TextBlock Text="GoodsItemsForT2LT2LF (Paste tab/CSV with columns: HS, Item#, Description, Gross, Net, Pkgs, Type, Marks)" Margin="0,12,0,4"/>
<DataGrid ItemsSource="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.GoodsItemsForT2LT2LF}"
AutoGenerateColumns="False" CanUserAddRows="True"
PreviewKeyDown="GoodsGrid_PreviewKeyDown" >
PreviewKeyDown="DataGrid_PreviewKeyDown" >
<DataGrid.Columns>
<DataGridTextColumn Header="HS Code" Binding="{Binding Commodity.HarmonizedSystemSubHeadingCode}"/>
<DataGridTextColumn Header="Item #" Binding="{Binding GoodsItemNumber}"/>
@ -92,9 +92,9 @@
<GroupBox Header="TransportDocuments" Margin="0,12,0,0">
<UniformGrid Columns="4" Margin="8">
<TextBlock Text="Type"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.TransportDocuments.Type}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.TransportDocuments.Type}" Margin="2" />
<TextBlock Text="ReferenceNumber"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.TransportDocuments.ReferenceNumber}"/>
<TextBox Text="{Binding ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.TransportDocuments.ReferenceNumber}" Margin="2" />
</UniformGrid>
</GroupBox>
</StackPanel>
@ -102,8 +102,9 @@
<!-- Actions -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,16,0,0">
<Button Content="Clear" Width="100" Margin="0,0,8,0" Click="Clear_Click"/>
<Button Content="Export" Width="120" Click="Export_Click"/>
<Button x:Name="buttonImport" Content="Import" Width="100" Margin="0,0,8,0" Click="buttonImport_Click" />
<Button x:Name="buttonClear" Content="Clear" Width="100" Margin="0,0,8,0" Click="buttonClear_Click"/>
<Button x:Name="buttonExport" Content="Export" Width="120" Click="buttonExport_Click"/>
</StackPanel>
</StackPanel>
</ScrollViewer>

View File

@ -1,5 +1,14 @@
using System;
// Copyright (c) 2017- schick Informatik
// Description: Display dialog for customs XML data upload app
//
using bsmd.database.EasyPeasy;
using ENI2.Util;
using Microsoft.Office.Interop.Excel;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -12,6 +21,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Serialization;
namespace ENI2.Controls
{
@ -20,9 +30,152 @@ namespace ENI2.Controls
/// </summary>
public partial class EasyPeasyControl : UserControl
{
private ProofRequest _vm;
public EasyPeasyControl()
{
InitializeComponent();
}
private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.V && (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
{
if (Clipboard.ContainsText())
{
var text = Clipboard.GetText();
PasteGoodsItems(text);
e.Handled = true;
}
}
}
private void buttonClear_Click(object sender, RoutedEventArgs e)
{
this._vm = EasyPeasyState.CreateDefault();
this.DataContext = this._vm;
}
private void buttonExport_Click(object sender, RoutedEventArgs e)
{
var dlg = new SaveFileDialog
{
FileName = "proofRequest.xml",
Filter = "XML file|*.xml",
OverwritePrompt = true
};
if (dlg.ShowDialog() == true)
{
try
{
using (var fs = File.Create(dlg.FileName))
{
var ser = new XmlSerializer(typeof(ProofRequest));
ser.Serialize(fs, _vm);
}
MessageBox.Show("Exported successfully.", "easy-peasy", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
MessageBox.Show("Export failed:\n" + ex.Message, "easy-peasy", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
_vm = EasyPeasyState.LoadOrCreate();
if (_vm.ProofInformationT2LT2LF == null)
_vm.ProofInformationT2LT2LF = new ProofInformationT2LT2LF();
if (_vm.ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF == null)
_vm.ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF = new GoodsShipmentForT2LT2LF
{
LocationOfGoods = new LocationOfGoods(),
TransportDocuments = new TransportDocuments()
};
this.DataContext = _vm;
}
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
{
try
{
EasyPeasyState.Save(_vm);
}
catch { }
}
private void PasteGoodsItems(string text)
{
if (_vm?.ProofInformationT2LT2LF?.GoodsShipmentForT2LT2LF == null) return;
var lines = text.Replace("\r\n", "\n").Replace('\r', '\n')
.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
// Split by tab first; if only one column, try CSV
var cells = line.Split('\t');
if (cells.Length == 1) cells = SplitCsv(line);
// Expected order: HS, Item#, Description, Gross, Net, Pkgs, Type, Marks
var item = new GoodsItemForT2LT2LF();
if (cells.Length > 0) item.Commodity.HarmonizedSystemSubHeadingCode = cells[0].Trim();
if (cells.Length > 1 && int.TryParse(cells[1], out var n)) item.GoodsItemNumber = n;
if (cells.Length > 2) item.DescriptionOfGoods = cells[2].Trim();
if (cells.Length > 3 && decimal.TryParse(cells[3], out var gross)) item.GoodsMeasure.GrossMass = gross;
if (cells.Length > 4 && decimal.TryParse(cells[4], out var net)) item.GoodsMeasure.NetMass = net;
if (cells.Length > 5 && int.TryParse(cells[5], out var pkgs)) item.Packaging.NumberOfPackages = pkgs;
if (cells.Length > 6) item.Packaging.TypeOfPackages = cells[6].Trim();
if (cells.Length > 7) item.Packaging.ShippingMarks = cells[7].Trim();
_vm.ProofInformationT2LT2LF.GoodsShipmentForT2LT2LF.GoodsItemsForT2LT2LF.Add(item);
}
}
// Very small CSV splitter (handles quotes)
private static string[] SplitCsv(string line)
{
var res = new System.Collections.Generic.List<string>();
var sb = new StringBuilder();
bool inQuotes = false;
for (int i = 0; i < line.Length; i++)
{
char c = line[i];
if (c == '\"')
{
if (inQuotes && i + 1 < line.Length && line[i + 1] == '\"')
{ sb.Append('\"'); i++; }
else { inQuotes = !inQuotes; }
}
else if (c == ',' && !inQuotes)
{ res.Add(sb.ToString()); sb.Clear(); }
else { sb.Append(c); }
}
res.Add(sb.ToString());
return res.ToArray();
}
private void buttonImport_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "XML file|*.xml";
ofd.RestoreDirectory = true;
ofd.Multiselect = false;
if (ofd.ShowDialog() == true)
{
using (var fs = File.OpenRead(ofd.FileName))
{
var ser = new XmlSerializer(typeof(ProofRequest));
_vm = (ProofRequest)ser.Deserialize(fs);
this.DataContext = _vm;
}
}
}
}
}

View File

@ -561,6 +561,7 @@
<Compile Include="Util\ByteConverter.cs" />
<Compile Include="Util\CutoffConverter.cs" />
<Compile Include="Util\DatabaseEntityWatchdog.cs" />
<Compile Include="Util\EasyPeasyState.cs" />
<Compile Include="Util\EnumHelper.cs" />
<Compile Include="Util\EnumToBooleanConverter.cs" />
<Compile Include="Util\EnumToCollectionConverter.cs" />

View File

@ -95,6 +95,7 @@
<MenuItem x:Name="menuItemUserAdministration" Header="{x:Static p:Resources.textUserAdministration}" Click="radioButton_Click" Visibility="Hidden"/>
<MenuItem x:Name="menuItemMaersk" Header="{x:Static p:Resources.textPOLists}" Click="radioButton_Click" Visibility="Hidden" />
<MenuItem x:Name="menuItemValueMappings" Header="{x:Static p:Resources.textExcelValueMappings}" Click="radioButton_Click" Visibility="Hidden" />
<MenuItem x:Name="menuItemEasyPeasy" Header="{x:Static p:Resources.textEasyPeasy}" Click="radioButton_Click" Visibility="Hidden" />
<MenuItem x:Name="labelStatusId" />
<MenuItem Header="Help" HorizontalAlignment="Right">
<MenuItem Header="Change Password" Click="buttonChangePassword_Click">

View File

@ -39,6 +39,7 @@ namespace ENI2
private ServerStatusControl statusControl;
private readonly SucheControl sucheControl;
private CompareExcelDialog compareExcelDialog;
private EasyPeasyControl easyPeasyControl;
private bool dbConnected;
private readonly ScaleTransform _transform = new ScaleTransform(1.0, 1.0);
@ -324,6 +325,14 @@ namespace ENI2
}
this.rootContainer.Children.Add(this.vmControl);
}
else if(sender == this.menuItemEasyPeasy)
{
if(this.easyPeasyControl == null)
{
this.easyPeasyControl = new EasyPeasyControl();
}
this.rootContainer.Children.Add(this.easyPeasyControl);
}
}
private void buttonCompareSheets_Click(object sender, RoutedEventArgs ev)
@ -690,6 +699,7 @@ namespace ENI2
ReportingParty.CurrentReportingParty = this.userEntity;
this.menuItemMaersk.Visibility = Visibility.Visible;
this.menuItemValueMappings.Visibility = Visibility.Visible;
this.menuItemEasyPeasy.Visibility = Visibility.Visible;
if (this.userEntity.IsAdmin)
{
this.menuItemUserAdministration.Visibility = Visibility.Visible;
@ -753,5 +763,6 @@ namespace ENI2
#endregion
}
}

View File

@ -2871,6 +2871,15 @@ namespace ENI2.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Easy Peasy 🍋.
/// </summary>
public static string textEasyPeasy {
get {
return ResourceManager.GetString("textEasyPeasy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to _Edit.
/// </summary>

View File

@ -2265,4 +2265,7 @@ New entry: {1}
Proceed?</value>
</data>
<data name="textEasyPeasy" xml:space="preserve">
<value>Easy Peasy 🍋</value>
</data>
</root>

View File

@ -0,0 +1,63 @@
// Copyright (c) 2017- schick Informatik
// Description: Helper class for customs data serialization
//
using bsmd.database.EasyPeasy;
using System;
using System.IO;
using System.Xml.Serialization;
namespace ENI2.Util
{
public static class EasyPeasyState
{
private static readonly string Root = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"EasyPeasy");
private static readonly string StatePath = Path.Combine(Root, "state.xml");
public static ProofRequest LoadOrCreate()
{
try
{
if (File.Exists(StatePath))
{
using (var fs = File.OpenRead(StatePath))
{
var ser = new XmlSerializer(typeof(ProofRequest));
return (ProofRequest)ser.Deserialize(fs);
}
}
}
catch { /* swallow & create new */ }
return CreateDefault();
}
public static void Save(ProofRequest data)
{
Directory.CreateDirectory(Root);
using (var fs = File.Create(StatePath))
{
var ser = new XmlSerializer(typeof(ProofRequest));
ser.Serialize(fs, data);
}
}
public static ProofRequest CreateDefault()
{
return new ProofRequest
{
ProofInformationT2LT2LF = new ProofInformationT2LT2LF
{
RequestedValidityOfTheProof = new RequestedValidityOfTheProof(),
GoodsShipmentForT2LT2LF = new GoodsShipmentForT2LT2LF
{
LocationOfGoods = new LocationOfGoods(),
TransportDocuments = new TransportDocuments()
}
}
};
}
}
}

View File

@ -0,0 +1,91 @@
// Copyright (c) 2024-present schick Informatik
// Description: Collection of classes for the customs XML upload app
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
namespace bsmd.database.EasyPeasy
{
// Root: <proofRequest>
[XmlRoot("proofRequest")]
public class ProofRequest
{
public string DelegateIdentificationType { get; set; }
public string TraderIdentificationType { get; set; }
public string LRN { get; set; }
public string TraderIdentificationNumber { get; set; }
public string Country { get; set; }
public ProofInformationT2LT2LF ProofInformationT2LT2LF { get; set; }
public string DelegateIdentificationNumber { get; set; }
}
public class ProofInformationT2LT2LF
{
public string CompetentCustomsOffice { get; set; }
public string DeclarationType { get; set; }
public DateTime DeclarationDate { get; set; }
public decimal TotalGrossMassKg { get; set; }
public RequestedValidityOfTheProof RequestedValidityOfTheProof { get; set; }
public GoodsShipmentForT2LT2LF GoodsShipmentForT2LT2LF { get; set; }
public string RequestType { get; set; }
}
public class RequestedValidityOfTheProof
{
public int NumberOfDays { get; set; }
}
public class GoodsShipmentForT2LT2LF
{
public bool ContainerIndication { get; set; }
public LocationOfGoods LocationOfGoods { get; set; }
[XmlElement("GoodsItemsForT2LT2LF")]
public List<GoodsItemForT2LT2LF> GoodsItemsForT2LT2LF { get; set; } = new List<GoodsItemForT2LT2LF>();
public TransportDocuments TransportDocuments { get; set; }
}
public class LocationOfGoods
{
public string TypeOfLocation { get; set; }
public string QualifierOfIdentification { get; set; }
public string UNLocode { get; set; }
}
public class GoodsItemForT2LT2LF
{
public Commodity Commodity { get; set; } = new Commodity();
public int GoodsItemNumber { get; set; }
public string DescriptionOfGoods { get; set; }
public GoodsMeasure GoodsMeasure { get; set; } = new GoodsMeasure();
public Packaging Packaging { get; set; } = new Packaging();
}
public class Commodity
{
public string HarmonizedSystemSubHeadingCode { get; set; }
}
public class GoodsMeasure
{
public decimal GrossMass { get; set; }
public decimal NetMass { get; set; }
}
public class Packaging
{
public string ShippingMarks { get; set; }
public int NumberOfPackages { get; set; }
public string TypeOfPackages { get; set; }
}
public class TransportDocuments
{
public string Type { get; set; }
public string ReferenceNumber { get; set; }
}
}

View File

@ -119,6 +119,7 @@
<Compile Include="Customer.cs" />
<Compile Include="DatabaseEntityAsync.cs" />
<Compile Include="DBManagerAsync.cs" />
<Compile Include="EasyPeasy.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="HAZ.cs" />
<Compile Include="HAZPosTemplate.cs" />