Modfying Item Code filter based on Sales Order selection

Hi

Busy with some server side scripting. 95% complete on this one.

Goal: When “sales_order” field is selected, filters for “item_code” field must be set
so that user can only select items that are on that sales order.

JS file in …/doctype/bdh/bdh.js

frappe.ui.form.on('BDH', {
//  refresh: function(frm) {

//  }
	//..............
	//..............
	// other code
	//.............

    },
    sales_order: function(frm) {
        if (frm.doc.sales_order) {
            return frm.call({
                method: "get_customer",
                doc: frm.doc,
                callback: function() {
                    refresh_field('customer');
                }
            });

    
            frm.set_query('item_code', function() {
                return {
                    filters: [
                        ['Item', 'name', 'in', itemCodeOptions]
                    ]
                };
            });
        }
    }
});


PY file in …/doctype/bdh/bdh.py

import frappe
from frappe.model.document import Document


def get_template_details(template):
	//......
	// other code
	//.........



class BDH(Document):

    def validate(self):
        frappe.msgprint("Validate")

	//...........
	// other code
	//.............


    @frappe.whitelist()
    def get_customer(self):
        if self.sales_order:
            sales_order_doc = frappe.get_doc("Sales Order", self.sales_order)
            self.customer = sales_order_doc.customer
            self.set_item_code_filters()

    @frappe.whitelist()
    def set_item_code_filters(self):
        if self.sales_order:
            # Filter item codes based on the selected sales_order
            item_codes = frappe.get_all("Sales Order Item",
                filters={"parent": self.sales_order},
                fields=["item_code"]
            )
            item_code_list = [item.item_code for item in item_codes]

            # Get the item_code_options and initialize it as an empty list if it's None
            item_code_options = self.get("item_code")
            if item_code_options is None:
                item_code_options = []

            item_code_options[:] = []  # Clear existing options
            for item_code in item_code_list:
                item_code_options.append({"item_code": item_code})

I have used bench --site console and ran the commands in my code through console and it seems that
“item_code_options” contains the correct dict / array of items codes that must be available for selection
in “item_code” by the user. So I added the “set_query” in my JS code,but I am not getting the result
I want.

Can someone offer some guidance as to the correctness of my set_query command ? Please ?

Thank you

Update …

In my JS-code I placed a console.trace statement and got “undefined”
I then modified my code so that “item_code_options” is returned in the
“get_customer” method.

Now I dont get any errors anymore, but the filter string when I select the
“item_code” field, is empty.

My console.trace confirms this.

I am missing something. Please could someone assist? I am 99% complete now
with my project.

Thank you

Please find below all info…

JS-code

    sales_order: function(frm) {
        console.log("Sales Order code");
        frappe.show_alert("Sales Orer Code", 5);
        if (frm.doc.sales_order) {
            return frm.call({
                method: "get_customer",
                doc: frm.doc,
                callback: function(r) {
                    refresh_field('customer');
                    frappe.show_alert("Refresh", 5);

                    var Item_Code_Options = r.message.Item_Code_Options;
                    console.trace(Item_Code_Options);
                    frm.set_query('item_code', function() {
                        return {
                            filters: {
                                item_code:  ['in', Item_Code_Options],
                            },
                        };
                    });

                }
            }); 
        }
    },
PY-code


    @frappe.whitelist()
    def get_customer(self):
        if self.sales_order:
            sales_order_doc = frappe.get_doc("Sales Order", self.sales_order)
            self.customer = sales_order_doc.customer
            self.set_item_code_filters()
            return {
                "Item_Code_Options": self.item_code_options
            }



    @frappe.whitelist()
    def set_item_code_filters(self):
        if self.sales_order:
            # Filter item codes based on the selected sales_order
            item_codes = frappe.get_all("Sales Order Item",
                filters={"parent": self.sales_order},
                fields=["item_code"]
            )
            item_code_list = [item.item_code for item in item_codes]

            # Get the item_code_options and initialize it as an empty list if it's None
            item_code_options = self.get("item_code")
            if item_code_options is None:
                item_code_options = []

            item_code_options[:] = []  # Clear existing options
            for item_code in item_code_list:
                item_code_options.append({"item_code": item_code})


bench console

Apps in this namespace:
frappe, erpnext, custom_app

In [1]: item_codes = frappe.get_all("Sales Order Item", filters={"parent": "SAL-ORD-2023-00015"}, fields=["item_code"])

In [2]: item_code_list = [item.item_code for item in item_codes]

In [3]: selfdoc = frappe.get_doc("BDH", "QUAL-BDH-2023-00026")

In [4]: item_code_options = selfdoc.get("item_code")

In [5]: item_code_options = []

In [6]: for item_code in item_code_list: item_code_options.append({"item_code": item_code})

In [7]: item_code_options?
Type:        list
String form: [{'item_code': 'S2C00004'}, {'item_code': '1R-001'}]
Length:      2
Docstring:
Built-in mutable sequence.

console.trace(Item_Code_Options);   //in JS-code


console.trace() 
Array []
?
length: 0
?
<prototype>: Array []
??
at: function at()
??
concat: function concat()
??
constructor: function Array()
??
copyWithin: function copyWithin()
??
entries: function entries()
??
every: function every()
??
fill: function fill()
??
filter: function filter()
??
find: function find()
??
findIndex: function findIndex()
??
findLast: function findLast()

Thank you