Архитектура приложения. Мозговой штурм.

ikenni

Новичок
Доброго дня/ночи!

[php 5.2.17, mysql 5.5.9]

Есть ли у кого на примете литература, в которой имеются примеры реализации сложных задач?
Различные ухищрения, структуры, способы работы с данными и их хранением.

----------------------------------------------------------------------------------------------------

Работаю над проектом. Система по управлению договорами на приобретение автомобиля в рассрочку.
Довольно долго уже мучаюсь с "архитектурой" приложения. Результат в принципе есть, однако в целом приложение получается громоздким, уверен, что его будет трудно поддерживать на плаву.

Итак, в базе создается договор:

- Статус договора (открыт | закрыт)
- Дата заключения договора
- Дата закрытия договора

- Предварительная стоимость
- Процент предварительной оплаты
- Сумма предварительной оплаты

- Окончательная стоимость
- Дата установки окончательной стоимости

- Срок кредита
- Срок отсрочки (дается только в начале, например 1 месяц)

- Процент годовых
- Процент пенальти

----------------------------------------------------------------------------------------------------

Каждый день договор нужно обрабатывать, для получения конечно вердикта отделного договора. Существуют крайние сроки, - это день в месяце, переступив за который и не оплатив ежемесячную задолжность, клиенту начисляется пеня. Сумма ежемесячной задолжности не постоянна и изменяется из-за курса доллара.

В какой-то момент я решил, что легче всего обрабатывать каждый день, от начала кредитного срока. Обработка заканчивается в следующих случаях:
- Достигнут конец договора (т.е. обработаны все месяцы, их обычно 12)
- Достигнута сегодняшняя дата
- Достигнута дата закрытия договора
- Найдена ошибка (например: отсутствует необходимый курс на определенную дату)

На словах все это более или менее просто.
Однако, с учетом:
- реализации обработчиков ошибок
- необходимых реализаций разветвления сценария обработки
- формирования определенных структур данных для облегчения
- прочих мелочей
количество строк кода достигает примерно 2-3 тысяч строк.

Желающим поштурмовать и подискутировать, вопрос: какие предложите реализации обработки?
 

WMix

герр M:)ller
Партнер клуба
приветствую
[Budweiser 0.5l 5.0% vol]

а можно пример "реализации обработки", чтобы было понятно о чем разговор...
 

AmdY

Пью пиво
Команда форума
я в такие моменты использую минд карты дл наглядности
 

ikenni

Новичок
Полагаю, я должен заранее извинится, так как неуверен, понятно ли все расписал.
Я пришел к данному варианту обработки как раз используя mind-maps.
Должен признаться, не совсем понимал что и почему делаю, но руки рисовали и печатали код.
Моя цель - найти более элегантное и простое решение.

Причины побудившие меня создать топик:
- Мысль о том, что я могу ошибатся в выбранном мною пути разработки;
- Громоздкость конструкции, трудности поддержания проекта на плаву;

-----------------------------------------------------------------------------

Процесс обработки договора следующий:

1. Извлекаем договор из базы данных
2. Проверяем на наличие ошибок. Существуют критические поля, отстутствие данных в которых прекращает обработку. Если ошибки обнаружены, но не в критических полях, обработка продолжается, а пользователь в конечном итоге будет оповещен.
3. Создается массив крайних сроков с учетом выходных дней. Дата крайнего срока генерируется исходя из даты заключения договора, если дата выпадает на выходные дни, дата меняется вперед или назад в пределах месяца.
4. Извлекаются все платежи, закрепленные за данным договором.
5. Извлекается диапазон курсов доллара.
6. Вычисляется ежемесячная сумма оплаты без учета курса доллара
7. Вычисляется сумма пени.
8. Вычисляется процент годовых на один месяц.
9. Вычисляется общая сумма годовых за весь период.
10. Устанавливается специальная переменная $balance. Когда поступает платеж, прибавляем, когда наступает новый месяц, убавляем нужную сумму исходя из ситуации. Если крайний срок преодолен, а задолжность не погашена, убавляем каждый за каждый день сумму пени.
- $balance = 0.0;
- $balance = -$monthlyPayment;
- $balance = +$paymentAmount;
- $balance = -$penaltyAmount;
11. Определяется конечная дата. Дата окончания договора.
12. Определяется начальная дата. Дата заключения договора (01.01.2013) + отсрочка (1 месяц) = начальная точка (01.02.2013)
13. Приступить к расчету только в том случае, если начальная точка уже достигнута, в ином случае выйти из обработки.
14. Из массива крайних сроков организуем массив $calendar. Ниже будет ясно зачем.

Далее идет цикл:
1. Проверяем, обрабатываемая дата совпала с обрабатываемой? Если да - выходим.
2. Проверяем, обрабатываемая дата совпала с датой окончания договора? Если да - выходим.
3. Проверяем платежи. Если платеж на обрабатываемую дату есть, прибавляем к переменной $balance сумму платежа. После проверяем массив $calendar, на наличие значения true у $isDeadlineOvercome (достигнут ли крайний срок) у предшествующих месяцев и если да, то устанавливаем значение false.
4. Проверяем, совпадает ли обрабатываемая дата с датой крайнего срока и если баланс ниже нуля, начисляем пеню и меняем значение $isDeadlineOvercome на true в массиве $calendar в обрабатываемом месяце.
5. Переход на следующий день $point->modify('+1 day');
6. Проверяем, не перешли ли мы на следующий месяц?
7. Повторяем цикл.

Примечание:
- Помимо переменных $isDeadlineOvercome в массиве $calendar, есть еще локальная одноименная переменная. Это необходимо для того чтобы начислять n-ное количество раз пеню, если клиент вдруг просрочил оплату на несколько месяцев.
- Массив $calendar служит для собирания данных. Поступил платеж? добавляем в соответствующий месяц данные. Пеня? также. В последствии, пользователь сможет остледить логику системы.
 

WMix

герр M:)ller
Партнер клуба
все описанное звучит как решение конкретной задачи... не совсем понятно что ты ожидаешь услышать, что есть смысл, к примеру, поменять пункт 1 и 2 местами - это ничего не меняет!
2-3 тысяч строк средний показатель, оно конечно много для одного файла, но не критично... большая часть решения ложится на модель я так понимаю.

может нужно более конкретно окунуться в тот или иной путнкт?
1. перебираем договора
2. на каждый договор вызов метода обработка договора...

далее практически каждый пункт таит в себе метод...
валидация, генерирование "крайних сроков с учетом выходных дней", дай платежи, курс доллара ... и тд. смысл перечислять написанное?

работает? проверял? каждый день проверял? тогда ничего не трогай!
 

ikenni

Новичок
WMix

Была мысль "усложнил всё", но устроив сегодня мозговой штурм на целый день, снова пришел к выводу, что все на своих местах.
Благодарю за поддержку и ответы,
но не откажусь от дальнейшей дискусии, если кто желает )
 

WMix

герр M:)ller
Партнер клуба
я не против, только пока не понимаю что обсуждать... тут уже все решено! я не знаю как ты решил, но то что ты описываешь по шагам, говорит что ты уже продумал все!...
усложнять не нужно, нужно упростить.... но это возможно когда появится еще пару задачек которые являются частью описанного + еще что-нибудь... и тут станет понятно как структурировать методы...
 

Тугай

Новичок
Бухгалтерская задача, решается не бухгалтерскими методами.
Бухгалтерский метод это, когда задолженность и пеня пишется в колонку Дебет с датой, а погашение задолженности в колонку Кредит с датой. И баланс на дату это разница между сумой колонок Дебет и Кредит.
Три типа операций: начисление задолженности, начисление пени, оплата. Короче надо наполнять таблицу Операция(Дата, Тип операции, СуммаДт, СуммаКт).

Возможно у вас все верно, но вообще-то так считать непринято.
Для иллюстрации:
Вася занял у Коли $100 и у Пети $50. Потом Вася купил сникерс за $20 и отдал $30 долга Коле.
Итак Вася должен $70 Коле и $50 Пете - итого $120.
У Васи сникерсов на $20 и $120 долга, т.е. $140 , а заняли $150, куда же делись $10 ?
 

WMix

герр M:)ller
Партнер клуба
Тугай
это совершенно не правильное представление.... все что написано конечно верно но в рамках всего предприятия, а тут конкретная задача....

дописать на конту задолжности +100 а васе -100 не составит труда... но это ничего не решает...
что дает тебе знание, что на конте всех пользователей, сумма равна сумме долгов клиентов + сумма дебитов клиентов? зачем этот гимор?
У Васи сникерсов на $20 и $120 долга, т.е. $140
20+(-120) = -100
 

Тугай

Новичок
:) -100 это, что такое ?
В том и дело, что сникерсы с долгом нельзя не складывать, не вычитать, иначе получаем хрень как $140 или вообще -100.
Если баланс считается не просто как разница между дебетом и кредитом, то сделать такую ошибку все вероятнее.
 

Тугай

Новичок
банк касса иии пишется негатив
долга 120, товаров 20, денег 100
Что ж тогда "моском" штурмовать? Давать себе установку отличать плюс от минуса на завтра (супер что для вас это не проблема) или даже не заморачиваться и просто следовать проверенной сотнями лет методологии.
В финансах "фреймворкам" лет и лет и "PHP" тут просто младенец может даже не вылупившийся. :)
Там давно своя модульность: оплаты, задолженность, пеня и т.п. Все это должно быть само по себе и независимо. Все это работает на "баланс".
И поскольку тс задался вопросом архитекутуры,, то он он избретает ее заново причем не верно, поскольку если спутать плюс и минус, то при его подходе ошибку найти далеко не просто.
 

WMix

герр M:)ller
Партнер клуба
это разные задачи, одна сводить баланс, другая начислять пении.
всегда можно добавить сводку баланса, но можно и переложить эти задачи на бухгалтера, который думает о большем!
 

Тугай

Новичок
Задача тс - это посчитать сальдо(именно во множественном числе) по договору на сегодня по начальным условиям.
Мн. число потому, что это сколько осталось выплатить(пени, ежемесячных платежей и далее как договорятся и т.п. и не дай бох)
То, что формально расчет пени самый сложный и "много строк кода", та какая нахрен разница сколько там строк кода, если рассчитывается реально только пеня?
Об этом я и говорю, что сложность расчета пени влияет на весть проект, а это быть просто не должно.
Если этой проблемы нет , то и "штурмовать" нечего.

(Это я про архитектуру, все подзадачи расчета баланса или сальдо по договору должны быть сами по себе, но реально существуют четкие зависимости, как расчет пени, только после начисления задолженности и определения крайних сроков и учета оплаты и т.п.
Как это красиво выразить в программе это второй вопрос. Красивый вариант формировать" конфиги", в которых будет прописан порядок выполнения мини обработок,
но как говорят лучшее враг хорошего и это зависит он платежеспособности заказчика и лени программиста).
 
  • Like
Реакции: AmdY

WMix

герр M:)ller
Партнер клуба
мы говорим о разном... чтоб писать проводку, ее нужно посчитать! эту задачу описывает ТС... а после делай что хочешь!
как тебе поможет двойная бухгалтерская запись, для выбора даты, курса доллара и тд, не понимаю!
 

ikenni

Новичок
Тугай

Думается мне, введение бухгалтерской фичи лишь усложнит структуру/понимание результата,
но я обязательно сяду на днях за данный вариант,
спасибо за потраченное время )
 

AmdY

Пью пиво
Команда форума
Тугай прав в главном
Это я про архитектуру, все подзадачи расчета баланса или сальдо по договору должны быть сами по себе
ты пытаешься сразу проглотить огромный кусок, думаешь о базе, валидации, конвертации, расчётах и проверки сроков. Если будешь решать задачу за раз, то она будет сложная, а если по частям, то у тебя будут легко вырисовываться на каждую один-два класса с парой методов и небольшая проблема будет только в рефакторинге для связи решений задач.
Такой кусок ни ты, ни тем более местные, плохо знакомые с деталями, решить за раз не смогут.
 
Сверху