kenoma / refugee.questionnaire Goto Github PK
View Code? Open in Web Editor NEWПроект для помощи беженцам и пострадавшим от боевых действий
Проект для помощи беженцам и пострадавшим от боевых действий
В некоторых пунктах нужно доделать выбор:
Например постельное белье
-подушка (кол-во)
В целях упрощения диагностики предлагаю сделать логи более информативными - как минмум не хватает таймстампов. Возможно имеет смысл добавить еще какую-либо инфу в них.
Как лучше:
По просьбе заказчика удалить поля и не сохранять в базу (в том числе во избежание хранения лишних ПД):
UserId
Id
IsCompleted
FirstName
LastName
IsAdmin
Добавлять в начало к значению поля Username символ @
Переименовать столбец Username в "Telegram"
Переименовать столбец Timestamp в "Дата заполнения" (для краткости - на самом деле в идеале там будут дата-время - см. #3 )
Необходимо пользователям без даты присваивать не текущую дату а например
public DateTime Created { get; set; } =Convert.ToDateTime("01.01.2000");
Задавать вопрос "Есть возможность помочь с жильем?" (да/нет), и если да - задаем про жилье вопросы, если нет - сразу следующий блок
Вариант реализации 1 (сложный, универсальный):
1)добавить в конфиг столбец Answers: пусто или json {"Да":EnableCategoryButton, "Нет":Button} (тогда выводить кнопки: Да, Нет и т.п.)
Вариант 2 (простой, не универсальный, но на 95% нужен только он):
В ValidationRegex писать "(Да|Нет)", и тогда показывать кнопки Да, Нет и считать этот вопрос триггером категории
Ключ и админов скинул в личку, опросник лежит в demo-mirsklad-ref-quest-6.csv
Вместо текста
———
Год рождения (в формате: 2022)
———
написать текст
———
Год рождения — например, 1982 (нужен только год рождения, а не дата)
———
В боте Белгорода при отправке анкеты выдавать сообщение:
———
Спасибо! Ваша анкета отправлена команде волонтёров Белгорода "Путь в будущее" https://t.me/putvbud
———
Реализовать возможность чтения конфига с любыми концами строк Windows/Unix на любой ОС
Не заливать ячейки черным/темно-серым/темно-коричневым цветом при обнаружении дублей - тогда не видно текст.
Проверено на версии 0.0.2
на выгружается часть архива с последнего архива с 11.07-24.07
в самом архиве записи есть, локально отрабатывает
на сервере памяти добавляли
PS может что то с библиотекой excel
Добрый день, увидел статью о вас в группе СМ.
Можете добавить контакты для связи, либо где можно получить информацию о доске и текущих задачах и требуемом функционале?
Работаю с похожим стеком, думаю, мог бы помочь.
QuestionnaireEntry
нужно добавить новое поле string[] AnswerVariations
. которое должно корректно считываться из csv (конвертер можно запилить в QuestionnaireEntryClassMap
).1|2|3|4
SendQuestMessageToUser
проверять, если ли варианты AnswerVariations
или нет, если есть - рендерить вопрос с блоком кнопокTryProcessStateMachineAsync
Бот https://t.me/help_refugees_voronezh_bot
Файл ref-9036.csv
Нужно исправить:
Добавить необязательный параметр командной строки для выбора направления сортировки по времени:
asc - старые записи сверху, новые снизу
desc - старые снизу, новые сверху (как сейчас)
По умолчанию, если параметр не указан, выбирать asc
Как лучше:
Переименовать Перезаполнить на Изменить (волонтеры просили). И по нажатию - уходить вглубь (не удалять все сразу). Далее в глубине - аналогичный принцип.
Для прозрачности писать не просто
Пользователь @... повышен до администратора.
А так:
@ повысил пользователя @... до администратора.
Добавить ключ ,булевый --check-config
, при указании которого запуска приложения не происходит, а происходит вычитывания файла с вопросами и выход с кодом возврата 0, если файл валидный, и не 0, если невалидный.
1 Добавить в LiteDbRepo и в IRepository соответственно
RefRequest[] GetRequestsDt(DateTime dt);
RefRequest[] GetRequestsDtArch(DateTime dt);
UserData[] GetUsersDt(DateTime dt);
public RefRequest[] GetRequestsDt(DateTime dt)
{
using var db = new LiteDatabase(Path.Combine(_dbPath, "current_requests.ldb"));
var collection = db.GetCollection<RefRequest>(nameof(RefRequest));
collection.EnsureIndex(z => z.Id);
collection.EnsureIndex(z => z.TimeStamp);
return collection.Find(z => z.TimeStamp > dt).OrderBy(z => z.TimeStamp).ToArray();
}
public RefRequest[] GetRequestsDtArch(DateTime dt)
{
var getAllArchives = Directory.GetFiles(_dbPath, "*current_requests.ldb");
var retval = new List<RefRequest>();
foreach (var archive in getAllArchives)
{
using var db = new LiteDatabase(archive);
var collection = db.GetCollection<RefRequest>(nameof(RefRequest));
collection.EnsureIndex(z => z.Id);
collection.EnsureIndex(z => z.TimeStamp);
retval.AddRange(collection.Find(z => z.TimeStamp > dt).OrderBy(z => z.TimeStamp));
}
return retval.OrderBy(t => t.TimeStamp).ToArray();
}
public UserData[] GetUsersDt(DateTime dt)
{
using var db = new LiteDatabase(Path.Combine(_dbPath, "users.ldb"));
var collection = db.GetCollection<UserData>(nameof(UserData));
collection.EnsureIndex(z => z.Token);
collection.EnsureIndex(z => z.UserId, unique: true);
collection.EnsureIndex(z => z.Created);
return collection.Find(z => z.Created > dt).OrderBy(z => z.Created).ToArray();
}
в контролер QuestionariesArchiveController.cs
/// <summary>
/// Возвращает записи из таблицы от даты
/// </summary>
/// <returns></returns>
/// <response code="200">Список анкет</response>
/// <response code="401">Не передан токен для доступа</response>
[HttpGet("refrequestDt")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public IActionResult GetRecordsDate([FromHeader(Name = "X-Volunteer-Token")] string token, [Required(ErrorMessage = "Установите дату")] DateTime? dt)
{
_logger.LogTrace("Someone requested {Method} with {Token}", nameof(GetRecords), token);
if (!_repo.IsKnownToken(token))
{
return Unauthorized();
}
var records = _repo.GetRequestsDt((DateTime)dt);
return Ok(records);
}
/// <summary>
/// Возвращает записи из архива от даты
/// </summary>
/// <returns></returns>
/// <response code="200">Список анкет</response>
/// <response code="401">Не передан токен для доступа</response>
[HttpGet("refrequestDtArch")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public IActionResult GetRecordsDateArch([FromHeader(Name = "X-Volunteer-Token")] string token, [Required(ErrorMessage = "Установите дату")] DateTime? dt)
{
_logger.LogTrace("Someone requested {Method} with {Token}", nameof(GetRecords), token);
if (!_repo.IsKnownToken(token))
{
return Unauthorized();
}
var records = _repo.GetRequestsDtArch((DateTime)dt);
return Ok(records);
}
/// <summary>
/// Возвращает записи пользователей из хранилища бота по дате
/// </summary>
/// <returns></returns>
/// <response code="200">Список пользователей</response>
/// <response code="401">Не передан токен для доступа</response>
[HttpGet("usersdt")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public IActionResult GetUsersDate([FromHeader(Name = "X-Volunteer-Token")] string token, [Required(ErrorMessage = "Установите дату")] DateTime? dt)
{
_logger.LogTrace("Someone requested {Method} with {Token}", nameof(GetRecords), token);
if (!_repo.IsKnownToken(token))
{
return Unauthorized();
}
var records = _repo.GetUsersDt((DateTime)dt);
return Ok(records);
}
4 в QuestionariesArchiveController -> GetRecords сортировку по дате
var records = _repo.GetAllRequests().OrderByDescending(z => z.TimeStamp);
Далеко не всегда человек который запускает бота, и человек, котоырй должен быть в нём админом, один и тот же человек.
Было бы гораздо удбнее, если бы был ключ командной строки --adminID, куда можно было бы передать идентификатор админского пользователя при запуске. Это исключит возможность кому-то левому стать "первым написавшим."
Навигация по меню. Сценарий: Открыть пункт меню с вопросами, например, Одежда и обувь / Верхняя одежда. Ответить на вопросы. После этого бот возвращается на самый верхний уровень меню. Тесты на людях показали, что это сбивает с толку. Надо оставаться на том же уровне меню (в примере - внутри Одежда и обувь). Для глубоких пунктов это еще и сэкономит время, чтобы не искать их снова для продолжения (пример - Одежда и обувь / Обувь).
Чтобы была преемственность данных при изменении текста вопроса, добавить в конфиг анкеты поле ColumnName (без ограничений набора символов, в т.ч. русские буквы с пробелами) и использовать его как ключ поля + выводить в заголовке в отчетах
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.