|
|
@ -0,0 +1,329 @@ |
|
|
|
#!/usr/bin/env python |
|
|
|
# -*- coding: utf-8 -*- |
|
|
|
|
|
|
|
''' |
|
|
|
Created on 17.12.2010 |
|
|
|
|
|
|
|
@author: morozov |
|
|
|
''' |
|
|
|
|
|
|
|
import sys, cgi, datetime |
|
|
|
sys.path.append('.') |
|
|
|
import functions |
|
|
|
from wsgiref.util import application_uri |
|
|
|
|
|
|
|
config = functions.readConfig() |
|
|
|
|
|
|
|
class pageParts(object): |
|
|
|
''' |
|
|
|
classdocs |
|
|
|
''' |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, environ, db): |
|
|
|
''' |
|
|
|
Constructor |
|
|
|
''' |
|
|
|
self.environ = environ |
|
|
|
self.userName = environ['REMOTE_USER'] |
|
|
|
self.fieldStorage = cgi.FieldStorage(fp = environ['wsgi.input'], environ = environ, keep_blank_values = 1) |
|
|
|
self.db = db |
|
|
|
self.appUrl = application_uri(environ) |
|
|
|
self.requestUri = environ['REQUEST_URI'] |
|
|
|
self.errStatus = False |
|
|
|
self.errMsg = '' |
|
|
|
self.now = datetime.datetime.now() |
|
|
|
|
|
|
|
if self.fieldStorage.has_key('year') and self.fieldStorage.has_key('month') and self.fieldStorage.has_key('day'): |
|
|
|
try: |
|
|
|
self.journalDate = datetime.date(year = int(self.fieldStorage.getfirst('year')), month = int(self.fieldStorage.getfirst('month')), day = int(self.fieldStorage.getfirst('day'))) |
|
|
|
except ValueError: |
|
|
|
self.journalDate = self.now.date() |
|
|
|
else: |
|
|
|
self.journalDate = self.now.date() |
|
|
|
|
|
|
|
try: |
|
|
|
self.previousDay = self.journalDate - datetime.timedelta(days = 1) |
|
|
|
except OverflowError: |
|
|
|
self.previousDayError = True |
|
|
|
else: |
|
|
|
self.previousDayError = False |
|
|
|
try: |
|
|
|
self.nextDay = self.journalDate + datetime.timedelta(days = 1) |
|
|
|
except OverflowError: |
|
|
|
self.nextDayError = True |
|
|
|
else: |
|
|
|
self.nextDayError = False |
|
|
|
self.tomorrow = datetime.datetime.now().date() + datetime.timedelta(days = 1) |
|
|
|
|
|
|
|
if self.fieldStorage.has_key('newName')\ |
|
|
|
and self.fieldStorage.has_key('newPosition')\ |
|
|
|
and self.fieldStorage.has_key('newDepartment')\ |
|
|
|
and self.fieldStorage.has_key('newStartTimeHour')\ |
|
|
|
and self.fieldStorage.has_key('newStartTimeMinute')\ |
|
|
|
and self.fieldStorage.has_key('newEndTimeHour')\ |
|
|
|
and self.fieldStorage.has_key('newEndTimeMinute')\ |
|
|
|
and self.fieldStorage.has_key('newDescription')\ |
|
|
|
and self.fieldStorage.has_key('newChief'): |
|
|
|
try: |
|
|
|
newRecord = self.db.journalRecord(name = self.fieldStorage.getfirst('newName'), |
|
|
|
position = self.fieldStorage.getfirst('newPosition'), |
|
|
|
department = self.fieldStorage.getfirst('newDepartment'), |
|
|
|
date = self.journalDate, |
|
|
|
startTime = datetime.time(hour = int(self.fieldStorage.getfirst('newStartTimeHour')), |
|
|
|
minute = int(self.fieldStorage.getfirst('newStartTimeMinute'))), |
|
|
|
endTime = datetime.time(hour = int(self.fieldStorage.getfirst('newEndTimeHour')), |
|
|
|
minute = int(self.fieldStorage.getfirst('newEndTimeMinute'))), |
|
|
|
description = self.fieldStorage.getfirst('newDescription'), |
|
|
|
chief = self.fieldStorage.getfirst('newChief'), |
|
|
|
userName = self.userName) |
|
|
|
for value in newRecord.name, newRecord.position, newRecord.department, newRecord.description: |
|
|
|
if len(value) == 0: |
|
|
|
raise ValueError |
|
|
|
except ValueError: |
|
|
|
self.errStatus = True |
|
|
|
self.errMsg = 'Введены неверные данные. Заполняйте форму внимательнее.' |
|
|
|
else: |
|
|
|
self.db.setProperty(self.userName, 'latestName', newRecord.name) |
|
|
|
self.db.setProperty(self.userName, 'latestPosition', newRecord.position) |
|
|
|
self.db.setProperty(self.userName, 'latestDepartment', newRecord.department) |
|
|
|
self.db.setProperty(self.userName, 'latestChief', newRecord.chief) |
|
|
|
self.db.journalSaveRecord(newRecord) |
|
|
|
|
|
|
|
if self.fieldStorage.has_key('delete'): |
|
|
|
try: |
|
|
|
self.db.journalDeleteRecord(self.userName, int(self.fieldStorage.getfirst('delete'))) |
|
|
|
except: |
|
|
|
self.errStatus = True |
|
|
|
self.errMsg = 'Ошибка при удалении записи. Возможно, вы пытались удалить несуществующую запись.' |
|
|
|
|
|
|
|
self.propertyLatestName = self.db.getProperty(self.userName, 'latestName') |
|
|
|
if self.propertyLatestName == None: |
|
|
|
self.propertyLatestName = '' |
|
|
|
self.propertyLatestPosition = self.db.getProperty(self.userName, 'latestPosition') |
|
|
|
|
|
|
|
if self.propertyLatestPosition == None: |
|
|
|
self.propertyLatestPosition = '' |
|
|
|
self.propertyLatestDepartment = self.db.getProperty(self.userName, 'latestDepartment') |
|
|
|
|
|
|
|
if self.propertyLatestDepartment == None: |
|
|
|
self.propertyLatestDepartment = '' |
|
|
|
self.propertyLatestChief = self.db.getProperty(self.userName, 'latestChief') |
|
|
|
|
|
|
|
if self.propertyLatestChief == None: |
|
|
|
self.propertyLatestChief = '' |
|
|
|
|
|
|
|
def _getWeekDay(self, date): |
|
|
|
days = {0: 'понедельник', |
|
|
|
1: 'вторник', |
|
|
|
2: 'среда', |
|
|
|
3: 'четверг', |
|
|
|
4: 'пятница', |
|
|
|
5: 'суббота', |
|
|
|
6: 'воскресенье'} |
|
|
|
return(days[date.weekday()]) |
|
|
|
|
|
|
|
def _replaceTags(self, str): |
|
|
|
str = str.replace('<', '<') |
|
|
|
str = str.replace('>', '>') |
|
|
|
return str |
|
|
|
|
|
|
|
def header(self): |
|
|
|
output = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n'\ |
|
|
|
'<html lang="ru">\n'\ |
|
|
|
'<head>\n'\ |
|
|
|
' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n'\ |
|
|
|
' <title>Журнал командировок</title>\n'\ |
|
|
|
'</head>\n'\ |
|
|
|
'<body bgcolor = "white">\n' |
|
|
|
output += ' <table width="100%" bgcolor="#336299"><tr><td>\n' |
|
|
|
output += ' <p align = "right"><a href="view-all.py" style = "text-decoration: none; border-bottom: 1px solid white; color: white;">Все журналы</a> <a href="index.py" style = "text-decoration: none; border-bottom: 1px solid white; color: white;">Сегодня</a> <a href="index.py?day=%s&month=%s&year=%s" style = "text-decoration: none; border-bottom: 1px solid white; color: white;">Завтра</a></p>\n' % (self.tomorrow.day, self.tomorrow.month, self.tomorrow.year) |
|
|
|
output += ' <H1><p align = "center"><font color = "white">Журнал командировок</font></p></H1>\n' |
|
|
|
output += ' </td></tr></table>\n' |
|
|
|
if self.errStatus: |
|
|
|
output += ' <table width = "100%" border = 0 bgcolor = "#FFF9B4">\n' |
|
|
|
output += ' <tr align = "center"><td><b><font color = "red"><b>%s</b></font></b></td></tr>\n' % self.errMsg |
|
|
|
output += ' </table>\n' |
|
|
|
return(output) |
|
|
|
|
|
|
|
def headerPrint(self): |
|
|
|
output = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n'\ |
|
|
|
'<html lang="ru">\n'\ |
|
|
|
'<head>\n'\ |
|
|
|
' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n'\ |
|
|
|
' <title>Журнал командировок</title>\n'\ |
|
|
|
'</head>\n'\ |
|
|
|
'<body>\n'\ |
|
|
|
' <style>\n'\ |
|
|
|
' @media print {\n'\ |
|
|
|
' .printButton {display: none;}\n'\ |
|
|
|
' }\n'\ |
|
|
|
' </style>\n' |
|
|
|
output += ' <H1><p align = "center">Журнал командировок</p></H1>\n' |
|
|
|
return(output) |
|
|
|
|
|
|
|
def journalForDay(self): |
|
|
|
records = self.db.journalGetRecords(self.journalDate) |
|
|
|
output = ' <table align = "right"><tr>\n' |
|
|
|
output += ' <td>\n' |
|
|
|
output += ' <a href = "print.py?day=%s&month=%s&year=%s"><img src = "images/printer.jpg" border = "0"/></a>\n' % (self.journalDate.day, self.journalDate.month, self.journalDate.year) |
|
|
|
output += ' </td>\n' |
|
|
|
output += ' <td>\n' |
|
|
|
output += ' <a href = "print.py?day=%s&month=%s&year=%s">версия для печати</a>\n' % (self.journalDate.day, self.journalDate.month, self.journalDate.year) |
|
|
|
output += ' </td>\n' |
|
|
|
output += ' </tr></table><br>\n' |
|
|
|
output += ' <h3><p align = "center">Дата:</p></h3>\n' |
|
|
|
output += ' <form method = "get" action = "%s" style = "text-align:center;">\n' % self.appUrl |
|
|
|
output += ' <table align = "center">\n' |
|
|
|
output += ' <tr>\n' |
|
|
|
if self.previousDayError == False: |
|
|
|
output += ' <td><a href="%s?day=%s&month=%s&year=%s"><img border = "0" src = "images/left.jpg"/></a></td>\n' % (self.appUrl, self.previousDay.day, self.previousDay.month, self.previousDay.year) |
|
|
|
else: |
|
|
|
output += ' <td><img border = "0" src = "images/left.jpg"/></td>\n' |
|
|
|
output += ' <td>\n' |
|
|
|
output += ' <input type = "text" name = "day" id = "day" size = "2" value = "%s" />.\n' % str(self.journalDate.day).zfill(2) |
|
|
|
output += ' <input type = "text" name = "month" id = "month" size = "2" value = "%s" />.\n' % str(self.journalDate.month).zfill(2) |
|
|
|
output += ' <input type = "text" name = "year" id = "year" size = "4" value = "%s" />\n' % self.journalDate.year |
|
|
|
output += ' </td>\n' |
|
|
|
if self.nextDayError == False: |
|
|
|
output += ' <td><a href="%s?day=%s&month=%s&year=%s"><img border = "0" src = "images/right.jpg"/></a></td>\n' % (self.appUrl, self.nextDay.day, self.nextDay.month, self.nextDay.year) |
|
|
|
else: |
|
|
|
output += ' <td><img border = "0" src = "images/right.jpg"/></td>\n' |
|
|
|
output += ' </tr>\n' |
|
|
|
output += ' </table>\n' |
|
|
|
output += ' %s' % self._getWeekDay(self.journalDate) |
|
|
|
output += ' <p><input type="submit" value = "Перейти" /></p>\n' |
|
|
|
output += ' </form>\n' |
|
|
|
if len(records) == 0: |
|
|
|
output += '<H3>Записи отсутствуют.</H3>' |
|
|
|
else: |
|
|
|
output += ' <table width = "100%" bordercolor = "black" border = "1" cellspacing = "0" rules = "all" frame = "border">\n'\ |
|
|
|
' <tr align = "center" bgcolor="#336299" style = "color: white;">\n'\ |
|
|
|
' <td><b>Фамилия И.О.</b></td>\n'\ |
|
|
|
' <td><b>Должность</b></td>\n'\ |
|
|
|
' <td><b>Отдел</b></td>\n'\ |
|
|
|
' <td><b>Время начала</b></td>\n'\ |
|
|
|
' <td><b>Время окончания</b></td>\n'\ |
|
|
|
' <td><b>Цель и место встречи</b></td>\n'\ |
|
|
|
' <td><b>Руководитель</b></td>\n'\ |
|
|
|
' <td><b>Удалить</b></td>\n'\ |
|
|
|
' </tr>\n' |
|
|
|
for i in xrange(len(records)): |
|
|
|
if i % 2 == 1: |
|
|
|
bgcolor = ' bgcolor = "#BFD0E0"' |
|
|
|
else: |
|
|
|
bgcolor = '' |
|
|
|
output += ' <tr%s>\n' % bgcolor |
|
|
|
if self.db.journalCheckDeletePermissions(self.userName, records[i].key): |
|
|
|
deleteField = '<a href="' + self.appUrl + '?year=' + str(self.journalDate.year) + '&month=' + str(self.journalDate.month) + '&day=' + str(self.journalDate.day) + '&delete=' + str(records[i].key) + '"><img src = "images/trash.png" border = "0"/></a>' |
|
|
|
else: |
|
|
|
deleteField = '' |
|
|
|
for field in self._replaceTags(records[i].name), self._replaceTags(records[i].position), self._replaceTags(records[i].department), str(records[i].startTime.hour) + ':' + str(records[i].startTime.minute).zfill(2), str(records[i].endTime.hour) + ':' + str(records[i].endTime.minute).zfill(2), self._replaceTags(records[i].description), self._replaceTags(records[i].chief), deleteField: |
|
|
|
output += ' <td>%s</td>\n' % field |
|
|
|
output += ' </tr>\n' |
|
|
|
output += ' </table>\n' |
|
|
|
return(output) |
|
|
|
|
|
|
|
def journalForDayPrint(self): |
|
|
|
records = self.db.journalGetRecords(self.journalDate) |
|
|
|
output = ' <h3><p align = "center">Дата: %s.%s.%s (%s)</p></h3>\n' % (str(self.journalDate.day).zfill(2), str(self.journalDate.month).zfill(2), self.journalDate.year, self._getWeekDay(self.journalDate)) |
|
|
|
output += ' <p>Отчёт сгенерирован: %s.%s.%s %s:%s</p>\n' % (str(self.now.day).zfill(2), str(self.now.month).zfill(2), self.now.year, self.now.hour, str(self.now.minute).zfill(2)) |
|
|
|
if len(records) == 0: |
|
|
|
output += ' <H3>Записи отсутствуют.</H3>\n' |
|
|
|
else: |
|
|
|
output += ' <table width = "100%" bordercolor = "black" border = "1" cellspacing = "0" rules = "all" frame = "border">\n'\ |
|
|
|
' <tr align = "center" >\n'\ |
|
|
|
' <td><b>Фамилия И.О.</b></td>\n'\ |
|
|
|
' <td><b>Должность</b></td>\n'\ |
|
|
|
' <td><b>Отдел</b></td>\n'\ |
|
|
|
' <td><b>Время начала</b></td>\n'\ |
|
|
|
' <td><b>Время окончания</b></td>\n'\ |
|
|
|
' <td><b>Цель и место встречи</b></td>\n'\ |
|
|
|
' <td><b>Руководитель</b></td>\n'\ |
|
|
|
' </tr>\n' |
|
|
|
for i in xrange(len(records)): |
|
|
|
output += ' <tr>\n' |
|
|
|
for field in self._replaceTags(records[i].name), self._replaceTags(records[i].position), self._replaceTags(records[i].department), str(records[i].startTime.hour) + ':' + str(records[i].startTime.minute).zfill(2), str(records[i].endTime.hour) + ':' + str(records[i].endTime.minute).zfill(2), self._replaceTags(records[i].description), self._replaceTags(records[i].chief): |
|
|
|
output += ' <td>%s</td>\n' % field |
|
|
|
output += ' </tr>\n' |
|
|
|
output += ' </table>\n' |
|
|
|
return(output) |
|
|
|
|
|
|
|
def addRecord(self): |
|
|
|
output = ' <H2>Добавить запись:</H2>\n'\ |
|
|
|
' <form method = "post" enctype = "multipart/form-data" action = "' + self.appUrl + '?year=' + str(self.journalDate.year) + '&month=' + str(self.journalDate.month) + '&day=' + str(self.journalDate.day) + '">\n'\ |
|
|
|
' <table width = "100%" bordercolor = "black" border = "1" cellspacing = "0" cellpadding = "5" rules = "all" frame = "border">\n'\ |
|
|
|
' <tr align = "center" bgcolor="#336299" style = "color: white;">\n'\ |
|
|
|
' <td><b>Фамилия И.О.</b></td>\n'\ |
|
|
|
' <td><b>Должность</b></td>\n'\ |
|
|
|
' <td><b>Отдел</b></td>\n'\ |
|
|
|
' <td><b>Время начала</b></td>\n'\ |
|
|
|
' <td><b>Время окончания</b></td>\n'\ |
|
|
|
' <td><b>Цель и место встречи</b></td>\n'\ |
|
|
|
' <td><b>Руководитель</b></td>\n'\ |
|
|
|
' </tr>\n'\ |
|
|
|
' <tr>\n'\ |
|
|
|
' <td align = "center"><input type = "text" name = "newName" id = "newName" style = "width: 95%; background-color: #FFF9B4;" value = "' + self._replaceTags(self.propertyLatestName) + '" /></td>\n'\ |
|
|
|
' <td align = "center"><input type = "text" name = "newPosition" id = "newPosition" style = "width: 95%; background-color: #FFF9B4;" value = "' + self._replaceTags(self.propertyLatestPosition) + '" /></td>\n'\ |
|
|
|
' <td align = "center"><input type = "text" name = "newDepartment" id = "newDepartment" style = "width: 95%; background-color: #FFF9B4;" value = "' + self._replaceTags(self.propertyLatestDepartment) + '" /></td>\n'\ |
|
|
|
' <td>\n'\ |
|
|
|
' <table width = "100%" border = "0" cellspacing = "0">\n'\ |
|
|
|
' <tr>\n'\ |
|
|
|
' <td>Часы:</td>\n'\ |
|
|
|
' <td><input type = "text" name = "newStartTimeHour" id = "newStartTimeHour" style = "background-color: #FFF9B4;" size = 2 value = "' + config.default_start_time_hour + '" /></td>\n'\ |
|
|
|
' </tr>\n'\ |
|
|
|
' <tr>\n'\ |
|
|
|
' <td>Минуты: </td>\n'\ |
|
|
|
' <td><input type = "text" name = "newStartTimeMinute" id = "newStartTimeMinute" style = "background-color: #FFF9B4;" size = 2 value = "' + str(config.default_start_time_minute).zfill(2) + '" /></td>\n'\ |
|
|
|
' </tr>\n'\ |
|
|
|
' </table>\n'\ |
|
|
|
' </td>\n'\ |
|
|
|
' <td>\n'\ |
|
|
|
' <table width = "100%" border = "0" cellspacing = "0">\n'\ |
|
|
|
' <tr>\n'\ |
|
|
|
' <td>Часы:</td>\n'\ |
|
|
|
' <td><input type = "text" name = "newEndTimeHour" id = "newEendTimeHour" style = "background-color: #FFF9B4;" size = 2 value = "' + config.default_end_time_hour + '" /></td>\n'\ |
|
|
|
' </tr>\n'\ |
|
|
|
' <tr>\n'\ |
|
|
|
' <td>Минуты: </td>\n'\ |
|
|
|
' <td><input type = "text" name = "newEndTimeMinute" id = "newEndTimeMinute" style = "background-color: #FFF9B4;" size = 2 value = "' + str(config.default_end_time_minute).zfill(2) + '" /></td>\n'\ |
|
|
|
' </tr>\n'\ |
|
|
|
' </table>\n'\ |
|
|
|
' </td>\n'\ |
|
|
|
' <td align = "center"><textarea name = "newDescription" id = "newDescription" style = "width: 95%; background-color: #FFF9B4;" rows = "4"></textarea></td>\n'\ |
|
|
|
' <td align = "center"><input type = text" name = "newChief" id = "newChief" style = "width: 95%; " value = "' + self._replaceTags(self.propertyLatestChief) + '" /></td>\n'\ |
|
|
|
' </tr>\n'\ |
|
|
|
' </table>\n'\ |
|
|
|
' <p><table><tr><td bgcolor = "#FFF9B4" width = "10px"></td><td> - обязательные поля</td></tr></table></p>\n'\ |
|
|
|
' <p align = "center"><input type="submit" value = "Добавить запись" /></p>\n'\ |
|
|
|
' </form>\n' |
|
|
|
|
|
|
|
return(output) |
|
|
|
|
|
|
|
def allDays(self): |
|
|
|
allDays = self.db.journalListDays() |
|
|
|
output = ' <H3><p align = "center">Все журналы:</p></H3>\n' |
|
|
|
output += ' <p align = "center">' |
|
|
|
if len(allDays) == 0: |
|
|
|
output += '<h3>Записи отсутствуют.</H3>\n' |
|
|
|
else: |
|
|
|
output += ' <table align = "center">\n' |
|
|
|
for i in xrange(len(allDays)): |
|
|
|
output += ' <tr><td><a href = "index.py?day=%s&month=%s&year=%s">%s.%s.%s</a></td><td>%s</td></tr>\n' % (allDays[i].day, allDays[i].month, allDays[i].year, str(allDays[i].day).zfill(2), str(allDays[i].month).zfill(2), allDays[i].year, self._getWeekDay(allDays[i])) |
|
|
|
output += ' </table>\n' |
|
|
|
output += ' </p>\n' |
|
|
|
return(output) |
|
|
|
|
|
|
|
def footer(self): |
|
|
|
output = ' <br><p align = "center"><font color = "gray">© 2010 Сергей Морозов, ОАО «Промышленно - строительное товарищество»</font></p>\n' |
|
|
|
output += '</body>\n' |
|
|
|
return(output) |
|
|
|
|
|
|
|
def footerPrint(self): |
|
|
|
output = ' <p>\n'\ |
|
|
|
' <form>\n'\ |
|
|
|
' <input type = "button" value = "Печать" class = "printButton" onClick = "window.print()">\n'\ |
|
|
|
' </form>\n'\ |
|
|
|
' </p>\n' |
|
|
|
output += '</body>\n' |
|
|
|
return(output) |