Проверить цену по диапазону и числу десятичных разрядов XSD

Учебные задачи

Цена от 0 до 9999.99 включительно, не более шести значащих десятичных цифр и двух дробных. Ограничения читаем из собственной схемы и проверяем на граничных значениях.

Где и как запускать

Учебная база: создайте серверный общий модуль УчебныеЗадачи (флаг Сервер). Код без директив вставьте в тело процедуры ВыполнитьПример() Экспорт. Вызовите её из серверного обработчика команды учебной обработки. Не запускайте в рабочей базе.

Подготовка

  1. Серверная процедура в учебной базе. Весь XSD находится в начале кода; сеть, справочники и файлы не нужны.

  2. Для XML десятичная точка записана как точка. В строках случаев намеренно есть значения за пределами контракта.

XSD = "<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema""
| xmlns:g=""urn:guide:limits"" targetNamespace=""urn:guide:limits"">
| <xs:simpleType name=""Price""><xs:restriction base=""xs:decimal"">
|  <xs:minInclusive value=""0""/><xs:maxInclusive value=""9999.99""/>
|  <xs:totalDigits value=""6""/><xs:fractionDigits value=""2""/>
| </xs:restriction></xs:simpleType>
| <xs:simpleType name=""Discount""><xs:restriction base=""xs:decimal"">
|  <xs:minExclusive value=""0""/><xs:maxExclusive value=""1""/>
| </xs:restriction></xs:simpleType>
| <xs:simpleType name=""Status""><xs:restriction base=""xs:string"">
|  <xs:whiteSpace value=""collapse""/>
|  <xs:enumeration value=""draft""/><xs:enumeration value=""published""/>
|  <xs:enumeration value=""closed""/>
| </xs:restriction></xs:simpleType>
| <xs:simpleType name=""Description""><xs:restriction base=""xs:string"">
|  <xs:minLength value=""3""/><xs:maxLength value=""20""/>
| </xs:restriction></xs:simpleType>
|</xs:schema>";
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(XSD);
Попытка
    Документ = Новый ПостроительDOM;
    DOM = Документ.Прочитать(Чтение);
    Чтение.Закрыть();
Исключение
    Чтение.Закрыть();
    ВызватьИсключение;
КонецПопытки;
Построитель = Новый ПостроительСхемXML;
Схема = Построитель.СоздатьСхемуXML(DOM.ЭлементДокумента);
Если Схема = Неопределено Тогда
    ВызватьИсключение "Не построена собственная схема ограничений";
КонецЕсли;
Набор = Новый НаборСхемXML;
Набор.Добавить(Схема);
Если Не Набор.Проверить() Тогда
    ВызватьИсключение "Не прошла проверка собственной схемы";
КонецЕсли;
Фабрика = Новый ФабрикаXDTO(Набор);

Определение = Схема.ОпределенияТипов.Получить("Price", "urn:guide:limits");
ТипМодели = Фабрика.Тип("urn:guide:limits", "Price");
Сообщить(Определение.Фасеты.Количество() = 4);

Для Каждого Фасет Из Определение.Фасеты Цикл
    Сообщить(Строка(Фасет.ТипКомпоненты) + ": " + Фасет.ЛексическоеЗначение);
    Сообщить("Типизированное значение: " + Строка(Фасет.Значение));
    Сообщить("Фиксирован в потомках: " + Строка(Фасет.Фиксированный));
    Сообщить(Фасет.ОпределениеПростогоТипа.Имя = Определение.Имя);
    Сообщить(Фасет.Контейнер <> Неопределено);
    Сообщить(Фасет.КорневойКонтейнер <> Неопределено);
    Сообщить(Фасет.Схема.ПространствоИмен = "urn:guide:limits");
    Сообщить(Фасет.Аннотация = Неопределено);
    Сообщить(Фасет.Компоненты.Количество() = 0);
    Фасет.ОбновитьЭлементDOM();
    Сообщить("XML-тег ограничения: " + Фасет.ЭлементDOM.ИмяЭлемента);
    КопияФасета = Фасет.КлонироватьКомпоненту(Истина);
    Сообщить(ТипЗнч(КопияФасета) = ТипЗнч(Фасет));
    Сообщить(КопияФасета.ЛексическоеЗначение = Фасет.ЛексическоеЗначение);
    Сообщить(Не Фасет.Содержит(КопияФасета));
КонецЦикла;

Для Каждого Граница Из Определение.Фасеты Цикл
    Если ТипЗнч(Граница) = Тип("ФасетМинимальногоВключающегоЗначенияXS")
        Или ТипЗнч(Граница) = Тип("ФасетМаксимальногоВключающегоЗначенияXS") Тогда
        Сообщить(Граница.Включающий И Не Граница.Исключающий);
    КонецЕсли;
КонецЦикла;
Случаи = Новый Массив;
Случаи.Добавить(Новый Структура("Текст,Ожидается", "0", Истина));
Случаи.Добавить(Новый Структура("Текст,Ожидается", "9999.99", Истина));
Случаи.Добавить(Новый Структура("Текст,Ожидается", "12.340", Истина));
Случаи.Добавить(Новый Структура("Текст,Ожидается", "-0.01", Ложь));
Случаи.Добавить(Новый Структура("Текст,Ожидается", "10000", Ложь));
Случаи.Добавить(Новый Структура("Текст,Ожидается", "12.345", Ложь));

Для Каждого Случай Из Случаи Цикл
    Допустимо = Ложь;
    Попытка
        ЗначениеМодели = Фабрика.Создать(ТипМодели, Случай.Текст);
        Допустимо = Истина;
    Исключение
        Сообщить("Отклонено: " + Случай.Текст + "; "
            + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
    Если Допустимо <> Случай.Ожидается Тогда
        ВызватьИсключение "Не совпал результат проверки значения: " + Случай.Текст;
    КонецЕсли;
    Сообщить(СтрШаблон("%1: допустимо = %2", Случай.Текст, Допустимо));
КонецЦикла;

Разбор по шагам

  1. Price наследует xs:decimal. Диапазон задают minInclusive/maxInclusive, точность — totalDigits/fractionDigits.

  2. Фасеты показывают лексическую запись, типизированное значение и связь с типом Price; это разные уровни представления.

  3. КлонироватьКомпоненту даёт отдельную копию ограничения в памяти. Копия не добавляется в исходную схему; Содержит проверяет компоненты, а не принадлежность числа диапазону.

  4. Включающий Истина означает, что обе граничные цены разрешены. У исключающих границ правило другое.

  5. Каждый случай проверяет создание настоящего ЗначениеXDTO. Несовпадение с ожидаемым результатом вызывает исключение.

  6. 12.340 и 12.34 представляют одно десятичное значение: завершающий ноль не увеличивает число значащих дробных разрядов.

Как проверить результат

  1. Четыре фасета: 0, 9999.99, 6 и 2; обе границы включающие.

  2. 0, 9999.99 и 12.340 принимаются; -0.01, 10000 и 12.345 отклоняются.

  3. Не должно быть исключения о несовпадении ожидаемого результата.

Ожидаемый результат

Шесть конкретных значений проверены по собственной модели цены с разбором диапазона и точности.

На что обратить внимание

  1. fractionDigits — максимум значащих дробных разрядов, не требование всегда печатать ровно два знака.

  2. Контракт цены не задаёт валюту, НДС, скидки и округление учётной системы.

  3. Содержит у фасета не проверяет число. Для проверки значения используем тип XDTO.

  4. Ожидаемые исключения перехватываются только вокруг отдельного создания значения, ошибки построения схемы не скрыты.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.