Мне нужно разработать программу на C#, где пользователи должны оплачивать счет (с фиксированной суммой) каждый месяц. Некоторые пользователи могут не заплатить в тот же месяц, когда им был отправлен счет, в результате чего возникнут просроченные платежи. Пользователь также должен иметь возможность проверить счет в Интернете по какому-либо идентификатору. Как мне подойти к этому?
Я думал о двух способах, но я не считаю их очень удовлетворительными.
Я создаю таблицу, в которой храню все счета вот так
+----+------+-----------+--------+--------+------------+
| Id | Code | CreatedOn | UserId | Amount | PaidOn? |
+----+------+-----------+--------+--------+------------+
| 1 | 1234 | 2018-04-1 | 1 | 100 | null |
| 2 | 1235 | 2018-05-1 | 1 | 210* | 2018-05-25 |
+----+------+-----------+--------+--------+------------+
* включает предыдущую сумму, текущую сумму и просроченную комиссию.
В этом случае я кэширую сумму, которую пользователь должен заплатить, и каждый месяц генерирую новый счет. Преимущества этого подхода заключаются в том, что когда пользователь вводит 1234, я могу проверить, не совпадают ли месяц и год, и указать им на самый последний счет, который они должны оплатить.
Также: нужен ли мне какой-то сервис, который генерирует их каждый месяц? Или всякий раз, когда администратор нажимает кнопку создания, я проверяю, существует ли уже счет для пользователя, если я не вставляю его?
Я храню только оплаченные счета. Я могу проверить, когда последний раз был оплачен счет, и отсюда рассчитать причитающуюся сумму. Однако проблема в том, что я не уверен, как мне обращаться с кодом. Поскольку счет-фактура по-прежнему будет печататься каждый первый день каждого месяца и отправляться пользователям, им нужен какой-то ссылочный код.
Одно из решений, которое я подумал, заключалось в том, чтобы иметь столбец GUID в таблице пользователей и использовать этот идентификатор для шифрования даты и времени в этом формате MMyyyy. Создаваемое значение всегда будет уникальным, и мне не нужно его нигде хранить. Поэтому, когда пользователь вводит ссылочный код, я расшифровываю дату и повторно создаю для него счет.
По сути, это все, но по какой-то причине оба эти метода кажутся неправильными.
@ vasily.sib В приведенных ниже предложениях не рекомендуется обновлять старые. Вместо этого просто создавайте новые каждый месяц. Спасибо за предоставленные библиотеки, я воспользуюсь комбинацией ответов здесь и информации, которую предоставит их бухгалтер, чтобы придумать определенное решение.





Я не думаю, что правильно добавлять сумму из предыдущих неоплаченных счетов к новым счетам-фактурам, это не то, как работает кредиторская задолженность. Вы выставляете новые счета-фактуры на новые товары, а затем, если есть неоплаченные счета-фактуры, вы можете выпустить Отчет, подтверждающий это.
Метод 2 лучше, но мне не нравится идея зашифрованной даты. Однажды начальник сказал мне, что налоговые органы ожидают, что номера счетов будут иметь последовательную нумерацию (и именно так работает программное обеспечение, такое как Quick Books). Кроме того, зашифрованные строки будут длинными и громоздкими.
Используйте метод 2, но используйте последовательные номера счетов и сохраняйте все счета, оплаченные или нет, я не вижу недостатков.
Обновлено:
О просроченных платежах (кстати, сайт QB хорош для общих вопросов и ответов по бухгалтерскому учету, например https://community.intuit.com/articles/1145979-can-i-enter-finance-charges-service-charges-or-late-fees-on-customer-invoices)
+----+------+-----------+--------+------------+------------+---------------+
| Id | Code | CreatedOn | UserId | LineAmount | PaidOn? | OtherCharges
+----+------+-----------+--------+------------+------------+---------------+
| 1 | 1234 | 2018-04-1 | 1 | 100 | null |
| 2 | 1235 | 2018-05-1 | 1 | 100 | 2018-05-25 | 10
+----+------+-----------+--------+------------+------------+---------------+
Я думаю, это должно быть больше похоже на это (кстати, вы должны проверить это в будущем, предполагая, что в какой-то момент будет несколько LineAmounts, сделайте это с типичным отношением один ко многим, но для простоты предположите здесь только 1).
Invoice.Id == 1 не был оплачен, поэтому плата за 10 может быть перенесена на Invoice.Id == 2 (всего 110).
Клиент по-прежнему должен оплатить Счет-фактуру 1, потому что Счет-фактура 2 не заменяет его.
Хорошо, поэтому, если я использую второй метод, скажем, я храню счет за этот месяц, а пользователь не платит, должен ли я добавить новый столбец для хранения просроченных сборов и в следующем счете добавить обычную сумму в сумма столбца, а просроченная сумма в соответствующем столбце? Я помечаю все как оплаченные после оплаты окончательного счета?
@ E.Hoxha Я добавил еще к ответу
Благодарю вас за вашу новость. Эта ссылка и ваш ответ в целом дали мне очень хорошее представление о том, как со всем этим справиться.
Относитесь к вещам такими, какие они есть:
Счет существует независимо от того, был он оплачен или нет. Это еще один шаг в его жизни. Итак, ваша база данных должна отражать этот факт.
Выставляйте реальный счет за каждый период, который пользователь использовал, и должен заплатить сумму за этот период. То есть в конце каждого месяца.
Как уже указывалось, используйте последовательную нумерацию счетов-фактур, независимо от того, оплачены они или нет.
Создайте еще одну таблицу с именем InvoicePayments, в которой вы будете хранить: InvoiceId | PaymentDate (и Amount, если вы хотите включить функцию частичных платежей по счету).
Время от времени (в зависимости от того, как часто вы хотите отправлять напоминания) просматривайте таблицу InvoicePayments, проверяйте те, которые подлежат оплате дольше, чем ваша политика, и отправляйте уведомления соответственно.
Не думаю, что мне нужна таблица InvoicePayments, так как частичные платежи не принимаются, все остальное хорошо. Однако как мне обращаться с пени за просрочку платежа? (Я вернусь к более конкретному способу их расчета, если необходимо)
Это нет проблема программного обеспечения. Пожалуйста, пожалуйста спросите бухгалтера, как обрабатываются счета в вашей стране. Неважно, красивый ли это дизайн базы данных или отличная архитектура программного обеспечения, в первую очередь он должен соответствовать правилам и положениям ваших налоговых органов.
Например, даже мысль об объединении двух счетов-фактур в один заставит налогового бухгалтера побледнеть и молча ускользнет в страну, в которой в моей юрисдикции нет договора об экстрадиции.
Если это домашнее задание, отлично. Выберите один вариант, пусть учитель оценит его и извлечет уроки. Если это реальное программное обеспечение, иди найди профессионала и пусть они выдадут вам требования. Вы разработчик программного обеспечения, неплохо не знать, как работает бухгалтерский учет. Это не наша работа. Но является наша работа - просить о помощи, а не просто подбрасывать ее.
Соберите требования от профессионала в области бухгалтерского учета. потом подумай о своем софте.
На самом деле это не домашнее задание и не «настоящее» программное обеспечение в том смысле, что имеет значение, будет ли оно соответствовать налоговым правилам или нормам. Но я думаю, что вы правы, поэтому я встречусь с их бухгалтером и попрошу их более подробно рассказать, как они хотят обрабатывать свои счета. +1 за «Но наша работа - просить о помощи, а не просто кричать». :П
Как насчет объединения этих двух методов? Вы можете создавать счет в начале каждого месяца, уведомлять пользователя по электронной почте со ссылкой на этот счет, а в следующем месяце (если счет не был оплачен) вы просто обновляете значение суммы и снова уведомляете пользователя. Для этого вам не нужна какая-то служба, просто используйте какой-нибудь планировщик (Cron, Windows Scheduler, Quartz.net и т. д.)