public static void WriteLogClientAction(string machineName, string format, params object[] paramArray) { if (AppProperties.GetBoolProperty("IsLogClientAction")) { _logger.Trace("clt {0}|{1}", machineName, string.Format(format, paramArray)); } }
// подробные действия о чтении заказов из БД public static void WriteLogOrderDetails(string msg) { if (AppProperties.GetBoolProperty("IsWriteTraceMessages") && AppProperties.GetBoolProperty("TraceOrdersDetails")) { _logger.Trace("svcDtl|" + msg); } }
// сообщения о действиях клиента public static void WriteLogClientAction(string machineName, string msg) { if (AppProperties.GetBoolProperty("IsLogClientAction")) { _logger.Trace(string.Format("clt {0}|{1}", machineName, msg)); } }
public static void WriteLogTraceMessage(string format, params object[] paramArray) { if (AppProperties.GetBoolProperty("IsWriteTraceMessages")) { _logger.Trace(format, paramArray); } }
// отладочные сообщения // стандартные действия службы public static void WriteLogTraceMessage(string msg) { if (AppProperties.GetBoolProperty("IsWriteTraceMessages")) { _logger.Trace(msg); } }
public static void WriteLogOrderDetails(string format, params object[] paramArray) { if (AppProperties.GetBoolProperty("IsWriteTraceMessages") && AppProperties.GetBoolProperty("TraceOrdersDetails")) { string msg = string.Format(format, paramArray); _logger.Trace("svcDtl|" + msg); } }
// 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>(); }
// *** 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
// сложить настройки из 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>()); }
// ctor // ДЛЯ НОВОГО БЛЮДА public OrderDishModel(OrderDish dbDish, OrderModel modelOrder) { _modelOrder = modelOrder; Id = dbDish.Id; Uid = dbDish.UID; DepartmentId = dbDish.DepartmentId; CreateDate = dbDish.CreateDate; Name = dbDish.DishName; FilingNumber = dbDish.FilingNumber; ParentUid = dbDish.ParentUid; Comment = dbDish.Comment; Quantity = dbDish.Quantity; DelayedStartTime = dbDish.DelayedStartTime; UID1C = dbDish.UID1C; // свойства объекта с зависимыми полями EstimatedTime = dbDish.EstimatedTime; _tsCookingEstimated = TimeSpan.FromSeconds(this.EstimatedTime); DishStatusId = dbDish.DishStatusId; Status = AppLib.GetStatusEnumFromNullableInt(dbDish.DishStatusId); // получить запись из таблицы состояний _dbRunTimeRecord = getOrderDishRunTimeRecord(dbDish.Id); _isDish = ParentUid.IsNull(); _isUseReadyConfirmed = AppProperties.GetBoolProperty("UseReadyConfirmedState"); _autoGotoReadyConfirmPeriod = AppProperties.GetIntProperty("AutoGotoReadyConfirmPeriod"); // словарь дат входа в состояние _dtEnterStatusDict = new Dictionary <OrderStatusEnum, DateTime>(); foreach (var item in Enum.GetValues(typeof(OrderStatusEnum))) { _dtEnterStatusDict.Add((OrderStatusEnum)item, DateTime.MinValue); } // создать словарь накопительных счетчиков _tsTimersDict = new Dictionary <OrderStatusEnum, TimeCounter>(); // таймер ожидания начала приготовления _tsTimersDict.Add(OrderStatusEnum.WaitingCook, new TimeCounter() { Name = OrderStatusEnum.WaitingCook.ToString() }); // таймер времени приготовления _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 (Quantity < 0) { if (Status != OrderStatusEnum.Cancelled) { UpdateStatus(OrderStatusEnum.Cancelled); } else { startStatusTimerAtFirst(); } } else { UpdateFromDBEntity(dbDish); // для новой записи DTS не сохранен startStatusTimerAtFirst(); } } // constructor