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(asm3.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 %s" % (m.lspeciesname, m.lbreedname, m.lmicrochip), \ 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>" % _("Microchip", 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(m.fmicrochip)) h.append(td(str(m.matchpoints) + "%")) h.append("</tr>") h.append("</tr></table>") else: h.append(p(_("No matches found.", l))) h.append(asm3.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, dbo.now()), "incidenttime": format_time_now(dbo.timezone), "incidenttype": asm3.configuration.default_incident(dbo), "calldate": python2display(l, dbo.now()), "calltime": format_time_now(dbo.timezone), "calltaker": username } return insert_animalcontrol_from_form(dbo, asm3.utils.PostedData(d, dbo.locale), username)
def merge_values_for_link(dbo, post, linkid, linktype="animal"): """ Saves incoming additional field values. Only updates the additional fields that are present in the post object and leaves the rest alone. It will only update a field if it has a value. This function is aimed at areas that merge into existing records, such as online forms and CSV imports. linkid: The link to the parent record linktype: The class of parent record Keys of either a.MANDATORY.ID can be used (ASM internal forms) or keys of the form additionalFIELDNAME (ASM online forms) """ for f in get_field_definitions(dbo, linktype): key = "a.%s.%s" % (f.mandatory, f.id) key2 = "additional%s" % f.fieldname if key2 in post: key = key2 if key in post: val = post[key] if val == "": continue if f.fieldtype == YESNO: val = str(post.boolean(key)) elif f.fieldtype == MONEY: val = str(post.integer(key)) elif f.fieldtype == DATE: val = python2display(dbo.locale, post.date(key)) dbo.delete("additional", "LinkID=%s AND AdditionalFieldID=%s" % (linkid, f.ID)) insert_additional(dbo, f.LINKTYPE, linkid, f.ID, val)
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": asm3.configuration.default_type(dbo), "breed1": a["BREEDID"], "breed2": a["BREEDID"], "basecolour": str(a["BASECOLOURID"]), "microchipped": asm3.utils.iif(a["MICROCHIPNUMBER"] is not None and a["MICROCHIPNUMBER"] != "", "1", "0"), "microchipnumber": a["MICROCHIPNUMBER"], "size": asm3.configuration.default_size(dbo), "internallocation": asm3.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 asm3.configuration.manual_codes(dbo): data["sheltercode"] = "FA" + str(aid) data["shortcode"] = "FA" + str(aid) nextid, dummy = asm3.animal.insert_animal_from_form(dbo, asm3.utils.PostedData(data, l), username) return nextid
def save_values_for_link(dbo, post, username, 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) """ dbo.delete( "additional", "LinkType IN (%s) AND LinkID=%s" % (clause_for_linktype(linktype), linkid)) audits = [] 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) audits.append("%s='%s'" % (f.FIELDNAME, 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: val = python2display(dbo.locale, post.date(key)) audits.append("%s='%s'" % (f.FIELDNAME, val)) insert_additional(dbo, f.LINKTYPE, linkid, f.ID, val) if len(audits) > 0: asm3.audit.edit(dbo, username, "additional", 0, "%s=%s " % (table_for_linktype(linktype), linkid), ", ".join(audits))
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 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 asm3.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_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(asm3.configuration.waiting_list_default_urgency(dbo)) } nextid = asm3.waitinglist.insert_waitinglist_from_form(dbo, asm3.utils.PostedData(data, dbo.locale), username) return nextid
def create_animal(dbo, username, wlid): """ Creates an animal record from a waiting list entry with the id given """ l = dbo.locale a = dbo.first_row( dbo.query("SELECT * FROM animalwaitinglist WHERE ID = ?", [wlid])) data = { "animalname": _("Waiting List {0}", l).format(wlid), "markings": str(a["ANIMALDESCRIPTION"]), "reasonforentry": str(a["REASONFORWANTINGTOPART"]), "species": str(a["SPECIESID"]), "hiddenanimaldetails": str(a["COMMENTS"]), "broughtinby": str(a["OWNERID"]), "originalowner": str(a["OWNERID"]), "animaltype": asm3.configuration.default_type(dbo), "entryreason": asm3.configuration.default_entry_reason(dbo), "breed1": asm3.configuration.default_breed(dbo), "breed2": asm3.configuration.default_breed(dbo), "basecolour": asm3.configuration.default_colour(dbo), "size": asm3.configuration.default_size(dbo), "internallocation": asm3.configuration.default_location(dbo), "dateofbirth": python2display(l, subtract_years(now(dbo.timezone))), "estimateddob": "1" } # If we aren't showing the time brought in, set it to midnight if not asm3.configuration.add_animals_show_time_brought_in(dbo): data["timebroughtin"] = "00:00:00" # If we're creating shelter codes manually, we need to put something unique # in there for now. Use the id if asm3.configuration.manual_codes(dbo): data["sheltercode"] = "WL" + str(wlid) data["shortcode"] = "WL" + str(wlid) nextid, code = asm3.animal.insert_animal_from_form( dbo, asm3.utils.PostedData(data, l), username) # Now that we've created our animal, we should remove this entry from the waiting list dbo.update( "animalwaitinglist", wlid, { "DateRemovedFromList": dbo.today(), "ReasonForRemoval": _("Moved to animal record {0}", l).format(code) }, username) # If there were any logs and media entries on the waiting list, create them on the animal # Media for me in dbo.query( "SELECT * FROM media WHERE LinkTypeID = ? AND LinkID = ?", (asm3.media.WAITINGLIST, wlid)): ext = me.medianame ext = ext[ext.rfind("."):].lower() mediaid = dbo.get_id("media") medianame = "%d%s" % (mediaid, ext) dbo.insert( "media", { "ID": mediaid, "DBFSID": 0, "MediaSize": 0, "MediaName": medianame, "MediaMimeType": asm3.media.mime_type(medianame), "MediaType": me.mediatype, "MediaNotes": me.medianotes, "WebsitePhoto": me.websitephoto, "WebsiteVideo": me.websitevideo, "DocPhoto": me.docphoto, "ExcludeFromPublish": me.excludefrompublish, # ASM2_COMPATIBILITY "NewSinceLastPublish": 1, "UpdatedSinceLastPublish": 0, # ASM2_COMPATIBILITY "LinkID": nextid, "LinkTypeID": asm3.media.ANIMAL, "Date": me.date, "CreatedDate": me.createddate, "RetainUntil": me.retainuntil }, generateID=False) # Now clone the dbfs item pointed to by this media item if it's a file if me.mediatype == asm3.media.MEDIATYPE_FILE: filedata = asm3.dbfs.get_string(dbo, me.medianame) dbfsid = asm3.dbfs.put_string(dbo, medianame, "/animal/%d" % nextid, filedata) dbo.execute( "UPDATE media SET DBFSID = ?, MediaSize = ? WHERE ID = ?", (dbfsid, len(filedata), mediaid)) # Logs for lo in dbo.query("SELECT * FROM log WHERE LinkType = ? AND LinkID = ?", (asm3.log.WAITINGLIST, wlid)): dbo.insert( "log", { "LinkID": nextid, "LinkType": asm3.log.ANIMAL, "LogTypeID": lo.LOGTYPEID, "Date": lo.DATE, "Comments": lo.COMMENTS }, username) return nextid
def handler(post, path, remoteip, referer, querystring): """ Handles the various service method types. post: The GET/POST parameters path: The current system path/code.PATH remoteip: The IP of the caller referer: The referer HTTP header querystring: The complete querystring return value is a tuple containing MIME type, max-age, content """ # Get service parameters account = post["account"] username = post["username"] password = post["password"] method = post["method"] animalid = post.integer("animalid") formid = post.integer("formid") mediaid = post.integer("mediaid") seq = post.integer("seq") title = post["title"] strip_personal = post.integer("sensitive") == 0 # If this method is in the cache protected list, only use # whitelisted parameters for the key to prevent callers # cache-busting by adding junk parameters cache_key = querystring.replace(" ", "") if method in CACHE_PROTECT_METHODS: cache_key = safe_cache_key(method, cache_key) # Do we have a cached response for these parameters? cached_response = get_cached_response(cache_key, account) if cached_response is not None: asm3.al.debug( "cache hit: %s (%d bytes)" % (cache_key, len(cached_response[3])), "service.handler", account) return cached_response # Are we dealing with multiple databases, but no account was specified? if account == "" and MULTIPLE_DATABASES: return ("text/plain", 0, 0, "ERROR: No database/alias specified") # Is flood protection activated for this method? if method in FLOOD_PROTECT_METHODS: flood_protect(method, remoteip) dbo = asm3.db.get_database(account) if dbo.database in asm3.db.ERROR_VALUES: asm3.al.error( "auth failed - invalid smaccount %s from %s (%s)" % (account, remoteip, dbo.database), "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid database (%s)" % dbo.database) # If the database has disabled the service API, stop now if not asm3.configuration.service_enabled(dbo): asm3.al.error("Service API is disabled (%s)" % method, "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Service API is disabled") # Do any database updates need doing in this db? dbo.installpath = path if asm3.dbupdate.check_for_updates(dbo): asm3.dbupdate.perform_updates(dbo) # Does the method require us to authenticate? If so, do it. user = None securitymap = "" if method in AUTH_METHODS: # If the database has authenticated service methods disabled, stop now if not asm3.configuration.service_auth_enabled(dbo): asm3.al.error( "Service API for auth methods is disabled (%s)" % method, "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Service API for authenticated methods is disabled") user = asm3.users.authenticate(dbo, username, password) if user is None: asm3.al.error( "auth failed - %s/%s is not a valid username/password from %s" % (username, password, remoteip), "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid username and password") securitymap = asm3.users.get_security_map(dbo, user["USERNAME"]) # Get the preferred locale and timezone for the site l = asm3.configuration.locale(dbo) dbo.locale = l dbo.timezone = asm3.configuration.timezone(dbo) dbo.timezone_dst = asm3.configuration.timezone_dst(dbo) asm3.al.info("call @%s --> %s [%s]" % (username, method, querystring), "service.handler", dbo) if method == "animal_image": hotlink_protect("animal_image", referer) if asm3.utils.cint(animalid) == 0: asm3.al.error( "animal_image failed, %s is not an animalid" % str(animalid), "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid animalid") else: dummy, data = asm3.media.get_image_file_data( dbo, "animal", asm3.utils.cint(animalid), seq) if data == "NOPIC": dummy, data = asm3.media.get_image_file_data(dbo, "nopic", 0) return set_cached_response(cache_key, account, "image/jpeg", 86400, 3600, data) elif method == "animal_thumbnail": if asm3.utils.cint(animalid) == 0: asm3.al.error( "animal_thumbnail failed, %s is not an animalid" % str(animalid), "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid animalid") else: dummy, data = asm3.media.get_image_file_data( dbo, "animalthumb", asm3.utils.cint(animalid), seq) if data == "NOPIC": dummy, data = asm3.media.get_image_file_data(dbo, "nopic", 0) return set_cached_response(cache_key, account, "image/jpeg", 86400, 3600, data) elif method == "animal_view": if asm3.utils.cint(animalid) == 0: asm3.al.error( "animal_view failed, %s is not an animalid" % str(animalid), "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid animalid") else: return set_cached_response( cache_key, account, "text/html", 86400, 120, asm3.publishers.html.get_animal_view( dbo, asm3.utils.cint(animalid))) elif method == "animal_view_adoptable_js": return set_cached_response( cache_key, account, "application/javascript", 10800, 600, asm3.publishers.html.get_animal_view_adoptable_js(dbo)) elif method == "animal_view_adoptable_html": return set_cached_response( cache_key, account, "text/html", 86400, 120, asm3.publishers.html.get_animal_view_adoptable_html(dbo)) elif method == "checkout": processor = asm3.financial.get_payment_processor( dbo, post["processor"]) if not processor.validatePaymentReference(post["payref"]): return ("text/plain", 0, 0, "ERROR: Invalid payref") if processor.isPaymentReceived(post["payref"]): return ("text/plain", 0, 0, "ERROR: Expired payref") return_url = post["return"] or asm3.configuration.payment_return_url( dbo) return set_cached_response( cache_key, account, "text/html", 15, 15, processor.checkoutPage(post["payref"], return_url, title)) elif method == "checkout_adoption": if post["token"] == "": raise asm3.utils.ASMError( "method checkout_adoption requires a valid token") elif post["sig"] == "": return set_cached_response( cache_key, account, "text/html", 120, 120, checkout_adoption_page(dbo, post["token"])) else: return ("text/plain", 0, 0, checkout_adoption_post(dbo, post)) elif method == "dbfs_image": hotlink_protect("dbfs_image", referer) return set_cached_response( cache_key, account, "image/jpeg", 86400, 86400, asm3.utils.iif(title.startswith("/"), asm3.dbfs.get_string_filepath(dbo, title), asm3.dbfs.get_string(dbo, title))) elif method == "document_repository": return set_cached_response( cache_key, account, asm3.media.mime_type(asm3.dbfs.get_name_for_id(dbo, mediaid)), 86400, 86400, asm3.dbfs.get_string_id(dbo, mediaid)) elif method == "extra_image": hotlink_protect("extra_image", referer) return set_cached_response( cache_key, account, "image/jpeg", 86400, 86400, asm3.dbfs.get_string(dbo, title, "/reports")) elif method == "media_image": hotlink_protect("media_image", referer) return set_cached_response( cache_key, account, "image/jpeg", 86400, 86400, asm3.dbfs.get_string_id( dbo, dbo.query_int("select dbfsid from media where id = ?", [mediaid]))) elif method == "json_adoptable_animal": if asm3.utils.cint(animalid) == 0: asm3.al.error( "json_adoptable_animal failed, %s is not an animalid" % str(animalid), "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid animalid") else: asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.publishers.base.get_animal_data( dbo, None, asm3.utils.cint(animalid), include_additional_fields=True) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.utils.json(rs)) elif method == "html_adoptable_animals": return set_cached_response(cache_key, account, "text/html", 600, 600, \ asm3.publishers.html.get_adoptable_animals(dbo, style=post["template"], \ speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid"), \ locationid=post.integer("locationid"), underweeks=post.integer("underweeks"), \ overweeks=post.integer("overweeks"))) elif method == "html_adopted_animals": return set_cached_response(cache_key, account, "text/html", 10800, 1800, \ asm3.publishers.html.get_adopted_animals(dbo, daysadopted=post.integer("days"), style=post["template"], \ speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid"))) elif method == "html_deceased_animals": return set_cached_response(cache_key, account, "text/html", 10800, 1800, \ asm3.publishers.html.get_deceased_animals(dbo, daysdeceased=post.integer("days"), style=post["template"], \ speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid"))) elif method == "html_flagged_animals": if post["flag"] == "": asm3.al.error("html_flagged_animals requested with no flag.", "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid flag") return set_cached_response(cache_key, account, "text/html", 1800, 1800, \ asm3.publishers.html.get_flagged_animals(dbo, style=post["template"], \ speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid"), flag=post["flag"], allanimals=post.integer("all"))) elif method == "html_held_animals": return set_cached_response(cache_key, account, "text/html", 1800, 1800, \ asm3.publishers.html.get_held_animals(dbo, style=post["template"], \ speciesid=post.integer("speciesid"), animaltypeid=post.integer("animaltypeid"))) elif method == "json_adoptable_animals_xp": rs = strip_personal_data( asm3.publishers.base.get_animal_data( dbo, None, include_additional_fields=True)) return set_cached_response(cache_key, account, "application/json", 600, 600, asm3.utils.json(rs)) elif method == "json_adoptable_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.publishers.base.get_animal_data( dbo, None, include_additional_fields=True) if strip_personal: rs = strip_personal_data(rs) return set_cached_response(cache_key, account, "application/json", 600, 600, asm3.utils.json(rs)) elif method == "jsonp_adoptable_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.publishers.base.get_animal_data( dbo, None, include_additional_fields=True) if strip_personal: rs = strip_personal_data(rs) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(rs))) elif method == "xml_adoptable_animal": if asm3.utils.cint(animalid) == 0: asm3.al.error( "xml_adoptable_animal failed, %s is not an animalid" % str(animalid), "service.handler", dbo) return ("text/plain", 0, 0, "ERROR: Invalid animalid") else: asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.publishers.base.get_animal_data( dbo, None, asm3.utils.cint(animalid), include_additional_fields=True) return set_cached_response(cache_key, account, "application/xml", 600, 600, asm3.html.xml(rs)) elif method == "xml_adoptable_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.publishers.base.get_animal_data( dbo, None, include_additional_fields=True) if strip_personal: rs = strip_personal_data(rs) return set_cached_response(cache_key, account, "application/xml", 600, 600, asm3.html.xml(rs)) elif method == "json_found_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_FOUND_ANIMAL) rs = asm3.lostfound.get_foundanimal_last_days(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.utils.json(rs)) elif method == "jsonp_found_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_FOUND_ANIMAL) rs = asm3.lostfound.get_foundanimal_last_days(dbo) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(rs))) elif method == "xml_found_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_FOUND_ANIMAL) rs = asm3.lostfound.get_foundanimal_last_days(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.html.xml(rs)) elif method == "json_held_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.animal.get_animals_hold(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.utils.json(rs)) elif method == "xml_held_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.animal.get_animals_hold(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.html.xml(rs)) elif method == "jsonp_held_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.animal.get_animals_hold(dbo) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(rs))) elif method == "json_lost_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_LOST_ANIMAL) rs = asm3.lostfound.get_lostanimal_last_days(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.utils.json(rs)) elif method == "jsonp_lost_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_LOST_ANIMAL) rs = asm3.lostfound.get_lostanimal_last_days(dbo) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(rs))) elif method == "xml_lost_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_LOST_ANIMAL) rs = asm3.lostfound.get_lostanimal_last_days(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.html.xml(rs)) elif method == "json_recent_adoptions": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.movement.get_recent_adoptions(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.utils.json(rs)) elif method == "jsonp_recent_adoptions": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.movement.get_recent_adoptions(dbo) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(rs))) elif method == "xml_recent_adoptions": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) rs = asm3.movement.get_recent_adoptions(dbo) return set_cached_response(cache_key, account, "application/xml", 3600, 3600, asm3.html.xml(rs)) elif method == "html_report": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_REPORT) crid = asm3.reports.get_id(dbo, title) p = asm3.reports.get_criteria_params(dbo, crid, post) rhtml = asm3.reports.execute(dbo, crid, username, p) rhtml = asm3.utils.fix_relative_document_uris(dbo, rhtml) return set_cached_response(cache_key, account, "text/html", 600, 600, rhtml) elif method == "csv_mail" or method == "csv_report": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_REPORT) crid = asm3.reports.get_id(dbo, title) p = asm3.reports.get_criteria_params(dbo, crid, post) rows, cols = asm3.reports.execute_query(dbo, crid, username, p) mcsv = asm3.utils.csv(l, rows, cols, True) return set_cached_response(cache_key, account, "text/csv", 600, 600, mcsv) elif method == "json_report" or method == "json_mail": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_REPORT) crid = asm3.reports.get_id(dbo, title) p = asm3.reports.get_criteria_params(dbo, crid, post) rows, cols = asm3.reports.execute_query(dbo, crid, username, p) return set_cached_response(cache_key, account, "application/json", 600, 600, asm3.utils.json(rows)) elif method == "jsonp_report" or method == "jsonp_mail": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_REPORT) crid = asm3.reports.get_id(dbo, title) p = asm3.reports.get_criteria_params(dbo, crid, post) rows, cols = asm3.reports.execute_query(dbo, crid, username, p) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(rows))) elif method == "jsonp_recent_changes": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) sa = asm3.animal.get_recent_changes(dbo) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(sa))) elif method == "json_recent_changes": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) sa = asm3.animal.get_recent_changes(dbo) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.utils.json(sa)) elif method == "xml_recent_changes": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) sa = asm3.animal.get_recent_changes(dbo) return set_cached_response(cache_key, account, "application/xml", 3600, 3600, asm3.html.xml(sa)) elif method == "jsonp_shelter_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) sa = asm3.animal.get_shelter_animals(dbo) if strip_personal: sa = strip_personal_data(sa) return ("application/javascript", 0, 0, "%s(%s);" % (post["callback"], asm3.utils.json(sa))) elif method == "json_shelter_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) sa = asm3.animal.get_shelter_animals(dbo) if strip_personal: sa = strip_personal_data(sa) return set_cached_response(cache_key, account, "application/json", 3600, 3600, asm3.utils.json(sa)) elif method == "xml_shelter_animals": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) sa = asm3.animal.get_shelter_animals(dbo) if strip_personal: sa = strip_personal_data(sa) return set_cached_response(cache_key, account, "application/xml", 3600, 3600, asm3.html.xml(sa)) elif method == "rss_timeline": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.VIEW_ANIMAL) return set_cached_response(cache_key, account, "application/rss+xml", 3600, 3600, asm3.html.timeline_rss(dbo)) elif method == "upload_animal_image": asm3.users.check_permission_map(l, user["SUPERUSER"], securitymap, asm3.users.ADD_MEDIA) asm3.media.attach_file_from_form(dbo, username, asm3.media.ANIMAL, int(animalid), post) return ("text/plain", 0, 0, "OK") elif method == "online_form_html": if formid == 0: raise asm3.utils.ASMError( "method online_form_html requires a valid formid") return set_cached_response( cache_key, account, "text/html; charset=utf-8", 120, 120, asm3.onlineform.get_onlineform_html(dbo, formid)) elif method == "online_form_json": if formid == 0: raise asm3.utils.ASMError( "method online_form_json requires a valid formid") return set_cached_response( cache_key, account, "application/json; charset=utf-8", 30, 30, asm3.onlineform.get_onlineform_json(dbo, formid)) elif method == "online_form_post": asm3.onlineform.insert_onlineformincoming_from_form( dbo, post, remoteip) redirect = post["redirect"] if redirect == "": redirect = BASE_URL + "/static/pages/form_submitted.html" return ("redirect", 0, 0, redirect) elif method == "sign_document": if formid == 0: raise asm3.utils.ASMError( "method sign_document requires a valid formid") if post["sig"] == "": m = asm3.media.get_media_by_id(dbo, formid) if m is None: raise asm3.utils.ASMError("invalid link") token = asm3.utils.md5_hash_hex("%s%s" % (m.ID, m.LINKID)) if token != post["token"]: raise asm3.utils.ASMError("invalid token") return set_cached_response( cache_key, account, "text/html", 2, 2, sign_document_page(dbo, formid, post["email"])) else: signdate = "%s %s" % (python2display( l, dbo.now()), format_time(dbo.now())) asm3.media.sign_document(dbo, "service", formid, post["sig"], signdate, "signemail") asm3.media.create_log(dbo, "service", formid, "ES02", _("Document signed", l)) if post.boolean("sendsigned"): m = asm3.media.get_media_by_id(dbo, formid) if m is None: raise asm3.utils.ASMError("cannot find %s" % formid) content = asm3.utils.bytes2str( asm3.dbfs.get_string(dbo, m.MEDIANAME)) contentpdf = asm3.utils.html_to_pdf(dbo, content) attachments = [("%s.pdf" % m.ID, "application/pdf", contentpdf) ] fromaddr = asm3.configuration.email(dbo) asm3.utils.send_email(dbo, fromaddr, post["email"], "", "", _("Signed Document", l), m.MEDIANOTES, "plain", attachments) return ("text/plain", 0, 0, "OK") else: asm3.al.error("invalid method '%s'" % method, "service.handler", dbo) raise asm3.utils.ASMError("Invalid method '%s'" % method)
def checkout_adoption_post(dbo, post): """ Called by the adoption checkout frontend with the document signature and donation amount. Handles the document signing, triggers creation of the payment records, etc. Returns the URL needed to redirect to the payment processor to complete payment. """ l = dbo.locale co = asm3.cachedisk.get(post["token"], dbo.database) if co is None: raise asm3.utils.ASMError("invalid token") mediaid = co["mediaid"] donationamt = post.integer("donationamt") * 100 # Sign the docs if they haven't been done already if not asm3.media.has_signature(dbo, mediaid): signdate = "%s %s" % (python2display( l, dbo.now()), format_time(dbo.now())) asm3.media.sign_document(dbo, "service", mediaid, post["sig"], signdate, "signemail") if post.boolean("sendsigned"): m = asm3.media.get_media_by_id(dbo, mediaid) if m is None: raise asm3.utils.ASMError("cannot find %s" % mediaid) content = asm3.utils.bytes2str( asm3.dbfs.get_string(dbo, m.MEDIANAME)) contentpdf = asm3.utils.html_to_pdf(dbo, content) attachments = [("%s.pdf" % m.ID, "application/pdf", contentpdf)] asm3.utils.send_email(dbo, asm3.configuration.email(dbo), co["email"], "", "", _("Signed Document", l), m.MEDIANOTES, "plain", attachments) # Create the due payment records if they haven't been done already, along with a receipt/payref if co["paymentfeeid"] == 0: co["paymentprocessor"] = asm3.configuration.adoption_checkout_processor( dbo) co["receiptnumber"] = asm3.financial.get_next_receipt_number( dbo) # Both go on the same receipt co["payref"] = "%s-%s" % (co["personcode"], co["receiptnumber"]) # Adoption Fee co["paymentfeeid"] = asm3.financial.insert_donation_from_form( dbo, "checkout", asm3.utils.PostedData( { "person": str(co["personid"]), "animal": str(co["animalid"]), "movement": str(co["movementid"]), "type": asm3.configuration.adoption_checkout_feeid(dbo), "payment": asm3.configuration.adoption_checkout_payment_method(dbo), "amount": co["fee"], "due": python2display(l, dbo.now()), "receiptnumber": co["receiptnumber"], "giftaid": str(co["giftaid"]) }, l)) # Donation (not linked to movement on purpose to avoid showing on adoption fee reports) if donationamt > 0: co["paymentdonid"] = asm3.financial.insert_donation_from_form( dbo, "checkout", asm3.utils.PostedData( { "person": str(co["personid"]), "animal": str(co["animalid"]), "type": str( asm3.configuration.adoption_checkout_donationid( dbo)), "payment": str( asm3.configuration. adoption_checkout_payment_method(dbo)), "amount": str(donationamt), "due": python2display(l, dbo.now()), "receiptnumber": co["receiptnumber"], "giftaid": str(co["giftaid"]) }, l)) # Update the cache entry asm3.cachedisk.put(post["token"], dbo.database, co, 86400 * 2) elif co["paymentdonid"] > 0 and donationamt > 0: # payments have already been created, must be a user revisiting the checkout. # update their donation amount in case they made a different choice this time. dbo.update("ownerdonation", co["paymentdonid"], {"Donation": donationamt}, "checkout") elif co["paymentdonid"] > 0 and donationamt == 0: # The user has changed their voluntary donation amount to 0 - delete it dbo.delete("ownerdonation", co["paymentdonid"], "checkout") # Construct the payment checkout URL params = { "account": dbo.database, "method": "checkout", "processor": co["paymentprocessor"], "payref": co["payref"], "title": _("{0}: Adoption fee") + asm3.utils.iif(co["paymentdonid"] != "0", _(" + donation"), "") } url = "%s?%s" % (SERVICE_URL, asm3.utils.urlencode(params)) return url