Beispiel #1
0
        /// <summary>
        /// Returns the contiguous acres associated with the user. This method does NOT
        /// populate the contiguous acres' wells property.
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public List<ContiguousAcres> GetContiguousAcres(int userId, bool includeNonOwned)
        {
            Param[] nonOwnedCAParams = new Param[] {};
            string[] nonOwnedCAParamNames = null;
            if (includeNonOwned) {
                var caIds = new PropertyDalc().GetAssociatedCAIds(userId);
                if (caIds.Count() == 0) {
                    // No associations exist; don't even try to retrieve them.
                    includeNonOwned = false;
                } else {
                    nonOwnedCAParams = ParameterizeInClause("caId", out nonOwnedCAParamNames, caIds.ToArray());
                }
            }

            return ExecuteDataTable(@"
            select
            ca.OBJECTID,
            ca.caID,
            ca.area as area_m2,
            ca.admin_area as area_acres,
            ca.description,
            ca.approved,
            ca.actingId
            from HP_CONTIGUOUS_ACRES" + dbTableSuffix + @" ca
            where
            (ca.actingId = @id" + (includeNonOwned
                        ? " or ca.caId in (" + string.Join(", ", nonOwnedCAParamNames) + "))"
                        : ")") + @"
            and isnull(ca.Deletion, '') <> 'True';",
                        new Param[] { new Param("@id", userId) }.Concat(nonOwnedCAParams).ToArray()
                ).AsEnumerable().Select(row => GetCAFromDataRow(row)).ToList();
        }
        /// <summary>
        /// Looks up the username (email address) of the given user, 
        /// and also finds any associated property descriptions (via
        /// either ownership or authorized producership) and returns
        /// the entire result as a JSON array.
        /// 
        /// In the event of an "act as" situation, the data returned
        /// will be for the _acted as_ user, with the sole exception
        /// of "data.actualClientId", which will be the client ID of
        /// the true (admin) user.
        /// </summary>
        /// <param name="ticket">(string) The FormsAuthentication ticket to decrypt.</param>
        /// <returns>(JSON) A JSON object containing username and any associated property descriptions.</returns>
        public JsonResult GetUserData(string ticket)
        {
            /* Sample result format
            {
            status:{success:true, errors:[]},
            data: {
            ActualClientId:1234,
            ActingAsClientId:5678,
            EmailAddress:"*****@*****.**",
            property_descriptions: [
                { OwnerName:"Matt", PropertyDesc:"123 Fifth Ave.", PropId:123, IsCurrentUserOwner:true },
                { OwnerName:"Meng", PropertyDsec:"555 wherever st.", PropId:555, IsCurrentUserOwner:false }
            ],
            VisibleContiguousAcresIds:[4,2,1,662,124]
            }
            }
             */
            bool success = true;
            var errors = new List<string>();
            List<PropertyDescription> propDescs = null;
            User actualUser = null, actingUser = null;
            int[] caIds = new int[] { };
            try {
                actualUser = actingUser = GetUserFromAuthTicket(ticket);
                if (actualUser != null) {
                    // If this user is an admin and is acting for someone else,
                    // pull that someone else's info instead.
                    if (actualUser.IsAdmin && actualUser.ActingAsUserId.HasValue) {
                        actingUser = new UserDalc().GetUser(actualUser.ActingAsUserId.Value);
                    }
                    // Pull property descriptions for this user, including owned and
                    // authorized properties
                    propDescs = (from pd in new UserDalc().GetAssociatedProperties(actingUser.Id)
                                 select new PropertyDescription(pd)).ToList();

                    // Retrieve the contiguous acres IDs that this user is permitted to see,
                    // namely, the ones associated with properties that are associated with
                    // the user's account, PLUS the contiguous acres definitions the user
                    // created (regardless of association).
                    caIds = new PropertyDalc().GetContiguousAcresIds(actingUser.Id, (from pd in propDescs select new Tuple<string, string>(pd.ParcelId, pd.County)));
                }

            } catch (Exception ex) {
                success = false;
                errors.Add("Exception occurred: " + ex.Message);
            }

            object ret;

            if (actualUser == null || actingUser == null) {
                ret = new JsonResponse(false, "No such user exists.");
            } else {
                var d = new {
                    ActualUserId = actualUser.Id,
                    ActingUserId = actingUser.Id,
                    DisplayName = actingUser.DisplayName,
                    EmailAddress = actingUser.Email,
                    PropertyDescriptions = propDescs.OrderBy(x => x.OwnerName).ToArray() ?? new PropertyDescription[] {},
                    VisibleContiguousAcresIds = caIds,
                    PhoneNumber = string.Join("; ", actingUser.PhoneNumbers)
                };
                ret = new JsonResponse(success, (object)d, errors.ToArray());
            }

            return Json(ret, JsonRequestBehavior.AllowGet);
        }
        public JsonResult ChangeUserRole(string authTicket, int actingUserId, int actualUserId, PropertyRole? role, string parcelId, string county, DisclaimerDataType? productionTypes)
        {
            try {
                List<string> errors = new List<string>();
                Func<JsonResult> jsonStatus = () => {
                    return Json(new JsonResponse(errors.Count == 0, errors.ToArray()));
                };

                // 0. Verify that all required data is present.
                if (actualUserId < 1) {
                    errors.Add("Parameter 'actualUserId' is required and must be greater than 0.");
                }
                if (actingUserId < 1) {
                    errors.Add("Parameter 'actingUserId' is required and must be greater than 0.");
                }
                if (string.IsNullOrWhiteSpace(parcelId)) {
                    errors.Add("Parameter 'parcelId' is required and cannot be blank.");
                }
                if (string.IsNullOrWhiteSpace(county)) {
                    errors.Add("Parameter 'county' is required and cannot be blank.");
                }

                if (!role.HasValue) {
                    // Default to operator
                    role = PropertyRole.authorized_producer;
                }
                if (!Enum.IsDefined(typeof(PropertyRole), role)) {
                    errors.Add("Invalid property role: " + role.ToString());
                }

                if (!productionTypes.HasValue) {
                    productionTypes = DisclaimerDataType.agriculture;
                }
                // Check for validity of production types - this is a flags enum,
                // so valid values are anything > 0 and < (sum of all values)
                var maxVal = Enum.GetValues(typeof(DisclaimerDataType)).Cast<int>().Sum();
                if (productionTypes < 0 || (int)productionTypes > maxVal || (productionTypes == 0 && role != PropertyRole.installer)) {
                    errors.Add("Invalid production type: " + productionTypes.ToString());
                }

                if (errors.Count > 0) {
                    return jsonStatus();
                }

                var udalc = new UserDalc();
                User actualUser = GetUserFromAuthTicket(authTicket);
                User actingUser = udalc.GetUser(actingUserId);
                if (actualUser == null) {
                    errors.Add("Unable to find user account based on provided auth ticket.");
                }
                if (actingUser == null) {
                    errors.Add("Unable to find user account corresponding to actingUserId == " + actingUserId.ToString());
                }
                if (errors.Count > 0) {
                    return jsonStatus();
                }

                if (actualUser.Id != actualUserId) {
                    // Bizarre - the auth ticket is not for the specified user id.
                    errors.Add("Unauthorized action: The specified authentication ticket does not match the provided actual user ID.");
                    return jsonStatus();
                }

                // 1. Ensure actual user has permission to pose as acting user
                if (actualUserId != actingUserId && !actualUser.IsAdmin) {
                    errors.Add("Unauthorized action: You do not have permission to act for that user.");
                    return jsonStatus();
                }

                var propDalc = new PropertyDalc();

                // 2. Verify that the property matches values in AppraisalRolls.
                if (!propDalc.DoesPropertyExist(parcelId, county)) {
                    errors.Add(string.Format("Unable to find a matching appraisal roll record for parcel ID '{0}', county '{1}'", parcelId, county));
                    return jsonStatus();
                }

                // 3. If the property has not been associated with the user account,
                //		return an error message to that effect.
                int clientPropertyId;
                if (!propDalc.IsPropertyAssociated(actingUserId, parcelId, county, out clientPropertyId)) {
                    errors.Add("The specified property is not associated with your account. Please first add the property to your account.");
                    return jsonStatus();
                }

                propDalc.ChangePropertyRoleAndProductionType(actingUser, clientPropertyId, role.Value, productionTypes.Value);

                return jsonStatus();
            } catch (Exception ex) {
                return Json(new JsonResponse(false, ex.Message));
            }
        }
        /// <summary>
        /// Associates a property with the user account specified by actingUserId.
        /// </summary>
        /// <param name="actualUserId">(int) The actual logged-in user.</param>
        /// <param name="actingUserId">
        ///		(int) The "act-as" user (may be the same as the logged-in user; 
        ///		actualUser must have privileges to act-as if this ID is different).
        ///		This is the user account the property will be associated with.
        ///	</param>
        /// <param name="role">(PropertyRole) The acting user's role in relation to the property.</param>
        /// <param name="parcelId">(string) The parcel ID (PropertyNumber) corresponding to the property in appraisal roll records.</param>
        /// <param name="county">(string) The county of the </param>
        /// <param name="productionTypes"></param>
        /// <returns></returns>
        public JsonResult AddProperty(string authTicket, int actualUserId, int actingUserId, PropertyRole role, string parcelId, string county, DisclaimerDataType productionTypes)
        {
            var errors = new List<string>();
            Func<JsonResult> jsonStatus = () => {
                return Json(new JsonResponse(errors.Count == 0, errors.ToArray()));
            };

            // 0. Verify that all required data is present.
            if (actualUserId < 1) {
                errors.Add("Parameter 'actualUserId' is required and must be greater than 0.");
            }
            if (actingUserId < 1) {
                errors.Add("Parameter 'actingUserId' is required and must be greater than 0.");
            }
            if (string.IsNullOrWhiteSpace(parcelId)) {
                errors.Add("Parameter 'parcelId' is required and cannot be blank.");
            }
            if (string.IsNullOrWhiteSpace(county)) {
                errors.Add("Parameter 'county' is required and cannot be blank.");
            }
            if (!Enum.IsDefined(typeof(PropertyRole), role)) {
                errors.Add("Invalid property role: " + role.ToString());
            }
            // Check for validity of production types - this is a flags enum,
            // so valid values are anything > 0 and < (sum of all values)
            var maxVal = Enum.GetValues(typeof(DisclaimerDataType)).Cast<int>().Sum();
            if (productionTypes < 0 || (int)productionTypes > maxVal || (productionTypes == 0 && role != PropertyRole.installer)) {
                errors.Add("Invalid production type: " + productionTypes.ToString());
            }

            if (errors.Count > 0) {
                return jsonStatus();
            }

            var udalc = new UserDalc();
            User actualUser = GetUserFromAuthTicket(authTicket);
            User actingUser = udalc.GetUser(actingUserId);
            if (actualUser == null) {
                errors.Add("Unable to find user account based on provided auth ticket.");
            }
            if (actingUser == null) {
                errors.Add("Unable to find user account corresponding to actingUserId == " + actingUserId.ToString());
            }
            if (errors.Count > 0) {
                return jsonStatus();
            }

            if (actualUser.Id != actualUserId) {
                // Bizarre - the auth ticket is not for the specified user id.
                errors.Add("Unauthorized action: The specified authentication ticket does not match the provided actual user ID.");
                return jsonStatus();
            }

            // 1. Ensure actual user has permission to pose as acting user
            if (actualUserId != actingUserId && !actualUser.IsAdmin) {
                errors.Add("Unauthorized action: You do not have permission to act for that user.");
                return jsonStatus();
            }

            var propDalc = new PropertyDalc();

            // 2. Verify that the property matches values in AppraisalRolls.
            //    Also check to ensure there is only one property matching this parcel id
            //		and county. (This is in response to a bug in production where there
            //		where many parcelIds of 0 in Cochran county; without this check
            //		some hundreds of records would be associated with the user account.)
            int propertyCount = propDalc.GetPropertyCount(parcelId, county);

            if (propertyCount == 0) {
                errors.Add(string.Format("Unable to find a matching appraisal roll record for parcel ID '{0}', county '{1}'", parcelId, county));
                return jsonStatus();
            } else if (propertyCount > 1) {
                errors.Add(string.Format("Multiple ({0}) records found for parcel ID '{1}', county '{2}'. Cannot add property when duplicates exist.", propertyCount, parcelId, county));
                return jsonStatus();
            }

            // 3. If the property has already been associated with the user account,
            //		return an error message to that effect.
            if (propDalc.IsPropertyAssociated(actingUserId, parcelId, county)) {
                errors.Add("The property is already associated with your account. If you wish to change roles, please delete the existing property from your account and add it again with the different role.");
                return jsonStatus();
            }

            // 4. Create the association.
            propDalc.AssociateProperty(actingUser, new Property(parcelId, county, ""), role, true, productionTypes, false);

            return jsonStatus();
        }
        /// <summary>
        /// Associates contiguous acres with parcel/county combo specified in form.
        /// This method deletes any existing associations, so only those parcels/counties
        /// specified here will be associated after the function returns.
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public JsonResult AssociateContiguousAcresWithParcels(FormCollection form)
        {
            try {
                int OBJECTID = form["contiguousAcresObjectId"].ToInteger();
                int contiguousAcresId = new GisDalc().GetContiguousAcresIdFromOBJECTID(OBJECTID);
                string authTicket = form["authTicket"].GetString();
                var user = GetUserFromAuthTicket(authTicket);

                if (user == null) {
                    return Json(new JsonResponse(false, "Invalid auth ticket - unable to find user."));
                }
                if (contiguousAcresId <= 0) {
                    return Json(new JsonResponse(false, "Unable to find a contiguous acres definition corresponding to OBJECTID " + OBJECTID));
                }

                string[] parcelIds = GetArrayFromFormParameter(form, "parcelIds");
                string[] counties = GetArrayFromFormParameter(form, "counties");

                if (parcelIds.Length == 0 || counties.Length == 0 || parcelIds.Length != counties.Length) {
                    return Json(new JsonResponse(false, string.Format(
                                                            "You must specify at least one parcel and county, and the length of the parcelIds and counties arrays must be the same (parcelIds.Length == {0}, counties.Length == {1})",
                                                            parcelIds.Length,
                                                            counties.Length
                                                    )));
                }

                var propDalc = new PropertyDalc();
                var parcelCounties = new List<Tuple<string, string>>();
                for (int i = 0; i < parcelIds.Length; i++) {
                    parcelCounties.Add(new Tuple<string, string>(parcelIds[i], counties[i]));
                }
                propDalc.AssociateContiguousAcres(contiguousAcresId, parcelCounties, user.Id, user.ActingAsUserId ?? user.Id);

                return Json(new JsonResponse(true));
            } catch (Exception ex) {
                return Json(new JsonResponse(false, ex.Message));
            }
        }