How to get child table values in frappe.route_options along with Parent table values - erpnext

In sales order , I have a button for creating Allotment which is a custom doctype. Using frappe.set_route I am able to get parent table values but not sure how to get child table values along with it. Kindly help, thanks!
frappe.ui.form.on('Sales Order', 'refresh', function(frm) {
frm.add_custom_button(
__('Make Allotment'),
function() {
frappe.route_options = {
customer: cur_frm.doc.customer,
sales_order: cur_frm.doc.name,
delivery_date: cur_frm.doc.delivery_date,
set_warehouse: cur_frm.doc.set_warehouse
};
frappe.set_route('Form', 'Allotment', 'New Allotment');
},
__('Make Allotment')
);
});

Related

react-bootstrap-typeahead: How to get attribute value on "OnChange" , I am using Typeahead in table cell

I am using react-bootstrap-typeahead in table row for invoice items.
my json is like [{record_id:1,value="value1"},{record_id:2,value="value2"}]
on this basis I am creating bootstrap table.
in table cell I am adding typeahead select box to change the value and update my json,
when I change the value I want to update my json array with latest value in related record.
But as in onChange we only get selected array not an event object so, I am not able to find record id.
I have create one solution , I know it is not best but it works for me.
I have set state called currentLineItem and I am updating this value on "onFocus" event of react-bootstrap-typeahead. in this event I am getting an event object.
const [currentLineItem, setCurrentLineItem] = useState(null);
const selectBoxOnFocus = (event) => {
const rowId = event.target.parentNode.parentNode.parentNode.parentNode.getAttribute("data-id");
setCurrentLineItem(rowId);
};
const taxCalcChangeInRow = async (option) => {
const rowId = currentLineItem;
// my other code
};
<SelectBox {/*(this is wrapper componat of typeahead)*/}
data-id={row.id}
name="inputTaxCalc"
options={taxCalcOptions}
OnChange={taxCalcChangeInRow}
onFocus={selectBoxOnFocus}
/>

ServiceNow REST API: Get list of column names

From the admin UI, there is a Tables and Columns explorer that dutifully shows all available columns for a table, such as the incident table:
My ultimate goal is to be able to query all fields for a given table that I can insert data to (mostly centered around incident and problem tables), match that against what data I have, and then insert the record with a PUT to the table. The immediate problem I am having is that when I query sys_dictionary as various forums suggest, I only get returned a subset of the columns the UI displays.
Postman query:
https://{{SNOW_INSTANCE}}.service-now.com/api/now/table/sys_dictionary?sysparm_fields=internal_type,sys_name,name,read_only,max_length,active,mandatory,comments,sys_created_by,element&name={{TableName}}&sysparm_display_value=all
I understand the reduced result set has something to do with them being real columns in the table vs. links to other tables but I can't find any documentation describing how to get the result set that the UI has using the REST api.
The follow on problem is that I can't find an example with an example payload where all standard fields have been filled out for the incident table so that I can populate as many fields as I have data for.
The reason you don't get all the columns back is because the table you are querying inherits from another table. You need to go through all the inheritance relationships first, finding all parent tables, then query the sys_dictionary for all of those tables.
In the case of the incident table, you need to query the sys_db_object table (table of all tables) to find the parent, which is the task table. Then query the sys_db_object table again to find its parent, which is empty, so we have all the relevant tables: incident and task. Obviously, you would want to write this code as a loop, building up a list of tables by querying the table at the end of the list.
Once you have this list, you can query sys_dictionary with the query: sysparm_query=name=incident^ORname=task, which should return your full list of columns.
I think you could do this by creating your own scripted rest api and iterating/inspecting the fields:
(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
var queryParams = request.queryParams;
var table = queryParams.table;
var t = new GlideRecord(table);
t.initialize();
var fields = t.getElements(); //or getFields if global scope
var fieldList = [];
for (var i = 0; i < fields.length; i++) {
var glideElement = fields[i]; //or field.get(i) if global scope
var descriptor = glideElement.getED();
var fldName = glideElement.getName().toString();
var fldLabel = descriptor.getLabel().toString();
var fldType = descriptor.getInternalType().toString();
var canWrite = glideElement.canWrite();
if (canWrite){
fieldList.push({
name: fldName,
type: fldType,
label: fldLabel,
writable: canWrite
});
}
}
return fieldList;
})(request, response);
This should save you the hassle of determining the inheritance of fields. Here's the sample output:
{
"result": [
{
"name": "parent",
"type": "reference",
"label": "Parent",
"writable": true
},
{
"name": "made_sla",
"type": "boolean",
"label": "Made SLA",
"writable": true
},
...

UI5 - how to dynamically bind data to a Select in Table, depending on another combobox?

I have a classic situation - a table with two comboboxes (or, to be exact, sap.m.Select controls) and after select in the first one, I would like to have the values in the second one updated. This is my model, basically, the first combobox should contain the list of available states and once some is selected, the second sap.m.Select control should be populated by relevant cities
{
countries: [
{ country: 'France', cities: ['Paris', 'Marseille', 'Lyon']},
{ country: 'Germany', cities: ['Berlin', 'Bonn']}
]
}
The problem is that I dont know how to do it. I am able to get the id of the updated row using something like this.
onCountryChange: function (oEvent) {
const selectedItem = oEvent.getParameter("selectedItem");
var path = selectedItem.getBindingContext().getPath();
bindComboBox(path); // this should rebind the data, but not written yet
}
I know now I should rebind the data in the correct combobox, however, I don't know how to affect only that single combobox on the correct row and how to update it. Could someone advise me how to do it? The whole table is defined in the .xml view, can I do it also with a formatter or inline expression or is this scenario too difficult for that?
Thank you
You can use the bindAggregation method (from the ManagedObject) class to rebind the combo boxes' items.
onCountryChange: function (oEvent) {
const selectedItem = oEvent.getParameter("selectedItem");
var path = selectedItem.getBindingContext().getPath();
this.byId("combo2").bindAggregation("items", {
path: path + "/cities",
template: new sap.ui.core.Item({
key: "{}",
text: "{}"
})
});
}
Note: Replacing "combo2" with the id of your 2nd combo box/select control.
Edit: To get the correct combo box (assuming you have multiple created on a table, use the ID of the first combo box (oEvent.getSource().getId()) to generate the ID of the 2nd combo box. Without knowing more of the structure of the table (and how it's created) I can't offer more.

How to allow editing of cells within SAPUI5 Table

Can you please show me how to allow editing of cells within SAPUI5 table? I am using JSON model.
look at this examples in the SDK Table.html, both of the examples show how to set a json model, set the json model as a data source of a table control, how to bind rows of the json to rows of the table, and how to bind the values to cells, once you change the cells values the new value will be reflect in the model
var employeeData = [
{lastName: "Dente", name: "Al"},
{lastName: "Friese", name: "Andy"},
{lastName: "Mann", name: "Anita"},
{lastName: "Schutt", name: "Doris}
];
//create the JSON model and set your data
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({ Employees: employeeData });
//create table
var oTable = new sap.ui.table.Table();
//add a column for lastname and bind the value to an editable textview
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Last Name"}),
template: new sap.ui.commons.TextView().bindProperty("text", "lastName"),
});
//add a column for name and bind the value to an editable textview
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "First Name"}),
template: new sap.ui.commons.TextField().bindProperty("value", "name"),
}));
oTable.setModel(oModel);
oTable.bindRows("/Employees);
First your table template objects have to be editable. For a textfield either use the setEditable(true), bindProperty('editable',true) or directly in the construtor new TextField({editalbe:true}).
If it is editable ensure you have switched on two way binding in your model. For JSON models this is the default I think. Also ensure, that there are no formatters involved, because these will destroy two way binding.
The you can check in your debugger, if the changes on the UI are transfered to the model. In general this works fine and from this point it is up to you what to do with the model (send it to some oData save service).
I had the same issue with a table that had to be editable when the value was zero and non-editable when it was greater than zero.
Value1 is my dinamic value.
Value2 is zero
<Input type="Number" editable="{parts:[{path : 'Value1'}, {path : 'Value2'}], formatter:'sap.ui.app.model.formatter.CantEditable'}"/>
Inside the formatter i defined a function called CantEditable like this.
jQuery.sap.declare("sap.ui.app.model.formatter");
sap.ui.app.model.formatter =
{
function1: (Value1, Value2)
{
//If value 1 > Value 2 return editable
if (Value1>Value2)
{
return false;
}
else
{
return true;
}
};
Since its binded to the value of these two variables. Whenever my value one changes, the editable function will check if it meets the requeriments of the function. Then it will change the value of the editable property.
My sap.m.Table demo here:
http://plnkr.co/edit/qifky6plPEzFtlpyV2vb?p=preview
I am using data-sap-ui-theme="sap_belize", you can change it to sap_bluecrystal.
The basic idea is using editable property of sap.m.Input, and enabled property of sap.m.Select.
I opened an issue of ui5 to discuss this problem: https://github.com/SAP/openui5/issues/1646

How do I get values from the link table in DBIx::Class?

In my app I have 2 table, books and tags, and the link table book_tags. The link table also contains the number of times the book was tagged with this particular tag. I can add a tag by doing
$book->add_tag($tag, { tag_count => 10 });
However when I retrieve the tags for a book
#tags = $book->tags();
it does not seem to return the values from the link table.
Is there a way to get the values from the link table without doing it by hand?
Since you have a join table named book_tags, you will have to create a many_to_many relationship from the books table to the has_many relation of the books table itself. The has_many relation should retrieve the ids of the tags associated with the book from the table book_tags. You may have to add relationships similar to:
In Your::App::Schema::Result::Book:
__PACKAGE__->has_many( book_tags => 'Your::App::Schema::Result::BookTag', 'book_id' );
__PACKAGE__->many_to_many( tags => 'book_tags', 'tag' );
In Your::App::Schema::Result::BookTag:
__PACKAGE__->belongs_to( tag => 'Your::App::Schema::Result::Tag', 'tag_id' );
You can proxy properties through relationships like this:
Schema::Tag->has_many('book_tags' => 'Schema::BookTag',
undef, {
proxy => [ 'tag_count' ],
}
);
Then you can access 'tag_count' like this:
my $tag_rs = $book->tags;
for( my $tag = $tag_rs->next ){
print $tag->tag_count;
}
You can find more at the relationship docs.
Thanks! I have already done this part, and it works.
My tables look like this:
BOOK:
book_id book_title [other fields]
TAG:
tag_id tag_name [other fields]
BOOK_TAG:
book_id tag_id tag_count
So I have a many-to-many relationship between tags and books with an additional attribute, tag_count, which is stored in the link table.
I can add a tag to a book by doing
$book->add_to_tags($tag, { tag_count => 10 } );
which populates the tag_count field in the BOOK_TAG table.
But when I do
$book->tags();
it does not automatically retrieve tag_count field from BOOK_TAG. I can write
$tag = $schema->resultset('BookTag')->find( { book_id=>$book->book_id, tag=>$tag->tag_id });
$tag_count = $tag->tag_count();
I'm trying to see if there is an easier way to get the extra attribute from the link table.