Разработка микро-учётной системы на lua, часть вторая. Постановка задачи

Теперь немного о самой задумке. Предполагается, что программа будет соответствовать следующим условиям:

  • Максимально возможная переносимость,
  • Быстрый унифицированный интерфейс,
  • Возможность максимально быстрого изменения данных,
  • Отсутствие необходимости в фиксации времени модификации документа,
  • Необходимость в отслеживании баланса по клиентам (сальдо).


Программа должна определённым образом управлять информацией. На входе ей должны предоставляться:

  • Данные о клиенте: имя / наименование и связаные телефоны, причём телефонов может быть больше двух;
  • Данные о позиции: наименование и стоимость. Данный тип используется для фиксаций операций и затрат — то есть, позиция может иметь как отрицательную, так и положительную стоимость (выплаты заказчика + затраты на оборудование / дорогу / операции и прочие радости);
  • Данные для формирования документа, собраные из предыдущих;


На выходе пользователь должен получать следующую структуру:

  • Каталог пользовательских данных,
  • Каталог телефонов с привязкой к пользователям,
  • Каталог позиций с возможностью редактирования,
  • Каталог документов с возможностью изменения клиентских выплат.


Теперь договоримся о терминологии.
Клиент — юридическое или физическое лицо, которому услуга предоставляется. В программе клиента представляют его имя / наименование и телефон. Мне больше и не надо.
Позиция — описание графы прихода / затрат денежных средств, имеющих свою стоимость. Стоимость может быть как положительная (выплата от заказчика, оплата расходов и прочее), так и отрицательная (оплата заказа / расходов, не- или недовыплаты по оказаным услугам и так далее). Состоит из наименования и фактической стоимости.
Документ — учётная структура, хранящая данные о стоимости позиции и фактическом покрытии клиентом затрат на неё.
Сальдо — фактическая разница между объёмом оказанных клиенту услуг и выплаченного денежного эквивалента. В программе будет использоваться как общее сальдо, так и отдельное на каждого клиента.

Программа создавалась при следующих условиях:

  • Отсутствие в необходимости делегирования пользовательского доступа для обработки информации;
  • Интерфейс должен быть быстрым, потому наибольший интерес представляют различные виды текстового интерфейса;
  • Ради возможности максимального переноса кода (например, на Win-машину с установленным комплектом «Lua for Windows») сам код был максимально упрощён, как и среда разработки. Это означает минимальное время развёртки программы в другой среде и меньшее количество правок при использовании утилиты luac.
  • Отработка минимально необходимого количества функций позволила упростить до крайней степени схему базы и алгоритмы её обслуживания;
  • И да, я не делал отработку ошибок при выполнении запросов — я постарался их максимально исключить. Да, я дилетант в Lua, но мне сейчас больше и не нужно. Качество кода приходит со временем.


Теперь о структуре программы:

  • Программа состоит из модулей: главного, множества исполнительных и модуля доступа к базе. Взаимодействие происходит в режиме конвейера;
  • Главный модуль не имеет доступ к модулю управления базой, но имеет экземпляры исполнительных. Исполнительные модули уже имеют доступ к экземпляру модуля доступа.
  • Программа после выполнения команды возвращается в главное меню.


Взаимодействие модулей программы, источника данных и человека выглядит так:
image
Схема пользовательских прецедентов (use case) выглядит так:

Большая схема use case. Желательно открыть в новой закладке.
image


Пользовательские сценарии делятся на следующие категории:

  • Управление пользовательскими данными, которая в свою очередь делится на функции управления телефонным справочником и списком клиентов;
  • Управление позициями — функции создания, модификации, просмотра и удаления;
  • Управление документацией;
  • Рассчёт баланса по документам: общий и для отдельного пользователя.


База данных представляет собой набор таблиц, связанных с помощью первичных автоинкрементных ключей. Дополнительно используется отображение при выдаче общей информации (хотя это спорное решение):
image
Передача данных происходит через прослойку модуля database, являющегося модулем доступа. Исполнительные формы создают запросы, которые в него и посылают. Все данные исполнительные модули разбирают самостоятельно. По факту, database является контейнером для экземпляра класса «luasql-sqlite3», соединённого с базой.

Маленькая деталь. Базу пришлось создавать через программу sqliteman, поскольку инициализация таблицы с первичным ключём автовычисляемого типа (autoincrement) при ручном формировании запроса не работает. Но, на всякий случай, я сформировал дамп базы для последующей развёртки:

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE "feedback" (
    "number" INTEGER PRIMARY KEY AUTOINCREMENT,
    "customer" TEXT,
    "phone" INTEGER
);

CREATE TABLE "customer" (
    "number" INTEGER PRIMARY KEY AUTOINCREMENT,
    "name" TEXT
);

CREATE TABLE "position" (
    "number" INTEGER PRIMARY KEY AUTOINCREMENT,
    "nominal" TEXT,
    "price" REAL
);

CREATE TABLE "document" (
    "number" INTEGER PRIMARY KEY AUTOINCREMENT,
    "customer" INTEGER,
    "position" INTEGER,
    "income" REAL
);

DELETE FROM sqlite_sequence;
INSERT INTO "sqlite_sequence" VALUES('customer',8);
INSERT INTO "sqlite_sequence" VALUES('feedback',10);
INSERT INTO "sqlite_sequence" VALUES('position',2);
INSERT INTO "sqlite_sequence" VALUES('document',6);
CREATE VIEW "journal" AS select document.number, customer.name, position.nominal, document.income, position.price
from document, customer, position
where document.customer = customer.number
and document.position = position.number;
COMMIT;

И на сладкое — скриншот работы приложения:

Главное меню.
image


Отработка расчёта баланса по клиенту.
image

И да, это быстрый текстовый интерфейс! Зато не замучаюсь с переносом программы (с GTK — зависимым интерфейсом) на другую машину!

В следующих статьях буду отдельно рассказывать про работу отдельных модулей программы и выкладывать их исходные коды.

© Habrahabr.ru