На основе запроса OrderSelectSqlQuery, который описан в серверном xml-файле, создадим запрос для получения списка заказов для мобильного приложения:
Template.xml
<SqlQueryName="AppOrderSelectSqlQuery"> <Text> WITH _filter AS ( SELECT date_trunc('week', CURRENT_DATE::timestamp) AS start_date, date_trunc('week', CURRENT_DATE::timestamp) + interval '7d - 1s' AS end_date ), _order AS ( SELECT O.order_id, O.client_id, C.city_id, O.order_number, O.order_date FROM template.order O LEFT JOIN template.client C USING(client_id) LEFT JOIN _filter ON true WHERE O.added AND NOT O.deleted AND O.order_date BETWEEN convert_date_filter(_filter.start_date) AND convert_date_filter(_filter.end_date) ), _order_position AS ( SELECT O.order_id, SUM(OP.quantity * OP.unit_price) AS total_cost, COUNT(O.order_id) AS position_count FROM _order O JOIN template.order_position OP USING(order_id) LEFT JOIN template.material M USING(material_id) GROUP BY O.order_id ), _payment AS ( SELECT O.order_id, SUM(C.summ) AS total_payment_summ FROM _order O JOIN template.order_payment OP USING(order_id) JOIN template.cash C USING(cash_id) WHERE NOT C.deleted GROUP BY O.order_id ) SELECT O.order_id AS "OrderId", '№ ' || O.order_number AS "OrderNumber", 'от ' || to_char(convert_date_to_user_timezone(O.order_date), 'dd.mm.yyyy') AS "OrderDate", client.title AS "ClientTitle", OP.position_count AS "PositionCount", 'Сумма ' || trim(to_char(COALESCE(OP.total_cost, 0), '999G999G999D00') || ' руб.') AS "TotalOrderCost", (COALESCE(OP.total_cost, 0) - COALESCE(P.total_payment_summ, 0)) <![CDATA[<=]]> 0 AS "IsPaid" FROM _order O LEFT JOIN _order_position OP USING(order_id) LEFT JOIN _payment P USING(order_id) LEFT JOIN template.client USING(client_id) ORDER BY O.order_number ASC; </Text></SqlQuery>
В качестве периода отображения заказов будем использовать текущую неделю - позже реализуем фильтр по датам, как делали на главной форме в приложении для ПК.
Номер и дату заказа (OrderNumber и OrderDate) выводим разными строками, заранее задав им нужный формат. Обратите внимание, что дату заказа сразу приводим к часовой зоне пользователя, чтобы она отображалась корректно. Как вы помните, при передаче даты со временем в формате строки, платформа не делает автоматическое приведение временных зон. И без ручного приведения временной зоны, даты со временем останется во временной зоне сервера. Работа с датами со временем подробно рассматривается в статье Временные зоны.
В запрос добавили поле PositionCount, хранящее количество позиций заказа, и поле IsPaid - признак полной оплаты заказа. Теперь возвращаем имена клиентов вместо идентификаторов, т.к. в отличии от таблицы DatabaseTable список CollectionView не поддерживает Substitution.
Перейдем в файл главной формы (TemplateMainForm.xml).
Самостоятельно создайте соответствующий PrimaryGetDataConnection.
Теперь создадим объект типа CollectionView, который представляет данные в виде списка карточек:
тэг <EmptyText> содержит текст-заглушку, который будет отображаться, если в списке нет записей;
В тэге <SourceDataConnection> указывается источник данных, каждой записи (строке) которого будет соответствовать отдельная карточка;
В тэге <TemplateItems> описывается набор элементов шаблона карточки
Шаблон карточки
Для начала добавим в шаблон карточки два поля: номер заказа, должен отображаться в верхнем левом углу, и дата заказа, должна отображаться в правом верхнем углу.
Номер заказа - это простое текстовое поле, для него будем использовать элемент типа TemplateItemLabel:
В тэгах <Top> и <Left> задаются абсолютные значения отступов от границ контейнера, с учетом внутренних отступов контейнера для его содержимого.
В тэге <Text> указывается текст, отображаемый в поле на карточке. При этом можно указать текст значением тэга, тогда такой текст будет одинаков на всех карточках. А можно указать атрибут Binding с именем одного из полей источника данных из тэга <SourceDataConnection>, в таком случае значение будет индивидуально для каждой карточки. Значение тэга <Text> и атрибут Binding вместе не работают - предпочтение отдается атрибуту.
В тэгах <FontStyle> и <TextColor> настраиваем стиль текста, его цвет и размер.
Для дата заказа также будем использовать элемент типа TemplateItemLabel:
Так как поле должно отображаться в правом верхнем углу, то координату <Left> переведем из абсолютного значения в пропорциональное. Для этого используем тэг <AbsoluteLayoutFlags> со значением XProportional. Теперь в тэге <Left> указываем не величину сдвига, а коэффициент, который будет использоваться для расчета координаты по формуле:
Аналогичным образом можно задавать пропорциональное значение для координаты <Top> - YProportional, а так же одновременно для координат <Top> и <Left> - PositionProportional. Пропорции можно задавать для ширины и высоты элемента - WidthProportional и HeightProportional соответственно, а так же одновременно для высоты и ширины - SizeProportional. Если необходимо для всех четырех значений использовать пропорциональные, то следует указывать All.
Запустите приложение и проверьте расположение объектов в карточке списка.
Под номером и датой заказа добавим поля с именем клиента и суммой заказа:
В качестве условия видимости элемента в атрибуте Binding тэга <Visible> укажем поле IsPaid.
Чтобы статус визуально выделялся, зададим цвет фона текста в тэге <BackgroundColor> и радиус скругления углов фона в тэге <CornerRadius>. Зададим высоту элемента в 25 единиц.
Чтобы текст был по центру блока, используем тэг <TextAlignment>, с указанием правил выравнивания для вертикали и горизонтали.
Тэг <Padding> добавит внутренние отступы текста от границ фона. слева и справа укажем - так блок будет выглядеть симпатичнее.
Стоит помнить, что по умолчанию текст всегда выравнивается по верхней части своего блока. Если высота элемента будет больше, например, 40, то внутреннего отступа в 2е единицы будет недостаточно. В таком случае лучше :
Отлично! Запустим приложение, чтобы проверить отображение всех элемнтов карточки.
Для начала создайте форму, которую будем использовать для редактирования заказа, выбранного в списке. Пока достаточно пустой формы, чтобы проверить переход на новый экран при выборе заказа в списке.
Чтобы получить значение поля из строки источника данных, соответствующей выделенной карточке, будем использовать get-проперти SelectedItemValueByFieldName, которое принимает один параметр FieldName с именем этого поля. Например, получим значение из поля OrderId:
Самостоятельно наполните форму редактирования заказа необходимыми полями и списком позиций заказа. Пока форму оставим без сохранения данных на сервер, но с возможностью чтения всех данных о заказе.
Итоги
На уроке мы рассмотрели процесс аутентификации пользователя, .
Ответы
В архиве присутствуют xml-файлы форм для мобильного приложения и серверный xml-файл, также лежит бэкап базы данных и файл с запросами на изменение структуры базы данных - с помощью файлов можете проверить себя.
Архив не содержит xml-файлы форм десктопного приложения.