Услуга в NoDeny - это запись в таблице users_services, которая наделяет учетную запись клиента определенными характеристиками, например, разрешает доступ в интернет.
Поле tags хранит через запятую теги, указывающие на характер действия услуги, например, стандартные:
SELECT uid FROM users_services WHERE tags LIKE '%,inet,%';
На одну учетную запись можно активировать несколько разных услуг, например, клиент может заказать услугу «доступ в интернет 2 Мбит/сек», а через время «повышение скорости в 2 раза на 1 день». Эти услуги могут сосуществовать вместе, при этом первая будет иметь теги inet и speed, а вторая только speed.
В таблице users_services хранятся персональные для клиента свойства услуги, а общие в таблице services. Связь по полю service_id. В свою очередь в таблице services поле module ссылается на модуль, который обрабатывает данный тип услуг.
Персональные свойства услуги: время старта услуги, время окончания услуги, теги, id услуги, которая будет подключена после окончания текущей и id платежа, в котором происходит списание денег за услугу.
Услуга может быть «вечной», т.е. не иметь времени окончания, пока администратор не удалит ее. Услуга может быть бесплатной, т.е id платежа = 0. Услуга может не иметь автопродления, т.е. id услуги, которая будет установлена после завершения текущей, = 0.
Общие свойства услуги задаются в таблице services: имя, описание, группы клиентов, которые могут заказать услугу, стоимость. Также в закодированном виде содержатся параметры, специфичные для конкретного модуля услуг. Поскольку невозможно предусмотреть абсолютно все возможные свойства для всех услуг, специфичные параметры хранятся в виде perl-дампа в поле param.
Поле module ссылается на файл, обрабатывающего услугу. Пример такого файла:
#!/usr/bin/perl
package services::test;
use strict;
sub description
{
return 'Услуга ничего не делает, просто снимает деньги';
}
sub tunes
{
return [];
}
sub set_service
{
my(undef, %p) = @_;
my $service_new = $p{service_new};
my $actions = $p{actions};
$actions->{pay} = {
cash => 0 - $service_new->{price},
comment => $service_new->{description},
category=> 100,
discount=> $service_new->{discount},
};
}
1;
Модуль услуги должен иметь такие подпрограммы:
В примере подпрограмма tunes возвращает ссылку на пустой массив, т.е дополнительных полей нет. set_service указывает сделать всего одно действие: платеж с категорией 100.
Подпрограмма set_service должна вернуть список действий, которые будут выполнены при подключении услуги:
$actions->{sql}{1} = [
'INSERT INTO tbl SET field=?', 'xxx'
];
$actions->{pay} = {
cash => 10,
comment => 'Пополнение счета на 10$',
category=> 2,
};
$actions->{set_service} = {
period => 60*60,
mode => 0,
tags => ',x-tag,',
};
Здесь в массиве @$fields хранятся те специфичные параметры, о которых было сказано выше: срок действия, входящая и исходящая скорости. В описании полей ключ type указывает на тип поля по классу Data, например, 1 - целое положительное число. Значение value будет предложено администратору при создании услуги.
Метод set_service должен вернуть хеш - список действий, которые выполнит модуль services при подключении услуги. В примере:
Любое из действий необязательно, однако формат конкретных действий строг.