Flask admin: add dynamic choices to SelectField inside embedded document - mongoengine

I have a string field inside an embedded document and override this field to be a selected field.
After overriding, I add an empty list of choices as an argument to the selcted field.
The issue is that on form access we try to add some dynamic choices to the selected field, but for some reason, this fails.
How can we add some dynamic choices?
I need to do this using some kind of preprocessor because the data is from DB that loads just after all the models.
class:
class BadgeDoc(EmbeddedDocument):
parent_id = ObjectIdField()
name = StringField()
display_text = StringField()
color = StringField()
extra_style = StringField()
service = ObjectIdField()
badge_type = StringField()
class PresentationCategory(Presentation):
product = ReferenceField('ProductType')
article = EmbeddedDocumentField(Article)
show_video_review = BooleanField()
show_video_reviews_count = IntField(default=0)
badge = ListField(EmbeddedDocumentField(BadgeDoc))
view:
class PresentationView(NewPresentationView):
form_subdocuments = {
'badge': {
'form_subdocuments': {
None:
{
'form_excluded_columns': ('name', 'display_text', 'color', 'extra_style', 'service',
'badge_type'),
'form_overrides': {
'parent_id': admin.form.fields.Select2Field,
},
'form_args': {
'parent_id': {'choices': []}
}
}
}
}
}

Related

Why I am getting this error? pydantic.error_wrappers.ValidationError: 2 validation errors for DishMenus

model.py
class Dish(db.Entity):
id = PrimaryKey(UUID, auto=True)
dish_name = Required(str, unique =True)
price = Required(float, default=0)
created_at = Required(date)
dish_menus = Set('Dish_Menu')
class Menu(db.Entity):
id = PrimaryKey(UUID, auto=True)
date = Required(date)
dish_menu = Set('Dish_Menu')
class Dish_Menu(db.Entity):
id = PrimaryKey(UUID, auto=True)
dish_availability = Required(int)
dishes = Required("Dish", column = "dish_id")
menus = Required("Menu", column = "menu_id")
routes.py
#api.post('/', status_code=status.HTTP_201_CREATED)
async def create_dish_menu(dish_menu: DishMenus):
with db_session:
new_dish = Dish_Menu(dish_availability = dish_menu.dish_availability,
dishes = dish_menu.dish_id, menus = dish_menu.menu_id)
commit()
result = SaveDishMenu.from_orm(new_dish)
return result
#api.get('/', status_code=status.HTTP_200_OK)
async def get_all_dish_menu():
with db_session:
dish_menu = Dish_Menu.select()
print(dish_menu);
result = [DishMenuDetails.from_orm(i) for i in dish_menu]
return result
schemas.py
class SaveDishMenu(BaseModel):
id : Optional [UUID]
dish_availability: int
class Config:
orm_mode = True
class DishMenus(SaveDishMenu):
dish_id : str
menu_id : str
class Config:
orm_mode = True
class DishMenuDetails(SaveDishMenu):
dish_id : DishDetails
menu_id : MenuSchema
I can post a dish menu, but I have problem in getting all of those input because I'm getting this error: pydantic.error_wrappers.ValidationError: 2 validation errors for DishMenus dish_id field required (type=value_error.missing) menu_id field required (type=value_error.missing)
In my schemas, I inherit some because of some factors. Do I need to change something on my model? or route?
Can someone help me with it? Thanks

Flutter access model attribute using dynamic key [duplicate]

I'm trying to access a class value by using a variable previously defined in dart, but I keep getting the error the operator [] isn't defined for the class
In Javascript I would access an object value using a variable like this:
let movie = {
movieTitle : 'Toy Story',
actor: 'Tom Hanks'
}
let actorName = 'actor';
console.log(movie[actorName]); // <- what I'm trying to replicate in dart
// expected output: Tom Hanks
Here is what I've tried and is throwing that error
class Movie {
String name;
String actor;
String producer;
}
void main() {
var movieTitle = new Movie();
movieTitle.name = 'Toy Story';
movieTitle.actor = 'Tom Hanks';
print(movieTitle.actor); <- prints out Tom Hanks as expected
var actorName = 'actor';
print(movieTitle[actorName]); <- throws error
}
I expect to be able to use a variable on the fly to access the value.
A trivial use case for me would be if I had a a list of Movie classes, where some actors and producers are null, I would like to filter on either non null actors or producer with a function like so:
List values = movieList.where((i) => i.actor != "null").toList(); // returns all Movies in movieList where the actor value isn't the string "null"
var actorIsNull = 'actor';
List values = movieList.where((i) => i[actorisNull] != "null").toList(); // throws error
You can createn a toMap() function in your Movie class and access properties using [] operator
class Movie {
String name;
String actor;
String producer;
Map<String, dynamic> toMap() {
return {
'name': name,
'actor' : actor,
'producer' : producer,
};
}
}
Now Movie class properties can be accessed as:
Movie movie = Movie();
movie.toMap()['name'];
You cannot access class members by a string containing their name. (Except with mirrors - outside the scope of this answer.)
You could remove the class altogether and just use a Map<String, String>.
Map<String, String> movie = {
'movieTitle': 'Toy Story',
'actor': 'Tom Hanks',
}
You could add some bool methods on the class.
bool hasNoActor() => actor == null;
...
List values = movieList.where((m) => !m.hasNoActor()).toList();
Or, you could pass a lambda to your mapper.
Movie movieTitle = Movie()
..name = 'Toy Story'
..actor = 'Tom Hanks';
Function hasActor = (Movie m) => m.actor != null;
List values = movieList.where(hasActor).toList();

Add Filter to selector in Acumatica Mobile

We have currently added the Warehouse/Bin Transfer to the Acumatica Mobile to allow users to do bin transfers via the Mobile versus using Acumatica.
We have added the QtyAvailable to the From and To Bin selectors in the with the SelectorContainer statement. However is there a way to filter out only those records for the item instead of showing all bins/location. This filter would only be on the from location. The to location would still show all locations.
To show only bin/locations with Qty. Available greater than 0, you should extend Where condition for LocationAvailAttribute decorating the INTran.LocationID field:
using PX.Data;
using System;
namespace PX.Objects.IN
{
public class INTransferEntryExt : PXGraphExtension<INTransferEntry>
{
[PXRemoveBaseAttribute(typeof(LocationAvailAttribute))]
[PXMergeAttributes(Method = MergeMethod.Append)]
[LocationAvailCst(typeof(INTran.inventoryID), typeof(INTran.subItemID),
typeof(INTran.siteID), typeof(INTran.tranType), typeof(INTran.invtMult))]
public virtual void INTran_LocationID_CacheAttached(PXCache sender)
{
}
public class LocationAvailCstAttribute : LocationAvailAttribute
{
public LocationAvailCstAttribute(Type inventoryType, Type subItemType,
Type siteIDType, Type TranType, Type InvtMultType)
: base(inventoryType, subItemType, siteIDType, TranType, InvtMultType)
{
var attr = _Attributes[_SelAttrIndex] as PXDimensionSelectorAttribute;
var dimAttr = attr.GetAttribute<PXDimensionAttribute>();
var selAttr = attr.GetAttribute<PXSelectorAttribute>();
var select = selAttr.GetSelect();
select = select.WhereAnd<Where<INLocationStatus.qtyAvail, Greater<Zero>>>();
var newAttr = new PXDimensionSelectorAttribute(DimensionName,
select.GetType(), typeof(INLocation.locationCD),
new Type[]
{
typeof(INLocation.locationCD),
typeof(INLocationStatus.qtyOnHand),
typeof(INLocationStatus.qtyAvail),
typeof(INLocationStatus.active),
typeof(INLocation.primaryItemID),
typeof(INLocation.primaryItemClassID),
typeof(INLocation.receiptsValid),
typeof(INLocation.salesValid),
typeof(INLocation.transfersValid),
typeof(INLocation.projectID),
typeof(INLocation.taskID)
});
_Attributes[_SelAttrIndex] = newAttr;
newAttr.ValidComboRequired = attr.ValidComboRequired;
newAttr.CacheGlobal = attr.CacheGlobal;
newAttr.DirtyRead = attr.DirtyRead;
newAttr.DescriptionField = attr.DescriptionField;
}
}
}
}
With the custom LocationAvailCstAttribute added on the INTran.LocationID field, Location selector will show only bins/locations, for which current Inventory Item Qty. Available is greater than 0:

Dynamics CRM - Accessing Custom Product Option Value

Is there a way to programmatically access the Label & Value fields that has been created as a custom Field in MS CRM Dynamics please?
I have added a custom field called "new_producttypesubcode" which, for example, has 2 options, Trophy = 1000000 and Kit = 10000001.
I am writing an import utility that mirrors products between the customers website and their CRM and I want to get a list of all possible product options in the CRM to see if they are matched in the website.
So, in essence I want to...
get the list of possible new_producttypesubcodes and their corresponding values.
Iterate through the product variants in the website.
if the product variant name matches any name in the list of new_producttypecodes then add the value 1000000
So, if I find a product added to the website and its marked as a "Trophy" and "Trophy" exists in the CRM then new OptionSetValue(100000001)
I hope that makes sense...
Thanks
This function retrieves a dictionary of possible values localised to the current user. Taken from: CRM 2011 Programatically Finding the Values of Picklists, Optionsets, Statecode, Statuscode and Boolean (Two Options).
static Dictionary<String, int> GetNumericValues(IOrganizationService service, String entity, String attribute)
{
RetrieveAttributeRequest request = new RetrieveAttributeRequest
{
EntityLogicalName = entity,
LogicalName = attribute,
RetrieveAsIfPublished = true
};
RetrieveAttributeResponse response = (RetrieveAttributeResponse)service.Execute(request);
switch (response.AttributeMetadata.AttributeType)
{
case AttributeTypeCode.Picklist:
case AttributeTypeCode.State:
case AttributeTypeCode.Status:
return ((EnumAttributeMetadata)response.AttributeMetadata).OptionSet.Options
.ToDictionary(key => key.Label.UserLocalizedLabel.Label, option => option.Value.Value);
case AttributeTypeCode.Boolean:
Dictionary<String, int> values = new Dictionary<String, int>();
BooleanOptionSetMetadata metaData = ((BooleanAttributeMetadata)response.AttributeMetadata).OptionSet;
values[metaData.TrueOption.Label.UserLocalizedLabel.Label] = metaData.TrueOption.Value.Value;
values[metaData.FalseOption.Label.UserLocalizedLabel.Label] = metaData.FalseOption.Value.Value;
return values;
default:
throw new ArgumentOutOfRangeException();
}
}
So you would then need to do something like:
Dictionary<String, int> values = GetNumericValues(proxy, "your_entity", "new_producttypesubcode");
if(values.ContainsKey("Trophy"))
{
//Do something with the value
OptionSetValue optionSetValue = values["Trophy"];
int value = optionSetValue.Value;
}
Yes, that data is all stored in the metadata for an attribute (SDK article). You have to retrieve the entity metadata for the entity and then find the attribute in the list. Then cast that attribute to a PicklistAttributeMetadata object and it will contain a list of options. I would mention that typically retrieving Metadata from CRM is an expensive operation, so think about caching.
private static OptionSetMetadata RetrieveOptionSet(IOrganizationService orgService,
string entityName, string attributeName)
{
var entityResponse = (RetrieveEntityResponse)orgService.Execute(
new RetrieveEntityRequest
{ LogicalName = entityName, EntityFilters = EntityFilters.Attributes });
var entityMetadata = entityResponse.EntityMetadata;
for (int i = 0; i < entityMetadata.Attributes.Length; i++)
{
if (attributeName.Equals(entityMetadata.Attributes[i].LogicalName))
{
if (entityMetadata.Attributes[i].AttributeType.Value ==
AttributeTypeCode.Picklist)
{
var attributeMD = (PicklistAttributeMetadata)
entityMetadata.Attributes[i];
return attributeMD.OptionSet;
}
}
}
return null;
}
Here is how to write the options to the console using the above call.
var optionSetMD = RetrieveOptionSet(orgService, "account", "accountcategorycode");
var options = optionSetMD.Options;
for (int i = 0; i < options.Count; i++)
{
Console.WriteLine("Local Label: {0}. Value: {1}",
options[i].Label.UserLocalizedLabel.Label,
options[i].Value.HasValue ? options[i].Value.Value.ToString() : "null");
}
I believe this works for global option set attributes as well, but if you know it is a global option set there is a different message for it that would probably a bit more efficient (SDK article).

Convert to view model, EF Partial Class calculated property using related entities returns 0

I am using EF 5 and have a new property that I've defined in a partial class to extend the base database fields. It requires summing data from a related table.
[Display(Name = "Qty Allocated")]
public decimal QtyAllocated
{
get { return this.AllocatedContainers == null ? 1 : this.AllocatedContainers.Sum(a => a.AllocatedQty); }
//get { return 2;}
}
This property returns the correct value....BUT, if I then use the following method to convert this to a view model, the returned value is 0. Note the view model inherits from the class:
public class InventoryContainerDetailListViewModel : InventoryContainerDetail
Method:
public IEnumerable<InventoryContainerDetailListViewModel> ConvertClassToViewModel(IEnumerable<InventoryContainerDetail> entityList)
{
IEnumerable<InventoryContainerDetailListViewModel> itemGrid =
from l in entityList.ToList()
select new InventoryContainerDetailListViewModel()
{
Id = l.Id,
InventoryContainerHeaderId = l.InventoryContainerHeaderId,
PONbr = l.ReceiptDetail == null ? (int?)null : l.ReceiptDetail.PODetail.POHeaderId,
ReceiptDetailId = l.ReceiptDetailId,
ItemId = l.ItemId,
ItemDescription = l.Item.ShortDescription,
QtyInContainer = l.QtyInContainer,
//QtyAllocated = l.AllocatedContainers == null ? 0 : l.AllocatedContainers.Sum(a => a.AllocatedQty),
Location = l.InventoryContainerHeader.Location.DisplayLocation
};
return itemGrid;
}
In this method, the input parameter entityList does show each item with the correct calculated values, but after the conversion, the value is always 0.
I assume this has something to do with the fact that I am inheriting from the base class, but can someone shed some light on this?
I don't think that the reason is inheritance. The more probable reason is that AllocatedContainers is empty collection (you don't assign it when creating instance of your view model).

Resources