Tuesday, 20 February 2018

how to setup erpnext on server Port based multitenancy

Install python

apt-get install python-minimal
apt-get install build-essential python-setuptools

Install Git
apt-get install git

 Run the install script
 For Dveloper
 python install.py --develop --user frappe

For production:
sudo python install.py --production

After successfull installation switch user frappe
su frappe
then cd
then cd frappe-bench

First create your site using 
bench new-site mahesh.erpnext.comm

Then istall that site with Erpnext
bench --site mahesh.erpnext.com istall-app erpnext

Migrate your database
bench migrate

Choose your site
bench use mahesh.erpnext.com


Port based multitenancy

bench set-nginx-port mahesh.erpnext.com 9000
bench setup nginx
sudo service nginx reload

How to setup erpnext on server DNS based multitenancy

Install python

apt-get install python-minimal
apt-get install build-essential python-setuptools

Install Git
apt-get install git

 Run the install script
 For Dveloper
 python install.py --develop --user frappe

For production:
sudo python install.py --production

After successfull installation switch user frappe
su frappe
then cd
then cd frappe-bench

First create your site using 
bench new-site mahesh.erpnext.comm

Then istall that site with Erpnext
bench --site mahesh.erpnext.com istall-app erpnext

Migrate your database
bench migrate

Choose your site
bench use mahesh.erpnext.com


DNS based multitenancy
On the dns 
bench config dns_multitenant on
bench setup nginx
bench setup nginx

Port based Multitenant erpnext Setup on server

Install python

apt-get install python-minimal
apt-get install build-essential python-setuptools

Install Git
apt-get install git

 Run the install script
 For Dveloper
 python install.py --develop --user frappe

For production:
sudo python install.py --production

After successfull installation switch user frappe
su frappe
then cd
then cd frappe-bench

First create your site using 
bench new-site mahesh.erpnext.comm

Then istall that site with Erpnext
bench --site mahesh.erpnext.com istall-app erpnext

Migrate your database
bench migrate

Choose your site
bench use mahesh.erpnext.com


Port based multitenancy

bench set-nginx-port mahesh.erpnext.com 9000
bench setup nginx
sudo service nginx reload

how to group the same item in any invoice using jinja templating .

<div class="container-fluid">
<div class="row">
<table class="table table-bordered">
 <tr>
    <th style="text-align: center;">Sr. No.</th>
    <th style="text-align: center;">Item Code</th>
    <th style="text-align: center;">Description</th>
    <th style="text-align: center;">Quantity</th>
    <th style="text-align: center;">For Warehouse</th>
    <th style="text-align: center;">UOM</th>
    <th style="text-align: center;">Project</th>
   
   
  </tr>
  {% for group in doc.items|groupby('item_code') %}
  <tr>
      <td style="width: 3%;">
          {{ group.list[0].idx or ''}}
      </td>
      <td style="width: 5%;">
          {{ group.grouper or ''}}
      </td>
      <td style="width: 21%;">
          {{ group.list[0].description or ''}} 
      </td>
      <td style="width: 7%;">
      {{ group.list|sum(attribute='qty') or ''}}
         
      </td>
      <td style="width: 14%;">
          {{ group.list[0].warehouse or ''}}
      </td>
      <td style="width: 14%;">
          {{ group.list[0].uom or ''}}
      </td> 
      <td style="width: 14%;">
          {{ group.list[0].item_group or ''}}
      </td> 
  </tr>
  {%- endfor -%}
 
  </table>
</div>
</div>

Tuesday, 13 February 2018

Python Logical Not (not or !) and bitwise not(~)

Logical not it return true of false
ex
a = not True
b = not False
o/p : False
       True

Bitwise Not it return the compliment of number(1 to 0 and 0 to 1)

a = True
b = False
print ~a
print ~b
o/p
 -2
-1 

Saturday, 10 February 2018

How to get value one doctype from other doctype using custom script

frappe.ui.form.on("Material Transfer", "validate", function(frm, cdt, cdn) {
var t=cur_frm.doc.material_transfer_type ;
  default_transit_warehouse = 'aa'
  frappe.call({
         method: "frappe.client.get_value",
                async:false,
         args: {
             doctype: "Company",
             fieldname: "default_transit_warehouse",
             filters: { name: cur_frm.doc.company },
         },
          callback: function(res){
            if (res && res.message){
            default_transit_warehouse=res.message['default_transit_warehouse']
                         
            }
        } 
});
});

Add header and footer in print format

{%- macro add_header(page_num, max_pages, doc, letter_head, no_letterhead) -%}
    {% if letter_head and not no_letterhead %}
        <div class="letter-head">
            {{frappe.db.get_value("Letter Head",content,"content")}}
        </div>
    {% endif %}
       
    {% if max_pages > 1 %}
        <p style="float:left">{{ _("Page #{0} of {1}").format(page_num, max_pages) }}
        </p>
    {% endif %}
{%- endmacro -%}
<div id="header-html" class="hidden-pdf">
     <div class= "row">
            <div class="col-xs-12">
                   {{ add_header(0,1,doc,letter_head, no_letterhead) }}
                    <hr>
            </div>
       </div>
</div>

<div id="footer-html" class="visible-pdf">
<hr>
   {% if not no_letterhead and footer %}

        <div class="letter-head-footer" >
            {{ footer }}
        </div>
        {% endif %}
        <p class='text-center small page-number visible-pdf' >
            {{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }}
        </p>
</div> 

How to generate Dialog box in erpnext.

eldname': 'city','label':'City', 'fieldtype': 'Data'},
        {'fieldname': 'country','label':'Country', 'fieldtype': 'Data'},
        {'fieldname': 'phone_number','label':'Phone Number','fieldtype':'Data'},
        {'fieldname': 'postal_code','label':'Postal Code','fieldtype':'Data'},
    ],
    primary_action: function(){
        s.hide();
        console.log(s.get_values());
        //cur_frm.set_value();
        cur_frm.save();
        //show_alert(d.get_values());
    }
});
//d.fields_dict.ht.$wrapper.html('Hello World');
s.show();

Wednesday, 7 February 2018

Simple Query report

SELECT
    name,
vehicle_name as "Vehical Name:Data:120",
company_name as "Comapany Name:Data:120",
dealer_name as "Dealer Name:Data:120",
customer_name as "Customer Name:Data:120",
dealer_contact_deatail as "Dealer Contact Detail:Data:150",
customer_contact_details as "Customer Contact Detail:Data:150",
launch_date as "Launch Date:Data:120",
purchasing_date as "Purchasing Date:Data:120",
chasis_no as "Chasis No:Data:120",
licence_no as "Licence No:Data:120",
image as "Image:Data:120",
dealer_email_id as "Dealer Email Id:Data:120",
mail_id as "Mail Id Data:120",
vehicle_number as "Vehicle Number:Data:120",
uid_number as "Uid Number:Data:120",
time as "Time:Data:120",
city as "City:Data:120",
state as "State:Data:120"
from
tabBike

Simple Script report

from future import unicode_literals
import frappe
def execute(filters=None):
    columns, data = [], []
    columns = [ ("ID") + ":Link/Patient Details:140", "Patient Name:Data:140", "Address:Small Text:140", "City:Data:100", "Date of Birth:Data:100", "Gender:Data:50", "Height:Int:50", "Blood Group:Data:10", "Phone No:Data:100", "Marital Status:Data:100", "Guardians Name:Data:140", "Relationship With Patient:Data:100",
    "Age:Data:50", "Mob No:Data:100", "Total Weight:Data:0"]
    data = frappe.db.sql("""Select name, patient_name, address, city, date_of_birth, gender, height, blood_group, phone_no, marital_status, guardian_name, defender, guardian_age, mob_no, total_weight 
     from `tabPatient Information` """ , as_list=1)

    return columns, data

Tuesday, 6 February 2018

How to fetch child table content

// territory_action is child table and Customer is parent table , we have fetch weightage  from child doctype and if total is greater tha 100 then only save doctype 


frappe.ui.form.on("Customer", "validate", function(frm, cdt, cdn) {
  var i=0;
var total=0.0;
   var d = cur_frm.doc.territory_action.length;

for (i = 0; i < d; i++) {
total += cur_frm.doc.territory_action[i].weightage;
if(cur_frm.doc.territory_action[i].weightage >=100){
frappe.trow("Please Enter weightage under 100 ");
}

}
if(total >=100)
    {
    total=100;
      frappe.msgprint("Your Weightage total is",total);
}
      else{
       frappe.msgprint( "your total is =",total);
}
});

Saturday, 3 February 2018

How to add dynamic columns in custom Script report using check box and get check box event

1) add code on report_name.js file
// Copyright (c) 2016, DP and contributors
// For license information, please see license.txt
/* eslint-disable */

frappe.query_reports["Task GL"] = {
"filters": [
{
"fieldname":"doctor",
"label": __("Doctor"),
"fieldtype": "Link",
"options": "Doctor",
},
{
"fieldname":"company",
"label": __("Doctor Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company"),
"get_query": function() {
var doctor = frappe.query_report_filters_by_name.doctor.get_value();
if(doctor){
return {
"doctype": "Company",
"filters": {
"doctor": doctor,
}
}
}
},
on_change: function() {
var company = frappe.query_report_filters_by_name.company.get_value();
var html = ""
abc = frappe.call({
method: "clinic_management.clinic_management.report.general_ledger_detail.general_ledger_detail.get_letter_head",
args:
{"company":company},
async:false,
callback: function(r) {
html = r.message
}
});
frappe.query_report_filters_by_name.clinic_letter_head.set_value(html);

}
},
{
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"reqd": 1,
"width": "60px"
},
{
"fieldname":"to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.datetime.get_today(),
"reqd": 1,
"width": "60px"
},
{
"fieldname":"account",
"label": __("Account"),
"fieldtype": "Link",
"options": "Account",
"get_query": function() {
var company = frappe.query_report_filters_by_name.company.get_value();
return {
"doctype": "Account",
"filters": {
"company": company,
}
}
}
},
{
"fieldname":"voucher_no",
"label": __("Voucher No"),
"fieldtype": "Data",
},
{
"fieldtype": "Break",
},
{
"fieldname":"party",
"label": __("Party/ Hospital"),
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"group_by_voucher",
"label": __("Group by Voucher"),
"fieldtype": "Check",
"default": 1
},
{
"fieldname":"group_by_account",
"label": __("Group by Account"),
"fieldtype": "Check",
},
{
"fieldname":"show_gst",
"label": __("Show GST"),
"fieldtype": "Check",
},
{
"fieldname":"voucher_type",
"label": __("Voucher Type"),
"fieldtype": "Check",
},
{
"fieldname":"voucher_no",
"label": __("Voucher No"),
"fieldtype": "Check",
},
{
"fieldname":"party_hospital",
"label": __("Party/ Hospital"),
"fieldtype": "Check",
},
{
"fieldname":"against_voucher_type",
"label": __("Against Voucher Type"),
"fieldtype": "Check",
},
{
"fieldname":"against_account",
"label": __("Against Account"),
"fieldtype": "Check",
},
{
"fieldname":"against_voucher",
"label": __("Against Voucher"),
"fieldtype": "Check",
},
{
"fieldname":"remarks",
"label": __("Remarks"),
"fieldtype": "Check",
},
{
"fieldname":"clinic_letter_head",
"label": __("clinic_letter_head"),
"fieldtype": "Data",
"default":"",
"hidden": 1
},
]
}

2) add code on report_name.py

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe
from frappe.utils import flt, getdate, cstr
from frappe import _
from erpnext.accounts.utils import get_account_currency
from frappe.contacts.doctype.address.address import get_address_display, get_default_address

def execute(filters=None):
account_details = {}
for acc in frappe.db.sql("""select name, is_group from tabAccount""", as_dict=1):
account_details.setdefault(acc.name, acc)

validate_filters(filters, account_details)

validate_party(filters)

filters = set_account_currency(filters)

columns = get_columns(filters)

res = get_result(filters, account_details)

return columns, res

def validate_filters(filters, account_details):
print filters
filters.clinic_letter_head = "h23232323232"
filters.clinic_letter_head = "clinic_letter_head"
print filters
# if not filters.get('doctor'):
# frappe.throw(_('{0} is mandatory').format(_('Doctor')))
if filters.get('show_gst'):
company = frappe.db.get_value("Company", filters.get('company') ,"abbr")
account = frappe.db.get_value("Account", "GST - "+ company,"name")
gst_account = frappe.get_doc("Account",account)
if gst_account:
filters.account = gst_account.name
filters.party_type = ""
else:
filters.party_type = "Customer"

if not filters.get('company'):
frappe.throw(_('{0} is mandatory').format(_('Company')))

if filters.get("account") and not account_details.get(filters.account):
frappe.throw(_("Account {0} does not exists").format(filters.account))

if filters.get("account") and filters.get("group_by_account") \
and account_details[filters.account].is_group == 0:
frappe.throw(_("Can not filter based on Account, if grouped by Account"))

if filters.get("voucher_no") and filters.get("group_by_voucher"):
frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher"))

if filters.from_date > filters.to_date:
frappe.throw(_("From Date must be before To Date"))


def validate_party(filters):
party_type, party = filters.get("party_type"), filters.get("party")

if party:
if not party_type:
frappe.throw(_("To filter based on Party, select Party Type first"))
elif not frappe.db.exists(party_type, party):
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))

def set_account_currency(filters):
if not (filters.get("account") or filters.get("party")):
return filters
else:
filters["company_currency"] = frappe.db.get_value("Company", filters.company, "default_currency")
account_currency = None

if filters.get("account"):
account_currency = get_account_currency(filters.account)
elif filters.get("party"):
gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
"party": filters.party, "company": filters.company}, "account_currency")
if gle_currency:
account_currency = gle_currency
else:
account_currency = frappe.db.get_value(filters.party_type, filters.party, "default_currency")

filters["account_currency"] = account_currency or filters.company_currency

if filters.account_currency != filters.company_currency:
filters["show_in_account_currency"] = 1

return filters

def get_columns(filters):
columns = [
_("Posting Date") + ":Date:90", _("Account") + ":Link/Account:200",
_("Debit") + ":Float:100", _("Credit") + ":Float:100"
]

if filters.get("show_in_account_currency"):
columns += [
_("Debit") + " (" + filters.account_currency + ")" + ":Float:100",
_("Credit") + " (" + filters.account_currency + ")" + ":Float:100"
]

if filters.get("voucher_type"):
columns += [ ("Voucher Type") + "::120" ]
if filters.get("voucher_no"):
columns += [ ("Voucher No") + ":Dynamic Link/"+_("Voucher Type")+":160" ]
if filters.get("against_account"):
columns += [ ("Against Account")   + "::80" ]
if filters.get("party_hospital") :
columns += [ _("Party/ Hospital") + "::150" ]
if filters.get("against_voucher_type"):
columns += [ ("Against Voucher Type") + "::120" ]
if filters.get("against_voucher"):
columns += [ ("Against Voucher") + ":Dynamic Link/"+_("Against Voucher Type")+":160"]

if filters.get("remarks"):
columns += [ ("Remarks") ]

return columns

def get_result(filters, account_details):
gl_entries = get_gl_entries(filters)

data = get_data_with_opening_closing(filters, account_details, gl_entries)

result = get_result_as_list(data, filters)

return result

def get_gl_entries(filters):
select_fields = """, sum(debit_in_account_currency) as debit_in_account_currency,
sum(credit_in_account_currency) as credit_in_account_currency""" \
if filters.get("show_in_account_currency") else ""

group_by_condition = "group by voucher_type, voucher_no, account, cost_center" \
if filters.get("group_by_voucher") else "group by name"

gl_entries = frappe.db.sql("""
select
posting_date, account, party,
sum(debit) as debit, sum(credit) as credit,
voucher_type, voucher_no,
against_voucher_type, against_voucher,
remarks, against, is_opening {select_fields}
from `tabGL Entry`
where company=%(company)s {conditions}
{group_by_condition}
order by posting_date, account"""\
.format(select_fields=select_fields, conditions=get_conditions(filters),
group_by_condition=group_by_condition), filters, as_dict=1)

return gl_entries

def get_conditions(filters):
conditions = []
if filters.get("account"):
lft, rgt = frappe.db.get_value("Account", filters["account"], ["lft", "rgt"])
conditions.append("""account in (select name from tabAccount
where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt))

if filters.get("voucher_no"):
conditions.append("voucher_no=%(voucher_no)s")

if filters.get("party_type"):
conditions.append("party_type=%(party_type)s")

if filters.get("party"):
conditions.append("party=%(party)s")

if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
conditions.append("posting_date >=%(from_date)s")

if filters.get("project"):
conditions.append("project=%(project)s")

from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")
if match_conditions: conditions.append(match_conditions)

return "and {}".format(" and ".join(conditions)) if conditions else ""

def get_data_with_opening_closing(filters, account_details, gl_entries):
data = []
gle_map = initialize_gle_map(gl_entries)

opening, total_debit, total_credit, opening_in_account_currency, total_debit_in_account_currency, \
total_credit_in_account_currency, gle_map = get_accountwise_gle(filters, gl_entries, gle_map)

# Opening for filtered account
if filters.get("account") or filters.get("party"):
data += [get_balance_row(_("Opening"), opening, opening_in_account_currency), {}]

if filters.get("group_by_account"):
for acc, acc_dict in gle_map.items():
if acc_dict.entries:
# Opening for individual ledger, if grouped by account
data.append(get_balance_row(_("Opening"), acc_dict.opening,
acc_dict.opening_in_account_currency))

data += acc_dict.entries

# Totals and closing for individual ledger, if grouped by account
account_closing = acc_dict.opening + acc_dict.total_debit - acc_dict.total_credit
account_closing_in_account_currency = acc_dict.opening_in_account_currency \
+ acc_dict.total_debit_in_account_currency - acc_dict.total_credit_in_account_currency

data += [{"account": "'" + _("Totals") + "'", "debit": acc_dict.total_debit,
"credit": acc_dict.total_credit},
get_balance_row(_("Closing (Opening + Totals)"),
account_closing, account_closing_in_account_currency), {}]

else:
for gl in gl_entries:
if gl.posting_date >= getdate(filters.from_date) and gl.posting_date <= getdate(filters.to_date) \
and gl.is_opening == "No":
data.append(gl)


# Total debit and credit between from and to date
if total_debit or total_credit:
data.append({
"account": "'" + _("Totals") + "'",
"debit": total_debit,
"credit": total_credit,
"debit_in_account_currency": total_debit_in_account_currency,
"credit_in_account_currency": total_credit_in_account_currency
})

# Closing for filtered account
if filters.get("account") or filters.get("party"):
closing = opening + total_debit - total_credit
closing_in_account_currency = opening_in_account_currency + \
total_debit_in_account_currency - total_credit_in_account_currency

data.append(get_balance_row(_("Closing (Opening + Totals)"),
closing, closing_in_account_currency))

return data

def initialize_gle_map(gl_entries):
gle_map = frappe._dict()
for gle in gl_entries:
gle_map.setdefault(gle.account, frappe._dict({
"opening": 0,
"opening_in_account_currency": 0,
"entries": [],
"total_debit": 0,
"total_debit_in_account_currency": 0,
"total_credit": 0,
"total_credit_in_account_currency": 0,
"closing": 0,
"closing_in_account_currency": 0
}))
return gle_map

def get_accountwise_gle(filters, gl_entries, gle_map):
opening, total_debit, total_credit = 0, 0, 0
opening_in_account_currency, total_debit_in_account_currency, total_credit_in_account_currency = 0, 0, 0

from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
for gle in gl_entries:
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
amount_in_account_currency = flt(gle.debit_in_account_currency, 3) - flt(gle.credit_in_account_currency, 3)

if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
and (gle.posting_date < from_date or cstr(gle.is_opening) == "Yes"):

gle_map[gle.account].opening += amount
if filters.get("show_in_account_currency"):
gle_map[gle.account].opening_in_account_currency += amount_in_account_currency

if filters.get("account") or filters.get("party"):
opening += amount
if filters.get("show_in_account_currency"):
opening_in_account_currency += amount_in_account_currency

elif gle.posting_date <= to_date:
gle_map[gle.account].entries.append(gle)
gle_map[gle.account].total_debit += flt(gle.debit, 3)
gle_map[gle.account].total_credit += flt(gle.credit, 3)

total_debit += flt(gle.debit, 3)
total_credit += flt(gle.credit, 3)

if filters.get("show_in_account_currency"):
gle_map[gle.account].total_debit_in_account_currency += flt(gle.debit_in_account_currency, 3)
gle_map[gle.account].total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)

total_debit_in_account_currency += flt(gle.debit_in_account_currency, 3)
total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)

return opening, total_debit, total_credit, opening_in_account_currency, \
total_debit_in_account_currency, total_credit_in_account_currency, gle_map

def get_balance_row(label, balance, balance_in_account_currency=None):
balance_row = {
"account": "'" + label + "'",
"debit": balance if balance > 0 else 0,
"credit": -1*balance if balance < 0 else 0
}

if balance_in_account_currency != None:
balance_row.update({
"debit_in_account_currency": balance_in_account_currency if balance_in_account_currency > 0 else 0,
"credit_in_account_currency": -1*balance_in_account_currency if balance_in_account_currency < 0 else 0
})

return balance_row

def get_result_as_list(data, filters):
result = []
for d in data:
row = [d.get("posting_date"), d.get("account"), d.get("debit"), d.get("credit")]

if filters.get("show_in_account_currency"):
row += [d.get("debit_in_account_currency"), d.get("credit_in_account_currency")]

row += [d.get("voucher_type"), d.get("voucher_no"), d.get("against"),
d.get("party"), d.get("against_voucher_type"), d.get("against_voucher"), d.get("remarks")
]

result.append(row)

return result

@frappe.whitelist(allow_guest=True)
def get_letter_head(company):
company_doc = frappe.get_doc("Company",company)
html = ""
html += "<h3 class='text-left' style='font-size:20px;'>" + company_doc.name + "</h3>"
html += "<p class='text-left' style='font-size:12px;'>"
if company_doc.company_reg_no:
html += "(UEN NO:" + company_doc.company_reg_no + ")</p><pclass='text-left' style='font-size:12px; text-transform:uppercase;'>"
if get_default_address('Company', company):
address = get_address_display(get_default_address('Company', company)).replace("<br>",", ")
html += address
html += "</p><p class='text-left' style='font-size:12px; text-transform:uppercase;'>"
if company_doc.contact_no:
html += " <b>T:</b> " + company_doc.contact_no +" | "
if company_doc.phone_no:
html += " <b>T:</b> " + company_doc.phone_no +" | "
if company_doc.fax:
html += "<b>F</b> " + company_doc.fax  +" | "
if company_doc.email:
html += " <b>E:</b> <span style='text-transform:lowercase;'>" + company_doc.email 
html += "</span></p>"

return html

Friday, 2 February 2018

Add custom button in form

frappe.ui.form.on("Sales Invoice", "refresh", function(frm) {
    frm.add_custom_button(__("Do Something"), function() {
        // When this button is clicked, do this

        var subject = frm.doc.subject;
        var event_type = frm.doc.event_type;

        // do something with these values, like an ajax request
        // or call a server side frappe function using frappe.call
        $.ajax({
            url: "http://example.com/just-do-it",
            data: {
                "subject": subject,
                "event_type": event_type
            }

            // read more about $.ajax syntax at http://api.jquery.com/jquery.ajax/

        });
    });
});

Generate dialog box and get and select value and set in another doctype

//popup

var d = new frappe.ui.Dialog({
  title: __("Get Item from Quote"),
  fields: [

      {
        "label": __("Quotation"),
        "fieldname": "quotation",
        "fieldtype": "Link",
        "options": "Quotation",
        "reqd": 1
      },
      {
        "fieldname":"sb1",
        "fieldtype":"Section Break",
      },
      {
        "label": __("html"),
        "fieldname": "my_html",
        "fieldtype": "HTML",
        "options" : "Items from quote<br>",
      },
      {
        "label": __("Add Items"),
        "fieldname": "Add Items",
        "fieldtype": "Button",
        "class":"add_items",
        "options" : "Add Items from quote<br>",
      },
      ],
      primary_action_label: "Get Items",
      // secondary_action_label: "Add Items",
      primary_action: function(){
       //msgprint("hi");
       args = d.get_values();
       if(!args) return;
       // console.log(args.quotation);
       qtn_no = args.quotation;
       frappe.call({
           method: "frappe.client.get_list",
           args: {
               doctype: "Quotation Item",
               fields: ["item_code", "item_name","qty","name","rate","amount"],
               filters: { 'parent':  qtn_no },
           },
              callback: function(res){

                if (res && res.message){
                  console.log("res",res)
                  html = "Items from<br>"
                  html += "<table border=1 style='width:100%' >"
                            +"<tr><th>Code</th><th>Name</th><th>Quantity</th><th>Rate</th><th>Amount</th></tr>"
                            // +"<tr>"
                            for (var i = 0; i<res.message.length; i=i+1) {
                              // html += "<tr><td>" +"<p><input type='checkbox' class='select' name='sport' value='+res.message[i].item_code' id='select' </p>"+"</td><td>" +res.message[i].item_code+"</td><td>"
                             html +="<tr><td>"+ "<p><input type='checkbox' class='select' id='select' name='items'"
                                    +"' value='"
                                +res.message[i].item_code
                                    +","
                                +res.message[i].item_name
                                    +","
                                +res.message[i].qty
                                    +","
                                +res.message[i].rate
                                    +","
                                +res.message[i].amount
                                    +"'> "
                                    +res.message[i].item_code
                                    + "</p></td><td>"
                              +res.message[i].item_name+"</td><td>"
                              +res.message[i].qty+"</td><td>"
                              +res.message[i].rate+"</td><td>"
                              +res.message[i].amount+"</td></tr>"
                          }                       
                        +"</table>"
                  $("#select").append("sam");
                  var wrapper = d.fields_dict.my_html.$wrapper;
                  wrapper.empty();
                  wrapper.html(html);
                }
               
              }   
       });
     
     }
 });
d.show();

var item_list = [];
var list=[];
$("button:contains('Add Items')").click(function(){

            $.each($("input[name='items']:checked"), function(){           
                item_list.push($(this).val());

            });
            console.log("Selected Items are: " + item_list.join(", "));
            list.push(item_list.join(", "));
            console.log(list)

            item_list.forEach(function(element) {
              console.log("length of element is :",element.length)
              var row = frappe.model.add_child(cur_frm.doc, "Sales Order Item", "items");
              list=element.split(",")
              console.log("list of element :",list);
              row.item_code = list[0];
              row.item_name =list[1];
              row.qty=list[2];
              row.rate = list[3];
              row.amount = list[4];
              //add child
              console.log("in row",row)
            });
             refresh_field("items");
             console.log("items",item_list)
});

Django rest api - filter

views.py from django_filters.rest_framework import DjangoFilterBackend class PollList(viewsets.ModelViewSet):     queryset = X.objects...