I am trying to write the Shipments widget for the Acumatica mobile app so that it can be used more like the web browser.
Specifically I want to be able to add serial numbers and bin locations to the line inventory items.
The problem I am having is if the line item has quantity 2 or more, I cannot get the Allocations screen to popup so that you can select and enter multiple SN's for that shipping line item. The error I most often receive is "Server error : 404". Which obviously means it is not finding/generating the web page for mobile app display.
Can anyone point me in the right direction as to what I am doing wrong?
Here is the code:
add container "ShipmentSummary" {
formActionsToExpand = 5
add layout "ShipmentHeader" {
displayName = "ShipmentHeader"
layout = "HeaderSimple"
add layout "ShipmentHeaderNbrRow" {
displayName = "ShipmentHeaderNbrRow"
layout = "Inline"
add field "ShipmentNbr"
add field "Status"
}
add layout "ShipmentQtyRow" {
displayName = "ShipmentQtyRow"
layout = "Inline"
add field "Operation"
add field "ShippedQuantity"
}
add layout "ShipmentCustomerRow" {
displayName = "ShipmentCustomerRow"
layout = "Inline"
add field "Customer"
}
add layout "ShipmentWarehouseID" {
displayName = "ShipmentWarehouseID"
layout = "Inline"
add field "WarehouseID"
}
add layout "ShipmentLocation" {
displayName = "ShipmentLocation"
layout = "Inline"
add field "Location"
}
}
add field "ShipmentDate" {
selectorDisplayFormat = Key
pickerType = Detached
}
add field "Workgroup" {
pickerType = Detached
}
add field "Owner" {
pickerType = Detached
}
add field "Description"
add group "OrderInfoGroup" {
displayName = "Orders"
collapsable = True
collapsed = True
add layout "OrdersLineInfo" {
displayName = "OrdersLineInfo"
layout = "Inline"
add field "Orders#OrderType"
add field "Orders#OrderNbr"
}
add layout "LineInvoiceInfo" {
displayName = "LineInvoiceInfo"
layout = "Inline"
add field "Orders#InvoiceType"
add field "Orders#InvoiceNbr"
}
add field "Orders#NoteText" {
displayName = "Order Notes"
textType = PlainMultiLine
}
}
add layout "DetailsTab" {
displayName = "Details"
layout = "DataTab"
add containerLink "DocumentDetails"
}
add recordAction "Save" {
behavior = Save
}
add recordAction "Cancel" {
behavior = Cancel
}
add containerAction "Insert" {
icon = "system://Plus"
behavior = Create
redirect = True
}
add recordAction "PutOnHoldAction" {
behavior = Record
}
add recordAction "ReleaseFromHoldAction" {
behavior = Record
}
add recordAction "ConfirmShipmentActionAction" {
behavior = Record
}
attachments {
}
}
add container "DocumentDetails" {
fieldsToShow = 2
listActionsToExpand = 1
formActionsToExpand = 2
containerActionsToExpand = 1
add group "LineInventoryIdGroup" {
displayName = "LineInventoryIdGroup"
collapsed = True
template = ExpansionPanel
add field "InventoryID" {
listPriority = 100
selectorDisplayFormat = Key
pickerType = Searchable
}
add field "Description" {
listPriority = 90
}
}
add field "Location"
add field "LotSerialNbr"
add layout "LineQuantityRow" {
displayName = "LineQuantityRow"
layout = "Inline"
add field "ShippedQty"
add field "UOM"
}
add layout "AllocationsTab" {
displayName = "Allocations"
layout = "DataTab"
add containerLink "Allocations"
}
add containerAction "Insert" {
icon = "system://Plus"
behavior = Create
}
add selectionAction "Delete" {
icon = "system://Trash"
behavior = Delete
}
add recordAction "Delete" {
icon = "system://Trash"
behavior = Delete
after = Close
}
add recordAction "Insert" {
displayName = "Add Another"
icon = "system://Plus"
behavior = Create
}
attachments {
}
}
add container "Allocations" {
visible = False
fieldsToShow = 3
listActionsToExpand = 2
formActionsToExpand = 3
containerActionsToExpand = 2
add field "InventoryID" {
selectorDisplayFormat = KeyDescription
listPriority = 100
}
add field "Location" {
pickerType = Attached
}
add field "LotSerialNbr" {
pickerType = Attached
}
add layout "AllocQtyRow"{
displayName = "AllocQtyRow"
layout = "Inline"
add field "Quantity" {
selectorDisplayFormat = KeyDescription
listPriority = 90
}
add field "UOM" {
selectorDisplayFormat = Key
listPriority = 80
}
}
add field "Description"
add containerAction "Insert" {
icon = "system://Plus"
behavior = Create
redirect = True
}
attachments {
}
}
}
I was able to figure out what the issue was.
First, Acumatica documentation for the mobile app is not very informative. So, a great deal has to be just 'Trial and Error'.
For the issue of this problem, what I needed to do was pass the redirect to the "Allocations" container as a "$List" directive, AND, add into the Allocations container both a containerAction and recordAction for "Insert" of a new entry. (Below is the code)
add container "DocumentDetails" {
fieldsToShow = 2
listActionsToExpand = 1
formActionsToExpand = 2
containerActionsToExpand = 1
add group "LineInventoryIdGroup" {
displayName = "LineInventoryIdGroup"
collapsed = True
template = ExpansionPanel
add field "InventoryID" {
listPriority = 100
selectorDisplayFormat = Key
pickerType = Searchable
}
add field "Description" {
listPriority = 90
}
}
add field "Location"
add field "LotSerialNbr"
add layout "LineQuantityRow" {
displayName = "LineQuantityRow"
layout = "Inline"
add field "ShippedQty"
add field "UOM"
}
add containerAction "Insert" {
icon = "system://Plus"
behavior = Create
}
add selectionAction "Delete" {
icon = "system://Trash"
behavior = Delete
}
add recordAction "Delete" {
icon = "system://Trash"
behavior = Delete
after = Close
}
add recordAction "Insert" {
displayName = "Add Another"
icon = "system://Plus"
behavior = Create
}
add recordAction "LSSOShipLineBinLotSerial" {
behavior = Void
redirect = True
redirectToContainer = "Allocations$List"
}
attachments {
}
}
add container "Allocations" {
visible = False
fieldsToShow = 3
listActionsToExpand = 2
formActionsToExpand = 3
containerActionsToExpand = 2
add field "InventoryID" {
selectorDisplayFormat = KeyDescription
listPriority = 100
}
add field "Location" {
pickerType = Attached
}
add field "LotSerialNbr" {
pickerType = Attached
}
add layout "AllocQtyRow"{
displayName = "AllocQtyRow"
layout = "Inline"
add field "Quantity" {
selectorDisplayFormat = KeyDescription
listPriority = 90
}
add field "UOM" {
selectorDisplayFormat = Key
listPriority = 80
}
}
add field "ExpirationDate"
add field "Description"
add containerAction "Insert" {
icon = "system://Plus"
behavior = Create
}
add recordAction "Insert" {
displayName = "Add Another"
icon = "system://Plus"
behavior = Create
}
attachments {
}
}
}
Related
I'm reading about Navigation in Jetpack Compose, and found this example I don't understand.
From the docs:
By using the saveState and restoreState flags, the state and back stack of that item is correctly saved and restored as you swap between bottom navigation items.
val navController = rememberNavController()
Scaffold(
bottomBar = {
BottomNavigation {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
items.forEach { screen ->
BottomNavigationItem(
icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}
) { innerPadding ->
NavHost(navController, startDestination = Screen.Profile.route, Modifier.padding(innerPadding)) {
composable(Screen.Profile.route) { Profile(navController) }
composable(Screen.FriendsList.route) { FriendsList(navController) }
}
}
Specifically, I don't understand how the back stack can be saved if clicking an item in the bottom bar pops the navigation stack to the root.
I would imagine a journey like:
User moves to /FriendsList/Friend(A)/Friend(B)/Friend(C)
User clicks Profile button, resetting the navigation stack to /Profile
User clicks FriendsList button.
Based on the explanation, I would expect the navigation stack to be re-set to /FriendsList/FriendA/FriendB/FriendC, even though the onClick listener seems to set the stack to /FriendsList?
I really don't understand how this can happen, how does the navigation controller link the route to the entire navigation sub-stack? Is item.route changing state containing the full route to /FriendsList/Friend(A)/Friend(B)/Friend(C), or is something else going on? Or do I understand the example wrong?
I suspect maybe the underlying mechanism is that FriendsList contains a nested navigation graph, since the example doesn't actually show any Friend route definitions. The state of this entire nested graph is contained somehow, i.e., something like /FriendsList{FriendA/FriendB/FriendC}, and a move to /FriendsList will unpack this navigation stack. Is that kind of how it works?
The code in the example you gave has only 1 navHost and 1 navController so it is not possible to save the FriendList back stack seperated from the rest back stack.
To achive this behavior you need to declare nested navHosts. Each of them with his own navController and thats it. All the rest is working automatically.
Here is an example
val navController = rememberNavController()
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
Scaffold(
bottomBar = {
BottomNavigation {
items.forEach { screen ->
BottomNavigationItem(
icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
label = { Text(stringResource(screen.resourceId)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}
) { innerPadding ->
NavHost(
navController,
startDestination = Screen.ProfileNavHost.route,
Modifier.padding(innerPadding)
) {
composable(Screen.ProfileNavHost.route) {
val profileNavController = rememberNavController()
NavHost(
navController = profileNavController,
startDestination = Screen.ProfileRoot.route
) {
composable(Screen.ProfileRoot.route) {
ProfileRoot(navController)
}
composable(Screen.ProfileScreen.route) {
ProfileScreen(navController)
}
}
}
composable(Screen.FriendsListNavHost.route) {
val friendsListNavController = rememberNavController()
NavHost(
navController = friendsListNavController,
startDestination = Screen.FriendsListRoot.route
) {
composable(Screen.FriendsListRoot.route) {
FriendsList(navController)
}
composable(Screen.FriendsListFriend.route) {
FriendsListFriend(navController)
}
}
}
}
}
I'm indexing a table where I have a date attribute and I want to sort the result by this date value by default using this typoscript file.
This sortBy property of solr in typo3 is not working on my typoscript file but it does on the solr plugin.
https://docs.typo3.org/p/apache-solr-for-typo3/solr/main/en-us/Configuration/Reference/TxSolrSearch.html#query-sortby
plugin.tx_solr {
search {
query.sortBy = date_intS desc
#This will not sort my index result but the same property on the solr plugin configuration will
initializeWithEmptyQuery = 1
showResultsOfInitialEmptyQuery = 1
faceting = 1
faceting {
facets {
Year {
label = Year
field = dod_intS
}
}
}
}
index.queue {
obituary = 1
obituary {
table = tx_myext_domain_model_obituary
additionalWhereClause = deleted = 0 AND hidden = 0
fields {
title = COA
title {
432 = TEXT
432.field = person
}
image_intS = SOLR_RELATION
image_intS {
localField = image
}
dod_intS = TEXT
dod_intS {
field = dod
data = date:U
strftime = %Y
}
date_intS = TEXT
date_intS {
field = dod
}
condolences_intS = TEXT
condolences_intS {
field = condolences
}
candles_intS = TEXT
candles_intS {
field = candles
}
url = TEXT
url {
typolink.parameter = {$pages.PIDs.myext.detailPid}
typolink.additionalParams = some_parameters
}
}
}
}
}
But this will work. Don't know what's my problem here.
I am trying to create routes in Transit gateway route table using a json template. However, while fetching each string value from an array of string defined in json template, getting error as below;
Error: Incorrect attribute value type\n\n on main.tf line 90, in resource \"aws_ec2_transit_gateway_route\" \"ip_route\":\n 90: destination_cidr_block = each.value.ip_network\n |----------------\n | each.value.ip_network is tuple with 3 elements\n\nInappropriate value for attribute \"destination_cidr_block\": string require
Here below is my code -->
resource "aws_ec2_transit_gateway_route" "ip_route" {
for_each = jsondecode(file("templates/my.json"))
destination_cidr_block = each.value.ip_network
transit_gateway_attachment_id = "tgw-attach-123"
transit_gateway_route_table_id = each.value.tgw_rt_id
}
json file -->
{
"RT-1": {
"tgw_rt_id": "tgw-rtb-00128",
"ip_network": [
"1.1.1.0/24",
"1.1.2.0/24",
"1.1.3.0/24"
]
},
"RT-2": {
"tgw_rt_id": "tgw-rtb-01f1b",
"ip_network": [
"1.1.1.0/24",
"1.1.2.0/24",
"1.1.3.0/24"
]
}
}
I am able to get the "destination_cidr_block" value as "string" if only single string is passed in "ip_network" (eg: "ip_network": "1.1.1.0/24") but failed to fetch when defined with array of string.
As you've identified, the destination_cidr_block only accepts a single CIDR block (a string), not multiple CIDR blocks. You need to create a separate aws_ec2_transit_gateway_route for each CIDR block for each route table. You can do this by flattening the map so there's one element for each RT/CIDR combination.
locals {
route_tables = jsondecode(file("templates/my.json"))
rt_cidr_blocks = merge([
for k, rt in local.route_tables:
{
for i, ip_network in rt.ip_network:
"${k}-${i}" => {
tgw_rt_id = rt.tgw_rt_id
ip_network = ip_network
}
}
]...)
}
resource "aws_ec2_transit_gateway_route" "ip_route" {
for_each = local.rt_cidr_blocks
destination_cidr_block = each.value.ip_network
transit_gateway_attachment_id = each.key
transit_gateway_route_table_id = each.value.tgw_rt_id
}
If you want to see what the flattened map looks like now:
output "rt_cidr_blocks" {
value = local.rt_cidr_blocks
}
Output:
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
blocks = {
"RT-1-0" = {
"ip_network" = "1.1.1.0/24"
"tgw_rt_id" = "tgw-rtb-00128"
}
"RT-1-1" = {
"ip_network" = "1.1.2.0/24"
"tgw_rt_id" = "tgw-rtb-00128"
}
"RT-1-2" = {
"ip_network" = "1.1.3.0/24"
"tgw_rt_id" = "tgw-rtb-00128"
}
"RT-2-0" = {
"ip_network" = "1.1.1.0/24"
"tgw_rt_id" = "tgw-rtb-01f1b"
}
"RT-2-1" = {
"ip_network" = "1.1.2.0/24"
"tgw_rt_id" = "tgw-rtb-01f1b"
}
"RT-2-2" = {
"ip_network" = "1.1.3.0/24"
"tgw_rt_id" = "tgw-rtb-01f1b"
}
}
In Extjs, I want to know whether I can restrict the dragging of elements within a specific x,y co-ordinates, just like an option, containment in jQuery-UI.
Currently this is my code:
abc.prototype.initDrag = function(v) {
v.dragZone = new Ext.dd.DragZone(v.getEl(), {
containerScroll : false,
getDragData : function(e) {
var sourceEl = e.getTarget(v.itemSelector, 10);
var t = e.getTarget();
var rowIndex = abc.grid.getView().findRowIndex(t);
var columnIndex = abc.grid.getView().findCellIndex(t);
var abcDragZone = v.dragZone ; //Ext.getCmp('idabcDragZone');
var widthToScrollV = $(window).width()-((columnIndex-1)*100);
var widthToScrollH = $(window).height()-((5-rowIndex)*30);
abcDragZone.setXConstraint(0,widthToScrollV);
abcDragZone.setYConstraint(widthToScrollH,0);
if ((rowIndex !== false) && (columnIndex !== false)) {
if (sourceEl) {
abc.isDragged = true;
def.scriptGrid.isDraggableForObject = false;
def.scriptGrid.dragRowIndex = false;
d = sourceEl.cloneNode(true);
d.id = Ext.id();
d.textContent = "\$" + abc.grid.getColumnModel().getColumnHeader(columnIndex);
return {
ddel : d,
sourceEl : d,
sourceStore : v.store
}
}
}
},
getRepairXY : function() {
return this.dragData.repairXY;
},
});
}
But the problem is that the initdrag is called when the csv sheet is added to DOM. Only when its added that element can be accessed and the individual cells' drag limits can be set. So once I add a csv, the limits are not getting set. If I add it again to DOM then the limits work. Is there an option like the jQuery UI containment for draggable, here in extjs?
edit:
I even tried :
constrainTo( constrainTo, [pad], [inContent] )
body had an id of #abc
when I tried with
dragZoneObj.startDrag = function(){
this.constrainTo('abc');
};
which is a method of the DragZone class. It still did not cover the whole body tag.
I have a manage_returns_controller and it has two action,add and index.It has one product dropdown,one stock dropdown and add button.And I also have manage_products_controller that contains a field stock.But now I want to do the following
When I click on the returns controller's add button then simultaneously save the return data as well as increase the stock in the product table.
heres the add action code
function add($id = null)
{
/*$this->pageTitle = "Edit Exchange";*/
$storeval = $this->Store->find('all',array('conditions'=>array('is_deleted'=>0,'is_blocked'=>0)));
//$storeval=$this->Store->findByName();
$storevalas = array();
foreach($storeval as $storevall)
{
$storevalas[$storevall['Store']['id']] = $storevall['Store']['name'];
}
$this->set('stock_entry_option_store', $storevalas);
//$product_name = $this->Exchange->product->find('list');
$storevaldd = $this->Product->find('all',array('conditions'=>array('is_deleted'=>0,'is_blocked'=>0)));
//$storeval=$this->Store->findByName();
$product_name = array();
foreach($storevaldd as $storevall)
{
$product_name[$storevall['Product']['id']] = $storevall['Product']['name'];
}
$this->set('stock_entry_option_product',$product_name);
$this->Return->id = $id;
if(!empty($id)){
$button_name = "Update";
$msg_act = "updated";
$this->pageTitle = "Edit Return";
} else {
$button_name = "Add";
$msg_act = "added";
$this->pageTitle = "Add Return";
}
if (empty($this->data))
{
$this->data = $this->Return->read();
}
else
{
if ($this->Return->save($this->data))
{
$this->Session->setFlash(__('Return successfully '.$msg_act.'.',true),'default',array('class' => 'success'));
$this->redirect(array('controller'=>'ManageReturns','action' => 'index'));
}
}
$this->set('button_name',$button_name);
}