def gkd(dbo, m, f, usetoday = False): """ reads field f from map m, returning a display date. string is empty if key not present or date is invalid. If usetoday is set to True, then today's date is returned if the date is blank. """ if not m.has_key(f): return "" lv = str(m[f]) # If there's a space, then I guess we have time info - throw it away if lv.find(" ") > 0: lv = lv[0:lv.find(" ")] # Now split it by either / or - b = lv.split("/") if lv.find("-") != -1: b = lv.split("-") # We should have three date bits now if len(b) != 3: # We don't have a valid date, if use today is on return that if usetoday: return i18n.python2display(dbo.locale, i18n.now(dbo.timezone)) else: return "" else: # Which of our 3 bits is the year? if utils.cint(b[0]) > 1900: # it's Y/M/D d = datetime.datetime(utils.cint(b[0]), utils.cint(b[1]), utils.cint(b[2])) elif dbo.locale == "en": # Assume it's M/D/Y for US d = datetime.datetime(utils.cint(b[2]), utils.cint(b[0]), utils.cint(b[1])) else: # Assume it's D/M/Y d = datetime.datetime(utils.cint(b[2]), utils.cint(b[1]), utils.cint(b[0])) return i18n.python2display(dbo.locale, d)
def match_report(dbo, username = "******", lostanimalid = 0, foundanimalid = 0, animalid = 0, limit = 0): """ Generates the match report and returns it as a string """ l = dbo.locale title = _("Match lost and found animals", l) h = [] h.append(reports.get_report_header(dbo, title, username)) if limit > 0: h.append("<p>(" + _("Limited to {0} matches", l).format(limit) + ")</p>") def p(s): return "<p>%s</p>" % s def td(s): return "<td>%s</td>" % s def hr(): return "<hr />" lastid = 0 matches = match(dbo, lostanimalid, foundanimalid, animalid, limit) if len(matches) > 0: for m in matches: if lastid != m.lid: if lastid != 0: h.append("</tr></table>") h.append(hr()) h.append(p(_("{0} - {1} {2} ({3}), contact {4} ({5}) - lost in {6}, postcode {7}, on {8}", l).format( \ m.lid, "%s %s %s" % (m.lagegroup, m.lbasecolourname, m.lsexname), \ "%s/%s" % (m.lspeciesname,m.lbreedname), \ m.ldistinguishingfeatures, m.lcontactname, m.lcontactnumber, m.larealost, m.lareapostcode, python2display(l, m.ldatelost)))) h.append("<table border=\"1\" width=\"100%\"><tr>") h.append("<th>%s</th>" % _("Reference", l)) h.append("<th>%s</th>" % _("Description", l)) h.append("<th>%s</th>" % _("Area Found", l)) h.append("<th>%s</th>" % _("Area Postcode", l)) h.append("<th>%s</th>" % _("Date Found", l)) h.append("<th>%s</th>" % _("Contact", l)) h.append("<th>%s</th>" % _("Number", l)) h.append("<th>%s</th>" % _("Match", l)) h.append("</tr>") lastid = m.lid h.append("<tr>") h.append(td(str(m.fid))) h.append(td("%s %s %s %s %s" % (m.fagegroup, m.fbasecolourname, m.fsexname, m.fspeciesname, m.fbreedname))) h.append(td(m.fareafound)) h.append(td(m.fareapostcode)) h.append(td(python2display(l, m.fdatefound))) h.append(td(m.fcontactname)) h.append(td(m.fcontactnumber)) h.append(td(str(m.matchpoints) + "%")) h.append("</tr>") h.append("</tr></table>") else: h.append(p(_("No matches found.", l))) h.append(reports.get_report_footer(dbo, title, username)) return "\n".join(h)
def jqm_options_next_month(l): d = now() days = [] for dummy in xrange(0, 31): days.append(jqm_option(python2display(l, d))) d = add_days(d, 1) d = add_months(now(), 3) days.append(jqm_option(python2display(l, d))) d = add_months(now(), 6) days.append(jqm_option(python2display(l, d))) d = add_years(now(), 1) days.append(jqm_option(python2display(l, d))) return "\n".join(days)
def match_report(dbo, username = "******", lostanimalid = 0, foundanimalid = 0, animalid = 0): """ Same interface as match above, but generates the match report """ l = dbo.locale title = _("Match lost and found animals", l) h = [] h.append(reports.get_report_header(dbo, title, username)) def p(s): return "<p>%s</p>" % s def td(s): return "<td>%s</td>" % s def hr(): return "<hr />" lastid = 0 matches = match(dbo, lostanimalid, foundanimalid, animalid) if len(matches) > 0: for m in matches: if lastid != m.lid: if lastid != 0: h.append("</tr></table>") h.append(hr()) h.append(p(_("{0} - {1} {2} ({3}), contact {4} ({5}) - lost in {6}, postcode {7}, on {8}", l).format( \ m.lid, "%s %s %s" % (m.lagegroup, m.lbasecolourname, m.lsexname), \ "%s/%s" % (m.lspeciesname,m.lbreedname), \ m.ldistinguishingfeatures, m.lcontactname, m.lcontactnumber, m.larealost, m.lareapostcode, python2display(l, m.ldatelost)))) h.append("<table border=\"1\" width=\"100%\"><tr>") h.append("<th>%s</th>" % _("Reference", l)) h.append("<th>%s</th>" % _("Description", l)) h.append("<th>%s</th>" % _("Area Found", l)) h.append("<th>%s</th>" % _("Area Postcode", l)) h.append("<th>%s</th>" % _("Date Found", l)) h.append("<th>%s</th>" % _("Contact", l)) h.append("<th>%s</th>" % _("Number", l)) h.append("<th>%s</th>" % _("Match", l)) h.append("</tr>") lastid = m.lid h.append("<tr>") h.append(td(str(m.fid))) h.append(td("%s %s %s %s %s" % (m.fagegroup, m.fbasecolourname, m.fsexname, m.fspeciesname, m.fbreedname))) h.append(td(m.fareafound)) h.append(td(m.fareapostcode)) h.append(td(python2display(l, m.fdatefound))) h.append(td(m.fcontactname)) h.append(td(m.fcontactnumber)) h.append(td(str(m.matchpoints) + "%")) h.append("</tr>") h.append("</tr></table>") else: h.append(p(_("No matches found.", l))) h.append(reports.get_report_footer(dbo, title, username)) return "\n".join(h)
def insert_animalcontrol(dbo, username): """ Creates a new animal control incident record and returns the id """ l = dbo.locale d = { "incidentdate": python2display(l, now(dbo.timezone)), "incidenttime": format_time_now(dbo.timezone), "incidenttype": configuration.default_incident(dbo), "calldate": python2display(l, now(dbo.timezone)), "calltime": format_time_now(dbo.timezone), "calltaker": username } return insert_animalcontrol_from_form(dbo, utils.PostedData(d, dbo.locale), username)
def create_foundanimal(dbo, username, collationid): """ Creates a found animal record from the incoming form data with collationid. Also, attaches the form to the found animal as media. """ l = dbo.locale fields = get_onlineformincoming_detail(dbo, collationid) d = {} d["datefound"] = i18n.python2display(l, i18n.now(dbo.timezone)) d["datereported"] = i18n.python2display(l, i18n.now(dbo.timezone)) for f in fields: if f["FIELDNAME"] == "species": d["species"] = guess_species(dbo, f["VALUE"]) if f["FIELDNAME"] == "sex": d["sex"] = guess_sex(dbo, f["VALUE"]) if f["FIELDNAME"] == "breed": d["breed"] = guess_breed(dbo, f["VALUE"]) if f["FIELDNAME"] == "agegroup": d["agegroup"] = guess_agegroup(dbo, f["VALUE"]) if f["FIELDNAME"] == "color": d["colour"] = guess_colour(dbo, f["VALUE"]) if f["FIELDNAME"] == "colour": d["colour"] = guess_colour(dbo, f["VALUE"]) if f["FIELDNAME"] == "description": d["markings"] = f["VALUE"] if f["FIELDNAME"] == "areafound": d["areafound"] = f["VALUE"] if f["FIELDNAME"] == "areapostcode": d["areapostcode"] = f["VALUE"] if f["FIELDNAME"] == "areazipcode": d["areazipcode"] = f["VALUE"] if not d.has_key("species"): d["species"] = guess_species(dbo, "") if not d.has_key("sex"): d["sex"] = guess_sex(dbo, "") if not d.has_key("breed"): d["breed"] = guess_breed(dbo, "") if not d.has_key("agegroup"): d["agegroup"] = guess_agegroup(dbo, "") if not d.has_key("colour"): d["colour"] = guess_colour(dbo, "") # Have we got enough info to create the found animal record? We need a description and areafound if not d.has_key("markings") or not d.has_key("areafound"): raise utils.ASMValidationError( i18n._( "There is not enough information in the form to create a found animal record (need a description and area found).", l)) # We need the person record before we create the found animal collationid, personid, personname = create_person(dbo, username, collationid) d["owner"] = personid # Create the found animal foundanimalid = lostfound.insert_foundanimal_from_form(dbo, d, username) # Attach the form to the found animal formname = get_onlineformincoming_name(dbo, collationid) formhtml = get_onlineformincoming_html(dbo, collationid) media.create_document_media(dbo, username, media.FOUNDANIMAL, foundanimalid, formname, formhtml) return (collationid, foundanimalid, utils.padleft(foundanimalid, 6) + " - " + personname)
def insert_animalcontrol(dbo, username): """ Creates a new animal control incident record and returns the id """ l = dbo.locale d = { "incidentdate": python2display(l, dbo.now()), "incidenttime": format_time_now(dbo.timezone), "incidenttype": configuration.default_incident(dbo), "calldate": python2display(l, dbo.now()), "calltime": format_time_now(dbo.timezone), "calltaker": username } return insert_animalcontrol_from_form(dbo, utils.PostedData(d, dbo.locale), username)
def insert_reserve_for_animal_name(dbo, username, personid, animalname): """ Creates a reservation for the animal with animalname to personid. animalname can either be just the name of a shelter animal, or it can be in the form name::code. If a code is present, that will be used to locate the animal. If the person is banned from adopting animals, an exception is raised. """ l = dbo.locale if animalname.find("::") != -1: animalcode = animalname.split("::")[1] aid = dbo.query_int("SELECT ID FROM animal WHERE ShelterCode = ? ORDER BY ID DESC", [animalcode]) else: aid = dbo.query_int("SELECT ID FROM animal WHERE LOWER(AnimalName) LIKE ? ORDER BY ID DESC", [animalname.lower()]) if 1 == dbo.query_int("SELECT IsBanned FROM owner WHERE ID=?", [personid]): raise utils.ASMValidationError("owner %s is banned from adopting animals - not creating reserve") if aid == 0: raise utils.ASMValidationError("could not find an animal for '%s' - not creating reserve" % animalname) move_dict = { "person" : str(personid), "animal" : str(aid), "reservationdate" : i18n.python2display(l, dbo.today()), "reservationstatus" : configuration.default_reservation_status(dbo), "movementdate" : "", "type" : str(NO_MOVEMENT), "returncategory" : configuration.default_return_reason(dbo) } return insert_movement_from_form(dbo, username, utils.PostedData(move_dict, l))
def save_values_for_link(dbo, post, 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 post.has_key(key): val = post[key] if f["FIELDTYPE"] == YESNO: val = str(post.boolean(key)) elif f["FIELDTYPE"] == MONEY: val = str(post.integer(key)) elif f["FIELDTYPE"] == DATE: if len(val.strip()) > 0 and post.date(key) == None: raise utils.ASMValidationError( _( "Additional date field '{0}' contains an invalid date.", l).format(f["FIELDNAME"])) val = python2display(dbo.locale, post.date(key)) 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_reserve_for_animal_name(dbo, username, personid, animalname): """ Creates a reservation for the animal with animalname to personid. animalname can either be just the name of a shelter animal, or it can be in the form name::code. If a code is present, that will be used to locate the animal. """ l = dbo.locale if animalname.find("::") != -1: animalcode = animalname.split("::")[1] aid = db.query_int(dbo, "SELECT ID FROM animal WHERE ShelterCode = %s ORDER BY ID DESC" % db.ds(animalcode)) else: aid = db.query_int(dbo, "SELECT ID FROM animal WHERE LOWER(AnimalName) LIKE '%s' ORDER BY ID DESC" % animalname.lower()) # Bail out if we couldn't find a matching animal if aid == 0: return move_dict = { "person" : str(personid), "animal" : str(aid), "reservationdate" : i18n.python2display(l, i18n.now(dbo.timezone)), "reservationstatus" : configuration.default_reservation_status(dbo), "movementdate" : "", "type" : str(NO_MOVEMENT), "returncategory" : configuration.default_return_reason(dbo) } return insert_movement_from_form(dbo, username, utils.PostedData(move_dict, l))
def csv(l, rows, cols = None, includeheader = True): """ Creates a CSV file from a set of resultset rows. If cols has been supplied as a list of strings, fields will be output in that order. """ if rows is None or len(rows) == 0: return "" strio = StringIO() out = UnicodeCSVWriter(strio) if cols is None: cols = [] for k, v in rows[0].iteritems(): cols.append(k) cols = sorted(cols) if includeheader: out.writerow(cols) for r in rows: rd = [] for c in cols: if is_currency(c): rd.append(decode_html(format_currency(l, r[c]))) elif type(r[c]) == datetime.datetime: rd.append(decode_html(python2display(l, r[c]))) else: rd.append(decode_html(r[c])) out.writerow(rd) return strio.getvalue()
def create_animal_from_found(dbo, username, aid): """ Creates an animal record from a found animal with the id given """ a = db.query(dbo, "SELECT * FROM animalfound WHERE ID = %d" % int(aid))[0] l = dbo.locale data = { "animalname": _("Found Animal {0}", l).format(aid), "markings": str(a["DISTFEAT"]), "species": str(a["ANIMALTYPEID"]), "comments": str(a["COMMENTS"]), "broughtinby": str(a["OWNERID"]), "originalowner": str(a["OWNERID"]), "animaltype": configuration.default_type(dbo), "breed1": a["BREEDID"], "breed2": a["BREEDID"], "basecolour": str(a["BASECOLOURID"]), "size": configuration.default_size(dbo), "internallocation": configuration.default_location(dbo), "dateofbirth": python2display(l, subtract_years(now(dbo.timezone))), "estimateddob": "1", } # If we're creating shelter codes manually, we need to put something unique # in there for now. Use the id if configuration.manual_codes(dbo): data["sheltercode"] = "FA" + str(aid) data["shortcode"] = "FA" + str(aid) nextid, code = animal.insert_animal_from_form(dbo, data, username) return nextid
def create_waitinglist(dbo, username, collationid): """ Creates a waitinglist record from the incoming form data with collationid. Also, attaches the form to the waiting list as media. """ l = dbo.locale fields = get_onlineformincoming_detail(dbo, collationid) d = {} d["dateputon"] = i18n.python2display(l, i18n.now(dbo.timezone)) d["urgency"] = "5" for f in fields: if f["FIELDNAME"] == "species": d["species"] = guess_species(dbo, f["VALUE"]) if f["FIELDNAME"] == "description": d["description"] = f["VALUE"] if f["FIELDNAME"] == "reason": d["reasonforwantingtopart"] = f["VALUE"] if not d.has_key("species"): d["species"] = guess_species(dbo, "") # Have we got enough info to create the waiting list record? We need a description if not d.has_key("description"): raise utils.ASMValidationError( i18n._( "There is not enough information in the form to create a waiting list record (need a description).", l)) # We need the person record before we create the waiting list collationid, personid, personname = create_person(dbo, username, collationid) d["owner"] = personid # Create the waiting list wlid = waitinglist.insert_waitinglist_from_form(dbo, d, username) # Attach the form to the waiting list formname = get_onlineformincoming_name(dbo, collationid) formhtml = get_onlineformincoming_html(dbo, collationid) media.create_document_media(dbo, username, media.WAITINGLIST, wlid, formname, formhtml) return (collationid, wlid, utils.padleft(wlid, 6) + " - " + personname)
def create_animal_from_found(dbo, username, aid): """ Creates an animal record from a found animal with the id given """ a = dbo.first_row( dbo.query("SELECT * FROM animalfound WHERE ID = %d" % int(aid)) ) l = dbo.locale data = { "animalname": _("Found Animal {0}", l).format(aid), "markings": str(a["DISTFEAT"]), "species": str(a["ANIMALTYPEID"]), "comments": str(a["COMMENTS"]), "broughtinby": str(a["OWNERID"]), "originalowner": str(a["OWNERID"]), "animaltype": configuration.default_type(dbo), "breed1": a["BREEDID"], "breed2": a["BREEDID"], "basecolour": str(a["BASECOLOURID"]), "size": configuration.default_size(dbo), "internallocation": configuration.default_location(dbo), "dateofbirth": python2display(l, subtract_years(now(dbo.timezone))), "estimateddob": "1", } # If we're creating shelter codes manually, we need to put something unique # in there for now. Use the id if configuration.manual_codes(dbo): data["sheltercode"] = "FA" + str(aid) data["shortcode"] = "FA" + str(aid) nextid, code = animal.insert_animal_from_form(dbo, utils.PostedData(data, l), username) return nextid
def create_waitinglist(dbo, username, collationid): """ Creates a waitinglist record from the incoming form data with collationid. Also, attaches the form to the waiting list as media. """ l = dbo.locale fields = get_onlineformincoming_detail(dbo, collationid) d = {} d["dateputon"] = i18n.python2display(l, i18n.now(dbo.timezone)) d["urgency"] = "5" for f in fields: if f["FIELDNAME"] == "species": d["species"] = guess_species(dbo, f["VALUE"]) if f["FIELDNAME"] == "description": d["description"] = f["VALUE"] if f["FIELDNAME"] == "reason": d["reasonforwantingtopart"] = f["VALUE"] if not d.has_key("species"): d["species"] = guess_species(dbo, "") # Have we got enough info to create the waiting list record? We need a description if not d.has_key("description"): raise utils.ASMValidationError(i18n._("There is not enough information in the form to create a waiting list record (need a description).", l)) # We need the person record before we create the waiting list collationid, personid, personname = create_person(dbo, username, collationid) d["owner"] = personid # Create the waiting list wlid = waitinglist.insert_waitinglist_from_form(dbo, d, username) # Attach the form to the waiting list formname = get_onlineformincoming_name(dbo, collationid) formhtml = get_onlineformincoming_html(dbo, collationid) media.create_document_media(dbo, username, media.WAITINGLIST, wlid, formname, formhtml ) return (collationid, wlid, utils.padleft(wlid, 6) + " - " + personname)
def save_values_for_link(dbo, post, 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 post.has_key(key): val = post[key] if f["FIELDTYPE"] == YESNO: val = str(post.boolean(key)) elif f["FIELDTYPE"] == MONEY: val = str(post.integer(key)) elif f["FIELDTYPE"] == DATE: if len(val.strip()) > 0 and post.date(key) == None: raise utils.ASMValidationError(_("Additional date field '{0}' contains an invalid date.", l).format(f["FIELDNAME"])) val = python2display(dbo.locale, post.date(key)) 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_payment_from_appointment(dbo, username, appointmentid, post): """ Creates a payment record from an appointment via the create payment dialog. """ l = dbo.locale c = get_appointment(dbo, appointmentid) d = { "person": str(c.OwnerID), "animal": str(c.AnimalID), "type": post["paymenttype"], "payment": post["paymentmethod"], "amount": str(c.Amount), "due": post["due"], "received": post["received"], "vat": utils.iif(c.IsVAT == 1, "on", ""), "vatrate": str(c.VATRate), "vatamount": str(c.VATAmount), "comments": i18n._("Appointment {0}. {1} on {2} for {3}").format( utils.padleft(c.ID, 6), c.OWNERNAME, i18n.python2display(l, c.DATETIME), c.ANIMALNAME) } return financial.insert_donation_from_form(dbo, username, utils.PostedData(d, l))
def create_animalcontrol(dbo, username, collationid): """ Creates a animal control/incident record from the incoming form data with collationid. Also, attaches the form to the incident as media. """ l = dbo.locale fields = get_onlineformincoming_detail(dbo, collationid) d = {} d["incidentdate"] = i18n.python2display(l, i18n.now(dbo.timezone)) d["incidenttime"] = i18n.format_time_now(dbo.timezone) d["calldate"] = d["incidentdate"] d["calltime"] = d["incidenttime"] d["incidenttype"] = 1 for f in fields: if f["FIELDNAME"] == "callnotes": d["callnotes"] = f["VALUE"] if f["FIELDNAME"] == "dispatchaddress": d["dispatchaddress"] = f["VALUE"] if f["FIELDNAME"] == "dispatchcity": d["dispatchtown"] = f["VALUE"] if f["FIELDNAME"] == "dispatchstate": d["dispatchcounty"] = f["VALUE"] if f["FIELDNAME"] == "dispatchzipcode": d["dispatchpostcode"] = f["VALUE"] # Have we got enough info to create the animal control record? We need notes and dispatchaddress if not d.has_key("callnotes") or not d.has_key("dispatchaddress"): raise utils.ASMValidationError(i18n._("There is not enough information in the form to create an incident record (need call notes and dispatch address).", l)) # We need the person/caller record before we create the incident collationid, personid, personname = create_person(dbo, username, collationid) d["caller"] = personid # Create the incident incidentid = animalcontrol.insert_animalcontrol_from_form(dbo, utils.PostedData(d, dbo.locale), username) # Attach the form to the incident formname = get_onlineformincoming_name(dbo, collationid) formhtml = get_onlineformincoming_html(dbo, collationid) media.create_document_media(dbo, username, media.ANIMALCONTROL, incidentid, formname, formhtml ) return (collationid, incidentid, utils.padleft(incidentid, 6) + " - " + personname)
def email_uncompleted_upto_today(dbo): """ Goes through all system users and emails them their diary for the day - unless the option is turned off. """ if not configuration.email_diary_notes(dbo): return l = dbo.locale try: allusers = users.get_users(dbo) except Exception as err: al.error("failed getting list of users: %s" % str(err), "diary.email_uncompleted_upto_today", dbo) # Grab list of diary notes for today notes = get_uncompleted_upto_today(dbo) # If we don't have any, bail out if len(notes) == 0: return # Go through all user to see if we have relevant notes for them for u in allusers: if u.emailaddress and u.emailaddress.strip() != "": s = "" totalforuser = 0 for n in notes: # Is this note relevant for this user? if (n.diaryforname == "*") \ or (n.diaryforname == u.username) \ or (u.roles.find(n.diaryforname) != -1): s += i18n.python2display(l, n.diarydatetime) + " " s += n.subject if n.linkinfo is not None and n.linkinfo != "": s += " / " + n.linkinfo s += "\n" + n.note + "\n\n" totalforuser += 1 if totalforuser > 0: al.debug( "got %d notes for user %s" % (totalforuser, u.username), "diary.email_uncompleted_upto_today", dbo) utils.send_email(dbo, configuration.email(dbo), u.emailaddress, "", "", i18n._("Diary notes for: {0}", l).format( i18n.python2display(l, dbo.now())), s, exceptions=False)
def gkd(dbo, m, f, usetoday=False): """ reads field f from map m, returning a display date. string is empty if key not present or date is invalid. If usetoday is set to True, then today's date is returned if the date is blank. """ if f not in m: return "" lv = str(m[f]) # If there's a space, then I guess we have time info - throw it away if lv.find(" ") > 0: lv = lv[0:lv.find(" ")] # Now split it by either / or - b = lv.split("/") if lv.find("-") != -1: b = lv.split("-") # We should have three date bits now if len(b) != 3: # We don't have a valid date, if use today is on return that if usetoday: return i18n.python2display(dbo.locale, i18n.now(dbo.timezone)) else: return "" else: try: # Which of our 3 bits is the year? if utils.cint(b[0]) > 1900: # it's Y/M/D d = datetime.datetime(utils.cint(b[0]), utils.cint(b[1]), utils.cint(b[2])) elif dbo.locale == "en": # Assume it's M/D/Y for US d = datetime.datetime(utils.cint(b[2]), utils.cint(b[0]), utils.cint(b[1])) else: # Assume it's D/M/Y d = datetime.datetime(utils.cint(b[2]), utils.cint(b[1]), utils.cint(b[0])) return i18n.python2display(dbo.locale, d) except: # We've got an invalid date - return today if usetoday: return i18n.python2display(dbo.locale, i18n.now(dbo.timezone)) else: return ""
def update_waitinglist_remove(dbo, username, wid): """ Marks a waiting list record as removed """ db.execute( dbo, "UPDATE animalwaitinglist SET DateRemovedFromList = %s WHERE ID = %d" % (db.dd(now(dbo.timezone)), int(wid))) audit.edit( dbo, username, "animalwaitinglist", "%s: DateRemovedFromList ==> %s" % (str(wid), python2display(dbo.locale, now(dbo.timezone))))
def get_stock_items(dbo): """ Returns a set of stock items. """ rows = db.query(dbo, "SELECT sv.*, sl.LocationName " \ "FROM stocklevel sv " \ "INNER JOIN stocklocation sl ON sl.ID = sv.StockLocationID " \ "WHERE sv.Balance > 0 " \ "ORDER BY sv.StockLocationID, sv.Name") for r in rows: r["ITEMNAME"] = "%s - %s %s %s (%g/%g)" % (r["LOCATIONNAME"], r["NAME"], r["BATCHNUMBER"], python2display(dbo.locale, r["EXPIRY"]), r["BALANCE"], r["TOTAL"]) return rows
def donation_tags(dbo, p): """ Generates a list of tags from a donation result. """ l = dbo.locale tags = { "DONATIONID" : str(p["ID"]), "RECEIPTNUM" : utils.padleft(p["ID"], 8), "DONATIONTYPE" : p["DONATIONNAME"], "DONATIONDATE" : python2display(l, p["DATE"]), "DONATIONDATEDUE" : python2display(l, p["DATEDUE"]), "DONATIONAMOUNT" : format_currency_no_symbol(l, p["DONATION"]), "DONATIONCOMMENTS" : p["COMMENTS"], "DONATIONGIFTAID" : p["ISGIFTAIDNAME"], "DONATIONCREATEDBY" : p["CREATEDBY"], "DONATIONCREATEDBYNAME" : p["CREATEDBY"], "DONATIONCREATEDDATE" : python2display(l, p["CREATEDDATE"]), "DONATIONLASTCHANGEDBY" : p["LASTCHANGEDBY"], "DONATIONLASTCHANGEDBYNAME" : p["LASTCHANGEDBY"], "DONATIONLASTCHANGEDDATE" : python2display(l, p["LASTCHANGEDDATE"]) } return tags
def create_foundanimal(dbo, username, collationid): """ Creates a found animal record from the incoming form data with collationid. Also, attaches the form to the found animal as media. """ l = dbo.locale fields = get_onlineformincoming_detail(dbo, collationid) d = {} d["datefound"] = i18n.python2display(l, i18n.now(dbo.timezone)) d["datereported"] = i18n.python2display(l, i18n.now(dbo.timezone)) for f in fields: if f["FIELDNAME"] == "species": d["species"] = guess_species(dbo, f["VALUE"]) if f["FIELDNAME"] == "sex": d["sex"] = guess_sex(dbo, f["VALUE"]) if f["FIELDNAME"] == "breed": d["breed"] = guess_breed(dbo, f["VALUE"]) if f["FIELDNAME"] == "agegroup": d["agegroup"] = guess_agegroup(dbo, f["VALUE"]) if f["FIELDNAME"] == "color": d["colour"] = guess_colour(dbo, f["VALUE"]) if f["FIELDNAME"] == "colour": d["colour"] = guess_colour(dbo, f["VALUE"]) if f["FIELDNAME"] == "description": d["markings"] = f["VALUE"] if f["FIELDNAME"] == "areafound": d["areafound"] = f["VALUE"] if f["FIELDNAME"] == "areapostcode": d["areapostcode"] = f["VALUE"] if f["FIELDNAME"] == "areazipcode": d["areazipcode"] = f["VALUE"] if not d.has_key("species"): d["species"] = guess_species(dbo, "") if not d.has_key("sex"): d["sex"] = guess_sex(dbo, "") if not d.has_key("breed"): d["breed"] = guess_breed(dbo, "") if not d.has_key("agegroup"): d["agegroup"] = guess_agegroup(dbo, "") if not d.has_key("colour"): d["colour"] = guess_colour(dbo, "") # Have we got enough info to create the found animal record? We need a description and areafound if not d.has_key("markings") or not d.has_key("areafound"): raise utils.ASMValidationError(i18n._("There is not enough information in the form to create a found animal record (need a description and area found).", l)) # We need the person record before we create the found animal collationid, personid, personname = create_person(dbo, username, collationid) d["owner"] = personid # Create the found animal foundanimalid = lostfound.insert_foundanimal_from_form(dbo, d, username) # Attach the form to the found animal formname = get_onlineformincoming_name(dbo, collationid) formhtml = get_onlineformincoming_html(dbo, collationid) media.create_document_media(dbo, username, media.FOUNDANIMAL, foundanimalid, formname, formhtml ) return (collationid, foundanimalid, utils.padleft(foundanimalid, 6) + " - " + personname)
def get_stock_items(dbo): """ Returns a set of stock items. """ rows = dbo.query("SELECT sv.*, sl.LocationName " \ "FROM stocklevel sv " \ "INNER JOIN stocklocation sl ON sl.ID = sv.StockLocationID " \ "WHERE sv.Balance > 0 " \ "ORDER BY sv.StockLocationID, sv.Name") for r in rows: r.ITEMNAME = "%s - %s %s %s (%g/%g)" % ( r.LOCATIONNAME, r.NAME, r.BATCHNUMBER, python2display(dbo.locale, r.EXPIRY), r.BALANCE, r.TOTAL) return rows
def page_messages(l, homelink, mess): h = [] h.append(jqm_page_header("messages", _("Messages", l), homelink)) h.append(jqm_list(jqm_link("#addmessage", _("Add Message", l), "message_new"))) hm = [] for m in mess: icon = "info" if m["PRIORITY"] == 1: icon = "alert" inner = jqm_h3(python2display(l, m["ADDED"]) + " " + m["CREATEDBY"]) inner += jqm_p(m["MESSAGE"]) hm.append(jqm_collapsible(inner, icon)) h.append(jqm_collapsible_set("\n".join(hm))) h.append(jqm_page_footer()) return h
def page_messages(l, homelink, mess): h = [] h.append(jqm_page_header("messages", _("Messages", l), homelink)) h.append(jqm_button("#addmessage", _("Add Message", l), "plus")) hm = [] for m in mess: icon = "info" if m["PRIORITY"] == 1: icon = "alert" inner = jqm_h3(python2display(l, m["ADDED"]) + " " + m["CREATEDBY"]) inner += jqm_p(m["MESSAGE"]) hm.append(jqm_collapsible(inner, icon)) h.append(jqm_collapsible_set("\n".join(hm))) h.append(jqm_page_footer()) return h
def page_tests(l, homelink, test, testresults): h = [] h.append(jqm_page_header("test", _("Test", l), homelink)) group = "" tlist = [] tforms = [] for t in test: required = python2display(l, t["DATEREQUIRED"]) if group != required: group = required tlist.append(jqm_list_divider(group)) pageid = "t" + str(t["ID"]) tlist.append( jqm_listitem_link( "#" + pageid, "%s - %s (%s)" % (t["ANIMALNAME"], t["SHELTERCODE"], t["TESTNAME"]), "vaccination", -1, "dialog", ) ) tforms.append(jqm_page_header(pageid, t["TESTNAME"], homelink)) tforms.append(jqm_table()) tforms.append( jqm_tablerow( _("Animal", l), jqm_link("mobile_post?posttype=va&id=%d" % t["ANIMALID"], t["SHELTERCODE"] + " " + t["ANIMALNAME"]), ) ) tforms.append(jqm_tablerow(_("Test", l), required + " " + t["TESTNAME"])) tforms.append(jqm_tablerow(_("Comments", l), t["COMMENTS"])) tforms.append(jqm_table_end()) tforms.append( jqm_p( _("Result", l) + ": " + '<select class="testresult" data="%s" data-animal="%s">' % (str(t["ID"]), t["ANIMALID"]) + "<option value=" "></option>" + jqm_options_testresults(testresults) + "</select>" ) ) tforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(tlist), True)) h.append(jqm_page_footer()) h.append("\n".join(tforms)) return h
def page_medication(l, homelink, med): h = [] h.append(jqm_page_header("med", _("Medicate", l), homelink)) group = "" mlist = [] mforms = [] for m in med: required = python2display(l, m["DATEREQUIRED"]) if group != required: group = required mlist.append(jqm_list_divider(group)) pageid = "m" + str(m["TREATMENTID"]) mlist.append( jqm_listitem_link( "#" + pageid, "%s - %s (%s)" % (m["ANIMALNAME"], m["SHELTERCODE"], m["TREATMENTNAME"]), "medical", -1, "dialog", ) ) mforms.append(jqm_page_header(pageid, m["TREATMENTNAME"], homelink)) mforms.append(jqm_table()) mforms.append( jqm_tablerow( _("Animal", l), jqm_link("mobile_post?posttype=va&id=%d" % m["ANIMALID"], m["SHELTERCODE"] + " " + m["ANIMALNAME"]), ) ) mforms.append(jqm_tablerow(_("Treatment", l), "%s %s<br />%s" % (required, m["TREATMENTNAME"], m["DOSAGE"]))) mforms.append(jqm_tablerow(_("Comments", l), m["COMMENTS"])) mforms.append(jqm_table_end()) mforms.append( jqm_button( "mobile_post?posttype=med&id=%s&animalid=%s&medicalid=%s" % (str(m["TREATMENTID"]), str(m["ANIMALID"]), str(m["REGIMENID"])), _("Medicate", l), "check", ) ) mforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(mlist), True)) h.append(jqm_page_footer()) h.append("\n".join(mforms)) return h
def writeJavaScript(self, animals): # Remove original owner and other sensitive info from javascript database # before saving it for a in animals: for k in a.iterkeys(): if k.startswith("ORIGINALOWNER") or k.startswith("BROUGHTINBY") \ or k.startswith("RESERVEDOWNER") or k.startswith("CURRENTOWNER") \ or k == "DISPLAYLOCATION": a[k] = "" self.saveFile( os.path.join(self.publishDir, "db.js"), "publishDate='%s';animals=%s;" % (i18n.python2display(self.locale, i18n.now( self.dbo.timezone)), utils.json(animals))) if self.pc.uploadDirectly: self.log("Uploading javascript database...") self.upload("db.js") self.log("Uploaded javascript database.")
def page_vaccinations(l, homelink, vacc): h = [] h.append(jqm_page_header("vacc", _("Vaccinate", l), homelink)) group = "" vlist = [] vforms = [] for v in vacc: required = python2display(l, v["DATEREQUIRED"]) if group != required: group = required vlist.append(jqm_list_divider(group)) pageid = "v" + str(v["ID"]) vlist.append( jqm_listitem_link( "#" + pageid, "%s - %s (%s)" % (v["ANIMALNAME"], v["SHELTERCODE"], v["VACCINATIONTYPE"]), "vaccination", -1, "dialog", ) ) vforms.append(jqm_page_header(pageid, v["VACCINATIONTYPE"], homelink)) vforms.append(jqm_table()) vforms.append( jqm_tablerow( _("Animal", l), jqm_link("mobile_post?posttype=va&id=%d" % v["ANIMALID"], v["SHELTERCODE"] + " " + v["ANIMALNAME"]), ) ) vforms.append(jqm_tablerow(_("Vaccination", l), required + " " + v["VACCINATIONTYPE"])) vforms.append(jqm_tablerow(_("Comments", l), v["COMMENTS"])) vforms.append(jqm_table_end()) vforms.append( jqm_button( "mobile_post?posttype=vacc&id=%s&animalid=%s" % (str(v["ID"]), str(v["ANIMALID"])), _("Vaccinate", l), "check", ) ) vforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(vlist), True)) h.append(jqm_page_footer()) h.append("\n".join(vforms)) return h
def create_waitinglist_from_found(dbo, username, aid): """ Creates a waiting list entry from a found animal with the id given """ a = db.query(dbo, "SELECT * FROM animalfound WHERE ID = %d" % int(aid))[0] l = dbo.locale data = { "dateputon": python2display(l, now(dbo.timezone)), "description": str(a["DISTFEAT"]), "species": str(a["ANIMALTYPEID"]), "comments": str(a["COMMENTS"]), "owner": str(a["OWNERID"]), "breed1": a["BREEDID"], "breed2": a["BREEDID"], "basecolour": str(a["BASECOLOURID"]), "urgency": str(configuration.waiting_list_default_urgency(dbo)) } nextid = waitinglist.insert_waitinglist_from_form(dbo, data, username) return nextid
def reregistrationPDF(self, fields, sig, realname, orgname, orgaddress, orgtown, orgcounty, orgpostcode): """ Generates a reregistration PDF document containing the authorised user's electronic signature. """ gender = fields["petgender"] if gender == "M": gender = "Male" elif gender == "F": gender = "Female" h = "<p align=\"right\"><b>%s</b><br />%s<br />%s, %s<br />%s</p>" % ( orgname, orgaddress, orgtown, orgcounty, orgpostcode) h += "<h2>Change of Registered Owner/Keeper</h2>" h += "<table border=\"1\">" h += "<tr><td>Chip:</td><td><b>%s</b></td></tr>" % fields["microchip"] h += "<tr><td>Implanted:</td><td>%s</td></tr>" % fields["implantdate"] h += "<tr><td>Animal:</td><td>%s</td></tr>" % fields["petname"] h += "<tr><td>DOB:</td><td>%s</td></tr>" % fields["petdob"] h += "<tr><td>Type:</td><td>%s %s %s</td></tr>" % ( gender, fields["petbreed"], fields["petspecies"]) h += "<tr><td>Colour:</td><td>%s</td></tr>" % fields["petcolour"] h += "<tr><td>Neutered:</td><td>%s</td></tr>" % fields["petneutered"] h += "<tr><td>New Owner:</td><td>%s %s %s</td></tr>" % ( fields["prefix"], fields["firstname"], fields["surname"]) h += "<tr><td>Address:</td><td>%s<br/>%s<br/>%s %s</td></tr>" % ( fields["address1"], fields["city"], fields["county"], fields["postcode"]) h += "<tr><td>Telephone:</td><td>H: %s<br/>W: %s<br/>M: %s</td></tr>" % ( fields["telhome"], fields["telwork"], fields["telmobile"]) h += "<tr><td>Email:</td><td>%s</td></tr>" % fields["email"] h += "</table>" h += "<p>I/We confirm that every effort has been made to reunite the animal with its owner/keeper, or that the previous " \ "owner has relinquished ownership/keepership.</p>\n" h += "<p>If the animal was a stray then the animal has been in our care for the minimum required time period before " \ "rehoming took place.</p>\n" h += "<p>Authorised Signature: <br /><img src=\"%s\" /><br />%s</p>\n" % ( sig, realname) h += "<p>Date: %s</p>\n" % i18n.python2display( self.dbo.locale, i18n.now(self.dbo.timezone)) h += "<p>Authorisation: I understand that the information I have given on this form will be retained by PETtrac and " \ "hereby agree that it may be disclosed to any person or persons who may be involved in securing the welfare of the " \ "pet above. PETtrac reserves the right to amend any microchip record in the event that we are subsequently " \ "provided with additional information.</p>\n" return utils.html_to_pdf(h)
def create_waitinglist_from_found(dbo, username, aid): """ Creates a waiting list entry from a found animal with the id given """ a = dbo.first_row( dbo.query("SELECT * FROM animalfound WHERE ID = %d" % int(aid)) ) l = dbo.locale data = { "dateputon": python2display(l, now(dbo.timezone)), "description": str(a["DISTFEAT"]), "species": str(a["ANIMALTYPEID"]), "comments": str(a["COMMENTS"]), "owner": str(a["OWNERID"]), "breed1": a["BREEDID"], "breed2": a["BREEDID"], "basecolour": str(a["BASECOLOURID"]), "urgency": str(configuration.waiting_list_default_urgency(dbo)) } nextid = waitinglist.insert_waitinglist_from_form(dbo, utils.PostedData(data, dbo.locale), username) return nextid
def insert_reserve_for_animal_name(dbo, username, personid, animalname): """ Creates a reservation for the animal with animalname to personid """ l = dbo.locale aid = db.query_int( dbo, "SELECT ID FROM animal WHERE LOWER(AnimalName) LIKE '%s' ORDER BY ID DESC" % animalname.lower()) # Bail out if an invalid animal name was given - we can't create the reservation if aid == 0: return move_dict = { "person": str(personid), "animal": str(aid), "reservationdate": i18n.python2display(l, i18n.now(dbo.timezone)), "movementdate": "", "type": str(NO_MOVEMENT), "returncategory": configuration.default_return_reason(dbo) } return insert_movement_from_form(dbo, username, utils.PostedData(move_dict, l))
def org_tags(dbo, username): """ Generates a list of tags from the organisation and user info """ u = users.get_users(dbo, username) realname = "" email = "" if len(u) > 0: u = u[0] realname = u["REALNAME"] email = u["EMAILADDRESS"] tags = { "ORGANISATION" : configuration.organisation(dbo), "ORGANISATIONADDRESS" : configuration.organisation_address(dbo), "ORGANISATIONTELEPHONE" : configuration.organisation_telephone(dbo), "DATE" : python2display(dbo.locale, now(dbo.timezone)), "USERNAME" : username, "USERREALNAME" : realname, "USEREMAILADDRESS" : email } return tags
def page_tests(l, homelink, test, testresults): h = [] h.append(jqm_page_header("test", _("Test", l), homelink)) group = "" tlist = [] tforms = [] for t in test: required = python2display(l, t["DATEREQUIRED"]) if group != required: group = required tlist.append(jqm_list_divider(group)) pageid = "t" + str(t["ID"]) tlist.append( jqm_listitem_link( "#" + pageid, "%s - %s (%s)" % (t["ANIMALNAME"], t["SHELTERCODE"], t["TESTNAME"]), "vaccination", -1, "dialog")) tforms.append(jqm_page_header(pageid, t["TESTNAME"], homelink)) tforms.append(jqm_table()) tforms.append( jqm_tablerow( _("Animal", l), jqm_link("mobile_post?posttype=va&id=%d" % t["ANIMALID"], t["SHELTERCODE"] + " " + t["ANIMALNAME"]))) tforms.append( jqm_tablerow(_("Test", l), required + " " + t["TESTNAME"])) tforms.append(jqm_tablerow(_("Comments", l), t["COMMENTS"])) tforms.append(jqm_table_end()) tforms.append( jqm_p( _("Result", l) + ": " + "<select class=\"testresult\" data=\"%s\" data-animal=\"%s\">" % (str(t["ID"]), t["ANIMALID"]) + "<option value=" "></option>" + jqm_options_testresults(testresults) + "</select>")) tforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(tlist), True)) h.append(jqm_page_footer()) h.append("\n".join(tforms)) return h
def page_medication(l, homelink, med): h = [] h.append(jqm_page_header("med", _("Medicate", l), homelink)) group = "" mlist = [] mforms = [] for m in med: required = python2display(l, m["DATEREQUIRED"]) if group != required: group = required mlist.append(jqm_list_divider(group)) pageid = "m" + str(m["TREATMENTID"]) mlist.append( jqm_listitem_link( "#" + pageid, "%s - %s (%s)" % (m["ANIMALNAME"], m["SHELTERCODE"], m["TREATMENTNAME"]), "medical", -1, "dialog")) mforms.append(jqm_page_header(pageid, m["TREATMENTNAME"], homelink)) mforms.append(jqm_table()) mforms.append( jqm_tablerow( _("Animal", l), jqm_link("mobile_post?posttype=va&id=%d" % m["ANIMALID"], m["SHELTERCODE"] + " " + m["ANIMALNAME"]))) mforms.append( jqm_tablerow( _("Treatment", l), "%s %s<br />%s" % (required, m["TREATMENTNAME"], m["DOSAGE"]))) mforms.append(jqm_tablerow(_("Comments", l), m["COMMENTS"])) mforms.append(jqm_table_end()) mforms.append( jqm_button( "mobile_post?posttype=med&id=%s&animalid=%s&medicalid=%s" % (str(m["TREATMENTID"]), str(m["ANIMALID"]), str( m["REGIMENID"])), _("Medicate", l), "check")) mforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(mlist), True)) h.append(jqm_page_footer()) h.append("\n".join(mforms)) return h
def page_vaccinations(l, homelink, vacc): h = [] h.append(jqm_page_header("vacc", _("Vaccinate", l), homelink)) group = "" vlist = [] vforms = [] for v in vacc: required = python2display(l, v["DATEREQUIRED"]) if group != required: group = required vlist.append(jqm_list_divider(group)) pageid = "v" + str(v["ID"]) vlist.append( jqm_listitem_link( "#" + pageid, "%s - %s (%s)" % (v["ANIMALNAME"], v["SHELTERCODE"], v["VACCINATIONTYPE"]), "vaccination", -1, "dialog")) vforms.append(jqm_page_header(pageid, v["VACCINATIONTYPE"], homelink)) vforms.append(jqm_table()) vforms.append( jqm_tablerow( _("Animal", l), jqm_link("mobile_post?posttype=va&id=%d" % v["ANIMALID"], v["SHELTERCODE"] + " " + v["ANIMALNAME"]))) vforms.append( jqm_tablerow(_("Vaccination", l), required + " " + v["VACCINATIONTYPE"])) vforms.append(jqm_tablerow(_("Comments", l), v["COMMENTS"])) vforms.append(jqm_table_end()) vforms.append( jqm_button( "mobile_post?posttype=vacc&id=%s&animalid=%s" % (str(v["ID"]), str(v["ANIMALID"])), _("Vaccinate", l), "check")) vforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(vlist), True)) h.append(jqm_page_footer()) h.append("\n".join(vforms)) return h
def page_diary(l, homelink, dia): h = [] h.append(jqm_page_header("diary", _("Diary", l), homelink)) group = "" dlist = [] dforms = [] for d in dia: fordate = python2display(l, d["DIARYDATETIME"]) if group != fordate: group = fordate dlist.append(jqm_list_divider(group)) pageid = "d" + str(d["ID"]) dlist.append( jqm_listitem_link("#" + pageid, "%s (%s)" % (d["SUBJECT"], d["LINKINFO"]), "diary", -1, "dialog")) dforms.append(jqm_page_header(pageid, d["SUBJECT"], homelink)) dforms.append(jqm_table()) dforms.append(jqm_tablerow(_("Subject", l), d["SUBJECT"])) lt = d["LINKINFO"] if d["LINKTYPE"] == diary.ANIMAL: lt = jqm_link("mobile_post?posttype=va&id=%d" % d["LINKID"], d["LINKINFO"]) dforms.append(jqm_tablerow(_("Link", l), lt)) dforms.append(jqm_tablerow(_("Note", l), d["NOTE"])) dforms.append(jqm_table_end()) dforms.append( jqm_button("mobile_post?posttype=dia&on=0&id=%s" % str(d["ID"]), _("Complete", l), "check")) dforms.append( jqm_p( _("Or move this diary on to", l) + ": " + "<select class=\"diaryon\" data=\"%s\">" % str(d["ID"]) + jqm_options_next_month(l) + "</select>")) dforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(dlist), True)) h.append(jqm_page_footer()) h.append("\n".join(dforms)) return h
def save_values_for_link(dbo, post, linkid, linktype = "animal", setdefaults=False): """ Saves incoming additional field values from a record. Clears existing additional field values before saving (this is because forms don't send blank values) linkid: The link to the parent record linktype: The class of parent record setdefaults: If True, will set default values for any keys not supplied (Should be True for calls from insert_X_from_form methods) Keys of either a.MANDATORY.ID can be used (ASM internal forms) or keys of the form additionalFIELDNAME (ASM online forms) """ l = dbo.locale dbo.delete("additional", "LinkType IN (%s) AND LinkID=%s" % (clause_for_linktype(linktype), linkid)) for f in get_field_definitions(dbo, linktype): key = "a.%s.%s" % (f.mandatory, f.id) key2 = "additional%s" % f.fieldname if key not in post and key2 not in post: if setdefaults and f.DEFAULTVALUE and f.DEFAULTVALUE != "": insert_additional(dbo, f.LINKTYPE, linkid, f.ID, f.DEFAULTVALUE) continue elif key not in post: key = key2 val = post[key] if f.fieldtype == YESNO: val = str(post.boolean(key)) elif f.fieldtype == MONEY: val = str(post.integer(key)) elif f.fieldtype == DATE: if len(val.strip()) > 0 and post.date(key) is None: raise utils.ASMValidationError(_("Additional date field '{0}' contains an invalid date.", l).format(f.fieldname)) val = python2display(dbo.locale, post.date(key)) insert_additional(dbo, f.LINKTYPE, linkid, f.ID, val)
def create_animal(dbo, username, wlid): """ Creates an animal record from a waiting list entry with the id given """ a = db.query(dbo, "SELECT * FROM animalwaitinglist WHERE ID = %d" % wlid)[0] l = dbo.locale data = { "animalname": _("Waiting List {0}", l).format(wlid), "markings": str(a["ANIMALDESCRIPTION"]), "reasonforentry": str(a["REASONFORWANTINGTOPART"]), "species": str(a["SPECIESID"]), "comments": str(a["COMMENTS"]), "broughtinby": str(a["OWNERID"]), "originalowner": str(a["OWNERID"]), "animaltype": configuration.default_type(dbo), "breed1": configuration.default_breed(dbo), "breed2": configuration.default_breed(dbo), "basecolour": configuration.default_colour(dbo), "size": configuration.default_size(dbo), "internallocation": configuration.default_location(dbo), "dateofbirth": python2display(l, subtract_years(now(dbo.timezone))), "estimateddob": "1" } # If we're creating shelter codes manually, we need to put something unique # in there for now. Use the id if configuration.manual_codes(dbo): data["sheltercode"] = "WL" + str(wlid) data["shortcode"] = "WL" + str(wlid) nextid, code = animal.insert_animal_from_form(dbo, data, username) # Now that we've created our animal, we should remove this entry from the waiting list db.execute(dbo, "UPDATE animalwaitinglist SET DateRemovedFromList = %s, ReasonForRemoval = %s " \ "WHERE ID = %d" % ( db.dd(now(dbo.timezone)), db.ds(_("Moved to animal record {0}", l).format(code)), wlid)) return nextid
def page_diary(l, homelink, dia): h = [] h.append(jqm_page_header("diary", _("Diary", l), homelink)) group = "" dlist = [] dforms = [] for d in dia: fordate = python2display(l, d["DIARYDATETIME"]) if group != fordate: group = fordate dlist.append(jqm_list_divider(group)) pageid = "d" + str(d["ID"]) dlist.append(jqm_listitem_link("#" + pageid, "%s (%s)" % (d["SUBJECT"], d["LINKINFO"]), "diary", -1, "dialog")) dforms.append(jqm_page_header(pageid, d["SUBJECT"], homelink)) dforms.append(jqm_table()) dforms.append(jqm_tablerow(_("Subject", l), d["SUBJECT"])) lt = d["LINKINFO"] if d["LINKTYPE"] == diary.ANIMAL: lt = jqm_link("mobile_post?posttype=va&id=%d" % d["LINKID"], d["LINKINFO"]) dforms.append(jqm_tablerow(_("Link", l), lt)) dforms.append(jqm_tablerow(_("Note", l), d["NOTE"])) dforms.append(jqm_table_end()) dforms.append(jqm_button("mobile_post?posttype=dia&on=0&id=%s" % str(d["ID"]), _("Complete", l), "check")) dforms.append( jqm_p( _("Or move this diary on to", l) + ": " + '<select class="diaryon" data="%s">' % str(d["ID"]) + jqm_options_next_month(l) + "</select>" ) ) dforms.append(jqm_page_footer()) h.append(jqm_list("\n".join(dlist), True)) h.append(jqm_page_footer()) h.append("\n".join(dforms)) return h
def substituteHFTag(self, searchin, page, user, title=""): """ Substitutes special header and footer tokens in searchin. page contains the current page number. """ output = searchin nav = self.navbar.replace( "<a href=\"%d.%s\">%d</a>" % (page, self.pc.extension, page), str(page)) dateportion = i18n.python2display(self.locale, i18n.now(self.dbo.timezone)) timeportion = i18n.format_date("%H:%M:%S", i18n.now(self.dbo.timezone)) if page != -1: output = output.replace("$$NAV$$", nav) else: output = output.replace("$$NAV$$", "") output = output.replace("$$TITLE$$", title) output = output.replace("$$TOTAL$$", str(self.totalAnimals)) output = output.replace("$$DATE$$", dateportion) output = output.replace("$$TIME$$", timeportion) output = output.replace("$$DATETIME$$", "%s %s" % (dateportion, timeportion)) output = output.replace("$$VERSION$$", i18n.get_version()) output = output.replace("$$REGISTEREDTO$$", configuration.organisation(self.dbo)) output = output.replace( "$$USER$$", "%s (%s)" % (user, users.get_real_name(self.dbo, user))) output = output.replace("$$ORGNAME$$", configuration.organisation(self.dbo)) output = output.replace("$$ORGADDRESS$$", configuration.organisation_address(self.dbo)) output = output.replace("$$ORGTEL$$", configuration.organisation_telephone(self.dbo)) output = output.replace("$$ORGEMAIL$$", configuration.email(self.dbo)) return output
def csv(l, rows, cols=None, includeheader=True): """ Creates a CSV file from a set of resultset rows. If cols has been supplied as a list of strings, fields will be output in that order. """ if rows is None or len(rows) == 0: return "" strio = StringIO() out = UnicodeCSVWriter(strio) if cols is None: cols = [] for k, v in rows[0].iteritems(): cols.append(k) cols = sorted(cols) if includeheader: out.writerow(cols) for r in rows: rd = [] for c in cols: if is_currency(c): rd.append(decode_html(format_currency_no_symbol(l, r[c]))) elif is_date(r[c]): timeportion = "00:00:00" dateportion = "" try: dateportion = python2display(l, r[c]) timeportion = format_time(r[c]) except: pass # Don't stop the show for bad dates/times if timeportion != "00:00:00": # include time if non-midnight dateportion = "%s %s" % (dateportion, timeportion) rd.append(decode_html(dateportion)) else: rd.append(decode_html(r[c])) out.writerow(rd) return strio.getvalue()
def update_waitinglist_remove(dbo, username, wid): """ Marks a waiting list record as removed """ db.execute(dbo, "UPDATE animalwaitinglist SET DateRemovedFromList = %s WHERE ID = %d" % ( db.dd(now(dbo.timezone)), int(wid) )) audit.edit(dbo, username, "animalwaitinglist", "%s: DateRemovedFromList ==> %s" % ( str(wid), python2display(dbo.locale, now(dbo.timezone))))
def run(self): if self.isPublisherExecuting(): return self.updatePublisherProgress(0) self.setLastError("") self.setStartPublishing() shelterid = configuration.smarttag_accountid(self.dbo) if shelterid == "": self.setLastError("No SmartTag Account id has been set.") self.cleanup() return animals = get_microchip_data( self.dbo, ["a.SmartTag = 1 AND a.SmartTagNumber <> ''"] + SMARTTAG_PREFIXES, "smarttag") if len(animals) == 0: self.setLastError("No animals found to publish.") self.cleanup(save_log=False) return if not self.openFTPSocket(): self.setLastError("Failed to open FTP socket.") if self.logSearch("530 Login") != -1: self.log( "Found 530 Login incorrect: disabling SmartTag publisher.") configuration.publishers_enabled_disable(self.dbo, "st") self.cleanup() return # SmartTag want data files called shelterid_mmddyyyy_HHMMSS.csv in a folder # called shelterid_mmddyyyy_HHMMSS dateportion = i18n.format_date("%m%d%Y_%H%M%S", i18n.now(self.dbo.timezone)) folder = "%s_%s" % (shelterid, dateportion) outputfile = "%s_%s.csv" % (shelterid, dateportion) self.mkdir(folder) self.chdir(folder) csv = [] anCount = 0 for an in animals: try: line = [] anCount += 1 self.log("Processing: %s: %s (%d of %d)" % (an["SHELTERCODE"], an["ANIMALNAME"], anCount, len(animals))) self.updatePublisherProgress( self.getProgress(anCount, len(animals))) # If the user cancelled, stop now if self.shouldStopPublishing(): self.log("User cancelled publish. Stopping.") self.resetPublisherProgress() self.cleanup() return # Upload one image for this animal with the name shelterid_animalid-1.jpg self.uploadImage(an, an["WEBSITEMEDIANAME"], "%s_%d-1.jpg" % (shelterid, an["ID"])) # accountid line.append("\"%s\"" % shelterid) # sourcesystem line.append("\"ASM\"") # sourcesystemanimalkey (corresponds to image name) line.append("\"%d\"" % an["ID"]) # sourcesystemownerkey line.append("\"%s\"" % str(an["CURRENTOWNERID"])) # signupidassigned, signuptype if self.stIsSmartTagPrefix(an["IDENTICHIPNUMBER"]): # if we have a smarttag microchip number, use that instead of the tag # since it's unlikely someone will want both line.append("\"%s\"" % an["IDENTICHIPNUMBER"]) line.append("\"IDTAG-LIFETIME\"") else: line.append("\"%s\"" % an["SMARTTAGNUMBER"]) sttype = "IDTAG-ANNUAL" if an["SMARTTAGTYPE"] == 1: sttype = "IDTAG-5 YEAR" if an["SMARTTAGTYPE"] == 2: sttype = "IDTAG-LIFETIME" line.append("\"%s\"" % sttype) # signupeffectivedate line.append( "\"" + i18n.python2display(self.locale, an["SMARTTAGDATE"]) + "\"") # signupbatchpostdt - only used by resending mechanism and we don't do that line.append("\"\"") # feecharged line.append("\"\"") # feecollected line.append("\"\"") # owner related stuff address = an["CURRENTOWNERADDRESS"] houseno = utils.address_house_number(address) streetname = utils.address_street_name(address) # ownerfname line.append("\"%s\"" % an["CURRENTOWNERFORENAMES"]) # ownermname line.append("\"\"") #ownerlname line.append("\"%s\"" % an["CURRENTOWNERSURNAME"]) # addressstreetnumber line.append("\"%s\"" % houseno) # addressstreetdir line.append("\"\"") # addressstreetname line.append("\"%s\"" % streetname) # addressstreettype line.append("\"\"") # addresscity line.append("\"%s\"" % an["CURRENTOWNERTOWN"]) # addressstate line.append("\"%s\"" % an["CURRENTOWNERCOUNTY"]) # addresspostal line.append("\"%s\"" % an["CURRENTOWNERPOSTCODE"]) # addressctry line.append("\"USA\"") # owneremail line.append("\"%s\"" % an["CURRENTOWNEREMAILADDRESS"]) # owneremail2 line.append("\"\"") # owneremail3 line.append("\"\"") # ownerhomephone line.append("\"%s\"" % an["CURRENTOWNERHOMETELEPHONE"]) # ownerworkphone line.append("\"%s\"" % an["CURRENTOWNERWORKTELEPHONE"]) # ownerthirdphone line.append("\"%s\"" % an["CURRENTOWNERMOBILETELEPHONE"]) # petname line.append("\"%s\"" % an["ANIMALNAME"].replace("\"", "\"\"")) # species line.append("\"%s\"" % an["SPECIESNAME"]) # primarybreed line.append("\"%s\"" % an["BREEDNAME1"]) # crossbreed (second breed) if an["CROSSBREED"] == 1: line.append("\"%s\"" % an["BREEDNAME2"]) else: line.append("\"\"") # purebred line.append("\"%s\"" % self.stYesNo(an["CROSSBREED"] == 0)) # gender line.append("\"%s\"" % an["SEXNAME"]) # sterilized line.append("\"%s\"" % self.stYesNo(an["NEUTERED"] == 1)) # primarycolor line.append("\"%s\"" % an["BASECOLOURNAME"]) # secondcolor line.append("\"\"") # sizecategory line.append("\"%s\"" % an["SIZENAME"]) # agecategory line.append("\"%s\"" % an["AGEGROUP"]) # declawed line.append("\"%s\"" % self.stYesNo(an["DECLAWED"] == 1)) # animalstatus (one of DECEASED, ADOPTED or NOT ADOPTED) if an["DECEASEDDATE"] is not None: line.append("\"DECEASED\"") elif an["ACTIVEMOVEMENTTYPE"] == 1 and an[ "ACTIVEMOVEMENTDATE"] is not None: line.append("\"ADOPTED\"") else: line.append("\"NOT ADOPTED\"") # Add to our CSV file csv.append(",".join(line)) # Mark success in the log self.logSuccess("Processed: %s: %s (%d of %d)" % (an["SHELTERCODE"], an["ANIMALNAME"], anCount, len(animals))) except Exception as err: self.logError( "Failed processing animal: %s, %s" % (str(an["SHELTERCODE"]), err), sys.exc_info()) # Mark published self.markAnimalsPublished(animals) header = "accountid,sourcesystem,sourcesystemanimalkey," \ "sourcesystemownerkey,signupidassigned,signuptype,signupeffectivedate," \ "signupbatchpostdt,feecharged,feecollected,ownerfname,ownermname," \ "ownerlname,addressstreetnumber,addressstreetdir,addressstreetname," \ "addressstreettype,addresscity,addressstate,addresspostal,addressctry," \ "owneremail,owneremail2,owneremail3,ownerhomephone,ownerworkphone," \ "ownerthirdphone,petname,species,primarybreed,crossbreed,purebred,gender," \ "sterilized,primarycolor,secondcolor,sizecategory,agecategory,declawed," \ "animalstatus\n" self.saveFile(os.path.join(self.publishDir, outputfile), header + "\n".join(csv)) self.log("Uploading datafile %s" % outputfile) self.upload(outputfile) self.log("Uploaded %s" % outputfile) self.log("-- FILE DATA --") self.log(header + "\n".join(csv)) self.cleanup()
def person_tags(dbo, p): """ Generates a list of tags from a person result (the deep type from calling person.get_person) """ l = dbo.locale tags = { "OWNERID" : str(p["ID"]), "OWNERCODE" : p["OWNERCODE"], "OWNERTITLE" : p["OWNERTITLE"], "TITLE" : p["OWNERTITLE"], "OWNERINITIALS" : p["OWNERINITIALS"], "INITIALS" : p["OWNERINITIALS"], "OWNERFORENAMES" : p["OWNERFORENAMES"], "FORENAMES" : p["OWNERFORENAMES"], "OWNERFIRSTNAMES" : p["OWNERFORENAMES"], "FIRSTNAMES" : p["OWNERFORENAMES"], "OWNERSURNAME" : p["OWNERSURNAME"], "SURNAME" : p["OWNERSURNAME"], "OWNERLASTNAME" : p["OWNERSURNAME"], "LASTNAME" : p["OWNERSURNAME"], "OWNERNAME" : p["OWNERNAME"], "NAME" : p["OWNERNAME"], "OWNERADDRESS" : p["OWNERADDRESS"], "ADDRESS" : p["OWNERADDRESS"], "OWNERTOWN" : p["OWNERTOWN"], "TOWN" : p["OWNERTOWN"], "OWNERCOUNTY" : p["OWNERCOUNTY"], "COUNTY" : p["OWNERCOUNTY"], "OWNERCITY" : p["OWNERTOWN"], "CITY" : p["OWNERTOWN"], "OWNERSTATE" : p["OWNERCOUNTY"], "STATE" : p["OWNERCOUNTY"], "OWNERPOSTCODE" : p["OWNERPOSTCODE"], "POSTCODE" : p["OWNERPOSTCODE"], "OWNERZIPCODE" : p["OWNERPOSTCODE"], "ZIPCODE" : p["OWNERPOSTCODE"], "HOMETELEPHONE" : p["HOMETELEPHONE"], "WORKTELEPHONE" : p["WORKTELEPHONE"], "MOBILETELEPHONE" : p["MOBILETELEPHONE"], "CELLTELEPHONE" : p["MOBILETELEPHONE"], "EMAILADDRESS" : p["EMAILADDRESS"], "OWNERCOMMENTS" : p["COMMENTS"], "COMMENTS" : p["COMMENTS"], "OWNERCREATEDBY" : p["CREATEDBY"], "OWNERCREATEDBYNAME" : p["CREATEDBY"], "OWNERCREATEDDATE" : python2display(l, p["CREATEDDATE"]), "OWNERLASTCHANGEDBY" : p["LASTCHANGEDBY"], "OWNERLASTCHANGEDBYNAME" : p["LASTCHANGEDBY"], "OWNERLASTCHANGEDDATE" : python2display(l, p["LASTCHANGEDDATE"]), "IDCHECK" : (p["IDCHECK"] == 1 and _("Yes", l) or _("No", l)), "MEMBERSHIPNUMBER" : p["MEMBERSHIPNUMBER"], "MEMBERSHIPEXPIRYDATE" : python2display(l, p["MEMBERSHIPEXPIRYDATE"]) } # Additional fields add = additional.get_additional_fields(dbo, int(p["ID"]), "person") for af in add: val = af["VALUE"] if af["FIELDTYPE"] == additional.YESNO: val = additional_yesno(l, af) tags[af["FIELDNAME"].upper()] = val return tags
al.error("failed getting list of users: %s" % str(err), "diary.email_uncompleted_upto_today", dbo) # Grab list of diary notes for today notes = get_uncompleted_upto_today(dbo) # If we don't have any, bail out if len(notes) == 0: return # Go through all user to see if we have relevant notes for them for u in allusers: if u["EMAILADDRESS"] is not None and u["EMAILADDRESS"].strip() != "": s = "" totalforuser = 0 for n in notes: # Is this note relevant for this user? if (n["DIARYFORNAME"] == i18n._("(all)", l) or n["DIARYFORNAME"] == i18n._("(everyone)", l)) \ or (n["DIARYFORNAME"] == u["USERNAME"]) \ or (u["ROLES"].find(n["DIARYFORNAME"]) != -1): s += i18n.python2display(l, n["DIARYDATETIME"]) + " " s += n["SUBJECT"] if n["LINKINFO"] is not None and n["LINKINFO"] != "": s += " / " + n["LINKINFO"] s += "\n" + n["NOTE"] + "\n\n" totalforuser += 1 if totalforuser > 0: al.debug("got %d notes for user %s" % (totalforuser, u["USERNAME"]), "diary.email_uncompleted_upto_today", dbo) utils.send_email(dbo, "*****@*****.**", u["EMAILADDRESS"], "", i18n._("Diary notes for: {0}", l).format(i18n.python2display(l, i18n.now(dbo.timezone))), s) def user_role_where_clause(dbo, user = ""): """ Returns a suitable where clause for filtering diary notes to the given user or any roles the user is in. If user is blank, the where clause return is empty. """
def handler_viewanimal(l, a, af, homelink, post): """ Generate the view animal mobile page. l: The locale a: An animal record af: Additional fields for the animal record homelink: Link to the home menu post: The posted values """ def table(): return "<table style='width: 100%; border-bottom: 1px solid black;'>" def table_end(): return "</table>" def tr(label, value, value2=""): if value is None or str(value).startswith("None "): value = "" if value2 is None or str(value2).startswith("None"): value2 = "" if value2 is not None and value2 != "": value2 = "<td>%s</td>" % value2 return "<tr><td style='font-weight: bold; width: 150px'>%s</td><td>%s</td>%s</tr>" % (label, value, value2) h = [] h.append(header(l)) h.append(jqm_page_header("", "%s - %s" % (a["CODE"], a["ANIMALNAME"]), homelink)) h.append(table()) h.append("<td><img src='%s' class='asm-thumbnail' /></td>" % html.thumbnail_img_src(a, "animalthumb")) h.append("<td><h2 style='margin: 2px;'>%s - %s</h2>" % (a["CODE"], a["ANIMALNAME"])) h.append("%s %s %s</td>" % (a["SEXNAME"], a["BREEDNAME"], a["SPECIESNAME"])) h.append("</tr></table>") h.append(table()) uploadstatus = "" if post["success"] == "true": uploadstatus = _("Photo successfully uploaded.", l) h.append( """ <tr><td style='font-weight: bold; width: 150px;'>%s</td> <td> <form data-ajax="false" action="mobile_post" method="post" enctype="multipart/form-data"> <input type="hidden" name="animalid" value="%d" /> <input type="hidden" name="posttype" value="uai" /> <input type="hidden" name="comments" value="" /> <input type="hidden" name="base64image" value="" /> <input type="file" data-role='none' name="filechooser" id="fc%d" /> <span class=".tipios6" style="display: none">%s</span> <input id='sfc%d' type='submit' data-icon='arrow-u' data-inline='true' data-mini='true' value='%s' /> </form> <span class="tip">%s</span> </td></tr>""" % ( _("Upload Photo", l), a["ID"], a["ID"], _("You will need to upgrade to iOS 6 or higher to upload files.", l), a["ID"], _("Send", l), uploadstatus, ) ) h.append(table()) h.append(tr(_("Type", l), a["ANIMALTYPENAME"])) h.append(tr(_("Location", l), a["DISPLAYLOCATIONNAME"])) h.append(tr(_("Color", l), a["BASECOLOURNAME"])) h.append(tr(_("Coat Type", l), a["COATTYPENAME"])) h.append(tr(_("Size", l), a["SIZENAME"])) h.append(tr(_("DOB", l), python2display(l, a["DATEOFBIRTH"]), a["ANIMALAGE"])) h.append(table_end()) h.append(table()) h.append(tr(_("Markings", l), a["MARKINGS"])) h.append(tr(_("Hidden Comments", l), a["HIDDENANIMALDETAILS"])) h.append(tr(_("Comments", l), a["ANIMALCOMMENTS"])) h.append(table_end()) h.append(table()) h.append(tr(_("Cats", l), a["ISGOODWITHCATSNAME"])) h.append(tr(_("Dogs", l), a["ISGOODWITHDOGSNAME"])) h.append(tr(_("Children", l), a["ISGOODWITHCHILDRENNAME"])) h.append(tr(_("Housetrained", l), a["ISHOUSETRAINEDNAME"])) h.append(table_end()) h.append(table()) h.append(tr(_("Original Owner", l), a["ORIGINALOWNERNAME"])) h.append(tr(_("Brought In By", l), a["BROUGHTINBYOWNERNAME"])) h.append(tr(_("Date Brought In", l), python2display(l, a["DATEBROUGHTIN"]))) h.append( tr( _("Bonded With", l), "%s %s %s %s" % (a["BONDEDANIMAL1CODE"], a["BONDEDANIMAL1NAME"], a["BONDEDANIMAL2CODE"], a["BONDEDANIMAL2NAME"]), ) ) h.append(tr(_("Transfer?", l), a["ISTRANSFERNAME"] == 1)) h.append(tr(_("Entry Category", l), a["ENTRYREASONNAME"])) h.append(tr(_("Entry Reason", l), a["REASONFORENTRY"])) h.append(table_end()) h.append(table()) h.append(tr(_("Microchipped", l), python2display(l, a["IDENTICHIPDATE"]), a["IDENTICHIPNUMBER"])) h.append(tr(_("Tattoo", l), python2display(l, a["TATTOODATE"]), a["TATTOONUMBER"])) h.append(tr(_("Neutered", l), python2display(l, a["NEUTEREDDATE"]))) h.append(tr(_("Declawed", l), a["DECLAWEDNAME"])) h.append(tr(_("Heartworm Tested", l), python2display(l, a["HEARTWORMTESTDATE"]), a["HEARTWORMTESTRESULTNAME"])) h.append( tr( _("FIV/L Tested", l), python2display(l, a["COMBITESTDATE"]), "%s %s" % (a["COMBITESTRESULTNAME"], a["FLVRESULTNAME"]), ) ) h.append(tr(_("Health Problems", l), a["HEALTHPROBLEMS"])) h.append(tr(_("Rabies Tag", l), a["RABIESTAG"])) h.append(tr(_("Special Needs", l), a["HASSPECIALNEEDSNAME"])) h.append(tr(_("Current Vet", l), a["CURRENTVETNAME"], a["CURRENTVETWORKTELEPHONE"])) h.append(table_end()) if len(af) > 0: h.append(table()) for d in af: h.append(tr(d["FIELDLABEL"], d["VALUE"])) h.append(table_end()) h.append( """ <script type="text/javascript"> // If this is an idevice and the file upload box is // disabled, it needs upgrading to iOS6 or better. if (is_idevice && $("#fc%d").attr("disabled")) { $(".tipios6").show(); } </script> """ % (a["ID"]) ) h.append(jqm_page_footer()) h.append("</body></html>") return "\n".join(h)
def animal_tags(dbo, a): """ Generates a list of tags from an animal result (the deep type from calling animal.get_animal) """ l = dbo.locale displaydob = python2display(l, a["DATEOFBIRTH"]) displayage = a["ANIMALAGE"] estimate = "" if a["ESTIMATEDDOB"] == 1: displaydob = a["AGEGROUP"] displayage = a["AGEGROUP"] estimate = _("estimate", l) tags = { "ANIMALNAME" : a["ANIMALNAME"], "ANIMALTYPENAME" : a["ANIMALTYPENAME"], "BASECOLOURNAME" : a["BASECOLOURNAME"], "BASECOLORNAME" : a["BASECOLOURNAME"], "BREEDNAME" : a["BREEDNAME"], "INTERNALLOCATION" : a["SHELTERLOCATIONNAME"], "LOCATIONUNIT" : a["SHELTERLOCATIONUNIT"], "COATTYPE" : a["COATTYPENAME"], "HEALTHPROBLEMS" : a["HEALTHPROBLEMS"], "ANIMALCREATEDBY" : a["CREATEDBY"], "ANIMALCREATEDDATE" : python2display(l, a["CREATEDDATE"]), "DATEBROUGHTIN" : python2display(l, a["DATEBROUGHTIN"]), "DATEOFBIRTH" : python2display(l, a["DATEOFBIRTH"]), "AGEGROUP" : a["AGEGROUP"], "DISPLAYDOB" : displaydob, "DISPLAYAGE" : displayage, "ESTIMATEDDOB" : estimate, "ANIMALID" : str(a["ID"]), "IDENTICHIPNUMBER" : a["IDENTICHIPNUMBER"], "IDENTICHIPPED" : a["IDENTICHIPPEDNAME"], "IDENTICHIPPEDDATE" : python2display(l, a["IDENTICHIPDATE"]), "MICROCHIPNUMBER" : a["IDENTICHIPNUMBER"], "MICROCHIPPED" : a["IDENTICHIPPEDNAME"], "MICROCHIPDATE" : python2display(l, a["IDENTICHIPDATE"]), "TATTOO" : a["TATTOONAME"], "TATTOODATE" : python2display(l, a["TATTOODATE"]), "TATTOONUMBER" : a["TATTOONUMBER"], "COMBITESTED" : a["COMBITESTEDNAME"], "FIVLTESTED" : a["COMBITESTEDNAME"], "COMBITESTDATE" : python2display(l, a["COMBITESTDATE"]), "FIVLTESTDATE" : python2display(l, a["COMBITESTDATE"]), "COMBITESTRESULT" : a["COMBITESTRESULTNAME"], "FIVTESTRESULT" : a["COMBITESTRESULTNAME"], "FIVRESULT" : a["COMBITESTRESULTNAME"], "FLVTESTRESULT" : a["FLVRESULTNAME"], "FLVRESULT" : a["FLVRESULTNAME"], "HEARTWORMTESTED" : a["HEARTWORMTESTEDNAME"], "HEARTWORMTESTDATE" : python2display(l, a["HEARTWORMTESTDATE"]), "HEARTWORMTESTRESULT" : a["HEARTWORMTESTRESULTNAME"], "HIDDENANIMALDETAILS" : a["HIDDENANIMALDETAILS"], "ANIMALLASTCHANGEDBY" : a["LASTCHANGEDBY"], "ANIMALLASTCHANGEDDATE" : python2display(l, a["LASTCHANGEDDATE"]), "MARKINGS" : a["MARKINGS"], "DECLAWED" : a["DECLAWEDNAME"], "RABIESTAG" : a["RABIESTAG"], "GOODWITHCATS" : a["ISGOODWITHCATSNAME"], "GOODWITHDOGS" : a["ISGOODWITHDOGSNAME"], "GOODWITHCHILDREN" : a["ISGOODWITHCHILDRENNAME"], "HOUSETRAINED" : a["ISHOUSETRAINEDNAME"], "NAMEOFPERSONBROUGHTANIMALIN" : a["BROUGHTINBYOWNERNAME"], "ADDRESSOFPERSONBROUGHTANIMALIN" : a["BROUGHTINBYOWNERADDRESS"], "TOWNOFPERSONBROUGHTANIMALIN" : a["BROUGHTINBYOWNERTOWN"], "COUNTYOFPERSONBROUGHTANIMALIN": a["BROUGHTINBYOWNERCOUNTY"], "POSTCODEOFPERSONBROUGHTIN": a["BROUGHTINBYOWNERPOSTCODE"], "CITYOFPERSONBROUGHTANIMALIN" : a["BROUGHTINBYOWNERTOWN"], "STATEOFPERSONBROUGHTANIMALIN": a["BROUGHTINBYOWNERCOUNTY"], "ZIPCODEOFPERSONBROUGHTIN": a["BROUGHTINBYOWNERPOSTCODE"], "BROUGHTINBYNAME" : a["BROUGHTINBYOWNERNAME"], "BROUGHTINBYADDRESS" : a["BROUGHTINBYOWNERADDRESS"], "BROUGHTINBYTOWN" : a["BROUGHTINBYOWNERTOWN"], "BROUGHTINBYCOUNTY" : a["BROUGHTINBYOWNERCOUNTY"], "BROUGHTINBYPOSTCODE" : a["BROUGHTINBYOWNERPOSTCODE"], "BROUGHTINBYCITY" : a["BROUGHTINBYOWNERTOWN"], "BROUGHTINBYSTATE" : a["BROUGHTINBYOWNERCOUNTY"], "BROUGHTINBYZIPCODE" : a["BROUGHTINBYOWNERPOSTCODE"], "BROUGHTINBYHOMEPHONE" : a["BROUGHTINBYHOMETELEPHONE"], "BROUGHTINBYPHONE" : a["BROUGHTINBYHOMETELEPHONE"], "BROUGHTINBYWORKPHONE" : a["BROUGHTINBYWORKTELEPHONE"], "BROUGHTINBYMOBILEPHONE" : a["BROUGHTINBYMOBILETELEPHONE"], "BROUGHTINBYCELLPHONE" : a["BROUGHTINBYMOBILETELEPHONE"], "BROUGHTINBYEMAIL" : a["BROUGHTINBYEMAILADDRESS"], "NAMEOFOWNERSVET" : a["OWNERSVETNAME"], "NAMEOFCURRENTVET" : a["CURRENTVETNAME"], "HASSPECIALNEEDS" : a["HASSPECIALNEEDSNAME"], "NEUTERED" : a["NEUTEREDNAME"], "FIXED" : a["NEUTEREDNAME"], "ALTERED" : a["NEUTEREDNAME"], "NEUTEREDDATE" : python2display(l, a["NEUTEREDDATE"]), "FIXEDDATE" : python2display(l, a["NEUTEREDDATE"]), "ALTEREDDATE" : python2display(l, a["NEUTEREDDATE"]), "ORIGINALOWNERNAME" : a["ORIGINALOWNERNAME"], "ORIGINALOWNERADDRESS" : a["ORIGINALOWNERADDRESS"], "ORIGINALOWNERTOWN" : a["ORIGINALOWNERTOWN"], "ORIGINALOWNERCOUNTY" : a["ORIGINALOWNERCOUNTY"], "ORIGINALOWNERPOSTCODE" : a["ORIGINALOWNERPOSTCODE"], "ORIGINALOWNERCITY" : a["ORIGINALOWNERTOWN"], "ORIGINALOWNERSTATE" : a["ORIGINALOWNERCOUNTY"], "ORIGINALOWNERZIPCODE" : a["ORIGINALOWNERPOSTCODE"], "ORIGINALOWNERHOMEPHONE" : a["ORIGINALOWNERHOMETELEPHONE"], "ORIGINALOWNERPHONE" : a["ORIGINALOWNERHOMETELEPHONE"], "ORIGINALOWNERWORKPHONE" : a["ORIGINALOWNERWORKTELEPHONE"], "ORIGINALOWNERMOBILEPHONE" : a["ORIGINALOWNERMOBILETELEPHONE"], "ORIGINALOWNERCELLPHONE" : a["ORIGINALOWNERMOBILETELEPHONE"], "ORIGINALOWNEREMAIL" : a["ORIGINALOWNEREMAILADDRESS"], "CURRENTOWNERNAME" : a["CURRENTOWNERNAME"], "CURRENTOWNERADDRESS" : a["CURRENTOWNERADDRESS"], "CURRENTOWNERTOWN" : a["CURRENTOWNERTOWN"], "CURRENTOWNERCOUNTY" : a["CURRENTOWNERCOUNTY"], "CURRENTOWNERPOSTCODE" : a["CURRENTOWNERPOSTCODE"], "CURRENTOWNERCITY" : a["CURRENTOWNERTOWN"], "CURRENTOWNERSTATE" : a["CURRENTOWNERCOUNTY"], "CURRENTOWNERZIPCODE" : a["CURRENTOWNERPOSTCODE"], "CURRENTOWNERHOMEPHONE" : a["CURRENTOWNERHOMETELEPHONE"], "CURRENTOWNERPHONE" : a["CURRENTOWNERHOMETELEPHONE"], "CURRENTOWNERWORKPHONE" : a["CURRENTOWNERWORKTELEPHONE"], "CURRENTOWNERMOBILEPHONE" : a["CURRENTOWNERMOBILETELEPHONE"], "CURRENTOWNERCELLPHONE" : a["CURRENTOWNERMOBILETELEPHONE"], "CURRENTOWNEREMAIL" : a["CURRENTOWNEREMAILADDRESS"], "CURRENTVETNAME" : a["CURRENTVETNAME"], "CURRENTVETADDRESS" : a["CURRENTVETADDRESS"], "CURRENTVETTOWN" : a["CURRENTVETTOWN"], "CURRENTVETCOUNTY" : a["CURRENTVETCOUNTY"], "CURRENTVETPOSTCODE" : a["CURRENTVETPOSTCODE"], "CURRENTVETCITY" : a["CURRENTVETTOWN"], "CURRENTVETSTATE" : a["CURRENTVETCOUNTY"], "CURRENTVETZIPCODE" : a["CURRENTVETPOSTCODE"], "CURRENTVETPHONE" : a["CURRENTVETWORKTELEPHONE"], "OWNERSVETNAME" : a["OWNERSVETNAME"], "OWNERSVETADDRESS" : a["OWNERSVETADDRESS"], "OWNERSVETTOWN" : a["OWNERSVETTOWN"], "OWNERSVETCOUNTY" : a["OWNERSVETCOUNTY"], "OWNERSVETPOSTCODE" : a["OWNERSVETPOSTCODE"], "OWNERSVETCITY" : a["OWNERSVETTOWN"], "OWNERSVETSTATE" : a["OWNERSVETCOUNTY"], "OWNERSVETZIPCODE" : a["OWNERSVETPOSTCODE"], "OWNERSVETPHONE" : a["OWNERSVETWORKTELEPHONE"], "RESERVEDOWNERNAME" : a["RESERVEDOWNERNAME"], "RESERVEDOWNERADDRESS" : a["RESERVEDOWNERADDRESS"], "RESERVEDOWNERTOWN" : a["RESERVEDOWNERTOWN"], "RESERVEDOWNERCOUNTY" : a["RESERVEDOWNERCOUNTY"], "RESERVEDOWNERPOSTCODE" : a["RESERVEDOWNERPOSTCODE"], "RESERVEDOWNERCITY" : a["RESERVEDOWNERTOWN"], "RESERVEDOWNERSTATE" : a["RESERVEDOWNERCOUNTY"], "RESERVEDOWNERZIPCODE" : a["RESERVEDOWNERPOSTCODE"], "RESERVEDOWNERHOMEPHONE" : a["RESERVEDOWNERHOMETELEPHONE"], "RESERVEDOWNERPHONE" : a["RESERVEDOWNERHOMETELEPHONE"], "RESERVEDOWNERWORKPHONE" : a["RESERVEDOWNERWORKTELEPHONE"], "RESERVEDOWNERMOBILEPHONE" : a["RESERVEDOWNERMOBILETELEPHONE"], "RESERVEDOWNERCELLPHONE" : a["RESERVEDOWNERMOBILETELEPHONE"], "RESERVEDOWNEREMAIL" : a["RESERVEDOWNEREMAILADDRESS"], "ENTRYCATEGORY" : a["ENTRYREASONNAME"], "REASONFORENTRY" : a["REASONFORENTRY"], "REASONNOTBROUGHTBYOWNER" : a["REASONNO"], "SEX" : a["SEXNAME"], "SIZE" : a["SIZENAME"], "SPECIESNAME" : a["SPECIESNAME"], "ANIMALCOMMENTS" : a["ANIMALCOMMENTS"], "SHELTERCODE" : a["SHELTERCODE"], "AGE" : a["ANIMALAGE"], "ACCEPTANCENUMBER" : a["ACCEPTANCENUMBER"], "LITTERID" : a["ACCEPTANCENUMBER"], "DECEASEDDATE" : python2display(l, a["DECEASEDDATE"]), "DECEASEDNOTES" : a["PTSREASON"], "DECEASEDCATEGORY" : a["PTSREASONNAME"], "SHORTSHELTERCODE" : a["SHORTCODE"], "MOSTRECENTENTRY" : python2display(l, a["MOSTRECENTENTRYDATE"]), "TIMEONSHELTER" : a["TIMEONSHELTER"], "WEBMEDIAFILENAME" : a["WEBSITEMEDIANAME"], "WEBSITEMEDIANAME" : a["WEBSITEMEDIANAME"], "WEBSITEVIDEOURL" : a["WEBSITEVIDEOURL"], "WEBSITEVIDEONOTES" : a["WEBSITEVIDEONOTES"], "WEBMEDIANOTES" : a["WEBSITEMEDIANOTES"], "WEBSITEMEDIANOTES" : a["WEBSITEMEDIANOTES"], "DOCUMENTIMGLINK" : "<img height=\"200\" src=\"" + html.img_src(a, "animal") + "\" >", "DOCUMENTIMGTHUMBLINK" : "<img src=\"" + html.thumbnail_img_src(a, "animalthumb") + "\" />", "DOCUMENTQRLINK" : "<img src=\"http://chart.apis.google.com/chart?cht=qr&chl=%s&chs=150x150\" />" % (BASE_URL + "/animal?id=%s" % a["ID"]), "ANIMALONSHELTER" : yes_no(l, a["ARCHIVED"] == 0), "ANIMALISRESERVED" : yes_no(l, a["HASACTIVERESERVE"] == 1), "ADOPTIONID" : a["ACTIVEMOVEMENTADOPTIONNUMBER"], "ADOPTIONNUMBER" : a["ACTIVEMOVEMENTADOPTIONNUMBER"], "INSURANCENUMBER" : a["ACTIVEMOVEMENTINSURANCENUMBER"], "RESERVATIONDATE" : python2display(l, a["ACTIVEMOVEMENTRESERVATIONDATE"]), "RETURNDATE" : python2display(l, a["ACTIVEMOVEMENTRETURNDATE"]), "ADOPTIONDATE" : python2display(l, a["ACTIVEMOVEMENTDATE"]), "FOSTEREDDATE" : python2display(l, a["ACTIVEMOVEMENTDATE"]), "TRANSFERDATE" : python2display(l, a["ACTIVEMOVEMENTDATE"]), "MOVEMENTDATE" : python2display(l, a["ACTIVEMOVEMENTDATE"]), "MOVEMENTTYPE" : a["ACTIVEMOVEMENTTYPENAME"], "ADOPTIONDONATION" : format_currency_no_symbol(l, a["ACTIVEMOVEMENTDONATION"]), "ADOPTIONCREATEDBY" : a["ACTIVEMOVEMENTCREATEDBY"], "ADOPTIONCREATEDBYNAME" : a["ACTIVEMOVEMENTCREATEDBYNAME"], "ADOPTIONCREATEDDATE" : python2display(l, a["ACTIVEMOVEMENTCREATEDDATE"]), "ADOPTIONLASTCHANGEDBY" : a["ACTIVEMOVEMENTLASTCHANGEDBY"], "ADOPTIONLASTCHANGEDDATE" : python2display(l, a["ACTIVEMOVEMENTLASTCHANGEDDATE"]) } # Set original owner to be current owner on non-shelter animals if a["NONSHELTERANIMAL"] == 1 and a["ORIGINALOWNERNAME"] is not None and a["ORIGINALOWNERNAME"] != "": tags["CURRENTOWNERNAME"] = a["ORIGINALOWNERNAME"] tags["CURRENTOWNERADDRESS"] = a["ORIGINALOWNERADDRESS"] tags["CURRENTOWNERTOWN"] = a["ORIGINALOWNERTOWN"] tags["CURRENTOWNERCOUNTY"] = a["ORIGINALOWNERCOUNTY"] tags["CURRENTOWNERPOSTCODE"] = a["ORIGINALOWNERPOSTCODE"] tags["CURRENTOWNERCITY"] = a["ORIGINALOWNERTOWN"] tags["CURRENTOWNERSTATE"] = a["ORIGINALOWNERCOUNTY"] tags["CURRENTOWNERZIPCODE"] = a["ORIGINALOWNERPOSTCODE"] tags["CURRENTOWNERHOMEPHONE"] = a["ORIGINALOWNERHOMETELEPHONE"] tags["CURRENTOWNERPHONE"] = a["ORIGINALOWNERHOMETELEPHONE"] tags["CURRENTOWNERWORKPHONE"] = a["ORIGINALOWNERWORKTELEPHONE"] tags["CURRENTOWNERMOBILEPHONE"] = a["ORIGINALOWNERMOBILETELEPHONE"] tags["CURRENTOWNERCELLPHONE"] = a["ORIGINALOWNERMOBILETELEPHONE"] tags["CURRENTOWNEREMAIL"] = a["ORIGINALOWNEREMAILADDRESS"] # If the animal doesn't have a current owner, but does have an open # movement with a future date on it, look up the owner and use that # instead so that we can still generate paperwork for future adoptions. if a["CURRENTOWNERID"] is None or a["CURRENTOWNERID"] == 0: latest = animal.get_latest_movement(dbo, a["ID"]) if latest is not None: p = person.get_person(dbo, latest["OWNERID"]) if p is not None: tags["CURRENTOWNERNAME"] = p["OWNERNAME"] tags["CURRENTOWNERADDRESS"] = p["OWNERADDRESS"] tags["CURRENTOWNERTOWN"] = p["OWNERTOWN"] tags["CURRENTOWNERCOUNTY"] = p["OWNERCOUNTY"] tags["CURRENTOWNERPOSTCODE"] = p["OWNERPOSTCODE"] tags["CURRENTOWNERCITY"] = p["OWNERTOWN"] tags["CURRENTOWNERSTATE"] = p["OWNERCOUNTY"] tags["CURRENTOWNERZIPCODE"] = p["OWNERPOSTCODE"] tags["CURRENTOWNERHOMEPHONE"] = p["HOMETELEPHONE"] tags["CURRENTOWNERPHONE"] = p["HOMETELEPHONE"] tags["CURRENTOWNERWORKPHONE"] = p["WORKTELEPHONE"] tags["CURRENTOWNERMOBILEPHONE"] = p["MOBILETELEPHONE"] tags["CURRENTOWNERCELLPHONE"] = p["MOBILETELEPHONE"] tags["CURRENTOWNEREMAIL"] = p["EMAILADDRESS"] # Additional fields add = additional.get_additional_fields(dbo, int(a["ID"]), "animal") for af in add: val = af["VALUE"] if af["FIELDTYPE"] == additional.YESNO: val = additional_yesno(l, af) if af["FIELDTYPE"] == additional.MONEY: val = format_currency_no_symbol(l, af["VALUE"]) tags[af["FIELDNAME"].upper()] = val include_incomplete = configuration.include_incomplete_medical_doc(dbo) # Vaccinations vaccasc = medical.get_vaccinations(dbo, int(a["ID"]), not include_incomplete) vaccdesc = medical.get_vaccinations(dbo, int(a["ID"]), not include_incomplete, medical.DESCENDING_REQUIRED) for idx in range(1, 101): tags["VACCINATIONNAME" + str(idx)] = "" tags["VACCINATIONREQUIRED" + str(idx)] = "" tags["VACCINATIONGIVEN" + str(idx)] = "" tags["VACCINATIONCOMMENTS" + str(idx)] = "" tags["VACCINATIONDESCRIPTION" + str(idx)] = "" tags["VACCINATIONNAMELAST" + str(idx)] = "" tags["VACCINATIONREQUIREDLAST" + str(idx)] = "" tags["VACCINATIONGIVENLAST" + str(idx)] = "" tags["VACCINATIONCOMMENTSLAST" + str(idx)] = "" tags["VACCINATIONDESCRIPTIONLAST" + str(idx)] = "" idx = 1 for v in vaccasc: tags["VACCINATIONNAME" + str(idx)] = v["VACCINATIONTYPE"] tags["VACCINATIONREQUIRED" + str(idx)] = python2display(l, v["DATEREQUIRED"]) tags["VACCINATIONGIVEN" + str(idx)] = python2display(l, v["DATEOFVACCINATION"]) tags["VACCINATIONCOMMENTS" + str(idx)] = v["COMMENTS"] tags["VACCINATIONDESCRIPTION" + str(idx)] = v["VACCINATIONDESCRIPTION"] idx += 1 idx = 1 uniquetypes = {} recentgiven = {} for v in vaccdesc: tags["VACCINATIONNAMELAST" + str(idx)] = v["VACCINATIONTYPE"] tags["VACCINATIONREQUIREDLAST" + str(idx)] = python2display(l, v["DATEREQUIRED"]) tags["VACCINATIONGIVENLAST" + str(idx)] = python2display(l, v["DATEOFVACCINATION"]) tags["VACCINATIONCOMMENTSLAST" + str(idx)] = v["COMMENTS"] tags["VACCINATIONDESCRIPTIONLAST" + str(idx)] = v["VACCINATIONDESCRIPTION"] idx += 1 # If this is the first of this type of vacc we've seen, make # some keys based on its name. if not uniquetypes.has_key(v["VACCINATIONTYPE"]): vname = v["VACCINATIONTYPE"].upper().replace(" ", "").replace("/", "") uniquetypes[v["VACCINATIONTYPE"]] = v tags["VACCINATIONNAME" + vname] = v["VACCINATIONTYPE"] tags["VACCINATIONREQUIRED" + vname] = python2display(l, v["DATEREQUIRED"]) tags["VACCINATIONGIVEN" + vname] = python2display(l, v["DATEOFVACCINATION"]) tags["VACCINATIONCOMMENTS" + vname] = v["COMMENTS"] tags["VACCINATIONDESCRIPTION" + vname] = v["VACCINATIONDESCRIPTION"] # If this is the first of this type of vacc we've seen that's been given # make some keys based on its name if not recentgiven.has_key(v["VACCINATIONTYPE"]) and v["DATEOFVACCINATION"] is not None: vname = v["VACCINATIONTYPE"].upper().replace(" ", "").replace("/", "") recentgiven[v["VACCINATIONTYPE"]] = v tags["VACCINATIONNAMERECENT" + vname] = v["VACCINATIONTYPE"] tags["VACCINATIONREQUIREDRECENT" + vname] = python2display(l, v["DATEREQUIRED"]) tags["VACCINATIONGIVENRECENT" + vname] = python2display(l, v["DATEOFVACCINATION"]) tags["VACCINATIONCOMMENTSRECENT" + vname] = v["COMMENTS"] tags["VACCINATIONDESCRIPTIONRECENT" + vname] = v["VACCINATIONDESCRIPTION"] # Tests testasc = medical.get_tests(dbo, int(a["ID"]), not include_incomplete) testdesc = medical.get_tests(dbo, int(a["ID"]), not include_incomplete, medical.DESCENDING_REQUIRED) for idx in range(1, 101): tags["TESTNAME" + str(idx)] = "" tags["TESTRESULT" + str(idx)] = "" tags["TESTREQUIRED" + str(idx)] = "" tags["TESTGIVEN" + str(idx)] = "" tags["TESTCOMMENTS" + str(idx)] = "" tags["TESTDESCRIPTION" + str(idx)] = "" tags["TESTNAMELAST" + str(idx)] = "" tags["TESTREQUIREDLAST" + str(idx)] = "" tags["TESTGIVENLAST" + str(idx)] = "" tags["TESTCOMMENTSLAST" + str(idx)] = "" tags["TESTDESCRIPTIONLAST" + str(idx)] = "" idx = 1 for t in testasc: tags["TESTNAME" + str(idx)] = t["TESTNAME"] tags["TESTRESULT" + str(idx)] = t["RESULTNAME"] tags["TESTREQUIRED" + str(idx)] = python2display(l, t["DATEREQUIRED"]) tags["TESTGIVEN" + str(idx)] = python2display(l, t["DATEOFTEST"]) tags["TESTCOMMENTS" + str(idx)] = t["COMMENTS"] tags["TESTDESCRIPTION" + str(idx)] = t["TESTDESCRIPTION"] idx += 1 idx = 1 uniquetypes = {} recentgiven = {} for t in testdesc: tags["TESTNAMELAST" + str(idx)] = t["TESTNAME"] tags["TESTRESULTLAST" + str(idx)] = t["RESULTNAME"] tags["TESTREQUIREDLAST" + str(idx)] = python2display(l, t["DATEREQUIRED"]) tags["TESTGIVENLAST" + str(idx)] = python2display(l, t["DATEOFTEST"]) tags["TESTCOMMENTSLAST" + str(idx)] = t["COMMENTS"] tags["TESTDESCRIPTIONLAST" + str(idx)] = t["TESTDESCRIPTION"] idx += 1 # If this is the first of this type of test we've seen, make # some keys based on its name. if not uniquetypes.has_key(t["TESTNAME"]): tname = t["TESTNAME"].upper().replace(" ", "").replace("/", "") uniquetypes[t["TESTNAME"]] = t tags["TESTNAME" + tname] = t["TESTNAME"] tags["TESTRESULT" + tname] = t["RESULTNAME"] tags["TESTREQUIRED" + tname] = python2display(l, t["DATEREQUIRED"]) tags["TESTGIVEN" + tname] = python2display(l, t["DATEOFTEST"]) tags["TESTCOMMENTS" + tname] = t["COMMENTS"] tags["TESTDESCRIPTION" + tname] = t["TESTDESCRIPTION"] # If this is the first of this type of test we've seen that's been given # make some keys based on its name if not recentgiven.has_key(t["TESTNAME"]) and t["DATEOFTEST"] is not None: tname = t["TESTNAME"].upper().replace(" ", "").replace("/", "") recentgiven[t["TESTNAME"]] = t tags["TESTNAMERECENT" + tname] = t["TESTNAME"] tags["TESTRESULTRECENT" + tname] = t["RESULTNAME"] tags["TESTREQUIREDRECENT" + tname] = python2display(l, t["DATEREQUIRED"]) tags["TESTGIVENRECENT" + tname] = python2display(l, t["DATEOFTEST"]) tags["TESTCOMMENTSRECENT" + tname] = t["COMMENTS"] tags["TESTDESCRIPTIONRECENT" + tname] = t["TESTDESCRIPTION"] # Medical medasc = medical.get_regimens(dbo, int(a["ID"]), not include_incomplete) meddesc = medical.get_regimens(dbo, int(a["ID"]), not include_incomplete, medical.DESCENDING_REQUIRED) for idx in range(1, 101): tags["MEDICALNAME" + str(idx)] = "" tags["MEDICALCOMMENTS" + str(idx)] = "" tags["MEDICALFREQUENCY" + str(idx)] = "" tags["MEDICALNUMBEROFTREATMENTS" + str(idx)] = "" tags["MEDICALSTATUS" + str(idx)] = "" tags["MEDICALDOSAGE" + str(idx)] = "" tags["MEDICALSTARTDATE" + str(idx)] = "" tags["MEDICALTREATMENTSGIVEN" + str(idx)] = "" tags["MEDICALTREATMENTSREMAINING" + str(idx)] = "" tags["MEDICALNAMELAST" + str(idx)] = "" tags["MEDICALCOMMENTSLAST" + str(idx)] = "" tags["MEDICALFREQUENCYLAST" + str(idx)] = "" tags["MEDICALNUMBEROFTREATMENTSLAST" + str(idx)] = "" tags["MEDICALSTATUSLAST" + str(idx)] = "" tags["MEDICALDOSAGELAST" + str(idx)] = "" tags["MEDICALSTARTDATELAST" + str(idx)] = "" tags["MEDICALTREATMENTSGIVENLAST" + str(idx)] = "" tags["MEDICALTREATMENTSREMAININGLAST" + str(idx)] = "" idx = 1 for m in medasc: tags["MEDICALNAME" + str(idx)] = m["TREATMENTNAME"] tags["MEDICALCOMMENTS" + str(idx)] = m["COMMENTS"] tags["MEDICALFREQUENCY" + str(idx)] = m["NAMEDFREQUENCY"] tags["MEDICALNUMBEROFTREATMENTS" + str(idx)] = m["NAMEDNUMBEROFTREATMENTS"] tags["MEDICALSTATUS" + str(idx)] = m["NAMEDSTATUS"] tags["MEDICALDOSAGE" + str(idx)] = m["DOSAGE"] tags["MEDICALSTARTDATE" + str(idx)] = python2display(l, m["STARTDATE"]) tags["MEDICALTREATMENTSGIVEN" + str(idx)] = str(m["TREATMENTSGIVEN"]) tags["MEDICALTREATMENTSREMAINING" + str(idx)] = str(m["TREATMENTSREMAINING"]) idx += 1 idx = 1 uniquetypes = {} recentgiven = {} for m in meddesc: tags["MEDICALNAMELAST" + str(idx)] = m["TREATMENTNAME"] tags["MEDICALCOMMENTSLAST" + str(idx)] = m["COMMENTS"] tags["MEDICALFREQUENCYLAST" + str(idx)] = m["NAMEDFREQUENCY"] tags["MEDICALNUMBEROFTREATMENTSLAST" + str(idx)] = m["NAMEDNUMBEROFTREATMENTS"] tags["MEDICALSTATUSLAST" + str(idx)] = m["NAMEDSTATUS"] tags["MEDICALDOSAGELAST" + str(idx)] = m["DOSAGE"] tags["MEDICALSTARTDATELAST" + str(idx)] = python2display(l, m["STARTDATE"]) tags["MEDICALTREATMENTSGIVENLAST" + str(idx)] = str(m["TREATMENTSGIVEN"]) tags["MEDICALTREATMENTSREMAININGLAST" + str(idx)] = str(m["TREATMENTSREMAINING"]) idx += 1 # If this is the first of this type of med we've seen, make # some keys based on its name. if not uniquetypes.has_key(m["TREATMENTNAME"]): tname = m["TREATMENTNAME"].upper().replace(" ", "").replace("/", "") uniquetypes[m["TREATMENTNAME"]] = m tags["MEDICALNAME" + tname] = m["TREATMENTNAME"] tags["MEDICALCOMMENTS" + tname] = m["COMMENTS"] tags["MEDICALFREQUENCY" + tname] = m["NAMEDFREQUENCY"] tags["MEDICALNUMBEROFTREATMENTS" + tname] = m["NAMEDNUMBEROFTREATMENTS"] tags["MEDICALSTATUS" + tname] = m["NAMEDSTATUS"] tags["MEDICALDOSAGE" + tname] = m["DOSAGE"] tags["MEDICALSTARTDATE" + tname] = python2display(l, m["STARTDATE"]) tags["MEDICALTREATMENTSGIVEN" + tname] = str(m["TREATMENTSGIVEN"]) tags["MEDICALTREATMENTSREMAINING" + tname] = str(m["TREATMENTSREMAINING"]) # If this is the first of this type of med we've seen that's complete if not recentgiven.has_key(m["TREATMENTNAME"]) and m["STATUS"] == 2: tname = m["TREATMENTNAME"].upper().replace(" ", "").replace("/", "") recentgiven[m["TREATMENTNAME"]] = m tags["MEDICALNAMERECENT" + tname] = m["TREATMENTNAME"] tags["MEDICALCOMMENTSRECENT" + tname] = m["COMMENTS"] tags["MEDICALFREQUENCYRECENT" + tname] = m["NAMEDFREQUENCY"] tags["MEDICALNUMBEROFTREATMENTSRECENT" + tname] = m["NAMEDNUMBEROFTREATMENTS"] tags["MEDICALSTATUSRECENT" + tname] = m["NAMEDSTATUS"] tags["MEDICALDOSAGERECENT" + tname] = m["DOSAGE"] tags["MEDICALSTARTDATERECENT" + tname] = python2display(l, m["STARTDATE"]) tags["MEDICALTREATMENTSGIVENRECENT" + tname] = str(m["TREATMENTSGIVEN"]) tags["MEDICALTREATMENTSREMAININGRECENT" + tname] = str(m["TREATMENTSREMAINING"]) # Diet dietasc = animal.get_diets(dbo, int(a["ID"])) dietdesc = animal.get_diets(dbo, int(a["ID"]), animal.DESCENDING) for idx in range(1, 101): tags["DIETNAME" + str(idx)] = "" tags["DIETDESCRIPTION" + str(idx)] = "" tags["DIETDATESTARTED" + str(idx)] = "" tags["DIETCOMMENTS" + str(idx)] = "" tags["DIETNAMELAST" + str(idx)] = "" tags["DIETDESCRIPTIONLAST" + str(idx)] = "" tags["DIETDATESTARTEDLAST" + str(idx)] = "" tags["DIETCOMMENTSLAST" + str(idx)] = "" idx = 1 for d in dietasc: tags["DIETNAME" + str(idx)] = d["DIETNAME"] tags["DIETDESCRIPTION" + str(idx)] = d["DIETDESCRIPTION"] tags["DIETDATESTARTED" + str(idx)] = python2display(l, d["DATESTARTED"]) tags["DIETCOMMENTS" + str(idx)] = d["COMMENTS"] idx += 1 idx = 1 for d in dietdesc: tags["DIETNAMELAST" + str(idx)] = d["DIETNAME"] tags["DIETDESCRIPTIONLAST" + str(idx)] = d["DIETDESCRIPTION"] tags["DIETDATESTARTEDLAST" + str(idx)] = python2display(l, d["DATESTARTED"]) tags["DIETCOMMENTSLAST" + str(idx)] = d["COMMENTS"] idx += 1 # Donations donasc = financial.get_animal_donations(dbo, int(a["ID"])) dondesc = financial.get_animal_donations(dbo, int(a["ID"]), financial.DESCENDING) for idx in range(1, 101): tags["RECEIPTNUM" + str(idx)] = "" tags["DONATIONTYPE" + str(idx)] = "" tags["DONATIONDATE" + str(idx)] = "" tags["DONATIONDATEDUE" + str(idx)] = "" tags["DONATIONAMOUNT" + str(idx)] = "" tags["DONATIONCOMMENTS" + str(idx)] = "" tags["DONATIONGIFTAID" + str(idx)] = "" tags["RECEIPTNUMLAST" + str(idx)] = "" tags["DONATIONTYPELAST" + str(idx)] = "" tags["DONATIONDATELAST" + str(idx)] = "" tags["DONATIONDATEDUELAST" + str(idx)] = "" tags["DONATIONAMOUNTLAST" + str(idx)] = "" tags["DONATIONCOMMENTSLAST" + str(idx)] = "" tags["DONATIONGIFTAIDLAST" + str(idx)] = "" idx = 1 for d in donasc: tags["RECEIPTNUM" + str(idx)] = utils.padleft(d["ID"], 8) tags["DONATIONTYPE" + str(idx)] = d["DONATIONNAME"] tags["DONATIONDATE" + str(idx)] = python2display(l, d["DATE"]) tags["DONATIONDATEDUE" + str(idx)] = python2display(l, d["DATEDUE"]) tags["DONATIONAMOUNT" + str(idx)] = format_currency_no_symbol(l, d["DONATION"]) tags["DONATIONCOMMENTS" + str(idx)] = d["COMMENTS"] tags["DONATIONGIFTAID" + str(idx)] = d["ISGIFTAID"] == 1 and _("Yes", l) or _("No", l) idx = 1 uniquetypes = {} recentrec = {} for d in dondesc: tags["RECEIPTNUMLAST" + str(idx)] = utils.padleft(d["ID"], 8) tags["DONATIONTYPELAST" + str(idx)] = d["DONATIONNAME"] tags["DONATIONDATELAST" + str(idx)] = python2display(l, d["DATE"]) tags["DONATIONDATEDUELAST" + str(idx)] = python2display(l, d["DATEDUE"]) tags["DONATIONAMOUNTLAST" + str(idx)] = format_currency_no_symbol(l, d["DONATION"]) tags["DONATIONCOMMENTSLAST" + str(idx)] = d["COMMENTS"] tags["DONATIONGIFTAIDLAST" + str(idx)] = d["ISGIFTAID"] == 1 and _("Yes", l) or _("No", l) idx += 1 # If this is the first of this type of donation we've seen, make # some keys based on its name. if not uniquetypes.has_key(d["DONATIONNAME"]): dname = d["DONATIONNAME"].upper().replace(" ", "").replace("/", "") uniquetypes[d["DONATIONNAME"]] = d tags["RECEIPTNUM" + dname] = utils.padleft(d["ID"], 8) tags["DONATIONTYPE" + dname] = d["DONATIONNAME"] tags["DONATIONDATE" + dname] = python2display(l, d["DATE"]) tags["DONATIONDATEDUE" + dname] = python2display(l, d["DATEDUE"]) tags["DONATIONAMOUNT" + dname] = format_currency_no_symbol(l, d["DONATION"]) tags["DONATIONCOMMENTS" + dname] = d["COMMENTS"] tags["DONATIONGIFTAID" + dname] = d["ISGIFTAID"] == 1 and _("Yes", l) or _("No", l) # If this is the first of this type of donation we've seen that's received if not recentrec.has_key(d["DONATIONNAME"]) and d["DATE"] is not None: dname = d["DONATIONNAME"].upper().replace(" ", "").replace("/", "") recentrec[d["DONATIONNAME"]] = d tags["RECEIPTNUMRECENT" + dname] = utils.padleft(d["ID"], 8) tags["DONATIONTYPERECENT" + dname] = d["DONATIONNAME"] tags["DONATIONDATERECENT" + dname] = python2display(l, d["DATE"]) tags["DONATIONDATEDUERECENT" + dname] = python2display(l, d["DATEDUE"]) tags["DONATIONAMOUNTRECENT" + dname] = format_currency_no_symbol(l, d["DONATION"]) tags["DONATIONCOMMENTSRECENT" + dname] = d["COMMENTS"] tags["DONATIONGIFTAIDRECENT" + dname] = d["ISGIFTAID"] == 1 and _("Yes", l) or _("No", l) # Logs logasc = log.get_logs(dbo, log.ANIMAL, int(a["ID"]), 0, log.ASCENDING) logdesc = log.get_logs(dbo, log.ANIMAL, int(a["ID"]), 0, log.DESCENDING) for idx in range(1, 101): tags["LOGNAME" + str(idx)] = "" tags["LOGDATE" + str(idx)] = "" tags["LOGCOMMENTS" + str(idx)] = "" tags["LOGNAMELAST" + str(idx)] = "" tags["LOGDATELAST" + str(idx)] = "" tags["LOGCOMMENTSLAST" + str(idx)] = "" idx = 1 for o in logasc: tags["LOGNAME" + str(idx)] = o["LOGTYPENAME"] tags["LOGDATE" + str(idx)] = python2display(l, o["DATE"]) tags["LOGCOMMENTS" + str(idx)] = o["COMMENTS"] idx += 1 idx = 1 uniquetypes = {} recentgiven = {} for o in logdesc: tags["LOGNAMELAST" + str(idx)] = o["LOGTYPENAME"] tags["LOGDATELAST" + str(idx)] = python2display(l, o["DATE"]) tags["LOGCOMMENTSLAST" + str(idx)] = o["COMMENTS"] idx += 1 uniquetypes = {} recentrec = {} # If this is the first of this type of log we've seen, make # some keys based on its name. if not uniquetypes.has_key(o["LOGTYPENAME"]): lname = o["LOGTYPENAME"].upper().replace(" ", "").replace("/", "") uniquetypes[o["LOGTYPENAME"]] = o tags["LOGNAME" + lname] = o["LOGTYPENAME"] tags["LOGDATE" + lname] = python2display(l, o["DATE"]) tags["LOGCOMMENTS" + lname] = o["COMMENTS"] tags["LOGNAMERECENT" + lname] = o["LOGTYPENAME"] tags["LOGDATERECENT" + lname] = python2display(l, o["DATE"]) tags["LOGCOMMENTSRECENT" + lname] = o["COMMENTS"] return tags
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)