Демон HMED-M (Mediation) является ядром предбиллинга. Его задачей является обработка поступающих с коллектора разобранных CDR по заданным правилам.
Обработка происходит в процессоре по цепочке фильтров. После завершения обработки результат проверяется валидаторами.
Помимо общих настроек доступны следующие параметры:
sources: amqp: mediation: # входная очередь разобранных CDR # значение должно совпадать с выходной очередью HMED-C consumer: amqp/mediation destinations: amqp: ocs: # выходная очередь обработанных CDR # обработанные CDR передаются в тарификатор (HOCS) producer: amqp/ocs error: # выходная очередь CDR, обработанных с ошибкой producer: amqp/error handlers: default: destinations: # список выходных очередей - amqp/ocs error: destinations: # список выходных очередей для CDR, обработанных с ошибкой - amqp/error constants: # константы, доступные для использования в спецификациях фильтров через переменную $consts number_length: 11 routes: # константа может быть хэшем C26052: COMSTAR C26053: COMSTAR skip_trunks_b: # или массивом - C30052 - C30055 - C30056 workers: # список воркеров - processor: base/switch # воркер реализует процессор base со спецификацией switch |
Пример настройки фильтров:
filters: # тип фильтра set: # спецификация фильтра short_trunk_a_name: # условие выполнения фильтра condition: $cdr.trunk_a.like?('^C\d+') # обращение к полю CDR field: $trunk_a # установка локальной переменной value: $cdr.trunk_a[0:6].upper() short_trunk_b_name: condition: $cdr.trunk_b.like?('^C\d+') field: $trunk_b value: $cdr.trunk_b[0:6].upper() full_trunk_a_name: condition: $trunk_a.empty?() field: $trunk_a value: $cdr.trunk_a.upper() full_trunk_b_name: condition: $trunk_b.empty?() field: $trunk_b value: $cdr.trunk_b.upper() route_a_by_trunk_a: field: route_a value: $const.routes[$trunk_a] or $const.pl_route # использование констант route_b_by_trunk_b: field: route_b value: $const.routes[$trunk_b] or $const.pl_route route_b_to_primelink: condition: $cdr.route_a != $const.pl_route and $cdr.route_b != $const.pl_route field: route_b value: $const.pl_route replace: # Правила замены префиксов по транкам station_a_by_trunk: # использование локальной переменной $trunk_a, установленной в set-фильтре condition: $cdr.station_a.length().in?($const.short_numbers_length) and $trunk_a.in?($const.station_a_replacements_by_trunks) field: station_a map: - '^92144': '749992244' - '^92139': '749578739' - '^921627': '7495797627' - '^921389': '7495981389' - '^921942': '7495517942' - '^921360': '7495741360' - '^921701': '7495741701' - '^921779': '7495741779' - '^921789': '7495741789' - '^921195': '7495510195' - '^921213': '7495514213' - '^921460': '7495600460' - '^921470': '7495600470' - '^921402': '7495728402' - '^921147': '7495730147' - '^921988': '7495739988' - '^921991': '7495739991' - '^921280': '7495580280' - '^921080': '7495981080' - '^96784': '749996784' - '^44': '749992244' - '^39': '749578739' - '^627': '7495797627' - '^389': '7495981389' - '^1942': '7495517942' - '^360': '7495741360' - '^701': '7495741701' - '^779': '7495741779' - '^789': '7495741789' - '^195': '7495510195' - '^213': '7495514213' - '^460': '7495600460' - '^470': '7495600470' - '^402': '7495728402' - '^147': '7495730147' - '^988': '7495739988' - '^991': '7495739991' - '^280': '7495580280' - '^080': '7495981080' leading_8_in_short_station_a: condition: $cdr.station_a.length() == $const.short_number_length field: station_a map: - '^8': 7 leading_8_in_long_station_b: condition: $cdr.station_b.length() >= $const.number_length field: station_b map: - '^8': 7 leading_8_in_short_station_b: condition: $cdr.station_b.length() == $const.short_number_length field: station_b map: - '^8': 7 if: station_a_length_is_7: if: $cdr.station_a.length() == 7 then: - if/pl_short_number pl_short_number: if: $cdr.station_a.starts_with?('922') and $route_a == $const.pl_route # условие then: # цепочка фильтров в случае выполнения условия - prepend/station_a_with('7499') else: # цепочка фильтров в случае невыполнения условия - replace/station_a_by_trunk prepend: pl_922_station_a_with_7499: condition: $cdr.station_a.length() == 7 and $route_a == $const.pl_route and $cdr.station_a.starts_with?('922') field: station_a string: 7499 pl_922_station_b_with_7499: condition: $cdr.station_b.length() == 7 and $cdr.station_b.starts_with?('922') field: station_b string: 7499 tiny_numbers_in_station_b_with_7495: condition: $cdr.station_b.length() == 2 or $cdr.station_b.length() == 3 field: station_b string: 7495 |
processors: base: # спецификация процессора switch: # валидатор (тип/спецификация) validator: base/main # цепочка фильтров filters: - skip/if_duration_is_0 # тип/спецификация - set/short_trunk_a_name - set/full_trunk_a_name - set/route_a_by_trunk_a - replace/dash_in_station_a_with_zeros - if/station_a_length_is_7 - prepend/pl_922_station_a_with_7499 # в скобках передаются аргументы, доступные в фильтре через переменную $args # $args[1] - первый аргумент, $args[2] - второй и т.д. - prepend/station_a_with('7495') - prepend/station_a_with('7') - replace/leading_string_in_station_a('8495', '7495') - replace/cut_international_prefix_in_station_b ... map: # поля выходной CDR, формируемой после обработки # эти поля проверяются валидатором trunk_a: $cdr.trunk_a trunk_b: $cdr.trunk_b route_a: $cdr.route_a route_b: $cdr.route_b station_a: $cdr.station_a station_b: $cdr.station_b duration_sec: $cdr.duration_sec termination_code: $cdr.termination_code call_begin: $cdr.call_datetime service_code: "'M200'" |
validators: base: # спецификация валидатора main: fields: call_begin: # проверяемое поле type: float # тип значения (integer - целое число, float - десятичная дробь, string - строка) required: true # признак обязательности присутствия поля в CDR station_a: type: string required: true length: # проверка длины строки min: 11 max: 15 service_code: type: string required: true value: M200 # проверка значения (только для строк) ... |