Форма поиска банка Primer. Часть 5. Фильтрация записей
Это пятая статья из серии, посвященной описанию процесса разработки управляющей формы, предназначенной для отбора кандидатов на работу в демонстрационном банке кадрового агентства Primer.
Предыдущие статьи серии:
Часть 2. Организуем контроль правильности ввода
В предыдущей части мы окончательно сформировали строчный запрос на отбор записей из базы “Лицо” с учетом ограничений на возраст, специальность по образованию, опыт работы и место проживания.
Сегодня выполним финальную работу по отбору: отфильтруем отобранный запросом набор записей с учетом ограничений по стажу работы на определенных должностях.
В общих чертах алгоритм нашей работы выглядит так:
- перебрать полученный в результате выполнения запроса набор записей ЛЦ;
- для каждой такой записи получить набор связанных с ней записей ТД, соответствующих критерию отбора на опыт работы, сохраненному нами в
conditions.career
; - для каждой записи из полученного набора ТД, подсчитать стаж работы как разницу между датой увольнения и датой начала работы;
- просуммировать полученные временные интервалы и исключить из исходного набора ЛЦ записи, у которых результат ниже ограничения, указанного в поле
experience
таблицыconditions
.
Прежде чем браться за реализацию данного алгоритма нам необходимо научиться вычислять временной интервал между датой начала работы и датой окончания для конкретной записи базы “Трудовая деятельность”.
Первая задача, которую нам необходимо при этом решить, - преобразовать значения полей типа “Дата”, которые являются строками в объекты типа DateTime, которые можно использовать в вычислениях. Вторая - научиться получать корректные значения DateTime для случаев, когда дата указана в сокращенном формате (00.00.ГГГГ) или не указана вовсе.
Будем придерживаться следующей стратегии:
- записи, в которых не указана дата начала (явное нарушение ограничений целостности), не будем учитывать при подсчете;
- если дата окончания не указана, ее следует принять равной текущей дате;
- даты, превышающие текущую, также следует приравнивать к текущей;
- дату начала работы, заданную в сокращенном формате следует принять равной дате начала соответствующего периода (месяца или года), дату окончания - равной максимальной дате в соответствующем периоде.
При таком подходе периоды работы, в которых не указана дата окончания, будут трактоваться как продолжающиеся по сей день, а периоды работы, в которых даты указаны сокращенно, будут трактоваться в пользу кандидата - как максимально возможные.
Опишем функцию makedate
, которая возвращает корректное значение DateTime, принимая на вход строковое значение val
, содержащее дату, и строковый параметр mode
(значения min
или max
, по умолчанию min
), указывающий требуется ли вернуть минимальную дату периода или максимальную:
function makedate(val,mode)
-- пустое значение: дата отсутствует
if val == "" then
return DateTime.Now
end
local date = DateTime(val)
if date.IsValid and date <= DateTime.Now then
return date
elseif date.IsValid then
return DateTime.Now
end
-- обработка неполных дат
if not mode or mode == "min" then
val = val:gsub("^00%.","01.")
val = val:gsub("%.00%.",".01.")
return DateTime(val)
else
local day, month, year = unpack(val:split(".",0,true,tonumber))
if month == 0 then
month = 12
end
if day == 0 then
local last = {31,28,31,30,31,30,31,31,30,31,30,31}
day = last[month]
end
date = DateTime()
date.Year, date.Month, date.Day = year, month, day
return date
end
end
А теперь используем эту функцию в реализации нашего алгоритма фильтрации записей ЛЦ.
function FilterByExperience(rs)
-- фильтрация по стажу
for rec in rs.Records do
local td_rs = rec:GetValue(90,"ТД")
if conditions.career then
td_rs:StringRequest("ОТ "..conditions.career)
end
local exp = DateTimeSpan()
for td in td_rs.Records do
if td:GetValue(1) ~= "" then
local start = makedate(td:GetValue(1))
local finish = makedate(td:GetValue(2),"max")
exp = exp + (finish - start)
end
end
if exp.Days/365 < conditions.experience then
rs:Remove(rec.SN)
end
end
return rs
end
Осталось внести дополнения в блок отображения найденных записей функции btnFind_Click
:
-- отображение найденных записей
if conditions.experience then
rs = FilterByExperience(rs)
end
GetBank():GetBase("ЛЦ"):OpenReview(rs)
Me.WindowState = Form.Minimized
На этом наша работа, связанная с реализацией отбора записей, завершена. В последней статье данной серии мы сделаем небольшие улучшения пользовательского интерфейса, связанные с обработкой событий от клавиатуры.
Дополнительные материалы
Текст модуля формы поиска на данный момент
Страница создана на основе шаблона flexible-jekyll