private void AppendInitialiseAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
 {
     foreach (var property in ObjectRecordService.GetFields(recordType))
     {
         var propertyInfo            = ObjectRecordService.GetPropertyInfo(property, recordType);
         var initialiseForAttributes = propertyInfo
                                       .GetCustomAttributes <InitialiseFor>()
                                       .Where(a => a.PropertyDependency == fieldName);
         if (initialiseForAttributes.Any())
         {
             onChanges.Add((re) =>
             {
                 foreach (var initialiseForAttribute in initialiseForAttributes)
                 {
                     var dependencyViewModel = re.GetFieldViewModel(fieldName);
                     var dependantViewModel  = re.GetFieldViewModel(propertyInfo.Name);
                     if (dependencyViewModel.ValueObject != null &&
                         dependencyViewModel.ValueObject.Equals(initialiseForAttribute.ForValue) &&
                         (initialiseForAttribute.AlwaysSetIfNotEmpty || dependantViewModel.ValueObject.IsEmpty()))
                     {
                         dependantViewModel.ValueObject = initialiseForAttribute.InitialValue;
                     }
                 }
             });
         }
     }
 }
 private void AppendDisplayNameAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
 {
     foreach (var property in ObjectRecordService.GetFields(recordType))
     {
         var propertyInfo = ObjectRecordService.GetPropertyInfo(property, recordType);
         var attributes   = propertyInfo
                            .GetCustomAttributes <DisplayNameForPropertyValueAttribute>()
                            .Where(a => a.Property == fieldName);
         if (attributes.Any())
         {
             onChanges.Add((re) =>
             {
                 foreach (var attribute in attributes)
                 {
                     var dependencyViewModel = re.GetFieldViewModel(fieldName);
                     var dependantViewModel  = re.GetFieldViewModel(propertyInfo.Name);
                     if (dependencyViewModel.ValueObject != null &&
                         dependencyViewModel.ValueObject.Equals(attribute.Value))
                     {
                         dependantViewModel.Label = attribute.Label;
                     }
                 }
             });
         }
     }
 }
        private void AppendUniqueOnAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var attributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType).GetCustomAttribute <UniqueOn>();

            if (attributes != null)
            {
                onChanges.Add(
                    re => re.StartNewAction(() =>
                {
                    //just need to if this in a grid then set all others off
                    if (re is GridRowViewModel)
                    {
                        var gridRowViewModel = (GridRowViewModel)re;
                        var fieldViewModel   = gridRowViewModel.GetFieldViewModel(fieldName) as BooleanFieldViewModel;
                        if (fieldViewModel != null && fieldViewModel.Value)
                        {
                            foreach (var row in gridRowViewModel.GridViewModel.GridRecords.ToArray())
                            {
                                if (row != gridRowViewModel)
                                {
                                    ((BooleanFieldViewModel)row.GetFieldViewModel(fieldName)).Value = false;
                                }
                            }
                        }
                    }
                }));
            }
        }
        private void AppendReadOnlyWhenSetAttributes(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var attributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType).GetCustomAttribute <ReadOnlyWhenSet>();

            if (attributes != null)
            {
                onChanges.Add(
                    re => re.StartNewAction(() =>
                {
                    //just need to if this in a grid then set all others off
                    var fieldViewModel = re.GetFieldViewModel(fieldName);
                    if (fieldViewModel != null)
                    {
                        fieldViewModel.IsEditable = fieldViewModel.ValueObject == null;
                    }
                }));
            }
        }
        private void AppendConnectionForChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges, bool isOnLoad)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(ConnectionFor), true).Cast <ConnectionFor>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re =>
                {
                    var changedViewModel = re.GetFieldViewModel(fieldName);
                    if (changedViewModel.ValueObject != null)
                    {
                        var matchingFields =
                            re.FieldViewModels.Where(f => f.FieldName == attribute.Property);
                        if (matchingFields.Any())
                        {
                            var fieldViewModel = matchingFields.First();
                            if (!isOnLoad && fieldViewModel is LookupFieldViewModel)
                            {
                                var typedViewModel = (LookupFieldViewModel)fieldViewModel;
                                typedViewModel.ConnectionForChanged();
                            }
                            if (fieldViewModel is RecordTypeFieldViewModel)
                            {
                                var typedViewModel         = (RecordTypeFieldViewModel)fieldViewModel;
                                typedViewModel.ItemsSource = ObjectRecordService
                                                             .GetPicklistKeyValues(fieldViewModel.FieldName,
                                                                                   fieldViewModel.GetRecordType())
                                                             .Select(p => new RecordType(p.Key, p.Value))
                                                             .Where(rt => !rt.Value.IsNullOrWhiteSpace())
                                                             .OrderBy(rt => rt.Value)
                                                             .ToArray();
                            }
                        }
                    }
                });
            }
        }
        private void AppendCascadeOnChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(CascadeOnChange), true).Cast <CascadeOnChange>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re =>
                {
                    var changedViewModel = re.GetFieldViewModel(fieldName);
                    if (changedViewModel.ValueObject != null)
                    {
                        var matchingFields = re.FieldViewModels.Where(f => f.FieldName == attribute.TargetProperty);
                        if (matchingFields.Any())
                        {
                            matchingFields.First().ValueObject = changedViewModel.ValueObject;
                        }
                    }
                });
            }
        }
        private void AppendLookupFieldCascadeChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(LookupFieldCascade), true).Cast <LookupFieldCascade>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re =>
                {
                    var changedViewModel = re.GetFieldViewModel(fieldName);
                    if (changedViewModel.ValueObject != null)
                    {
                        var changedViewModelLookup = ((LookupFieldViewModel)changedViewModel).Value;
                        var matchingFields         = re.FieldViewModels.Where(f => f.FieldName == attribute.TargetProperty);
                        var lookupService          = ObjectRecordService.GetLookupService(changedViewModel.FieldName, re.GetRecordType(), re.ParentFormReference, re.GetRecord());
                        if (lookupService != null)
                        {
                            var lookupRecord = lookupService.Get(changedViewModelLookup.RecordType, changedViewModelLookup.Id);
                            if (lookupRecord == null)
                            {
                                changedViewModel.ValueObject = null;
                                re.ApplicationController.UserMessage(string.Format("The {0} Was Not Found And The Value Has Been Cleared", changedViewModel.Label));
                            }
                            else
                            {
                                var sourceFieldValue = lookupRecord.GetField(attribute.SourceRecordField);
                                if (matchingFields.Any())
                                {
                                    matchingFields.First().ValueObject = sourceFieldValue;
                                }
                            }
                        }
                    }
                });
            }
        }
        internal override IEnumerable <CustomGridFunction> GetCustomFunctionsFor(string referenceName, RecordEntryFormViewModel recordForm)
        {
            var functions  = new Dictionary <string, Action>();
            var recordType = recordForm.GetEnumerableFieldViewModel(referenceName).RecordType;

            if (recordType == null)
            {
                return(new CustomGridFunction[0]);
            }

            var enumeratedType  = ObjectRecordService.GetClassType(recordType);
            var customFunctions = enumeratedType.GetCustomAttributes <CustomFunction>();

            if (customFunctions != null)
            {
                foreach (var item in customFunctions)
                {
                    functions.Add(item.GetFunctionLabel(), item.GetCustomFunction(recordForm, referenceName));
                }
            }
            var allowDownloadAttribute = ObjectRecordService.GetPropertyInfo(referenceName, recordForm.RecordType).GetCustomAttribute <AllowDownload>();

            if (allowDownloadAttribute != null)
            {
                functions.Add("Download CSV", () => { recordForm.GetEnumerableFieldViewModel(referenceName).DynamicGridViewModel.DownloadCsv(); });
            }
            var customGridFunctions = functions.Select(kv => new CustomGridFunction(kv.Key, kv.Key, kv.Value)).ToList();
            var typesToResolve      = GetTypesToResolve(enumeratedType);

            foreach (var typeToResolve in typesToResolve)
            {
                var injectedFunctions = recordForm.ApplicationController.ResolveInstance(typeof(CustomGridFunctions), typeToResolve.AssemblyQualifiedName) as CustomGridFunctions;
                customGridFunctions.AddRange(injectedFunctions.CustomFunctions);
            }
            return(customGridFunctions);
        }
        private PropertyInfo GetPropertyInfo(string field, string type)
        {
            var propertyInfo = ObjectRecordService.GetPropertyInfo(field, type);

            return(propertyInfo);
        }
        private void AppendFieldForChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges, bool clearValue = false)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(RecordFieldFor), true).Cast <RecordFieldFor>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re => re.StartNewAction(() =>
                {
                    var recordFieldViewModel = re.GetRecordFieldFieldViewModel(fieldName);
                    if (recordFieldViewModel.Value != null)
                    {
                        var matchingFields = re.FieldViewModels.Where(f => f.FieldName == attribute.PropertyPaths.First());
                        foreach (var fieldViewModel in matchingFields.ToArray())
                        {
                            var selectedFieldName       = recordFieldViewModel.Value.Key;
                            var selectedFieldRecordType = GetRecordTypeFor(recordFieldViewModel.FieldName, re);
                            var lookupService           = re.RecordService.GetLookupService(recordFieldViewModel.FieldName, recordFieldViewModel.GetRecordType(), null, recordFieldViewModel.RecordEntryViewModel.GetRecord());
                            if (lookupService != null)
                            {
                                //get the source field type
                                var fieldType = lookupService.GetFieldType(selectedFieldName, selectedFieldRecordType);
                                //get the section the target field is in and its field metadata
                                var metadata = re.FormService.GetFormMetadata(re.GetRecordType(), ObjectRecordService);
                                FormFieldMetadata fieldMetadata = null;
                                string sectionName = null;
                                foreach (var sectionMetadata in metadata.FormSections.Cast <FormFieldSection>())
                                {
                                    foreach (var field in sectionMetadata.FormFields)
                                    {
                                        if (field.FieldName == fieldViewModel.FieldName)
                                        {
                                            sectionName   = sectionMetadata.SectionLabel;
                                            fieldMetadata = field;
                                        }
                                    }
                                }
                                if (!string.IsNullOrWhiteSpace(sectionName))
                                {
                                    var targetPropInfo = ObjectRecordService.GetPropertyType(attribute.PropertyPaths.First(), recordType);
                                    if (targetPropInfo.IsEnum)
                                    {
                                        //if target is an enum then filter the items source for the field type
                                        var picklistFieldViewModel = fieldViewModel as PicklistFieldViewModel;
                                        var picklistOptions        = ObjectRecordService.GetPicklistKeyValues(picklistFieldViewModel.FieldName, picklistFieldViewModel.GetRecordType(), fieldType.ToString(), picklistFieldViewModel.RecordEntryViewModel.GetRecord());
                                        if (clearValue)
                                        {
                                            picklistFieldViewModel.Value = null;
                                        }
                                        picklistFieldViewModel.ItemsSource = picklistOptions;
                                    }
                                    else
                                    {
                                        //otherwise is a field input dynamic for the field's tpye
                                        //now we need to create the view model for the target field as the correct type
                                        //okay now we need to replace the old field view model for this field
                                        var explicitTargetType = fieldType == RecordFieldType.Lookup || fieldType == RecordFieldType.Customer || fieldType == RecordFieldType.Owner
                                                ? lookupService.GetLookupTargetType(selectedFieldName, selectedFieldRecordType)
                                                : null;
                                        var explicitPicklistOptions = fieldType == RecordFieldType.Picklist ||
                                                                      fieldType == RecordFieldType.Status ||
                                                                      fieldType == RecordFieldType.State ||
                                                                      fieldType == RecordFieldType.Integer
                                                ? lookupService.GetPicklistKeyValues(selectedFieldName, selectedFieldRecordType)
                                                : null;
                                        if (clearValue)
                                        {
                                            fieldViewModel.ValueObject = null;
                                        }
                                        var newFieldViewModel = fieldMetadata.CreateFieldViewModel(re.GetRecordType(), re.RecordService, re, re.ApplicationController, explicitFieldType: fieldType, explicitLookupTargetType: explicitTargetType, explicitPicklistOptions: explicitPicklistOptions);
                                        var section           = re.FieldSections.First(s => s.SectionLabel == sectionName);
                                        var index             = section.Fields.Count;
                                        for (var i = 0; i < section.Fields.Count; i++)
                                        {
                                            if (section.Fields[i].FieldName == fieldViewModel.FieldName)
                                            {
                                                index = i;
                                                break;
                                            }
                                        }

                                        re.DoOnMainThread(() =>
                                        {
                                            if (section.Fields.Count > index)
                                            {
                                                section.Fields.RemoveAt(index);
                                            }

                                            if (clearValue)
                                            {
                                                fieldViewModel.ValueObject = null;
                                            }
                                            section.Fields.Insert(index, newFieldViewModel);
                                            re.RefreshVisibility();
                                        });
                                    }
                                }
                            }
                        }
                    }
                }));
            }
        }
        public override FormMetadata GetFormMetadata(string recordType, IRecordService recordService = null)
        {
            if (_formMetadata == null)
            {
                var formSections = new List <FormFieldSection>();

                var type             = ObjectToEnter.GetType();
                var propertyMetadata = ObjectRecordService.GetFieldMetadata(type.AssemblyQualifiedName);

                var standardFieldSectionName = type.GetDisplayName();

                var fieldSections = type.GetCustomAttributes <Group>();
                var otherSections = new Dictionary <string, List <FormFieldMetadata> >();
                foreach (var section in fieldSections)
                {
                    var functions = new List <CustomFormFunction>();
                    if (section.SelectAll)
                    {
                        functions.Add(new CustomFormFunction("SELECTALL", "SELECT ALL", (re) =>
                        {
                            var entryForm = re as RecordEntryFormViewModel;
                            if (entryForm != null)
                            {
                                var thisSection   = entryForm.GetFieldSection(section.Name);
                                var booleanFields = thisSection.Fields.Where(f => f is BooleanFieldViewModel).Cast <BooleanFieldViewModel>();
                                var turnOff       = booleanFields.All(b => b.Value);
                                foreach (var field in booleanFields)
                                {
                                    field.Value = !turnOff;
                                }
                            }
                        }));
                    }
                    otherSections[section.Name] = new List <FormFieldMetadata>();
                    var newSection = new FormFieldSection(section.Name, otherSections[section.Name], section.DisplayLayout, section.Order, customFunctions: functions);
                    formSections.Add(newSection);
                }

                foreach (var property in propertyMetadata.Where(m => m.Readable || m.Writeable))
                {
                    var propinfo       = ObjectRecordService.GetPropertyInfo(property.SchemaName, type.AssemblyQualifiedName);
                    var groupAttribute = propinfo.GetCustomAttribute <Group>();

                    string enumerableType = null;
                    if (property is EnumerableFieldMetadata)
                    {
                        enumerableType = ((EnumerableFieldMetadata)property).EnumeratedTypeQualifiedName;
                    }

                    var displayLabel = property.FieldType != RecordFieldType.Enumerable ||
                                       groupAttribute != null;

                    var fieldMetadata = new PersistentFormField(property.SchemaName, enumerableType, displayLabel);
                    fieldMetadata.Order = property.Order;

                    string sectionName = null;
                    if (groupAttribute != null)
                    {
                        sectionName = groupAttribute.Name;
                    }
                    else if (property.FieldType == RecordFieldType.Enumerable)
                    {
                        sectionName = property.DisplayName;
                    }
                    else
                    {
                        sectionName = standardFieldSectionName;
                    }

                    var order = 0;
                    if (groupAttribute != null)
                    {
                        order = groupAttribute.Order;
                    }
                    else if (property.FieldType == RecordFieldType.Enumerable)
                    {
                        order = 200000;
                    }
                    else
                    {
                        order = 1;
                    }

                    var displayLayout = groupAttribute != null
                        ? groupAttribute.DisplayLayout
                        : Group.DisplayLayoutEnum.VerticalList;

                    if (!otherSections.ContainsKey(sectionName))
                    {
                        otherSections[sectionName] = new List <FormFieldMetadata>();
                        var newSection = new FormFieldSection(sectionName, otherSections[sectionName], displayLayout, order);
                        formSections.Add(newSection);
                    }
                    otherSections[sectionName].Add(fieldMetadata);
                }
                foreach (var section in formSections)
                {
                    var fields = section.FormFields;
                    if (section.DisplayLayout == Group.DisplayLayoutEnum.HorizontalInputOnly)
                    {
                        foreach (var field in fields)
                        {
                            field.DisplayLabel = false;
                        }
                    }
                    if (fields.Count() == 1)
                    {
                        var field   = fields.First();
                        var fieldMt = ObjectRecordService.GetFieldMetadata(field.FieldName, type.AssemblyQualifiedName);
                        if (fieldMt is EnumerableFieldMetadata ||
                            fieldMt is MemoFieldMetadata ||
                            (fieldMt is StringFieldMetadata && fieldMt.IsMultiline()))
                        {
                            field.DisplayLabel = false;
                        }
                    }
                }
                formSections  = formSections.OrderBy(s => s.Order).ToList();
                _formMetadata = new FormMetadata(formSections);
            }
            return(_formMetadata);
        }
        private void AppendRecordTypeForChanges(string fieldName, string recordType, List <Action <RecordEntryViewModelBase> > onChanges)
        {
            var lookupForAttributes = ObjectRecordService.GetPropertyInfo(fieldName, recordType)
                                      .GetCustomAttributes(typeof(RecordTypeFor), true).Cast <RecordTypeFor>();

            foreach (var attribute in lookupForAttributes)
            {
                onChanges.Add(
                    re => re.StartNewAction(() =>
                {
                    var recordTypeViewModel = re.GetRecordTypeFieldViewModel(fieldName);
                    var matchingFields      = re.FieldViewModels.Where(f => f.FieldName == attribute.PropertyPaths.First());
                    if (matchingFields.Any())
                    {
                        var fieldViewModel = matchingFields.First();
                        if (fieldViewModel is LookupFieldViewModel)
                        {
                            var typedViewModel     = (LookupFieldViewModel)fieldViewModel;
                            var selectedRecordType = recordTypeViewModel.Value == null
                                    ? null
                                    : recordTypeViewModel.Value.Key;
                            typedViewModel.RecordTypeToLookup = selectedRecordType;
                            typedViewModel.Value = null;
                        }
                        else if (fieldViewModel is RecordFieldFieldViewModel)
                        {
                            var typedViewModel     = (RecordFieldFieldViewModel)fieldViewModel;
                            var selectedRecordType = recordTypeViewModel.Value == null
                                    ? null
                                    : recordTypeViewModel.Value.Key;
                            typedViewModel.RecordTypeForField = selectedRecordType;
                        }
                        else if (fieldViewModel is RecordFieldMultiSelectFieldViewModel)
                        {
                            var typedViewModel     = (RecordFieldMultiSelectFieldViewModel)fieldViewModel;
                            var selectedRecordType = recordTypeViewModel.Value == null
                                    ? null
                                    : recordTypeViewModel.Value.Key;
                            typedViewModel.RecordTypeForField = selectedRecordType;
                        }
                    }
                    else
                    {
                        if (re is ObjectEntryViewModel)
                        {
                            if (attribute.PropertyPaths.Count() < 2)
                            {
                                throw new NullReferenceException(string.Format("The {0} Attribute References an Enumerable Property But Does Not Specify The Property On The Enumerated Type. The Value Is {1} And Should Be Of Form Property1.Property2", typeof(RecordTypeFor).Name, attribute.LookupProperty));
                            }
                            var oevm          = (ObjectEntryViewModel)re;
                            var matchingGrids = oevm.SubGrids.Where(sg => sg.ReferenceName == attribute.PropertyPaths.First());
                            if (matchingGrids.Any())
                            {
                                //clear the rows as they are no longer relevant for the change in type
                                matchingGrids.First().ClearRows();
                            }
                        }
                    }
                }));
            }
        }