| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 | using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Comal.Classes;using Comal.Classes.SecurityDescriptors;using InABox.Core;using InABox.Mobile;using Xamarin.Essentials;using Xamarin.Forms;using Xamarin.Forms.Xaml;using XF.Material.Forms.UI.Dialogs;using Result = ZXing.Result;namespace PRS.Mobile{    public class HoldingUnitCalculator : AbstractConverter<StockHoldingShell, double>    {        public RequisitionItemModel RequisitionItems { get; set; }        protected override double Convert(StockHoldingShell shell, object? parameter = null)        {            return Calculate(shell, RequisitionItems);        }        public static double Calculate(StockHoldingShell holding, RequisitionItemModel? items)        {            var instock = holding.Units;            var picked = items?.Items.Where(x =>                x.LocationID == holding.LocationID                && x.ProductID == holding.ProductID                && x.StyleID == holding.StyleID                && x.JobID == holding.JobID                && x.DimensionsLength == holding.DimensionsLength                && x.DimensionsWidth == holding.DimensionsWidth                && x.DimensionsHeight == holding.DimensionsHeight                && x.DimensionsWeight == holding.DimensionsWeight                && holding.DimensionsQuantity == x.DimensionsQuantity)                .Sum(x => x.ActualQuantity) ?? 0.0;            return instock - picked;        }    }    public class QuickPickViewModel : BindableObject    {        public bool HasItems { get; set; }        public StockHoldingModel Holdings { get; private set; }        public RequisitionItemModel RequisitionItems { get; private set; }                public JobShell Job { get; set; }                public QuickPickViewModel()        {            Holdings = new StockHoldingModel(App.Data, () => new Filter<StockHolding>().None());            RequisitionItems = new RequisitionItemModel(App.Data, () => new Filter<RequisitionItem>().None());            Job = App.Data.Jobs.CreateItem();        }    }        [XamlCompilation(XamlCompilationOptions.Compile)]    public partial class QuickPickModule : MobilePage    {        public QuickPickModule()        {            InitializeComponent();            UnitCalculator.RequisitionItems = _viewModel.RequisitionItems;            var options = new ZXing.Mobile.MobileBarcodeScanningOptions()            {                PossibleFormats = new List<ZXing.BarcodeFormat>() { ZXing.BarcodeFormat.QR_CODE },                AutoRotate = false,                TryInverted = true,                TryHarder = true,            };            _scanView.Options = options;            _scanView.IsAnalyzing = false;            _scanView.IsScanning = true;        }        protected override void OnAppearing()        {            base.OnAppearing();            try            {                _scanView.IsAnalyzing = _tabStrip.SelectedIndex == 0;            }            catch (Exception e)            {                InABox.Mobile.MobileLogging.Log(e);            }        }                protected override void OnDisappearing()        {                        try            {                _scanView.IsAnalyzing = false;            }            catch (Exception e)            {                InABox.Mobile.MobileLogging.Log(e);            }            base.OnDisappearing();        }                private void _tabStrip_OnSelectionChanged(object sender, EventArgs e)        {            _scanView.IsAnalyzing = _tabStrip.SelectedIndex == 0;            _viewModel.HasItems = _viewModel.RequisitionItems.Any();        }                private bool bProcessing = false;        private Guid _lastGuid = Guid.Empty;        private async void ScanView_OnScanResult(ZXing.Result result)        {            if (bProcessing)                return;            if (!Guid.TryParse(result.Text, out Guid id) || id == Guid.Empty || id == _lastGuid)                return;            _lastGuid = id;                        bProcessing = true;            using (await MaterialDialog.Instance.LoadingDialogAsync($"Processing..."))            {                Vibration.Vibrate();                SearchLocationID(id);                bProcessing = false;            }        }        private void SearchLocationID(Guid id)        {            //App.Data.StockLocations.Refresh(false);            //var location = App.Data.StockLocations.FirstOrDefault(x => Guid.Equals(x.ID,id));            //if (location != null)            //{                _viewModel.Holdings.Filter = () =>                    new Filter<StockHolding>(x => x.Location.ID).IsEqualTo(id).Or(x=>x.Product.ID).IsEqualTo(id);                _viewModel.Holdings.Refresh(true);            //}        }                private void SelectFromHolding_Click(object sender, EventArgs e)        {            var holding = (sender as MobileCard)?.BindingContext as StockHoldingShell;            if (holding == null)                return;            ShowPopup(() =>                {                    var qty = HoldingUnitCalculator.Calculate(holding, _viewModel.RequisitionItems);                    var editor = new SelectFromHoldingView(holding, qty, _viewModel.RequisitionItems);                    editor.OnSave += (o, args) =>                    {                        if (args.Quantity.IsEffectivelyGreaterThan(0.0))                        {                            var requiItem = _viewModel.RequisitionItems.CreateItem();                            requiItem.LocationID = args.Holding.LocationID;                            requiItem.ProductID = args.Holding.ProductID;                            requiItem.ProductCode = args.Holding.ProductCode;                            requiItem.ProductName = args.Holding.ProductName;                            requiItem.StyleID = args.Holding.StyleID;                            requiItem.StyleCode = args.Holding.StyleCode;                            requiItem.StyleDescription = args.Holding.StyleDescription;                            requiItem.JobID = args.Holding.JobID;                            requiItem.DimensionsUnitID = args.Holding.DimensionsUnitID;                            requiItem.DimensionsHeight = args.Holding.DimensionsHeight;                            requiItem.DimensionsWidth = args.Holding.DimensionsWidth;                            requiItem.DimensionsLength = args.Holding.DimensionsLength;                            requiItem.DimensionsQuantity = args.Holding.DimensionsQuantity;                            requiItem.DimensionsWeight = args.Holding.DimensionsWeight;                            requiItem.DimensionsValue = args.Holding.DimensionsValue;                            requiItem.DimensionsUnitSize = args.Holding.DimensionsUnitSize;                            requiItem.ImageID = args.Holding.ImageID;                            if (args.Holding.Parent.Images.TryGetValue(args.Holding.ImageID, out var _image))                                _viewModel.RequisitionItems.Images[args.Holding.ImageID] = _image;                            requiItem.SourceJRI = args.JobRequisitionItemID;                            requiItem.TargetJRI = args.JobRequisitionItemID;                            requiItem.Quantity = args.Quantity;                            requiItem.ActualQuantity = args.Quantity;                            requiItem.Cost = args.Holding.AverageCost;                            requiItem.Done = true;                            _viewModel.RequisitionItems.CommitItem(requiItem);                            _viewModel.Holdings.Refresh(false);                            DismissPopup();                        }                    };                    editor.OnCancel += (o, args) => DismissPopup();                    return editor;                },                new PopupManagerConfiguration()                {                    RequestedHeight = Math.Min(700,500 + (holding.Allocations.Length * 55))                });        }                private void SelectJob_Clicked(object sender, MobileButtonClickEventArgs args)        {            ShowPopup(() => SelectionView.Execute<JobShell>(                (columns) =>                {                    columns.Add(new MobileGridTextColumn<JobShell>()                    {                        Column = x => x.JobNumber,                         Width = GridLength.Auto,                         Caption = "#",                        Alignment = TextAlignment.Center                    });                    columns.Add(new MobileGridTextColumn<JobShell>()                    {                        Column = x => x.Name,                        Width = GridLength.Star,                        Caption = "Select Job",                        Alignment = TextAlignment.Start                    });                },                (refresh) => App.Data.Jobs.Refresh(false),                 (jobs) =>                {                    _viewModel.Job = jobs.FirstOrDefault() ?? App.Data.Jobs.CreateItem();                    DismissPopup();                }));        }        private async void SaveList_Click(object sender, MobileMenuButtonClickedEventArgs args)        {            if (_viewModel.Job.ID == Guid.Empty && !Security.IsAllowed<AllowMobileQuickPickWithoutJob>())            {                await MaterialDialog.Instance.AlertAsync("Please select a Job before saving!", "Error");                return;            }                        using (await MaterialDialog.Instance.LoadingDialogAsync(message: "Saving"))            {                try                {                    var _requiModel = new RequisitionModel(App.Data, () => new Filter<Requisition>().None());                    var requi = _requiModel.CreateItem();                    requi.Title = $"Quick Pick by {App.Data.Me.Name}";                    requi.RequestedByID = App.Data.Me.ID;                    requi.Due = DateTime.Now;                    requi.JobID = _viewModel.Job.ID;                    _requiModel.CommitItem(requi);                    _requiModel.Save("Requisition Created from Mobile Quick Pick Module");                    foreach (var _item in _viewModel.RequisitionItems.Items)                    {                        if (_viewModel.Job.ID != _item.JobID)                            _item.TargetJRI = Guid.Empty;                        _item.RequisitionID = requi.ID;                    }                    _viewModel.RequisitionItems.Save("Created from Mobile Quick Pick Module");                    requi.Filled = requi.Due;                    requi.StockUpdated = requi.Filled;                    _requiModel.Save("Stock Movements created from Mobile Quick Pick Module");                }                catch (Exception e)                {                    InABox.Mobile.MobileLogging.Log(e);                }            }            Navigation.PopAsync();        }        private async void DeleteRequisitionItem(object sender, MobileMenuButtonClickedEventArgs args)        {            var shell = ((sender as MobileMenuButton)?.BindingContext as RequisitionItemShell);            if (shell == null)                return;            if (await MaterialDialog.Instance.ConfirmAsync("Delete Picked Item?", "Confirm") == true)            {                _viewModel.RequisitionItems.DeleteItem(shell);            }        }    }}
 |