Ejemplo n.º 1
0
 def set_changes(self, calc):
     """Устанавливает новые данные для вычислений."""
     self.calc = calc
     self.dateSpinBox.set_border_date(
         bottom=date_plus_months(
             calc.first_date if not calc.data else max(calc.data), \
             1, initdate=calc.first_date),
         top=date_plus_months(calc.first_date, calc.first_period))
     self.__calculation(initiator='pp_date')
Ejemplo n.º 2
0
 def set_changes(self, calc):
     """Устанавливает новые данные для вычислений."""
     self.calc = calc
     self.dateSpinBox.set_border_date(
         bottom=date_plus_months(
             calc.first_date if not calc.data else max(calc.data), \
             1, initdate=calc.first_date),
         top=date_plus_months(calc.first_date, calc.first_period))
     self.__calculation(initiator='pp_date')
Ejemplo n.º 3
0
    def __init__(self, parent, calc, *arg, **kw):
        """Графическая форма для получения платежа/даты досрочного погашения"""
        super(AdvancedRepayment, self).__init__(parent, *arg, **kw)
        self.calc = calc

        self.configure(bg='light goldenrod')

        self.plan_paymentVar = StringVar()

        planedLabel = Label(self,
                            text="Досрочное погашение",
                            width=20,
                            anchor=CENTER,
                            bg='cornsilk')
        ppLabel = Label(self,
                        text="Платеж:",
                        width=20,
                        anchor=CENTER,
                        bg='cornsilk')
        pdLabel = Label(self,
                        text="Дата:",
                        width=20,
                        anchor=CENTER,
                        bg='cornsilk')
        planedLabel.grid(row=0,
                         column=0,
                         columnspan=2,
                         padx=2,
                         pady=2,
                         sticky=EW)
        ppLabel.grid(row=1, column=0, padx=2, pady=2, sticky=W)
        pdLabel.grid(row=1, column=1, padx=2, pady=2, sticky=W)

        self.ppVar = StringVar()
        self.ppEntry = FloatEntry(self,
                                  width=20,
                                  from_=0,
                                  textvariable=self.ppVar,
                                  justify=CENTER)
        self.ppEntry.bind(
            '<Any-KeyRelease>',
            lambda *ign: self.__calculation(initiator='pp_payment'))
        self.ppEntry.bind('<FocusOut>',
                          lambda *ign: self.__calculation(initiator='pp_date'))
        self.ppEntry.grid(row=2, column=0, padx=2, pady=2, sticky=SW)

        self.dateSpinBox = MySpinBoxDate(
            self,
            first_date=date_plus_months(calc.first_date, calc.period // 2),
            t_date=date_plus_months(calc.first_date, calc.period),
            b_date=date_plus_months(calc.first_date, 1))
        self.dateSpinBox.check_changes(
            lambda *ign: self.__calculation(initiator='pp_date'))
        self.dateSpinBox.grid(row=2, column=1, padx=2, pady=2, sticky=E)

        self.__calculation(initiator='pp_date')
Ejemplo n.º 4
0
    def remove_row(self, date):
        """Удаляет все нижние строки ничиная с указанной даты"""
        if self.last_date is not None:
            assert date <= self.last_date, 'Нет такой даты'
        else:
            return
        x, y = self.canvas.coords(str(date))
        self.canvas.addtag_overlapping(
            'delete', int(x), int(y),
            *[int(float(i)) for i in \
              self.canvas['scrollregion'].split(' ')[2:4]]
            )
        self.canvas.delete('delete')
        self.canvas.dtag('delete')
        self.canvas.config(scrollregion=(0, 0, self.canvas_width, int(y)))

        for d in sorted(self.expend_rowVars.keys(), reverse=True):
            if d < date:
                break
            del self.expend_rowVars[d]
            del self.changing_cells[d]

        self.last_date = date_plus_months(date, -1, initdate=self.first_date) \
                         if not len(self.expend_rowVars) == 0 else None
        if self.last_date is None:
            self.first_date = None
            self.canvas.create_text(
                312 if not sys.platform == 'win32' else 240,
                180 if sys.platform == 'win32' else 140,
                tags='init_text',
                font=('New Roman', 12),
                text=('Здесь будет таблица с информацией о Ваших платежах\n'
                      '(после добавления платежа)'),
                justify=CENTER)
Ejemplo n.º 5
0
 def wrapper(self, *arg, **kw):
     date = self.calculation.date
     result = func(self, *arg, **kw)
     self.calculation.remove_payment(
         date_plus_months(date, 1,
                          initdate=self.calculation.first_date))
     return result
Ejemplo n.º 6
0
    def remove_row(self, date):
        """Удаляет все нижние строки ничиная с указанной даты"""
        if self.last_date is not None:
            assert date <= self.last_date, 'Нет такой даты'
        else:
            return
        x, y = self.canvas.coords(str(date))
        self.canvas.addtag_overlapping(
            'delete', int(x), int(y),
            *[int(float(i)) for i in \
              self.canvas['scrollregion'].split(' ')[2:4]]
            )
        self.canvas.delete('delete')
        self.canvas.dtag('delete')
        self.canvas.config(
            scrollregion=(0, 0, self.canvas_width, int(y)))

        for d in sorted(self.expend_rowVars.keys(), reverse=True):
            if d < date:
                break
            del self.expend_rowVars[d]
            del self.changing_cells[d]

        self.last_date = date_plus_months(date, -1, initdate=self.first_date) \
                         if not len(self.expend_rowVars) == 0 else None
        if self.last_date is None:
            self.first_date = None
            self.canvas.create_text(
                312 if not sys.platform == 'win32' else 240,
                180 if sys.platform == 'win32' else 140, tags='init_text',
                font=('New Roman', 12),
                text=('Здесь будет таблица с информацией о Ваших платежах\n'
                      '(после добавления платежа)'),
                justify=CENTER)
Ejemplo n.º 7
0
 def expand_row(self, date):
     """Метод разворачивает строку с соответствующей датой."""
     if self.expend_rowVars[date].get():
         # сдвинули область скрола
         self.canvas.config(
             scrollregion=(
                 0, 0, self.canvas_width,
                 int(float(self.canvas['scrollregion'].split(' ')[3])) + \
                 self.row_height*(len(self.__names)+1)
                 )
             )
         # разварачиваем строку
         if date != self.last_date:
             x, y = self.canvas.coords(
                 str(date_plus_months(date, 1, initdate=self.first_date)))
             self.canvas.addtag_overlapping(
                 'move', int(x), int(y),
                 *[int(float(i)) for i in \
                   self.canvas['scrollregion'].split(' ')[2:4]]
                 )
             self.canvas.move('move', 0,
                              self.row_height * (len(self.__names) + 1))
             self.canvas.dtag('move')
         self.canvas.itemconfig(str(date),
                                height=self.row_height *
                                (len(self.__names) + 2))
     else:
         if date != self.last_date:
             x, y = self.canvas.coords(
                 str(date_plus_months(date, 1, initdate=self.first_date)))
             self.canvas.addtag_overlapping(
                 'move', int(x), int(y),
                 *[int(float(i)) for i in \
                   self.canvas['scrollregion'].split(' ')[2:4]])
             self.canvas.move('move', 0,
                              -self.row_height * (len(self.__names) + 1))
             self.canvas.dtag('move')
         self.canvas.itemconfig(str(date), height=self.row_height)
         self.canvas.config(
             scrollregion=(
                 0, 0, self.canvas_width,
                 int(float(self.canvas['scrollregion'].split(' ')[3]) - \
                     self.row_height*(len(self.__names)+1))
                 )
             )
Ejemplo n.º 8
0
 def expand_row(self, date):
     """Метод разворачивает строку с соответствующей датой."""
     if self.expend_rowVars[date].get():
         # сдвинули область скрола
         self.canvas.config(
             scrollregion=(
                 0, 0, self.canvas_width,
                 int(float(self.canvas['scrollregion'].split(' ')[3])) + \
                 self.row_height*(len(self.__names)+1)
                 )
             )
         # разварачиваем строку
         if date != self.last_date:
             x, y = self.canvas.coords(
                 str(date_plus_months(date, 1, initdate=self.first_date)))
             self.canvas.addtag_overlapping(
                 'move', int(x), int(y),
                 *[int(float(i)) for i in \
                   self.canvas['scrollregion'].split(' ')[2:4]]
                 )
             self.canvas.move(
                 'move', 0, self.row_height*(len(self.__names)+1))
             self.canvas.dtag('move')
         self.canvas.itemconfig(
             str(date), height=self.row_height*(len(self.__names)+2))
     else:
         if date != self.last_date:
             x, y = self.canvas.coords(
                 str(date_plus_months(date, 1, initdate=self.first_date)))
             self.canvas.addtag_overlapping(
                 'move', int(x), int(y),
                 *[int(float(i)) for i in \
                   self.canvas['scrollregion'].split(' ')[2:4]])
             self.canvas.move(
                 'move', 0, -self.row_height*(len(self.__names)+1))
             self.canvas.dtag('move')
         self.canvas.itemconfig(str(date), height=self.row_height)
         self.canvas.config(
             scrollregion=(
                 0, 0, self.canvas_width,
                 int(float(self.canvas['scrollregion'].split(' ')[3]) - \
                     self.row_height*(len(self.__names)+1))
                 )
             )
Ejemplo n.º 9
0
    def __init__(self, parent, calc, *arg, **kw):
        """Графическая форма для получения платежа/даты досрочного погашения"""
        super(AdvancedRepayment, self).__init__(parent, *arg, **kw)
        self.calc = calc

        self.configure(bg='light goldenrod')

        self.plan_paymentVar = StringVar()

        planedLabel = Label(self, text="Досрочное погашение",
                            width=20, anchor=CENTER, bg='cornsilk')
        ppLabel = Label(self, text="Платеж:", width=20,
                        anchor=CENTER, bg='cornsilk')
        pdLabel = Label(self, text="Дата:", width=20,
                        anchor=CENTER, bg='cornsilk')
        planedLabel.grid(row=0, column=0, columnspan=2,
                         padx=2, pady=2, sticky=EW)
        ppLabel.grid(row=1, column=0, padx=2, pady=2, sticky=W)
        pdLabel.grid(row=1, column=1, padx=2, pady=2, sticky=W)

        self.ppVar = StringVar()
        self.ppEntry = FloatEntry(self, width=20, from_=0,
                                  textvariable=self.ppVar, justify=CENTER)
        self.ppEntry.bind(
            '<Any-KeyRelease>',
            lambda *ign: self.__calculation(initiator='pp_payment'))
        self.ppEntry.bind(
            '<FocusOut>',
            lambda *ign: self.__calculation(initiator='pp_date'))
        self.ppEntry.grid(row=2, column=0, padx=2, pady=2, sticky=SW)

        self.dateSpinBox = MySpinBoxDate(
            self, first_date=date_plus_months(calc.first_date, calc.period//2),
            t_date=date_plus_months(calc.first_date, calc.period),
            b_date=date_plus_months(calc.first_date, 1))
        self.dateSpinBox.check_changes(
            lambda *ign: self.__calculation(initiator='pp_date'))
        self.dateSpinBox.grid(row=2, column=1, padx=2, pady=2, sticky=E)

        self.__calculation(initiator='pp_date')
Ejemplo n.º 10
0
 def _next_date(self, date):
     """Возвращает дату следующего платежа"""
     return date_plus_months(date, 1, initdate=self.first_date)
Ejemplo n.º 11
0
 def _last_date(self, date):
     """Возвращает дату предыдущего платежа платежа"""
     return date_plus_months(date, -1, initdate=self.first_date)
Ejemplo n.º 12
0
 def _next_date(self, date):
     """Возвращает дату следующего платежа"""
     return date_plus_months(date, 1, initdate=self.first_date)
Ejemplo n.º 13
0
 def _last_date(self, date):
     """Возвращает дату предыдущего платежа платежа"""
     return date_plus_months(date, -1, initdate=self.first_date)
Ejemplo n.º 14
0
    def check(self):
        """Проверяет вхождение платежа в имеющиеся границы.

        Метод проверяет, чтобы введенный платеж был не меньше
        аннуитетного ежемесячного платежа и не больше суммы долга.
        Проверяет каждый платеж в отдельности. Если какой-то не верный -
        дальше не считает. И в любом случае всегда откатывает
        self.calculation  на начальное состояние после проверки.
        """

        def error(annuity, date):
            """Сообщение об ошибке"""
            messagebox.showinfo(
                'Невозможное значение',
                'Месяц: {1}. Платеж меньше возможного ({0})'.format(
                    annuity, date.strftime('%B')))

        if [(k, v) for k, v in self.message_lst.items() if not \
            (''.join(v) == '' or k >= datetime.date(2100, 1, 1))]:
            messagebox.showinfo(
                'Введены неприавильные значения!',
                'Необходимо исправить указанные недочёты.',
                parent=self)
            self.__update_message()
            return False
        # проверяет каждый платеж в отдельности.
        # если какой-то не верный - дальше считать нет смысла.
        # и в любом случае всегда откатывает self.calculation
        # на начальное состояние после проверки
        self.debt_is_end = False
        for date, widgets_row in sorted(self.widget_rows.items()):
            annuity = self.calculation.actualy_annuity
            payments = [float(widget.get()) for widget in widgets_row[1:]]
            if sum(payments) < annuity:
                last_date = date_plus_months(
                    date, -1, initdate=self.calculation.first_date)
                # если это первый платеж - нет остатка в прошлом месяце
                if last_date == self.calculation.first_date:
                    error(annuity, date)
                    return False
                # проверяем есть ли остаток в прошлом месяце
                info = self.calculation.data[last_date]
                if info.the_rest > 0:
                    if info.the_rest >= annuity:
                        replay = messagebox.askyesno(
                            '{}. Оплата из остатка'.format(date.strftime('%B')),
                            ('В прошлом месяце ({2}) остаток денег на '
                             'вашем счёте составил: {0}.\n'
                             'Это позволит в этом месяце '
                             'не вносить платеж ({1}), а недостающую сумму'
                             'вычесть из остатка. \n\nВычетаем?').format(
                                 info.the_rest, annuity,
                                 last_date.strftime('%B')),
                            parent=self)
                        if not replay:
                            error(annuity, date)
                            return False
                    else:
                        # если платеж + остаток > ежемесячного
                        if sum(payments) + info.the_rest >= annuity:
                            replay = messagebox.askyesno(
                                '{}. Оплата из остатка'.format(
                                    date.strftime('%B')),
                                ('В прошлом месяце ({2}) остаток денег на '
                                 'вашем счёте составил: {0}.\n'
                                 'Это позволит в этом месяце внести денег '
                                 'меньше ежемесячного платежа ({1}), '
                                 'а недостающую часть вычесть из остатка. \n\n'
                                 'Вычетаем?').format(
                                     info.the_rest, annuity,
                                     last_date.strftime('%B')),
                                parent=self)
                            if not replay:
                                error(annuity, date)
                                return False
                        else:
                            messagebox.showinfo(
                                'Невозможное значение',
                                ('Месяц: {1}. Платеж меньше ежемесячного ({0})'
                                 '\n.С учетом остатка на счету в прошлом '
                                 'месяце, платеж в этом месяце должен быть'
                                 'не менее {2}').format(
                                     annuity, date.strftime('%B'),
                                     annuity - info.the_rest),
                                parent=self)
                            return False
                else:
                    error(annuity, date)
                    return False

            # считаем calc с учётом нового платежа
            self.calculation.new_payment(
                {date: Storage(
                    payment=payments, recalc=bool(
                        int(self.reculcVars[date].get())))}
                )
            # задолженность до платежа
            last_date = date_plus_months(
                date, -1, initdate=self.calculation.first_date)
            loan = self.calculation.data[last_date].loan_sum if \
                   last_date != self.calculation.first_date else \
                   self.calculation.first_loan_sum
            # плата банку за пользование
            bank_interest = self.calculation.data[date].bank_interest
            # остаток в прошлом месяце
            the_rest = self.calculation.data[last_date].the_rest if \
                       last_date != self.calculation.first_date else 0
            if sum(payments) + the_rest > loan + bank_interest:
                messagebox.showinfo(
                    'Невозможное значение',
                    ('Месяц: {1}. \nПлатеж {2}больше'
                     ' оставшейся задолженности: {0}').format(
                         round(loan + bank_interest, 2), date.strftime('%B'),
                         '' if the_rest == 0 else \
                         '(вместе с остатком за прошлый месяц) '),
                    parent=self)
                return False
            # сравниваю целые числа, т.к. аннуитетный платеж не считает
            # настолько маленькие числа (1 рубль на 10 лет)
            if int(sum(payments)) == int(loan + bank_interest):
                messagebox.showinfo(
                    'Кредит закрыт',
                    ('Месяц: {0}. \nВ этом месяце кредит закрыт.\n'
                     'Поздравляем =).').format(date.strftime('%B')),
                    parent=self)
                self.debt_is_end = True
                # долг закрыт, удаляем все нижние строки
                for i in (date_ for date_ in self.widget_rows.keys() \
                          if date_ > date):
                    self.deleteLastPayment()
                return True
        return True
Ejemplo n.º 15
0
 def __next_date(self, date):
     """Прибавляет к дате один месяц"""
     return date_plus_months(date, 1, initdate=self.calculation.first_date)
Ejemplo n.º 16
0
    def check(self):
        """Проверяет вхождение платежа в имеющиеся границы.

        Метод проверяет, чтобы введенный платеж был не меньше
        аннуитетного ежемесячного платежа и не больше суммы долга.
        Проверяет каждый платеж в отдельности. Если какой-то не верный -
        дальше не считает. И в любом случае всегда откатывает
        self.calculation  на начальное состояние после проверки.
        """
        def error(annuity, date):
            """Сообщение об ошибке"""
            messagebox.showinfo(
                'Невозможное значение',
                'Месяц: {1}. Платеж меньше возможного ({0})'.format(
                    annuity, date.strftime('%B')))

        if [(k, v) for k, v in self.message_lst.items() if not \
            (''.join(v) == '' or k >= datetime.date(2100, 1, 1))]:
            messagebox.showinfo('Введены неприавильные значения!',
                                'Необходимо исправить указанные недочёты.',
                                parent=self)
            self.__update_message()
            return False
        # проверяет каждый платеж в отдельности.
        # если какой-то не верный - дальше считать нет смысла.
        # и в любом случае всегда откатывает self.calculation
        # на начальное состояние после проверки
        self.debt_is_end = False
        for date, widgets_row in sorted(self.widget_rows.items()):
            annuity = self.calculation.actualy_annuity
            payments = [float(widget.get()) for widget in widgets_row[1:]]
            if sum(payments) < annuity:
                last_date = date_plus_months(
                    date, -1, initdate=self.calculation.first_date)
                # если это первый платеж - нет остатка в прошлом месяце
                if last_date == self.calculation.first_date:
                    error(annuity, date)
                    return False
                # проверяем есть ли остаток в прошлом месяце
                info = self.calculation.data[last_date]
                if info.the_rest > 0:
                    if info.the_rest >= annuity:
                        replay = messagebox.askyesno(
                            '{}. Оплата из остатка'.format(
                                date.strftime('%B')),
                            ('В прошлом месяце ({2}) остаток денег на '
                             'вашем счёте составил: {0}.\n'
                             'Это позволит в этом месяце '
                             'не вносить платеж ({1}), а недостающую сумму'
                             'вычесть из остатка. \n\nВычетаем?').format(
                                 info.the_rest, annuity,
                                 last_date.strftime('%B')),
                            parent=self)
                        if not replay:
                            error(annuity, date)
                            return False
                    else:
                        # если платеж + остаток > ежемесячного
                        if sum(payments) + info.the_rest >= annuity:
                            replay = messagebox.askyesno(
                                '{}. Оплата из остатка'.format(
                                    date.strftime('%B')),
                                ('В прошлом месяце ({2}) остаток денег на '
                                 'вашем счёте составил: {0}.\n'
                                 'Это позволит в этом месяце внести денег '
                                 'меньше ежемесячного платежа ({1}), '
                                 'а недостающую часть вычесть из остатка. \n\n'
                                 'Вычетаем?').format(info.the_rest, annuity,
                                                     last_date.strftime('%B')),
                                parent=self)
                            if not replay:
                                error(annuity, date)
                                return False
                        else:
                            messagebox.showinfo(
                                'Невозможное значение',
                                ('Месяц: {1}. Платеж меньше ежемесячного ({0})'
                                 '\n.С учетом остатка на счету в прошлом '
                                 'месяце, платеж в этом месяце должен быть'
                                 'не менее {2}').format(
                                     annuity, date.strftime('%B'),
                                     annuity - info.the_rest),
                                parent=self)
                            return False
                else:
                    error(annuity, date)
                    return False

            # считаем calc с учётом нового платежа
            self.calculation.new_payment({
                date:
                Storage(payment=payments,
                        recalc=bool(int(self.reculcVars[date].get())))
            })
            # задолженность до платежа
            last_date = date_plus_months(date,
                                         -1,
                                         initdate=self.calculation.first_date)
            loan = self.calculation.data[last_date].loan_sum if \
                   last_date != self.calculation.first_date else \
                   self.calculation.first_loan_sum
            # плата банку за пользование
            bank_interest = self.calculation.data[date].bank_interest
            # остаток в прошлом месяце
            the_rest = self.calculation.data[last_date].the_rest if \
                       last_date != self.calculation.first_date else 0
            if sum(payments) + the_rest > loan + bank_interest:
                messagebox.showinfo(
                    'Невозможное значение',
                    ('Месяц: {1}. \nПлатеж {2}больше'
                     ' оставшейся задолженности: {0}').format(
                         round(loan + bank_interest, 2), date.strftime('%B'),
                         '' if the_rest == 0 else \
                         '(вместе с остатком за прошлый месяц) '),
                    parent=self)
                return False
            # сравниваю целые числа, т.к. аннуитетный платеж не считает
            # настолько маленькие числа (1 рубль на 10 лет)
            if int(sum(payments)) == int(loan + bank_interest):
                messagebox.showinfo(
                    'Кредит закрыт',
                    ('Месяц: {0}. \nВ этом месяце кредит закрыт.\n'
                     'Поздравляем =).').format(date.strftime('%B')),
                    parent=self)
                self.debt_is_end = True
                # долг закрыт, удаляем все нижние строки
                for i in (date_ for date_ in self.widget_rows.keys() \
                          if date_ > date):
                    self.deleteLastPayment()
                return True
        return True
Ejemplo n.º 17
0
 def wrapper(self, *arg, **kw):
     date = self.calculation.date
     result = func(self, *arg, **kw)
     self.calculation.remove_payment(date_plus_months(
         date, 1, initdate=self.calculation.first_date))
     return result
Ejemplo n.º 18
0
 def __next_date(self, date):
     """Прибавляет к дате один месяц"""
     return date_plus_months(date, 1, initdate=self.calculation.first_date)