def update_foundanimal_from_form(dbo, data, username): """ Updates a found animal record from the screen data: The webpy data object containing form parameters """ l = dbo.locale lfid = utils.df_ki(data, "id") if utils.df_kd(data, "datefound", l) is None: raise utils.ASMValidationError(_("Date found cannot be blank", l)) if utils.df_kd(data, "datereported", l) is None: raise utils.ASMValidationError(_("Date reported cannot be blank", l)) if utils.df_ki(data, "owner") == "0": raise utils.ASMValidationError(_("Found animals must have a contact", l)) preaudit = db.query(dbo, "SELECT * FROM animalfound WHERE ID = %d" % lfid) db.execute(dbo, db.make_update_user_sql(dbo, "animalfound", username, "ID=%d" % lfid, ( ( "AnimalTypeID", utils.df_s(data, "species")), ( "DateReported", utils.df_d(data, "datereported", l)), ( "ReturnToOwnerDate", utils.df_d(data, "returntoownerdate", l)), ( "DateFound", utils.df_d(data, "datefound", l)), ( "Sex", utils.df_s(data, "sex")), ( "BreedID", utils.df_s(data, "breed")), ( "AgeGroup", utils.df_t(data, "agegroup")), ( "BaseColourID", utils.df_s(data, "colour")), ( "DistFeat", utils.df_t(data, "markings")), ( "AreaFound", utils.df_t(data, "areafound")), ( "AreaPostcode", utils.df_t(data, "areapostcode")), ( "OwnerID", utils.df_s(data, "owner")), ( "Comments", utils.df_t(data, "comments")) ))) additional.save_values_for_link(dbo, data, lfid, "foundanimal") postaudit = db.query(dbo, "SELECT * FROM animalfound WHERE ID = %d" % lfid) audit.edit(dbo, username, "animalfound", audit.map_diff(preaudit, postaudit))
def insert_foundanimal_from_form(dbo, data, username): """ Inserts a new found animal record from the screen data: The webpy data object containing form parameters """ l = dbo.locale if utils.df_kd(data, "datefound", l) is None: raise utils.ASMValidationError(_("Date found cannot be blank", l)) if utils.df_kd(data, "datereported", l) is None: raise utils.ASMValidationError(_("Date reported cannot be blank", l)) if utils.df_ki(data, "owner") == "0": raise utils.ASMValidationError(_("Found animals must have a contact", l)) nid = db.get_id(dbo, "animalfound") db.execute(dbo, db.make_insert_user_sql(dbo, "animalfound", username, ( ( "ID", db.di(nid)), ( "AnimalTypeID", utils.df_s(data, "species")), ( "DateReported", utils.df_d(data, "datereported", l)), ( "ReturnToOwnerDate", utils.df_d(data, "returntoownerdate", l)), ( "DateFound", utils.df_d(data, "datefound", l)), ( "Sex", utils.df_s(data, "sex")), ( "BreedID", utils.df_s(data, "breed")), ( "AgeGroup", utils.df_t(data, "agegroup")), ( "BaseColourID", utils.df_s(data, "colour")), ( "DistFeat", utils.df_t(data, "markings")), ( "AreaFound", utils.df_t(data, "areafound")), ( "AreaPostcode", utils.df_t(data, "areapostcode")), ( "OwnerID", utils.df_s(data, "owner")), ( "Comments", utils.df_t(data, "comments")) ))) audit.create(dbo, username, "animalfound", str(nid)) return nid
def insert_retailer_from_form(dbo, username, data): """ Inserts a retailer from the workflow move to retailer screen. Returns the new movement id """ # Validate that we have a movement date before doing anthing l = dbo.locale if None == utils.df_kd(data, "retailerdate", l): raise utils.ASMValidationError(i18n._("Retailer movements must have a valid movement date.", l)) # Is this animal already at a foster? If so, return that foster first fm = get_animal_movements(dbo, utils.df_ki(data, "animal")) for m in fm: if m["MOVEMENTTYPE"] == FOSTER and m["RETURNDATE"] is None: return_movement(dbo, m["ID"], utils.df_ki(data, "animal"), utils.df_kd(data, "retailerdate", l)) # Create the retailer movement move_dict = { "person" : utils.df_ks(data, "person"), "animal" : utils.df_ks(data, "animal"), "movementdate" : utils.df_ks(data, "retailerdate"), "adoptionno" : utils.df_ks(data, "movementnumber"), "type" : str(RETAILER), "donation" : utils.df_ks(data, "amount"), "returncategory" : configuration.default_return_reason(dbo) } movementid = insert_movement_from_form(dbo, username, move_dict) return movementid
def insert_retailer_from_form(dbo, username, data): """ Inserts a retailer from the workflow move to retailer screen. Returns the new movement id """ # Validate that we have a movement date before doing anthing l = dbo.locale if None == utils.df_kd(data, "retailerdate", l): raise utils.ASMValidationError( i18n._("Retailer movements must have a valid movement date.", l)) # Is this animal already at a foster? If so, return that foster first fm = get_animal_movements(dbo, utils.df_ki(data, "animal")) for m in fm: if m["MOVEMENTTYPE"] == FOSTER and m["RETURNDATE"] is None: return_movement(dbo, m["ID"], utils.df_ki(data, "animal"), utils.df_kd(data, "retailerdate", l)) # Create the retailer movement move_dict = { "person": utils.df_ks(data, "person"), "animal": utils.df_ks(data, "animal"), "movementdate": utils.df_ks(data, "retailerdate"), "adoptionno": utils.df_ks(data, "movementnumber"), "type": str(RETAILER), "donation": utils.df_ks(data, "amount"), "returncategory": configuration.default_return_reason(dbo) } movementid = insert_movement_from_form(dbo, username, move_dict) return movementid
def save_values_for_link(dbo, data, linkid, linktype="animal"): """ Saves incoming additional field values from a form, clearing any existing values first. """ delete_values_for_link(dbo, linkid, linktype) af = get_field_definitions(dbo, linktype) l = dbo.locale for f in af: key = "a." + str(f["MANDATORY"]) + "." + str(f["ID"]) if data.has_key(key): val = utils.df_ks(data, key) if f["FIELDTYPE"] == YESNO: val = str(utils.df_kc(data, key)) elif f["FIELDTYPE"] == MONEY: val = str(utils.df_km(data, key, l)) elif f["FIELDTYPE"] == DATE: if len(val.strip()) > 0 and utils.df_kd(data, key, l) == None: raise utils.ASMValidationError( _( "Additional date field '{0}' contains an invalid date.", l).format(f["FIELDNAME"])) val = python2display(dbo.locale, utils.df_kd(data, key, l)) sql = db.make_insert_sql("additional", (("LinkType", db.di(f["LINKTYPE"])), ("LinkID", db.di(int(linkid))), ("AdditionalFieldID", db.di(f["ID"])), ("Value", db.ds(val)))) try: db.execute(dbo, sql) except Exception, err: al.error("Failed saving additional field: %s" % str(err), "animal.update_animal_from_form", dbo, sys.exc_info())
def update_diary_from_form(dbo, username, data): """ Updates a diary note from form data """ l = dbo.locale diaryid = utils.df_ki(data, "diaryid") if utils.df_ks(data, "diarydate") == "": raise utils.ASMValidationError(i18n._("Diary date cannot be blank", l)) if utils.df_kd(data, "diarydate", l) is None: raise utils.ASMValidationError(i18n._("Diary date is not valid", l)) if utils.df_ks(data, "subject") == "": raise utils.ASMValidationError(i18n._("Diary subject cannot be blank", l)) if utils.df_ks(data, "note") == "": raise utils.ASMValidationError(i18n._("Diary note cannot be blank", l)) diarytime = utils.df_ks(data, "diarytime").strip() if diarytime != "": if diarytime.find(":") == -1: raise utils.ASMValidationError(i18n._("Invalid time, times should be in HH:MM format", l)) if not utils.is_numeric(diarytime.replace(":", "")): raise utils.ASMValidationError(i18n._("Invalid time, times should be in HH:MM format", l)) sql = db.make_update_user_sql(dbo, "diary", username, "ID=%d" % diaryid, ( ( "DiaryDateTime", utils.df_dt(data, "diarydate", "diarytime", l) ), ( "DiaryForName", utils.df_t(data, "diaryfor") ), ( "Subject", utils.df_t(data, "subject") ), ( "Note", utils.df_t(data, "note") ), ( "Comments", utils.df_t(data, "comments") ), ( "DateCompleted", utils.df_d(data, "completed", l) ) )) preaudit = db.query(dbo, "SELECT * FROM diary WHERE ID=%d" % diaryid) db.execute(dbo, sql) postaudit = db.query(dbo, "SELECT * FROM diary WHERE ID=%d" % diaryid) audit.edit(dbo, username, "diary", audit.map_diff(preaudit, postaudit))
def update_test_from_form(dbo, username, data): """ Updates a test record from posted form data """ l = dbo.locale testid = utils.df_ki(data, "testid") if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError( _("Required date must be a valid date", l)) sql = db.make_update_user_sql( dbo, "animaltest", username, "ID=%d" % testid, (("AnimalID", db.di(utils.df_ki(data, "animal"))), ("TestTypeID", utils.df_s(data, "type")), ("TestResultID", utils.df_s(data, "result")), ("DateOfTest", utils.df_d(data, "given", l)), ("DateRequired", utils.df_d(data, "required", l)), ("Cost", utils.df_m(data, "cost", l)), ("Comments", utils.df_t(data, "comments")))) preaudit = db.query(dbo, "SELECT * FROM animaltest WHERE ID = %d" % testid) db.execute(dbo, sql) postaudit = db.query(dbo, "SELECT * FROM animaltest WHERE ID = %d" % testid) audit.edit(dbo, username, "animaltest", audit.map_diff(preaudit, postaudit)) # ASM2_COMPATIBILITY update_asm2_tests(dbo, testid)
def update_vaccination_from_form(dbo, username, data): """ Updates a vaccination record from posted form data """ l = dbo.locale vaccid = utils.df_ki(data, "vaccid") if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError( _("Required date must be a valid date", l)) sql = db.make_update_user_sql( dbo, "animalvaccination", username, "ID=%d" % vaccid, (("AnimalID", db.di(utils.df_ki(data, "animal"))), ("VaccinationID", utils.df_s(data, "type")), ("DateOfVaccination", utils.df_d(data, "given", l)), ("DateRequired", utils.df_d(data, "required", l)), ("Cost", utils.df_m(data, "cost", l)), ("Comments", utils.df_t(data, "comments")))) preaudit = db.query( dbo, "SELECT * FROM animalvaccination WHERE ID = %d" % vaccid) db.execute(dbo, sql) postaudit = db.query( dbo, "SELECT * FROM animalvaccination WHERE ID = %d" % vaccid) audit.edit(dbo, username, "animalvaccination", audit.map_diff(preaudit, postaudit))
def save_values_for_link(dbo, data, linkid, linktype="animal"): """ Saves incoming additional field values from a form, clearing any existing values first. """ delete_values_for_link(dbo, linkid, linktype) af = get_field_definitions(dbo, linktype) l = dbo.locale for f in af: key = "a." + str(f["MANDATORY"]) + "." + str(f["ID"]) if data.has_key(key): val = utils.df_ks(data, key) if f["FIELDTYPE"] == YESNO: val = str(utils.df_kc(data, key)) elif f["FIELDTYPE"] == MONEY: val = str(utils.df_km(data, key, l)) elif f["FIELDTYPE"] == DATE: if len(val.strip()) > 0 and utils.df_kd(data, key, l) == None: raise utils.ASMValidationError( _("Additional date field '{0}' contains an invalid date.", l).format(f["FIELDNAME"]) ) val = python2display(dbo.locale, utils.df_kd(data, key, l)) sql = db.make_insert_sql( "additional", ( ("LinkType", db.di(f["LINKTYPE"])), ("LinkID", db.di(int(linkid))), ("AdditionalFieldID", db.di(f["ID"])), ("Value", db.ds(val)), ), ) try: db.execute(dbo, sql) except Exception, err: al.error( "Failed saving additional field: %s" % str(err), "animal.update_animal_from_form", dbo, sys.exc_info(), )
def insert_regimen_from_form(dbo, username, data): """ Creates a regimen record from posted form data """ l = dbo.locale if utils.df_kd(data, "startdate", l) is None: raise utils.ASMValidationError(_("Start date must be a valid date", l)) if utils.df_ks(data, "treatmentname") == "": raise utils.ASMValidationError(_("Treatment name cannot be blank", l)) l = dbo.locale nregid = db.get_id(dbo, "animalmedical") timingrule = utils.df_ki(data, "timingrule") timingrulenofrequencies = utils.df_ki(data, "timingrulenofrequencies") timingrulefrequency = utils.df_ki(data, "timingrulefrequency") totalnumberoftreatments = utils.df_ki(data, "totalnumberoftreatments") treatmentsremaining = int(totalnumberoftreatments) * int(timingrule) treatmentrule = utils.df_ki(data, "treatmentrule") singlemulti = utils.df_ki(data, "singlemulti") if singlemulti == 0: timingrule = 0 timingrulenofrequencies = 0 timingrulefrequency = 0 treatmentsremaining = 1 if treatmentrule != 0: totalnumberoftreatments = 0 treatmentsremaining = 0 sql = db.make_insert_user_sql( dbo, "animalmedical", username, (("ID", db.di(nregid)), ("AnimalID", db.di(utils.df_ki(data, "animal"))), ("MedicalProfileID", utils.df_s(data, "profileid")), ("TreatmentName", utils.df_t(data, "treatmentname")), ("Dosage", utils.df_t(data, "dosage")), ("StartDate", utils.df_d(data, "startdate", l)), ("Status", db.di(0)), ("Cost", utils.df_m(data, "cost", l)), ("TimingRule", db.di(timingrule)), ("TimingRuleFrequency", db.di(timingrulefrequency)), ("TimingRuleNoFrequencies", db.di(timingrulenofrequencies)), ("TreatmentRule", utils.df_s(data, "treatmentrule")), ("TotalNumberOfTreatments", db.di(totalnumberoftreatments)), ("TreatmentsGiven", db.di(0)), ("TreatmentsRemaining", db.di(treatmentsremaining)), ("Comments", utils.df_t(data, "comments")))) db.execute(dbo, sql) audit.create( dbo, username, "animalmedical", str(nregid) + ": " + utils.df_ks(data, "treatmentname") + " " + utils.df_ks(data, "dosage")) update_medical_treatments(dbo, username, nregid)
def insert_regimen_from_form(dbo, username, data): """ Creates a regimen record from posted form data """ l = dbo.locale if utils.df_kd(data, "startdate", l) is None: raise utils.ASMValidationError(_("Start date must be a valid date", l)) if utils.df_ks(data, "treatmentname") == "": raise utils.ASMValidationError(_("Treatment name cannot be blank", l)) l = dbo.locale nregid = db.get_id(dbo, "animalmedical") timingrule = utils.df_ki(data, "timingrule") timingrulenofrequencies = utils.df_ki(data, "timingrulenofrequencies") timingrulefrequency = utils.df_ki(data, "timingrulefrequency") totalnumberoftreatments = utils.df_ki(data, "totalnumberoftreatments") treatmentsremaining = int(totalnumberoftreatments) * int(timingrule) treatmentrule = utils.df_ki(data, "treatmentrule") singlemulti = utils.df_ki(data, "singlemulti") if singlemulti == 0: timingrule = 0 timingrulenofrequencies = 0 timingrulefrequency = 0 treatmentsremaining = 1 if treatmentrule != 0: totalnumberoftreatments = 0 treatmentsremaining = 0 sql = db.make_insert_user_sql(dbo, "animalmedical", username, ( ( "ID", db.di(nregid)), ( "AnimalID", db.di(utils.df_ki(data, "animal"))), ( "MedicalProfileID", utils.df_s(data, "profileid")), ( "TreatmentName", utils.df_t(data, "treatmentname")), ( "Dosage", utils.df_t(data, "dosage")), ( "StartDate", utils.df_d(data, "startdate", l)), ( "Status", db.di(0)), ( "Cost", utils.df_m(data, "cost", l)), ( "TimingRule", db.di(timingrule)), ( "TimingRuleFrequency", db.di(timingrulefrequency)), ( "TimingRuleNoFrequencies", db.di(timingrulenofrequencies)), ( "TreatmentRule", utils.df_s(data, "treatmentrule")), ( "TotalNumberOfTreatments", db.di(totalnumberoftreatments)), ( "TreatmentsGiven", db.di(0)), ( "TreatmentsRemaining", db.di(treatmentsremaining)), ( "Comments", utils.df_t(data, "comments")) )) db.execute(dbo, sql) audit.create(dbo, username, "animalmedical", str(nregid) + ": " + utils.df_ks(data, "treatmentname") + " " + utils.df_ks(data, "dosage")) update_medical_treatments(dbo, username, nregid)
def update_log_from_form(dbo, username, data): """ Updates a log from form data """ l = dbo.locale logid = utils.df_ki(data, "logid") if utils.df_kd(data, "logdate", l) is None: raise utils.ASMValidationError(i18n._("Log date must be a valid date", l)) sql = db.make_update_user_sql(dbo, "log", username, "ID=%d" % logid, ( ( "LogTypeID", utils.df_s(data, "type")), ( "Date", utils.df_d(data, "logdate", l) ), ( "Comments", utils.df_t(data, "entry") ) )) preaudit = db.query(dbo, "SELECT * FROM log WHERE ID=%d" % logid) db.execute(dbo, sql) postaudit = db.query(dbo, "SELECT * FROM log WHERE ID=%d" % logid) audit.edit(dbo, username, "log", audit.map_diff(preaudit, postaudit))
def update_vaccination_from_form(dbo, username, data): """ Updates a vaccination record from posted form data """ l = dbo.locale vaccid = utils.df_ki(data, "vaccid") if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError(_("Required date must be a valid date", l)) sql = db.make_update_user_sql(dbo, "animalvaccination", username, "ID=%d" % vaccid, ( ( "AnimalID", db.di(utils.df_ki(data, "animal"))), ( "VaccinationID", utils.df_s(data, "type")), ( "DateOfVaccination", utils.df_d(data, "given", l)), ( "DateRequired", utils.df_d(data, "required", l)), ( "Cost", utils.df_m(data, "cost", l)), ( "Comments", utils.df_t(data, "comments")) )) preaudit = db.query(dbo, "SELECT * FROM animalvaccination WHERE ID = %d" % vaccid) db.execute(dbo, sql) postaudit = db.query(dbo, "SELECT * FROM animalvaccination WHERE ID = %d" % vaccid) audit.edit(dbo, username, "animalvaccination", audit.map_diff(preaudit, postaudit))
def insert_vaccination_from_form(dbo, username, data): """ Creates a vaccination record from posted form data """ l = dbo.locale if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError( _("Required date must be a valid date", l)) nvaccid = db.get_id(dbo, "animalvaccination") sql = db.make_insert_user_sql( dbo, "animalvaccination", username, (("ID", db.di(nvaccid)), ("AnimalID", db.di(utils.df_ki( data, "animal"))), ("VaccinationID", utils.df_s(data, "type")), ("DateOfVaccination", utils.df_d(data, "given", l)), ("DateRequired", utils.df_d(data, "required", l)), ("Cost", utils.df_m(data, "cost", l)), ("Comments", utils.df_t(data, "comments")))) db.execute(dbo, sql) audit.create(dbo, username, "animalvaccination", str(nvaccid)) return nvaccid
def insert_vaccination_from_form(dbo, username, data): """ Creates a vaccination record from posted form data """ l = dbo.locale if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError(_("Required date must be a valid date", l)) nvaccid = db.get_id(dbo, "animalvaccination") sql = db.make_insert_user_sql(dbo, "animalvaccination", username, ( ( "ID", db.di(nvaccid)), ( "AnimalID", db.di(utils.df_ki(data, "animal"))), ( "VaccinationID", utils.df_s(data, "type")), ( "DateOfVaccination", utils.df_d(data, "given", l)), ( "DateRequired", utils.df_d(data, "required", l)), ( "Cost", utils.df_m(data, "cost", l)), ( "Comments", utils.df_t(data, "comments")) )) db.execute(dbo, sql) audit.create(dbo, username, "animalvaccination", str(nvaccid)) return nvaccid
def insert_diary_from_form(dbo, username, linktypeid, linkid, data): """ Creates a diary note from the form data username: User creating the diary linktypeid, linkid: The link data: The web.py form object """ l = dbo.locale if utils.df_ks(data, "diarydate") == "": raise utils.ASMValidationError(i18n._("Diary date cannot be blank", l)) if utils.df_kd(data, "diarydate", l) is None: raise utils.ASMValidationError(i18n._("Diary date is not valid", l)) if utils.df_ks(data, "subject") == "": raise utils.ASMValidationError( i18n._("Diary subject cannot be blank", l)) if utils.df_ks(data, "note") == "": raise utils.ASMValidationError(i18n._("Diary note cannot be blank", l)) diarytime = utils.df_ks(data, "diarytime").strip() if diarytime != "": if diarytime.find(":") == -1: raise utils.ASMValidationError( i18n._("Invalid time, times should be in HH:MM format", l)) if not utils.is_numeric(diarytime.replace(":", "")): raise utils.ASMValidationError( i18n._("Invalid time, times should be in HH:MM format", l)) linkinfo = get_link_info(dbo, linktypeid, linkid) diaryid = db.get_id(dbo, "diary") sql = db.make_insert_user_sql( dbo, "diary", username, (("ID", db.di(diaryid)), ("LinkID", db.di(linkid)), ("LinkType", db.di(linktypeid)), ("LinkInfo", db.ds(linkinfo)), ("DiaryDateTime", utils.df_dt(data, "diarydate", "diarytime", l)), ("DiaryForName", utils.df_t(data, "diaryfor")), ("Subject", utils.df_t(data, "subject")), ("Note", utils.df_t(data, "note")), ("DateCompleted", utils.df_d(data, "completed", l)))) db.execute(dbo, sql) audit.create(dbo, username, "diary", str(diaryid)) return diaryid
def insert_diary_from_form(dbo, username, linktypeid, linkid, data): """ Creates a diary note from the form data username: User creating the diary linktypeid, linkid: The link data: The web.py form object """ l = dbo.locale if utils.df_ks(data, "diarydate") == "": raise utils.ASMValidationError(i18n._("Diary date cannot be blank", l)) if utils.df_kd(data, "diarydate", l) is None: raise utils.ASMValidationError(i18n._("Diary date is not valid", l)) if utils.df_ks(data, "subject") == "": raise utils.ASMValidationError(i18n._("Diary subject cannot be blank", l)) if utils.df_ks(data, "note") == "": raise utils.ASMValidationError(i18n._("Diary note cannot be blank", l)) diarytime = utils.df_ks(data, "diarytime").strip() if diarytime != "": if diarytime.find(":") == -1: raise utils.ASMValidationError(i18n._("Invalid time, times should be in HH:MM format", l)) if not utils.is_numeric(diarytime.replace(":", "")): raise utils.ASMValidationError(i18n._("Invalid time, times should be in HH:MM format", l)) linkinfo = get_link_info(dbo, linktypeid, linkid) diaryid = db.get_id(dbo, "diary") sql = db.make_insert_user_sql(dbo, "diary", username, ( ( "ID", db.di(diaryid)), ( "LinkID", db.di(linkid) ), ( "LinkType", db.di(linktypeid) ), ( "LinkInfo", db.ds(linkinfo) ), ( "DiaryDateTime", utils.df_dt(data, "diarydate", "diarytime", l) ), ( "DiaryForName", utils.df_t(data, "diaryfor") ), ( "Subject", utils.df_t(data, "subject") ), ( "Note", utils.df_t(data, "note") ), ( "DateCompleted", utils.df_d(data, "completed", l) ) )) db.execute(dbo, sql) audit.create(dbo, username, "diary", str(diaryid)) return diaryid
def insert_log_from_form(dbo, username, linktypeid, linkid, data): """ Creates a log from the form data username: User creating the diary linktypeid, linkid: The link data: The web.py form object """ l = dbo.locale if utils.df_kd(data, "logdate", l) is None: raise utils.ASMValidationError(i18n._("Log date must be a valid date", l)) logid = db.get_id(dbo, "log") sql = db.make_insert_user_sql(dbo, "log", username, ( ( "ID", db.di(logid)), ( "LogTypeID", utils.df_s(data, "type")), ( "LinkID", db.di(linkid) ), ( "LinkType", db.di(linktypeid) ), ( "Date", utils.df_d(data, "logdate", l) ), ( "Comments", utils.df_t(data, "entry") ) )) db.execute(dbo, sql) audit.create(dbo, username, "log", str(logid)) return logid
def update_diary_from_form(dbo, username, data): """ Updates a diary note from form data """ l = dbo.locale diaryid = utils.df_ki(data, "diaryid") if utils.df_ks(data, "diarydate") == "": raise utils.ASMValidationError(i18n._("Diary date cannot be blank", l)) if utils.df_kd(data, "diarydate", l) is None: raise utils.ASMValidationError(i18n._("Diary date is not valid", l)) if utils.df_ks(data, "subject") == "": raise utils.ASMValidationError( i18n._("Diary subject cannot be blank", l)) if utils.df_ks(data, "note") == "": raise utils.ASMValidationError(i18n._("Diary note cannot be blank", l)) diarytime = utils.df_ks(data, "diarytime").strip() if diarytime != "": if diarytime.find(":") == -1: raise utils.ASMValidationError( i18n._("Invalid time, times should be in HH:MM format", l)) if not utils.is_numeric(diarytime.replace(":", "")): raise utils.ASMValidationError( i18n._("Invalid time, times should be in HH:MM format", l)) sql = db.make_update_user_sql( dbo, "diary", username, "ID=%d" % diaryid, (("DiaryDateTime", utils.df_dt(data, "diarydate", "diarytime", l)), ("DiaryForName", utils.df_t(data, "diaryfor")), ("Subject", utils.df_t(data, "subject")), ("Note", utils.df_t(data, "note")), ("Comments", utils.df_t(data, "comments")), ("DateCompleted", utils.df_d(data, "completed", l)))) preaudit = db.query(dbo, "SELECT * FROM diary WHERE ID=%d" % diaryid) db.execute(dbo, sql) postaudit = db.query(dbo, "SELECT * FROM diary WHERE ID=%d" % diaryid) audit.edit(dbo, username, "diary", audit.map_diff(preaudit, postaudit))
def update_test_from_form(dbo, username, data): """ Updates a test record from posted form data """ l = dbo.locale testid = utils.df_ki(data, "testid") if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError(_("Required date must be a valid date", l)) sql = db.make_update_user_sql(dbo, "animaltest", username, "ID=%d" % testid, ( ( "AnimalID", db.di(utils.df_ki(data, "animal"))), ( "TestTypeID", utils.df_s(data, "type")), ( "TestResultID", utils.df_s(data, "result")), ( "DateOfTest", utils.df_d(data, "given", l)), ( "DateRequired", utils.df_d(data, "required", l)), ( "Cost", utils.df_m(data, "cost", l)), ( "Comments", utils.df_t(data, "comments")) )) preaudit = db.query(dbo, "SELECT * FROM animaltest WHERE ID = %d" % testid) db.execute(dbo, sql) postaudit = db.query(dbo, "SELECT * FROM animaltest WHERE ID = %d" % testid) audit.edit(dbo, username, "animaltest", audit.map_diff(preaudit, postaudit)) # ASM2_COMPATIBILITY update_asm2_tests(dbo, testid)
def insert_test_from_form(dbo, username, data): """ Creates a test record from posted form data """ l = dbo.locale if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError( _("Required date must be a valid date", l)) ntestid = db.get_id(dbo, "animaltest") sql = db.make_insert_user_sql( dbo, "animaltest", username, (("ID", db.di(ntestid)), ("AnimalID", db.di(utils.df_ki( data, "animal"))), ("TestTypeID", utils.df_s(data, "type")), ("TestResultID", utils.df_s(data, "result")), ("DateOfTest", utils.df_d(data, "given", l)), ("DateRequired", utils.df_d(data, "required", l)), ("Cost", utils.df_m(data, "cost", l)), ("Comments", utils.df_t(data, "comments")))) db.execute(dbo, sql) audit.create(dbo, username, "animaltest", str(ntestid)) # ASM2_COMPATIBILITY update_asm2_tests(dbo, ntestid) return ntestid
def insert_test_from_form(dbo, username, data): """ Creates a test record from posted form data """ l = dbo.locale if utils.df_kd(data, "required", l) is None: raise utils.ASMValidationError(_("Required date must be a valid date", l)) ntestid = db.get_id(dbo, "animaltest") sql = db.make_insert_user_sql(dbo, "animaltest", username, ( ( "ID", db.di(ntestid)), ( "AnimalID", db.di(utils.df_ki(data, "animal"))), ( "TestTypeID", utils.df_s(data, "type")), ( "TestResultID", utils.df_s(data, "result")), ( "DateOfTest", utils.df_d(data, "given", l)), ( "DateRequired", utils.df_d(data, "required", l)), ( "Cost", utils.df_m(data, "cost", l)), ( "Comments", utils.df_t(data, "comments")) )) db.execute(dbo, sql) audit.create(dbo, username, "animaltest", str(ntestid)) # ASM2_COMPATIBILITY update_asm2_tests(dbo, ntestid) return ntestid
def insert_reserve_from_form(dbo, username, data): """ Inserts a movement from the workflow reserve an animal screen. Returns the new movement id """ # Validate that we have a date before doing anthing l = dbo.locale if None == utils.df_kd(data, "reservationdate", l): raise utils.ASMValidationError( i18n._("Reservations must have a valid reservation date.", l)) # Do the movement itself first move_dict = { "person": utils.df_ks(data, "person"), "animal": utils.df_ks(data, "animal"), "reservationdate": utils.df_ks(data, "reservationdate"), "adoptionno": utils.df_ks(data, "movementnumber"), "movementdate": "", "type": str(NO_MOVEMENT), "donation": utils.df_ks(data, "amount"), "returncategory": configuration.default_return_reason(dbo) } movementid = insert_movement_from_form(dbo, username, move_dict) # Then the donation if we have one donation_amount = int(utils.df_m(data, "amount", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "reservationdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "reservationdate") received = "" don_dict = { "person": utils.df_ks(data, "person"), "animal": utils.df_ks(data, "animal"), "movement": str(movementid), "type": utils.df_ks(data, "donationtype"), "payment": utils.df_ks(data, "payment"), "frequency": "0", "amount": utils.df_ks(data, "amount"), "due": due, "received": received, "giftaid": utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) # And a second donation if there is one donation_amount = int(utils.df_m(data, "amount2", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "movementdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "movementdate") received = "" don_dict = { "person": utils.df_ks(data, "person"), "animal": utils.df_ks(data, "animal"), "movement": str(movementid), "type": utils.df_ks(data, "donationtype2"), "payment": utils.df_ks(data, "payment2"), "frequency": "0", "amount": utils.df_ks(data, "amount2"), "due": due, "received": received, "giftaid": utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) return movementid
def insert_adoption_from_form(dbo, username, data, creating=[]): """ Inserts a movement from the workflow adopt an animal screen. Returns the new movement id creating is an ongoing list of animals we're already going to create adoptions for. It prevents a never ending recursive loop of animal1 being bonded to animal2 that's bonded to animal1, etc. """ l = dbo.locale # Validate that we have a movement date before doing anthing if None == utils.df_kd(data, "movementdate", l): raise utils.ASMValidationError( i18n._("Adoption movements must have a valid adoption date.", l)) # Get the animal record for this adoption a = animal.get_animal(dbo, utils.df_ki(data, "animal")) if a is None: raise utils.ASMValidationError( "Adoption POST has an invalid animal ID: %d" % utils.df_ki(data, "animal")) al.debug( "Creating adoption for %d (%s - %s)" % (a["ID"], a["SHELTERCODE"], a["ANIMALNAME"]), "movement.insert_adoption_from_form", dbo) creating.append(a["ID"]) # If the animal is bonded to other animals, we call this function # again with a copy of the data and the bonded animal substituted # so we can create their adoption records too. if a["BONDEDANIMALID"] is not None and a["BONDEDANIMALID"] != 0 and a[ "BONDEDANIMALID"] not in creating: al.debug( "Found bond to animal %d, creating adoption..." % a["BONDEDANIMALID"], "movement.insert_adoption_from_form", dbo) newdata = dict(data) newdata["animal"] = str(a["BONDEDANIMALID"]) insert_adoption_from_form(dbo, username, newdata, creating) if a["BONDEDANIMAL2ID"] is not None and a["BONDEDANIMAL2ID"] != 0 and a[ "BONDEDANIMAL2ID"] not in creating: al.debug( "Found bond to animal %d, creating adoption..." % a["BONDEDANIMAL2ID"], "movement.insert_adoption_from_form", dbo) newdata = dict(data) newdata["animal"] = str(a["BONDEDANIMAL2ID"]) insert_adoption_from_form(dbo, username, newdata, creating) cancel_reserves = configuration.cancel_reserves_on_adoption(dbo) # Prepare a dictionary of data for the movement table via insert_movement_from_form move_dict = { "person": utils.df_ks(data, "person"), "animal": utils.df_ks(data, "animal"), "adoptionno": utils.df_ks(data, "movementnumber"), "movementdate": utils.df_ks(data, "movementdate"), "type": str(ADOPTION), "donation": utils.df_ks(data, "amount"), "insurance": utils.df_ks(data, "insurance"), "returncategory": configuration.default_return_reason(dbo), "trial": utils.df_ks(data, "trial"), "trialenddate": utils.df_ks(data, "trialenddate") } # Is this animal currently on foster? If so, return the foster fm = get_animal_movements(dbo, utils.df_ki(data, "animal")) for m in fm: if m["MOVEMENTTYPE"] == FOSTER and m["RETURNDATE"] is None: return_movement(dbo, m["ID"], utils.df_ki(data, "animal"), utils.df_kd(data, "movementdate", l)) # Is this animal current at a retailer? If so, return it from the # retailer and set the originalretailermovement and retailerid fields # on our new adoption movement so it can be linked back for m in fm: if m["MOVEMENTTYPE"] == RETAILER and m["RETURNDATE"] is None: return_movement(dbo, m["ID"], utils.df_ki(data, "animal"), utils.df_kd(data, "movementdate", l)) move_dict["originalretailermovement"] = str(m["ID"]) move_dict["retailer"] = str(m["OWNERID"]) # Did we say we'd like to flag the owner as homechecked? if utils.df_kc(data, "homechecked") == 1: db.execute(dbo, "UPDATE owner SET IDCheck = 1, DateLastHomeChecked = %s WHERE ID = %d" % \ ( db.dd(i18n.now(dbo.timezone)), utils.df_ki(data, "person"))) # If the animal was flagged as not available for adoption, then it # shouldn't be since we've just adopted it. db.execute( dbo, "UPDATE animal SET IsNotAvailableForAdoption = 0 WHERE ID = %s" % utils.df_ks(data, "animal")) # Is the animal reserved to the person adopting? movementid = 0 for m in fm: if m["MOVEMENTTYPE"] == NO_MOVEMENT and m["RESERVATIONDATE"] is not None \ and m["RESERVATIONCANCELLEDDATE"] is None and m["ANIMALID"] == utils.df_ki(data, "animal") \ and m["OWNERID"] == utils.df_ki(data, "person"): # yes - update the existing movement movementid = m["ID"] move_dict["movementid"] = str(movementid) move_dict["adoptionno"] = utils.padleft(movementid, 6) move_dict["reservationdate"] = str( i18n.python2display(l, m["RESERVATIONDATE"])) move_dict["comments"] = utils.nulltostr(m["COMMENTS"]) break elif cancel_reserves and m["MOVEMENTTYPE"] == NO_MOVEMENT and m["RESERVATIONDATE"] is not None \ and m["RESERVATIONCANCELLEDDATE"] is None: # no, but it's reserved to someone else and we're cancelling # reserves on adoption db.execute(dbo, "UPDATE adoption SET ReservationCancelledDate = %s WHERE ID = %d" % \ ( utils.df_d(data, "movementdate", l), m["ID"] )) if movementid != 0: update_movement_from_form(dbo, username, move_dict) else: movementid = insert_movement_from_form(dbo, username, move_dict) # Create the donation if there is one donation_amount = int(utils.df_m(data, "amount", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "movementdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "movementdate") received = "" don_dict = { "person": utils.df_ks(data, "person"), "animal": utils.df_ks(data, "animal"), "movement": str(movementid), "type": utils.df_ks(data, "donationtype"), "payment": utils.df_ks(data, "payment"), "frequency": "0", "amount": utils.df_ks(data, "amount"), "due": due, "received": received, "giftaid": utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) # And a second donation if there is one donation_amount = int(utils.df_m(data, "amount2", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "movementdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "movementdate") received = "" don_dict = { "person": utils.df_ks(data, "person"), "animal": utils.df_ks(data, "animal"), "movement": str(movementid), "type": utils.df_ks(data, "donationtype2"), "payment": utils.df_ks(data, "payment2"), "frequency": "0", "amount": utils.df_ks(data, "amount2"), "due": due, "received": received, "giftaid": utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) # Then any boarding cost record cost_amount = int(utils.df_m(data, "costamount", l)) cost_type = utils.df_ks(data, "costtype") cost_create = utils.df_ki(data, "costcreate") if cost_amount > 0 and cost_type != "" and cost_create == 1: boc_dict = { "animalid": utils.df_ks(data, "animal"), "type": cost_type, "costdate": utils.df_ks(data, "movementdate"), "cost": utils.df_ks(data, "costamount") } animal.insert_cost_from_form(dbo, username, boc_dict) return movementid
def validate_movement_form_data(dbo, data): """ Verifies that form data is valid for a movement """ l = dbo.locale movementid = utils.df_ki(data, "movementid") movement = None if movementid != 0: movement = db.query( dbo, "SELECT * FROM adoption WHERE ID = %d" % movementid)[0] adoptionno = utils.df_ks(data, "adoptionno") movementtype = utils.df_ki(data, "type") movementdate = utils.df_kd(data, "movementdate", l) returndate = utils.df_kd(data, "returndate", l) reservationdate = utils.df_kd(data, "reservationdate", l) reservationcancelled = utils.df_kd(data, "reservationcancelled", l) personid = utils.df_ki(data, "person") animalid = utils.df_ki(data, "animal") retailerid = utils.df_ki(data, "retailer") al.debug( "validating saved movement %d for animal %d" % (movementid, animalid), "movement.validate_movement_form_data", dbo) # If we have a date but no type, get rid of it if movementdate is None and movementtype == 0: data["movementdate"] = "" al.debug("blank date and type", "movement.validate_movement_form_data", dbo) # If we've got a type, but no date, default today if movementtype > 0 and movementdate is None: movementdate = i18n.now() data["movementdate"] = i18n.python2display(l, movementdate) al.debug("type set and no date, defaulting today", "movement.validate_movement_form_data", dbo) # If we've got a reserve cancellation without a reserve, remove it if reservationdate is None and reservationcancelled is not None: data["reservationdate"] = "" al.debug("movement has no reserve or cancelled date", "movement.validate_movement_form_data", dbo) # Animals are always required if animalid == 0: al.debug("movement has no animal", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("Movements require an animal", l)) # Owners are required unless type is escaped, stolen or released if personid == 0 and movementtype != ESCAPED and movementtype != STOLEN and movementtype != RELEASED: al.debug("movement has no person and is not ESCAPED|STOLEN|RELEASED", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("A person is required for this movement type.", l)) # Is the movement number unique? if 0 != db.query_int( dbo, "SELECT COUNT(*) FROM adoption WHERE AdoptionNumber LIKE '%s' AND ID <> %d" % (adoptionno, movementid)): raise utils.ASMValidationError( i18n._("Movement numbers must be unique.", l)) # If we're updating an existing record, we only need to continue validation # if one of the important fields has changed (movement date/type, return date, reservation, animal) if movement is not None: if movementtype == movement[ "MOVEMENTTYPE"] and movementdate == movement[ "MOVEMENTDATE"] and returndate == movement[ "RETURNDATE"] and reservationdate == movement[ "RESERVATIONDATE"] and animalid == movement[ "ANIMALID"]: al.debug( "movement type, dates and animalid have not changed. Abandoning further validation", "movement.validate_movement_form_data", dbo) return # If the animal is held in case of reclaim, it can't be adopted if movementtype == ADOPTION: if 1 == db.query_int( dbo, "SELECT IsHold FROM animal WHERE ID = %d" % animalid): al.debug("movement is adoption and the animal is on hold", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("This animal is currently held and cannot be adopted.", l)) # If it's a foster movement, make sure the owner is a fosterer if movementtype == FOSTER: if 0 == db.query_int( dbo, "SELECT IsFosterer FROM owner WHERE ID = %d" % personid): al.debug("movement is a foster and the person is not a fosterer.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._( "This person is not flagged as a fosterer and cannot foster animals.", l)) # If it's a retailer movement, make sure the owner is a retailer if movementtype == RETAILER: if 0 == db.query_int( dbo, "SELECT IsRetailer FROM owner WHERE ID = %d" % personid): al.debug( "movement is a retailer and the person is not a retailer.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._( "This person is not flagged as a retailer and cannot handle retailer movements.", l)) # If a retailer is selected, make sure it's an adoption if retailerid != 0 and movementtype != ADOPTION: al.debug("movement has a retailerid set and this is not an adoption.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("From retailer is only valid on adoption movements.", l)) # If a retailer is selected, make sure there's been a retailer movement in this animal's history if retailerid != 0: if 0 == db.query_int( dbo, "SELECT COUNT(*) FROM adoption WHERE AnimalID = %d AND MovementType = %d" % (animalid, RETAILER)): al.debug( "movement has a retailerid set but has never been to a retailer.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._( "This movement cannot be from a retailer when the animal has no prior retailer movements.", l)) # You can't have a return without a movement if movementdate is None and returndate is not None: al.debug("movement is returned without a movement date.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("You can't have a return without a movement.", l)) # Return should be after or same day as movement if movementdate is not None and returndate != None and movementdate > returndate: al.debug("movement return date is before the movement date.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("Return date cannot be before the movement date.", l)) # Can't have multiple open movements if movementdate is not None: existingopen = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE MovementDate Is Not Null AND " \ "ReturnDate Is Null AND AnimalID = %d AND ID <> %d" % (animalid, movementid)) if existingopen > 0: al.debug( "movement is open and animal already has another open movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("An animal cannot have multiple open movements.", l)) # If we have a movement and return, is there another movement with a # movementdate between the movement and return date on this one? if movementdate is not None and returndate != None: clash = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE " \ "AnimalID = %d AND ID <> %d AND ((ReturnDate > %s AND ReturnDate < %s) " \ "OR (MovementDate < %s AND MovementDate > %s))" % ( animalid, movementid, db.dd(movementdate), db.dd(returndate), db.dd(returndate), db.dd(movementdate) )) if clash > 0: al.debug("movement dates overlap an existing movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("Movement dates clash with an existing movement.", l)) # Does this movement date fall within the date range of an already # returned movement for the same animal? if movementdate is not None and returndate is None: clash = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE AnimalID = %d AND ID <> %d AND " \ "MovementDate Is Not Null AND ReturnDate Is Not Null AND " \ "%s > MovementDate AND %s < ReturnDate" % ( animalid, movementid, db.dd(movementdate), db.dd(movementdate))) if clash > 0: al.debug("movement dates overlap an existing movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("Movement dates clash with an existing movement.", l)) # If there's a cancelled reservation, make sure it's after the reserve date if reservationdate is not None and reservationcancelled != None and reservationcancelled < reservationdate: al.debug("reserve date is after cancelled date.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("Reservation date cannot be after cancellation date.", l)) # If this is a new reservation, make sure there's no open movement (fosters do not count) if movementid == 0 and movementtype == 0 and movementdate is None and reservationdate is not None: om = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE AnimalID = %d AND " \ "MovementDate Is Not Null AND ReturnDate Is Null AND MovementType <> 2" % animalid) if om > 0: al.debug( "movement is a reservation but animal has active movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("Can't reserve an animal that has an active movement.", l)) # Make sure the adoption number is unique an = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE ID <> %d AND " \ "AdoptionNumber LIKE %s" % ( movementid, utils.df_t(data, "adoptionno" ))) if an > 0: al.debug("movement number is not unique.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError( i18n._("The movement number '{0}' is not unique.", l).format(utils.df_ks(data, "adoptionno"))) # If this is an adoption and the owner had some criteria, expire them if movementtype == ADOPTION and personid > 0: al.debug("movement is an adoption, expiring person criteria.", "movement.validate_movement_form_data", dbo) sql = "UPDATE owner SET MatchActive = 0, MatchExpires = %s WHERE ID = %d" % ( db.dd(i18n.now(dbo.timezone)), int(personid)) db.execute(dbo, sql) # If the option to cancel reserves on adoption is set, cancel any outstanding reserves for the animal if movementtype == ADOPTION and configuration.cancel_reserves_on_adoption( dbo): al.debug("movement is an adoption, cancelling outstanding reserves.", "movement.validate_movement_form_data", dbo) sql = "UPDATE adoption SET ReservationCancelledDate = %s " \ "WHERE ReservationCancelledDate Is Null AND MovementDate Is Null " \ "AND AnimalID = %d AND ID <> %d" % ( db.dd(i18n.now(dbo.timezone)), animalid, int(movementid) ) db.execute(dbo, sql)
def validate_movement_form_data(dbo, data): """ Verifies that form data is valid for a movement """ l = dbo.locale movementid = utils.df_ki(data, "movementid") movement = None if movementid != 0: movement = db.query(dbo, "SELECT * FROM adoption WHERE ID = %d" % movementid)[0] adoptionno = utils.df_ks(data, "adoptionno") movementtype = utils.df_ki(data, "type") movementdate = utils.df_kd(data, "movementdate", l) returndate = utils.df_kd(data, "returndate", l) reservationdate = utils.df_kd(data, "reservationdate", l) reservationcancelled = utils.df_kd(data, "reservationcancelled", l) personid = utils.df_ki(data, "person") animalid = utils.df_ki(data, "animal") retailerid = utils.df_ki(data, "retailer") al.debug("validating saved movement %d for animal %d" % (movementid, animalid), "movement.validate_movement_form_data", dbo) # If we have a date but no type, get rid of it if movementdate is None and movementtype == 0: data["movementdate"] = "" al.debug("blank date and type", "movement.validate_movement_form_data", dbo) # If we've got a type, but no date, default today if movementtype > 0 and movementdate is None: movementdate = i18n.now() data["movementdate"] = i18n.python2display(l, movementdate) al.debug("type set and no date, defaulting today", "movement.validate_movement_form_data", dbo) # If we've got a reserve cancellation without a reserve, remove it if reservationdate is None and reservationcancelled is not None: data["reservationdate"] = "" al.debug("movement has no reserve or cancelled date", "movement.validate_movement_form_data", dbo) # Animals are always required if animalid == 0: al.debug("movement has no animal", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("Movements require an animal", l)) # Owners are required unless type is escaped, stolen or released if personid == 0 and movementtype != ESCAPED and movementtype != STOLEN and movementtype != RELEASED: al.debug("movement has no person and is not ESCAPED|STOLEN|RELEASED", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("A person is required for this movement type.", l)) # Is the movement number unique? if 0 != db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE AdoptionNumber LIKE '%s' AND ID <> %d" % (adoptionno, movementid)): raise utils.ASMValidationError(i18n._("Movement numbers must be unique.", l)) # If we're updating an existing record, we only need to continue validation # if one of the important fields has changed (movement date/type, return date, reservation, animal) if movement is not None: if movementtype == movement["MOVEMENTTYPE"] and movementdate == movement["MOVEMENTDATE"] and returndate == movement["RETURNDATE"] and reservationdate == movement["RESERVATIONDATE"] and animalid == movement["ANIMALID"]: al.debug("movement type, dates and animalid have not changed. Abandoning further validation", "movement.validate_movement_form_data", dbo) return # If the animal is held in case of reclaim, it can't be adopted if movementtype == ADOPTION: if 1 == db.query_int(dbo, "SELECT IsHold FROM animal WHERE ID = %d" % animalid): al.debug("movement is adoption and the animal is on hold", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("This animal is currently held and cannot be adopted.", l)) # If it's a foster movement, make sure the owner is a fosterer if movementtype == FOSTER: if 0 == db.query_int(dbo, "SELECT IsFosterer FROM owner WHERE ID = %d" % personid): al.debug("movement is a foster and the person is not a fosterer.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("This person is not flagged as a fosterer and cannot foster animals.", l)) # If it's a retailer movement, make sure the owner is a retailer if movementtype == RETAILER: if 0 == db.query_int(dbo, "SELECT IsRetailer FROM owner WHERE ID = %d" % personid): al.debug("movement is a retailer and the person is not a retailer.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("This person is not flagged as a retailer and cannot handle retailer movements.", l)) # If a retailer is selected, make sure it's an adoption if retailerid != 0 and movementtype != ADOPTION: al.debug("movement has a retailerid set and this is not an adoption.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("From retailer is only valid on adoption movements.", l)) # If a retailer is selected, make sure there's been a retailer movement in this animal's history if retailerid != 0: if 0 == db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE AnimalID = %d AND MovementType = %d" % ( animalid, RETAILER )): al.debug("movement has a retailerid set but has never been to a retailer.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("This movement cannot be from a retailer when the animal has no prior retailer movements.", l)) # You can't have a return without a movement if movementdate is None and returndate is not None: al.debug("movement is returned without a movement date.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("You can't have a return without a movement.", l)) # Return should be after or same day as movement if movementdate is not None and returndate != None and movementdate > returndate: al.debug("movement return date is before the movement date.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("Return date cannot be before the movement date.", l)) # Can't have multiple open movements if movementdate is not None: existingopen = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE MovementDate Is Not Null AND " \ "ReturnDate Is Null AND AnimalID = %d AND ID <> %d" % (animalid, movementid)) if existingopen > 0: al.debug("movement is open and animal already has another open movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("An animal cannot have multiple open movements.", l)) # If we have a movement and return, is there another movement with a # movementdate between the movement and return date on this one? if movementdate is not None and returndate != None: clash = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE " \ "AnimalID = %d AND ID <> %d AND ((ReturnDate > %s AND ReturnDate < %s) " \ "OR (MovementDate < %s AND MovementDate > %s))" % ( animalid, movementid, db.dd(movementdate), db.dd(returndate), db.dd(returndate), db.dd(movementdate) )) if clash > 0: al.debug("movement dates overlap an existing movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("Movement dates clash with an existing movement.", l)) # Does this movement date fall within the date range of an already # returned movement for the same animal? if movementdate is not None and returndate is None: clash = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE AnimalID = %d AND ID <> %d AND " \ "MovementDate Is Not Null AND ReturnDate Is Not Null AND " \ "%s > MovementDate AND %s < ReturnDate" % ( animalid, movementid, db.dd(movementdate), db.dd(movementdate))) if clash > 0: al.debug("movement dates overlap an existing movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("Movement dates clash with an existing movement.", l)) # If there's a cancelled reservation, make sure it's after the reserve date if reservationdate is not None and reservationcancelled != None and reservationcancelled < reservationdate: al.debug("reserve date is after cancelled date.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("Reservation date cannot be after cancellation date.", l)) # If this is a new reservation, make sure there's no open movement (fosters do not count) if movementid == 0 and movementtype == 0 and movementdate is None and reservationdate is not None: om = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE AnimalID = %d AND " \ "MovementDate Is Not Null AND ReturnDate Is Null AND MovementType <> 2" % animalid) if om > 0: al.debug("movement is a reservation but animal has active movement.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("Can't reserve an animal that has an active movement.", l)) # Make sure the adoption number is unique an = db.query_int(dbo, "SELECT COUNT(*) FROM adoption WHERE ID <> %d AND " \ "AdoptionNumber LIKE %s" % ( movementid, utils.df_t(data, "adoptionno" ))) if an > 0: al.debug("movement number is not unique.", "movement.validate_movement_form_data", dbo) raise utils.ASMValidationError(i18n._("The movement number '{0}' is not unique.", l).format(utils.df_ks(data, "adoptionno"))) # If this is an adoption and the owner had some criteria, expire them if movementtype == ADOPTION and personid > 0: al.debug("movement is an adoption, expiring person criteria.", "movement.validate_movement_form_data", dbo) sql = "UPDATE owner SET MatchActive = 0, MatchExpires = %s WHERE ID = %d" % ( db.dd(i18n.now(dbo.timezone)), int(personid) ) db.execute(dbo, sql) # If the option to cancel reserves on adoption is set, cancel any outstanding reserves for the animal if movementtype == ADOPTION and configuration.cancel_reserves_on_adoption(dbo): al.debug("movement is an adoption, cancelling outstanding reserves.", "movement.validate_movement_form_data", dbo) sql = "UPDATE adoption SET ReservationCancelledDate = %s " \ "WHERE ReservationCancelledDate Is Null AND MovementDate Is Null " \ "AND AnimalID = %d AND ID <> %d" % ( db.dd(i18n.now(dbo.timezone)), animalid, int(movementid) ) db.execute(dbo, sql)
def insert_adoption_from_form(dbo, username, data, creating = []): """ Inserts a movement from the workflow adopt an animal screen. Returns the new movement id creating is an ongoing list of animals we're already going to create adoptions for. It prevents a never ending recursive loop of animal1 being bonded to animal2 that's bonded to animal1, etc. """ l = dbo.locale # Validate that we have a movement date before doing anthing if None == utils.df_kd(data, "movementdate", l): raise utils.ASMValidationError(i18n._("Adoption movements must have a valid adoption date.", l)) # Get the animal record for this adoption a = animal.get_animal(dbo, utils.df_ki(data, "animal")) if a is None: raise utils.ASMValidationError("Adoption POST has an invalid animal ID: %d" % utils.df_ki(data, "animal")) al.debug("Creating adoption for %d (%s - %s)" % (a["ID"], a["SHELTERCODE"], a["ANIMALNAME"]), "movement.insert_adoption_from_form", dbo) creating.append(a["ID"]) # If the animal is bonded to other animals, we call this function # again with a copy of the data and the bonded animal substituted # so we can create their adoption records too. if a["BONDEDANIMALID"] is not None and a["BONDEDANIMALID"] != 0 and a["BONDEDANIMALID"] not in creating: al.debug("Found bond to animal %d, creating adoption..." % a["BONDEDANIMALID"], "movement.insert_adoption_from_form", dbo) newdata = dict(data) newdata["animal"] = str(a["BONDEDANIMALID"]) insert_adoption_from_form(dbo, username, newdata, creating) if a["BONDEDANIMAL2ID"] is not None and a["BONDEDANIMAL2ID"] != 0 and a["BONDEDANIMAL2ID"] not in creating: al.debug("Found bond to animal %d, creating adoption..." % a["BONDEDANIMAL2ID"], "movement.insert_adoption_from_form", dbo) newdata = dict(data) newdata["animal"] = str(a["BONDEDANIMAL2ID"]) insert_adoption_from_form(dbo, username, newdata, creating) cancel_reserves = configuration.cancel_reserves_on_adoption(dbo) # Prepare a dictionary of data for the movement table via insert_movement_from_form move_dict = { "person" : utils.df_ks(data, "person"), "animal" : utils.df_ks(data, "animal"), "adoptionno" : utils.df_ks(data, "movementnumber"), "movementdate" : utils.df_ks(data, "movementdate"), "type" : str(ADOPTION), "donation" : utils.df_ks(data, "amount"), "insurance" : utils.df_ks(data, "insurance"), "returncategory" : configuration.default_return_reason(dbo), "trial" : utils.df_ks(data, "trial"), "trialenddate" : utils.df_ks(data, "trialenddate") } # Is this animal currently on foster? If so, return the foster fm = get_animal_movements(dbo, utils.df_ki(data, "animal")) for m in fm: if m["MOVEMENTTYPE"] == FOSTER and m["RETURNDATE"] is None: return_movement(dbo, m["ID"], utils.df_ki(data, "animal"), utils.df_kd(data, "movementdate", l)) # Is this animal current at a retailer? If so, return it from the # retailer and set the originalretailermovement and retailerid fields # on our new adoption movement so it can be linked back for m in fm: if m["MOVEMENTTYPE"] == RETAILER and m["RETURNDATE"] is None: return_movement(dbo, m["ID"], utils.df_ki(data, "animal"), utils.df_kd(data, "movementdate", l)) move_dict["originalretailermovement"] = str(m["ID"]) move_dict["retailer"] = str(m["OWNERID"]) # Did we say we'd like to flag the owner as homechecked? if utils.df_kc(data, "homechecked") == 1: db.execute(dbo, "UPDATE owner SET IDCheck = 1, DateLastHomeChecked = %s WHERE ID = %d" % \ ( db.dd(i18n.now(dbo.timezone)), utils.df_ki(data, "person"))) # If the animal was flagged as not available for adoption, then it # shouldn't be since we've just adopted it. db.execute(dbo, "UPDATE animal SET IsNotAvailableForAdoption = 0 WHERE ID = %s" % utils.df_ks(data, "animal")) # Is the animal reserved to the person adopting? movementid = 0 for m in fm: if m["MOVEMENTTYPE"] == NO_MOVEMENT and m["RESERVATIONDATE"] is not None \ and m["RESERVATIONCANCELLEDDATE"] is None and m["ANIMALID"] == utils.df_ki(data, "animal") \ and m["OWNERID"] == utils.df_ki(data, "person"): # yes - update the existing movement movementid = m["ID"] move_dict["movementid"] = str(movementid) move_dict["adoptionno"] = utils.padleft(movementid, 6) move_dict["reservationdate"] = str(i18n.python2display(l, m["RESERVATIONDATE"])) move_dict["comments"] = utils.nulltostr(m["COMMENTS"]) break elif cancel_reserves and m["MOVEMENTTYPE"] == NO_MOVEMENT and m["RESERVATIONDATE"] is not None \ and m["RESERVATIONCANCELLEDDATE"] is None: # no, but it's reserved to someone else and we're cancelling # reserves on adoption db.execute(dbo, "UPDATE adoption SET ReservationCancelledDate = %s WHERE ID = %d" % \ ( utils.df_d(data, "movementdate", l), m["ID"] )) if movementid != 0: update_movement_from_form(dbo, username, move_dict) else: movementid = insert_movement_from_form(dbo, username, move_dict) # Create the donation if there is one donation_amount = int(utils.df_m(data, "amount", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "movementdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "movementdate") received = "" don_dict = { "person" : utils.df_ks(data, "person"), "animal" : utils.df_ks(data, "animal"), "movement" : str(movementid), "type" : utils.df_ks(data, "donationtype"), "payment" : utils.df_ks(data, "payment"), "frequency" : "0", "amount" : utils.df_ks(data, "amount"), "due" : due, "received" : received, "giftaid" : utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) # And a second donation if there is one donation_amount = int(utils.df_m(data, "amount2", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "movementdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "movementdate") received = "" don_dict = { "person" : utils.df_ks(data, "person"), "animal" : utils.df_ks(data, "animal"), "movement" : str(movementid), "type" : utils.df_ks(data, "donationtype2"), "payment" : utils.df_ks(data, "payment2"), "frequency" : "0", "amount" : utils.df_ks(data, "amount2"), "due" : due, "received" : received, "giftaid" : utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) # Then any boarding cost record cost_amount = int(utils.df_m(data, "costamount", l)) cost_type = utils.df_ks(data, "costtype") cost_create = utils.df_ki(data, "costcreate") if cost_amount > 0 and cost_type != "" and cost_create == 1: boc_dict = { "animalid" : utils.df_ks(data, "animal"), "type" : cost_type, "costdate" : utils.df_ks(data, "movementdate"), "cost" : utils.df_ks(data, "costamount") } animal.insert_cost_from_form(dbo, username, boc_dict) return movementid
def insert_reserve_from_form(dbo, username, data): """ Inserts a movement from the workflow reserve an animal screen. Returns the new movement id """ # Validate that we have a date before doing anthing l = dbo.locale if None == utils.df_kd(data, "reservationdate", l): raise utils.ASMValidationError(i18n._("Reservations must have a valid reservation date.", l)) # Do the movement itself first move_dict = { "person" : utils.df_ks(data, "person"), "animal" : utils.df_ks(data, "animal"), "reservationdate" : utils.df_ks(data, "reservationdate"), "adoptionno" : utils.df_ks(data, "movementnumber"), "movementdate" : "", "type" : str(NO_MOVEMENT), "donation" : utils.df_ks(data, "amount"), "returncategory" : configuration.default_return_reason(dbo) } movementid = insert_movement_from_form(dbo, username, move_dict) # Then the donation if we have one donation_amount = int(utils.df_m(data, "amount", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "reservationdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "reservationdate") received = "" don_dict = { "person" : utils.df_ks(data, "person"), "animal" : utils.df_ks(data, "animal"), "movement" : str(movementid), "type" : utils.df_ks(data, "donationtype"), "payment" : utils.df_ks(data, "payment"), "frequency" : "0", "amount" : utils.df_ks(data, "amount"), "due" : due, "received" : received, "giftaid" : utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) # And a second donation if there is one donation_amount = int(utils.df_m(data, "amount2", l)) if donation_amount > 0: due = "" received = utils.df_ks(data, "movementdate") if configuration.movement_donations_default_due(dbo): due = utils.df_ks(data, "movementdate") received = "" don_dict = { "person" : utils.df_ks(data, "person"), "animal" : utils.df_ks(data, "animal"), "movement" : str(movementid), "type" : utils.df_ks(data, "donationtype2"), "payment" : utils.df_ks(data, "payment2"), "frequency" : "0", "amount" : utils.df_ks(data, "amount2"), "due" : due, "received" : received, "giftaid" : utils.df_ks(data, "giftaid") } financial.insert_donation_from_form(dbo, username, don_dict) return movementid