using System; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Lagerprogramm.Models; using Lagerprogramm.Services; namespace Lagerprogramm.ViewModels; public partial class DeductionsViewModel : ObservableObject { private readonly JsonDataService _dataService; private readonly AppData _appData; public AppData AppData => _appData; [ObservableProperty] private ObservableCollection _deductions = new(); [ObservableProperty] private ObservableCollection _lines = new(); [ObservableProperty] private DateTime _date = DateTime.Now; [ObservableProperty] private string _comment = string.Empty; [ObservableProperty] private string _customer = string.Empty; [ObservableProperty] private bool _generateDeliveryNote; public ObservableCollection PartNumbers { get; } = new(); public DeductionsViewModel(JsonDataService dataService, AppData appData) { _dataService = dataService; _appData = appData; RefreshPartNumbers(); foreach (var d in appData.Deductions.OrderByDescending(d => d.Date)) Deductions.Add(d); Lines.Add(new TransactionLine()); } [RelayCommand] private void AddLine() => Lines.Add(new TransactionLine()); [RelayCommand] private void RemoveLine(TransactionLine? line) { if (line is null) return; Lines.Remove(line); } [RelayCommand] private void SearchPart(TransactionLine? line) { } [RelayCommand] private void SearchDeduction() { } [RelayCommand] private void Save() { if (Lines.Count == 0) return; if (Lines.Any(l => string.IsNullOrWhiteSpace(l.PartInternalNumber) || l.Quantity <= 0)) return; foreach (var line in Lines) { var part = _appData.Parts.FirstOrDefault(p => p.InternalPartNumber == line.PartInternalNumber); if (part is null || part.StockQuantity < line.Quantity) return; } var deduction = new Deduction { Date = Date, Comment = Comment.Trim(), Customer = Customer.Trim(), GenerateDeliveryNote = GenerateDeliveryNote, Lines = Lines.Select(l => new TransactionLine { PartInternalNumber = l.PartInternalNumber.Trim(), Quantity = l.Quantity }).ToList() }; _appData.Deductions.Add(deduction); Deductions.Insert(0, deduction); foreach (var line in deduction.Lines) { var part = _appData.Parts.FirstOrDefault(p => p.InternalPartNumber == line.PartInternalNumber); if (part is not null) part.StockQuantity -= line.Quantity; } _dataService.Save(_appData); if (GenerateDeliveryNote) WriteDeliveryNote(deduction); Comment = string.Empty; Customer = string.Empty; GenerateDeliveryNote = false; Date = DateTime.Now; Lines.Clear(); Lines.Add(new TransactionLine()); RefreshPartNumbers(); } [RelayCommand] private void DeleteDeduction(Deduction? deduction) { if (deduction is null) return; foreach (var line in deduction.Lines) { var part = _appData.Parts.FirstOrDefault(p => p.InternalPartNumber == line.PartInternalNumber); if (part is not null) part.StockQuantity += line.Quantity; } _appData.Deductions.Remove(deduction); Deductions.Remove(deduction); _dataService.Save(_appData); RefreshPartNumbers(); } private void RefreshPartNumbers() { PartNumbers.Clear(); foreach (var p in _appData.Parts.OrderBy(p => p.InternalPartNumber)) PartNumbers.Add(p.InternalPartNumber); } private void WriteDeliveryNote(Deduction deduction) { var path = string.IsNullOrWhiteSpace(_appData.Settings.StoragePath) ? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) : _appData.Settings.StoragePath; if (!Directory.Exists(path)) Directory.CreateDirectory(path); var fileName = Path.Combine(path, $"DeliveryNote_{deduction.Id:N}_{deduction.Date:yyyyMMdd}.txt"); var sb = new StringBuilder(); sb.AppendLine("Delivery Note"); sb.AppendLine($"Company: {_appData.Settings.CompanyName}"); sb.AppendLine($"Date: {deduction.Date:yyyy-MM-dd}"); sb.AppendLine($"Customer: {deduction.Customer}"); sb.AppendLine(); foreach (var line in deduction.Lines) { var part = _appData.Parts.FirstOrDefault(p => p.InternalPartNumber == line.PartInternalNumber); sb.AppendLine($"Part: {line.PartInternalNumber} Qty: {line.Quantity}"); if (part is not null) { sb.AppendLine($" Description: {part.Description}"); sb.AppendLine($" MSRP: {part.Msrp:C}"); sb.AppendLine($" Line Total: {part.Msrp * line.Quantity:C}"); } sb.AppendLine(); } var grandTotal = deduction.Lines .Sum(l => (_appData.Parts.FirstOrDefault(p => p.InternalPartNumber == l.PartInternalNumber)?.Msrp ?? 0) * l.Quantity); sb.AppendLine($"Grand Total: {grandTotal:C}"); sb.AppendLine(); sb.AppendLine($"Comment: {deduction.Comment}"); File.WriteAllText(fileName, sb.ToString()); } }