def set_locked_version(self, tallySheetVersion: TallySheetVersion): if tallySheetVersion is None: if not has_role_based_access(self, ACCESS_TYPE_UNLOCK): raise ForbiddenException( message="User not authorized to unlock the tally sheet.", code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_UNLOCK) self.submission.set_locked_version(submissionVersion=None) else: if self.template.is_submit_allowed(): if self.submittedVersionId is None: raise ForbiddenException( message= "Data entry tally sheet cannot be locked before submitting", code=MESSAGE_CODE_TALLY_SHEET_CANNOT_LOCK_BEFORE_SUBMIT ) elif self.submittedStamp.createdBy == get_user_name(): raise ForbiddenException( message= "Data entry tally sheet submitted user is not allowed to lock/unlock.", code= MESSAGE_CODE_TALLY_SHEET_SAME_USER_CANNOT_SAVE_AND_SUBMIT ) if not has_role_based_access(self, ACCESS_TYPE_LOCK): raise ForbiddenException( message="User is not authorized to lock the tally sheet.", code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_LOCK) self.submission.set_locked_version( submissionVersion=tallySheetVersion.submissionVersion) self.update_status_report()
def set_notified_version(self): if self.lockedVersionId is None: raise ForbiddenException( message="Tally sheet cannot be notified before it's verified.", code=MESSAGE_CODE_TALLY_SHEET_CANNOT_BE_NOTIFIED_BEFORE_LOCK) elif self.notified is True: raise ForbiddenException( message="Tally sheet is already notified.", code=MESSAGE_CODE_TALLY_SHEET_ALREADY_NOTIFIED) else: self.submission.set_notified_version( submissionVersion=self.lockedVersion) self.update_status_report()
def __init__(self, invoiceId, stationaryItemId): if Invoice.has_confirmed(invoiceId): raise ForbiddenException("Stationary items cannot be added to confirmed invoices (%d)" % invoiceId) elif StationaryItem.is_locked(stationaryItemId): raise ForbiddenException("Stationary item is not available (%d)" % stationaryItemId) else: received_proof = Proof.create( proofType=ProofTypeEnum.InvoiceStationaryItemReceive ) super(InvoiceStationaryItemModel, self).__init__( invoiceId=invoiceId, stationaryItemId=stationaryItemId, receivedProofId=received_proof.proofId )
def set_released_version(self): if self.notified is False: raise ForbiddenException( message="Tally sheet cannot be released before notifying", code= MESSAGE_CODE_TALLY_SHEET_CANNOT_BE_RELEASED_BEFORE_NOTIFYING) elif self.released is True: raise ForbiddenException( message="Tally sheet is already released.", code=MESSAGE_CODE_TALLY_SHEET_ALREADY_RELEASED) else: self.submission.set_released_version( submissionVersion=self.notifiedVersion) self.update_status_report()
def get_template_column_to_query_filter_map(self, only_group_by_columns=False): extended_election = self.tallySheet.election.get_extended_election() template_column_to_query_filter_map = super( ExtendedTallySheet_PCE_42, self).get_template_column_to_query_filter_map( only_group_by_columns=only_group_by_columns) template_column_to_query_column_map = self.get_template_column_to_query_column_map() party_ids_to_be_filtered = [] pe_r2_tally_sheets = db.session.query(TallySheet.Model).filter( TallySheet.Model.tallySheetId == TallySheetTallySheetModel.childTallySheetId, TallySheet.Model.latestVersionId != None, TallySheetTallySheetModel.parentTallySheetId == self.tallySheet.tallySheetId, TallySheet.Model.templateId == Template.Model.templateId, Template.Model.templateName == TALLY_SHEET_CODES.PCE_42, WorkflowInstance.Model.workflowInstanceId == TallySheet.Model.workflowInstanceId, WorkflowInstance.Model.status.in_( extended_election.tally_sheet_verified_statuses_list() ), ).all() if len(pe_r2_tally_sheets) == 0: raise ForbiddenException( message="Candidates cannot be allocated until the seat calculation (PCE-R2) is completed and verified.", code=MESSAGE_CODE_PE_21_CANNOT_BE_PROCESSED_WITHOUT_PE_R2 ) pe_r2_tally_sheet_ids = [tallySheet.tallySheetId for tallySheet in pe_r2_tally_sheets] for pe_r2_tally_sheet in pe_r2_tally_sheets: pe_r2_extended_tally_sheet_version = pe_r2_tally_sheet.get_extended_tally_sheet_version( tallySheetVersionId=pe_r2_tally_sheet.latestVersionId) party_wise_seat_calculation_df = pe_r2_extended_tally_sheet_version.get_party_wise_seat_calculations() for party_wise_seat_calculation_df_index in party_wise_seat_calculation_df.index: seats_allocated = party_wise_seat_calculation_df.at[ party_wise_seat_calculation_df_index, 'seatsAllocated'] if seats_allocated > 0: party_id = party_wise_seat_calculation_df.at[party_wise_seat_calculation_df_index, 'partyId'] party_ids_to_be_filtered.append(int(party_id)) pe_ce_ro_pr_3_tally_sheets = db.session.query( TallySheet.Model.tallySheetId ).filter( TallySheet.Model.tallySheetId == TallySheetTallySheetModel.childTallySheetId, TallySheetTallySheetModel.parentTallySheetId == self.tallySheet.tallySheetId, TallySheet.Model.templateId == Template.Model.templateId, Template.Model.templateName == TALLY_SHEET_CODES.PE_CE_RO_PR_3, MetaData.Model.metaId == TallySheet.Model.metaId, MetaData.Model.metaDataKey == "partyId", MetaData.Model.metaDataValue.in_(party_ids_to_be_filtered) ).all() pe_ce_ro_pr_3_tally_sheet_ids = [tallySheet.tallySheetId for tallySheet in pe_ce_ro_pr_3_tally_sheets] template_column_to_query_filter_map["partyId"] += [ template_column_to_query_column_map["partyId"].in_(party_ids_to_be_filtered), TallySheet.Model.tallySheetId.in_(pe_ce_ro_pr_3_tally_sheet_ids + pe_r2_tally_sheet_ids) ] return template_column_to_query_filter_map
def submit(tallySheetId, body): request_body = RequestBody(body) tallySheetVersionId = request_body.get("submittedVersionId") tally_sheet: TallySheetModel = TallySheet.get_by_id(tallySheetId=tallySheetId) if tally_sheet is None: raise NotFoundException( message="Tally sheet not found (tallySheetId=%d)" % tallySheetId, code=MESSAGE_CODE_TALLY_SHEET_NOT_FOUND ) if tally_sheet.tallySheetCode not in [TallySheetCodeEnum.PRE_41, TallySheetCodeEnum.CE_201, TallySheetCodeEnum.CE_201_PV, TallySheetCodeEnum.PRE_34_CO]: raise ForbiddenException( message="Submit operation is not supported for this tally sheet type.", code=MESSAGE_CODE_TALLY_SHEET_SUBMIT_IS_NOT_SUPPORTED ) tally_sheet_version = TallySheetVersion.get_by_id(tallySheetVersionId=tallySheetVersionId, tallySheetId=tallySheetId) if tally_sheet_version is None: raise NotFoundException( message="Tally sheet version not found (tallySheetVersionId=%d)" % tallySheetVersionId, code=MESSAGE_CODE_TALLY_SHEET_VERSION_NOT_FOUND ) tally_sheet.set_submitted_version(tally_sheet_version) if tally_sheet.tallySheetCode in [TallySheetCodeEnum.CE_201, TallySheetCodeEnum.CE_201_PV]: election = tally_sheet.submission.election electionId = election.parentElectionId countingCentreId = tally_sheet.areaId results = StatusCE201.get_status_records(electionId, countingCentreId) for item in results: item.status = "Submitted" if tally_sheet.tallySheetCode in [TallySheetCodeEnum.PRE_41]: election = tally_sheet.submission.election electionId = election.parentElectionId countingCentreId = tally_sheet.areaId results = StatusPRE41.get_status_records(electionId, countingCentreId) for item in results: item.status = "Submitted" if tally_sheet.tallySheetCode in [TallySheetCodeEnum.PRE_34_CO]: election = tally_sheet.submission.election electionId = election.parentElectionId countingCentreId = tally_sheet.areaId results = StatusPRE34.get_status_records(electionId, countingCentreId) for item in results: item.status = "Submitted" db.session.commit() return TallySheetSchema().dump(tally_sheet).data, 201
def populate_seats_per_party(self, number_of_members_to_be_elected=0): df = self.get_party_wise_valid_vote_count_result() total_valid_vote_count = df['numValue'].sum() if total_valid_vote_count == 0: raise ForbiddenException( message= "Bonus Seat Allocation 1 (PCE_PC_BS_1) cannot be decided until the Provincial Vote Results (PCE-PC-V) is completed and verified.", code= MESSAGE_CODE_PCE_PC_BS_1_CANNOT_BE_PROCESSED_WITHOUT_PCE_PC_V ) valid_vote_count_required_per_seat = total_valid_vote_count / number_of_members_to_be_elected valid_vote_count_required_per_seat_ceil = math.ceil( valid_vote_count_required_per_seat) df = df.sort_values(by=['numValue'], ascending=True) max_num_value_index = 0 max_num_value = 0 for index in df.index: num_value = df.at[index, 'numValue'] if num_value > max_num_value: max_num_value = num_value max_num_value_index = index df.at[index, 'seatsAllocated'] = 0 df.at[max_num_value_index, 'seatsAllocated'] = 2 df["voteCountCeilPerSeat"] = pd.Series(np.full( len(df.index), valid_vote_count_required_per_seat_ceil), index=df.index) return df
def upload_file(proofId, fileSource, fileType): proof = get_by_id(proofId=proofId) if proof is None: raise NotFoundException( message="Proof not found associated with the given proofId (proofId=%d)" % proofId, code=MESSAGE_CODE_PROOF_NOT_FOUND ) elif proof.finished is True: raise ForbiddenException( message="No more evidence is accepted for this proof (proofId=%d)" % proofId, code=MESSAGE_CODE_PROOF_NOT_MORE_EVIDENCE_ACCEPTED ) else: file = File.createFromFileSource( fileSource=fileSource, fileType=fileType ) FolderFile.create( folderId=proof.scannedFilesFolderId, fileId=file.fileId ) return proof
def close(self): if self.size() is 0: raise ForbiddenException( message="A proof required at least one evidence. Please upload at least one evidence (proofId=%d)" % self.proofId, code=MESSAGE_CODE_PROOF_CANNOT_BE_CONFIRMED_WITHOUT_EVIDENCE ) self.finished = True db.session.flush()
def delete(invoiceId, stationaryItemId): if Invoice.has_confirmed(invoiceId): raise ForbiddenException("Stationary items cannot be deleted from confirmed invoices (%d)" % invoiceId) else: result = Model.query.filter( Model.invoiceId == invoiceId, Model.stationaryItemId == stationaryItemId ).delete() db.session.flush() return result
def set_submitted_version(self, tallySheetVersion: TallySheetVersion): if self.locked: raise ForbiddenException( message="Tally sheet is already locked.", code=MESSAGE_CODE_TALLY_SHEET_CANNOT_SUBMIT_AFTER_LOCK) if tallySheetVersion is None: self.submission.set_submitted_version(submissionVersion=None) else: self.submission.set_submitted_version( submissionVersion=tallySheetVersion.submissionVersion) self.update_status_report()
def populate_seats_per_party(self, number_of_members_to_be_elected=0): df = self.get_party_wise_valid_vote_count_result() total_valid_vote_count = df['numValue'].sum() if total_valid_vote_count == 0: raise ForbiddenException( message= "National list seat calculation cannot be done on zero votes.", code= MESSAGE_CODE_PE_AI_NL_1_CANNOT_BE_PROCESSED_WITHOUT_PE_AI_ED ) valid_vote_count_required_per_seat = total_valid_vote_count / number_of_members_to_be_elected valid_vote_count_required_per_seat_ceil = math.ceil( valid_vote_count_required_per_seat) for index in df.index: num_value = df.at[index, 'numValue'] number_of_seats_qualified = math.floor( num_value / valid_vote_count_required_per_seat_ceil) df.at[index, 'seatsAllocatedFromRound1'] = number_of_seats_qualified number_of_members_to_be_elected -= number_of_seats_qualified df.at[ index, 'validVotesRemainFromRound1'] = num_value % valid_vote_count_required_per_seat_ceil df = df.sort_values(by=['validVotesRemainFromRound1'], ascending=False) for index in df.index: if number_of_members_to_be_elected > 0: number_of_seats_qualified = 1 df.at[ index, 'seatsAllocatedFromRound2'] = number_of_seats_qualified number_of_members_to_be_elected -= number_of_seats_qualified else: df.at[index, 'seatsAllocatedFromRound2'] = 0 df['seatsAllocated'] = df.seatsAllocatedFromRound1 + df.seatsAllocatedFromRound2 df['draftSeatsAllocatedFromRound2'] = df.seatsAllocatedFromRound2 df = df.sort_values(by=['numValue'], ascending=False) df["voteCountCeilPerSeat"] = pd.Series(np.full( len(df.index), valid_vote_count_required_per_seat_ceil), index=df.index) return df
def populate_seats_per_party(self, number_of_members_to_be_elected=0): df = self.get_party_wise_valid_vote_count_result() total_valid_vote_count = df['numValue'].sum() if total_valid_vote_count == 0: raise ForbiddenException( message= "Bonus Seat Allocation 1 (PCE_PC_BS_1) cannot be decided until the Provincial Vote Results (PCE-PC-V) is completed and verified.", code= MESSAGE_CODE_PCE_PC_BS_1_CANNOT_BE_PROCESSED_WITHOUT_PCE_PC_V ) valid_vote_count_required_per_seat = total_valid_vote_count / number_of_members_to_be_elected valid_vote_count_required_per_seat_ceil = math.ceil( valid_vote_count_required_per_seat) for index in df.index: num_value = df.at[index, 'numValue'] number_of_seats_qualified = math.floor( num_value / valid_vote_count_required_per_seat_ceil) df.at[index, 'seatsAllocatedFromRound1'] = number_of_seats_qualified number_of_members_to_be_elected -= number_of_seats_qualified df.at[ index, 'validVotesRemainFromRound1'] = num_value % valid_vote_count_required_per_seat_ceil df = df.sort_values(by=['validVotesRemainFromRound1'], ascending=False) for index in df.index: if number_of_members_to_be_elected > 0: number_of_seats_qualified = 1 df.at[ index, 'seatsAllocatedFromRound2'] = number_of_seats_qualified number_of_members_to_be_elected -= number_of_seats_qualified else: df.at[index, 'seatsAllocatedFromRound2'] = 0 df['seatsAllocated'] = df.seatsAllocatedFromRound1 + df.seatsAllocatedFromRound2 df['draftSeatsAllocatedFromRound2'] = df.seatsAllocatedFromRound2 df = df.sort_values(by=['numValue'], ascending=False) df["voteCountCeilPerSeat"] = pd.Series(np.full( len(df.index), valid_vote_count_required_per_seat_ceil), index=df.index) return df
def validate_tally_sheet_version_request_content_special_characters( content_array): invalid_strings = ["'", "\"", "<", ">", "=", ",", ";"] for array_item in content_array: if "strValue" in array_item and array_item["strValue"] is not None: text_value = str(array_item["strValue"]) for char in invalid_strings: if char in text_value or len(text_value) > 500: raise ForbiddenException( message= "Invalid input detected. Use of disallowed characters/invalid input length detected. " + char + " included in " + text_value, code=MESSAGE_CODE_INVALID_INPUT) return True
def create(invoiceId, stationaryItemId): if Invoice.has_confirmed(invoiceId): raise ForbiddenException("Stationary items cannot be added to confirmed invoices (%d)" % invoiceId) elif StationaryItem.is_locked(stationaryItemId): raise ForbiddenException("Stationary item is not available (%d)" % stationaryItemId) else: received_proof = Proof.create( proofType=ProofTypeEnum.InvoiceStationaryItemReceive ) print("######################### received_proof ###", received_proof) print("######################### received_proof.proofId ###", received_proof.proofId) result = Model( invoiceId=invoiceId, stationaryItemId=stationaryItemId, receivedProofId=received_proof.proofId ) db.session.add(result) db.session.commit() return result
def delete(invoiceId): instance = get_by_id(invoiceId) if instance is None: raise NotFoundException( "Invoice not found associated with the given invoiceId (invoiceId=%d)" % invoiceId) elif instance.confirmed: raise ForbiddenException( "Confirmed invoices cannot be deleted (invoiceId=%d)" % invoiceId) else: instance.delete = True db.session.flush() return 1
def upload_file(proofId, fileSource, fileType): proof = get_by_id(proofId=proofId) if proof is None: raise NotFoundException( "Proof not found associated with the given proofId (proofId=%d)" % proofId) elif proof.finished is True: raise ForbiddenException( "No more evidence is accepted for this proof (proofId=%d)" % proofId) else: file = File.create(fileSource=fileSource, fileType=fileType) FolderFile.create(folderId=proof.scannedFilesFolderId, fileId=file.fileId) return proof
def update(proofId, finished=None): instance = get_by_id(proofId) if instance is None: raise NotFoundException( "Proof not found associated with the given proofId (proofId=%d)" % proofId) else: if finished is not None: if len(instance.scannedFiles) is 0: raise ForbiddenException( "A proof required at least one evidence. Please upload an evidence (proofId=%d)" % proofId) instance.finished = finished db.session.commit() return instance
def request_edit(tallySheetId): tally_sheet = TallySheet.get_by_id(tallySheetId=tallySheetId) if tally_sheet is None: raise NotFoundException( message="Tally sheet not found (tallySheetId=%d)" % tallySheetId, code=MESSAGE_CODE_TALLY_SHEET_NOT_FOUND ) if tally_sheet.tallySheetCode not in [TallySheetCodeEnum.PRE_41, TallySheetCodeEnum.CE_201, TallySheetCodeEnum.CE_201_PV, TallySheetCodeEnum.PRE_34_CO]: raise ForbiddenException( message="Submit operation is not supported for this tally sheet type.", code=MESSAGE_CODE_TALLY_SHEET_SUBMIT_IS_NOT_SUPPORTED ) tally_sheet.set_submitted_version(None) db.session.commit() return TallySheetSchema().dump(tally_sheet).data, 201
def update(proofId, finished=None): instance = get_by_id(proofId) if instance is None: raise NotFoundException( "Proof not found associated with the given proofId (proofId=%d)" % proofId, code=MESSAGE_CODE_PROOF_NOT_FOUND ) else: if finished is not None: if len(instance.scannedFiles) is 0: raise ForbiddenException( message="A proof required at least one evidence. Please upload an evidence (proofId=%d)" % proofId, code=MESSAGE_CODE_PROOF_CANNOT_BE_CONFIRMED_WITHOUT_EVIDENCE ) instance.finished = finished db.session.flush() return instance
def get_post_save_request_content(self): tally_sheet_id = self.tallySheetVersion.tallySheetId template_rows = db.session.query( TemplateRowModel.templateRowId, TemplateRowModel.templateRowType).filter( TemplateModel.templateId == TallySheet.Model.templateId, TemplateRowModel.templateId == TemplateModel.templateId, TemplateRowModel.templateRowType.in_([ TEMPLATE_ROW_TYPE_ELECTED_CANDIDATE, TEMPLATE_ROW_TYPE_DRAFT_ELECTED_CANDIDATE ]), TallySheet.Model.tallySheetId == tally_sheet_id).group_by( TemplateRowModel.templateRowId).all() content = [] seats_allocated_per_party_df = self.df.loc[( self.df['templateRowType'] == TEMPLATE_ROW_TYPE_SEATS_ALLOCATED ) & (self.df['numValue'] > 0)] if len(seats_allocated_per_party_df) == 0: raise ForbiddenException( message= "Bonus Seat Allocation 2 (PCE_PC_BS_2) cannot be determined until the Bonus Seat Allocation 1 (PCE_PC_BS_1) is decided and verified.", code= MESSAGE_CODE_PCE_PC_BS_2_CANNOT_BE_PROCESSED_WITHOUT_PCE_PC_BS_1 ) # The derived rows are calculated only if the PCE-R2 is available and verified. if len(seats_allocated_per_party_df) > 0: for index_1 in seats_allocated_per_party_df.index: party_id = int(seats_allocated_per_party_df.at[index_1, "partyId"]) number_of_seats_allocated = seats_allocated_per_party_df.at[ index_1, "numValue"] if number_of_seats_allocated is not None and not math.isnan( number_of_seats_allocated): candidates = db.session.query( Candidate.Model.candidateId).filter( Candidate.Model.candidateId == ElectionCandidateModel.candidateId, ElectionCandidateModel.partyId == party_id).group_by( Candidate.Model.candidateId).order_by( Candidate.Model.candidateId).all() for candidate in candidates: if number_of_seats_allocated > 0: for template_row in template_rows: candidate_id = candidate.candidateId content.append({ "templateRowId": template_row.templateRowId, "templateRowType": template_row.templateRowType, "partyId": int(party_id), "candidateId": int(candidate_id), # TODO remove once the complete validation has been fixed. "numValue": 0 }) number_of_seats_allocated -= 1 return content
def __init__(self, reportId): report = Report_PRE_41.get_by_id(reportId=reportId) if report is None: raise NotFoundException("Report not found. (reportId=%d)" % reportId) if len(report.area.tallySheets_PRE_41) is 0: raise ForbiddenException( "There's no PRE-41 tally sheet for the counting centre (officeId)" % report.area.areaId) elif len(report.area.tallySheets_PRE_41) > 1: raise ForbiddenException( "There's more than one PRE-41 tally sheet for the counting centre (officeId)" % report.area.areaId) tallySheet = report.area.tallySheets_PRE_41[0] latestVersion = tallySheet.latestVersion if latestVersion is None: raise NotFoundException("No tallysheet data filled yet. (tallySheetId=%d)" % tallySheet.tallySheetId) tallySheetContent = latestVersion.content content = { "title": "PRESIDENTIAL ELECTION ACT NO. 15 OF 1981", "electoralDistrict": Area.get_associated_areas(report.area, AreaTypeEnum.ElectoralDistrict)[0].areaName, "pollingDivision": Area.get_associated_areas(report.area, AreaTypeEnum.PollingDivision)[0].areaName, "pollingDistrictNos": ", ".join([ pollingDistrict.areaName for pollingDistrict in Area.get_associated_areas(report.area, AreaTypeEnum.PollingDistrict) ]), "countingHallNo": report.area.areaName, "data": [ ], "total": 0, "rejectedVotes": 0, "grandTotal": 0 } for row_index in range(len(tallySheetContent)): row = tallySheetContent[row_index] if row.count is not None: content["data"].append([ row_index + 1, row.candidateName, row.partySymbol, row.countInWords, row.count, "" ]) content["total"] = content["total"] + row.count else: content["data"].append([ row_index + 1, row.candidateName, row.partySymbol, "", "", "" ]) content["rejectedVotes"] = 0 # TODO content["grandTotal"] = content["total"] + content["rejectedVotes"] html = render_template( 'pre-41.html', content=content ) super(ReportVersion_PRE_41_Model, self).__init__(reportId=reportId, html=html)
def populate_seats_per_party(self, minimum_vote_count_percentage_required, number_of_members_to_be_elected=0): df = self.get_party_wise_valid_vote_count_result() total_valid_vote_count = df['numValue'].sum() if total_valid_vote_count == 0: raise ForbiddenException( message="Seat calculation cannot be done on zero votes.", code= MESSAGE_CODE_SEAT_CALCULATION_CANNOT_BE_DONE_ON_ZERO_VOTES) _minimum_valid_vote_count_required_per_party_to_be_qualified = total_valid_vote_count * minimum_vote_count_percentage_required total_valid_vote_count_of_qualified_parties = 0 for index in df.index: if df.at[ index, 'numValue'] >= _minimum_valid_vote_count_required_per_party_to_be_qualified: df.at[index, 'qualifiedForSeatsAllocation'] = True total_valid_vote_count_of_qualified_parties += df.at[ index, 'numValue'] else: df.at[index, 'qualifiedForSeatsAllocation'] = False max_valid_vote_count_per_party = df['numValue'].max() for index in df.index: if df.at[index, 'numValue'] == max_valid_vote_count_per_party: df.at[index, 'bonusSeatsAllocated'] = 1 number_of_members_to_be_elected -= 1 else: df.at[index, 'bonusSeatsAllocated'] = 0 valid_vote_count_required_per_seat = total_valid_vote_count_of_qualified_parties / number_of_members_to_be_elected valid_vote_count_required_per_seat_ceil = math.ceil( valid_vote_count_required_per_seat) for index in df.index: num_value = df.at[index, 'numValue'] if df.at[index, 'qualifiedForSeatsAllocation']: number_of_seats_qualified = math.floor( num_value / valid_vote_count_required_per_seat_ceil) df.at[ index, 'seatsAllocatedFromRound1'] = number_of_seats_qualified number_of_members_to_be_elected -= number_of_seats_qualified df.at[ index, 'validVotesRemainFromRound1'] = num_value % valid_vote_count_required_per_seat_ceil else: df.at[index, 'seatsAllocatedFromRound1'] = 0 df.at[index, 'validVotesRemainFromRound1'] = 0 df = df.sort_values(by=['validVotesRemainFromRound1'], ascending=False) for index in df.index: if df.at[ index, 'qualifiedForSeatsAllocation'] and number_of_members_to_be_elected > 0: number_of_seats_qualified = 1 df.at[ index, 'seatsAllocatedFromRound2'] = number_of_seats_qualified number_of_members_to_be_elected -= number_of_seats_qualified else: df.at[index, 'seatsAllocatedFromRound2'] = 0 df['seatsAllocated'] = df.seatsAllocatedFromRound1 + df.seatsAllocatedFromRound2 + df.bonusSeatsAllocated df['draftSeatsAllocatedFromRound2'] = df.seatsAllocatedFromRound2 df['draftBonusSeatsAllocated'] = df.bonusSeatsAllocated df = df.sort_values(by=['numValue'], ascending=False) df["voteCountCeilPerSeat"] = pd.Series(np.full( len(df.index), valid_vote_count_required_per_seat_ceil), index=df.index) df["minimumVoteCountRequiredForSeatAllocation"] = pd.Series( np.full( len(df.index), _minimum_valid_vote_count_required_per_party_to_be_qualified ), index=df.index) return df