コード例 #1
0
ファイル: OrderDishModel.cs プロジェクト: AlCher2018/KDS
        // метод, который возвращает значения полей даты/времени состояния
        private StatusDTS getStatusRunTimeDTS(OrderStatusEnum status)
        {
            StatusDTS retVal = new StatusDTS();

            switch (status)
            {
            case OrderStatusEnum.None:
                break;

            case OrderStatusEnum.WaitingCook:
                retVal.DateEntered  = Convert.ToDateTime(_dbRunTimeRecord.InitDate);
                retVal.TimeStanding = Convert.ToInt32(_dbRunTimeRecord.WaitingCookTS);
                break;

            case OrderStatusEnum.Cooking:
                retVal.DateEntered  = Convert.ToDateTime(_dbRunTimeRecord.CookingStartDate);
                retVal.TimeStanding = Convert.ToInt32(_dbRunTimeRecord.CookingTS);
                break;

            case OrderStatusEnum.Ready:
                retVal.DateEntered = Convert.ToDateTime(_dbRunTimeRecord.ReadyDate);
                if (_isUseReadyConfirmed)
                {
                    retVal.TimeStanding = Convert.ToInt32(_dbRunTimeRecord.ReadyTS);
                }
                else
                {
                    retVal.TimeStanding = Convert.ToInt32(_dbRunTimeRecord.WaitingTakeTS);
                }
                break;

            case OrderStatusEnum.ReadyConfirmed:
                retVal.DateEntered  = Convert.ToDateTime(_dbRunTimeRecord.ReadyConfirmedDate);
                retVal.TimeStanding = Convert.ToInt32(_dbRunTimeRecord.WaitingTakeTS);
                break;

            case OrderStatusEnum.Took:
                retVal.DateEntered  = Convert.ToDateTime(_dbRunTimeRecord.TakeDate);
                retVal.TimeStanding = Convert.ToInt32(_dbRunTimeRecord.WaitingCommitTS);
                break;

            case OrderStatusEnum.Cancelled:
                retVal.DateEntered = Convert.ToDateTime(_dbRunTimeRecord.CancelDate);
                break;

            case OrderStatusEnum.Commit:
                retVal.DateEntered = Convert.ToDateTime(_dbRunTimeRecord.CommitDate);
                break;

            case OrderStatusEnum.CancelConfirmed:
                retVal.DateEntered = Convert.ToDateTime(_dbRunTimeRecord.CancelConfirmedDate);
                break;

            default:
                break;
            }
            return(retVal);
        }
コード例 #2
0
        private void startStatusTimer(StatusDTS statusDTS)
        {
            DateTime dtEnterToStatus = statusDTS.DateEntered;

            if (_tsTimersDict.ContainsKey(this.Status) &&
                ((_curTimer == null) || (_curTimer.Enabled == false) || (_curTimer != _tsTimersDict[this.Status]) ||
                 (_curTimer.StartDT != _tsTimersDict[this.Status].StartDT))
                )
            {
                _curTimer = _tsTimersDict[this.Status];
                _curTimer.Start(dtEnterToStatus);
            }
        }
コード例 #3
0
ファイル: OrderDishModel.cs プロジェクト: AlCher2018/KDS
        // запуск таймера для обновленного состояния
        private void startStatusTimer(StatusDTS statusDTS)
        {
            DateTime dtEnterToStatus = statusDTS.DateEntered;

            // сохранить дату входа в состояние во внутреннем словаре
            _dtEnterStatusDict[this.Status] = dtEnterToStatus;

            if (_tsTimersDict.ContainsKey(this.Status) &&
                ((_curTimer == null) || (_curTimer.Enabled == false) || (_curTimer != _tsTimersDict[this.Status]) ||
                 (_curTimer.StartDT != _tsTimersDict[this.Status].StartDT))
                )
            {
                _curTimer = _tsTimersDict[this.Status];
                _curTimer.Start(dtEnterToStatus);
            }
        }
コード例 #4
0
ファイル: OrderDishModel.cs プロジェクト: AlCher2018/KDS
        // первый (инициализирующий) старт таймера
        private void startStatusTimerAtFirst()
        {
            StatusDTS statusDTS = getStatusRunTimeDTS(this.Status);

            // установить дату входа в состояние
            DateTime dtEnterState = statusDTS.DateEntered;

            if (dtEnterState.IsZero())
            {
                dtEnterState = DateTime.Now;
                setStatusRunTimeDTS(this.Status, dtEnterState, -1);
                saveRunTimeRecord();
                statusDTS = getStatusRunTimeDTS(this.Status);
            }

            startStatusTimer(statusDTS);
        }
コード例 #5
0
ファイル: OrderDishModel.cs プロジェクト: AlCher2018/KDS
        // обновить добавленный к списку зависимый ингредиент по родительскому блюду
        // т.е. для нового объекта в заказе
        private void updateIngredientByParentDish()
        {
            // найти уже существующее блюдо для данного ингредиента
            _parentDish = getParentDish();

            if (_parentDish != null)
            {
                StatusDTS dtsBase = _parentDish.getStatusRunTimeDTS(_parentDish.Status);
                // и если оно поменялось, то обновляем статус ингредиента
                if (this.DishStatusId != _parentDish.DishStatusId)
                {
                    StatusDTS preDtsBase = _parentDish.getStatusRunTimeDTS(this.Status);
                    UpdateStatus(_parentDish.Status, dtsBase.DateEntered, preDtsBase.TimeStanding);
                }
                else
                {
                    setStatusRunTimeDTS(this.Status, dtsBase.DateEntered, -1);
                    saveRunTimeRecord();

                    startStatusTimer(dtsBase);
                }
            }
        }
コード例 #6
0
        }     // method UpdateFromDBEntity

        // внешнее обновление СОСТОЯНИЯ заказа
        // параметр isUpdateDishStatus = true, если заказ БЫЛ обновлен ИЗВНЕ (из БД/КДС), то в этом случае дату входа в новое состояние для блюд берем из заказа
        //          isUpdateDishStatus = false, если заказ БУДЕТ обновлен по общему состоянию всех блюд
        public bool UpdateStatus(OrderStatusEnum newStatus, bool isUpdateDishStatus, string machineName = null)
        {
            // если статус не поменялся, то попытаться обновить только статус блюд
            if (this.Status == newStatus)
            {
                return(false);
            }

            bool     retVal  = false;
            string   sLogMsg = string.Format(" - ORDER.UpdateStatus() Id/Num {0}/{1}, from {2} to {3}", this.Id, this.Number, this.Status.ToString(), newStatus.ToString());
            DateTime dtTmr   = DateTime.Now;

            if (machineName == null)
            {
                AppLib.WriteLogOrderDetails(sLogMsg + " - START");
            }
            else
            {
                AppLib.WriteLogClientAction(machineName, sLogMsg + " - START");
            }

            // время нахождения в ПРЕДЫДУЩЕМ состоянии, в секундах
            int secondsInPrevState = 0;

            if (_curTimer != null) // если есть таймер предыдущего состояния
            {
                _curTimer.Stop();  // остановить таймер состояния
                // получить время нахождения в состоянии с момента последнего входа
                secondsInPrevState = _curTimer.IncrementTS;
            }
            // дата входа в новое состояние
            DateTime dtEnterToNewStatus = DateTime.Now;

            // обновление заказа по ПОСЛЕДНЕМУ состоянию блюд, если они есть
            if ((isUpdateDishStatus == false) && (_dishesDict.Values.Count > 0))
            {
                dtEnterToNewStatus = getMaxDishEnterStateDate(newStatus);
            }

            // сохранить новый статус ОБЪЕКТА в БД
            if (saveStatusToDB(newStatus, machineName))
            {
                // изменить статус в ОБЪЕКТЕ
                OrderStatusEnum preStatus = this.Status;
                this.Status   = newStatus;
                OrderStatusId = (int)Status;

                // сохраняем в записи RunTimeRecord дату входа в новое состояние
                setStatusRunTimeDTS(this.Status, dtEnterToNewStatus, -1);
                //  и время нахождения в предыдущем состоянии
                setStatusRunTimeDTS(preStatus, DateTime.MinValue, secondsInPrevState);
                // и в БД
                saveRunTimeRecord();

                // запуск таймера для нового состояния
                StatusDTS statusDTS = getStatusRunTimeDTS(this.Status);
                startStatusTimer(statusDTS);

                // обновить уже существующие блюда при внешнем изменении статуса заказа
                if (isUpdateDishStatus)
                {
                    bool dishUpdSuccess = true;  // для получения результата обновления через AND
                    try
                    {
                        foreach (OrderDishModel modelDish in _dishesDict.Values)
                        {
                            // только для блюд
                            if (modelDish.ParentUid.IsNull())
                            {
                                // дату входа в состояние берем из заказа, а время нахожд.в предыд.состоянии из самого блюда
                                dishUpdSuccess &= modelDish.UpdateStatus(newStatus, statusDTS.DateEntered);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        AppLib.WriteLogErrorMessage("Ошибка обновления статуса блюд при обновлении статуса заказа {0}/{1} с {2} на {3}: {4}", this.Id, this.Number, this.Status, newStatus, ex.ToString());
                        dishUpdSuccess = false;
                    }
                }
                retVal = true;
            }

            sLogMsg += " - FINISH - " + (DateTime.Now - dtTmr).ToString();
            if (machineName == null)
            {
                AppLib.WriteLogOrderDetails(sLogMsg);
            }
            else
            {
                AppLib.WriteLogClientAction(machineName, sLogMsg);
            }

            // различные действия после успешного изменения статуса заказа
            if (retVal)
            {
                // создание файла для Одермана (feature enable, ready status is terminal)
                if (OrdermanNotifier.IsEnable && IsReadyStatusFinal())
                {
                    OrdermanNotifier omanNotifier = new OrdermanNotifier(this);
                    bool             result       = omanNotifier.CreateNoticeFileForOrder();
                }
            }

            return(retVal);
        }  // method
コード例 #7
0
        // *** CONSTRUCTOR  ***
        public OrderModel(Order dbOrder)
        {
            Id               = dbOrder.Id; Uid = dbOrder.UID; Number = dbOrder.Number;
            TableName        = dbOrder.TableNumber;
            CreateDate       = dbOrder.CreateDate;
            HallName         = dbOrder.RoomNumber;
            Waiter           = dbOrder.Waiter;
            DivisionColorRGB = dbOrder.DivisionColorRGB;

            OrderStatusId = dbOrder.OrderStatusId;
            Status        = (OrderStatusEnum)dbOrder.OrderStatusId; //AppLib.GetStatusEnumFromNullableInt(dbOrder.OrderStatusId);

            _isUseReadyConfirmed = AppProperties.GetBoolProperty("UseReadyConfirmedState");

            _dishesDict = new Dictionary <int, OrderDishModel>();
            // получить отсоединенную RunTime запись из таблицы состояний
            _dbRunTimeRecord = getOrderRunTimeRecord(dbOrder.Id);

            // создать словарь накопительных счетчиков
            _tsTimersDict = new Dictionary <OrderStatusEnum, TimeCounter>();
            // таймер времени приготовления
            _tsTimersDict.Add(OrderStatusEnum.Cooking, new TimeCounter()
            {
                Name = OrderStatusEnum.Cooking.ToString()
            });
            // таймер времени ожидания выдачи, нахождение в состоянии Готов
            _tsTimersDict.Add(OrderStatusEnum.Ready, new TimeCounter()
            {
                Name = OrderStatusEnum.Ready.ToString()
            });
            if (_isUseReadyConfirmed)
            {
                _tsTimersDict.Add(OrderStatusEnum.ReadyConfirmed, new TimeCounter()
                {
                    Name = OrderStatusEnum.ReadyConfirmed.ToString()
                });
            }
            // таймер времени ожидания фиксации заказа, нахождение в состоянии Выдано
            _tsTimersDict.Add(OrderStatusEnum.Took, new TimeCounter()
            {
                Name = OrderStatusEnum.Took.ToString()
            });
            // таймер нахождения в состоянии отмены
            _tsTimersDict.Add(OrderStatusEnum.Cancelled, new TimeCounter()
            {
                Name = OrderStatusEnum.Cancelled.ToString()
            });

            // для нового объекта статус по умолчанию - В ПРОЦЕССЕ ГОТОВКИ
            if (this.OrderStatusId < 1)
            {
                OrderStatusEnum newStatus = OrderStatusEnum.Cooking;
                UpdateStatus(newStatus, false);
            }
            else
            {
                // обновить статус заказа по статусам всех блюд
                OrderStatusEnum eStatusAllDishes = AppLib.GetStatusAllDishes(dbOrder.Dishes);
                if ((eStatusAllDishes != OrderStatusEnum.None) &&
                    (this.Status != eStatusAllDishes) &&
                    ((int)this.Status < (int)eStatusAllDishes))
                {
                    UpdateStatus(eStatusAllDishes, false);
                }
            }

            StatusDTS statusDTS    = getStatusRunTimeDTS(this.Status);
            DateTime  dtEnterState = statusDTS.DateEntered;

            if (dtEnterState.IsZero())
            {
                dtEnterState = DateTime.Now;
                setStatusRunTimeDTS(this.Status, dtEnterState, -1);
                saveRunTimeRecord();
                statusDTS = getStatusRunTimeDTS(this.Status);
            }
            startStatusTimer(statusDTS);

            // добавить блюда к заказу
            //   расставить сначала блюдо, потом его ингредиенты, т.к. ингр.могут идти ПЕРЕД блюдом
            List <OrderDish>            dishParentList = dbOrder.Dishes.Where(d => d.ParentUid.IsNull()).ToList();
            Dictionary <int, OrderDish> dAll           = new Dictionary <int, OrderDish>();

            foreach (OrderDish dishParent in dishParentList)
            {
                if (dAll.ContainsKey(dishParent.Id) == false)
                {
                    dAll.Add(dishParent.Id, dishParent);

                    // отобрать ингредиенты
                    List <OrderDish> ingrList = dbOrder.Dishes.Where(ingr => (ingr.ParentUid == dishParent.UID) && (ingr.Id != dishParent.Id)).ToList();
                    foreach (OrderDish ingr in ingrList)
                    {
                        if (dAll.ContainsKey(ingr.Id) == false)
                        {
                            dAll.Add(ingr.Id, ingr);
                        }
                    }
                }
            }

            foreach (OrderDish dbDish in dAll.Values)   // dbOrder.OrderDish
            {
                if (this._dishesDict.ContainsKey(dbDish.Id) == false)
                {
                    OrderDishModel newDish = new OrderDishModel(dbDish, this);
                    this._dishesDict.Add(newDish.Id, newDish);
                }
            }
        }  // ctor
コード例 #8
0
ファイル: StatusDTS.cs プロジェクト: AlCher2018/KDS
        public override bool Equals(object obj)
        {
            StatusDTS obj2 = (StatusDTS)obj;

            return(DateEntered.Equals(obj2.DateEntered) && TimeStanding.Equals(obj2.TimeStanding));
        }
コード例 #9
0
ファイル: OrderDishModel.cs プロジェクト: AlCher2018/KDS
        }     // method

        // ******************************************
        //    ОСНОВНАЯ ПРОЦЕДУРА БИЗНЕС-ЛОГИКИ
        //    ПРИ ИЗМЕНЕНИИ СТАТУСА БЛЮДА или НЕЗАВИСИМОГО ИНГРЕДИЕНТА
        // ******************************************
        // команды на изменение статуса блюда могут приходить как от КДС, так и из FrontOffice (при чтении из БД)
        // состояния и даты сохраняются в БД при каждом изменении
        //  isUpdateParentOrder = true, если запрос на изменение состояния пришел от КДС, иначе запрос из внутренней логики, напр. автоматическое изменение статуса из ожидания в готовку
        public bool UpdateStatus(OrderStatusEnum newStatus,
                                 DateTime dtEnterState = default(DateTime), int preStateTS = 0, string machineName = null)
        {
            // если статус не поменялся для существующей записи, то ничего не делать
            if (this.Status == newStatus)
            {
                return(false);
            }

            // автоматический переход из Готово в ПодтвГотово: вход в режим отслеживания нахождения в состоянии Готов
            if ((_isUseReadyConfirmed == true) && (_autoGotoReadyConfirmPeriod > 0) &&
                (newStatus == OrderStatusEnum.Ready) && (this.Status != OrderStatusEnum.Ready))
            {
                _dtReadyStatusInput = DateTime.Now;
            }

            string   sLogMsg = string.Format(" - DISH.UpdateStatus() Id {0}/{1}, from {2} to {3}", this.Id, this.Name, this.Status.ToString(), newStatus.ToString());
            DateTime dtTmr   = DateTime.Now;

            if (machineName == null)
            {
                AppLib.WriteLogOrderDetails(sLogMsg + " - START");
            }
            else
            {
                AppLib.WriteLogClientAction(machineName, sLogMsg + " - START");
            }

            bool isUpdSuccess = false;

            // здесь тоже лочить, т.к. вызовы могут быть как циклческие (ингр.для блюд), так и из заказа / КДС-а
            lock (this)
            {
                // время нахождения в ПРЕДЫДУЩЕМ состоянии, в секундах
                int secondsInPrevState = 0;
                if (_curTimer != null) // если есть таймер предыдущего состояния
                {
                    _curTimer.Stop();  // остановить таймер состояния
                    // получить время нахождения в состоянии с момента последнего входа
                    secondsInPrevState = _curTimer.IncrementTS;
                    // Debug.Print("secondsInPrevState {0}", secondsInPrevState);
                }
                if (preStateTS != 0)
                {
                    secondsInPrevState = preStateTS;
                }

                // дата входа в новое состояние: или то, что передано, или текущую
                DateTime dtEnterToNewStatus = DateTime.Now;
                // если переданы данные из родительского объекта (заказ или блюдо для ингредиентов)
                if (!dtEnterState.IsZero())
                {
                    dtEnterToNewStatus = dtEnterState;
                }

                // сохранить новый статус ОБЪЕКТА в БД
                if (saveStatusToDB(newStatus, machineName))
                {
                    // изменить статус в ОБЪЕКТЕ
                    OrderStatusEnum preStatus = this.Status;
                    this.Status       = newStatus;
                    this.DishStatusId = (int)newStatus;

                    // **** запись или в RunTimeRecord или в ReturnTable
                    StatusDTS statusDTS = getStatusRunTimeDTS(this.Status);
                    if (statusDTS.DateEntered.IsZero())
                    {
                        // сохраняем дату входа в новое состояние
                        setStatusRunTimeDTS(this.Status, dtEnterToNewStatus, -1);
                        // сохраняем в записи RunTimeRecord время нахождения в предыдущем состоянии
                        setStatusRunTimeDTS(preStatus, DateTime.MinValue, secondsInPrevState);

                        saveRunTimeRecord();
                    }
                    // возврат в предыдущие состояния, создать новую запись в Return table
                    else
                    {
                        saveReturnTimeRecord(preStatus, newStatus, dtEnterToNewStatus, secondsInPrevState);
                        // при возврате из Ready в Cooking обнулять в RunTime-record дату входа в состояние Ready
                        // чтобы при следующем входе в Ready таймер ожидания выноса начал считаться с периода ExpectedTake
                        if (!_isUseReadyConfirmed && (preStatus == OrderStatusEnum.Ready) && (newStatus == OrderStatusEnum.Cooking))
                        {
                            _dbRunTimeRecord.ReadyDate = DateTime.MinValue;
                        }
                        if (_isUseReadyConfirmed && (preStatus == OrderStatusEnum.ReadyConfirmed) &&
                            ((newStatus == OrderStatusEnum.Cooking) || (newStatus == OrderStatusEnum.Ready)))
                        {
                            _dbRunTimeRecord.ReadyConfirmedDate = DateTime.MinValue;
                        }
                    }

                    // запуск таймера для нового состояния
                    statusDTS = getStatusRunTimeDTS(this.Status);
                    startStatusTimer(statusDTS);

                    // попытка обновить статус ЗАКАЗА проверкой состояний всех блюд/ингредиентов
                    _modelOrder.UpdateStatusByVerificationDishes();

                    isUpdSuccess = true;
                }
            }

            sLogMsg += " - FINISH - " + (DateTime.Now - dtTmr).ToString();
            if (machineName == null)
            {
                AppLib.WriteLogOrderDetails(sLogMsg);
            }
            else
            {
                AppLib.WriteLogClientAction(machineName, sLogMsg);
            }

            return(isUpdSuccess);
        }  // method UpdateStatus