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')
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')
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)
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
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)
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)) ) )
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)) ) )
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')
def _next_date(self, date): """Возвращает дату следующего платежа""" return date_plus_months(date, 1, initdate=self.first_date)
def _last_date(self, date): """Возвращает дату предыдущего платежа платежа""" return date_plus_months(date, -1, initdate=self.first_date)
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
def __next_date(self, date): """Прибавляет к дате один месяц""" return date_plus_months(date, 1, initdate=self.calculation.first_date)
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
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