Exemple #1
0
        public static OrderStatusEnum GetStatusAllDishes(IEnumerable <OrderDish> dishes)
        {
            if ((dishes == null) || (dishes.Count() == 0))
            {
                return(OrderStatusEnum.None);
            }

            int           statId = -1, curStat;
            HashSet <int> unUsedDeps = (HashSet <int>)AppProperties.GetProperty("UnusedDepartments");

            foreach (OrderDish dish in dishes)
            {
                if ((unUsedDeps != null) && (unUsedDeps.Contains(dish.DepartmentId)))
                {
                }
                else
                {
                    curStat = dish.DishStatusId;
                    if (statId == -1)
                    {
                        statId = curStat;
                    }
                    else if (statId != dish.DishStatusId)
                    {
                        return(OrderStatusEnum.None);
                    }
                }
            }

            return((OrderStatusEnum)statId);
        }
Exemple #2
0
        public static bool UpdateModelDictsFromDB(out string errMsg)
        {
            errMsg = "";
            // список статусов -> в словарь
            List <OrderStatusModel> list1 = DBOrderHelper.GetOrderStatusesList();

            if (list1 == null)
            {
                errMsg = DBOrderHelper.ErrorMessage;
                return(false);
            }
            list1.ForEach(item => _statuses.Add(item.Id, item));

            // список отделов -> в словарь
            // а также обновить словарь кол-ва блюд по цехам
            Dictionary <int, decimal> depQty = (Dictionary <int, decimal>)AppProperties.GetProperty("dishesQty");

            depQty.Clear();
            List <DepartmentModel> list2 = DBOrderHelper.GetDepartmentsList();

            if (list2 == null)
            {
                errMsg = DBOrderHelper.ErrorMessage;
                return(false);
            }
            list2.ForEach(item =>
            {
                _departments.Add(item.Id, item);
                depQty.Add(item.Id, 0m);
            });

            return(true);
        }
Exemple #3
0
        // проверка возможности АВТОМАТИЧЕСКОГО перехода в состояние Cooking
        private void checkAutoStartCooking(Dictionary <int, OrderModel> orders)
        {
            OrderStatusEnum           eStatus;
            decimal                   depDepth, dishQnt;
            bool                      isStart;
            Dictionary <int, decimal> dishesQty = (Dictionary <int, decimal>)AppProperties.GetProperty("dishesQty");

            foreach (OrderModel order in orders.Values)              // orders loop
            {
                foreach (OrderDishModel dish in order.Dishes.Values) //  dishes loop
                {
                    eStatus = (OrderStatusEnum)dish.DishStatusId;
                    if (eStatus <= OrderStatusEnum.WaitingCook)
                    {
                        // 1. для отдела установлен автоматический старт приготовления и текущая дата больше даты ожидаемого времени начала приготовления
                        DateTime n = DateTime.Now;
                        isStart = (ModelDicts.GetDepAutoStart(dish.DepartmentId) &&
                                   (n >= dish.CreateDate.AddSeconds(dish.DelayedStartTime)));

                        // 2. проверяем общее кол-во такого блюда в заказах, если установлено кол-во одновременно готовящихся блюд
                        if (isStart == true)
                        {
                            depDepth = ModelDicts.GetDepDepthCount(dish.DepartmentId);
                            if ((dishesQty != null) && (dishesQty.ContainsKey(dish.DepartmentId)) && (depDepth > 0))
                            {
                                dishQnt = Math.Ceiling(dish.Quantity);
                                if (dishesQty[dish.DepartmentId] < depDepth)
                                {
                                    isStart = true;
                                    // обновить кол-во готовящихся блюд в словаре
                                    dishesQty[dish.DepartmentId] += dishQnt;
                                }
                                else
                                {
                                    isStart = false;
                                }
                            }
                        }

                        // автостарт приготовления блюда
                        if (isStart)
                        {
                            DateTime dtTmr   = DateTime.Now;
                            string   sLogMsg = string.Format(" - AutoStart Cooking Id {0}/{1}", dish.Id, dish.Name);
                            AppLib.WriteLogOrderDetails(sLogMsg + " - start");

                            dish.UpdateStatus(OrderStatusEnum.Cooking);

                            sLogMsg += " - finish - " + (DateTime.Now - dtTmr).ToString();
                            AppLib.WriteLogOrderDetails(sLogMsg);
                        }
                    }
                } // loop
            }     // loop
        }
Exemple #4
0
        // обновление состояния заказа проверкой состояний всех блюд
        // установить сост.заказа в 0,2,3,4,5 если ВСЕ блюда наход.в этом состоянии
        // установить сост.заказа в 1, если ХОТЬ одно блюдо наход.в сост. 1
        public void UpdateStatusByVerificationDishes()
        {
            int           iStat      = -1;
            HashSet <int> unUsedDeps = (HashSet <int>)AppProperties.GetProperty("UnusedDepartments");

            foreach (OrderDishModel dish in _dishesDict.Values)
            {
                // пропуск блюд, входящих в неотображаемые цеха
                // или имеющие отрицательное количество - отмененные
                if ((unUsedDeps != null) && (unUsedDeps.Contains(dish.DepartmentId)))
                {
                    continue;
                }
                if (dish.Quantity < 0)
                {
                    continue;
                }

                // первое доступное блюдо
                if (iStat == -1)
                {
                    iStat = dish.DishStatusId;
                }

                // если хотя бы одно блюдо в состояние Готовится, то и заказ переводим в это состояние, если он был не в этом состоянии
                if ((dish.DishStatusId == (int)OrderStatusEnum.Cooking) &&
                    (this.OrderStatusId != (int)OrderStatusEnum.Cooking))
                {
                    AppLib.WriteLogOrderDetails(string.Format("   изменение статуса заказа {0}/{1} с {2} на 'Готовится', т.к. есть блюдо в состоянии 'Готовится'"
                                                              , this.Id, this.Number
                                                              , ((OrderStatusEnum)this.OrderStatusId).ToString()));

                    UpdateStatus(OrderStatusEnum.Cooking, false);
                    _isUpdStatusFromDishes = true;
                    return;
                }

                // есть неодинаковый статус - выйти
                if (iStat != dish.DishStatusId)
                {
                    return;
                }
            }

            if ((iStat != -1) && (this.OrderStatusId != iStat))
            {
                string sLog = string.Format("   изменение статуса заказа {0}/{1} на {2} согласно общему статусу всех блюд ПРИ ОБНОВЛЕНИИ БЛЮДА...", this.Id, this.Number, iStat);
                AppLib.WriteLogOrderDetails(sLog);

                OrderStatusEnum statDishes = AppLib.GetStatusEnumFromNullableInt(iStat);
                UpdateStatus(statDishes, false);
                _isUpdStatusFromDishes = true;
            }
        }  // method
Exemple #5
0
        }         // method

        private string getDishesQtyString()
        {
            // получить словарь по отделам (направлениям печати)
            Dictionary <int, decimal> dishesQty = (Dictionary <int, decimal>)AppProperties.GetProperty("dishesQty");

            StringBuilder sb = new StringBuilder();

            foreach (KeyValuePair <int, decimal> item in dishesQty)
            {
                if (sb.Length > 0)
                {
                    sb.Append("; ");
                }
                sb.Append(string.Format("{0}/{1}", item.Key, item.Value));
            }
            return(sb.ToString());
        }
Exemple #6
0
        // узнать, в каком состоянии находятся ВСЕ БЛЮДА заказа
        public static OrderStatusEnum oldGetStatusAllDishes(IEnumerable <OrderDish> dishes)
        {
            if ((dishes == null) || (dishes.Count() == 0))
            {
                return(OrderStatusEnum.None);
            }

            OrderStatusEnum retVal = OrderStatusEnum.None;

            int iLen      = Enum.GetValues(typeof(OrderStatusEnum)).Length;
            int dishCount = dishes.Count();

            int[]         statArray  = new int[iLen];
            HashSet <int> unUsedDeps = (HashSet <int>)AppProperties.GetProperty("UnusedDepartments");

            int iStatus;

            foreach (OrderDish dish in dishes)
            {
                if ((unUsedDeps != null) && (unUsedDeps.Contains(dish.DepartmentId)))
                {
                    dishCount--;
                }
                else
                {
                    iStatus = dish.DishStatusId;
                    statArray[iStatus]++;
                }
            }

            for (int i = 0; i < iLen; i++)
            {
                if (statArray[i] == dishCount)
                {
                    retVal = (OrderStatusEnum)i; break;
                }
            }

            return(retVal);
        }
Exemple #7
0
        // CONSTRUCTOR
        public OrdersModel()
        {
            // статусы заказов, которые выбираются из БД для отображения на КДС
            _allowedKDSStatuses = new HashSet <int>();
            _allowedKDSStatuses.Add((int)OrderStatusEnum.WaitingCook);
            _allowedKDSStatuses.Add((int)OrderStatusEnum.Cooking);
            _allowedKDSStatuses.Add((int)OrderStatusEnum.Ready);
            if (AppProperties.GetBoolProperty("IsReadTakenDishes"))
            {
                _allowedKDSStatuses.Add((int)OrderStatusEnum.Took);
            }
            _allowedKDSStatuses.Add((int)OrderStatusEnum.Cancelled);
            _allowedKDSStatuses.Add((int)OrderStatusEnum.Transferred);
            _allowedKDSStatuses.Add((int)OrderStatusEnum.ReadyConfirmed);
            DBOrderHelper.AllowedKDSStatuses = _allowedKDSStatuses;

            // неиспользуемые отделы, отфильтровываются на службе
            _unUsedDeps = (HashSet <int>)AppProperties.GetProperty("UnusedDepartments");
            DBOrderHelper.UnusedDeps = _unUsedDeps;

            // буферы для хранения коллекций заказов
            _dbOrders = DBOrderHelper.DBOrders;
            _orders   = new Dictionary <int, OrderModel>();

            // учитывать ли отмененные блюда при подсчете одновременно готовящихся блюд для автостарта готовки
            _takeCancelledInAutostartCooking = AppProperties.GetBoolProperty("TakeCancelledInAutostartCooking");
            // используется, если для детального лога нужно еще чего-то сделать
            _isLogOrderDetails = (AppProperties.GetBoolProperty("IsWriteTraceMessages") && AppProperties.GetBoolProperty("TraceOrdersDetails"));

            _changeStatusYesterdayOrdersCfg     = (AppLib.TimeOfAutoCloseYesterdayOrders != TimeSpan.Zero);
            _changeStatusYesterdayOrdersCurrent = _changeStatusYesterdayOrdersCfg;
            _currentDate = DateTime.Now.Date;
            //_currentDate = _currentDate.AddDays(-1);


            _delOrders = new List <Order>();
        }
Exemple #8
0
        //  обновить коллекцию
        private void updateDishesQuantityDict(Dictionary <int, OrderModel> orders)
        {
            // получить словарь по отделам (направлениям печати)
            Dictionary <int, decimal> dishesQty = (Dictionary <int, decimal>)AppProperties.GetProperty("dishesQty");
            // очистить кол-во
            List <int> keys = dishesQty.Keys.ToList();

            foreach (int key in keys)
            {
                dishesQty[key] = 0m;
            }

            decimal         qnt;
            OrderStatusEnum eStatus;
            bool            isTakeQuantity, isTakeCancelled;

            foreach (OrderModel order in orders.Values)              // orders loop
            {
                foreach (OrderDishModel dish in order.Dishes.Values) //  dishes loop
                {
                    eStatus         = (OrderStatusEnum)dish.DishStatusId;
                    isTakeCancelled = (_takeCancelledInAutostartCooking && (eStatus == OrderStatusEnum.Cancelled));
                    isTakeQuantity  = dish.ParentUid.IsNull() &&
                                      ((eStatus == OrderStatusEnum.Cooking) || isTakeCancelled);

                    // кол-во блюд для подсчета округляем до верхнего целого
                    qnt = Math.Ceiling(dish.Quantity);
                    qnt = isTakeQuantity ? (isTakeCancelled ? -qnt : qnt) : 0m;

                    if ((dishesQty.ContainsKey(dish.DepartmentId)) && (qnt != 0m))
                    {
                        dishesQty[dish.DepartmentId] += qnt;
                    }
                } // loop
            }     // loop
        }         // method
Exemple #9
0
        // сложить настройки из config-файла в словарь настроек приложения
        private static void putAppConfigParamsToAppProperties()
        {
            NameValueCollection cfg = ConfigurationManager.AppSettings;
            string value;

            // наименование службы MS SQL Server, как в services.msc
            setGlobalValueFromCfg("MSSQLServiceName", MSSQLService.Controller.ServiceName);
            // флаг перезапуска sql-службы, по умолчанию - false
            setGlobalValueFromCfg("MSSQLServiceRestartEnable", false);
            // уровень совместимости БД (120 - это MS SQL Server 2014)
            setGlobalValueFromCfg("MSSQLServerCompatibleLevel", 0);
            // таймаут выполнения команд в MS SQL, в СЕКУНДАХ
            setGlobalValueFromCfg("MSSQLCommandTimeout", 2);

            // уведомление Одерманов о готовом заказе
            setGlobalValueFromCfg("NoticeOrdermanFeature", false);
            setGlobalValueFromCfg <string>("NoticeOrdermanFolder", null);
            // проверка настроек ф-и уведомления
            if (AppProperties.GetBoolProperty("NoticeOrdermanFeature"))
            {
                string folder = (string)AppProperties.GetProperty("NoticeOrdermanFolder");
                if (folder == null)
                {
                    AppLib.WriteLogInfoMessage("Функция NoticeOrdermanFeature включена, но не указана папка для сохранения файлов-уведомлений NoticeOrdermanFolder");
                }
                else
                {
                    if (!folder.EndsWith(@"\"))
                    {
                        AppProperties.SetProperty("NoticeOrdermanFolder", folder + @"\");
                    }
                    if (!System.IO.Directory.Exists(folder))
                    {
                        AppLib.WriteLogInfoMessage("Функция NoticeOrdermanFeature включена, указана папка для сохранения файлов-уведомлений NoticeOrdermanFolder, но в системе эта папка не существует!");
                    }
                }
            }

            // режим сортировки заказов
            string ordersSortMode = "Desc";

            value = cfg["SortOrdersByCreateDate"];
            if ((value != null) && (value.Equals("Asc", StringComparison.OrdinalIgnoreCase)))
            {
                ordersSortMode = "Asc";
            }
            AppProperties.SetProperty("SortOrdersByCreateDate", ordersSortMode);

            // время ожидания в состоянии ГОТОВ (время, в течение которого официант должен забрать блюдо), в секундах
            setGlobalValueFromCfg("ExpectedTake", 0);

            // читать ли из БД выданные блюда
            setGlobalValueFromCfg("IsReadTakenDishes", false);
            // использовать ли двухэтапный переход в состояние ГОТОВ/ подтверждение состояния ГОТОВ (повар переводит, шеф-повар подтверждает)
            setGlobalValueFromCfg("UseReadyConfirmedState", false);
            // Время, в СЕКУНДАХ, автоматического перехода из Готово в ПодтвГотово, при включенном ПодтвГотово (UseReadyConfirmedState = true). Если отсутствует или равно 0, то автоматического перехода не будет.
            setGlobalValueFromCfg("AutoGotoReadyConfirmPeriod", 0);

            // учитывать ли отмененные блюда при подсчете одновременно готовящихся блюд для автостарта готовки
            setGlobalValueFromCfg("TakeCancelledInAutostartCooking", false);

            value = cfg["TimeOfAutoCloseYesterdayOrders"];
            TimeSpan ts = TimeSpan.Zero;

            if (value != null)
            {
                if (!TimeSpan.TryParse(value, CultureInfo.InvariantCulture, out ts))
                {
                    ts = TimeSpan.Zero;
                }
            }
            AppProperties.SetProperty("TimeOfAutoCloseYesterdayOrders", ts);

            setGlobalValueFromCfg("MidnightShiftShowYesterdayOrders", 0d);

            // неиспользуемые цеха
            value = cfg["UnusedDepartments"];
            if (!value.IsNull())  // не Null и не пусто
            {
                HashSet <int> unUsed = new HashSet <int>();
                if (value.Contains(','))
                {
                    value = value.Replace(',', ';');
                }
                int[] ids = value.Split(';').Select(s => s.Trim().ToInt()).ToArray();
                foreach (int item in ids)
                {
                    if ((item != 0) && !unUsed.Contains(item))
                    {
                        unUsed.Add(item);
                    }
                }

                if (unUsed.Count == 0)
                {
                    AppProperties.SetProperty("UnusedDepartments", null);
                }
                else
                {
                    AppProperties.SetProperty("UnusedDepartments", unUsed);
                }
            }
            else
            {
                AppProperties.SetProperty("UnusedDepartments", null);
            }

            // Максимальное количество архивных файлов журнала. По умолчанию, равно 0 (нет ограничения).
            value = cfg["MaxLogFiles"];
            AppProperties.SetProperty("MaxLogFiles", ((value == null) ? 0 : value.ToInt()));

            // отладочные сообщения
            setGlobalValueFromCfg("IsWriteTraceMessages", false);
            setGlobalValueFromCfg("TraceOrdersDetails", false);
            setGlobalValueFromCfg("IsLogClientAction", false);
            setGlobalValueFromCfg("TraceQueryToMSSQL", false);


            // ВНУТРЕННИЕ КОЛЛЕКЦИИ

            // коллекция для хранения готовящегося количества блюд по цехам (направлениям печати)
            AppProperties.SetProperty("dishesQty", new Dictionary <int, decimal>());
        }
Exemple #10
0
        public bool CreateNoticeFileForOrder()
        {
            OrderStatusEnum status = (OrderStatusEnum)_order.OrderStatusId;
            string          logMsg = $"Создание файла-уведомления для заказа № {_order.Number} (id {_order.Id}, status {status.ToString()})...";

            writeLogMsg(logMsg);

            // check notice folder
            string sResult = null;
            string folder  = (string)AppProperties.GetProperty("NoticeOrdermanFolder");
            bool   bResult = IntegraLib.AppEnvironment.CheckFolder(folder, out sResult);

            if (bResult == false)
            {
                writeLogMsg(" - " + sResult);
                return(false);
            }
            folder = sResult;

            bool            retVal = false;
            string          fileName = null, fileText = null;
            OrderStatusEnum toFileStatus = (OrderStatusEnum)_order.OrderStatusId;

            if (toFileStatus == OrderStatusEnum.ReadyConfirmed)
            {
                toFileStatus = OrderStatusEnum.Ready;
            }
            fileText = string.Format("Order UID: {1}{0}Order Id: {2}{0}Order Number: {3}{0}Order Status: {4} ({5}){0}Write Time: {7}{0}Waiter Name: {6}{0}Table Name: {8}",
                                     Environment.NewLine, _order.Uid, _order.Id, _order.Number,
                                     ((int)toFileStatus).ToString(), toFileStatus.ToString(),
                                     _order.Waiter, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                     _order.TableName);

            // для терминального состояния Готов ЗАКАЗА
            if (_order.IsReadyStatusFinal() == true)
            {
                fileName = $"{folder}ordNumber_{_order.Number}" + ".txt";
            }

            // иначе вывести в файл-уведомление БЛЮДА в состоянии Готово
            else
            {
                List <OrderDishModel> readyDishes = _order.GetDishesReadyStatFin();
                int cnt = readyDishes.Count;
                if (cnt > 0)
                {
                    IntegraLib.StringHelper.SBufClear();
                    foreach (OrderDishModel dish in readyDishes)
                    {
                        logMsg = $"   - блюдо '{dish.Name}' id {dish.Id}, status {((OrderStatusEnum)dish.DishStatusId).ToString()}";
                        writeLogMsg(logMsg);
                        IntegraLib.StringHelper.SBufAppendText(Environment.NewLine + getDishStrForNoticeFile(dish));
                    }
                    fileText += IntegraLib.StringHelper.SBufGetString();
                    fileName  = $"{folder}ordNumber_{_order.Number} ({cnt.ToString()} dishes)" + ".txt";
                }
                else
                {
                    writeLogMsg(" - нет блюд в состоянии ГОТОВ");
                }
            }

            if ((fileName != null) && (fileText != null))
            {
                try
                {
                    System.IO.File.WriteAllText(fileName, fileText);

                    writeLogMsg($" - файл '{fileName}' создан успешно");
                    retVal = true;
                }
                catch (Exception ex)
                {
                    writeLogMsg(" - Error: " + ex.Message);
                }
            }

            return(retVal);
        }
Exemple #11
0
        // создание файла уведомления о состоянии БЛЮДА
        // для заказа создается файл [номер заказа].txt, для блюда - [номер заказа]([id блюда]).txt
        // для блюда, не ингредиента, только, если сам заказ еще не готов и NoticeOrdermanDishNotice = 1 (создавать файл-уведомления для блюда)
        public bool CreateNoticeFileForDishes(string orderDishIds)
        {
            string logMsg = $"Создание файла состояния для блюд/id {orderDishIds} заказа № {_order.Number} (id {_order.Id})...";

            writeLogMsg(logMsg);

            if (orderDishIds.IsNull())
            {
                writeLogMsg(" - перечень id блюд - пустой!");
                return(false);
            }

            // check notice folder
            string sResult = null;
            string folder  = (string)AppProperties.GetProperty("NoticeOrdermanFolder");
            bool   bResult = IntegraLib.AppEnvironment.CheckFolder(folder, out sResult);

            if (bResult == false)
            {
                writeLogMsg(" - " + sResult);
                return(false);
            }
            folder = sResult;

            bool            retVal = false;
            string          fileName = null, fileText = null;
            OrderStatusEnum toFileStatus = (OrderStatusEnum)_order.OrderStatusId;

            if (toFileStatus == OrderStatusEnum.ReadyConfirmed)
            {
                toFileStatus = OrderStatusEnum.Ready;
            }
            fileText = string.Format("Order UID: {1}{0}Order Id: {2}{0}Order Number: {3}{0}Order Status: {4} ({5}){0}Waiter Name: {6}",
                                     Environment.NewLine, _order.Uid, _order.Id, _order.Number,
                                     ((int)toFileStatus).ToString(), toFileStatus.ToString(),
                                     _order.Waiter);

            int[] ids = orderDishIds.Split(';').Select(s => s.ToInt()).ToArray();
            if (ids.Length > 0)
            {
                IntegraLib.StringHelper.SBufClear();
                OrderDishModel dish;
                foreach (int dishId in ids)
                {
                    if (_order.Dishes.ContainsKey(dishId))
                    {
                        dish = _order.Dishes[dishId];
                        IntegraLib.StringHelper.SBufAppendText(Environment.NewLine + getDishStrForNoticeFile(dish));
                    }
                }
                fileText += IntegraLib.StringHelper.SBufGetString();

                fileName = $"{folder}ordNumber_{_order.Number} (dishes {orderDishIds})" + ".txt";
                try
                {
                    System.IO.File.WriteAllText(fileName, fileText);

                    writeLogMsg($" - файл '{fileName}' создан успешно");
                    retVal = true;
                }
                catch (Exception ex)
                {
                    writeLogMsg(" - Error: " + ex.Message);
                }
            }

            return(retVal);
        }