def format(self, values): payStatus = forceInt(values[0]) result = payStatusText(payStatus) contractId = forceRef(values[1]) # forceRef(QtGui.qApp.db.translate('Event', 'id', eventId, 'contract_id')) try: contractInfo = getContractInfo(contractId) if contractInfo.isIgnorePayStatusForJobs: result += u', %s' % contractInfo.resolution finally: return toVariant(result)
def on_selectionModelTree_currentChanged(self, current, previous): # сохраняем индексы выбранных элементов в таблице self.parent.selectedContractIdList = self.getContractIdList( \ self.treeContracts.currentIndex()) if self.parent.selectedContractIdList != []: contractInfo = getContractInfo( self.parent.selectedContractIdList[0]) if not self.chkEventSetDate.isChecked(): self.edtEventSetBegDate.setDate(contractInfo.begDate) self.edtEventSetEndDate.setDate(contractInfo.endDate) if not self.chkEventExecDate.isChecked(): self.edtEventExecBegDate.setDate(contractInfo.begDate) self.edtEventExecEndDate.setDate(contractInfo.endDate) if not self.chkActionDate.isChecked(): self.edtActionBegDate.setDate(contractInfo.begDate) self.edtActionEndDate.setDate(contractInfo.endDate) self.emit(SIGNAL('completeChanged()'))
def fillTable(self, table, eventId): db = QtGui.qApp.db results = [] event = db.getRecord( table='Event ' ' LEFT JOIN Person ON Person.id = Event.execPerson_id' ' LEFT JOIN mes.MES ON MES.id = Event.MES_id' ' LEFT JOIN rbService ON rbService.code = MES.code', cols=[ 'Event.client_id', 'Event.setDate', 'Event.execDate', 'Event.eventType_id', 'Event.MES_id', 'rbService.id as serviceId', 'Person.tariffCategory_id', 'Event.contract_id' ], itemId=eventId) eventContractId = forceRef(event.value('contract_id')) contractInfo = getContractInfo(eventContractId) eventEndDate = forceDate(event.value('execDate')) eventTypeId = forceRef(event.value('eventType_id')) tariffCategoryId = forceRef(event.value('tariffCategory_id')) eventBegDate = forceDateTime(event.value('setDate')) mesId = forceRef(event.value('MES_id')) clientId = forceRef(event.value('client_id')) # Случай лечения tariffList = contractInfo.tariffByEventType.get(eventTypeId, []) for tariff in tariffList: if isTariffApplicable(tariff, eventId, tariffCategoryId, eventEndDate, mapEventIdToMKB=self.mapEventIdToMKB): serviceId = getEventServiceId(eventTypeId) price = tariff.price federalPrice = 0 if contractInfo.isConsiderFederalPrice: federalPrice = tariff.federalPrice discount = getClientDiscountInfo(clientId)[0] price *= 1.0 - discount sum = round((price + federalPrice), 2) results.append((forceString( db.translate('rbService', 'id', serviceId, 'name')), sum)) break # Визит по МЭС serviceId = forceRef(event.value('serviceId')) tariffList = contractInfo.tariffVisitsByMES.get( (eventTypeId, serviceId), []) for tariff in tariffList: if isTariffApplicable(tariff, eventId, tariffCategoryId, eventEndDate, mapEventIdToMKB=self.mapEventIdToMKB): amount = float(getMesAmount(eventId, mesId)) federalPrice = 0 if contractInfo.isConsiderFederalPrice: federalPrice = tariff.federalPrice amount, price, sum = tariff.evalAmountPriceSum( amount, clientId) sum = round((price + federalPrice) * amount, 2) results.append((forceString( db.translate('rbService', 'id', serviceId, 'name')), sum)) break # Обращение по МЭС tariffDate = eventEndDate # Дата для выбора подходящего тарифа tariffList = contractInfo.tariffEventByMES.get( (eventTypeId, serviceId), []) eventLengthDays = getEventLengthDays(eventBegDate, eventEndDate, True, eventTypeId) # Если включена опция "Учитывать максимальную длительность по стандарту" if contractInfo.exposeByMESMaxDuration: # Получаем максимальную длительность текущего МЭС mesMaxDuration = CMesInfo(self.infoContext, mesId).maxDuration else: # В качестве максимальной используем реальную длительность события mesMaxDuration = eventLengthDays # Если максимальная длительность события по МЭС меньше реальной if mesMaxDuration < eventLengthDays: purposeCode = getEventPurposeCode(eventTypeId) # Для обращений с типом назначения "заболевание", "профилактика" или "патронаж" if purposeCode in ['1', '2', '3']: # Дата, по которой ищется нужный тариф, получается путем добавления к дате начала обращения максимальной длительности с учетом выходных tariffDate = addPeriod(eventBegDate, mesMaxDuration, True) # Для обращений с типом назначения "Реабилитация" или "Стационар" elif purposeCode in ['7', '10']: # Дата, по которой ищется нужный тариф, получается путем добавления к дате начала обращения максимальной длительности без учета выходных tariffDate = addPeriod(eventBegDate, mesMaxDuration, False) for tariff in tariffList: if isTariffApplicable(tariff, eventId, tariffCategoryId, tariffDate, mapEventIdToMKB=self.mapEventIdToMKB): if tariff.tariffType == CTariff.ttEventByMESLen: amount = eventLengthDays else: amount = 1 federalPrice = 0 if contractInfo.isConsiderFederalPrice: federalPrice = tariff.federalPrice amount, price, sum = tariff.evalAmountPriceSum( amount, clientId) sum = round((price + federalPrice) * amount, 2) results.append((forceString( db.translate('rbService', 'id', serviceId, 'name')), sum)) break # Визиты visitStmt = db.selectStmt( table='Visit' ' LEFT JOIN Person ON Person.id = Visit.person_id', fields=[ 'Visit.id', 'Visit.event_id', 'Visit.date', 'Visit.service_id', 'Person.tariffCategory_id', 'Person.speciality_id', ], where='Visit.event_id = %s AND Visit.deleted = 0' % eventId) visitQuery = db.query(visitStmt) while visitQuery.next(): visit = visitQuery.record() serviceId = forceRef(visit.value('service_id')) tariffList = contractInfo.tariffByVisitService.get(serviceId, None) if tariffList: visitDate = forceDate(visit.value('date')) specialityId = forceRef(visit.value('speciality_id')) tariffCategoryId = forceRef(visit.value('tariffCategory_id')) for tariff in tariffList: if isTariffApplicable( tariff, eventId, tariffCategoryId, visitDate, mapEventIdToMKB=self.mapEventIdToMKB): if not tariff.specialityId or specialityId == tariff.specialityId: price = tariff.price federalPrice = 0 if contractInfo.isConsiderFederalPrice: federalPrice = tariff.federalPrice discount = getClientDiscountInfo(clientId)[0] price *= 1.0 - discount amount = 1.0 sum = round((price + federalPrice) * amount, 2) results.append((forceString( db.translate('rbService', 'id', serviceId, 'name')), sum)) actionStmt = db.selectStmt( table='Action' ' LEFT JOIN Person ON Person.id = Action.person_id' ' LEFT JOIN mes.MES ON MES.id = Action.MES_id' ' LEFT JOIN rbService ON rbService.code = MES.code', fields=[ 'Action.id', 'Action.actionType_id', 'Action.event_id, Action.begDate', 'Action.endDate', 'Action.amount', 'Action.MKB', 'Person.tariffCategory_id', 'Action.MES_id', 'Action.contract_id', 'rbService.id as serviceId' ], where='Action.event_id = %s AND Action.deleted = 0' % eventId) actionQuery = db.query(actionStmt) while actionQuery.next(): success = False action = actionQuery.record() actionContractId = forceRef(action.value('contract_id')) if actionContractId and actionContractId != eventContractId: actionContractInfo = getContractInfo(actionContractId) else: actionContractInfo = contractInfo serviceId = forceRef(action.value('serviceId')) tariffList = actionContractInfo.tariffActionsByMES.get( (eventTypeId, serviceId), None) amount = getActionLengthDays(forceDate(action.value('begDate')), forceDate(action.value('endDate')), True, eventTypeId) if tariffList: endDate = forceDate(action.value('endDate')) MKB = forceString(action.value('MKB')) tariffCategoryId = forceRef(action.value('tariffCategory_id')) for tariff in tariffList: if isTariffApplicable( tariff, eventId, tariffCategoryId, endDate, MKB, mapEventIdToMKB=self.mapEventIdToMKB): amount, price, sum = tariff.evalAmountPriceSum( amount, clientId) results.append((forceString( db.translate('rbService', 'id', serviceId, 'name')), sum)) success = True break if success: continue serviceIdList = CMapActionTypeIdToServiceIdList.getActionTypeServiceIdList( forceRef(action.value('actionType_id')), actionContractInfo.finance_id) origAmount = forceDecimal(action.value('amount')) for serviceId in serviceIdList: tariffList = actionContractInfo.tariffByActionService.get( serviceId, None) if tariffList: endDate = forceDate(action.value('endDate')) MKB = forceString(action.value('MKB')) tariffCategoryId = forceRef( action.value('tariffCategory_id')) for tariff in tariffList: if isTariffApplicable( tariff, eventId, tariffCategoryId, endDate, MKB, mapEventIdToMKB=self.mapEventIdToMKB): federalPrice = 0 if actionContractInfo.isConsiderFederalPrice: federalPrice = tariff.federalPrice amount, price, sum = tariff.evalAmountPriceSum( origAmount, clientId) sum += federalPrice * amount results.append((forceString( db.translate('rbService', 'id', serviceId, 'name')), sum)) break for result in results: i = table.addRow() table.setText(i, 0, result[0]) table.setText(i, 1, result[1])
def createInstantAccount(eventId): """Создание счёта по всем действиям события. @param eventId: идентификатор события, которое будет выставлено в счета. """ db = QtGui.qApp.db tableAction = db.table('Action') tableActionType = db.table('ActionType') tableEvent = db.table('Event') tableContract = db.table('Contract') tableFinance = db.table('rbFinance') tableResult = db.table('rbResult') tablePaymentScheme = db.table('PaymentScheme') tablePaymentSchemeItem = db.table('PaymentSchemeItem') remainSum = None depositTable = tableContract.innerJoin(tableEvent, db.joinAnd([tableEvent['contract_id'].eq(tableContract['id']), tableEvent['id'].eq(eventId)])) depositRecord = db.getRecordEx(depositTable, 'Contract.deposit, Contract.id as contract_id, Contract.number as contract_number, Event.externalId, Event.eventType_id') deposit = forceDecimal(depositRecord.value('deposit')) eventContractId = forceRef(depositRecord.value('contract_id')) eventContractNumber = forceRef(depositRecord.value('contract_number')) eventExternalId = forceString(depositRecord.value('externalId')) eventTypeId = forceRef(depositRecord.value('eventType_id')) if deposit > 0: sumUsedRecord = db.getRecordEx('Account', 'SUM(Account.sum) as totalSum', 'Account.deleted = 0 AND Account.contract_id = %s' % eventContractId) sumUsed = forceDecimal(sumUsedRecord.value('totalSum')) remainSum = deposit - sumUsed if remainSum <= 0: QtGui.QMessageBox.critical(None, u'Внимание!', u'Выставление счета невозможно, так как сумма депозита по договору %s исчерпана.' % eventContractNumber, QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok ) return table = tableAction table = table.leftJoin(tableActionType, tableActionType['id'].eq(tableAction['actionType_id'])) table = table.leftJoin(tableEvent, tableEvent['id'].eq(tableAction['event_id'])) table = table.leftJoin(tableContract, 'Contract.id = IF(Action.contract_id IS NULL, Event.contract_id, Action.contract_id)') table = table.leftJoin(tableFinance, tableFinance['id'].eq(tableContract['finance_id'])) table = table.leftJoin(tableResult, tableResult['id'].eq(tableEvent['result_id'])) cond = [ tableAction['deleted'].eq(0), tableAction['event_id'].eq(eventId), '(Action.payStatus & (3 << 2 * CAST(%s AS UNSIGNED ))) = 0' % tableFinance['code'].name(), #getPayStatusMaskByCode(CFinanceType.cash) db.joinOr([tableResult['notAccount'].eq(0), tableResult['notAccount'].isNull()]), db.joinOr([tableActionType['class'].ne(ActionClass.Analyses), tableAction['parent_id'].isNotNull()]) # только дочерние дествия со вкладки "Анализы" ] mapContractIdToActionIdList = defaultdict(list) for record in db.iterRecordList(table, [tableContract['id'].alias('contract_id'), tableAction['id'].alias('action_id')], cond): contractId = forceRef(record.value('contract_id')) actionId = forceRef(record.value('action_id')) mapContractIdToActionIdList[contractId].append(actionId) accountIdList = [] try: today = QtCore.QDate.currentDate() franchisPercent = getFranchisePercentByEvent(eventId) db.transaction() for contractId in sorted(mapContractIdToActionIdList.keys()): builder = CAccountBuilder() contractInfo = getContractInfo(contractId) accountPool = CAccountPool(contractInfo, QtGui.qApp.currentOrgId(), QtGui.qApp.currentOrgStructureId(), today, False) actionIdList = sorted(mapContractIdToActionIdList[contractId]) builder.exposeByActions(None, contractInfo, accountPool.getAccount, actionIdList, today, franchisePercent=franchisPercent) accountPool.updateDetails() if getExternalIdAsAccountNumber(eventTypeId): for details in accountPool.getDetailsList(): details.changeNumber(eventExternalId, step=True, fromZero=True) if contractId == eventContractId and remainSum != None: exposedSum = 0 for details in accountPool.getDetailsList(): exposedSum += (details.totalSum * (franchisPercent/100.0)) if franchisPercent else details.totalSum paySchemeId = forceInt( db.translate(tablePaymentSchemeItem, tablePaymentSchemeItem['contract_id'], contractId, tablePaymentSchemeItem['paymentScheme_id'])) if paySchemeId: recPayScheme = db.getRecordEx(tablePaymentScheme, '*', tablePaymentScheme['id'].eq(paySchemeId)) remainSumPayScheme = forceDecimal(recPayScheme.value('total')) - forceDecimal(recPayScheme.value('spent')) if exposedSum > remainSumPayScheme: QtGui.QMessageBox.critical(None, u'Внимание!', u'Выставление счета невозможно, так как выставляемая сумма превышает сумму схемы оплаты %s.' % forceString(recPayScheme.value('numberProtocol')), QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok) db.rollback() return else: recPayScheme.setValue('spent', toVariant(forceDecimal(recPayScheme.value('spent')) + forceDecimal(exposedSum))) db.updateRecord(tablePaymentScheme, recPayScheme) if exposedSum > remainSum: QtGui.QMessageBox.critical(None, u'Внимание!', u'Выставление счета невозможно, так как выставляемая сумма превышает сумму депозита по договору %s.' % eventContractNumber, QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok) db.rollback() return if contractInfo.endDate: if forceDate(contractInfo.endDate) > QtCore.QDate.currentDate(): QtGui.QMessageBox.critical(None, u'Внимание!', u'Выставление счета невозможно, так как срок действия договора %s истек.' % eventContractNumber, QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok) db.rollback() return accountIdList += accountPool.getAccountIdList() db.commit() except: db.rollback() raise if accountIdList: dialog = CInstantAccountDialog(QtGui.qApp.mainWindow, eventId) dialog.setAccountIdList(accountIdList) dialog.exec_() else: QtGui.QMessageBox.information( QtGui.qApp.mainWindow, u'Создание счёта по событию', u'Счёт не создан, так как нечего выставлять.', QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
def createInstantAccountForPeriod(eventId, eventTypeId, clientId): """Выставление всех действий за период, указанный в умолчаниях. @param eventId: id основного события, по которому будут определены контексты печати при показе результата выставления счетов. @param eventTypeId: тип событий, из которых будут выставлены действия. @param clientId: идентификатор клиента, чьи мероприятия попадут в счета. @raise: """ db = QtGui.qApp.db tableAction = db.table('Action') tableActionType = db.table('ActionType') tableEvent = db.table('Event') tableContract = db.table('Contract') tableFinance = db.table('rbFinance') tableResult = db.table('rbResult') table = tableAction table = table.leftJoin(tableActionType, tableActionType['id'].eq(tableAction['actionType_id'])) table = table.leftJoin(tableEvent, db.joinAnd([tableEvent['id'].eq(tableAction['event_id']), tableEvent['eventType_id'].eq(eventTypeId)])) table = table.leftJoin(tableContract, 'Contract.id = IF(Action.contract_id IS NULL, Event.contract_id, Action.contract_id)') table = table.leftJoin(tableFinance, tableFinance['id'].eq(tableContract['finance_id'])) table = table.leftJoin(tableResult, tableResult['id'].eq(tableEvent['result_id'])) cond = [ tableAction['deleted'].eq(0), '(Action.payStatus & (3 << 2 * CAST(%s AS UNSIGNED ))) = 0' % tableFinance['code'].name(), #getPayStatusMaskByCode(CFinanceType.cash) db.joinOr([tableResult['notAccount'].eq(0), tableResult['notAccount'].isNull()]), tableEvent['client_id'].eq(clientId), 'Action.createDatetime > \'%s\'' % forceString(QtCore.QDateTime.currentDateTime().addSecs(-(period*3600)).toString("yyyy-MM-dd hh:mm:ss")), db.joinOr([tableActionType['class'].ne(ActionClass.Analyses), tableAction['parent_id'].isNotNull()]) # только дочерние дествия со вкладки "Анализы" ] mapContractIdToActionIdList = defaultdict(list) for record in db.iterRecordList(table, [tableContract['id'].alias('contract_id'), tableAction['id'].alias('action_id')], cond): contractId = forceRef(record.value('contract_id')) actionId = forceRef(record.value('action_id')) mapContractIdToActionIdList[contractId].append(actionId) accountIdList = [] try: today = QtCore.QDate.currentDate() db.transaction() for contractId in sorted(mapContractIdToActionIdList.keys()): builder = CAccountBuilder() contractInfo = getContractInfo(contractId) accountPool = CAccountPool(contractInfo, QtGui.qApp.currentOrgId(), QtGui.qApp.currentOrgStructureId(), today, False) actionIdList = sorted(mapContractIdToActionIdList[contractId]) builder.exposeByActions(None, contractInfo, accountPool.getAccount, actionIdList, today) accountPool.updateDetails() accountIdList += accountPool.getAccountIdList() db.commit() except: db.rollback() raise if accountIdList: dialog = CInstantAccountDialog(QtGui.qApp.mainWindow, eventId) dialog.setAccountIdList(accountIdList) dialog.exec_() else: QtGui.QMessageBox.information( QtGui.qApp.mainWindow, u'Создание счёта по событию', u'Счёт не создан, так как нечего выставлять.', QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
def on_btnExport_clicked(self): fileName = self.edtFileName.text() self.aborted = False if fileName.isEmpty(): return if self.parent.selectedContractIdList == []: self.log(u'! Не выбрано ни одного договора для выгрузки', True) QtGui.QMessageBox.warning( self, u'Экспорт результатов действий', u'Не выбрано ни одного договора для выгрузки') self.parent.back() # вернемся на пред. страницу. пусть выбирают return if self.addContractNumberToFileName: self.log(u'К имени файла добавлен номер договора.') contractInfo = getContractInfo( self.parent.selectedContractIdList[0]) fileInfo = QFileInfo(fileName) fileName = fileInfo.path()+'/'+fileInfo.baseName() + '_' + \ contractInfo.number + '.' +fileInfo.suffix() if self.addDateToFileName: self.log(u'К имени файла добавлена дата выгрузки.') fileInfo = QFileInfo(fileName) fileName = fileInfo.path()+'/'+fileInfo.baseName() + '_' + \ QDate.currentDate().toString(Qt.ISODate)+ \ '.' +fileInfo.suffix() outFile = QFile(fileName) if not outFile.open(QFile.WriteOnly | QFile.Text): self.log(u'! Не могу открыть файл для записи %s:\n%s' \ % (fileName, outFile.errorString()), True) QtGui.QMessageBox.warning(self, u'Экспорт результатов действий', u'Не могу открыть файл для записи %s:\n%s' \ % (fileName, outFile.errorString())) self.log(u'Экспорт результатов в файл:"%s"' % fileName, True) myXmlStreamWriter = CMyXmlStreamWriter( self, self.parent.selectedContractIdList, self.parent.filterEvent, self.parent.filterAction) self.btnAbort.setEnabled(True) self.btnExport.setEnabled(False) self.parent.button(QtGui.QWizard.BackButton).setEnabled(False) self.parent.button(QtGui.QWizard.FinishButton).setEnabled(False) self.parent.button(QtGui.QWizard.CancelButton).setEnabled(False) self.chkAddContractNumberToFileName.setEnabled(False) self.chkAddDateToFileName.setEnabled(False) if (myXmlStreamWriter.writeFile(outFile, self.progressBar)): self.progressBar.setText(u'Готово') self.recordsNumber = myXmlStreamWriter.querySize self.clientsNumber = len(myXmlStreamWriter.clientInfoCache) outFile.close() if self.checkRAR.isChecked(): cmdLine = u'rar mf -ep -m5 -o+ -y -- "%s" "%s"' % \ (fileName+'.rar', fileName) self.progressBar.setText(u'Сжатие') self.log(u'Сжатие в RAR.') self.log(u'Запуск внещней программы "%s"' % cmdLine) self.checkRAR.setEnabled(False) try: compressFileInRar(fileName, fileName + '.rar') self.progressBar.setText(u'Сжато в "%s"' % (fileName + '.rar')) self.checkRAR.setEnabled(True) self.writtenFileName = fileName + '.rar' except CRarException as e: self.progressBar.setText(unicode(e)) QtGui.QMessageBox.critical(self, e.getWindowTitle(), unicode(e), QtGui.QMessageBox.Close) else: self.writtenFileName = fileName self.done = True self.btnSend.setEnabled(True) else: self.progressBar.setText(u'Прервано') outFile.close() self.btnAbort.setEnabled(False) self.btnExport.setEnabled(True) self.parent.button(QtGui.QWizard.BackButton).setEnabled(True) self.parent.button(QtGui.QWizard.FinishButton).setEnabled(True) self.parent.button(QtGui.QWizard.CancelButton).setEnabled(True) self.chkAddContractNumberToFileName.setEnabled(True) self.chkAddDateToFileName.setEnabled(True) self.emit(SIGNAL('completeChanged()'))
def on_btnSend_clicked(self): if self.writtenFileName: db = QtGui.qApp.db record = None for x in self.parent.selectedContractIdList: record = db.getRecord('Contract', 'format_id', forceInt(x)) if record: formatId = forceInt(record.value('format_id')) if formatId: record = db.getRecordEx('rbAccountExportFormat', '*', \ 'id=%d' % formatId) if record: break record = None if not record: record = db.getRecordEx('rbAccountExportFormat', '*', 'prog=\'XML\'') if record: emailTo = forceString(record.value('emailTo')) subject = forceString(record.value('subject')) message = forceString(record.value('message')) else: emailTo = u'<введите адрес эл.почты>' subject = u'Результаты действий' message = u'Уважаемые господа,\n' \ u'Высылаем Вам результаты действий в формате XML\n' \ u'в {shortName}, ОГРН: {OGRN}\n' \ u'за период с {actBegDate} по {actEndDate}\n' \ u'в приложении {NR} записей\n' \ u'для {NC} пациентов\n' \ u'фильтр статуса действий {actStatus}\n' \ u'номера договора(ов): {contractNumber}\n' \ u'\n' \ u'--\n' \ u'WBR\n' \ u'{shortName}\n' orgRec = QtGui.qApp.db.getRecord('Organisation', 'INN, OGRN, shortName', QtGui.qApp.currentOrgId()) data = {} data['INN'] = forceString(orgRec.value('INN')) data['OGRN'] = forceString(orgRec.value('OGRN')) data['shortName'] = forceString(orgRec.value('shortName')) filtersPage = self.parent.page( 0) # qwizardpage с фильтрами по экспорту data['actBegDate'] = forceString( filtersPage.edtActionBegDate.date().toString(Qt.ISODate)) data['actEndDate'] = forceString( filtersPage.edtActionEndDate.date().toString(Qt.ISODate)) if filtersPage.chkActionStatus.isChecked(): data['actStatus'] = CActionType.retranslateClass( False).statusNames[ filtersPage.cmbActionStatus.currentIndex()] else: data['actStatus'] = u'любой' data['NR'] = self.recordsNumber data['NC'] = self.clientsNumber contractNumberList = [] for x in self.parent.selectedContractIdList: contractInfo = getContractInfo(x) contractNumberList.append(forceString(contractInfo.number)) data['contractNumber'] = u', '.join( [str(et) for et in contractNumberList]) subject = substFields(subject, data) message = substFields(message, data) sendMail(self, emailTo, subject, message, [self.writtenFileName])