123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using Comal.Classes;
- using InABox.Clients;
- using InABox.Configuration;
- using InABox.Core;
- using InABox.DynamicGrid;
- using InABox.WPF;
- using InABox.Wpf;
- using System.Threading.Tasks;
- using System.IO;
- using System.Collections.ObjectModel;
- using System.Windows.Media;
- using System.Runtime.CompilerServices;
- namespace PRSDesktop;
- public class SupplierBillPanelSettings : IUserConfigurationSettings
- {
- public SupplierBillPanelSettings()
- {
- AnchorWidth = 500F;
- ViewType = ScreenViewType.Combined;
- }
- public ScreenViewType ViewType { get; set; }
- public double AnchorWidth { get; set; }
- }
- public class SupplierBillPanelProperties : BaseObject, IGlobalConfigurationSettings
- {
- [IntegerEditor]
- [EditorSequence(1)]
- public int CurrencyDecimalPlaces { get; set; } = 2;
-
- [EditorSequence(2)]
- [CheckBoxEditor]
- public bool AllowBlankBillNumbers { get; set; }
- }
- public partial class SupplierBillPanel : UserControl, IPanel<Bill>, IPropertiesPanel<SupplierBillPanelProperties, CanConfigureAccountsPanels>, INotifyPropertyChanged
- {
- private SupplierBillPanelSettings settings;
- private SupplierBillEditLayout EditLayout;
- public SupplierBillPanel()
- {
- InitializeComponent();
- }
- #region IPanel Interface
- public bool IsReady { get; set; }
- public event DataModelUpdateEvent? OnUpdateDataModel;
- public Dictionary<string, object[]> Selected()
- {
- return new Dictionary<string, object[]> { { typeof(Bill).EntityName(), Bills.SelectedRows } };
- }
- public void CreateToolbarButtons(IPanelHost host)
- {
- AccountsSetupActions.Standard(host);
- PostUtils.CreateToolbarButtons(host,
- () => (DataModel(Selection.Selected) as IDataModel<Bill>)!,
- () => Bills.Refresh(false, true),
- true);
- host.CreateSetupSeparator();
- host.CreateSetupActionIfCanView<BillApprovalSet>("Bill Approval Sets", PRSDesktop.Resources.bill, (action) =>
- {
- var list = new MasterList(typeof(BillApprovalSet));
- list.ShowDialog();
- });
- }
- public string SectionName => "Supplier Bills";
- public SupplierBillPanelProperties Properties { get; set; }
- public DataModel DataModel(Selection selection)
- {
- var ids = Bills.ExtractValues(x => x.ID, selection).ToArray();
- return new BaseDataModel<Bill>(new Filter<Bill>(x => x.ID).InList(ids));
- }
- public void Refresh()
- {
- if (CheckSaved())
- {
- Bills.Refresh(false, true);
- SetChanged(false);
- }
- }
- public void Setup()
- {
- settings = new UserConfiguration<SupplierBillPanelSettings>().Load();
- SplitPanel.View = settings.ViewType == ScreenViewType.Register ? DynamicSplitPanelView.Master :
- settings.ViewType == ScreenViewType.Details ? DynamicSplitPanelView.Detail : DynamicSplitPanelView.Combined;
- SplitPanel.AnchorWidth = settings.AnchorWidth;
- EditLayout = new();
- EditLayout.Approve += EditLayout_Approve;
- Bill.SetLayout(EditLayout);
- Bills.Refresh(true, false);
- BillPanelDocumentCache.Cache.ClearOld();
- }
- #region Approval
- private BillApproval? _approval = null;
- private SupplierBillLineGrid? _billLinePage = null;
- private void EditLayout_Approve()
- {
- if (_approval is null) return;
- if(_approval.Approved == DateTime.MinValue)
- {
- _approval.Approved = DateTime.Now;
- EditLayout.IsApproved = true;
- }
- else
- {
- _approval.Approved = DateTime.MinValue;
- EditLayout.IsApproved = false;
- }
- Bill.DoChanged();
- }
- private void SaveApproval()
- {
- if (_approval is null) return;
- Client.Save(_approval, "Approval updated by user.");
- }
- private void CancelApproval()
- {
- UpdateApproval();
- }
- private void UpdateApproval()
- {
- if(_bills is not null && _bills.Length == 1)
- {
- _approval = Client.Query<BillApproval>(
- new Filter<BillApproval>(x => x.Employee.ID).IsEqualTo(App.EmployeeID)
- .And(x => x.Bill.ID).IsEqualTo(_bills[0].ID),
- Columns.Required<BillApproval>().Add(x => x.Approved))
- .ToObjects<BillApproval>().FirstOrDefault();
- EditLayout.CanApprove = _approval is not null;
- EditLayout.IsApproved = _approval is not null ? _approval.Approved != DateTime.MinValue : false;
- if(Bill.Pages.TryGetPage(out _billLinePage))
- {
- _billLinePage.OnChanged -= BillLinePage_OnChanged;
- _billLinePage.OnChanged += BillLinePage_OnChanged;
- EditLayout.BillAmount = _billLinePage.Items.Sum(x => x.IncTax);
- EditLayout.POAmount = _billLinePage.Items.Sum(x =>
- {
- return x.OrderItem.IncTax + x.Consignment.IncTax;
- });
- }
- }
- else
- {
- _approval = null;
- EditLayout.CanApprove = false;
- }
- }
- private void BillLinePage_OnChanged(object? sender, EventArgs e)
- {
- if (_billLinePage is null) return;
- EditLayout.BillAmount = _billLinePage.Items.Sum(x => x.IncTax);
- EditLayout.POAmount = _billLinePage.Items.Sum(x =>
- {
- return x.OrderItem.IncTax + x.Consignment.IncTax;
- });
- }
- #endregion
- private void CheckSaved(CancelEventArgs cancel)
- {
- if (!bChanged)
- {
- return;
- }
- var result = MessageBox.Show("You have an unsaved Supplier Bill; do you wish to save these changes?", "Save Changes?", MessageBoxButton.YesNoCancel);
- if (result == MessageBoxResult.Yes)
- {
- Bill.SaveItem(cancel);
- if (!cancel.Cancel)
- {
- MessageBox.Show("Purchase Order saved.");
- }
- }
- else if (result == MessageBoxResult.Cancel)
- {
- cancel.Cancel = true;
- }
- }
- private bool CheckSaved()
- {
- var cancel = new CancelEventArgs();
- CheckSaved(cancel);
- return !cancel.Cancel;
- }
- public void Shutdown(CancelEventArgs? cancel)
- {
- if(cancel is not null)
- {
- CheckSaved(cancel);
- }
- }
- public void Heartbeat(TimeSpan time)
- {
- }
-
- #endregion
- private Bill[]? _bills = null;
- private CoreRow[]? _editRows = null;
-
- private void Bills_OnOnSelectItem(object sender, DynamicGridSelectionEventArgs e)
- {
- if(SplitPanel.View != DynamicSplitPanelView.Master)
- {
- ReloadBills();
- }
- }
- private void ReloadBills(bool force = false)
- {
- var newRows = Bills.SelectedRows;
- if (newRows.Length != 0)
- {
- if(force || _editRows is null || !newRows.CompareTo(_editRows))
- {
- _editRows = Bills.SelectedRows;
- _bills = Bills.LoadBills(_editRows);
- Bills.InitialiseEditorForm(Bill, _bills, null, true);
- Bill.Visibility = Visibility.Visible;
- LinkDocumentPage();
- }
- UpdateApproval();
- }
- else
- {
- _bills = null;
- _editRows = null;
- Bill.Visibility = Visibility.Hidden;
- ClearDocumentPage();
- UpdateApproval();
- }
- }
- private void Bill_OnOnOK()
- {
- using (new WaitCursor())
- {
- // Saving the approval must happen before saving the bill, because otherwise the BillStore's approval stuff is overwritten
- // by this SaveApproval function.
- SaveApproval();
- var cancel = new System.ComponentModel.CancelEventArgs();
- Bill.SaveItem(cancel);
- if (!cancel.Cancel)
- {
- if(_editRows is not null && _bills is not null)
- {
- _bills = Bills.LoadBills(_editRows);
- Bills.UpdateRows(_editRows, _bills);
- }
- ReloadBills();
- SetChanged(false);
- }
- }
- }
- private void Bill_OnOnCancel()
- {
- CancelApproval();
- ReloadBills();
- SetChanged(false);
- }
- private void SetChanged(bool changed)
- {
- bChanged = changed;
- Bills.IsEnabled = !changed;
- Bill.HideButtons = !changed;
- if (!changed)
- {
- bDocumentsChanged = false;
- DoPropertyChanged(nameof(CanRotateImage));
- }
- }
- private bool bChanged = false;
- private void Bill_OnOnChanged(object? sender, EventArgs e)
- {
- SetChanged(true);
- }
- private void SplitPanel_OnChanged(object sender, DynamicSplitPanelSettings e)
- {
- settings.ViewType = SplitPanel.View == DynamicSplitPanelView.Master ? ScreenViewType.Register :
- SplitPanel.View == DynamicSplitPanelView.Detail ? ScreenViewType.Details : ScreenViewType.Combined;
- settings.AnchorWidth = SplitPanel.AnchorWidth;
- new UserConfiguration<SupplierBillPanelSettings>().Save(settings);
- }
- #region Documents
- private DynamicDocumentGrid<BillDocument, Bill, BillLink>? DocumentPage;
- public bool CanRotateImage => !bDocumentsChanged;
-
- private void ClearDocumentPage()
- {
- ViewList.Documents = [];
- }
- private void LinkDocumentPage()
- {
- DocumentPage = Bill.Pages.OfType<DynamicDocumentGrid<BillDocument, Bill, BillLink>>().FirstOrDefault();
- if(DocumentPage is not null)
- {
- DocumentPage.AfterRefresh += (o, e) =>
- {
- if (bRefreshingDocuments)
- {
- return;
- }
- ReloadViewList(true);
- };
- DocumentPage.OnChanged += DocumentPage_OnChanged;
- }
- }
- private bool bRefreshingDocuments = false;
- private bool bDocumentsChanged = false;
- private void DocumentPage_OnChanged(object? sender, EventArgs e)
- {
- bDocumentsChanged = true;
- DoPropertyChanged(nameof(CanRotateImage));
- if (bRefreshingDocuments)
- {
- return;
- }
- ReloadViewList();
- }
- private void ReloadViewList(bool force = false)
- {
- if(DocumentPage is null)
- {
- return;
- }
- ViewList.UpdateViewList(DocumentPage.LoadItems(DocumentPage.Data.Rows), force);
- }
- private void ViewList_UpdateDocument(BillDocument document, Document doc)
- {
- if(DocumentPage is null)
- {
- return;
- }
- if (Path.GetExtension(doc.FileName) == ".pdf")
- {
- document.Thumbnail = ImageUtils.GetPDFThumbnail(doc.Data, 256, 256);
- }
- Client.Save(document, "");
- BillPanelDocumentCache.Cache.Add(new DocumentCachedDocument(doc));
- DocumentPage.Refresh(false, true);
- ViewList.UpdateViewList(DocumentPage.LoadItems(DocumentPage.Data.Rows), true);
- }
- private void Documents_DragOver(object sender, DragEventArgs e)
- {
- if(Bills.SelectedRows.Length == 0)
- {
- e.Effects = DragDropEffects.None;
- }
- else
- {
- if (e.Data.GetDataPresent(DataFormats.FileDrop) || e.Data.GetDataPresent("FileGroupDescriptor"))
- {
- e.Effects = DragDropEffects.Copy;
- }
- else
- {
- e.Effects = DragDropEffects.None;
- }
- }
- e.Handled = true;
- }
- private void Documents_Drop(object sender, DragEventArgs e)
- {
- if(Bills.SelectedRows.Length == 0 || DocumentPage is null)
- {
- return;
- }
- var selectedBill = Bills.SelectedRows[0].ToObject<Bill>();
- Task.Run(() =>
- {
- Dispatcher.Invoke(() =>
- {
- Progress.Show("Uploading documents");
- try
- {
- var result = DocumentUtils.HandleFileDrop(e);
- if (result is not null)
- {
- var docs = new List<Document>();
- foreach (var (filename, stream) in result)
- {
- var doc = new Document();
- doc.FileName = filename;
- if (stream is null)
- {
- doc.Data = File.ReadAllBytes(filename);
- doc.TimeStamp = new FileInfo(filename).LastWriteTime;
- }
- else
- {
- using var memStream = new MemoryStream();
- stream.CopyTo(memStream);
- doc.Data = memStream.ToArray();
- doc.TimeStamp = DateTime.Now;
- }
- doc.CRC = CoreUtils.CalculateCRC(doc.Data);
- docs.Add(doc);
- }
- Client.Save(docs, "Initial Upload");
- var billDocs = new List<BillDocument>();
- foreach (var doc in docs)
- {
- var billDoc = new BillDocument();
- billDoc.DocumentLink.CopyFrom(doc);
- billDoc.EntityLink.CopyFrom(selectedBill);
- billDocs.Add(billDoc);
- }
- DocumentPage.SaveItems(billDocs);
- DocumentPage.Refresh(false, true);
- try
- {
- bRefreshingDocuments = true;
- DocumentPage.DoChanged();
- }
- finally
- {
- bRefreshingDocuments = false;
- }
- }
- Progress.Close();
- }
- catch (Exception e)
- {
- Progress.Close();
- MessageWindow.ShowError("Could not upload documents.", e);
- }
- });
- });
- }
- #endregion
- public event PropertyChangedEventHandler? PropertyChanged;
- protected void DoPropertyChanged([CallerMemberName] string propertyName = "")
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- private Column<Bill> ApprovalSetID = new(x => x.ApprovalSet.ID);
- private void Bills_OnChanged(object sender, EventArgs e)
- {
- ReloadBills(force: true);
- }
- private void Bills_OnCustomiseEditor(IDynamicEditorForm sender, Bill[] items, DynamicGridColumn column, BaseEditor editor)
- {
- if(column.ColumnName == "Approved" || ApprovalSetID.IsEqualTo(column.ColumnName))
- {
- editor.Editable = Editable.Hidden;
- }
- if((editor is DateEditor || editor is TimestampEditor) && !column.ColumnName.Contains("."))
- {
- if(editor.Page == "Additional")
- {
- editor.EditorSequence += 100;
- }
- editor.Page = "Dates";
- }
- }
- }
- public class BillDocumentViewList : DocumentViewList<BillDocument>
- {
- protected override IEnumerable<Document> LoadDocuments(IEnumerable<Guid> ids)
- {
- return BillPanelDocumentCache.Cache.LoadDocuments(ids, checkTimestamp: true);
- }
- protected override Guid GetID(BillDocument document)
- {
- return document.ID;
- }
- protected override Guid GetDocumentID(BillDocument document)
- {
- return document.DocumentLink.ID;
- }
- protected override string GetDocumentFileName(IEnumerable<BillDocument> documents, Document document)
- {
- return Documents.FirstOrDefault(x => x.DocumentLink.ID == document.ID)?.DocumentLink.FileName ?? "";
- }
- }
- public class BillPanelDocumentCache : DocumentCache
- {
- public override TimeSpan MaxAge => TimeSpan.FromHours(1);
- private static BillPanelDocumentCache? _cache;
- public static BillPanelDocumentCache Cache
- {
- get
- {
- _cache ??= DocumentCaches.GetOrRegister<BillPanelDocumentCache>();
- return _cache;
- }
- }
- public BillPanelDocumentCache() : base(nameof(BillPanelDocumentCache))
- {
- }
- }
|