} // 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
} // 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