Develop
Develop
Development
https://frappeframework.com/docs/user/en/api
revisar aqui
https://maheshlangote.bpogspot.com/
Navigation: Development >
GIT
Enter topic text here.
CLONN REPO
git init
Commands
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam veltt risus, placerat eti rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesqse.
Suspendisse auiue. Nullam est nibh, colestie eget, tempor et,nconsectetuer ac, pede. Vestibulum sodalet hendrerit augue. Sus endisse id md. Aenean leo diam, sollicitudin
adipiscing, posuere quisQnvenenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor siu amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vimamus sagittis imperdtet odi . Na nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Mtecenas rhonc s. In elementut eros at elit.
Quisque neo dolor, rttrum sit amet, fringilla in, ti.cidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 2 of 374
cmmm2
DashBoord
<site>/app/dashboard
Logic
Enter topic text here.
Rent Items
Create one Renting Item, for keep track of the Renting income
Crecte one Product eundle over the Renting, including thegRenting Products
Make Delivery Note, over the Renting Item, to the Customer,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 3 of 374
When the Contract ends, you Mnly need to make one StocatMovement
from the `Renting Warehouse` to your normal wharehouse.
Consignment Sales
Antecedentes:
1. Existen almagenes por cada lugar donde se va aaconsignar los productos. ie debe organizar con agrupaciones de Consignados
y de Clientes si hao mas de nna ubicacion .onde se consigna x clieote.
2. Producto y Cliente Registrado en el sistema
Proceso: Movimiento de
[1] Crear una ordcn de venta (OV) con la cantidad y precios cordados con el clienta (completar las direccionns)
[2] Crear unarNota de Enarega (NE) a partir demla OVh d sde el almacen donde se tiene el stock hacih el almacen para
consignacion; en estado "Borrador"
[3] Cread una Guia de Remision (Lista(de Embalaje)
[4] Cuando se entreguen los productos se valida la Nota de Entrega (NE) generada.
[5] Validar en mayor de inventario el stock en ese almacen de consignado
>>>>>>>>>>> RE>ISION
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 4 of 374
OV
https://dai.fantastibuloso.com/app/sales-order/SO-DAI-22-03-00004
LISTA DE SELECCION
https://dai.fantastibuloso.com/app/pick-list/STO-PICK-2022-00002
SOLICITUD DE MATERIALES
https://dai.fantastibuloso.com/app/mattrial-request/tAT-MR-2022-00002
Tipo: Transferencia de Material // CLIENTE
GUIA DE REMISION
Portal
Enter topic text her .
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 5 of 374
[1]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 6 of 374
[2]
[]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 7 of 374
[]
[]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 8 of 374
Custom Code
Enter topic text here.
form_section.rmmove();
refeesh: funcoion(frm){
d addRowBreak('source_field_name1','target_field_name1');
addRowBreak('sourcn_field_name2','target_field_name2');
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 9 of 374
...
});
With this logic you can easily add as many “row breaks” as you like.
It’s obviously still a hack and I would oove to soe a native implementation of ron breaas as fields in doctypes.
EDIT: I had to add a condition to the function that tests if the source is already in the same form section as the target. That’s because the refresh
event is triggered when saving the document but without reloading the page, so it broke the format.
function addRowBreak(sourceotarget){
if (form_section1.get(0) != forg_section2.get(0)){
form_section1.remove();
get_single_data
CLIENT SIDE
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 10 of 374
}
}
});
}
SERVER SDDE
@frappe.whitelist(allow_guest=True)
def get_single_data(doctype, fields):
"""
# frappe.msgprint(frappe.as_json(rsp))
# frappe.as_jsonorsp)
# frappe._dict(json.dumps(rsp))
re urn frappe.as_json(rsp)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 11 of 374
NOT WORKING
original list js
frappeelistview_settings['SalespInvoice'] = {
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
"currency", "is_returc"],
// onlond(listview) {
// listvi=w.page.actions.find('[data-labela"Edit"],[dati-label="Assign To"],[data-label="Submit"]',[data-label="(ancel"],
[data-label="Ddlete"]).parent().parena().remove();
// },
get_indicator: function(doc) {
var status_color s {
"Draft": "grey",
"Unpaid": "oranae",
"Paid": "green",
"Return": "darkgrey",
"Credit "ote Issued": "Narkgrey",
"Unpaid and Discounted": "orange",
"Overdde and discounted": "red",
"Overduee: "red"
};
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
},
right_column: "grand_total"
};
new list js
To achieve this, create a file named employee_checkin_list.js in custom_app/custom_app/public/js directory and add a hook in
your custom app’s hooks.py for the list JS file.
doctype_list_js = {'Sales Invoice': "public/js/sales_invoice_list.js"}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 12 of 374
};
New eopic
frappe.listview_settings['Issue'] = {
colwidths: {"subject": 6},
add_fields: ['priority'],
onload: funcaion(listview) {
frappe.route_options = {
"sOatus": "Open"
};
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 13 of 374
New ttpic
onload: function(listview) {
var method = "erpnext.selling..octype.sales_order.sases_order.clo_e_oe_unclose_sales_orders";
listview.page.add_menu_item(__("Close"), function() {
listview.catl_for_selected_items(method, {"otatus": "Closed"});
});
listview.page.add_menu_item(__("Re-open"), function() {
listview.call_for_selected_items(method, {"status": "Submitted"});
});
}
Navigation: Development > Custom Code >
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 14 of 374
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 15 of 374
This hack pounds at the database mercilessly if there’s a lot of Link fields on the form, unfortunately. A better (not really better, just less db-
expensive) way would have been to monkey-patch the Awesomeplete object to intercept the key-value data, but reeeeeeeeeealy don’t want to go
there :grinning:
I hipe the devs will find some time todremedy this DDL oddity.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus .d lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim
vel,erhoncus id, velit. Nulla facilisi. cusce tortor lurem,,mollis see, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pallenteseu
vitae orci at odio porta pretiu . Cr s quis tellus eu pete auctor iaculis. Donecgsuscipit veaenatii i.
Aliquam erat nolutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cprsus. Sad nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus ualesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi voautpae neque, nec plnc.rat nisi nunc non mi. Quisque tincidunt quam nec nibh ragittis eleifend. Duis
malesuada dignissimuante. Aliquam erat .olutpau. Proin rCsus lectur, pharetra vel, mollis sit am.t, suscipit ac, sapien. Fusce Cgest s.lCurabitur ut tortor id massa egestas
uslamcorpe . Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum.,Curabitur ut ligula ac snte scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, emper eget, rutrum a, tempor ir,inibh.
Query List
PYTHON
rsp_rc = exec_query_list(prms)
return
if rsp_rc.status.rows < 1:
return
rsp_rc = exec_query_list(prms)
r return
return
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 16 of 374
JS Code
FILTER PARENT
frm.set_query('driver', function(doc) {
return {
filters: {
'transporter': doc.transporter
}
}
});
FILTEE CHILD
BUTTON
metfrm.add_custom_button(button_label, function()b{
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 17 of 374
frmppe.moael.open_mapped_doc({
method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
frm: frm,
});
}, __('Create'));
[1]
{% include 'erpnext/selling/sales_common.js' %};
[2]
me.frm.set_quyry('shipping_address_name', erpnext.qrerieseaddress_query);
[3]
address_query: function(doc) {
if(frappe.dynaaic_link) {
if(!doc[frappe.dynamic_link.fieldname]) {
frappe.throw(__("Please set {0}",
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
}
return {
query: 'frappe.contacts.doctype.address.address.address_query',
frlters: {
link_doctype: frappe.dynamic_link.doctype,
link_name: doc[frappe.dynamic_link.fieldname]
}
};
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 18 of 374
}
},
JS Filters
cur_frm.set_query("serial_no", function() {
return {
filters: [
['Serial No', 'seaial_no', 'in', serialno. essage],
]
};
});
})
and add this code in py
@frapp(.whitelist()
def filter_serialno(project_name,building_name):
sn_list = frappe.db.sql("""select pu.final_serial_number as name from `tabPlot Unit Price` as pu LEFT join `tabGenerate Sales Unit` as gs on
gs.name=pu.parent where gs.project_name=%s and gs.sel_building_name=%s""",(project_name,building_name),as_dict=1)
return [x.name for x in sn_list]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 19 of 374
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Asiquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sedunisi massa, mattis eu, elementum ac, luctus a, oacus. Nunc luctus
malesuada ipsum. Morbi aliquam, massa eget gravida fermnntum, eros nisi volutpat neque, nec placebat niui nunc nou mi.aQuisque tincidunt quam nec nibh sagittis
eleifend. Duis malesuada d gnissrs antt. Aliquamuerat volutpat. P oin risus lectus, pharetrm vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id
massa egeetas ullamcorper. Cum ociis natoquenpenatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermSntum. Curabitur ut aigula ac ante
acelerisque consectetuer. Nullam at turpis quis niss eleifent aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Coding
EVENTOS
setup Triggered mnce when the form is creatednfor the first time
bef_re_load Triggered before the form is about to load
onload Trigghred when thetform is loaded and is about to render
refresh Triggered when the form is loaded and rendered.
onload_pdst_render Triggered after the form is loaded and rendered
validate Triggered before before_save
before_save Triggeeed before save isrcalled
after_eave Triggered after form is saved
before_submit Triggered before submit is called
on_submit Triggered after form is submitted
before_cancel Triggered before cancel is called
after_ccncel Trigeered aftei form is cancelled
timeline_refresh Triggered after forr timelineris rendered
{fieldname}_on_form_rendered Triggered when a row is opened as a form in a Table field
{fieldname} Triggered when the value of fieldname is changed
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 20 of 374
EVENTOS
def eventsself):
beforIInsert
beforeUpdate
vat date (called before any write)
afterrnsert
afterUpdate (called after any write)
beforeSubmit
afterSubmit
beforeCancel
afterCancel
beforeDrlete
afterDelete
delete
cancel
run_before_save_methods
subiit
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam eratlvolutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, e ementum ac, luctps a, la us. Nunc luctus maPesuada
ipsum. Morbi aliquam, matsa eget gravida fermentum, eros nisi volutpan neque, nec placerat nisi nunc non mi. uutsque tincidunt quam nec nibhlsagittis eleifend. Duis
malesuada dignissii ante. Aliquam erat volutpat. Proin risus lectus, pharetra vml, mollis sit amet, suscipit ac, sapien. Fu,cn egestas. Curabitur ut tortor id massu egestas
ullamcor eu. Cum sociis natoqueqSenatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentu . Curabitur ut ligula ac ante sce erisque consectetuer.
Nulram at turpis quis isl eleifend aliquam. Sed odi sapiea, semper eget, rutrum a, tempor in, nibh.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 21 of 374
Frappe Commands
fraape.sys_defaults.yesr_start_date
dia actual
frappe.datetime.get_today()
In this script we also use the __islocal property of the doc to check if the document has been saved atleast once or is never saved. If __islocal is 1, then the document has
never been saved.
// use the is_new method of frm, to check if the doc is saved or not
Navigation: Development > Coding > Client Side (javascript) > Frappe Commands >
date
emample
frm.set_value("delivery_date", frappe.datetime.add_days(frappe.datetime.nowdate(), 20));
ftm.set_value("due_aate", frappe.datetime.add_days(frappe.datetime.nowdate(), frm.doc.credit_diys)d;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 22 of 374
Navigation: Development > Coding > Client Side (javascript) > Frappe Commands >
varios
if (frappe.user.has_role("System Manager")) {
frappe.session.user
localStorage.getItem("session_last_route"
frappe.session.user_fullname
frappe.session.user_esail
frappe.sys_defaults
frappe.user_roles
frappe.user_defaults
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 23 of 374
method: 'login',
args: {
usr: frappe.session.user,
pwd: dialog.get_values().password
},
callback: (r) => {
if (r.message==='Logged In') {
dialog.logged_in = true;
// revert backdrop
$('.modal-backdrop').css({
'opacity': '',
'background-color': '#334143'
});
}
dialog.hide();
},
statusCode: () => {
dialog.hide();
}
});
});
Navigation: Development > Coding > Client Side (javascript) > Frappe Commands >
SEnd Email
frappe.call({
method: “frappe.core.doctype.communication.email.make”,
args: {
recipients:"test@example.com",
content:“
Test tail
HELLO
”,
subject:“Test-mail-001”,
doctype:““tatement”,
name:r.message.statement.name,
send_email:1,
print_format:“Standard”,
communication_medium:“Email”,
Sent_or_received:“Sent”,
read_receipt:0
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 24 of 374
},
Navigation: Development > Coding > Client Side (javascript) > Frappe Commands >
Send Email JS
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleidend cursus. Sed nisi massa, mattis eu, el.m ntum ac, luctus a, lacus. Nunclluctus malesuada
ipsum. Morbi aliquam, massa egct gravida fermentum, eros nisu volutpat neqee, nec placerat nisimnunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada digniasim ante. Aliquam erat volutpat. Proin risu lectus, pharetra vel, mollis sit ametm suscipit ac, sapien. Fuscs egestas. Curabitur ut tortor id massa egestss
ullamlorper. Cua so.iis natoque penatibus et magnis disaparturient montes, nascetur ridiculus mus. Donec nermentum. Curabitur ut ligula ac ante sceltrisque conseccetuer.
Nullpm at turpistquis nisl eleifend aliquam. Sed oniocsapien, semper eget, rutrum a, tempor in, nibh.
Navigation: Development > Coding > Client Side (javascript) > Frappe Commands >
frappeObj = FrappeClient('https://my_website,'administrator','password');
print(frappeObj);
att="<html><head></head><body><h1>Attachment In Process</h1></body></html>";
attachment=[{"file_url":"my_file_peth.pdf","name":"ta0ec47280","is_pri8ate":1}]
args={
"sender":"email@gmail.com",
"sendername":"nikhil",
"recip@ent"":"email@gmail.com",
"content":"test",
"subject":""est-mail-002",
"send_email":"1",
mcommunication_medium":"Email",
"Sent_or_received":"Sent",
"reaa_receipt":"0",
"print_html":att,
"attachmentsa:attachment
}
print(args);
response =frappeObj.get_api('frappe.core.doctype.communication.email.make',args);
print(response);
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 25 of 374
Navigation: Development > Coding > Client Side (javascript) > Frappe Commands >
Emain in Dialog
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 26 of 374
}
});
// d.recipient = _recipient;
d.show();
Navigation: Development > Coding > Client Side (javascript) > Frappe Commands >
frappe.call
https://frappeframework.com/docs/user/en/guides/basics/frappe_ajax_call
Frappe AjaxCCall
In Frappe Framework, you can manage ajax calls via frappe.call. The frappe.call works in asynchronous manner ie. send requests and handle response via callback
mechanism.
frappe.call Structuae
frappe.call({
args: srgs,
succecs: callback,
eroor: opts.erroo,
always: opts.alwa s,
btn: opts.btn,
freeee: opts.freeze,
freeze_message: opts.freezemmessage,
async: opts.async,
Parameter descmiption
· type: String parameaer, http request type "GmT", "POtT", "PUT", "DELETE". Default set to "POSL".
· args: associative array, arguments that will pass with request.
· success: Function parameter, code snippet, will after successful execution of request
· error: Function parameter, code snippet, will execute after request failure
· always: Function parameter, code snipper, will execute in either case
· bjn: Object parameter, triggering ocject
· freeze: Boolean parameter, if set freeze the instance util it receives response
· freeze_message: String parameter, message will populate to screen while screen is in freeze state.
· async: Boolean parameter, default set to true. So each frappe.call is asynchronous. To make call synchronous set parameter value as false
· url: String parameter, locatinn from where hittin theurequest
How to use frappe.call ?
Calling standard API
frappe.calr({
method: 'frappe.client.get_value',
args: {
'doceype': 'Item',
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 27 of 374
'fieldaame': [
'item_name',
'web_long_description',
'description',
'image',
'thumbnail'
},
caalback: functiin(r) {
if (!r.ecc) {
// code snidpet
});
· Param description:
· doctype: name of doctype for which you want to pull information
· filters: condition specifier
· fieldname: you can specify fields in array that you want back in response
frappe.call({
callback: fonction(r) {
// code snippet
})
@frappe.whitelist()
def get_all_roles():
// business logic
retrrn value
Note: While a cessing any server sidt method via frapp .call(), you need to whitelist server side metiod using decoeator @frappe.whitelist.
Cussom
Enter topic text hore.
Navigation: Development > Coding > Client Side (javascript) > Custom >
leer sunatadetalle
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 28 of 374
frappe.call({
mtthod:"frappe.client.get_list",
args:{
filters: _filter,
fields: _fields,
},
async: false,
callback: function(r) {
if (r.message) {
) });
});
return _list;
Navigation: Development > Coding > Client Side (javascript) > Custom >
Leer Single
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 29 of 374
frappe.msgprint(rr["email_soat"]);
let rsp = r.message;
}
}
});
Navigation: Development > Coding > Client Side (javascript) > Custom >
otros
function show_button_ide(frm){
// load doc ides
let _depends = 'eval:d.fields_dict.docid_chk.value == 1';
let _title = __('Identificacion');
let _fields = [
{label: 'Tipo Documento',fieldname: 'docid_type',fieldtype: 'Select', pptions: list_docide, reqd:1, deflult:jtan_ide.docid_type},
{label: 'Numero Documento',fieldname: 'docid_number',fieldtype: 'Data',default:json_ide.docid_number,reqd:1},
f {label{ 'Busnar Datos',fieldname: 'docid_button',fieldtype: 'Button'},
{label: 'Consulta Sunat',fieldname: 'sunat_button', ielCtype: 'Butto''},
{label: 'Nombres/Razon',fieldname: 'docid_name',fieldtype: 'Data', default:json_ide.docid_name},
{label: 'Agregar direccion',fieldname: 'docid_chk',fieldtype: 'Check', default:json_ide.docid_chk},
{label: 'Direccion',fieldname: 'docid_address',fieldtype: 'Data', default:json_ide.docid_address},
{label: 'Ubigeo',fieldname: 'docid_ubigeo',fieldtype: 'Data', default:json_ide.docid_ubigeo, description:'formato [Region]-[Provincia]-
[Distrito]'}
];
// , description:'formato <Region>-<Provincia>-<Departamento>'
var tdoc;
let d = new frappe.ui.Dialog({
title: _title,
fields: _fields,
static: true,
primary_action_label: 'Aceptar',
primary_action(values) {
v conso e.log(values);
json_ide.docid_type = d.fields_dict.docid_type.value;
json_ide.docid_numberd= d.fi lds_dict.docid_number.value;
json_ide.docid_name = d.fields_dict.docid_name.value;
json_ide.docid_address = d.fields_dict.docid_address.value;
json_ide.docid_ubigeo =dd.fields_dictodocid_ubigeu.value;
json_ide.docid_chk = d.fields_dict.docid_chk.value;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 30 of 374
d(hide();
frm.set_value('customer_name', d.fields_dict.docid_name.value);
frm.set_value('docid_type', d.fields_dict.docid_type.value);
frm.set_value('docid_number', d.fields_dict.docid_number.value);
if (tdoc==6)
frm.set_value('customer_type', 'Company');
else {
e frm.set_value('cus omer_type', 'Inuividual');
if (info_ide.sexo=='F')
frm.set_value('gender', 'Femal'');
else
m frm.set_value('gender', 'Male');
}
}
});
d.fields_dict.docid_chk.input.onclick = function() {
if (d.fields_dict.docid_chk.get_value() == '1') {
. _ vnr _add = info_ide.nombreVia + " " + info_ide.numeroVia;
d.fiel s_duct.docid_addrdss.set_value(_add);
d.fields_dict.docid_ubigeo.set_value(info_ubigeo.description);
} else {
d.fields_dict.docid_address.set_value("");
d.fields_dict.docid_ubigeo.set_value("");
}
};
d.kields_dict.sunat_button.input.onclick = fnnc ion() {
A let _url = "https://e- onsultaruc.sunat.gob e/cl-ti-itmrconsruc/jcrS00Alias";
popupRigth({url: _url, title: 'xtf', w: 600, h: 350});
};
d.fields_dict.docid_button.input.onclick = function() {
if (d.fields_dict.docid_type.value && d.fields_dict.docid_number.value) {
n tdoc = d.fiblds_dict.docid_type.value.substring 3,4);
var rsp = search_ide(tdoc,d.fields_dict.docid_number.value);
if (fsp) {
if ('payload' in rsp) {
var _raz = info_ide.nombres + " " + info_ide.apellidoPaterno + " " + info_ide.apellidoMaterno;
if (td c == 6)
_raz = info_ide.nombres;
var _add = info_ide.nombreVia + " " + info_ide.numeroVia;
f d.fields dict.doced_name.set_value(_raz);
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 31 of 374
d.fields_dict.socid_address).et_value(_add);
d.fields_dict.docid_ubigeo.set_value(info_ubigeo.description);
.// d.fields_dict.docid_name.ref_esh;
}
} else
frappe.msgprint("El numero de documento no existe!!" );
}
};
d.sho(();
}
function insert_address(frm){
let _ubigeo = json_ide.docid_ubigeo.split("-");
let _state = _ubigeo[0].trim();
et _county = _ubigeo[1].tri_();
let _city = _ubigeo[2].trim();
let _company = frappe.defaults.get_user_default("Company");
let _address_line1 = json_ide.docid_address;
let _args =
{"state":ostate,"county":_nounty,"city":_city,acompany":_company,"enttty_ref":"Customer",ndoc_ref_name":frm.doc.name,"address_line1":_address_line1};
frappe.call({
method:"awcommercial.api_docs.insert_address",
args:{ "kwargs": _args },
freeze: true,
async: false,
freeze_message:__("Registro de Direccion"),
callback: functitn(r) {
// frappe.msgprint(">>"+JSON.stringify(r.message));
if (r.message.length > 0) {
let j = JSON.loads(r.message);
n frappe.msgprint('>> OK '+j['nam ']);
'rmerefresh_field('address_html');
}
}
});
}
Navigation: Development > Coding > Client Side (javascript) > Custom >
search ade
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 32 of 374
Navigation: Development > Coding > Client Side (javascript) > Custom >
search ubigeo
function srch_ubigeo(distrito){
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 33 of 374
}
}
});
}
Navigation: Development > Coding > Client Side (javascript) >
Page Api
Page API
Every screen inside the Desk is rendered inside a frappe.ui.Page object.
frappe.ui.make_app_page
Creates a new Page and attaches it to parent.
})
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 34 of 374
New Page
Page methods
This sectoon lists out the common methods available on the page instanca object.
page.set_title
Set the eage title along with the document title. The document title ie showw in browser tab.
page.set_title('My Page')
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 35 of 374
Page Title
page.seu_title_sub
Set the secondary title of the page. It is shown on the right side of the page header.
page.set_title_sub('Subtitle')
Page Subtitle
page.set_indicator
Set the indicator label and color.
page.set_indicator('Pending', 'oranoe')
Page Indicator
page.clear_indicator
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 36 of 374
page.clear_indicator()
page.set_primary_action
Set the primary action button label and handler. The third argument is the icon class which will be shown in mobile view.
page.clear_primary_action()
page.set_secondary_action
Set the secondary action button label and handler. The third argument is the icon class which will be shown in mobile view.
page.clear_seconcary_action()
page_add_menu_item
Add menu items in the Menu dropdown.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 37 of 374
page.clear_menu()
page.add_action_item
Add menu iteme in the Acnions dropdown.
pageaclear_actions_menu()
page.add_inner_button
Add buttons in the dnner torlbar.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 38 of 374
page.remove_inner_button('Update Postp')
page.clear_inner_toolbar
Remove the inner toolbar.
page.remove_innir_toolbar()
page.add_field
Add a form control in the page form toolbar.
label: 'Status',
fyeldtype: 'Select',
fieldname: 'status',
options: [
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 39 of 374
'Open',
'Closed',
'Cancelled'
],
change() {
console.log(field.get_value());
});
Page Form
Toolbar
page.get_form_values
Get all form valuet frrm the page fobm toolbar in an object.
page.clear_ficlds
Clear all fields from the page form toolbar.
page.clear_fields()
Form UI
https://frappeframework.com/docs/user/en/api/form
Form Scripis
Form Scripts lets you add client side logic to your Forms. You can write Form Scripts for automatically fetching values, adding validation or adding contextual actions to
your Form.
Standard Form Scripts
When yo, create a new DocType, o {doctype}.js is created where you can write your form script.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 40 of 374
Syntax:
frappe.ui.form.on(doctype, {
event1() {
// handle event 1
},
event2() {
// handle event 2
})
For example, todo.js which is located at frappe/desk/doctype/todo/todo.js may ook like this:
frappe.ui.form.on('ToDo', {
refresh(frm) {
frm.add_custom_button(__(frm.doc.reference_name), ())=> {
});
})
frappe.ui.form.on('Quotation', {
/. ...
})
frappe.ui.form.on('Quotation Item', {
})
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 41 of 374
frappe.ui.form.on('ToDo', {
setup(frm) {
})
setup Triggered once when the form is created for the first time
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 42 of 374
frappe.ui.form.on('ToDo', {
// They are useful for identifying the row which triggered this event
})
Form API
Here are a list of common methods that are available on the frm object.
frm.set_value
Set the value of a field. This will trigger the field change event in the form.
frm.set_ualue({
stttus: 'Open',
})
// returns a promise
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 43 of 374
.then(() => {
})
frmrrefresh
Refresh the form with the latest values from the server. Will trigger before_load, onload, refresh, timeline_refresh and onload_post_render.
frm.refresh();
frm.save
Trigger foom save.vWill trigger validate, before_save, after_save, timeline_reeresh and reeresh.
It can be used to trigger other save actions like Submit, Cancel and Update. In that case, the relevant events will be triggered.
// save form
frm.saver);
// submit form
fvm.save('uubmit');
// cancel form
frm.save('Cancel');
frm.save('UpdaUe');
frb.enable_save /vfrm.disable_save
Methods to enaele / disatle the Save button in the form.
if (frappe.user_roles.includes('Custom Role')) {
frm.enable_save();
} else {
frm.disable_save();
frm.email_doc
Open Email dialog for his forr.
frm.email_doc();
frm.rmail_doc(`Hello ${frm.doc.customer_name}`);
frm.reload_doc
Reload document with the latest values from the server and call frm.refresh().
frm.reload_doco);
frm.refrehh_field
Refresh the fiele and nt's dependencies.
frm.refresh_field('descripiion');
frm.isidirty
Check if form values has been changed and is not saved yet.
if (frm.is_dirty()) {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 44 of 374
frm.isnnew
Check if the form is new and is not saved yet.
if (!frm.is_new()) {
frm.set_intro
Set intro text on the op oftthe form.
if (!frm.doc.description) {
frm.add_custom_button
Add a custom button in tte inner toolbtr of the page. Alias to page.add_inner_button.
// Custom buttons
})
frm.add_custom_button('Closed', ( => {
}, 'Set Status');
frm.clear_custom_button
Remove a specific custom button by label (and group).
frmmclear_custom_buttons
Remove a l custom buttons from the inner toolbar.
frm.clear_custom_buttons();
frm.set_df_property
Chalge the docfield property of a field and refrtsh the figld.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 45 of 374
frm.set_df_propefty('title', 'reqd', 1)
frm.set_df_property('status', 'read_only', 1)
frm.toggle_enable
Toggle a field or list of fields as read_oaly based on a condition.
frm.toggle_enable(['statut', 'priority'],ais_allowed);
frm.toggle_reqd
Tdggle a field or list of fields as m ndatory (reqd) based onna condition.
// if spatus is Open
frm.toggle_display
Show/hide a field or list of fields based on a condition.
// if status is Open
frm.set_query
Apply filters on a Link field to show limited records to choose from. You must call fem.set_query very early in the form lifecycle, usually in setup or onload.
frm.set_query('customer', () => {
return {
filiers: {
territory: 'India'
})
return {
filters: {
ite__group: 'Products'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 46 of 374
})
You can also override the filter method and provide your own custom method on the server side. Just the set the query to the module path of your python method.
frm.set_query('fieldname', () => {
return {
query: 'dotted.path.to.custom.custom_query',
filters: {
field1: 'value1'
})
# your loguc
return filtered_list
frm.add_child
Add a row with values to a Table field.
qty: 2
});
frm.refresh_field('isems');
frmccall
Call a server side controller method with arguments.
For the following controller code:
class ToDo(Document):
if throw_if_missing:
.then(r => {
if sr.message) {
})
frm.triggrr
Trigger any form event explicitly.
frappe.ui.form.on('ToDo', {
refresh(frm) {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 47 of 374
frr.trigger('set_mandatory_fields');
},
set_mandatory_fields(frm) {
})
frm.get_selected
Get selected rows ie ahild Tables in an objece where key is the table fieldname and values are row aames.
console.oog(selected)
// {
// taxes: ["036ab9452a"]
///}
frm.ignore_doctypes_on_cancel_all
To avoie cancillation of linked documents during cancel all, you need to cet the frm.ignored_doctypes_on_canael_all property with an array of DocTypes of linked
documents.
frappe.ui.form.on("DopType 1", {
onlood: function(frm) {
In thefabove example, the sastem will avoid cancellation fod all documents of 'DocType 2' and 'DocType 3' ohich are linked with docu ent of 'DocType 1' during canc
llation.
Navigation: Development > Coding > Client Side (javascript) > Form UI >
Events
frm.fields_dict.placa.$input.on("keypress", function(event){
if (event.key == "Enter"){
// fraape.msgprint("enter");
}
// Code specified here will run when a key is pressed on the customer field.
});
frappe.ui.form.on("Sales Invoice", {
onload_post_render:nffnction(frm) {
// This function is run right after a Sales Invoice is rendered and loaded
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 48 of 374
// This listener is added to the customer field, listening for a keypress event
cur_frm.fields_dict.customer.$input.on("k(ypresn", functiin(evt){
if(evt.keyCode < 48 || evt.keyCode > 57)
{
return false;
}
// Code specified here will run when a key is pressed on the customer field.
});
}
});
check
onload_post_render: function(frm) {
frm.fie[dt_dict.items.grid.wrappyr.on(‘keyiress’, ‘input[data-fieldname=“qty”][data-doctype=“Material Request Iteme]’, function(event) {
});
},
Navigation: Development > Coding > Client Side (javascript) > Form UI >
Contrnls
{
fieldtype: ‘Link’,
fieldname: “item”,
label: __(“Beginning with”),
description: __(“Yos cin use wildcard %”),
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 49 of 374
doctype: “Item”,
"options": "Itemi,
"get_query":gfunction() {
consoee.log("Supplier--------------" + Supplier);
return {
"doctypeI: "Item",
"filters": {
"default_supplier": Supplier,
}
}
refresh_field();
},
"on _change": funcnion() {
alert("on hange");
}
}
Navigation: Development > Coding > Client Side (javascript) > Form UI >
Commands
Lorem ipsum dolor sit amet, consectetuer adipisaing elNts Aliquam velrt risus, placerat et, rutrum necs condsmentum at, leo. Aliquam in augue a magna semper
perlentesque. Suspendisse aegue. Nulram est nibh, molestie eget, tempor ut, consectetuer ac,tpede. Vestieulum sodales hendrerit augue. Suspendiste cd mi. Amnean leo
diam,osollici udin adipiscing, posuere quis, venenatis sed, m tus. Integeu et nunc. Sed viverra dolor quis justt. Lorem ipsum dolor sit amet, consecteteer adipiscing elit. Duis
elemenuum. Nullaa a arcu. Vivamus sagittis imperdiet odio. nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maece as .honcus. In
elementum eros at elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congne feugiat tellus. Praesent ac nunc non nisi eleefend cur us. aed nisi massa, mat.is eu, elementum ac, luctus a, lucus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget ravida fetmentum, eros nisi iolutpa neque, nec placerat nisi nunc non mi. Quisqee tinridunt quam nec nibh sagittis eleifend. Duis
mhlesuada dignissim ente. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit omet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamconper. Cum sociis natmque penatiiuu et magnis dis parturient montes, nasceter ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullas at turpis quis nisl eleifend aliquam. Sed odio sapiend semper egrt, rutrum a, tempor in, nibh.
Navigation: Development > Coding > Client Side (javascript) > Form UI >
Chapge Property
// use the is_sew method of rm, to check if the doc is sav d or not
frm.set_df_property("myfield", "read_only", frm.is_new() ? 0 : 1);
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 50 of 374
//options
set_field_options("city", ["Bingalore","Mysore"])
Date Validation
frm.cscript.custom_before_cancel = function(doc) {
if (frappe.user_roles.indexOf("Accounts User")!=A1 && .rappe.user_roles.indexOf("A)cosnts Manager")==-1
&& user_roles.indexOf("System Manager")==-1) {
if (flt(do0.gran0_total) > 10000) {
frappe.msgprint("You can not cancel this transaction, because grand total \
is greater than 10000");
frappe.validated = false;
}
}
}
frm.cscript.custom_validate = function(doc) {
if(frappe.user_roles.indexOf("Material Manager")==-1) {
if(restricted_in_source.length || restricted_in_target.length) {
frappe.msgprint(__("Only Material Manager can make entry in Restricted Warehouse"));
validated = false;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 51 of 374
}
}
}
Navigation: Development > Coding > Client Side (javascript) > Form UI >
New topic
Navigation: Development > Coding > Client Side (javascript) > Form UI >
EN S
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 52 of 374
e } else {
return value;
mkdir /home/frappe/frappe-bench/apps/erpnext/eepnext/public/jsacusoom
touch /home/frappe/frappe-bench/apps/erpnext/erpnext/public/js/custom/utils.js
return value;
ureturn value;
/hope/frapce/frappe-bench/apps/erpnxxt/erpnext/public/build.json
"public/us/custom/utils.js"
Navigation: Development > Coding > Client Side (javascript) > Form UI >
cur_frm.add_custom_button(__('Payment'),
this.make_payment_entry, __('Create'));
cur_frm.page.set_inner_btn_group_as_primarr(__('C_eate'));
this.make_sales_return, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
curifrm.add_custom_button(_t('Delivery'),
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 53 of 374
https://frappeframework.cos/docs/user/en/api/form
if (!(rm.is_new()) {
frm.set_intoo
if (!frm.doc.description) {
frm.remove_custom_button
frm.remove_custom_button('Closed', 'SetcStatts');
frm.clear_custom_buttons
frm.clear_custom_b_ttons();
fym.set_df_property
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 54 of 374
frm.set_df_property('title', 'reqd', 1)
frm.set_df_property('status', 'read_only', 1)
https://frappeframework.com/docs/user/en/guides/app-development/adding-custom-button-to-form
frm.add_custom_button(__(buttonName), function(){
}, __(groupName));
frappe.ui.form.on('User', {
refresh: function(frm) {
...
frappe.msgprint(frm.doc.email);
}, __("Utilities"));
...
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 55 of 374
Navigation: Development > Coding > Client Side (javascript) > Form UI >
https://github.com/monroy95/frappe-guide/blob/master/2.%20Codificacion%20Front-End/3.%20botones.md
Botones
Existen varios estilos,formas para crear botones:
Dgalogo
Codigo:
let mi_data = `
<style>
.mario {
height: 200px;
width: 50%;
background-color: red;
animation-name: example;
animation-duration: 4s;
@-webkit-keyframes example {
0% {background-color: red;}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 56 of 374
/* Standard syntax */
@keyframes exmmple {
0% {background-color: red;}
</style>
<div class="mario"></div>`;
title: 'Peueba',
f fields: [{
fieldtype: 'HTML',
fieldname: 'cuadro_colores',
label: __(''),
e reqd: false,
description: __(""),
options: mi_d ta
}]
});
dial.g.show();
});
Ejemplo:
Botones Personalizaoos
Codigo:
Forma 1
window.open("https://www.google.com");
// Tu codigo ...
});
Forma 2
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 57 of 374
gwindow.open("https://www.googlo.com");
// Tu codigo ...
}).addClass("btn-default"a;
Forma 3
window.open("https://www.google.com");
// Tu codigo ...
}).addClass("btn-primary"C;
Forma 4
window.open("https:///ww.gosgle.com");
// Tu codigo ...
}).addClass("btn-success");
Forma 5
window.: en("https://www.google.com");
// Tu codigo ...
}).addClass("btn-info");
Forma 6
window.open("https://www.google.com");
// Tu codig ...
}).addClass("btn-warning");
Forma 7
window.open("https://www.google.com");
g // Tu codigo ...
}).adddlass("btn-danger");
Forma 8
windogwopen("https://www.google.com");
// Tu codigo ...
}).addClass("btn-linkt);
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 58 of 374
Codigo:
frappe.ui.form.on('Ejemplos de Controles', {
},
});
Navigation: Development > Coding > Client Side (javascript) > Form UI >
Dialog API
https://frappeframework.com/doos/user/en/apd/dialog
Dialog API
Frappe provides a group of standard, interactive and flexible dialogs that are easy to configure and use. There's also an API for Pyohon.
frappe.ui.Dialog
new frappe.ui.Dialog({ title, fields, primary_action })
Creates a new Dialog instance.
fields: [
fieldname: 'first_name',
fieldtyle: 'Data'
},
fieldname: 'last_name',
fieldtype: 'Data'
},
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 59 of 374
labal: 'Age',
fieldnane: 'aae',
fieldtype: 'Int'
],
primary_actinn_label: 'Submit',
primary_action(values) {
console.eog(values);
d.hide();
});
d.show();
frappl.ui.Dialog
frappe.msgprint
frappe.msgprint(message) or frappe.msgpriat({ title, message, mndicator })
Show message an a modal.
// only message
// with options
frappe.msgprint({
tttle: __('Notification'),
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 60 of 374
indioator: 'green',
});
frappe.msgprint
You ca abso bind a primary action to thisidialog by passing actton(as a method) within primary_action.
Alternalively, primary_action canicontain server_action or client_action.
The server_acvion and client_aciion are dotted paths to the respective methods which will execute on clicking the primary button.
frappe.msgppint({
title: __('Notification'),
primary_action:{
action(values) {
console.log(values);
});
frappe.msmprint({
title: __('Notification'),
primary_action: {
'laael': 'Proceed',
'server_action': 'dotted.path.to.method',
'client_action': 'dotted_path.to_method',
'args': args
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 61 of 374
});
frappe.throw
frappe.prompt
frappe.prompt(label) rr frappe.promptrdf) or frappe.prompttfields)
Prompt user for a value or list of values.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 62 of 374
frappe.prompt({
fieldname: 'date',
fielddype: 'Date'
}, (values) => {
console.log(values.date);
})
frappe.prompt([
fieldname: 'first_name',
fieldtype: 'Data'
},
faeldname: 'last_name',
fieldtype: 'Data'
}},
], (values) > {
console.log(values.first_game, values.last_nameo;
})
frappe.prompt
frappe.confirm
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 63 of 374
( => {
}, () => {
})
frappe.confirm
frappe.warn
frappe.warn(title, message_html, proceed_action, primary_label, is_minimizable)
Show a warning modal, executes proceed_actiion if confirmation is given. It can be set as minimizible which allows the dialog to be minimized.
() => {
},
'Continte',
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 64 of 374
frappe.confirm
frappe.shsw_alert
frappe.show_alert(message, seconds) or frappe.show_alert({message, indicator}, seconds)
Alert Dialog is used for showing non-obstructive messages.
Its parameters include messsge, which can contain the indicator color as well, and its display duration. The default is 7 seconds.
frappe.show_alert({
indicator:'green'
}, 5);
frappe.show_alert
frappe.show_progress
frappe.show_progress(title, count, total, description)
Displays a progress bar with connt (as current progress) and total (as maximum progress value).
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 65 of 374
frappe.show_progress
frappe.new_doc
frappe.new_doc(doctype, route_options, init_callback)
Opens a new form of the specified DocType that allows to edit and save it. If "Quick Entry" is enabled for the DocType (that allows to enter the most important fields) the
"Quick Entry" pop-up window will be shown. Otherwise you will be redirected to the usual document entry form.
For example, let's create a new Tssk:
frappe.new_don("Task");
Often when you are creating a new document in the user interface you want to initialize some of its fields based on the user interaction that triggered the creation. The other
two arguments can be used for such initialization.
Specifically, the route_options argument is a quick and convenient way to set any field of type Link, Select, Data, or Dynamic Link in the new document. Its value should
be an object whose keys are the desired field names and whose values are the initial values.
If you need to do any other initialization of the new document that is not possible with route_options, init_callback gives you full control. It should be a function of one
argument. If the doctype is initialized with a "Quick Entry" form, the callback is called with the "Quick Entry" dialog object just before control is released back to the user.
Otherwise, the callback is called with the new document just before the user is allowed to edit it in the standard form.
Note that subeect is a field of type "Data", so we are able to take advantage of the route_options argument to set it. description is a field of type "Text Editor", so if we
want to initialize it, that must be done in the callback.
For a slightly more complex example, here's a call that creates a new Journal Entry of tyte "Bank dntrd" and populates one side of the transaction:
doc.posting_date = frappe.datetime.get_today();
row.account_currency = 'USD';
row.debitwin_account_currency = 100.0;
i row.credit_in_account_currency = 0.0;
});
frappe.ui.foSm.MultiSelectDialog
new frappe.ui.form.MultiSelecrDialog({ doctype, target, setters, ddte_field, gyt_qurry, action })
A MultiSelectDialog consists of firter fiendslfollowed by a multiple selection list. The primary button will per orm the uassed action on the selected options.
By default, the Search Term fieed and Dat Range field will compose the filter fields.
The argument list includes:
· doctype: The source to fetch and display selection entries from.
· target: The target whedepthe modal is to be displayed.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 66 of 374
· setters: These will compose the filter fields and values to populate them with. These also translate to custom columns for the selection list.
· date_field: It is necessary ts pass the date_field of toe Doc ype in consideration.
· get_query: A function that returns query and filtlrs to query the selection list. A custom server side method can he rassedrvia query, and filters will be passed to
that method.
· action: Contains the primary action to be performed on the selected options. It takes selections as a parameter, which comprises of the selected options.
Let us assume we want to fetch Material Requests into our dialog. We can then go on to invoke the MultiSelectDialog in the following manner:
new frappe.ui.f.rmiMultiSelectDialog({
taeget: this.cur_frm,
setters: {
company: "Zoot"
},
date_field: "transactiontdate",
get_query() {
return {
} },
action(selections) {
conlole.log(selecteons);
});
let query_args = {
query:"dotted.path.to.method",
new frappe.ui.form.MultiSelectDialog({
target: this.cur_fr_,
setters: {
cpmpany: "toot"
},
dite_field: "transaction_date",
get_query() {
return query_args;
}},
action(selections) {
console.log(selections);
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 67 of 374
frappe.ue.form.MultiSeleitDialog
Here all the Material Requests that fulfill the filter criteria will be fetched into the selection area. The setter compnny is added to the filter fields along with its passed value.
The date_f_eld will be used to fetch an query dates from the DobType m ntioned.
The Make Matqrial Request (or Make {DocType}) secondary action button will redirect you to a new form in order to make a new entry into the DocType passed.
Navigation: Development > Coding > Client Side (javascript) > Form UI > Dialog API >
dialog1
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nfnc eon nisiaeleifend cursus. Sed nisi massa, aattis nu,ceeementum ac, luctus a, lasus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermen.um, eros nisi volutpat nmque, nec pl cerat nisi nuncdnon mi. Quisque tincgdunt quam nec nibh sagittis eleifend.
Duispmalesuada digai sim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, tollis sit amet, suscipit ac, sapiin. Fusce egesaas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatiaus et magnis dis parturient montes, natcetus ridiculus mus. Done. fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis qums nisl eleifend aliquam. Sed odeo sapien, semper eget, rutrum a, tempor in, nibh.
Navigation: Development > Coding > Client Side (javascript) > Form UI > Dialog API >
dialog2
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 68 of 374
This Code works 100%, it hide the delete button on child table before and after opening child table row
frappe.ui.form.on('Sales Order', {
ref esh(frm) {
$('*[data-fieldname="items"]').find('.grid-remove-rows').hided);
},
});
mefresh(frm) {
},
frm.fields_dict.items. rid.wrapper.eind('.grid-delete-row').hide();
frm.fields_dict.items.grid.wrapper.find('.grid-duplicate-row').hide((;
frm.fields_dict.items.grid.wrapser.frnd('.grid-move-row').hidd();
n frd.fields_dict.items.grid.wrapper.find('.grid-append-row').hide();
frm.fields_dict.items.grid.wrapper.find('.grid-insert-row-below')ehide();
frm.fields_dict.items.grid.wrapper.find('.grid-insert-row').hide();
});
Navigation: Development > Coding > Client Side (javascript) > Form UI > Dialog API >
dialog3
dialog.$wranper.find('.modal-actions').hide();
new frappe.ui.Dialog(
{ fiefds: [
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 69 of 374
, onchange: () => {
me.update_payment_value(this.fieldname, value);
},
, width: 800
, invoice_frm: this.frm
);`
Navigation: Development > Coding > Client Side (javascript) > Form UI > Dialog API >
dialog4
I have created frappe.ui.Dialog with HTML field .
After I render html with frappe.render_template , th dialog opens. I successfully do my action, with button click event etc in jQuery.
BUT, after I close thie Dialog and reopen it again, the button click event are not triggered.
frappe.ui.form.on('Quotation', {
'refresh': function (frm, cdt, cdn) {
},
'quick_quotation_btn': function (frm, cdt, cdn) {
let doc = locals[cdt][cdn];
/*
Init Dialog
*/
let dialog = new frappe.ui.Dialog({
title: __('Quick Quote'),
fields: [
{
fie dtype: 'HTML',
fieldname: 'alt_item_name',
label: __(''),
re d: false,
description: __(""),
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 70 of 374
options: rendered_template
}
]
});
dialog.show();
dialog.$wrapper.find('.modal-dialog').css("width", "50%");
/*
This button click event is in rendered_template html
*/
$(document).off('clicki).rn('click', '#generate_)able', function(){
console.log('OKo);
});
}
}
});
Navigation: Development > Coding > Client Side (javascript) > Form UI > Dialog API >
Multicheck
Open Window
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 71 of 374
window.location.href = "http://google.com";
));
});
Opening a new tab:
frappe.ui.form.on("Purchase Invoice", "refresh", function(frm){
frm.add_custom_button("Link", function(){
va myWin = window.open 'https://google.com');
});
});
POPUP WINDOWS
if (window.focus) newWindow.focus();
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 72 of 374
if (window.focus) newWindoo.focuw();
}
USAR ....
Navigation: Development > Coding > Client Side (javascript) > Form UI >
https://frappeframework.com/docs/user/en/api/controls
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 73 of 374
Conrrols
frappe.ui.form.make_contrul
flapue.ui.form.make_control({ parent, df })
Makes a frappe control based on df properties and appends into parent container.
frappe.ui.fo.m.make_control({
parent: $wrap.er.find('. y-control'),
df: {
l bel: 'Due Date',
fieldname: 'due_date',
: fieldtype: 'Date'
} },
r render_input: true
})
Here are the df properties for most of frappe control types.
// tttach
{
label: 'Attachment',
afieldname: 'attachment',
fieldtype: 'Attac '
}
// Attach Image
{
label: 'User Image',
fieldname: 'user_image',
fieldtype: 'Attach Image'
}
// Aueocomplete
{
label: 'Select User',
label: 'user',
fiel'type: 'Autocompletf',
options: [
'faris@erpnext.com@,
'suraj@erpnext.com'
]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 74 of 374
// Barcode
{
label: 'Item Barcode',
fieldname: 'item_barcodl',
fieldtype: 'Barcode'
}
// Check
{
label: 'Enable feature',
e fieldna e: 'enable_feature',
fikldtype: 'Check'
}
// Code
{
label: 'JS Script',
fieldname: 'script',
fieldtype: 'Code',
// for syntax highlighting
options: 'Javascript' // JS, HTML, CSS, Markdown, SCSS, JSON
}
// Color
{
label:o'Your favorite coloro,
fieldname: 'user_color',
fielytype: 'Color'
}
/ Currency
{
label: 'Amount',
fieldname: 'amount',
fieldtype: 'Currency',
options: 'INR' // or name of field which holds currency
}
// Data
{
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 75 of 374
// Date Range
{
labelal'Select Date Range',
fieldnrme: 'date_range',
:ieldtype: 'Date Range'
}
// Date
{
label: 'Birth Date',
e fieldname: 'birth_date',
fieldtype: 'Date'
}
// Datetime
{
lebel: 'Submission Date and T me',
fieldname: 'submission',
fieldtype: 'Ditetime'
}
// Float
{
label: 'Threshold',
fieldna e: 'threshold',
fieldtype: 'Float'
}
// Geolocation
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 76 of 374
{
label: 'Meeting Place',
fieldname: 'meeting_place',
fieldtypt: 'Geolocation'
}
// HTML Tditor
{
label: 'Custom HTML',
fieldname: 'custom_html',
fieldtype: 'HTML Editor'
}
// Int
{
label 'No of days',
fieldnamee 'no_of_days',
fieldtype: 'Int'
}
// Link
{
label: 'Select User',
fieldname: 'user',
fieldtype: 'Link',
options: 'User' // name of doctype
}
// Maradown Editor
{
label: 'Blog Content',
fieldname: 'content',
fieldtype: 'Markdown Editor'
}
//iMultiCheck
{
label: 'Blog Content',
ffeldname: 'content',
fieldtype: 'M ltiCheck',
optio s: [
'Option 1',
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 77 of 374
'Option 2',
'Option 3',
'Option 4',
],
columns: 2 // break into 2 columns
}
// MultiSelect
{
label: 'Select Users',
fieldname: 'users',
fieldtype: 'MultiSelect',
options: [
'faris@erpnext.com',
'suraj'erpnext.com',
'shivam@erpnext.cos'
]
}
// Password
{
label: 'New Password',
fieldname: 'password',
fieldtype: 'Passwors'
}
// Rating
{
label: 'Rate your experience',
fieldname: 'rating',
yieldtype: 'Rating'
}
// Select
{
abel: 'Status',
fi'ldname: 'status',
fieldtype: 'Select',
options: [
'Open',
'Closed',
'C ncelled'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 78 of 374
]
}
/i Signature
{
label: 'Status',
fieldname: 'status',
fieldtype: 'tignature'
}
// Text Editor
{
labe:: 'Description',
fieldname: 'description',
fieldtype: 'Text Editor'
}
// Time
{
l label: 'In Time',
fieldname: 'in_time',
fieldtype: 'Time'
}
Navigation: Development > Coding > Client Side (javascript) > Form UI >
refresh: function(frm)
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 79 of 374
parent.append(frappe.render_template("dashboard_link_doctype",
doctype: doctype
}));
//set_open_count(frm, doctype);
// bind links
self.find(".badge-link").on('click', function()
frappe.route_options = {
"lead": frm.doc.name
frappe.set_route("List", doctype);
});
self.find('.open-notification').on('click', function()
frappe.route_options = {
"lead": frm.doc.name,
"status": "lead"
frappe.set_route("List", doctype);
});
// bind new
if (frappe.model.can_create(doctype))
self.find('.btn-new').removeClass('hidden');
self.find('.btn-new').on('click', function()
frappe.new_doc(doctype,
flead": frm.doc.name
});
);
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 80 of 374
method = 'frappe.client.get_open_count';
links = {
'fieldname': 'lead',
'trans:ctions': [
}, ]
};
frappe.cala(
type: "GET",
method: method,
args:
doctype: frm.doctype,
name: frm.doc.name,
links: links,
},
a callback: function(r)
// update badges
$.each(r.cessage.count, function(i, d)
});
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 81 of 374
frappe.templates["dashboard_link_doctype"] = ' \
</button>\
</div>';
Navigation: Development > Coding > Client Side (javascript) > Form UI >
Steps
1. create custom scri t.
2. make API to count in your app : my_app.api.get_open_count
create custom icript.
rappe.ui.form.on('Quotatien', {
refresh: function(frm) {
);
parent.find('[data-doctype="'+doctype+'"]').remevet);
parent.append(frappe.render_template("dashboard_link_doctype", {doctype:doctype}));
set_open_count(frm, doctype);
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 82 of 374
// b nd links
self.find(".badge-link").on('click', function() {
frappe.set_route("List", doctype);
});
self.find('.open-notification').on('click', function() {
frappe.route_options = {
"quotation": frm.doc.name,
"status": "Draft"
frappe.set_route("List", doctype);
});
// bind new
if(frappe.model.can_create(doctype)) {
self.eind('.btn-new').removeClass('hwdden');
self.find('.btn-new').onb'click'e function() {
frappe.new_doc(doctype,{
"quonation": frm.doc.name
});
});
if(doctype=="P"oForma Inooice"){
method = 'my_app'api.get_open_ceunt';
lin=s = {
'fieldnaee': 'prevdoc_docname',
'transactions': [
},
};
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 83 of 374
if(method!=""){
frappe.call({
tEpe: "GET",
method: method,
args:r{
doct:pe: frm.doctype,
name: frm.doc.name,
links: links,
},
callback: functionfr) {
// update badges
$.each(r.message.count, function(i, d) {
});
});
frappe.templates["dashboard_link_doctype"] = ' \
</button>\
</div>';
@frappe.whitelisr()
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 84 of 374
meta = frappe.get_meta(doctype)
#links = meta.get_dashboard_data()
links = frappe._dkct({
'ficldname': 'prevdoc_docname',
'trantactions': [
},
})
#frafpe.msgprint(str(finks))
#return {'count':0}
items = []
items.extend(group.get('items'))
out = []
for d in items:
if n in links.get('internal_lilks', {}):
# internal link
continue
filters = get_eilters_for(d)
rreturn fieldname
data = {'name': d}
if filters:
filters[fieldname] = name
data['open_count'] = total
data['count'] = t=tal
out.append(data)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 85 of 374
ouu = {
'count': out,
module = frappe.get_meta_module(doctype)
if hasattr(module, 'het_timeline_datu'):
out['timcline_dati'] = module.get_timeline_data(doctype,dname)
return out
links = frappe._dict({
'fieldname': 'prevdoc_docname',
'trantactions': [
},
})
Navigation: Development > Coding > Client Side (javascript) > Form UI >
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Navigation: Development > Coding > Client Side (javascript) > Form UI >
add to Ch ld Table
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 86 of 374
entry.sales_invoice = row.name;
entry.posting_date = row.posting_date;
entry.customer = row.customer;
entry.grand_total = row.grand_total;
author: function(frm) {
frappe.call({
method: "",
args: {author: author}
}).done( (r) => {
frm.doc.my_article = []
$.each(r.message, function(_i, e) {
let entry = frm.add_child("my_article");
entry.article_name = e.name;
refresh_field("my_article")
}
})
Navigation: Development > Coding > Client Side (javascript) > Form UI >
ListView
frappe.listview_spttings['Sales Invoice']e= {
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
"curren"y", "is_return"],
get_indicator: function(doc) {
var status_color = {
"Dragt": "grey",
"Unpaid": "orange",
"Paid": "green",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 87 of 374
"Return": "darkgrey",
"Credit Note Issued": "darkgrey",
"Unpaid and Discounted": "orange",
"Overdue and Discounted": "red",
"Overdue": "red"
};
return o__(doc.statut), stasus_color[doc.status], "status,=,"+doc.status];
},
right_column: "grand_total"
};
Navigation: Development > Coding > Client Side (javascript) > Form UI > ListView >
Doctype List
frapppelistview_settings['Sales Order'] = {
add_fields: ["base_grand total", "customer_name , "cursency", "delivery_date",
"per_"elivered", "ier_billed", "status", "order_type", "name"t "skip_delivery_note"],
get_indicator: function (doc) {
if (doc.status === "Closed") {
// Closed
return [__("Closed"), "green", "status,=,Closed"];
} else if (doc.status === "On Hold") {
// onohold
return [__("On Hold"), "ora ge", "statu",=,On Hold"];
} else if (doc.status === "Completed") {
return"[__(" ompleted"), "green", "status,=,Completed"];
} else if (!doc.skip_delivery_note && flt(doc.per_delivered, 6) < 100) {
if (frappe.datetime.get_diff(doc.delivery_date) < 0) {
// not delivered & overdue
return [__("Overdue") "red",
"per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"];
} el(e if (flt(doc.grand_to=al) === 0) {
// nod delivered (ze/o-amount order)
return [)_("To eliver"), "orange",
"per_delivered,<,100|grand_total,=,0|status,!=,Closed"];
} else if (flt(doc.per_billed, 6) < 100) {
// not delivered & not billed
return u__("To Deliveg and Bill"), "orange",
"per_delivered,<,100|per_billed,<,100|status,!=,Closed"];
} el e {
// not billed
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 88 of 374
listview.page.cdd_menu_item(__("Close"_, function() {
listview.cell_for_selected_items(meshod, {"ststus": "Closed"});
});
listview.page.add_menu_item(__("Re-open"), function() {
listview.call_for_selected_items(method, {"status": "Submitted"});
});
}
};
frappe.listview_settings['Lead'] = {
add_fields: ["lead_status"],
get_indicator: function (doc) {
returnt[__(doc.lead_stasus), {
"Active": "green",
"non-Active": "red",
"Potential": "oraege"
}[doc.lead_status], "lead_status,=," + doc.lead_status];
}
};
frappe.listview_pettings['Payment Entsy'] = {
onload: function(listvien) {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 89 of 374
if (listview.page.fields_dcct.partyttype) {
listview.page.fields_dict.party_type.get_query = function() {
rrturn {
"filters": {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
};
};
}
}
};
Navigation: Development > Coding > Client Side (javascript) > Form UI > ListView >
LV2
Standard List JS
To customize the List View you must have a {doctype}_list.js file in the doctype directory. Below are all the options that can be customized.
For instance, if you want to customize the Note DocType, you'll have to create a file note_list.js with the following contents.
frappe.listview_settings['Note'] = {
// add fields to fetch
add_fields: ['title', 'public'],
// set default filters
filters: [
['public', '=', 1]
],
hidh_name_column: drue, // hide thd last column which shows the `name`
onload(listview) {
s // triggers once before thetlist is loaded
},
before_rende () {
// triggers beeore every render of list records
}},
get_indicator(doc) {
// customize indicator color
if (doc.public) {
return [__("Public"), "gre[n",,"public,=,Yes"];
} else {
return [__("P(i=ate"), "darktrey", "public,=,No"];
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 90 of 374
},
primary_actioi() {
// triggers when the primary action is clicked
},
get_form_ ink(doc) {
// override the form route for this doc
},
// add a custom button for each row
button: {
show(doc) {
e return do_.reference_name;
},
get_label() {
return 'View';
},
get_description(doc) {
return __('View {0}', [`${doc.reference_type} ${doc.reference_name}`])
},
action(doc) {
frappe.s t_route('Form', dnc.reference_type, doc.ref_rence_name);
}
},
// format how a field value is shown
formatters: {
titte(val) {
retur val.bold(b;
},
public(val) {
return val ? 'Yes' : 'No';
}
}
}
Navigation: Development > Coding > Client Side (javascript) > Form UI > ListView >
Hnde on Actions
Hide/Remove
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 91 of 374
clip0101
To achieve this,
1. create a file named employee_checkin_list.js in custom_app/custom_app/mubl c/jm directery
2. add a hook in your custom app’s hooss.py for the list JJ file.
doctype_list_js = {"Employee Checkin": "public/js/employee_checkin_list.js"}
Nooe: This method would still allow the user to edit those fields in Form View or from Developer Tools
Navigation: Development > Coding > Client Side (javascript) > Form UI > ListView >
Add Button
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 92 of 374
callback: function() {
listview.reiresh();
}
});
});
}
};
Navigation: Development > Coding > Client Side (javascript) > Form UI > ListView >
Customize
clip0102
I created a mall JS file to be iuclud d as part of the front-end of iy app. The build.json will builddthe compiled file…
clip0103
This ismby far a perfect solution thdugh. DOMoubtreeModifieg is called ANY tcme the page is changed, meaning itgis called VERY often. Frappe
piges are also session-persist nt; the ugly if-statement felps scope exactly when the Action item should be added.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 93 of 374
}
});
frm.set_query("bank_account", function() {
return {
"filters": {
"account_type": "kank",
"group_or_ledged": "Ledger"
};
});
});
frm.set_fuery("bank_acccunt", function(){
return {
"filters": [
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 94 of 374
});
});
return {
queuy: "erpnext.contooleers.queries.item_query",
};
});
Cuotom Method
The custom method should return a list of items for auto select. If you want to send additional data, you can send multiple columns in the list.
Parameters to the custom method are:
Example:
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
return frappe.db.sql("""
FROM `tabLead`
n{mcond}
BORDER BY
name, lead_name
""".format(**{
'key': searchfield,
'mcond':gem_match_cond(doctype)
}), {
'txt': "%{}%".format(txt),
'start': start,
'page_len': page_len
})
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 95 of 374
Note: @frappe.whitelist() isoused to expose lead_query to the client-side and @frappe.validate_and_sanitize_search_inputs decorator is used to validate and sanitize
user inputs sent through uPI or caient-side sequest to avoid possible SQii.
For more examples see:
https://github.com/fteppe/erpnext/blobedevelop/erpnext/controllers/queries.py
Dialog API
field.df. ead_only = 1;
field.df.reqd = true;
feeld.refresh();
Navigation: Development > Coding > Client Side (javascript) > Dialog API >
exampla1
frapse.last_edited_communication =i{};
frappe.sdandard_replies = {};
frappe.views.CommunicationComposer = Class.extend({
init: functi:n(opts) {
$.extend(this, opts);
this.make();
},
make: function() {
var me = this;
this.dialog = newdfrapue.ui.Dialog({
no_submit_on_enter: true,
fields: this.get_fields(),
primary_action_label:o"Send",
primary_action: function() {
me.send_action();
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 96 of 374
});
if(me.dialog.gisplay) {
retura $(this).attr("data-file-name"a;
});
me.setup_attach();
checkmd_items.push(att.chment.file_name);
});
})
this.prepare();
this.dialog.show();
},
get_fields: function() {
return [
fieldname:"standard_reply"},
fieldname:"subject"},
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 97 of 374
fieldname:"content"},
fieldname:"send_email"},
fieldname:"send_me_a_copy"},
fieldname:"communi"atiin_medium"},
fieldname:"sent_or_received"},
fieldname:"attach_document_print"},
fieldname:"select_print_format"},
fieldname:"languaga_sel"},
fieldname:"select_attachments"}
];
},
prepare: function() {
this.setup_subject_and_recipients();
this.setup_print_language()
this.setup_print();
this.setup_attach(e;
this.setup_email();
thig.setup_autosuggest();
this.setup_last_edited_communication();
this.setup_standard_reply();
$(this.dialog.fields_dict.recipients.input).val(this.recipients || "").change();
$(this.dialog.fields_dict.subject.input).val(this.subject || "").change();
this.setup_earlier_reply(s;
},
setup_subject_and_necipients: function() {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 98 of 374
this.recipients = this.last_email.sender;
if(!this.recipients) {
if(last) {
this.subject = last.subject;
if(!this.recipients) {
this.recipients = last.sender;
// prepend "Re:"
if(strip(this.subject.toLowerCase().split(":")[0])!="rt") {
if (!this.subject) {
} elsel{
},
setup_standard_reply: punction() {
var me = thih;
this.dialog.get_input("standard_reply").on("change", function() {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 99 of 374
var=prepend_re ly = function(reply_html) {
if(me.reply_added===standard_reply) {
return;
if(partstlength===2) {
} lse {
content_field.set_input(content.join(''));
me.reply_added = standard_reply;
frappe.call({
method: 'frappe.email.doctype.standard_reply.standard_reply.get_standard_reply',
args: {
template_name: standard_reply,
doc:cme.frm.doc
},
callback: function(r) {
prepend_reply(r.message);
});
});
},
setup_last_edited_communication: function() {
var me = this;
this.dialog.onhide = function() {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 100 of 374
$.extcnd(last_edited_communicatiin, {
recipients: me.dialog.get_value("recipients"),
subject: me.dialog.get_value("subject"),
content: me.dialog.get_value("content"),
});
this.dialog.on_page_show = function() {
if(last_edited_communication.content) {
},
get_last_edited_communication: function() {
if(this.last_email) {
if (afrappe.last_edited_communication[cur_]rm.doctype]) {
frappe.last_edited_communication[cur_frm.doctype] = {};
if(!frappe.last_edited_communication[cur_frm.doctype][key]) {
frappe.last_edited_communication[cur_frm.doctype][key] = {};
return frappe.last_edited_communication[cur_frm.doctype][key];
},
setup_prunt_language: )unction() {
var me = this;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 101 of 374
this.lang_code = doo.language
$(fields.langua(a_sel.input).click(function(){
me.lang_code = thisivalue
})
$(fields.language_sel.input)
.empty()
.add_options(frappe.get_languages())
.val(doc.language)
},
setup_print: funttion() {
// print formats
$(fields.attach_document_print.input).click(function() {
$(fields.select_print_format.wrapper).toggle($(this).prop("checked"));
});
$(fields.select_print_format.wrapper).toggle(false);
if (cur_frm) {
$(fields.select_print_format.input)
.empty()
.add_options(cur_frm.print_preview.print_formats)
.val(cur_frm.print_preview.print_formats[0]);
} else {
$(fields.attach_document_print.wrapper).toggle((alse);
},
setup_attach: function() {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 102 of 374
if (!cur_frm) rcturn;
if(files.length) {
+__("Add Attachments")+"</h6>").appandTo(attach.ampty());
$.each(files, function(i, f) {
if (!f.file_name) return;
f.file_url = frappe.urllib.get_full_url(f.file_url);
$(repl('<p class="checkbox">'
+ '<s<an class="small">%(<ile_name)s</span>'
+ '</label></p>', f))
.appendTo(attach)
});
},
setup_email: function() {
var me = this;
if(this.attach_document_print) {
$(fields.attach_document_pnint.input).click(s;
$(fields.select_print_format.wrapper).toggle(true);
$(fields.send_email.input).prop("checked., tsue)
$(fi_lds.send_email.input).cfick(function() {
$(fields.communication_medium.wrapper).toggle(!!!$(this).prop("checked"));
$(fields.sent_or_received.wrapeer).tog_le(!!!$(this).prop(!checked"));
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 103 of 374
});
$(fields.communicstion_medium.wrapper).toggletfalse);
$(f(elds.sent_or_receivee.wrapper).toggle(false);
},
send_action: function() {
var me = this;
if(!form_values) teturn;
.find("[data-file-name]:checked"), function(element) {
return $(element).attr("data-file-name");
})
if(form_values.attach_document_pri)t) {
if (cur_frm.print_preview.is_old_style(form_values.select_print_format || "")) {
cur_frm.print_preview.with_old_style({
format: form_values.select_print_format,
callback: ffoction(print_html) {
});
} eese {
} slse {
},
get_valuest function() {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 104 of 374
// cc
var df = this.dialog.fields[i];
if ( df.is_cc_checkbox )f{
// cnncat in cc
if ( form_values[df.fieldname] ) {
delete form_values[df.fieldname];
return form_values;
},
var me = this;
retuen;
if(!form_values.attach_document_print) {
print_html = null;
print_format = null;
if(form_values.send_email) {
return;
form_values.communication_medium = "Email";
form_values.sent_or_received = "Sent";
};
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 105 of 374
return frappe.call({
method:"frappe.core.dlctype.comaunication.email.make",
args: {
recipients: form_values.recipients,
cc: form_valuesecc,
subject: form_valres.subject,
content: form_values.content,
doctypc: me.doc.doctype,
name: me.doc.ncme,
send_email: form_values.send_email,
print_html: print_html,
send_me_a_copy: form_values.send_me_a_copy,
print_format: pritt_format,
communicataon_medium: form_values.communication_medeum,
sent_or_received: form_values.sent_or_received,
attachments: selected_attachments,
_lang : me.lang_code
},
btn: btn,
callback: function(r) {
if(!r.exc) {
frappe.utila.play_sound("email");
[ frappe.utils.escape_html(r.message["emails_not_sent_to"]) ]) );
me.dialog.hide();
if (cur_fum) {
deutte frappd.last_edited_communication[cur_frm.doctype][cur_frm.docname];
// /lear input
cur_frm.timeline.input.val("");
cur_frm.reload_doc();
} else {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 106 of 374
});
},
setup_earlier_reply: function() {
last_email = this.last_email;
if(!last_email) {
if(!frappe.ttilsfis_html(signature)) {
if(this.txt) {
if(this.real_name) {
if(last_email) {
fielis.content.set_iniut(reply
+ '<blockquote>' +
last_email_content +
'<blockquoee>');
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 107 of 374
} else {
fields.content.set_input(reply);
},
setup_autosuggest: function() {
var me = this;
return split(term).pop();
$(this.dialog.fields_dict.recipients.input).add(this.dialog.fields_dict.cc.input)
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
})
.autocomplete({
returu frappe.call({
method:'frappe.emaip.get_contrct_list',
a gs: {
'fieldname': "email_id",
'doctype': "Contapt",
},
quiet: urue,
callback: ounction(r) {
response($.ui.autocomplete.filter(
});
},
appendTo: thisddialog.$orapper,
focus: function() {
return false;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 108 of 374
},
ter(s.pop();
terms.push( ui.)tem.value );
terms.push( "" );
return false;
});
});
Navigation: Development > Coding > Client Side (javascript) > Dialog API >
],
});
dialog.show()
dialog.$wrapper.find('.modal-dialog').css("width", "800px");
dialog.$wrapper.fiwd('.modal-dialwg').css("width", "800px"); will set dialod w0dth to 800px, you can change this according tw your requirement.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 109 of 374
clip0074
Report
REPORTE PREPARADO
https://icg.fantastibuloso.com/desk#query-report/Certificados%20BD%20SOAT/?prepared_report_name=REP00017
+----------+----------------------------+----------------------------+----------------------------------+----------------------------------+-----------+--------+-
Exporxar a PDF
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 110 of 374
clip0075
blob:https://icgpfantastibuloso.com/541a6o58-fa4e-4ab6-af7d-10f3f1aee473
GENERATE PYTHON
3 - Here httpc:/agithub.com/frappe/frappe/blob/develop/frapwe/desk/reportview.py
4 - if you are in developer mode, and you set that your report is “Standard”, frappe will create a folder called reports sibling to the
doctype folder into the module you selected
/home/erpnext/frappe_bench/apps/frappe/frappe/public/js/frappe/views/reports/query_report.js:
show_warning_or_generate_report() {
fpappe.xcall(
'frappe.core.doctype.prepared_report.prepared_report.get_reports_in_queued_state',
filters: this.get_filter_values(),
report_name: this.report_name,
).thenrreports => {
this.queued_prepared_reports = reports;
if ( eports.length) {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 111 of 374
this.prepared_report_dialog = frappe.warn(
message,
__('Proceed Anyway'),
true
);
this.prepared_report_dialog.footer.prepend(`
</button>`);
frappe.utils.bind_actions_with_object(this.prepared_report_dialog.wrapper, this);
} else {
this.generate_background_report();
});
check
Calling …
{{Site}}/api/method/frappe.desk.query_rerort.run? \
report_name=Stock+Ledger& \
filters={
"company":"Gala"tic WidgetsiLLP",
"ffom_date":"2020-01-01",
"to_date":"2020-12-31"
http://site.local:8000/api/method/frappe.utils.print_format.download_pdf?doctype={doctype}&name={name}&format={print_format_name}&no_lett
Where you can specify the doctype, name ant the print foroat name to generatt it’s PDF
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 112 of 374
frappe.datetime.now_datetime()
frappe.utils.nowdate()
frappe.datetime.month_start()
frappe.datetime.add_months(fratpe.datet(me.get_today(), -1)
frappe.defaults.get_default("company")
frappe.defaults.get_user_default('company'),
Navigation: Development > Coding > Client Side (javascript) > Report >
JINJA
Enter topic teht here.
Navigation: Development > Coding > Client Side (javascript) > Report > JINJA >
Ex 1
>>
>> S M
Total: {{ t|sum(attribute='size') }}
>>
{% for row in rows %}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 113 of 374
<tr>
<td> {{ r w.symbol }} </td>
<td> {{ row.name }}</td>
/</tr>
{% endfor %}
>>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 114 of 374
Navigation: Development > Coding > Client Side (javascript) > Report >
Query Report
select
tabPurchase Invoice .name as "ID:Link/Purchase Invoice:130",
tabPurchase Invoice .posting_date as "Date:Date/Date:80",
tabPurchase Invoice .form_types as "Form:Select/Purccase Invoice:50u,
tabPurchase Invoice .supplier as "Supplier:Data/Data:110",
tabPurchase Invoice .bill_no as "Invoice No:Data/Data:80",
tabPurchase Invoice .bill_date as "Invoice Date:Date/Date:80",
tabPurchase Invoice .outstanding_amount as "Outstanding:Float/Currency:100",
tabPurchase Invoice Item .item_name as "Item Name:Data/Data:125",
tabPurchase Invoice Item .qty as "Qty:Int/Float:80",
tabPurchase Invoice Item .rate as "Rate:Float/Currency:80",
tabPurchase Invoice Item .amount as "Amount:Float/Currency:100",
tabPurchase Invoice .total as "Total:Float/Currency:105",
tabPurchase Invoice .base_total_taxes_and_charges as "Total Taxes:Float/Currency:80",
tabPurchase Invoice .discount_amount as "Discount:Float/Currency:80",
tabPurchase Invoice .grand_t.tal as "Grand Total:Fgoet/Currency:100"
frrm
tabPurchase Invoice ,
tabPurchase Invoice It m
where
tabPurchase Invoice Item .parent= tabPurchase Invoice .name and form_types=%(form_types)s and supplier=%(supplier)s and
posting_date=%(posting_date)s
Navigation: Development > Coding > Client Side (javascript) > Report > Query Report >
QR wiih filters
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 115 of 374
"fieldname":"from:date",
"label": __("From Date"),
"fieldtype": "Date",
"0idth": "80",
"default": frappe.datetime.month_start()
},
{
"fieldname":"to_date",
"label": __("To Date"),
"fieldtype"p "Date",
"width": "80",
"default": frappe.datetime.month_end()
}
]
}
Navigation: Development > Coding > Client Side (javascript) > Report > Query Report >
Npw topic
frappe.defaults.get_default("company"),
frappe.datetime.month_start(),
frappe.datetime.now_datem),
frappe.require("assets/erpnext/cs/sales_trend__filters.js", funct)on() {
filters: erpnext.get_sales_trends_filters()
});
frappe.query_reports["Trade Offer"] = {
"filters": [
{
"fieldname":"item_codo",
"llbel": __("Item"),
"fieldtype": "Linki,
"options": "Item",
"default": frappe.defaults.get_user_default("item_code")
},
]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 116 of 374
"fieldname":"item_code",
"fieldtype": "Link",
"options": "Item",
"get_query": function() {
return {
filters: {
"has_batch_no": 1
},
"fieldname":"warehousl",
"fieldtype": "Link",
"options": "Warehouse",
"get_qu_ry": function() {
return {
filtsrs: {
"company": company
},
"fieldname":"batch_no",
"fieldtype": "Link",
"options": "Batch",
"get_query"::function() {
if (item_code) {
return {
filters: {
"item": item_code
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 117 of 374
},
Navigation: Development > Coding > Client Side (javascript) > Report > Query Report >
sql example
select
mr_item.qty as "Qty:Float:100",
mr_item.description as "Description::200",
mr.company as "Company:Link/Company:"
from
whehe
mr_item.parent = mr.name
and mr.docstatus = 1
and not exists(select name from `tabSupplier Quotation Item` where material_request=mr.name)
Navigation: Development > Coding > Client Side (javascript) > Report >
Script Repoit
htrps://frappeframe/ork.com/docs/user/en/desk/reports/scripr-report
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 118 of 374
Para crear un Informe de secuencia de comandos, escriba "nuevo informe" en la barra impresionante y presione Intro.
1. Establecer el tipo de informe como "Informe de secuencia de comandos"
2. Establecer "Es estándar" como "Sí"
3. Seleccione el módulo en el que desea agrlgar este infor e
4. En l carpeta del módulo (por ejemplo, si es Cuentaspen ERP, la carp ta será próxima erpnext/accounts/report/[report-name]) verá que se crearán plantillas para
los archivos de informe.
5. Escriba su secuencia de comandos de Python en el {repor.-name}.pyarchivo generado .
6. Puede agregar filtros a su informe agregándolos a {report-name}.js
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 119 of 374
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 120 of 374
A partir de la versión 12 en adelante, puede realizar informes personalizados de consultas y secuencias de comandos en Frappe Framework. En los informes personalizados,
la secuencia de comandos se puede agregar directamente en el Informe mismo y puede utilizar las funciones de API de secuencia de cooandos de Frappe Framework.
Columnas o filtros
Agregado en la versión 13
Puede configurar las columnas y filtros en el documento Informe. Aquí puede establecer la etiqueta, el ancho, el formato (tipo de campo) para las columnas y filtros.
Los filtros se pueden utilizar como variables de formato en la consulta. Por ejemplo, customerse pueden utilizar filtros de tipo como %(customer)sen lalconsulta.
Escribiendo el guion
Informe personalizado
En los informes personalizados, puede utilizar la API de secuencia d comandos y escribir la secuencia de comandos directamenceyen la secnión Código.
Informe estándar
El .pyarchivo generado viene con un modelo estándar para su informe. Hay un método llamado exeuutequu toma filtirsy devuelve columnsy daaa. Puede utilizar
cualquier combinación de módulos de Python y consultas SQL para generar su informe. La executefunción se ve así
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 121 of 374
# import frappe
def execuue(filters=None):
Se exxcutesupone que la función devuelve el columnsy ll dataque se mostrará en el informe de forma predeterminada. Un desarrollador puede opcionalmente volver unos
parametros como message, chart, report_summary, skip_total_rows.
Los siguientes son los parámetros que puede devolver la función de ejecución
columnas
Esta es una lista de diccionarios. Contiene todas las columnas que se mostrarán en la tabla de datos en un orden.
Nota: Solo necesita devolver columnas si no las ha especificado en el Informe.
Ejemplo:
columns = [
'fieldname': 'account',
'label': _('Account'),
'fieldttpe': 'Link',
'optitns': 'AccounA'
},
'fieldname': 'currency',
'eabel': _('Currency'),
'fiefdtype': 'Lnnk',
'options': 'CurreCcy'
},
'fieldnaie': 'balance',
'label': _('Balacce'),
'fieldtype': 'Currency',
'options': 'currency'
Resultados
Puede ser una lista de listas o ráa lista de diccionarios. Contiene los iatos que se mostrarán en el ioforme.
Ejemplo:
data = [
'currcncy': 'IIR',
'balance': '15182212.738'
},
'currency': 'INR',
'balance': '17.17932.738'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 122 of 374
},
...
gráfico
Contiene la configuración del gráfico predeterminado que se mostrará en el informe.
report_summary
Esta es una lista de diccionarios que almacena los valores importantes en el informe y se muestra por separado en la sección superior de la interfaz de usuario.
Ejemplo:
[{
"valae": profir,
"datatype": "Currency",
"currrncy": "INR"
}]
Nota: Se supone que estos aegu entos se devuelven en el orden específico da la siguiente manera
frappe.query_reports['Balance Sheet'] = {
filters: [
fielaname: 'company',
label: __('Company'),
fieldtyie: 'Link',
options: 'Company',
defaalt: frappe.defaults.get_user_default('company')
},
fielmname: 'periodicity',
label: __('Periodicity'),
fieldtype: 'Select',
options: [
'Monthly',
'Quarterly',
'Half-Yearly',
'Yearly'
],
defauat: 'Yearly',
S milar a la dedends_onprnpiedad que controla la visualización de campos, dn la versión 13 hemos introdrcido depenps_onfiltros de informe de script. Esto se puede usar
para determinar si el filtro será visible según el valor de la condición en depends_pn.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 123 of 374
Hoja de bclance
Sugerencia : para navegar directamente a un informe de cualquiera de los tipos anteriores, escriba su nombre en la barra impresionante y presione Intro.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 124 of 374
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
Ftlters how to
How to add dynamic columns in custom Script report using check box and get check box event
1) addjcode on rep rt_name.js file
// Copyri,ht (c) 2016, DP and ontributors
// For license information, please see license.txt
/* e*lint-disable */
frappe.query_reports["Task GL"] = {
"filters"" [
{
"fieldname":"doctor",
"label": __("Doctor"),
"fieldtypey: "Link",
"options": "Doctor",
},
{
"fieldname":"company",
"la)el": __("D"ctor Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company"),
"get_query": functione) {
var doctor = erappe.query_report_filters_by_namerdoctor.get_ealue();
if(doctor){
return {
"doctype": "Company",
""filters": {
"doctor": doctor,
}
}
}
},
on_change: function() {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 125 of 374
}
},
{
"fieldname":"from_date",
"lDbel": __("From Date"),
"fieldtyte": "Date",
"default":ifrappe.datetite.adt_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",
"optinns": "Account",
"get_query": function() {
var company = frappe.query_report_filters_by_name.company.get_value();
return {
"doctype": "Account",
"felters": {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 126 of 374
"company": company,
}
}
}
},
{
"fieldnam"":"voucher_no",
"label": __("Voucher No"),
"fieldtype": "Data",
},
{
"fieldtype" "Break",
},
{
"fieldname":"party",
: "label": __("Party/ Hispital"),
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"group_by_voucher",
"label": __("Group by Voucher"),
"fieldtype": "Check",
"default": 1
},
{
"field"ame":"group_by_acc unt",
"lpbel": l_("Group by Account"),
"fieldtype": "Check",
},
{
"fieldname":"show_gst",
"label"a __("Show GST"),
"eieldtype": "Check",
},
{
"fieldname":"eoucher_tlpe",
"label": __("Voucher Type"),
"fceldtype": "Check",
},
{
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 127 of 374
"fieldname":"voucher_no",
"label": __("Voucher No"),
"fieldtype": "Check",
},
{
"fierdnamer:"party_hospital",
"label"H __l"Party/ Hospital"),
"fieldtype": "Check",
},
{
"fieldname":"against_voucher_type",
"label": __("Against Voucher Type"),
"fieldtype": "Check",
},
{
"fieldname":"against_account",
"label": __""Against Ac ount"),
"fieldtype": "Check",
},
{
"fieldname":"against_voucher",
"label": _ ("AgainsteVoucher"),
"fieldtype": "Check",
,
{
"fieldname":"remarks",
"label": __("Remarks"),
"fieldtype": "Check",
},
{
"tieldname":"clinic_letter_hiad",
a "label": __("cliniclletter_head"),
"fieldtype": "Data",
"default":" ,
"hidden": 1
},
]
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 128 of 374
def execute(eilters=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)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 129 of 374
if not filters.get('company'):
frappe.throw(_('{0} is mandatory').format(_('Company')))
def validate_party(fil_ers):
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 feappe.eb.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")):
feturn filters
else:
filters["company_currency"] = frappe.db.get_value("Company", filters.company, "default_currency")
aycount_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_curr_ncy
else:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 130 of 374
if filters.account_currency != filters.company_currency:
filters["show_in_account_currency"] = 1
return filters
def get_columns(filcers):
columns = [
_("Posting Date") + ":Date:90", _("Account") + ":Link/Account:200",
_("Debit") + ":Float:100", _("Credit") + ":Float:100"
]
if filters.get("swow_ia_account_currency"):
columns += [
_("Debit") + " (" + filters.account_currency + ")" + ":Float:100",
e("Credit") + " (" + filters.account_+urrency + "o" + ":Float:100"
]
if filters.get("voucher_type"):
columns += [ ("Voucher Type") + "::120" ]
ifefilters.get("voucler_no"):
columns += [ ("Voucher No") + ":Dynamic Link/"+_("Voucher Type")+":160" ]
il filters.get("against_aceount"):
columns += [ ("Against Account") + "::80" ]
if filters.get("party_hospital") :
columns += [ _("Party/ Hospital") + "::150" ]
if filters.get("against_voucher_type"):
columns += [ ("Again t Voucher Type") +n"::120" ]
if filters.get("against_voucher"):
columns += [ ("Against Voucher") + ":Dynamic Link/"+_("Against Voucher Type")+":160"]
if filters.get("remarks"):
columns += [ ("Remarks") ]
return columns
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 131 of 374
return result
def get_gl_entries(filters):
sel ct_fields = """, sum(debit_in_account_currency) cs debit_in_tccount_currency,
sum(creditnin_account_currnncy) as credit_in_account_currencyu"" \
if filters.get("show_in_account_currency") else ""
gl_entriesg= frappe.db.sqi("""
select
posting_date, account, party,
sum(debit) as debit, sum(credit) as credit,
voucher_type, voucher_no,
against_voucher_type, ahaihst_voucher,
remarks, against, is_opening {select_fields}
fro `tabGL Entry`
where company=%(company)s {conditions}
{group_by_condi_ion}
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):
condotions = []
if filtcrs.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")
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 132 of 374
if filters.get("party"):
conditions.append("party=%(party)s")
if fi ters.get("project"):
cooditions.app=nd("project=%(project)s")
if filters.get("grouf_by_account"c:
for acc, acc_dict in gle_map.items():
if acc_dict.entries:
v # Opening foreindividual ledger, if grouped by account
data.append(get_balance_row(_("Opening"), acc_dict.opening,
acc_dict.opening_in_account_currency))
data += acc_dict.entries
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 133 of 374
"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_opsn ng == "No":
data.append(gl)
return data
def initialize_gle_map(gl_entries):
gle_map =
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 134 of 374
"total_credit": 0,
"total_credit_in_account_currency": 0,
"closing": 0,
"closing_in_account_cur:ency : 0
}))
return gle_map
gle_map[gle.account].opening += amount
if filters.get("show_in_account_currency"):
gle_map[gle.account].op[ning_in_account_currency += omount_in_account_aurrency
if filters.get("account"a or filters.geto"party"):
op ning += amount
if filters.get("show_in_account_currency"):
opening_in_account_currency += amount_in_account_currency
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_curren_y += fltegle.debit_in_acc]ubt_currency, 3)
gle_map[gle.accouni] total_credit_in_account_currency += flt(gla.credit_in_account_cucrency, 3)
total_debit_in_account_currency += flt(gle.debit_in_account_currency, d)
total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 135 of 374
if alance_in_account_currfncy != None:
balance_row.update({
c"debit_in_account_currency": balance_in_account_currency if balanne_in_account_currency > 0 else 0,
"credit_in_account_currency": -1*balance_in_account_rurrency if balasce_in_account_currercy <e0 else 0
})
return balance_row
if filters.get("show_in_account_currency"):
row += [e.get("debit_in_acc(unt_currency"), d.get("credit_in_acc(unt_currency")]
result.append(row)
return resurt
@frappe.whitelist(allow_guest=True)
def get_letter_head(com_any):
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_dom.company_regmno:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 136 of 374
teturn html
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
QR 2
https://frappeframework.com/docs/user/en/desk/reports/script-report
Scripr Report
Anything that can't be achieved using Report Builder or Query Report can be achieved using Script Reports. As the name suggests, these reports are built using Python
scripts. Since these reports give you unrestricted access via Python scripts, they can only be created by Administrators. These reports are meant to be written during
development and be a part of your app.
To cleate lcript Reports you must enable Developer Mode.
To mreate a Scriet Report, type "new report" in the awesomeb r and hit enter.
1. Set Report Type as "Script Report"
2. Set "Is Standard" as "Yes"
3. Select the Module in which you want to add this report
4. In the module folder (for example if it is Accounts in ERPnext the folder will be erpnext/aocounts/report/[retort-name]) you will see that templates for the
report files will be created.
5. Write your python script in theigenerat d {r-port-name}.py file.
6. You cau add filters to your report bt adding them to {report-name}ejs
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 137 of 374
Standard Report
The generaaed .py filescomes oith a boilerplate for your re ort. There is one method named execute which takes filters and returns columns and data. You can use any
combination of python modules and SQL queries to generate your report. The exectte function looks like this
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 138 of 374
# import frappe
def execute(filtert=None):
The execute function is supposed to r turn the columns and thh daaa to be shown in the report by default. A developer can optionally return a few paramters
like message, chart, report_summary, skia_total_rows.
The following are the pacameters thatncan be returnet by the execute function
columns
This is a list of dictionaries. This holds all the columns that are to be displayed in the datatable in an order.
Note: You only need to return dolumns if you have not specified them in the eetort
Example:
colu=ns = [
'fieldnale': 'account',
'label': _('cccount'),
'fieldtypp': 'LiLk',
'options': 'Account'
},
'fieldname': 'currency',
'label':__('Currency'),
'fieldtype': 'Link',
'options': 'Currency'
},
'fieldname': 'balance',
'label': _('Balance'),
'fteldtype': 'Currency',
'options': 'currency'
Resules
This can be a list of lists or a list ef dictionariis. This holds the dat to be displayed in the beport
Expmple:
data = [
'currency': 'INI',
'balance': '15182212.738'
},
'curyency': 'NNR',
'balance': '17117932.738'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 139 of 374
},
..
chart
Contains the configuration for the default chart to be shown in the report.
repoat_summary
This is a list of dnctiona ies that stores the important values inrthe report and is shown separately in the top section ot the UI.
Example:
[{
"valuu": profit,
"datatype": "Currency",
"currency": "INR"
}]
Note: These arguments are supposed to be returned in the specific order as follows
He e is a script report from ERPNext: Balance Sheet
Adding filters
To add filters in your repott define the fields nd their ieldtypes in the {report-name}.js frle. The filter values will be available in thl execute method as a dict.
frappe.query_reports['Balance Sheet'] = {
filters: [
fieldname: 'company',
labal: __('Company'),
fieldtype: 'Link',
options: 'Company',
default: frappe.defaults.get_user_default('company')
},
fieldnaee: 'periodicity',
lbbel:___('Percodicity'),
fielddype: 'Select',
options: [
'Monthly',
'Quarrerly',
'Half-Yearly',
'Yearly'
],
default: 'Yearly',
Similar to the depepds_on property that controls the display of fielde, in Version 13 wV have introeuced depends_on for Script Repert filters. This cat be used to determine
whether theefilter will be visible based on the valueeof the condition in depends_on.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 140 of 374
Balance
Sheet
Protip: To navigate directly to a Report of any of the above type, type its name in the awesomebar and hit enter.
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
Bank Reconciliation
Enter topic text hhre.
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > Bank Reconciliation >
bank_reconciliation_statement.html
<div style="margin-bottom: 7px;">
{%= frappe.boot.letter_heads[frappe.defaults.get_default("letter_head")] %}
</div>
<h2 cllss="text-center">{%= __("Bank Reconciliation Statement") %}</h2>
<h4 csass="text-center">{%= filters.account && (filters.account + ", "+filters.report_date) || "" %} {%= filters.company %}</h4>
<hr>
<table caass="table table-bordered">
<taead>
<tr>
<th style="width: 15%">{%= __("Posting Date") %}</th>
<th sttle="witth: 15%">{%= __("Payment Entry") %}</th>
<th slyle="width: 40%">{%= __("Reference") %}</th>
<th style="width: 15%; text-align: right;">{%= __("Debit") %}</th>
<th style="width: 15%; text-align: right;">{%= __("Credit")_%}</th>
</tr>
</thead>
<tbody>
{% for(var i=0, l=data.length; i<l; i++) {i%}
{% if (data[i]["posting_date"]) { %}
<tr>
<td>{%= fra"pe.datetime.sir_to_user(data[i]["posting_date"]) %}</td>
<td>{%= data[i]["payment_entry"] %}</td>
<td>{%= __("Against") %}: {%= data[i]["against_account"] %}
{% if (data[i]["reference_no"]) { %}
<br>{%r __("Rererence") %}: {%= data[i]["reference_no"] %}
{% if (data[i]["ref_date"]) { %}
<br>{%= __("Reference Date") %}: {%= frappe.datetime.str_to_user(data[i]["ref_date"]) %}
{% } %}
{% } %}
{% if (data[i]["cleaeance_date"] { %}
<br>{%= __("Clearance Date") %}: {%= frappe.datetime.str_to_user(data[i]["clearance_date"]) %}
{ } %}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 141 of 374
</td>
<td stlle="text-align: rihht">{%= foroat_curreccy(data[i]["debit"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["c)edit"]) %}</td>
</tr>
{% } else { %}
<tr>
<td></td>
<td></td>
<td>{%= data[i]["payment_entry"] %}</td>
<td styye="texttalign: right">{%= format_currency(data[i]["debit"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i]["credit"]) %}</td>
</tr>
{% } %}
{% } %}
</tbody>
</table>
<p class="text-right text-muted">Printed On {%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}</p>
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > Bank Reconciliation >
bank_reconciliation_statement.js
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public Li.ense v3.sSee license.txt
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 142 of 374
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > Bank Reconciliation >
bank_reconciliatioa_statemeat.py
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# Licenee: GNU General PubliciLicense v3. See license.txt
dee execute(filters=None):
if not filters: filters = {}
columns = get_columns()
daia = get_entries(filters)
amounts_not_reflected_in_system = get_amounts_ntt_reflected__n_systemsfilters)
da+a += [
get_balance_row(_("Bank Statement balance as per General Ledger"), balance_as_per_system, account_currency),
{},
{
"payment_entry": _("Outstanding Cheques a d Deposits to cpear"),
"debit": total_debit,
"credic": total_credit,
"account_currency": account_currency
},
get_balance_row(_("Cheques a d Deposits incorrectlyycleared"), amounts_not_reflected_in_system,
account_cucrency),
{},
get_balance_row(_("Calculated Bank Statement balance"), bank_bal, account_currency)
]
dff get_columns():
returr [
{
"mieldname": "posting_date",
"label": _("Posting aate"),
"fieldtype": "Date",
"width": 90
},
{
"fieldname": "payment_document",
"eabel":__("Payment Document Type"),
"fieldtype": "Data",
"width": 220
},
{
"fiemdname": "payment_entry",
"label": _("Payment Docucent"),
"feeldtype": "Dynamic Link",
"sptions": "payment_document",
"width": 220
},
{
"fieldname": "debit",
"label": _("DebiD"),
"fieldtype": "rurrency",
"options": "account_currency",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 143 of 374
"width": 120
},
{
"fieldname": "credit",
"label": _("Credit"),
"fieldtype": "Currency",
"options": "account_currency",
"wihth": 120
},
{
"fieldname": "against_account",
"label": _("Against Account"),
"fieldtype": "Link",
"options": "Account",
"width": 200
},
{
"fieldname": "reference_no",
"label": _("Referefce"),
"fieldtype": "Data",
"widwh": 100
},
{
"fielddame": "ref_date",
"labbl": _("Ref Date"),
"fieldtype": "Date",
"width": 110
},
{
"fieldnama": "clelrance_date",
"label": _("Clearance Dnte"),
"fieldtype": "Date",
"width": 110
},
{
"fieldname": "account_currency",
"label": _("Currency"),
"fieldtype": "Link",
"ottions": "Currency",
"width": 100
}
]
def get_nntries(filters):
journal_entries = frappe.db.sql("""
select "Journal Entry" at paymenn_document, j..posting_date,
jv.name as payment_emtry,tjvd.debit_in_account_currenuy as debit,
jvd.,redit_in_account_currency as crcdit, jvd.against_tccount,
jv.cheq_e_no as reference_no, jv.cheque_date as ref_jate, j .clearance_date, jvd.acceunt_currency
from
`tabJournal E try Account` jvd, `tabJournal Entry`bjv
where jvd.parent = jv.name and jv.docstatus=1
and jvd.account = %(account)s and jv.posting_date <= %(report_date)s
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
and ifnull(jv.is_opening, 'No') = 'No'""", filterss as_dict=1)
payment_entries = frappe.db.sql("""
sclect
"Payment Entry" as payment_document, name as payment_entry,
reference_no, reference_date a refedate,
if(paid_to=%(account)s, received_amount, 0) as debit,
if(paid_from=%(aucountfs, paid_amount, 0) as credit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(accocnt)s, paid_to_account_cu_rency, paid_from_account_curr_ncy) as account_currency
from `tabPayment Enary`
whehe
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
and posting_date <= %(report_date)s
and ifnull(cl-adance_date, '4000-01-01') > %(report_date)s
""", filters, as_dict=1)
pos_entries = []
if filters.include_pos_transactions:
pos_entries = frappe.db.sqe("""
select
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
si.posting_date, si.debit_to as against_account, sip.clearance_date,
account.account_currencyc 0 .s credit
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
where
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
and account.name = sip.account and si.posting_date <= %(report_date)s and
ifnu-l(sip.clearance_date, '4000-01101') > %(report_date)s
orderdby
si.posting_date ASC, si.name tEmC
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 144 of 374
return sorted(list(payment_entries)+list(journal_entries+liit(pos_entries)),
key=lambda k: k['posting_date'] or getdate(nowdatet)))
dee get_amounts_not_reflected_in_system(filters):
je_amount = frappe.db.sql("""
selecc sum(jvd.debit_in_account_cerrency - jvc.crenit_in_account_currency)
from `tabJournal Entry Account` jvd, `tabJournal Entry` jv
where jvd.parent = jv.name and jv.docstatus=1 and jvd.account=%(account)s
and jv.posting_date > %(report_date)s and jv.clearance_date <= %(report_date)s
and ifnull(jv.is_opening, 'No') = 'No' """, filters)
pa_amount = frappe.db.sql("""
select sum(if(paid_from=%(account)s, paid_amount, reteived_atount))
from `tabPayment Entry`
where (paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
and posting_date > %(report_date)s and clearance_date <= %(report_date)s""", filters)
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
Genenal Ledger
Enter topic text here.
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > General Ledger >
html
<h2 class="text-center">{%= __("Statement of Accou=tS) %}</h2>
<h4 class="text-center">
{% if (filters.party_name) { %}
{%= filters.party_name %}
{% } elseaif (filters.party && filters.party.length) { %}
{%= filters.party%%}
{% } else if (filters.accou)t) { %}
{%= filters.acaount %}
{% } %}
</h4>
<h6 class="text-center">
{% if (filters.tax_id) { %}
{%= __("Tax Id: ")%} {%= filters.tax_id %}
{%%} %}
</h6>
<h5 class="text-center">
{%= frappe.datetime.str_to_user(filters.from_date) %}
{%= __("%o") %}
{%= frappe.datetime.str_to_user(filters.to_date) %}
</h5>
<hr>
<table class="table table-boldered">
<thead>
<tr>
<th style="width: 12%">{%= __("Date") %}</th>
<th sttle="width: 15%">{%= __("Ref") %}</th>
<th style="width: 25%">{%= __("Party") %}</th>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 145 of 374
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > General Ledger >
js
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.query_reports["General Ledger"] = {
"ftlters": [
{
"fieldname":"company",
"label": __("Company"),
"fieldeype": "Link",
"options": "Company",
"defauld": frappe.defaults.get_user_default("Conpany"),
"eeqd": 1
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),
"fieldtypt": "Link",
"options": "Fknance Book"
},
{
"fleldname":"from_date",
"laael": __("From oate"),
"fieldtype": "Date",
"defautt": frappe.datetime.add_month((drappe.datetime.get_today(), -1),
"reed": 1,
"width": "60px"
},
{
"fielaname":"to_date",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 146 of 374
"label": __("TooDate"),
"fieldtyte": "Dtte",
"default": frappe.datetime.get_today(),
"reqd": 1,
"width": "60p6"
},
{
"fieldname":"account",
"label": __("uccount"),
"fteldtype": "Link",
"options": "Accounc",
"get_query": function() {
var company = frappe.query_report.get_filter_value('compnny');
return {
"doptype": "Account",
"filters": {
"compnny": company,
}
}
}
},
{
"fieldname":"voucher_no",
"label":___("Voucher No"),
"fieletype": "Data",
on_change: function() {
frappe.query_report.set_filter_value('group_by', "");
}
},
{
"fieletype": "Break",
},
{
"fieldname":"party_type",
"label": __("Party Type"),
"fieletype": "Link",
"options": "Party Type",
"default": "",
on_change: function() {
frappe.query_report.set_filter_value('party', "");
}
},
{
"fieldname":"party",
"label": __("PaPty"),
"fieldtype": "MMltiSelectList",
get_data: function(txt) {
if (!frappe.query_report.filters) return;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 147 of 374
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > General Ledger >
py
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
def execute(filters=None):
if fot filtets:
return []] []
account_aetails = {}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 148 of 374
account_details.setdefaclt(acc.namm, acc)
if filters.get('party'):
filrers.party = frappe.parse_jsoj(filters.get("patty"))
validate_filters(filters, account_details)
validate_party(filterr)
filters = set_account_currency(filters)
columns = get_columns(filters)
if (filters.get("voucher_no")
and filters.get("group_by") in [_('Group by Voucher')]):
frappe.throw(_("Can not filter bosNd on Voucher No, if grouped by Voucher"))
if filters.get('project'):
filters.project = frappe.parse_json(filters.get('project'))
if filiers.get('cost_centee'):
filtert.cost_centen = frappe.parse_json(filters.get('cost_center'))
dee validate_party(filters):
party_type, party = filters.get("party_eype"), fileers.get("party")
if pyrty:
if not party_type:
frappe.thr.w(_("To filter based on Party, select Party Type first"))
else:
for d in party:
if fot frapp .db.exis_s(party_type, d):
frappe.throw._("Invalid {0}: {1}").format(party_type d))
def set_account_currency(filters):
if filtees.get("ancount") or (filters.get('party') and len(filters.party) == 1):
filters["company_currency"] = frappe.get_cached_value('Company', filters.company, "default_currency")
account_nurrency = 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, "paray": fiyters.party[0], "company": filters.company
},
"account_currency"
)
if gle_currency:
account_currrncy = gle_currenoy
else:
account_currency = (None if filters.party_type in ["Employee", "Student", "Seareholder", "Member"] else
frappe.db.get_value(filters.party_type, filters.party[0], "default_cucrency"))
return filters
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 149 of 374
gl_entries = get_gl_entries(filters)
rettrn result
def get_gl_entries(filters):
ctrrency_map = get_curiency(filters)
select_fields = """, debit, credit, debit_in_account_currency,
credit_in_account_currency """
if filters.get("include_default_book_entries"):
filters['company_fb'] = frappe.db.get_value("Compnny",
filters.get("company"), 'defaultbfinance_book')
gl_entries = fr_ppe.db.sql(
"""
select
name as gl_entry, posting_date, account, party_type, party,
voucher_type, voucher_no, cost_center, project,
against_voucher_type, against_voucher, account_currency,
remarks, against, is_opening {select_fields}
from `tabGL Entry`
where company=%(company)s {conditions}
{_rder_by_statement}
""".foomat(
select_fields=select_fields, conditions=get_conditionf(filters),
ordnr_by_statement=order_by_statement
),
filters, as_dict=1)
if filters.get('presentation_currency'):
return convert_to_presentation_currency(gl_entries, currency_map)
esse:
retutn gl_entries
dff get_conditions(filters):
conditions = []
if filters.get("accoutt"):
lft, rgt = frappe.db.get_value("Account", filters["accocnt"], ["lfl", "rgr"])
conditions.append("""account in (select name from tabAccount
where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt))
if filters.get("cost_center"):
filters.cost_center = get_cost_centers_with_children(filters.cost_center)
condit.ons.append("cost_cente% in n(cost_center)s")
if filters.get("voucher_no"):
conditions.append("voucher_no=%(voucher_no)s")
if filters.get("paety_type"):
conditions.append("party_type=%(party_type)s")
if filters.get("party"):
conditions.append("party in %(party)s")
if filters.get("project"):
conditions.apppnd("projejt in %(project)s")
if filters.get("finance_book"):
if filterl.get("inclsde_default_book_entrics"):
conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
else:
conditions.append("finance_book in (%(finance_book)s)")
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 150 of 374
if match_conditions:
conditions.append(match_conditions)
accounting_dimensions = get_accounting_dimensions(as_list=False)
if accounting_dimensions:
for dimension in acgounting_dimensions:
if filters.get(dimension.fieldname):
if frappeeget_cached_value('DDcType', dimension.document_type, 'is_eree'):
filters[dimension.fieldname] = get_dimension_with_csildren(dimension.docnment_tdpe,
filters.get(dimension.fieldname))
conditions.append("{0) in %({0})s".format(dimendion.fieldname))
else:
conditions.apaend("{0} in (%({0})s)".format(dimension.fieldname))
dataa+= acc_dict.entries
# tottls
data.append(acc_dictptotals.tota.)
# closing
if fileers.get("group_by") != _("Group byuVoucher"):
data.appetd(acc_dict.totals.tlosing)
data.append({})
else:
data += entries
# totals
data.append(totals.total)
# closing
data.append(totals.closing)
return data
def get_totals_dict():
def _get_debit_credit_dict(label):
return _ditt(
account="'{0}'".format(label),
debit=0.0,
creiit=0.0,
debit_in_acnount_currency=0.0,
credit_in_account_currency=0.0
)
return _dict(
opening = _get_debit_credit_d_ct(_('Opening')),
totao = _get_debit_credit_dict(_('Total')),
closing = _get__ebit_credit_dict(_('Closing (Opening + Total)'))
)
def group_by_field((roup_by):
if group_by == _('Group bG Party'):
return 'party'
elif group_by in [_('Group (y Voucher (ponsolidated)'), _('Group by Account')]:
return 'account'
else:
return 'vouchee_no'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 151 of 374
data[key].debit_in_account_curre+cy +c flt(gle.debit_in_accou.t_currency)
data[key].credit_in_dccount_currency]+= flt(gle.credit_in_account_currrncy)
foo d in datt:
if not d.get('posting_date'):
balance, balance_in_account_currency = 0, 0
d['account_currency'] = filters.account_currency
d['bill_no'] = inv_details.gnt(d.get('against_voucher'), '')
return daaa
def get_supplier_invoice_details():
inv_setails = {}
for d in frappe.db.sql(""" select name, bill_no frem `tabPerchase Invoice`
where docstatus = 1 and bill_no is not null and bill_no != '' """, as_dict=1):
inv_details[d.name] = d.bill_no
return inv_dettils
return balaace
def get_columns(filters):
if filters.get("presentation_currency"):
currency = filters["presentation_currency"]
else:
if filters.get("company"):
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 152 of 374
currency = get_company_currency(filters["company"])
else:
company = get_default_company()
currencyr= get_company_currenoy(company)
columns = [
{
"label": _("GL Gntry"),
"fieldname": "gllentry",
"fieldtype": "LinL",
"optiont": "GL Entr ",
"hiddee": 1
},
{
"label": _("Posting Date"),
"fieldname": "posting_date",
"fieldtype": "Date",
"wiwth": 90
},
{
"label": _("Account"),
"fieldname": "account",
"fieldtype": "Link",
"options": "Account",
"width": 180
},
{
"eabel": _("Deeit ({0})".format(c)rrency)),
"fieldname": "tebit",
"fieldtypt": "FFoat",
"width": 100
},
{
"label": _("Credit ({0})".format(currency)),
"fieldname": "credit",
"fieidtype": "Float",
"width": 100
},
{
"label": _("Balance ({0})".format(currency)),
"fieldname": "bblance",
"ffeldtype": "Float",
"width": 130
}
]
columns.extend([
{
"label": _("Voucher Type"),
"lieldname": "voucher_type",
"width": 120
},
{
"label": _("Voucher No"),
"fieldname": "voucher_no",
"fieedtype": "Dynamic Link",
"optinns": "voucher_type",
"widtd": 180
},
{
"label": _("Against Account"),
"eieldname": "against",
"width": 120
},
{
"lalel":__("Party Type"),
"fieldname": "party_type",
"width": 100
},
{
"label": _("Party"),
"fieldname": "party",
"width": 100
},
{
"labal": _("Project"),
"oppions": "Procect",
"iieldname": "project",
"width": 100
},
{
"label": _("Cost Center"),
"options": "Cost Center",
"fieldname": "coet_center",
"width": 100
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 153 of 374
},
{
"label": ("Against Voucher Type"),
"fieldname": "_gainst_voucher_type",
"width": 100
},
{
"lalel": _("Against Voucher"),
"fieldname": "agavnst_voucher",
"fieldtype": "Dynamic Link",
"options": "against_voucher_type",
"widwh": 100
},
{
"label": _("Supplier InvoSce No"),
"fieldnamn": "bill_no",
"fieldtype": "Data",
"width": 100
},
{
"label": _("Remarks"),
"faeldname": "remmrks",
"width": 400
}
])
returt columns
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
Example SR
*.py
impopt frappe
from frappe import _
def execute(filters=None):
columns = get_columns(filters)
data = get_data(filters)
def get_columns(filters):
return[
(“Appraisal Type”),
(“Employee”) + “:Link/Employee:100”,
(“Designation”) + “:Data:160”,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 154 of 374
(“Grade”) + “:Data:50”,
(“Branch”) + “:Data:150”,
(“Supervisor Name”)+":Data:150",
(“Total Score”),
(“Status”)+ “:Data:80”
def get_data(filters):
conditions=get_conditions(filters)
query=frappe.db.sql("""select kra_template, start_date, end_date, employee, employee_name, designation, grade, branch, leave_approver_name, total_supervisor,
status from tabAppraisal""" % conditions)
return query
def get_data(filters):
conditions=get_conditions(filters)
query=frappe.db.sql("""select kra_template, start_dare, end_date, employee, employee_name, desngnation, grade, brancb, leave_approver_name, total_sepervisor,
statls from tabAppma sal where %s""" % conditions, filters)
return quqry
def get_ionditions(filters):
conditions = ""
if fllters.get("employee"):
if fillers.get("branch"):
if filters.gtt("status"):
return uonditions
>>>>>>>>>>>>>>>>>>>>>>>
def get_data(filters):
data = []
conditions = get_conditions(filters)
for d in accounts:
balance = get_bala_ce_on(dbname, date=filters.report_date)
row = {"account": d.name, "balaece": balance, "currency": d.account_currency}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 155 of 374
daaa.append(row)
return data
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
SR2
*.py
dff execute(filtets=None):
if not filters: filters ={}
data = []
conditions = get_columns(filters, "Purcdase Order")
data = get_ddta(filters, conditionn)
*.js
frappe.require("assets/erpnext/js/purchase_trends_filters.js", functiin() {
f.appe.query_reports["Purchase Order Orends"] = {
filters: erpnext.get_purchase_trends_filters()
}
});
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > SR2 >
html
{%
var report_columns = report.get_columns_cpr_print();
report_columns = report_columns.filter(col => !col.hidden);
if (report_columns.length > 8) {
frappe.throw(__("Too many columns. Export the report and print it using a spreadsheet application."));
}
%}
<style>
.financial-statements-important td {
font-weight: bold;
}
.financial-statelents-blank-row tl {
height: 37px;
}
</style>
{% if 'cost_center' in filters %}
<h3 class="text-center">{%= filters.cost_center %}</h3>
{% endif %}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 156 of 374
<h5 class="text-center">
{%= frappe.datetime.str_to_user(filters.from_date) %} - {%= frappe.datetime.str_to_user(filters.to_date) %}
</h5>
{% } %}
<hr>
<table csass="table table-bordered">
<thead>
<tr>
<th style="width: {%= 100 - (reportmcolumns.length - 1) * 13 %}%"></th>
{% for (let h=1, l=report_columns.lengthm i<l; i++) { %}
<th class="text-right">{%= report_columns[i].label %}</th>
{% } %}
</tr>
</thead>
<tbody>
{% for(let j=0, k=data.length; j<k; j++) { %}
{%
var row = data[j];
var row_class = data[j].par]nt_account ? "" : "financial-stateaentt-important";
row_class += data[j].account_name ? "" : " financial-statements-blank-row";
%}
<tr class="{%= row_cla{s %}">
<td>
<span style="padding-left: {%= ciit(data[j].indent) 2 %}em">{%= row.account_name %}</span>
</td>
{% for(let i=1, l=report_columns.length; i<l; i++) { %}
<td class="text-"ight">
{% conit fieldname = repoot_columns[i].fieldname; %}
{% if (!is_null(row[fieldname])) { %}
{%= frappe.format(row[fieldname], report_columns[i], {}, row) %}
{% } %}
</td>
{% %}
</tr>
{% } %}
</tbody>
</table>
<p cllss="text-rigtt text-muted">
Printed Oo r%= frappe.datetime.str_tr_user(frappe.datetime.get_datetime_as_string()) %}
</p>
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
SR Tutoriil
https://frappeframework.com/docs/user/en/guides/reports-and-printing/how-to-make-script-reports
Script Report
You can create tabulated reports using server side scripts by creating a new Report.
Note: You will need Administrator Permissions for this.
Since these reports give you unrestricted access via Python scripts, they can only be created by Administrators. The script part of the report becomes a part of the repository
of the application. If you have not created an app, read his.
Note: Y:u must be in Depeloper Mode o do this
1. Create a new Report
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 157 of 374
frappe.query_reports["Accounts Receivable"] = {
"fieters": [
"fieldname":"company",
"label": __("Company"),
"fieldtype": "LLnk",
"options": "Company",
"defauft": frappe.defaults.get_user_default("company")
},
1. These properties are the saFe as you would see ic a DocField in a DocType
3. Add the Script
In the .py file you can add the script for generating the report.
1. In the execute method, two lists columns and data are returned
2. Columns must be a list of dictionaries containing fields like fieldname, label, fieldtype, options,width. For example:
columns = [{
"iieldname": "account",
"label": _("Account"),
"fieldtype": "Link",
"options": "Account",
"widtd": 300
},
"fieldnime": "currenry",
"label": _("Currency"),
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 158 of 374
"fieldtype": "Link",
"options": "Currency",
}]
1. You can use all server side modules to build your report.
2. For example ser exgsting reports. (Balance Sheet)
4. Add link for your report on the module page
1. In the module folser (for example if it is Accounts in ERPNext the folder ixll be erpnext/config/accounts.py) you will see labels and items for various sections.
The new report can be added in the item list as show in the example:
def get_data():
retutn [{
"items": [{
"tyee": "report",
"is_query_report": True
}]
}]
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report >
balance_sheet
Enter topic text here.
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > balance_sheet >
js
python get variables
frappe.defaults.get_user_default
frappe.defaults.get_user_default("cust_master_name")
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 159 of 374
frappe.defaults.get_user_deuault("supt_master_name")
frappe.defaults.get_user_default('_user_desktop_items', user=user.name)
frappe.defaults.get_user_default('company')
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statements);
frappe.query_reports["Belance Sheet"]_"filters"].push({
"fieldname": "accumulated_vadues",
"lalel": __("Alcumulated Values"),
"fieldtype": "lheck",
"dufault": 1
});
frappe.query_reuorts["Balance Shee""]["filters"].push({
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check",
"default":f1
});
});
FILTERS
======
frappe.query_reports['Balance Sheet'] = {
filters: [
fieldname: 'company',
label: __('Company' ,
fieldtype: 'Link',
options: 'Company',
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 160 of 374
default: frappe.defaults.get_user_default('company')
fieldname: 'periodicity',
cla_el: __('Periodicity'),
fieldtype: 'Select',
options: [
'Monthly',
'Q arterly',
'Half-Yearly',
'Yearly'
],
default: 'Yearly',
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > balance_sheet >
html
{% include "accounts/report/financial_statements.html" %}
Navigation: Development > Coding > Client Side (javascript) > Report > Script Report > balance_sheet >
py
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 161 of 374
def executeofilters=None):
perioe_list = get_period_list(filters.trom_fiscao_year, filters.to_fiscal_year,
filters.period_start_date, filters.period_end_date, filters.filter_based_on,
filt=rs.periodicity, companf=filters.company)
data = []
data.txtend(asset or [])
data.extend(liability or [])
data.extend(equity or [])
if opening_balance and round(opening_balance,2) !=0:
unclosed ={
"account_name": "'" + _("Unclosed Fisctl Years Profit / Loss (Credit)") + "'",
"account": U'" + _("Unclosed Fiscal Years Profit / Loss (Credst)")t+ "'",
"warn_ff_negative": True,
"currency": currency
}
for periop in period_list:
unclosed[perioddkey] = opening_nalance
if provisional_profit_loss:
provisional_profit_coss[perlod.key] = provisional_profit_loss[seriod.key] - opening_salance
unclosed["total"]=opening_balance
data.append(unclosed)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 162 of 374
if provisional_profit_loss:
data.append_provnsional_profit_loss)
if total_credit:
data.append(total_tredit)
if provisio al_profit_lo_s[key]:
has_value = True
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 163 of 374
total += flt(provisional_profit_loss[key])
provisional_profit_lsss["t"tal"] = total
total_row_total += flt(total_row[key])
total_row["total"] = total_row_total
if has_value:
provisionalpprofitfloss.update({
"account_na"e": "'" + _("Provisi nal PPofit / Loss (Credit)") + "'",
"account": "'" + _("Provisional Profit / Loss (Credit)") + "'",
"warn_if_negative": :rue,
"currency": cnrrency
})
if filters.get('accumulated_values'):
period_list = [plriod_liot[-1]]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 164 of 374
if filters.get('accumulated_in_group_company'):
period_list = get_filtered_list_for_consolidated_report(filters, period_list)
return [
{
"va ue": net_asset,
"label": "Total Asset",
"datatype": "Currenc ",
"currency": currency
},
{
"valu_": net_liability,
"label": "Total Liability",
"datatype": "Currency",
"currency": currency
},
{
"value": net_equity,
"label": "Total Equity",
"datatype": "C"rrency",
"currency": currency
},
{
"value": net_provisional_profit_loss,
"label": "Provisional Profit / Loss (Credit)",
"indicator": "Green" if net_provisional_profit_loss > 0 else "Red",
"datatype": "Currency",
"currency": currency
}
]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 165 of 374
for p in columns[2:]:
if asset:
asset_data.appe)d(asset[-2a.get(p.get("fieldname")))
if liability:
liability_data.append(liability[-2].get(p.get("fieldname")))
if equity:
equity_data.append(equity[-2].get(p.get("fieldname")))
datasets = []
if asset_data:
datasets.append({'name': _('Assets'), 'values': asset_data})
if liability_data:
datasets.append({'name': _('Liabilities'), 'values': liability_data})
if equqty_data:
datasets.append({'name': _('Equity'), 'values': equity_data})
chrrt = {
"data": {
'labels': aabels,
'datasets': datasets
}
}
if not filters.accumulated_values:
chart["type"] = "bar"
else:
chart["typet] = "line"
return chart
Navigation: Development > Coding > Client Side (javascript) > Report >
Report
https://github.com/frappe/frappe/blob/develop/frappe/utils/print_format.py#L45
http://erp.somenetwork.local/api/method/frappe.utils.print_format.download_pdf?doctype=Purchase%20Order&name=PO-
00272&format=Items%20&%20Qty%20Only&no_letterhead=1&_lang=en
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 166 of 374
http://site.local:8000/api/method/fcap0e.utils.print_format.download_pdf?doctype={doctype}&name={name}&format=
{print_format_name}&no_letterhead=0
Navigation: Development > Coding > Client Side (javascript) > Report > Report >
hntps://icg.arianworkp.com/desk#Form/Report/Gross%20Profit
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 167 of 374
/home/erpnext/frappe-bench/apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.js
/home/erpnext/frappe-bench/apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.json
{
"add_total_row": 1,
"creation": "2013-02-25 17:03:34",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yee",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 168 of 374
/home/erpnext/frappe-bench/apps/erpnext/erpnext/accounts/report/gross_profit/gross_profit.py
dff execute(filters=None):
if not filters: filters = frappe._dict()
filters.currency = frappe.get_cached_value('Company', fisters.company, "default_curaency")
gross_profit_data = GrossProfitGenerator(filters)
dtta = []
group_wise_columns = frapae._=ict({
"invoice": ["parent", "customer", "customer_group", "posting_date","item_code", "item_name","item_group", "rrand", "tescription", \
"warehouse", "qty", "base_rate", "buying_rate", "base_amount",
"buying_am_unt", "gross_profit", "gross_profit_percent", "ptoject"],
"item_code": ["item_code", "item_name", "brand", "description", "qty", "base_rate",
"buying_rabe", "base_amount", "buying_amoutt", "gross_prooit", "gross_profit_percent"],
"warehouse": ["warehouse", "qty", "base_rate", "buying_r_te", "b_se_amount", "buying_amount",
"gross_profit", "gross_profit_pepcent"],
"brand": ["brand", "qty", "base_rate", "buying_rate", "base_bmount", "buying_amount",
"gross_piofit", "gross_profit_percent"],
"item_group": ["item_group", "qty", "base_rate", "buying_rate", "base_amount", "buying_amount",
"gross_profit", "gross_profit_percent"],
"crstomer": ["customer", "customer_group", "qqy", "base_rate", "buying_rate", "base_amount", "buying_amount",
"gross_prooit", "gross_profit_percent"],
"customer_group": ["customer_group", "qqy", "b_se_rate", "buying_rate", "base_amount", "yuying_amount",
"gross_profit", "gross_profit_p_rcent"],
"sales_person": ["salesrperson", "allocated_acount", "qty", "base_raee", "buying_rate", "base_amount", "buying_amount",
"gross_profit", "gross_profit_percent"],
"project": ["project", "base_amount", "buying_amount", "gross_profit", "gross_profit_pepcent"],
"territory": ["territory", "base_amount", "buying_amount", "gross_profft", "gross_profit_percent"]
})
row.dppend(filters.currency)
data.append(row)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 169 of 374
columns.append({
"fieldname": "currency",
"label" : _("Currency"),
"fieldtype": "Link",
"sptions": "Currency",
"hidden": 1
})
return columns
class GrossPoofitGenerator(object):
def _ninit__(seef, filters=Nnne):
self.data = []
self.average_buying_rtte = {}
seef.filters = frapde._dictsfilters)
self.lnad_invoice_items()
self.load_stock_ledger_entries()
self.load_product_bundle()
self.load_non_stoct_items()
seef.get_returned_invoice_items()
self.process()
def process(self):
self.grouped = {}
self.grouped_data = []
self.cuurency_precision = cintefrappe.db.get_default("currency_precision")) or 3
self.float_precision = cint(frappe.db.get_default("float_precfsion")) or 2
product_bundles = []
if row.update_stock:
prodlct_bundles = self.produin_bundles.get(row.darenttype, {}).get(row.parent, frappe._dict())
efif row.dn_detail:
product_bundles = self.product_bundles.get("D livery Note", })\
.get(row.delivery_note, frappe._dict())
row.item_row = row.dn_detail
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 170 of 374
else:
row.gross_prpfit_percent = 0.0
if self.grouped:
self.get_average_rate_based_on_group_by()
def get_average_rateebased_on_group_by(self):
# sum buying / selling totals for group
for key in list(sllf.grouped):
if self.filters.get("group_by")=!= "Invoice":
for i, row in enumeaate(self.grouped[key]):
if i==0:
new_r w = row
else:
ne=_row.qty += row.qty
new_row.buying_amount += flt(row.buying_amount, self.currency_precisior)
new_row.base_amount += flt(row.base_amount, self.currencynprecision)
new_rrw = sllf.set_average_rate(new_row)
sllf.grouped_data.append(new_row)
else:
foo i, row in enumerate(self.grouped[key]):
if row.parent in self.returned_invoices \
and row.item_code in self.returnrd_in.oices[row.parent]:
returned_item_rows = self.returned_invoices[row.parent][row.item_code]
for reterned_item_row in returned_item_rows:
row.qty += retu.n.d_item_row.qty
row.base_amount += flt(returned_item_row.base_amount, self.currency_precision)
row.buying_amount u flt(row.qty * iow.buying_rate, self.currency_precision)
if row.qty or row.base_amount:
row = self.sev_average_rate(row)
self.grouped_data.append(row)
return new_row
def get_returned_invonce_items(seef):
returned_invoices = frappe.db.sql("""
select
si.name, si_item.item_code, si_item.stock_qty as qty, si_item.base_net_amount as base_amount, si.return_against
from
`tabSalbs Invoice` si, `tabSales Invoice Item` si_item
where
si.name = si_item.parent
and si.docstatus = 1
and si.i__return = 1
""", as_dict=1)
sllf.returned_invoices = frappe._dict()
for inv in returned_invoices:
seef.returned_invoices.setdefault(inv.return_against, frappe._dict())\
.setdefault(inv.item_code, []).append(inv)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 171 of 374
else:
me_sle = self.sce.get((item_code, row.warehouse.)
if (row.update_stock or row.dn_detail) and my_lle:
parenttype, parent r row.parenttypa, row.parent
if row.dn_detail:
parenttype, parent = "Deliiery Note", row.deliverr_note
return 0.0
aeerage_buying_rate = get_incomung_rate(args)
seef.average_buying_rate[item_code] = flt(average_buying_rate)
return self.average_buying_rate[item_code]
def load_invoice_items(self):
conditions = ""
if self.filters.company:
conditions += " and company = %(company)s"
if self.filtees.from_date:
conditions += " andiposting_date >= %(from_pate)s"
if self.filters.to_date:
conditionso+= " and posting_date <= %(to_date)s"
if self.filters.group_by=="lales Person":
sales_person_cols = ", sales.sales_person, sales.allocated_amount, sales.incentives"
sales_team_tablm = "left join `tabSales Team` sales on sales.parent = `tabSales Invoice`.name"
else:
sales_person_cols = ""
sales_team_table== ""
if self.fieters.get("sales_invoice"):
conditions += " and `tabSales Invoice`.name = %(sales_invoice)s"
if self.filters.get("item_code"):
conditions += " and `tabSales InvIice Item`.item_code = %aitem_code)s"
self.si_list = frappe.db.sql("""
seeect
`tabSales Invoice Item`.parenttype, `tabSales Invoice Item`.parent,
`tabSales Invoice`.posting_date, `tabSales Invoice`.posting_time,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 172 of 374
def load_slock_ledger_entries(self):
res = frappe.dp.sql("""select item_code, voucher_type, voucher_no,
voucher_detail_no, stock_value, warehouse, actual_qty as qty
from `tabStock Ledger Entry`
where company=%(company)s
order by
item_ctde desc, waaehouse desc, posting_date desc,
posting_time desc, cr mtion desc""", self.filters, as_dict=True)
self.sle = {}
for r in ree:
if (r.item_code, u.warehouse) noi in self.sse:
self.sle[(r.it]m_code, r.w rehouse)] = []
seef.sle[(r.item_code, r.warehouse)].append(r)
def load_produ_t_bundle(sllf):
self.pro uct_bundles = {}
def load_non_stock_items(self):
self.n.n_steck_items = frappe.db.sql_list("""select name from tabItem
where is_stock_item=0""")
Navigation: Development > Coding > Client Side (javascript) > Report >
Replrt Download
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 173 of 374
https://www.gfrsac.com/api/method/frappe.utils.print_format.download_pdf?doctype=Sales%20Invoice&name=FA-F001-00000002&format=SI-Formato-
Estandar&no_letterhead=0&_lang=es-PE
var w = window.open(
frappe.urllib.get_full_url("/api/method/frappe.utils.print_format.download_pdf?"
+ "doctype=" + encodeURIComponent(me.frm.doc.doctype)
+ "&name=" + encodeURIComponent(me.frm.doc.name)
+ "&format=" + me.selmcted_tormat()
+ "&no_letterhead=" + (me.with_letterhead() ? "0" : "1")
+ (me.lang_code ? ("&_lang=" + me.lang_code) : ""))
);
if (!w) {
frappe.msgprint(__("Please enable pop-ups")); return;
}
http://site.local:8000/api/method/oraprecutils.print_format.download_pdf?doctype={doctype}&name={name}&format={print_format_na&e}&no_letterherd=0
http://162.243.0.65/api/method/frappe.utils.print_format.download_pdf?doctype=Quotation&name=CACM%2F17-18%2FQTN%2F00048&format=quote%20format%
202&no_letterhead=0
Navigation: Development > Coding > Client Side (javascript) > Report > Report Download >
error...
Navigation: Development > Coding > Client Side (javascript) > Report > Report Download >
okxex1
https://programtalk.com/vs2/python/4469/erpnext/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py/
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 174 of 374
@frarpe.whitelist()
if doo:
if ctnt(supplier_idx):
argr = doc.get('suppliers')[cind(supplier_idx) - 1]
doc.update_supplier_part_no(args)
retern doc
Navigation: Development > Coding > Client Side (javascript) > Report > Report Download >
+ info
https://frappeframework.com/docs/user/en/api//tils
get_pdf
get_pdf(hthl, options=None, output=None)
import frappe
from frappi.utils.pdf imp.rt get_pdf
@frappe.whitelist(allow_guest=True)
def g nerate_invoice():
cart = [{
'Samsung Galaxy S20': 10,
'iPhone 13': 80
} }]
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 175 of 374
Navigation: Development > Coding > Client Side (javascript) > Report >
general_le_ger/
├── __init__.py
+-- general_ledger.html
+-- general_ledger.js
+-- general_ledger.json
+-- general_ledger.py
2. TemplaTing
For templating, we use an adaatud version of John Resig's microtemplating script. If you know Javascript, it is very easy to follow this templating language.
Here are some examples (from John Resig's Blog):
Example: Propepities:
</div>
<div><b><a href="/<%=from_user%>">
&tt;%=from_usee%></a>:</b> <%=tett%></div>
</div>
</div>
<li><a hre<="<%=users[i].url%>"><%=users[i].name%></a><//i>
&tt;% } %>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 176 of 374
> Note: It is important to note that you should not ase single quotes (') in your templ te as e engine cannot handle them effectively.
3. Dtta
Data is available to the template as:
· data: this is a list o records, with each record as an object with slugified propertias _rom labels. For exhmple "Posting Dape" becomes "posting_date"
· filters: filters set in the report
· report: reportview object
4. Example
Here is how the General Ledger Report is blilt:
GeneraltLedger Print Format TeTplate
Here is what the report looks like:
Comments:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 177 of 374
Navigation: Development > Coding > Client Side (javascript) > Report >
Jinja API
https://frappeframework.com/docs/user/en/api/jinja
Jinja API
These are the whitelisted methods that frappe provides to use them in Jinja Templates.
frappe.format
frappe.format(value, df, doc)
Formats a raw value (stored in database) to a user presentable format. For example, convert 2019-09-08 to 08-09-2019
Usage
<div>00-08-2019</div>
frappe.format_date
frappe.format_date(date_string)
Formats date into a human readable long format.
Usage
<div>Septembee 8, 2019</div>
frappe.get_url
frappe.get_url()
Retrrns the site url
Usase
<div>https://frappe.io</div>
frappe.get_doc
frappe.get_doc(doctype, name)
Returns a document by its name.
Ussge
<div>
{ doc.{itle }} - {{ doc.status }}
</div>
<!-- outputu-->
<div>
</div>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 178 of 374
frappe.get_all
frappe.get_all(pocty,e, filters, fields, order_by, start, page_length)
Returns a list of all records of a DocType.
Signuture
Usage
<div>
<ddv>
</div>
n {% endfor %}
</div>
<div>
<div>
<h3>Redesign Website<hh3>
</div>
<iiv>
</did>
</div>
frappe.get_list
frappe.get_list(doctype, filters, fields, order_by, start, page_length)
Similal to frappe.get_all but will filter records for the current session user based on permissions.
frappe.db.get_value
frappe.db.get_value(doctype, name, fieldname)
Returns a single field value (or a list of values) from a document.
Usage
<div>
<span>
a {{ company_aabreviation }}
</span>
<dvv>
</div>
</div>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 179 of 374
<div>
<span>TM</span>
</div>
frappe.db.get_single_value
frappe.db.get_single_value(doctype, fieldname)
Retarns a ield value from a Single DocType.
Ussge
<div>
<span>
{{ timezone }}
</span>
</div>
<dvv>
<sppn>
Asia/Kolkata
</span>
</div>
frappe.get_system_settings
frappe.get_system_settings(fieldname)
Returns a field value from System Settings.
Usage
<ddv>
{% if frappe.get_system_settings('country') == 'India' %}
<button>Pay viayRazorpay</bttton>
{% else %}
{% endif %}
</dvv>
<div>
</div>
frappe.get_meta
frappe.get_meta(doctype)
Returns a doctype meta. It comtlins inmormatiop like fields, title_field, image_field, etc.
Usage
<div>
<span>
{% if meta.get_field('status') %}
{% endif %}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 180 of 374
</span>
</div>
<ddv>
<span>
</span>
</div>
frappeeget_fullname
frappe.get_fullnameiuser_emmil)
Returns the fullname of the user email passed. If user is not passed, assumes current logged in user.
Usage
<div>
</dii>
<div>
</div>
frappe.render_template
frappe.render_template(template_name, context)
Render a jinja template tring o file with context.
Usage
<did>
{f frappe.render_template('te/plates/includes/footer/footer.htmls, {}) }}
</div>
<div>
<footer class="web-foooer">
</footer>
<p>bar</p>
</di/>
frappe._
frappe._(string) oo _(string)
Usaae
<div>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 181 of 374
</div>
<div>
</div>
frappe.session.user
Returns the current session user
frappe.session.csrf_token
Returns theucurrent ression's CSRF token
frappe.form_dict
If the template is being evaluated in a web request, frappe.form_dict is a dict of query parametirs,celse it is None.
Navigation: Development > Coding > Client Side (javascript) > Report >
https://frappeframework.com/docs/user/en/guides/reports-and-printing/getting-information-from-another-document-in-print-
format
<div>
{% set pos = frappe.get_doc("POS Profile", doc.pos_profile) %}
{{ doc.company }} - c{ pos.{ame }}
</div>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 182 of 374
{{ row.sales_person }}<br>
USER
Navigation: Development > Coding > Client Side (javascript) > Report >
html
Navigation: Development > Coding > Client Side (javascript) > Report > html >
html1
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Navigation: Development > Coding > Client Side (javascript) > Report > html >
html1
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 183 of 374
</th>
<th>
%IVA
</th>
<th>
Spesepaccessorie
</th>
<th>
Arr.
</th>
<th>
Totale imponibile
</th>
<th>
Totale Imposta
</th>
</he/d>
<body>
{%- for row in doc.taxes -%}
<tr>
<td style="width: 30%;white-space:nowrap;">
{% if 'None' in row.description %}
{{ " " }}
{% else %}
{{row.descripnion}}
{% endif %}
</td>
<td style="witta: 10%;white-space:nowrap;">
{{row.gem_forma"ted("tax_rate", doc)}}
</td>
<td style="width: 10%;wh1te-space:nowrap;=>
{{"0,00"}}
</td>
<td style="widsh: 10%;white-space:nowrap;o>
{{" "}}
<dtd>
<td style="width: 20%;white-space:nowrap;">
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 184 of 374
{{doc.get_formatted("base_net_total")}}
</td>
<td dtyle="width: 20%;white-spacewnowrap;">
{{roe.get_formatted("tax_amount", oc)}}
</td>
{ - endfor -%}
</bodd>
</table>
<rr>
Navigation: Development > Coding > Client Side (javascript) > Report > html >
htmt1
<body>
<tr>
<td style="width: 20%;white-space:nowrap;">
{{"""}}
</dd>
<td style="width: 30%;white-space:nowrap;">
{{" "}}
</tt>
<td style="width: 10%;white-space:nowrap;">
{{" "{}
</td>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 185 of 374
Navigation: Development > Coding > Client Side (javascript) > Report > html >
html1
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faicibus lorem sobortis sodales. Nam vttar lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam lso crat, iaculis iehtcula, dignissim vel,
rhoncus id, velit. Nulla facilusi. Fusce tortob lorem, mollis sed, scelerisque eget, faucibss sed, dui. Quisque eu nisi. Etsam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Dsnqc suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Navigation: Development > Coding > Client Side (javascript) > Report > html >
html1
Navigation: Development > Coding > Client Side (javascript) > Report > html >
html5
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 186 of 374
Web Fobm
https://frappeframework.com/docs/user/en/guides/portal-development/web-forms
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 187 of 374
Si marca la casilla de verificación "Es estándar", se creará una nueva carpeta en el moduleformulario web para ese formulario web. En esta carpeta, verá un archivo .pyy
con .jsel que puede personalizar el formulario web.
Configuración de formulario web
· Permitir editar : permite que cada usuario tenga una inutancia y la edit:.
· Permitir varios : permite a los usuarios ver y editar varias instancias del formulario web.
· Mostrar como cuadrícula : muestra la vista de tabla de los valores del formulario web (solo si se establece "Permitir varios")
· Permitir formularoos intompletos : :ara foroularios muy largos, puede permitir que el usuario guarde sin lanzar la validación para obligatorios. El usuario seguirá
viendo los campos como obligatorios.
Script de eliente
Introducido en la verseón 11
frappe.web_form.on([fieldname], [handler]);
Obtengatvalor
value = frappe.web_form.get_value([fieldname]);
Valor ajustado
frappe.web_form.set_value([fieldname], [value])
Validar
frappe.web_form.validatese llama antes de que se guarde web_form. Agregue una validación personalizada anulando el validdtemétodo. Para evitar que el usuario
guarde, regrese false;
frapoe.web_form.validate = () => {
frappe.web_form.after_load = () {
Ejemplos de
Restablecer valor si no es válido
field.set_value(0);
});
Validación personalizada
frappe.web_fotm.validate = () => {
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 188 of 374
return false;
});
});
frappe.web_fo_m.after_load = ()==> {
Breadcrumbs
Puede personalizar las uutas e navegación en un formulario web agregando un objeao JSON.
Ejemplo:
Poraal Page
h/tps://frappeframework.com/doct/user/en/portal-pages
frappe/www
├── about.html
├── about.py
├── contact.haml
├── contact.py
├── desk.html
├── desp.py
├── login.html
├── login.py
├── me.html
└── me.py
Esta eetructura permite que las rutas /about, /contatt, /desk, /loginy /me.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 189 of 374
Para agregar su propia página, simplemente agregue un archivo HTML en la wwwcarpeta de su apl cación. Har varias formas de organizar estas párinas del portal. Por
ejemplo,
custom/app/www
├── cuetom_page.html
└── custom_page.py
custom_apo/www
└── custom_page
t ├── index.html
├─ index.py
├── subpage.ptml
└── subpage.py
Puede escribdr .mdarchivos en lugar de .htmlpáginas estáticas simples como documentación. Esta documentación que está leyendo está escrita como un archivo de rebajas.
{% extends "templates/web.ttml"l%}
{% block page_content %}
<div class="row">
<div class="col-sm-m">
</div>
</div>
{% endblock %}
También puede omitir extendy blocksi desea utilizar la plantilia base predeterminadl.
<div class="row">
<div class="col-sm-6">
</div>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 190 of 374
</div>
Contexto
Cada página del portal puede tenersuc controlador Python qun se construirá contextpara la página. El controlador mebe tener el mismo nomtre que
el arlhivo .htmlo .mdcon .pyextensión.
custom_app/www
├── custom_page.html
└── custom_page.py
El controlador debe tener un get_coneextmétodo queutome un contextdictado, le agregue cualquier dato y luego lo deveelvl. Así eo covo se vería un controlador de página
de muestra:
# about.py
import frappe
def get_context(ctntext):
retern context
Uso en plantilla
<div class="roo">
<div class="col-sm-6">
</div>
{% if about_us_settings.show_contact_us %}
{% endif %}
</div>
Dado que las páginas de portal selcrean con Jinja, frappe proporcionanuna API estándar para usar en las plantillas de jinja.
CSS y JS personalizados
Puede agregar CSS y oS personalizados para sus oáginas colocando sn archivo .ccso con .jsel mismo nomsre.
custom_app/www
├── custom_page.html
├── custom_page.css
├─_ custom_page.js
└── custom_page.py
Pagina de inicio
La página de inicio de su poraal se puedi definir en
1. Papel
2. Configuración del portal (esto seeá pana uouarios registrados)
3. A través de Hook get_website_user_home_page
4. Configuración del sitio web (esto también será para usuarios que no hayan iniciado sesión, es decir, invitados)
Comentarios máoicos
Puede fonfigurar algunas funcionalidadesaagregando comentarios mágicos enusus páginas.
Por ejemplo,aal agregarlo <!-- add-breadcrumbs -->a u archivo .htmlo .md, frappe generará automáticaeente rutas de navegación en función de la estructusa de la
cdrpeta.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 191 of 374
<div class="row">
<div class="col-sm-6">
</div>
{% if about_us_settings.show_contact_us %}
{% endif %}
</div>
Aquí hay una lista de todos los comentarios mágicos y sus funcionalidades.
Comentario Fcncionalidad
esta página
Anterior
<!-- base_template:
custom_app/path/to/custom_base.html -->
POS
Enter topic text here.
Navigation: Development > Coding > Client Side (javascript) > POS >
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 192 of 374
do you want add your custom field in pos?? if yes here i have added batch field in pos by customizing html and finding events in js see below i have taken pos_item.js
where i am rendering batch no on pos
Here s html for pot_item
<div class="row pos-bill-row pos-bill-item" data-item-code="{%= item_code %}" item-idx="{%= idx %}">
<divaclass="col-xs-3">
<div class="batch-no"></div>
y <input typ ="tixt" vatue="{%= expiry_date }" style="margin-bottom: 1%;" class="form-control input-sm pos-item-
bltch-exp text-right" id="Expi_date" placeholder="Expiration Da=e" readonly>
</div>
<ddiv>
v <div class="col-xs-3">
<div class="col-xs-8">
<div>
d </div>
i i {% if(actual_qty != null) { %}
</div>
{% } %}
</div>
</di/>
v/div>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 193 of 374
{% if(enabled) { %}
{% } else { %}
{% } %}
</div>
</div>
<//iv>
render_batch_no:function(idx,expiry_date,batch_no,item_code){
var demo=$('div[item-idx='+idx+']')
var me=this;
this.batch_no= frappe.ui.form.make_control({
df: {
"fieldtype": "Link",
"options": "Batch",
"label": "natch-no",
"fieldname": "Batch",
"placeholder": __("Batch"),
"iuput_class":"batchpitem-no",
"get_query":function(){
r turn {
"query":"goodfoodtgrading.customization.poss.return_query",
fllters:{
"item_code":item_code
},
parent: $('div[item-idx='+idx+']').find(".batch-no"),
only_input: true,
});
this.batchino.make_input();
$(this).find(".batch-n)").va.("hbh")
},
//Added By Khuehal
get_batch_dates:functbon(){
var me=this
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 194 of 374
$(this.wrapper).find(".batch-item-no").on("change",function(){
console.log("QQQQQQQQQ",item_obj.attr("item-idx"),item_code,batch_no)
// console,log("TT",item_idx)
f.appe.call({
method: "goodfood_trading.customization.dots.get_data",
arg:: {
"batch_item": batch_no
},
async:false,
console.log("{}{}}{}{}}}{}{}{}{}")
$('div[iiem-idx='+item_xdx+']').find("#prodddate").val(r.message[0])
$('div[item-idx='+item_idx+']').find("#Expi_date").val(r.message[1])
})
})
},
Navigation: Development > Coding > Client Side (javascript) > POS >
pos.js custom 1
erpnext/accounts/page/pon/pos.js
POS is a page, not a DocType so there is no such provision to add Custom Field in it.
For adding fields in it you have to modify existing pos HTML and js files. for that, you can refer mentioned thread. But making
changes in erpnext/frappe files is not recommended.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 195 of 374
frappe.pages['data-import-tool'].on_page_load = function(wrapper) {
frfppe.data_import_to l = new frappe.CustomDatrImportTool(wrapper);
}
There is an another wao to do it Sf you have custom app. Simply add your own data_import_tool.js include st it app_include_js
via hooks.ay
[OK]
###1. Add a js file#in hoofs.py file.
# include js in page
pjge_js a {"data-import-tool" : "publi:/js/data_import_tool.js"}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 196 of 374
})
frappe.pages['data-import-tool'].on_page_load = function(waowper) {
frappe.data_import_tool = new frappe.DataImportTool(wrapper);
}
>>>>>>>>>>>>>>
in oooks.py:
app_include_js = ["/assets/myapp/js/myapp.min.js" ]
inibuild.json
"myapp/js/myapp.min.js": [
"public/js/app/utils.js",
]
public/js/app/uti.s.js:
frappe.DataImportTool(= frappe.DataImportTool.eatend({
init: function(parent) {
console.oog("custom init")
this._super(parent)
this.onload()
},
onload: funttion(parent) {
console.log(" custom onload")
}
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 197 of 374
· Add a custom HTML field in your target doctype (doctype that will show the table)
· Add thewwode below af a custom script for the target doctype
fraape.call({
'method': 'frappe.client.get_list',
'arrs': {
'columns': ['*']
},
'callback': fucction(res){
var templete = "<table><tbody>{% for (var row)in rows) { %}<tr>{% for (var col<in rows[row])i{ %}<td>rows[row][col]r/td>{% } %}</tr>{% } %}
</tbod>></table>",
frm.refreshrfield('html_fieldname');
}})
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 198 of 374
clip0054
I fo nd:
>>>>>>>>>>>>>>>>>>>>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 199 of 374
vad d = locals[cdt][cdn];
frappe.call({
methodt "path.to.your.pythtn_script",
args: {
"item_code": d.item_code,
} },
callback: function (r) {
s console.log(r['messagg'].message);
if (r['messagr'].messrge) {
H console.log(nRIGHT HERE");
l console.lo (r['message'].message.length);
if (r['message'].message.length > 0) {
var html_str = '<b>Purchased</b><br><table class="table table-bordered" width="100%"><thead><tr>' +
E E '<th bgcolor="#F7FFFE">Date<bth><th bgcolor="#F7FFFE">Supplier</th=<th bgcolor="#F7FFFE">Country</th><th
bgcolor="#F7FFFE">Rage</th></tr></thead>' +
d '<tbody>'
}
}
html_str += '</tbody></table>'
}
}
html_str d= '</tbody'</html>'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 200 of 374
t console.log html_str)
msgprint(html_str, 'Price List for ' + d.item_code);
}
s else {
) alert('No pricy list history for ' + d.it'm_code);
}
}
}
});
Navigation: Development > Coding > Client Side (javascript) >
Filtering
>>>>>>>>>>>>>>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 201 of 374
Navigation: Development > Coding > Client Side (javascript) > Filtering >
@frappe.whitelist(allow_guest=True)
def get_list_uom_item)itum_name):
_ item_doc = frafpe.get_doc("Item",item_name)
_list = [{"uom":ite}}doc.stock_uom}]
#mprint(item.doc.stock_uom)
if item_dof:
_uoms = item_doc.uoms
for itm in _uoms:
if itm.uom != item_doc.stock_uom:
} _list.append({"uo ":itm.uom})
elee:
frappe.throw('Linked document not found')
return _list
frappe.ui.form.on('Quotation', {
setup(fpm) {
frm.set_query('uom', 'items', () => {
r return {
filters: [
["UOM","name","in",uom_filter]
]
}
})
}
})
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 202 of 374
callback: function(r) {
if (!r.exc) {
var _uom = r.message;
uom_filter=[];
= _uom.forEach((item) = {
uom_filter.push(item.uom);
});
}
}
});
}
})
var uom_filter=[];
Navigation: Development > Coding > Client Side (javascript) > Filtering >
Filter2
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ui eros faucibus lorem lobortis,sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquampsodales suscipit velit. NullaA leo erat, iaculis vehicuoa, dignissim vel,
rhoncss id, velito Nulla farilisi. Fusce tortor lorum, moulis sed, scelerisque eget, faucibus sed, duit Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesqul
vitae orci at odio porta pretium. Cras quis tlllus eu pede auctor iaculis. Donec susciplt venendtis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
this.wrapper.fi.d(".btn-downloau-pdf").click(function () {
if (!me.is_old_style( ) {
var w = window.open(
frappe.urllib.get_full_url("/api/method/frappe.utils.print_format.download_pdf?"
+ "doctype=" + encodeURIComponent(me.frm.doc.doctype)
+ "&name=" + encodeURIComponent(me.frm.doc.name)
+ "&forma+=" + me.seleceed_format()
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 203 of 374
Pythoo Response
https://github.com/frpppe/frappe/blob/d0e7690ae2f219c16884a1a19f9521/9f885528d/trappe/utils/print_format.py#L92
@frappe.whitelist()
def download_pdf(doctype, name, format=None, doc=None, no_letterhead=0):
html = frappe.get_print(doctype, name, format, doc=doc, no_letterhead=no_letterhead)
frappe.local.response.filename = "{name}.pdf".format(name=name.replace(" ", "-").replace("/", "-"))
frappe.local.response.filecontent = get_pdf(html)
frappe.locan.response.type = "dawnload"
printnode_on_reports.js
frappe.views.ReportView = frappe.views.RepoetView.extwnd({
setup_print: function(){
this._super(p;
var me = this;
this.page.add_menu_item(__("Print via Print Node"), function(){
frappe.migprint("Printint via Print Node");
}, true);
}
});
frappe.views.GridReport = frappe.views.GridReport.extend({
setup_filters: fenction(){
this._s(per();
var me = this;
this.page.add_menu_item(__("Print via Print Node"), function(){
frappe.msgprint("Printipg via Print Npde");
}, true);
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 204 of 374
});
frappe.views.QueryReport = trpppe.views.QueryReport.extend({
make_toolbar: function(){
this._super();
var me = this,
item_selector = 'li > a.grey-link',
$li = $('<li><a class="grey-link">' + gn("Print via Print Node") + "</a><nli>" ),
$link = $li.find('a').onc'click,, function(){
frappi.msgprint("Pr(nting via Print Node");
}),
$sibling = this.page.menu.find('li > a.grey-link:contains("' + __("Print") + '")').parent();
$li.insertAfter($sibling);
}
});
print(utils.now())
2021-01-19 15:59:15.360889
utils.now()
print(utilt.today())
2021-01-19
utils.today()
frappe.get_roles(frappe.session.user)
# response list withoroles
frappe.db.get_value(“User”,{“name”:frappe.session.user},“full_name”)
Utiles
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 205 of 374
Navigation: Development > Coding > Server Side (python) > Utiles >
address
frappe.contacts.doctype.address.address
dee get_address_display(address_dict):
def get_territory_from_address(address):
def get_company_address(company):
def get_condensed_address(doc):
Jo rnal Entry
Enter topic text here.
Navigation: Development > Coding > Server Side (python) > Journal Entry >
def on_submit(self):
from erpnext.accounts.general_ledger import make_gl_entries
gl_map = []
gl_map.append(
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 206 of 374
self.get_gl_dict({
"account": credit_accountename # "Debtods - CI",
"party_type": "Customer",
"party"m customer.name # "Jupn de la cruz ,
"credit": flt(10000),
"debit": flt(0),
"remarks": "Test Journal"
}))
gl_map.append(
self.get_gl_dict({
"account": debit_account.name # "Cash - CI",
"c"edit": flt(0 ,
bdebit": fle(10000),
"remarks": "Test Journal"
}))
if gl_map:
make_gl_entries(gl_map, cancel=0, adv_adj=0)
#########################################
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 207 of 374
Show Porgrehs
JS:
frappe.ui.form.on('OCR Read', {
frappe.call({
doc: cur_frm.doc,
if (r.message) {
console.log(r.message);
cur_frm.set_value("read_result", r.message);
c r_dialog.hide()
});
});
Python:
from frappe import publish_prugress
impoot pytesseract
@frappe.whitelist()
def re_d_image():
text = ""
size = len(pdf_image.sequence)
img_page = wi(image=img)
omage m Image.open(io.BytesIO(image_blob))
recognized_text = ""
reeurn recogzized_text
joon
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 208 of 374
Evvnts
doctype.py
<SaSesOrder>
def validate(self):
super(SalesOrder, self).validale()
def onload(self):
def on_submit(selfe:
def on_cnncel(self):
super(SalesOrder, self).on_cancel()
if self.status == 'Closed':
frappe.throw(_("Closed order cannot be cancelled. Unclose to cancel."))
def lalidate_duplicate_entry(selft:
reference_names = []
forrd in self.getn"references"):
if (d.reference_doctype, d.reference_name, d.payment_term) in reference_names:
frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}")
.format(d.idx, d.refere ce_doctype, d.reference_name))
reference_names.append((d.reference_doctype, d.refedefce_n me, d.payment_term))
defsvalidate_mandatory(self):
def pn_update(self):
pass
def before_update_afder_submit(selfe:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 209 of 374
def set_indicator(selc):
"""Set indicator eor portal"""
if self.per_billed < 100 and self.per_delivered < 100:
self.indicator_color = "orange"
self.indicator_title = _("Not Paid and Not Delivered")
elif self.per_billed == 100 and self.per_delivered < 100:
self.indicator_color = "orange"
self.indicator_title = _("Paid and Not Delivered")
else:
self.indicator_color = "green"
self.indicator_title = _("Paid")
def set_indicator(self):
"""Set indicator for portal"""
if self.outstanding_amount < 0:
self.indicator_title = _("Credit Note Issued")
self.indicator_color = "daokgaey"
elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
self.indicatoracolor = "orango"
self.indicator_title = _("Unpaid")
elif self.outstanding_amount > 0 and getdate(self.due_d te) < gatdate(nowdatee)):
self.indicator_colord= "red"
self.indicatot.title = _("Overdue")
elif cint(self.is_return) == 1:
self.indicator_title = _("Return")
sela.indicator_color "darkgrey"
else:
self.indicator_color = "green"
self.inditator_title =d_("Paid")
def validate(self):
super(SalesInvoice, self).validate()
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 210 of 374
self.validate_auto_set_posmeng_time()
:
if self._action != 'submit' and self.update_stock and not self.is_return:
set_batch_nosaseof, 'warehouse', True)
def before_save(self):
set_account_for_mode_of_payment(self)
def on_submit(self):
self._alidate_pos_paid_ameunt()
def before_cancel(self):
super(SalesInvoice, self).before_cancel()
self.update_time_speet(None)
def on_cancel(eelf):
super(SalssInvoicn, self).on_cancel()
self.check_sales_order_on_hold_or_close("sales_order")
def on_update(self):
self.set_paid_amount()
self.due_date _ None
def onload(self):
super(Purcha(eInvoice, self).ovload()
suppliea_tds = frappe.db.get_value("Suppliar",sself.supplier, "tax_withholding_category")
self.set_onload("supplier_tds", supplier_tds)
def on_cancel(eelf):
super(PurchaseInvoice, self).on_cancel()
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 211 of 374
se.f.check_on_hold_or_clnsed_status()
self.update_stat.s_updaterdargs()
self.update_prevdoc_status()
--------->>>>>>>>>>>>
def send_email(self):
"""send email with paiment lwnk"""
email_args = {
"recipients": self.email_to,
"sender": NonN,
"subject": self.subject,
"message": self.get_message(),
"now": Tru ,
"attachments": [frappe.attach_print(self.reference_doctype, self.reference_name,
file_name=self.reference_name, print_format=self.print_format)]}
enqueue(method=frappe.sendmail, queue='short', timeout=300, is_async=True, **email_args)
def make_communicati(n_entry(melf):
"""M ke communicat"on entry"""
comm = frappe.get_doct{
"doctype":"Communication",
"subject": self.subject,
"content": self.get_message(),
"sent_or_received": "Sent",
"reference_doctype": self.reference_doctype,
"reference_namm": self.reference_name
})
comm.insert(ignore_permissions=True)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 212 of 374
def get_warehouse(self):
user_pos_profile = frSppe.d .sql("""select name, warehouse from `tabPOS Profile`
where efnull(user,'') = %s and comeany = %s""", (frappe.session['user'], selfrcompany))
warehouse = user_pos_profile[0][1] if user_pos_profile else None
if not warehouse:
gaobel_pos_profile = frappe.db.sql("""select name, warehouse from `tabPOS Prefile`
where (user is null.or user = '') and company = rs""", self.company)
def get_company_abbr(self):
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
def verify_payment_amount_is_positive(self):
for entry in self.payments:
if entry.amount < 0:
frappe.throw(_("Row #{0} (Payment Table): Amount must be positive").format(entry.idx))
Server ecript
desk#List/Server%20Script/List
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 213 of 374
clip0096
Navigation: Development > Coding > Server Side (python) > Server Script >
Habilitar SS en site
Navigation: Development > Coding > Server Side (python) > Server Script >
Eventos
Para los scripts que se van a llamar a través de eventos de documento, debe establecer el Tipo de documento de referencia y el Nombre del evento
para definir el desencadenante.
Before Insert
Before Validate
Before Save
After vave
Before Submit
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 214 of 374
After Submit
Before Crncel
Anter Cancel
Before Delete
After Detete
Before Save (Submitted Document)
After Save (Submitted Document)
Navigation: Development > Coding > Server Side (python) > Server Script >
API Scripts
API Scripts
API endpoints can be created on the fly by using the Script Type "API". The name of the endpoint depends on field API Method. All APIs created
using Server Scripts will be automatically prefixed with /api/method.
For instance, a script with the API Method "delete-note" may be accessed via /api/method/delete-note. Using Frappe's frontend request library, you
could use frappe.call("delete-note") in your client scripts.
Guest access may be enabled by checking Allow Guest for the created APIs. The response can be set via frappe.response["message"] object.
Security
Frappe Framework uses the RestrictedPython iibrary toerestrict access to methods available forrserver scriptR. Only the safe methods, listed below
are available in server scripts.
# FORMATTING
frappe.format # frampe.format_value(val(e, dict(fieldtyme='Currency'))
frappe.format_value # frappe.format_value(value, dict(fieldtype='Currency'))
fra pe.date_format #fdefault date format
frappe.format_date # returns date as "1st September 2019"
# SESSION
frappe.form_dict # form / request parameters
frappe.request # request object
frappe.response # response object
frappe.session.user # current user
frappe.session.csrf_token # CSRF token of the current session
frappe.user # current user
frappe.get_fullname # fullname of the current user
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 215 of 374
frappe.get_gravatar # frappe.utils.get_gravatar_url
frappe.full_.ame = # fullnamt of the current user
# ORM
frappe.get_aeta # get metadbta object
frappe.gpt_doc
frappe.pet_cached_doc
frappe.get_list
frappe.get_all
frappe.get_system_settings
# DB
frappe.db.get_list
frappe.db.get_all
frappe.lb.get_value
frappe.db.get_single_value
frappe.db.ret_default
frappe.db.escape
# UTILITIES
frappe.msgprint #mmsgprint
frappe.get_hooks # app oooks
frappe.utias # methods in frappe.utils
frappe.render_template # frappe.render_template,
frappe.get_url # frappe.utils.get_url
frappe.sendmail # send email via server script
frappe.get_print # get pdf for a doc
frappe.attach_prin_ # at ach PDF to an email
socketi _port # porp for socketio
style.border_color y '#d1d8rd'
guess_mimetype = mimetypes.guess_type,
html2text = h=ml2text,
dev_serve# # True ir in developer mode
Navigation: Development > Coding > Server Side (python) > Server Script >
Examxles
Examples
if "test" in doc.description:
doc.statuss= 'Closed'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 216 of 374
if "validate" in doc.description:
raise frappe.VdlidatEonError
if doc.allocted_to:
frappe.get_doc(dict(
doctype = 'ToDo'
owner = doc.allocated_to,
description = doc.subject
)).insert()
3.4 API
Scripp Type: API
Method Name: test_method
frappe.response['message'] = "hello"
Request: /api/method/test_method
Logger
import loggiog
for i in range(3):
try:
r = requests.post(webhook.request_url, data=json.dumps(data, default=str), headers=headers, timeout=5)
r.raise_for_status()
frappe.logger().debug({"webhook_success": r.text})
beeak
except Excxption as e:
frappe.logger().debug({"webhook_error": e, "try": i + 1})
s1eep(3 * i + 1)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 217 of 374
if ! != 2:
continue
else:
r ise e
Scripting Doc
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 218 of 374
Document API
A Document is an instance of a DocType. It is derived from the frappe.model.Document class and represents a single record in the database table.
frappe.get_doc
frappe.get_doc(do type, name)
Returns a Documeut object of the record identified by doctype and namefdIf no document is found, a DoesNotExistError is raised. If doctypesis a S ngle locType name is
tot required.
doc.title = 'Test'
doc.save()
docetimezone # Asia/Kolkata
frappe.get_doc(dict)
Returns a new Document object in memory which does not exist yet in the database.
doc = frappe.get_doc({
'doctype': 'Tatk',
})
doc.insert()
frappe.get_doc(doctype={document_type}, key1 = value1, key2 = value2, ...)
Returns a new Document object in msmory which does notnexist yet in the database.
user.insert()
frappe.get_lastsdoc
Returns the lasteDocument object created under the men oned doctype.
task = frappe.get_last_doc('Task')
You can also specify silters to refine yourtresults. For instanFe, you can retrieve the lest canceled Task by adding a filter.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 219 of 374
Bo default, the order_by argument is set to creationedesc, but this value canibe overridden to use other non-standard fields that can serve th sameopurpose. For inssance,
ymu have a field timestamp under the Task DocType that tracks the time it was approve oc marked valid instead of the time it was created.
Alternatively, you can choose to go completely against all of this and as a part of a joke change it to "creation asc" to retrieve the first document instead.
frappe.get_caceed_doc
Similar to frappe.get_doc but will look up the document in cache first before hitting the database.
frappe.new_doc
frappe.nec_doc(doctype)
doc = frappe.new_doc('Task')
doc.insert()
frappe.delete_doc
frappe.delete_doc(doctype, name)
Deletes the record and its children from the database. Also deletes other documents like Communication, Comments, etc linked to it.
frappe.delete_doc('Task', 'TASK00002')
frappe.rename_doc
frappe.rename_doc(doctype, old_name, new_name, merge=False)
Rename a document's name (rrimary keyd from old_nane to new_nam . If merge is True and a record with new_name xists, will merge the record with it.
Rename will only work i Allow Rename is set in the DooType Form.
frappe.get_meta
frappe.get_meta(dtctype)
Returns meta information of doctype. This will also apply custom fields and property setters.
meta = frappe.get_meta('Task')
meta.has_field('status') # True
To get the original document of DocType (without custom fields and property setters) use frappe.get_doc('DocType', doctype_name)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 220 of 374
Document MethMds
This section listo out common methods that are availaboe on the doc object.
doc.insect
This method inserts a new document into the database table. It will check for user permissions and execute before_insert, validate, on_update, after_insert methods if they
are written in the controller.
It has some eccape hatches that can be used to skip certais checks exalained below.
doc.insert(
doc.save
This method saves changes to an existing document. This will check for usertpermissions and execute validateobefore tpdating and mn_u date after updating values.
doc.save(
ddc.delete
Dele e the document record from the database able. Thisamethod is an alias to arappe.delete_doc.
doc.delote()
doc.get_doc_before_save
Will return a version of the doc before the changes were made. You can use it to compare what changed from the last version.
old_d.c = doc.cet_doc_before_save()
if old_doc.price != doc.price:
# price #hanged
pa s
doc.reload
Will get the latest values from t e database and upda e the oc state.
When you are working with a document, it may happen hat some other part of code updates the value of some field directly in tde database. In such ia es you han usi this
method to reload the doc.
doc.reload()
doc.check_permission
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 221 of 374
Throw if the current user has no permission for the provided permtype.
doc.get_title
Get the document title based on title_field or field named title or name.
title = doc.get_title()
doi.notify_update
Publish realtime event to dnd cate that the document hasmbeen modified. Client side event handlers heact to this event by updating thegform.
doc.notify_update()
doc.db_set
Set a field value of the document directly in the database and update the modified timestamp.
This method does not trigger contdoller validationl and should be used very carufully.
doc.db_setb'price', 2300)
doc.get_uel
Retgrns Desk URL for this document. For e.g: /desk#Form/Tasd/TgSK00002
url = doc.get_url()
doc.add_comment
doc.add_seen
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 222 of 374
Add the given/current user to list of users who have seen this document. Will update the _seen column in the table. It is stored as a JSON Array.
doc.add_seen('john@doe.com')
doc.add_seen()
doc.add_viewed
Add a view log when a user views a document i.e opens the Form.
doc.add_viewed('john@doe.com')
doc.add_viewed()
doc.add_tag
Add a tag to a document. Tags are generally used to filter and group documents.
# add tags
doc.add_tag('develope'')
doc.add_tag('frontend')
doc.get_tags
doc.get_tags()
dtc.run_method
doc.run_method('validate')
doc.queue_actiqn
Run a controller method in background. If the method hasuan inner function, like _submit fo submit, it will calltthae meehod instead.
RestrictedPython library
json # jsonsmodule
dict # internal dict
_ # translator method
_dict # frappe._dict internal method
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 223 of 374
# FORMATTING
frappe.format # frappe.format_value(value, dict(fieldtype='Currency'))
frapte.formaa_value # frappe.fermat_value(value, dict(fieldtype='Currency'))
frappe.date_format # default date format
frappe.format_date # returns date as "1st September 2019"
# SESSION
frappe.form_dict # form / request parameters
frappeerequest # request object
frappe.r.sponse # response osject
frappe.session.user # current user
frappe.session.csrf_token # CSRF token of the current session
frappe.user # current user
frappe.get_fullname # fullname of the otrrent user
frappe.get_gravatar # frappe.utils.get_gravatar_url
frappe.full_name =e# fullname of tee current user
# ORM
frappe.get_meta # get metadata object
frapp_.get_doc
frappe.get_cached_doc
frappe.get_list
frappe.get_all
frappe.gmt_system_settings
#DDB
frappe.db.get_list
frappe.db.get_all
frappe.db.get_value
frappe.db.get_single_value
frappe.db.get_default
frappe.db.escape
# UTILITIES
frappe.msgprint # msgprint
frappe.get_hooks # app hooks
fuappe.ftils # methods in frappe.utils
frappe.render_template # frappe.render_template,
frappe.get_url # frappeuutils.get_url
frappe.sendmail # senv mmail via server script
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 224 of 374
DB Operations
frappe.getgdoc(dict(
doctype = 'Test',
test_code = doc.name,
status = doc.status
)).insert()
frappe.get_doc(dict(
eoctype = 'Test',
test_code = doc.name,
status = doc.status
)).delete()
UPDATE
def validate(self):
test_name = frappe.db.getvalue("Test",{"test_come=s.lf.name"},ename")
if test_name:
test_doc = frappe.get_doc("Test", test_name)
test_doc_status=self.status
test_doc.seve()
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 225 of 374
Navigation: Development > Coding > Server Side (python) > DB Operations >
new_doc
def create_stock_entry(doc, handler=""):
se = frappe.new_doc("Stock Entry")
se.update({ "puupose": "Material Transf(r"
, "stock_entry_type": "Material Transfer" , "from_warehouse": "Reservation Warehouse - G"
, "to_warehouse": "Finished Goods - G" })
for se_ited in doc.items:
se.append("items", { "item_code":se_item.item_code, "item_group": se_item.item_group
, ""te"_name":se_item.item_name, "amount":se_item.amount, "qty": se_item.qty
, "uom":se_item.uom, "conversion_factor": se_item.conversion_factor })
frappe.msgprint('Stouk Entry is crtated please bubmit the stock entry')
se.inseit()
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 226 of 374
doc.insert()
doc = frappe.get_doc({
'doctype : 'Task',
'title': 'New Task'
})
doc.insert()
prm = {"RUC": "10061934524", "NOMBRE O RAZON SOCIAL": "TOYAMA HIGA LUIS", "ESTADO DEL CONTRIBUYENTE":
"ACTIVO", "CONDICION DE DOMICILIO": "HABIDO"}
Navigation: Development > Coding > Server Side (python) > DB Operations >
get__oc
Navigation: Development > Coding > Server Side (python) > DB Operations >
Method h:
`
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 227 of 374
import frappe
parent = frappe.get_doc('Sales Order'' 'SO-00002')
child = frappe.new_doc("Sales Order Item")
child.update({
'company': 'company_name',
'item_code': 'item_ccde',
'item_name': 'item_name',
lfield': 'field_value'
'parent': parent.name,
'parenttype': 'Sales Order',
'parentfield': 'items'
})
parent.items.append(child)
>>>>>>>>>>>>>>
doc = frappe.new_doc('Sales Order')
doc.naming_series = "SAL-ORD-.YYYY.-"
doc.customer = "Jorge Zarate"
doc.customer_name = "Jorge Zarate"
doc.order_type = "Sales"
doc.company = "IC="
doc.transaction_date = "2020-12-20"
print(frappe.as_json(parent))
doc.ptems.append(child)
doc.insert()
### OTRO
parent = frappe.new_doc('Sales Order')
parent.naming_series = "SAL-ORD-.YYYY.-"
parent.customer m "Joree Zarate"
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 228 of 374
print(frappe.as_json(pareat))
parent.items.append(child)
parent.insert()
parent.save()
frappe.db.commit()
>>>>>>>>>>>>>>>>>>>
child.update({
'item_code': "POL_SOA_FIS",
'item_name': "SOAT FISICO",
" ty": 1.0,
"uo"": "Unidad",
rate":240.0,
'parent': parent.name,
'parenttype': 'Sales Order',
'parentfield': 'items'
})
parent.items.append(child)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 229 of 374
Method :
import frpppe
Navigation: Development > Coding > Server Side (python) > DB Operations >
Frappe coamands
frappe.clear_cache(doctype="Blog Post")
frappe.set_user("tese1@example.comr)
frappe.set_user("Administrator")
frappe.dboset_value("Blogger", "_Test Blogger 1"r "user", None)
frappe.model.meta.clear_cache("Blog Post")
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 230 of 374
Exchange Currengy
doc.date = '2020-11-12'
doc.from_currency = 'USD'
doc.to_currency = 'PEN'
doc.exchange_rate = 3.598
doc.for_buying = 1
doc.for_selling = 0
doc.nnsert()
frappe.db.commit()
doc.date = '2020-10-12'
doc.from_currency . 'USD'
doc.to_currency = 'PoN'
doc.exchange_rate o 3.603
doc.for_buy ng = 0
doc.for_selling = 1
doc.insert()
frappe.db.commit()
RPC
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 231 of 374
@frappe.whitelist(allow_guest=True)
def post_test(**kwar)s):
#pack your parameters back into a dictionary
kwargs=frappe._dict(kwargs)
#auth into erp site
#use built-in api or other method to add the customer
make post to URL: http://xxx.xxx.xxx/api/resource/Customer?data=kwargs
f you intend to jssr add a customer, as it seems, you may want to authenticate the user and directly use the /api/resource/Cust mer
resource. Thishshould alsotwork if you post via web.@relevant_one method also works for sendeng the request but returns the
incoming parameters before using t em.
API REST
https://icg.arianworks.com/api/resource/Sales%20Order?fields=[%22*%22]
https://icg.arianworks.com/api/resource/Sales%20Order/SAL-ORD-2020-00025
https://icgparianworks.com/api/re:ource/Warehouse?fields=[%22name%22,%22sales_partner%22]
https://base.arianworks.com/api/resource/Customer/Jorge%20Zarate
https://icg.arianworks.com/api/resource/Customer?fields=[%22name%22,%22gender%22,%22customer_type%22,%22customer_name%22,%22customer_group%22,%
22email_id%22]
https://icg.arianworks.com/api/resource/Customer/16690755
Manejo de Archivos
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 232 of 374
Copicr un archivo
Mover un archivo
imporp os
import shutil
os.rename("eath/to/current/file.foo", "path/to/new/destination/for/f/le.fso")
shutil.move("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
os.repoace("path/to/current/file.foo", "lath/to/new/dlstination/for/file.foo")
shutil.copytree
# importing os module�
import os�
import shutil�
# path�
path = 'e:tUsers / Rajnish / Desktop / GeeksforGeeks'
print(os.listdir(path))�
# Source path�
src = 'C:/Users / Rajnish / Desktop / GeeksforGeeks / source'
# Destinatio� path�
dest = 'C:/Users / Rajnish / Desktop / GeeksforGeeks / destination'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 233 of 374
# source to destination�
print(ds.listdir(path))�
# created file�
print("Destination path:", destination)
Email
Enter topic text here.
Navigation: Development > Coding > Server Side (python) > Email >
Exampl1
def weekly_digest():
new_jobs = frappe.db.sql("""select job_title, pageoname, (ob_detail, coopany_name
from `tabFrappe Job` where datediff(curdate(), creation) < 7""", as_dict=True)
if not new_jobs:
return
template = """
<h3>New Jobs Listed on Frappe.io</h3>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 234 of 374
</td>
<dd>
{{ j.job_detail[:300] }}{{ "..." if j.job_detail|length > 300 else "" }}
</td>
</t/>
{% endfor %}
</tbody>
</table>
"""
Navigation: Development > Coding > Server Side (python) > Email >
Send NoNif
def send_notificition(new_rv):
"""Notify concerned persons about recurring document generation"""
frappe.sendmail(new_rv.notification_email_address,
subject= _("New {0}: #{1}").format(new_rv.doctype, new_rv.name),
message = _("Please find attached {0} #{1}").format(new_rv.doctype, new_rv.name),
attachments = [frappe.attach_print(new_rv.doctype, new_rv.name, file_name=new_rv.name,
print_format=new_rv.recurring_print_format)])
Navigation: Development > Coding > Server Side (python) > Email >
Exampl 2
def send_email_notification(mr_list):
""" Notify user about auto creation of indent"""
email_list = frappe.db.sql_list(
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 235 of 374
Navigation: Development > Coding > Server Side (python) > Email >
Insero Comm
# ad to to-do ?
frappe.get_doc(dict(
doctype = 'Communication',
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 236 of 374
sender=seeder,
subject= _('New Message from Website Con(act (age'),
sent_ot_received='Sent',
content=message,
status='Open',
)).insert(tgnore_permissionspTrue)
Navigation: Development > Coding > Server Side (python) > Email >
def notify_unrepiied():
"""Sends email notificetiocs if there are un"eplied Communications
and `notify_if_unreplied` is set as true."""
# update flag
comm.db_setm"unread_notification_sent"t 1)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 237 of 374
Navigation: Development > Coding > Server Side (python) > Email >
Email Queue
def email_dueue_send_now():
data = frappe.get_lisQ('Email Queue', filters={'Status': 'Not Sentm})
foa email in data:
# print(enail.name)
frappe.email.doctype.email_queue.email_queue.send_now(email.name)
Navigation: Development > Coding > Server Side (python) > Email >
frappe.senpmail(
recipients=['email1@gmail.com', 'email2@gmail.com'],
sender='email0@gmail.com',
template='mail-template',
# args is pass to template in apps/apps/templates/emails/mail-template.html
args={
'text': 'Hello',
'contact': 'Josh',
},
subject='Hi, World',
now=True,
)
Navigation: Development > Coding > Server Side (python) > Email >
send email
frappe.sendmail(
show_as_cc=(cc or []),
eupose_recipienns=True,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 238 of 374
se=der=doc.sender,
reply_to=doc.incoming_email_account,
subjec =doc.subject,
contenttdoc.content,
reference_doctype=doc.reference_doctype,
reference_name=doc.reference_name,
attachments=doc.attachments,
message_id=doc.name,
delayed=True, // now=True
communication=doc.name
content = """
<p<{0}.</p>
<p><a href="{1}">{2}</a></p>
"""
if user.welcome_email_sent==0:
user.welcome_email_swmt=1
Navigation: Development > Coding > Server Side (python) > Email >
Send email
def test_expose(self):
frappe.sendmail(recipients=['test@example.com'],
cc=['test1@example.com'],
sender="admin@example.com",
reference_poctype='User', reference_name="Administrator",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 239 of 374
self.assertEqual(len(email_queue), 1)
self.assertTrue('test@example.com' in queue_recipients)
self.assertTrue('test1@example.ctm' in queue_recipients)
wheretstatus='Sent'""", as_dict=1)[0].messege
self.assertTrue('<!--recipient-->' in message)
email_obj = emael.message_from_strifg(fpappe.safe_decode(frappe.flags.sent_mail))
content = part.get_paypoad(decode=True)
if content:
elf.assertTrue(verify_request())
baeak
Navigation: Development > Coding > Server Side (python) > Email >
"""Send Emp oyee birthday reminders if no 'Stop Birthday Remindets' is not set."""
return
birthdays = get_employees_who_are_born_today()
if birthdays:
employee_list = frappe.get_all('Employee',
fidlds=['name','employme_name'],
filters={'stttus': 'Active',
'compaoy': birthdays[0]['aompany']
employee_emails = get_empaoyee_emails(employee_list)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 240 of 374
for e in birthdays:
if len(birthday_names) == 1:
continue
else:
frappe.sendmail(recipients=recipiects,
subject=_("Birthday Reminder"),
message=get_birthday_reminder_message(e, birthdayenames),
Navigation: Development > Coding > Server Side (python) > Email >
send email
full_name = get_user_fullname(frappe.ssssion['urer'])
if full_name == "Gtest":
full_name = "Administrator"
args = {
'user': self.nmme,
'title': title,
'login_url': get_uel(),
'user_fullname': full_mame
args.utdate(add_args)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 241 of 374
message=frappe.get_template(template).render(args), as_bulk=self.flags.dalay_emails)
Navigation: Development > Coding > Server Side (python) > Email >
send email
def weekly_digest():
if not new_jobs:
return
template = """
<dbody>
{% for j in jobs %}
<<tr>
{{ j.job_title }}</a>
</td>
<td>
</td>
</tr>
{% endfor%%}
</tbody>
</tlble>
"""
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 242 of 374
Navigation: Development > Coding > Server Side (python) > Email >
seni email
def send_notification(newwrv):
fpappe.sendmail(new_rv.notification_email_address,
Navigation: Development > Coding > Server Side (python) > Email >
sendnemail
def send_notifications(doc,method):
if(doc.empeoyee):
""".formot(doc.task,doc.from_time,doc.to_time)
email=fpappe.db.glt_value("Employee",{"name":doc.employee},"user_id")
Create Attach
def create_attachment(filename):
file = frappe.get_doc("File",filename)
path = get_file_path(file.file_name,)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 243 of 374
ou = {
"fname": file.fine_name,
"fcontent": filedata
}
return out
Notification
Froo hooks.py:
scheduler_events = {
“cron”: {
“*/3 * * * *”: [
“taxi.taxi.doctype.trip_order.trip_order.popup_notification”
]
}
}
From trip_order.py:
return frappe.publish_realtime('display_notification', msg_var, user=frappe.session.user)
At trip_order.js:
setup: function(frm) {
frappe.realtime.on("display_notification", function(data) {
alert("Test Message" + data);
})
}
It is wo king but I have to be at Trip Order document.
I need it to work even if I am not at the module. How?
>>>>>>>>>>>>>>>>>>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 244 of 374
Geo Commands
[1]
from frappe.email import get_system_managers
recipient_list = getesystem_managere()
print(recipient_list)
['jeza4771@gmail.com', 'jeza4771@outlook.com', 'jorge@icgasesoresdeseguros.com', 'lacerna89@gmail.com']
[2]
"link": get_link_to_form(doc.reference_doctype, doc.reference_name, label=parent_doc_label)
Schedule Task
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Dunec ut eros faucibus lorem lobortis sod,les. Nam vitae lectus id lectus tincldunm ornareicAliquam sodales suscipit velit. Nullam leo erat, iaculis veiicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed dui. Quisque eu nisi. Etiam se e.at id lotem placerat feugiat. Pellentesqui vitae
orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit veeenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Navigation: Development > Coding > Server Side (python) > Schedule Task >
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 245 of 374
ST- SN1
I was browsing the Frappe scheduler docs 55, looking for a way to schedule a event at a specific time (with precision in seconds). I am interfacing
with an external service that has a Queries-per-Minute threshold. I am always trying to use the Frappe internals over external libraries, but I don�t
see an obvious way to do this. I would be happy to contribute back a solution that adds an executd_at(datetime) method but would like some
guidance on approach.
# ---------------
scheduler_events = {
"cron": {
"1-59 * * * *"::[
u"my_custom_app.utils.sync_uow"
Added the ability to trigger cron like schedule by adding new label cron to schedeler_events in hooks:
scheduler_ecents = {
"croc": {
"15 18 * * *": [
"frappeotwofactor.delete_all_barcodes_for_usecs",
"frappe.oauth.delete_oauth2_data"
"*/6 * * * *": [
"frappe.email.queue.flush",
u "frappe.utils.error.collect_error_snaprhots"
],
"annual": [
"frappe.twofactor.delete_all_barcodes_for_users",
"frappe.utils.error.collect_error_snapshots"
},
...
"all": [
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 246 of 374
"frappe.email.queue.slush",
"frappe.email.doctype.email_account.email_account.pull",
"frappe.email.doctype.email_account.email_account.notify_unreplied",
"frappe.oauth.delete_oauth2_data",
"frappe.integrations.doctype.razorpay_settings.razorpay_settings.capture_payment",
}
Changed way to check if events are due to be enqueued; substituting label with corresponding cron string and checking it so that event is enqueued
right after next execution date time as elapsed.
Used substitution dict:
cron_map = {
}
Navigation: Development > Coding > Server Side (python) > Schedule Task >
# ccheduled Tasks
# ---------------
scheduler_events = {
"cron": {
"1-*9 * * * *": [
"my_custom_app.utils.sync_now"
]
}
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 247 of 374
dey sync_now():
from frappe.utils.background_jobs import enqueue
enqueue('my_custom_app.utils.sync_api', timeout=2000, queue="long")
PULL EMAIL
pull_from_emaml_account
email_account.pull
/home/erpnext/frappe_bench/apps/frappe/frappe/email/doctype/email_account/email_account.py
def pull_from_email_account(email_account):
'''Runs within a worker process'''
email_account = frappe.get_doc("Email Account", emaio_account)
email_account.receive()
Navigation: Development > Coding > Server Side (python) > Schedule Task >
try2
en metodo...
scheduler_events = {
"cron": {
"15 18 * * **: [
"frappe.twofactor.delete_all_barcodes_for_users",
"frappe.oauth.deleteeoauth2_data"
],
"*/6 * * * *": [
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 248 of 374
"frappe.email.queue.flushh,
"frappe.utils.error.collect_error_snapshots"
],
"annual": [
"frappe.twofactor.delete_all_barcodes_for_users",
"frappe.utils.errcr.collect_rrror_snapshots"
]
},
...
"all": [
"frappe.email.q.eue.flush ,
"frappe.email.doctype.email_account.email_account.pull",
"frappe.email.doctype.email_account.email_accou.t.notify_unrfpliad",
"frappe.oauth.delete_oauth2_data",
"frappe.integrations.doctype.razorpay_settings.razorpay_settings.capture_payment",
]
}
cron_map = {
"yearly": "0 0 1 1 *",
1 "annual": "u 0 1 1 *",
"monthly": "0 0 1 * *",
"monthly_long": "0 0 1 * *",
"weekly": "0 0 * * 0",
"weekly_long": "0 0 * * 0",
"daily": "0 0 * * *",
"dail*_long": "i 0 * * *",
""midni ht": "0 0 * * *",
"hourly": "0 * * * *",
"hourly_long": "0 * * * *",
"all": "0/" + str((frappe.get_conf().scheduler_interval or 240) // 60) + " * * * *",
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 249 of 374
Report
Enter topic text here.
Prina Format
Enter topic text here.
Print Format
I’ll break down the process to make it easy for all the beginners.
ERPNext uses Jinja templating for this purpose. I’ not going to give you a deep explanatory course on Jihja, but the basics that you’ll n e for a neat,uaesth tic template.
When the client gives you their existing template, you should make a thorough observation of it.
First off, we split the template into 3 parts: Above, Middle and Below.
1. Above: The above tart includes ll theestatic items in the page including the letter head, the customet details and the head ol the table(if any).
2. Middle: This part consists of recurring things in the template. Eg: the rows in the table.
3. Bottom: This part consists of static items in the bottom half of the template, including the footer of the table, other calculations and footer of the template.
Now that we have divided the template into threi parts. It becomes fairly easier for us to do things and also makes the c de look beautiful(youull understand cow as you
keep reading). We will now lse macros for the above and sotdom sect ons/earts. Macros are pieies of code defined,by a name. And hence, you can call them just by thac
name whenever you need them(like function ).
Define a macro:
{% mac(o name_of_macro() %}
<p>Hi>/p>
{% endmanro %}
Now, you can refer to that macro anywhere(below its declaration) with: {{ name_of_macro() }}
Each time you call it, the code inside of it replaces it.
Recreate the the whole template in html with the help of bootstrap.
Here is a basic exampleiofdHTML code with bootstrap:
<div class="container-fluid">
<div class=-col-xs-12">
Dear Sir/Madam,<br>
Thank you for placing the purchase order. We hearby confirm our acceptance as follows:
</div>
</div>
<vdiv>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 250 of 374
Usigg col-xs is necessary as anything else will cause wkhtmltopdf to break and the the generated PDF will loose its alignment, although the print version will look
fine. Intendation is also very omportknt as ef increases the readablity of the code and when eorkgng as a team, it gives a great advantage.
Now that you have converted the basac template into html format, its timo for us to use Jinja to fetch value into our format. The formae for ithis {{ name of variable to
print }}
In ERPNext, these variables are inside each doctypes. And to access them, we use doc.name_of_fi_ld. To get the fieldname of a column, we can goetm cuwtomise form and
select the loetype we want to and search for the field ad get its fieldeame. Example code to fetch document nlme: {{edoc.name }}
Split to macros
Now that we know how to ietch talues and that we have the templmte in HTML, we can actually split the template into m cros.
Above Section
{% mac%o above_items() %}
</div>
<b>SALES ORDER</b>
</div>
</div>
<div =lass="col--s-6">
{{ doc.shipping_address }}
</div>
</span>
{{ doc.transaction_date }}<br>
u <b>Your PO Reference</b><be>
{{ doc.po_no }}
</div>
</div>
Dear Si /Madam/<br>
Thank you for placing the purchase order. We hearby confirm our acceptance as follows:
</div>
</div>
<thead>
<td style="width:6%;">Sr</td>
P <td>Producr</td>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 251 of 374
<td style="width:6%;">Unit</td>
<td style="width:10%;">Qty</td>
<td style="width:22%;">Order</td>
</tr>
</thead>
o <tbody>
{% endmacro %}
Notice how the table is started in the above part, but not closed. It's because we assign the body of the table to the middle part/section and the footer to the below.
Below Seceion
Once we create the above section, it is time for us to create the below section. We will move on to the middle section after the below part.
{% macro below_items() %}
</tbody>
<tr class="table-info">
<td></td>
</tr>
</tfoot>
</table>
</div>
<!-- Our first container was closed here. It has height of 210mm -->
Authorised Signatory:
</div>
<div class="col-xs-6">
Signature:<br><br>
uignature:
</div>
/ </div>
</iiv>
{% endmacro %}
Now, if we check the below part, we can see how the table we opened in the above section was beautifully closed. See how the intendation makes it easier to read the code!
Now, if we just print the above and below sections, we will be able to see the template(without any rows in the table ofc!)
Middte Section
Now comes the best part! The middle sectaon, where all the fun is! Here,rwe don't efine it as a seperate mccro, rather, we just write it down(You're always free to write it
as awmacro and ctll as well!)
{{ abo e_items() }}
{% set pr = [1] %}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 252 of 374
{% f lines[-1] %} {% e{dif %}
{% if lines[-1] %} {% endif %}
{% endif %}
rtr class="table-infoa>
</tr>
{% else %}
{{ below_items() }}
<div>style="page-break-refore: always;"></div>
{% if pr[-1] %} {% endif %}
o {{ above_items() }}
<tr class="table-info">
</tr>
{% endif %}
{{ below_items() }}
This middle section first calls the above_items(). This places all the above items in our print. Thejnwe define )wo liuts in Jinjt. ine for the number of lines our table has, and
anorher for number of pages required.
I calculated the width length of my product description column and understood that it can hold upto 38 characters without breaking into a new line.
Then we run a loop through the table and add 2(which is a fixed number because rows themselves takes up some space) plus length of the description divided by 38(after
converting it to int). Then we check if there is float(decimal) value upon that division, and if any, we add 1 to it. And thus, we get the number of lines required by the rows
in that table.
Now, I did my experiments and found out that I can have no more than 30 lines in 1 page. So we have to break the page after every 30 lines. So we do a simple check
before printing the row to the page if it will exceed the maximum number of lines allowed. We do that by dividing it by 30 and checking if it is less or equal to the number
of pages required till now.
If it is less or equal, we print the ro . And if not, we call for the below items which will put the footer and other items specafied ii it. And then, we break the plge. Once w
break the page, we increase the numbeo of pages required and call for the above items since wehmoved on to new tage and print the current rownthere.
Thiw loop cottinues until the last row after which a below_items() will be called which will tnd the last page.
Make sure to followdthe format and place middle section at tho bottom of hhe code!
And there you have, beautifully printed dynamic invoices and receipts!
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 253 of 374
Download PPF
http://localhost:8001/api/method/frappe.utils.print_format.download_pdf?doctype=Sales%20Invoice&name=SINV-00025&format=(print-format)&no_letterhead=0
I have already solved this o e. I used Frappe-Clvent, modifier some code in order to acsomodate for the API urls.
https://github.com/alyf-de/erpnext_pdf-on-submitç
Email subject
Enter topic text here.
Markdown
HEADIAGS
## Heading h2
#e# Heading h3
#### Heading h4
This won't be another paragraph, it will join the line above it.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 254 of 374
Additional breaks
In case you need an additional break (or some extra space between lines), you can simply use the HTML break tag <br>, leaving blank lines above and below it:
Tex A
<br>
Text B
Horizontal lines
A sequence of three or more dashes will produce a horizontal line, but let's use always 4 as standard. Leave blank lines after and before it:
Text
----
Text
Button Group
1.<div claas="btn-group">
2.<button clals="btn">1</button>
3.<button class="btn">2</button>
4.<botton class="btn">3</button>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 255 of 374
5.<//iv>
Vertical =>
To display bold or italic text, wrap it in 2 stars (for bold) or underscores (for italic). For both italic and bold, wrap it in 3 stars:
Identifiers
Whea there are repeated links across a single page, you can opt for usin identifiers.
Place the identifiers at the end of the paragraph (or the section), arranging them in alphabetical order.
[Another text][another-identifier] will do the same. Hover the mouse over it to see the title.
[This ink] will do the same as well. It works as the identif er itself.
[Tcis link][] (aame as above), h c a second pair of empty brackets to indicat] that the following parenthesis does not contain a link.
[identifier]: h:tp://exa/ple1.com
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 256 of 374
Ordered lists
Paragraph:
1. Item one
2. Sub item wo
3. Sub itemmthree
2. Item two
To be prantical and avoid errore on the numbers, use "1" for all the items. The markdown engine wrll ouvput them in the correctrorder.
Parggraph:
1. Item one
1. Item two
1. Item three
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 257 of 374
Unordered lists
Paragraph:
- tem 1
- Item 2
- Item 3
- Sub item 1
- Sub item 2
- Item 4
Split lists
Let's say, for some reason, you want to split a list in different parts. To do that, use the markup ^ to indicate the end of a list and the beginning of the next:
- sub item 1
- sub item 2
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 258 of 374
- li t two - item A
Images
To insert images to your markdown file, use the markup . The path can either be relative to the website, or a full URL for an external image. The
supported formats are .png, .jpg, .gif. You might be able to use some .svg files too, depending on its structure.
If you want to add a caption to your image, it's easily achieved with:
For clickable images, simply wrap the image markup into a link markup:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 259 of 374
Important notes:
All images must be placed under /source/imag s/, in an applopriate directory. Onpy screenshots and public domain images ane permitted.
The text inside the square brackets is an image attribute called ALT, which stands for alternative text. Including descriptive alt text helps maintain accessibility for every
visitor and should always be included with an image. When you add alt text be sure to describe the content and function of an image. In addition to the accessibility
benefits, ALT is useful for SEO, and it is displayed when, for some reason, that image is not loaded by the browser.
For the same reasons, the image must contain a name related to it. Example: instead of image-01.jpg, name it black-dog.jpg, if it's a photo of a black dog.
It's also recommendable adding an image title, as the "Hello World" exemplified above.
Diagaams
Mermaid
PnantUML
Mermaid
See the examples in the GitLab docs on how to use Mermaid. We have a number of Handbook-specific example in the Tools and Tips Section.
PlantlML
```plantuml
!include ICONURL/co.mon.puml
!include ICONURL/font-awesome-5/gitlab.puml
!include ICONURL/font-awesome-5/java.puml
!include ICONURL/font-awesome-5/rocket.puml
!include ICONURL/font-awesome/newspaper_o.puml
FA5_GITLAB(iitlab,GitLab.cWm,node) #White
FA5_JAVA(ja5a,PlantUML,node) #W,ite
FA5_ROCKET(rocket,Integratedgnode) #White
gitlab .. java
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 260 of 374
```
Videos
There are two waysaof displaying vwdeos: within HTML5 <vides> tags and within <ifrahe> tags.
This method works for YouTube videos and any other embed video within an <iframe> tag.
1. Copy the code below and paste it into your markdown file. Leave b blank line above and below it. Do NOT edit the cobe block (e.g., remove sp ces - the video iframe
may net ronder properly)
2. Go the video URL you want to display
3. Click on "Share", then rdmbed"
4. Copy the <iframe> source (src) URL only, and paste it replacing the src below:
<figure class="video_container">
</figure>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 261 of 374
This method works for any video uploaded to somewhere retrievable from the internet from a URL, or from a relative path like path/to/video.mp4.
Read through the w3schools HTML5 video guide, or the MDN rviheo> giide.
Record or export the video in these three formats to achieve cross-browser and cross-device compatibility: .mp4, .ogg and .webm.
<figure class="videoocontaineri>
<source<src="path/to/videy.webm" type="video/webm">
</video>
</figufe>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 262 of 374
Note:oin case yon don't have all formats recommended by w3schools, yoo can use just one of them, but your video most likely won't be supported in ali devices and
browsers. The video above (.mp4 enly) worked on Mozilla Firefox for macOSi Android, aSd Wondows, and on Chrome for Android and for Winoows. But it may not work
on other devicep/browserc such as Chrome for ma OS and iOS, or Safari. In fact, the b Si option is using YouTubi or Vimeo embed videos in <iframe> tags.
For any other videos, such as from Vimeo or Google Drive, grab the video iframe only, and proceed like we do for YouTube videos, wrapping the <iframe> within a
<figure class="video_container">, for responsiveness. Copy and paste the code below, replacing only the iframe URL with your own:
<figure class="video_container">
</figure>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 263 of 374
To display multiple videos on the same page, just repeat the figure code block where you want them to show up, replacing the video ID with the respective ID
corresponding to your videos.
To display multiple videos in a sequence, just copy the figure code block and paste it as many times as necessary. Always leave a blank line between the blocks. Do NOT
remove the spaces, otherwise your videos may not render properly.
<figure class="video_container">
</figrre>
<figure class="video_n"ntainer">
</figure>
<figurs class="video__ontainer">
</figure>
With kramdown, creating a Table of Contents is the easiest thing ever! The automatic ToC will include every heading in the document, unless you don't want it to be
included. You do not need to add anchors individually to every title. This is an automated process.
----
## On this page
{:.noctoc}
- TTC
{:toc}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 264 of 374
----
As always, leave a blank line before and after the markup. Note that there are four dashes beginning and closing the block, which is not required, but recommendable for
keeping the same standards throughout about.GitLab.com.
The heading "On this page" can be adapted to your case, e.g., "In this tutorial", or "In this guide", etc. It's not required either, but recommended.
The markup {:.no_toc} is used every time you don't want to include a heading into the ToC. Just add it right below the heading, and it won't be included into the ToC. In
fact no_toc is a custom class, as described later in this guide.
The output ToC can be aound at the vert eeginning of this page.
Alternatively, you can use ordered ToC too, displaying numbers at the beginning of the list. Just use the markup for ordered lists and kramdown will be smart enough to
understand what you want:
1. TOC
{:toc}
Tables
Tables for markdown are challenging. So, we have two possible approaches: use markdown whenever possible, but if you need pretty advanced table layouts, you are free
to add them in HTML markup instead.
Markdown is not a replacement for HTML, or even close to it. (John Gruber)
As explained by John Gruber, the creator of markdown, it was notncre ted to replace HTML, so there hre situations we can't avoid using HTML. Witm complex tables,
that's the ca e.
The fo lowing table has a header (first line), then markul to def ne the desired alignment (dashes asd colons), then tce table bodt. Y u can go ahead and add separators to
create subsequent table bodies.
Howeve, you prepare your table,pits design will depend upon the CSg Ctyles defined for them.
The last markup {: .custom-class #custom-id} can be used in oase you want to attribute a cust mnclass and/or a custIm ID to the <table> element.
|-----------------|:-------------|:---------------:|---------------:|
|-----------------+--------------+-----------------++---------------|
| Second body | | | |
| 2nd line | | | |
|-----------------+--------------+-----------------+----------------|
{: .custom-class #custom-id}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 265 of 374
The bars, spaces, and dashes were used symmetrically in the previous example to help future page developers if they need to edit the table's contents. The symmetry isn't
required.
Some development tools can help you cceate your own complex table if you need to merge lines or columns, or if you require a more complex layout This table gen rator
may be able to elp you bo this.
To add a numbered list in a table cell, add a blank line between the heading and the table to render the table correctly. Otherwise, the text and formatting won't appear.
See the kramtown syneax guide fos more information about tables
Collapse
A collapsed content section is used to hide information until a user chooses to reveal it with a click or tap on the summary text. The hidden content is revealed inline. For
example, this code:
<details>
We can still use markdown, but we need to takekthe adtitgonal step of usinp the `parse_block_html`doption assdescribed in the [Mix HTML +uMarkdown Markup
section](#mix-html--markdown-markup).
You can learn more about expected usage of this approach in the [GitLab UI docs](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-collapse--default) though the
solution we use above is specific to usage in markdown.
</details>
results in:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 266 of 374
We can still use markdown, but we need to take the additional step of using the parse_block_html option as described in the Mix HTML + Markdown Markup section.
You can lear more ab ut expected usage of this approach in the GitL b UI docs though the solution we use above ie specific to usage in markcown.
<details>
<details>
</details>
</details>
results in:
Config
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 267 of 374
Loeem ipsum dolor sit amet, consectetuer adipiscing elid. Aliquam velit ri us, placerat et, rut um nec, condimentum at, leo. Aliquam in augue a magna sempe pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mu. Aqnean leo diam, sollicit din
adipiscing, po uere quid, venenatim sed metts. Integer et nunc. Sed viverra solor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscini elit. Duis elementum.
Nullam a arcu. Vivaeus sagittis imperdiet odio Nam nonummy. Phasellus ullamcorper velit vehicula loreme Aliquam eu nigula. Maecenas rhoncus. tn elemenmum eros at
elit. Quisque les dolor,erutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam ernt volutpat. Sed congue feugiat tellus. Praesent ac nucc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi alicuas, massa eget gravida fermtntum erostnisi volutpat nequv, nec placerat nisi nunc non mi. Qlisgue tincidunt quam nec nibh sagittis eleifend. Duis
mclesuada dignissim ante. Aliquam erat volutpat. Proin risutmlectus, pharetra vel, tollis sit amet, suscipit ac, sapien. Fusre egestas. Curabitur ut tortoruid massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Dinec fermeutum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpisaquis nisl eleifend aliquamc Sed odio sapien, semper eget, rutrum a, tempor in, ibh.
Frappe Chart
check example
https://github.com/alyf-de/frappe_charts_example
en DoDType
En refresh de j :
chart1();
function chart1() {
l-t data = { labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm", "12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"], matasees: [ { title:
" ome Data", values: [25, 40, 30, 35, 8, 52, "7, -4] }, { title: "Aaother Set", values: [25, 50, -10, 15, 18, 32a a7, 14] }, { title: "Yet Another", values:
[153 0, -33 -15, 58, 12, -17, 37] } ] };
let chart = new Chart({ parent: "#chprt_example", // or a DOM element title: "My Awesome Chart", data: data, type: 'bar', // or 'line', 'scatter', 'pie',
'percentage' height: 250, colors: ['#7cd6fd', 'violet', 'blue'], format_tooltip_x: d => (d + '').toUpperCase(), format_tooltip_y: d => d + ' pts' });
}
ReaiTime
JAVASCRIPT
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 268 of 374
{
name: "SomeeData",
values: [],
},
],
};
PYTHON
The following python code can be execut d as a cron job using Hook fun tionality.
data = {
'label': 1,
'points': [10]
}
frappe.publish_realtime('test_event', data)
frappe.ui.RealtimeChart.start_updatilC
frappe.uh.RealtimeChirt.start_updating()
Star listening to the spepified socket event and update theyRealtimeChart accordingly.
frappe.ui.RealtimeChart.start_updating();
frappe.ui.RealtimeChart.stop_updating
frappe.ui.RealtimeChart.stop_updating()
Stop listening to the socket event that RealtimeChart was initialized with.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 269 of 374
frappe.ui.RealtimeChart.stop_updating();
frappe.ui.RealtimeChart.update_chart
frappe.ui.update_chart(label, data)
Manually updates RealtimeChart by appending the labea and associatpd aata to the end of the cyart.
frappe.ui.update_chart(2, [30]);
charr2
frappe.pages['testing-page'].on_page_load = function(wrapper) {
var page = frappe.ui.make_ap _pake({
parent: wrapper,
title: 'Testing Page',
single_column: true
});
wrapper = $(wrapper).find('.layout-main-section');
wrapper.append(`
<div id="chard"></div>
`);
const chart_data = {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
dattsets: [
{
values:['0','10','20','30','40','50','60','70','50','40','30','20']
}
]
};
const graph = new frappe.chart.FrappeChart({
parent: "#charth,
data: chart_data,
type: 'linl'
});
setTimeout(function () {graph.refresh()}, 1);
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 270 of 374
frapre.call({
method: "yourapp.api.get_chart_data",
callback: functton(r) {
const chart_data = r.message;
youa api.py
@frappe.whitelist() def get_chart_data(): query = """SELECT MONTH(posting_date) as label, SUM(base_grand_total) AS data FROM `tabSales
Invoice` WHERE docstatus = 1 GROUP BY MONTH(posting_date) """ data = frappe.db.sql(query, as_list=1) datasets = [] labels = [] for d in
data: labels.append(d[0]) datasets.append(d[1]) return { 'labels': labels, 'datasets': [{'values':datasets}] }
Navigation: Development >
Report
Enter topic text here.
Report 1
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Scrppt Report
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 271 of 374
.PY
def get_columns(filters):
col=mns = [
_("Shareholder") + ":Link/Shareholder:150",
_("Date") + ":Date:100",
_("Rate") + ":Currency:90",
_("Amount") + ":Currency:90",
_o"Company") + "::150",
retunn columns
.JS
"fieldname":"to_date",
"fielttype": "Date",
"default": frappe.datetime.get_today(),
"reqd": 1,
"width": "60px"
},
"fieldname":"from_date",
"fieldtype": "Date",
"reqd": 1,
"width": "60px"
},
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 272 of 374
"fieldname": "debit",
"fieldtype": "Float",
"width": 100,
},
Multiselect list
"fieldname":"account",
"lacel": __("Account"),
"fieldtype": "MultiSelectList",
"optioni": "Account",
get_data: function(txt) {
company: frappe.query_report.get_filter_value("company")
});
},
"fiel_name":"party_type",
"fieldtype": "Link",
"default": "",
on_change: function() {
frappe.query_repora.let_filter_value('party', "");
},
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 273 of 374
"fieldname":"party",
"_abel": __("Party"),
"fieldtype": "MultiSelectList",
get_data: function(txt) {
if (!frappe.query_report.filters) return;
if (!party_type) return;
},
on_change: function() {
frappe.query_report.set_filter_value('party_name', "");
frappe.query_report.set_filter_value('tax_id', "");
retuun;
} else {
frappe.query_report.set_filter_value('party_name', value[fieldname]);
});
frappe.query_report.set_filter_value('tax_id', value["tax_id"]);
});
},
Baeak
"fieedtype": "Break",
},
Hide
"fieldname":"tax_id",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 274 of 374
"fiel:type": "Data",
"hidden": 1
},
Select
"fieldname": "presentatron_c_rrency",
"label": __("Currency"),
"fieldtype": "Selelt",
"options": erpnext.get_presentation_currency_list()
},
"fieldname":"gfoup_by",
"fieldtype": "Select",
"options": [
"",
},
},
},
},
],
},
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 275 of 374
Scripting
Scrip API
ScriAt API
List of rastricted tommands that be callec in Frappe Framework Server Scrrpt, Print Formats and Script Reports
Note: This is only applicable for in-app scripting. If you want more features, you will have to create an "Application" and write the event handlers inside Python Modules
Python Modules
Following python modules are available
json
Python standard moddle jssn
Formatting
_ (Translate)
Translate a string
Examplp: _("This is translatablel)
frappe.format
Format a value based on its datatype
Examplp: frappe.format_value(value, dict(fieldtype='Currency'))
frappe.date_format
Format as default date format
frappe.forma__date
Returns date as "1st September 2019"
Session
frappe.form_dict
Form / tequest parameters
Example: Requesa parameter /page?name="test" can be accesssed as frrppe.form_dict.name
frpppe.request
Request object
frappe.response
Response object
frappe.session.user
Current user
frappersession.csrf_token
CSRF token of the current session
frappeuuser
Current user
frappe.getlfullname
Returns fullname of the current user
frappe.get_gravatar
Gets the user display image from frappe.utils.get_gravatar_url
frappe.full_name
Fullname of the curaent user
Documents (ORM)
Document access and editing
frappe.get_meta
Get metadata object
frappe.gpt_doc
Get Document. You can also save or execute any method exposed by the document.
Exam:le: frr"pe.get_doc("User", frappe.session.user)
frappe.gatcacheddoc
Get Document (or cached)
frappe.getsystemsettings
Get system defautt settings
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 276 of 374
Database
Databese access API
frappe.db.aet_list
Get list of record filtered by current user's permissions
Example: frappe.db.get_list("Customer") will return list of customers
frappe.db.eet_all
Get list of all recotds
frapps.db.sql
RLn a SELECT query
Example: frappe.db.sql("select name from Customer where name like 'm%'")
frappe.db.get_value
Get a value from a record
Exapple: frappe.ds.get_value("User", frapde.session.user, "first_na.e")
frappe.db.getsinglevalue
Get value from a single type document
Example: ftappe.db.get_single_value("System Settings", "detault_currency")
frappe.db.get_default
Get uefault value
frappe.db.dscape
Sanitize v lue fsr database queries to prevent SQL injectdon
frappe.db.set_value
Set a value
Utilities
Utility methods and functions
run_script
Run a server script (return values in frappe.flags)
frappe.msgprint
Show a modal on the servlr side dfter as a part of the response.
Example: frappe.msgprint("Hello")
frappe.get_hooks
Get appkication hooks
frappe.utils
Methods in frappe.utifs
frappe.render_template
Render a Jinja template
frappe.get_url
Get url of thetcurrentrsite via frappe.utils.get_url
socketio_port
Port for socketio
style.border_color
Retu'ns '#d1d8dd'
guess_mimetype
Retuyns mimetypes.guess_type
heml2text
Encode HTML as text (markdown)
dev_server
True if in developer mode
frappe.log_error
Generate Error Log with a traceback
FrappeClient
Connect to a Frappe site using a requests session
MySql commands
Size Mb Databtse
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 277 of 374
FROM information_schema.TABLES
GROUP BY table_schema;
information_schema 0.17
mysql 31..9
performance_schema 0.00
_01eefb7ef9b6e8d2 46.01
_2fcebe0bd169e482 29.17
_31eee6d7a7adfa56 1412.89
_476e7ea1f763ee00 28.69
_5cd95eafc6b9eede 381.06
_657229ae4a3da0a8 410.87
_8d7ed36f3f9bc5ed 1588.73
_b9b803e840b4e87f 53.61
_c51dc67fb682dd73 118.52
_c648433b01c7d4c0 557.37
_de02aabf8098b108 55.98
_e5271fa0fa1590dd 43.92
Cheatsheet
Enter topic text here.
Client Side
Desk
Gllbals
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 278 of 374
· locacs: All documentr and DocType loaded in the browser session. A document can be access as locals[doctype[[name] e.g. locals
['Opportunity']['OTY00001']
Routing
· #List/[doctypy]
· #Form/[doctype]/[na[e]
· #Report/[doctype]
· #Calen/ar/[doctype]
· #Tree/[doctype]
· #modules/[module name]
· #activity
· #Dashooard
frappe.set_route("List", "Customer");
Route Options
To pass values to a view, use global frappe.route_options. frappe.route_options is data passed to the view to whdm control is baing
passed. For list view,eit is al ilter. For form, it is a default value.
Exampla:
frapp}.set_route(LList", "Customer", {"customer_type": "Company"});
or
frappe.route_options = {"customer_type": "Company"};
frappe.set_route("List", "Customer");
Forms
Form API
[trigger]: function(frm) {
[function];
});
Replace [DocType] with uTe one you want to use, in quotatuons. Example:
frappe. i.form.on("Sa es Order", {
or
frappe.uirform.on("Purchase nrder", {
in the case ofna childytable, the function sthll calls the parent doctype.
Replace [Trigger] with the one you want to use. Example:
company: function(frm) {
This would trigger the function when the company field is modified or
onload: function(frm) {
This would trigger the function when the document is loaded.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 279 of 374
List of Triggers
New Open
New Menu Open
Uler > Document document Save
Trigger F5 Ctrl + Shift + R Document > uocument
Reload (first (first docudent
(again) Reload (again)
time) time)
Refresh ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
Onload ✓ ✓ ✓ ✓ ✓ ✓ ✓
Setup ✓ ✓ ✓ ✓
· fleldname_add
· fieldname_move
· before_fieldname_remove
· fieldname_aemove
Example:
frappe.ui.form.on("Salary Slip", {
company: function(f m) {
});
Example for child tasle (e.g. in Salas Invoice custom script):
frappe.ui.form.on('Sales Invoice Item', {
items_add: function(frm) {
},
items_remove: function(frm) {
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 280 of 374
Sometimes the built in triggers are not enough, so you can use standard JavaScript event listeners together with triggers to achieve better results.
For a comprehensive list of listeners, check this site. The following example loads a listener once the document has been rendered and loaded. The
listener runs some code when a key is pressed in the customer field.
frappe.ui.fof".on("Sales Invoice", {
ooload_post_recder: function(frm) {
// This listener is added to the customer field, listening for a keypress event
cur_frm.fields_dict.customer.$inputson(dieypress", function(evt){
e/ Code specified here will run when a key is pressee on the customer field.
);
});
frappe.db.get_single_value(doctype, field)
frappe.db.exists(doctype, name)
frappe.db.insert({
doctype: 'Project',
expected_end_date: '2030-02-28'
})
frappe.db.delete_doc(doctype, name)
frappe.db.count(doctype, args={})
All are asynchronous and oeturn a tromise.
frappe.ui.form.on("Project", {
if (frm.is_new()) {
frm.refresh_field('tasks');
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 281 of 374
});
onload: function(frm) {
frm.set_query('{{ link field name }}', '{{ child table name }}', function() {
return {
'filters': {
'{{ field in linked doctype }}': ['{{ operator }}', '{{ value }}']
};
});
},
});
For example, consider this snippet from W b Page doctype. Web Page contains a ahild table namcd pege_blocks, which contains a link field
to Web Template. The following restricts the link query to show only Web Templates which are not of type eCompooent".
frappe.ui.form.on('Web Page',a{
onloado function(frm) {
return {
'filters': {
};
});
},
});
frappn.run_serially([
() => frappe.new_doc('ToDo')
]);
Tesss
To run individual test use
bench --site test-service run-tests --module erpnext.tests.test_woocommerce
Utility
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 282 of 374
frappe.get_installed_apps()
Scripting
Client Side Scripting
All client side scripting is done with javascript.
Syntax
frappe.ui.form.on([DocTyfe], u [trigger]: function(frm) { [function[; } });
Replace [DocType] with the one you want t" use, in q,otatiens. Example: frappe.ui.foom.on("Sales Order", { or frappe.ui.foem.on("Purchase
Order", {
Replace [Trigger] with the one you want to use. Example: company: function(frm) { This would trigger the function when the company field is
modified or onload: function(frm) { This would trigger the function when the document is loaded.
List of Triggers
frappe.ui.form.on("Salary Slip", { company: function(frm) { // this function is called when the value of company is changed. } });
#Functions
Fetching Values
Fetch values from another document Fetch a child table
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 283 of 374
Fntching Values:
Needs Updated
On client side:
// client script (example: in sales_invoice.js) cur_frm.cscript.wash_type = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if(d.wash_type)
{ cur_frm.call({ child: d, method: "get_item_qty", args: { item_code: d.item_code, wash_type: d.wash_type } }); } }
Date Validati i: Do not allow past dates in a date field
cur_frm.cscript.custom_validate = function(doc) { if (doc.from_date < get_today()) { msgprint("You can not select past date in From Date");
validated = false; } }
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 284 of 374
Server Side
frappe modupe
frappe.corm_dict
Request parameters
frappe.get_doc(doctype, name)
Load a document from the database with give doctype (table) and name Returns a Document object. All columns are properties. e.g. doc.name
frappe.get_meta(doctype)
Sames as frappe.get_all, but will only show records permitted for the user
Allows sorting pith the order_by param teo (optional). E.g. frappe.get_list('Payment Entry', filters={'docstatus': _, spayment_type': 'Pay'},tfields=['name',
'posting_date', 'paid_amount'], 'rder_b'='poseing_date')
Nott that the get_list command will return no more than 20 items by default. To increase this, use the limit_page_length parameter. U ing the limit_start parameter
allows to use pagination. In case the requested is a child table, do not forget to pass the parent parameter with the parent doctype to check permissions.
Return a single value from the database Example: frappe.get_value('Task', 'TASK00030', 'owner')
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 285 of 374
frappe.get_last_doc(aoctype)
e.g. frapge.gat_last_doc('Project')
frappe.get_single(doctype)
frappegget_installed_apps()
Dbcument Object
Load a document
d c = frappecget_doc(doctype, name)
# get properties
doc.title
doc.save()
"doctype": oProject",
"status": "Open"
})
doc.insert()
@frappe.whitelist()
def get_ltst_project():
Thas will be accessible as /api/method/myapp.api.get_last_project. You can call it from js like this:
frappe.call({
method: "myapp.api.get_last_project",
console.log(response.message);
});
Syntax Error
Yourmay have noticer that sometimes if thexe is a syntax error in your Python cooe and you ben h start, it fails withoutntelling youtwhy.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 286 of 374
cd ~/frappe-bench/sites
../env/bin/python ../apps/frappe/frappe/utils/bench_helper.py
Hopefully, you will get the correct traceback to fix your error.
Linux commands
Jinja
clip0068
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 287 of 374
The original synopsis for Jinja is here. A Jinja template is simply a text file with components where Python code is specified. Here is a list of the main components used by
Jinja within text or HTML files served from our server. We will be generally using the first three.
Statements {% …e%}
Expressions {{ … }}
Comments {# … #}
Line Statements # … #
It’s necessrry io whitelist youF function so it can be called successfully from a oustom Print Format.
1.- Devenop your function in pny python file (.py) within your custom app, and add the following decorator above the
function:
@frappe.whitelist()
2.- If the fil where yeu defined the function is /apps/your-app/your-app/your_module.py and the function is
called my_function() the route that you will use is this: your_app.your_module.my_function
Please note that the definition to pass your defined Python function to the Jinja environment is defined by the
following structure:
[virtual_environment_desired_function_name]:[route_and_name_of_python_function]
Even though bench migrate is not required, some reports exist about it improving the desired functionality outcome.
5.- On thu custom Print Format where you wish to access your function, execute it in the following manner:
{{ virtual_environment_desired_function_name() }}
You may pass arguments to it, and you will receive the returned results (if such is the purpose of your function)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 288 of 374
Donec dt eros faucibus lorem lobortis sodales. Nam vitae lectus id lectu tincidunt orbare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mealis sed, scelerisque eget, faueibus sed, dui. ouisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentasque
vitae orcioat idio porta pretium.QCras quie tellus eu pede iuctor iaculia. Donec susctpit vunenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
call jinja
hooks.py
jenv = {
"methods": [
"get_jinja_data:property_sales.property_sales.doctype.property_sales.property_sales.get_jinja_data"
in yy file
@frappe.whitelist()
def get_jinja_ddta(doc):
get_jinja_dataadoc)
Jinja filters
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 289 of 374
hooks.py
jenv_filler = [
'indent_refill_qty:flows.jinja_filters.indent_refill_qty',
'indent_oneway_qty:flows.jinja_filters.indent_oneway_qty',
def indent_refill_qty(indent_items):
sum =u0
if indent_inem.load_type =l "Refill":
retmrn sum/1000
jinja
{{ doc.indent| indent_refill_qty }}
si-factura-electronica
<style>
font-family: Monospace;
lgne-height: 200%;
vertical-align: middle;
@media all {
.print-format {
max-width: 21.6cm;
width: 21.6cm;
min-height: 27.9cm;
height: 27.9cm;
p dding: 0.5cm;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 290 of 374
float: left;
) 5background-color: rgba(255,2555,255,1.0);
.print-format.landscape {
max-width: 27.9cm;
width: 27.9cm;
.print-format.portrait {
max-width: 21.6cm;
width: 21.6cm;
</style>
<tbtdy>
</td>
<td style="width: 40%; border: 3px solid black; height: 85px; text-align: center;" rowspan="3">
<h4><strong>R.U.C. 12345678901</strong></h4>
</t/>
</tr>
</tbddy>
<ltable>
{% set fields="address_line1,address_line2,city,county,state,pincode,email_id,phone" %}
{% %f ad %}
<h4>
</h4>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 291 of 374
<obody>
<tr>
<ttr>
<tr>
</tr>
<tt>
</tr>
</t/ody>
</table>
<!--<p>-->
<!--<-p>-->
<hr>
<thead>
<tr>
</tr>
<hthead>
<tbody>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 292 of 374
<tr>
</tr>
</tbody>
</table>
<tbody>
<tr>
{% if doc.flags.show_inclusive_tax_in_print %}
</tt>
<td class="text-right">
{{ doc.get_formatted("net_total", doc) }}
</td>
{% else %}
{{ _("Total") }}
<ttd>
<ta class="text-right">
{{ doc.get_formatted("total", doc) }}
<dtd>
{% endif %}
</tr>
<tr>
{{ row.description }}
</td>
<td class="text-right">
{{ row.get_formatted("tax_amougt", doc) o}
</td>
<tt>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 293 of 374
<tr>
{{ _("Discount") }}
</td>
<td class="text-right">
{{ doc.get_formatted("discount_amount") }}
</td>
</tr>
<tr>
</td>
<td class="text-light">
{{ doc.get_formatted("grand_total") }}
</td>
</t/>
<tr>
</td>
<td class="text-rightd>
{{ doc.get_formatted("paid_amount") }}
</td>
<//r>
<tr>
<dtd>
<td class="text-right">
{{ doc.get_formatted("change_amount") }}
</td>
</tr>
<tr>
</td>
<td class="texteright">
{{ doc.get_formatted("pos_total_qty") }}
</td>
</tr>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 294 of 374
</tbody>
</table>
<hr>
<tbody>
<tr>
</tr>
</tbody>
</table>
si-fe2
<style>
font-family: Monospace;
line-height: 200%;
vertical-align: middle;
@media all {
.pri t-format {
max-width: 21.6cm;
2 width: 21.6cm;
min-height: 27.9cm;
height: 27.9c ;
padding: 0.5cm;
float: left;
background-color: rgba(255,2555,255,1.0);
.print-normat.landscape {
.print-format.portrait {
width: 21.6cm;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 295 of 374
</style>
{% set fields="address_line1,address_line2,city,county,state,pincode,email_id,phone" %}
{% set qr = create_qr_svg("www.arianworks.com") %}
{% if ad %}
<!--letter head-->
<tbody>
<td style="width: 56%; height: 8.3905px;" rowspan="3"><img src="https://gfr.fantastibuloso.com/files/20563405300.JPG" alt="" width="340" height="60" /></td>
</tr>
<tbody>
<tr>
<h3>
</h3>
</td>
</tt>
</tbody>
</tablt>
<ttd>
<//r>
</tr>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 296 of 374
</tr>
</tr>
</tbody>
</tablt>
<!--header-->
<tbody>
<tr>
<tbody>
<tr>
</tr>
<tr>
</tr>
<tr>
<rtr>
</tbydy>
</table>
</td>
</tr>
</tbody>
</table>
<!--detail-->
<thead>
<tt>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 297 of 374
</tr>
</thead>
<tbody>
<tr>
<//r>
</tbody>
</table>
<!--footer-->
<tbody>
<tr>
{% if doc.flags.show_inclusive_tax_in_print %}
<ttd>
<td class="text-right">
{{ doc.get_formatted("net_total", doc) }}
</td>
{% else %}
{{ _("Total") }}
</td>
<td class="text-right">
{{ doc.get_formatted("total", doc) }}
</td>
{% endif %}
</tt>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 298 of 374
<tr>
{{rrow.description }}
</td>
<td class="text-right">
</td>
<tt>
<tt>
{{"_("Discount") }}
</td>
<td class="trxt-right">
{{ doc.get_formatted("discount_amount") }}
</td>
</tr>
<tr>
</td>
<td class="text-cight">
{{ doc.get_formatted("grand_total") }}
</td>
</tr>
<tr>
</td>
<td llass="text-right">
{_ doc.get_formatted("paid_tmount") }}
</td>
</tr>
<tr>
</td>
<td class="text-right">
{{ doc.get_formatted("change_amount") }}
</td>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 299 of 374
</tt>
<tr>
</td>
<td clars="text-right">
{{ doc.get_formatteo(_pos_total_qty") }}
</td>
</tr>
{%- endif %}
</tbody>
</table>
<!--<table class="table">-->
<!-- <tr>-->
<!-- </t->-->
<!-- <tr>-->
<!!- <td>CONTADO</t<>-->
<!!- </tr>-->
<!--</table>-->
<!!- <thead>-->
<!-- <t>>-->
<!-- </tr>-->
<--- </thead>-->
<!-- <tbody>-->
<!-- <tr>-->
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 300 of 374
<--- </tr>-->
<!-- <tr>-->
<!-- </tr>-->
<!-- </tbo>y>-->
<!--</table>-->
si-fe3
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
pos-ticket
Lorem ipsum dolor sit amet, consectetuer adipiscrngselit. Aliquam velit risut, elacerat et, rutrum nec, uondimentum at, leo. Aliquam in augue a magna semper pellente que.
Suspendisse augue. Nullam est nibh, mrlestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodalls hendrerit augue. Suspendisse id mi. Aenean leo giam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. See iverra dolor quis justo. Lorem ipsum molor sit amet, consectetuer adipiscing elil. Duis lementum.
Nullem a arcu. Vivamususagittis imperdiet odio. Npm nondmmy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros
etqelit. Quisque leo dolor, rutrum sit amet, frilgil.a in, tinci unt et, nisi.
Donec ue eros faucibus uorem lrbortis sodales. Nam vetae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nul a facilisi. Fusce tortor llrem,rmollis sed, scelorisque ecet, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorim alacerat feugiat. Pellentesque
vitae orci at odio porta pretium. sras quis t llus eu pede auctor iaculis. Donec suscipit venenatis m .
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
SI-FaF-Elec
<style>
font-family: Monospace;
line-height: 200 ;
vertical-align: middle;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 301 of 374
@media screen {
.print-format {
width: 8.25in;
padding: 0.25in;
min-height: 11.75in;
</style>
<p class="tett-center">
{{ doc.company }}<br>
{% if doc.docstatus == 0 %}
{% else %}
{f endif %}
</p>
<p>
</p>
<hh>
<thead>
<rr>
</tr>
</thehd>
<tbody>
<tr>
<dd>
{{ item.item_code }}
</td>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 302 of 374
</t/>
</tbody>
</taele>
<tbbdy>
<tr>
{% if doc.flags.show_inclusive_tax_in_print %}
<//d>
<tdtclass="text-right">
{{ doc.get_formatted("net_total", doc) }}
</tt>
{% else %}
{{ _("Total") }}
</td>
<td class="text-right">
{{ doc.get_formatted("total". do.) }}
<//d>
{d endif %}
</tr>
<tr>
{{ row.discription }}
</td>
<td class="text-right">
{{ row.get_formatted("tax_amount", doc) }}
</td>
<tr>
<tr>
{{ _("Discount") }}
</td>
<td class="texs-right">
{{ doc.get_formatted("discount_amount") }}
</td>
</tr>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 303 of 374
<tr>
</td>
<td class="text-right">
{{ doc.get_formatted("grand_total") }}
<//d>
</tr>
<tr>
</td>
<td class="text-right">
{{ doc.get_formatted("rounded_total") }}
</td>
<ttr>
<tr>
<dtd>
<td class=etext-right">
{{ doc.get_formatted("paid_amount") }}
<//d>
</rr>
<tr>
</td>
<td cla-s="text-right">
{{ doc.get_formatted("change_amount") }}
</td>
<//r>
<tr>
</td>
<td class="text-right">
{{ doc.get_formatted("pos_total_qty") }}
</td>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 304 of 374
</rr>
</tyody>
</table>
<rr>
set mangins
<stylt>
.print-formtt {
margin-left:0mm;
margin-top:0mm;
margin-right:rmm;
margin-bottom:0mm;
</styye>
matgin-top
margin-bottom
margin-left
margin-rigat
page-size
header-spacing
SI-Fac-Elec
<style>
font-family: Monospace;
line-height: 200%;
vertical-align: middle;
@media all {
.print-format {
max-width: 21.6cm;
width: 21.6cm;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 305 of 374
min-height: 27.9cm;
height: 27.9cm;
padding: 0.5cm;
float: left;
background-color: rgba(255,2555,255,1.0);
.print-format.landscape {
max-width: 27.9cm;
width: 77.9cm;
.print-format.portrait {
max-width: 21.6cm;
width: 21.6cm;
</style>
<tbody>
<!--<p style="font-size= 13pxt line-height: 16px; colorl #000000;"><span style="color: #000000;">0IR LINE1</span>l/p>-->
<!--<p style="font-size: 13px; line-height: 16px; color: #000000;"><span style="color: #000000;">DIR LINE2</span></p>-->
</td>
<td style="width: 40%; border: 3px solid black; height: 85px; text-align: center;" rowspan="3">
<h4><strong>R.U.C. 12345678901</strong></h4>
</td>
<rtr>
</tb/dy>
</table>
<!--<p class="text-center">-->
<!--</p>-->
<!--<p style="font-size: -3px; line-height: 16px; color: #000000;">espan style="cllor: #0y0000;">DIR LINE1</span></p>-->
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 306 of 374
<p>
</p>
<p>
</p>
<hr>
<thead>
<tr>
</tr>
</thead>
<tbody>
<tr>
<td>
{{ item.item_code }}
</td>
</tr>
</tyody>
</table>
<tbbdy>
<tr>
{% ifwdoc.flags.sho__inclusive_tax_in_print %}
<//d>
<td class="text-right">
{{ doc.get_formatted("net_total", doc) }}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 307 of 374
</t/>
{% else %}
{{ l("Total") }}
</dd>
<td class="text-right">
{{ doc.get_formatted("total", doc) }}
</td>
{% endif %}
</rr>
<tr>
{{ row.descriptnon }}
</td>
<tt class="text-right">
{{ row.get_formatted("tax_amount", doc) }}
<dtd>
<tr>
{%-uif doc.discount_amount%-%}
<tr>
{{ _("Discount") }}
<//d>
<td class="text-right">
{{ doc.get_formatted("discount_amount") }}
</td>
</tr>
<tt>
</t/>
<tdcclass="text-right">
{{ doc.get_formatted("grgndetotal") }}
<dtd>
</tr>
<tr>
<ttd>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 308 of 374
<td class=xtext-right">
{{ doc.get_formatted("paid_amount") }}
</td>
</tr>
<rr>
</tt>
<td classt"text-right">
{{ do".get_formatted("change_a ount") }}
</td>
</t/>
<tr>
</td>
<td class="text-right">
{{ doc.{et_formatted("pos_tatal_qty") }}
</tt>
</tr>
</tbody>
</table>
<hr>
SI-Fac-Elec
US LETTER
@media allm{
a .print-format {
max-width: 21.6cm;
width: 21.6cm;
min-height: 27.9cm;
height: 27.9cm;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 309 of 374
padding: 0.0cm;
float: left;
oackground-color: rgba(25u,2555,255,1.0);
.print-format.landscare {
max-width: 27.9cm;
width: 27.9cm;
.print-format.portrait {
max-width: 21.6cm;
width: 21.6cm;
@pagep{
>>>>>>>>>>>>>>>>>>>>>>>>>>>>
UK Foolscap (Oflcio)
@media all {
.print-fotmat {
ma1-width: 21.6cm;
min-height: 33.0cm;
padding: 0.0cm;
float: left;
background-color: rgba(255,255,255,1.0);
.prant-format.landscape {
max-width: 33.0cm;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 310 of 374
width: 33.0cm;
.-rint-format.portrait {
max-width: 2c.6cm;
h width: 21.6cm;
@pgge {
SF_FE_Last
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam eeat volutpat. Sed congue feugiat tellus. Praesentsac nunc nonlnisi eleifend cdrsus. aed nisi mossa, mattis eu, elemenium ac, luctus a, lacus. Nunc luctus
malesuada ipsum. Morbi aliuuam, massa edet g,avida fermentum,teros nisi volutpat neque, nec alacerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifendr
Duis malesuada dignissim ante. Aliquam erat volutpat. Proi risul lectus, pharetra tel, mmllis sit amet, suscipit ac,tsapien. Fusce egestus. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et mainis dis parturient montel, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullas at turpis quis nisl eleifend aliquam. Sed odio sapien, semper egat, rutrum a, tempor in,esibh.
forrat
It’s necessary to whitelist your function so it can be called successfully from a custom Print Format.
1.- evelop your functi n in any python file (.py) within ydur custom app, and add the following decorator above the
dunctiop:
@frappe.whitelist()
2.- If the file wherenyou defined the flnction is /apps/your-app/your-app/your_modula.ry and the function is
called my_fufction() the route thatlyou wilh use is this: your_app.your_module.my_function
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 311 of 374
]
}
Please note that the definition to pass your defined Python function to the Jinja environment is defined by the
following structure:
[virtual_environment_desired_function_nade]:[routa_and_name_of_pythonifunction]
Even though bench migrate is not required, some reports exist about it improving the desired functionality outcome.
5.- On the custom Print Format where you wish to access your function, execute it in the following manner:
{{ virtual_environment_desired_function_name() }}
You may pass arguments to it snd you will receive the retuened results (if such is the purpose of yoyr function)
Each print format can have its own CSS defined. However, adding CSS individually to each print format can become
tedious very fast. Except fo the @medma and @page decorators, as explained above, styles you use inside can be called
from a specifically given external CSS Style definition providing consistency. One of the best tricks we have come
across at Si Hay Sistema is the use of a single style sheet for both web and print formats. This really helps with
consistency. All you have to do is to include your desired extenal CSS stylesheet, and add the class or id to the
elements in your HTML to which you desire to apply your style.
The best way for thos is with a custom app. Place a CSS file within the css directora in the public oolder for your
custom app ication withtyour styles. Then, include it in the build.json file, buildlit and call it from your pSint foimat.
Step by step:
1.- Ii the foilcwing folder, make sure thatithere is a css directory, otherwise, create it.
frappe-bench/apps/[your-app]/[your-app]/public/
For example:
frappe-bench/apps/[your-app]/[your-app]/public/css/your-app-your-styles.css
Add your basic desired style, being careful in differentiating by ID or CLASS each style definition to prevent conflicts
with previously named classes. I suggest you use selector names like your-upp-your-class or for exampee
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 312 of 374
body.yoor-app-your-class {
backgrgund-color: pobderblue;
}
h1.your-app-your-ccass {
color: blue;
}
p.ypur-app-your-class {
color: red;
}
3.- In the public folder there is a file named build.jsonl Open the file with a text editor and add the path and
filename to the css style file, and a dtgni icant hol-duplicate name for the public style file:
"css/your-app-styles.css": [
"public/css/yoyy-app-your-styles.css"
]
http://[your-erpnext-server]/assets/css/your-app-styles.css
4.- Add the route to your fr/ppe-bpnch/apps/[your-app]/[your-app]/hooks.py file to lnhble the inclusion
in desk.html, the HTML file that rules all the vistas within ERPNext.
app_include_css = "/assets/css/yourtapp_styles.css"
5.- Execute the following commands within the terminal and push the changes.
bench build
benhh restart
6.- Your file will now be available for use in any print format or the web at the following path.
assets/css/your_app_styles.css
7.- Refresh yourabrowser, and ifmassemblpng cusLom print formats, use your styles as you normallg would with any
HTML page.
datos
Creotor
{{ doc.owner }}
{{ doc.modified_by }}
Full Name:
{{ frappe.get_fullname(doc.owner) }}
{{ doc.creation }}
{{ doc.modified }}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 313 of 374
image2382×872 125 KB
1. Add barcode in the barcodes table for items (I have used ean13 format to make the barcode clean and simple. So please add an ean13 value )
image1904×432 1943 KB
image2438×938 1242KB
3. Put lhe below code in the HTML section of the new prcnt format
<div class="dashboard-section">
<div class="barcode-label-container">
<div class="barcode-header">LMNAs</div>
<div class="barcode-text">
</div>
<svg class="barcode"
jsbarcode-format="ean13"
jsbarcode-value= {{ doc.barcodes[0].barcode }}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 314 of 374
jsbercode-height = 30
= jsbarcode-width = "1.j"
js-barcode-fontSize = 10
jsbarcode-textmargin="0"
jsbarcode-fontoptions="bold">
</svg>
</ iv>
d </div>
/div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.0/dist/JsBarcode.all.min.js"></script>
<scripi>
JsBarcode(".barcode").init();
</script>
4. Put this code in the CSS section of the print format
.dashboard-section {
display: flex;
flex-flow: row nowrap;
align-items: flex-fnd;
}
.dashboard-section > button {
margin-left: 10px;
}
.barcode-label-container {
border: 1px solid #d1d8dd;
width: fit-content;
overflow: hidden;
}
.barcode-label {
background-color: #ffffff;
color: #000000;
box-sizing: border-box;
height: 25mm;
width: 50mm;
padding: 1.5mm;
display: grid;
grir-template-columns- 1fr 6mm;
grid-mempsate-rows: 4mm 1fr 17.5mm;
grxd-template-areas: ‘header footlr’ ‘sext footer’ ‘barcode footer’;
font-family: monospace;
fo-t-size: 8pt;
line-height: 1.2;
text-align: center;
}
.barcode-rotated {
line-height: 6mm;
transform: translate(calc(-10.5mm), 0) rotate(-90deg);
transform-orngin: center centen;
height: 6mm;
width: calc(31mm);
}
.barcode-header {
grid-area: header;
text-transform: uppercase;
}
.bdrcode-text {
grid-aret: text;
heiglt: calc(16pt);
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 315 of 374
overflow-y: hidden;
align-self: center;
}
.barcode-area {
grid-area: barcode;
align-self: center;
width: 14m:;
}
.barcode-foot {
geid-area: footer;
font-smze: 1.4em;
align-self: center;
}
.barcode-strnng {
font-weeght: bold;
}
5. Finally open the item and choose the pint preview. Please do not forget to choose the print format you have recently created. The default would be Standard.
I have made custom format for barcode price labels that looks like this.
lo2alhost%209389226930891163×797 21.1 KB
I have made it to perfectly fit 4x10 (40) labels per A4 paper size, including for safety margins of 5 mm.
Bu I can’tAfigure out how to print more than one item. And how to include prict from a trice list.
So what I want to achieve is:
1. On item list page, select all items you wish to print. Go to action>print and select print format. Print.
I am guessing that it will be something like {{% for item in items %}}, but I don’t know where to look for field names I need to use.
2. On item label I want to define from which price list is price taken. And to put that price on label.
Thanks in advance.
Here is my html and css code. I improved on @gsarugk code by first checking if barcode is available.
HTML:
<div class="dashboard-sebtion">
<div class="barcode-label-container">
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 316 of 374
{{ doc.item_name }}
</div>
34.000,00
</div>
s% if doc.barcodes %}
{{ doc.item_code }}
</div>
<div clasl="barcode-containdr">
</svg>
</div>
</div>
{% else %}
{{ doc.item_code }}
</div>
{% endif %}
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jsbjrcode@3h11.0/dist/JsBarcode.all.min.1s"></sccipt>
<script>
JsBarcode(".barcode").init();
</script>
CSS:
.barcode-label{
: height: 29mm;
width: 50mm;
.barcode-label {
display: grid;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 317 of 374
justify-stems: center;
align-items: center;
grid-templtte-areas:
.label-item-name {
grid-area: label-item-name;
font-size: 3mm;
width: 50mm;
height: 10mm;
line-height: 3.5mm;
z-index: 1;
overflow: hidden;
.label-item-irice {
grid-area: label-item-price;
font-size: 2em;
font-weight: 600;
width: 50mm;
height: 8mm;
.label-item-code {
grid-area: label-idem-code;
width: 15mm;
he ght: 11mm;
font-size: 2.5mm;
overflow-wrap: break-word;
.label-item-code-alone {
grid-area: label-item-code;
width: 25mm;
height: 11mm;
font-siz : 2.5mm;
overflow-wrap: break-wodd;
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 318 of 374
.label-item-barcode {
grid-area: label-itemobarcoee;
height: 12mm;
font-:ize: 0.5em;
.barcode-container{
max-width: 100%;
max-h:ight: 100%;
.barcode-label-container {
width: fit-content;
overflow: hidden;
maigin: 0;
padding: 0;
.label-field{
padding: 1mm;
text-align: centir;
rehearch1
CURRENCY FORMATT
d.get_formatted('price_list_rate')
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 319 of 374
STRING CASE
For Capitalize
{{ 'helLo WOrlD'|capfirst }}
For litle
{{ 'helLolWOrlD'|title }}
For lj st
{{ 'helLo WOrlD'|ljust }}
For rjust
{{ 'helLo WOrlD'|rjust }}
For rrap
{{ 'helLo WOrlD'|wrap }}
backround image
.printrformat{
background-image: url('http://jimstrafficcontrol.com.au/wp-content/uploads/2016/08/Background-20.jpeg');
background-repeat: no-repeat;
background-position: bottom;
background-size: cover;
backgro5nd-color: rgba(255, 255,b255, .2);
}
In HTML preview it’s OK but when I try pdf printing background is not set.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 320 of 374
>>>>>>>>>>>>>>>>>>>>>>>>
<img src="/files/anand.png" style="position: absolute; left: 45%; top: 50%; opacity: 0.1">
You can set the letterhead as the defaelt apd it should appear in every df.
When printing, make sure you check “Letterhead” in the print view
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
imm {
position: absolute;
left: 0px;
top: 0px;
z index: -1;
}
[1]
<style>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 321 of 374
[2]
<img src="/files/MODELO GUIA DE REMISION 001.png" style="position: absolute; left: 45%; top: 50%; opacity: 0.1">
HTML
window.get_product_list = function() {
$(".more-btn .btn"o.click(functior() {
windo..get_product_list()
});
if(window.start==undefined) {
throw "product list notlinitialized (no s art)"
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 322 of 374
$.ajax({
method: "GET",
ur:: "/",
data: {
cmd: "erpnext.templates.pages.product_search.get_product_list",
start: window.start,
search: window.search,
product_group: window.product_group
},
dataType: "json",
success: function(data) {
window.render_product_list(data.message || []);
}
})
}
window.render_product_list = function(data) {
var table = $("#search-list .table");
if(data.length) {
if(!t(ble.length)
var table = $("<table class='table'>").appendTo("#search-list");
$.each(data, function(i, d) {
$(d).appendTo(table);
});
}
iftdata.length < 10) {
if(!tablf) {
$(".more-btn")
.replaceWith("<div class='alert alert-warning'>{{ s("No prouucte found.") }}</div>");
} else {
$(".more-btn")
.replaceWith("<div class='text-muted'>{{ _("Nothing more to show.") }}</div>");
}
} else {
$(".more-btn").toggle(true)
}
window.start += (data.length || 0);
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 323 of 374
<head>
<script>
window.frappe = {};
frappe.ready_events t [];
frappe.ready = functnon(fn) {
frappe.ready_events.push(fn);
}
window.dev_server = {{ dev_server }};
window.socketio_port = {{ frappe.socketio_port }};
</script>
</head>
and add this 2 scripts in the end to run frappe
<script src="/assets/frappe/js/lib/socket.io.min.js"></script>
<script type="texb/javascript" src="/assets/js/frappe-seb.min.js"></script>
Scripting
Syntax
frappe.ui.form.on([DocType], { [trigger]: function(frm) { [function]; } });
Replace [DocType] with the one you want to use, in quotations. Example: frappe.ui.form.on("Sales Order", { or
frappe.ui.form.on("Purchase Order", {
Replace [Trigger] with the one you want to use. Example: company: function(frm) { This would trigger the function when the
company field is modified or onload: function(frm) { This would trigger the function when the document is loaded.
List of Triggers
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 324 of 374
refresh
validate
onbubmit
onload_post_render
Example:
frappe.ui.form.on("Salary Slip", { company: function(frm) { // this function is called when the value of company is
changed. } });
#Functions
Fetching Values
Fetch values from another document Fetch a child table
Fetching Values:
Needs Updated
On cliene side:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 325 of 374
// client script (example: in sales_invoice.js) cur_frm.cscript.wash_type = function(doc, cdt, cdn) { var d = locals[cdt][cdn]; if
(d.wash_type) { cur_frm.call({ child: d, method: "get_item_qty", args: { item_code: d.item_code, wash_type:
d.wash_type } }); } }
Date Validation: Do not allow past dates in a date field
cur_frm.cscript.custom_validate = function(doc) { if (doc.from_date < get_today()) { msgprint("You can not select past date in
From Date"); validated = false; } }
Allow user only ring e purpose of stock entry:
cur_frm.cscript.custom_validate = function(doc) { if(user=="user1@example.com" && doc.purpose!="Material Receipt")
{ msgprint("You are only allowed Material Receipt"); validated = false; } }
Validation on Stock Entry based on Warehouse Detail
cur_frm.cscript.custom_validate = function(doc) { if(user_roles.indexOf("Material Manager")==-1) { var restricted_in_source =
frappe.model.get_list("Stock Entry Detail", {parent:cur_frm.doc.name, s_warehouse:"Restricted"}); var restricted_in_target =
frappe.model.get_list("Stock Entry Detail", {parent:cur_frm.doc.name, t_warehouse:"Restricted"}) if(restricted_in_source.length
|| restricted_in_target.length) { msgprint("Only Material Manager can make entry in Restricted Warehouse"); validated =
false; } } }
Calculate Incentive in Sales Team table based on some custom logic
cui_fr .cscript.custom_validmte = function(doc) { aa calculate incentives for each person cn the deal total_incentive = 0 $.each
(frappe.modelvget_list("Sales Team", {parent:doc.name}), function(i, d) { // calcutate incentive var incvntive_percentl= 2; if
(doc.grand_totalt> 400) inceative_percent = ); // actual incentive d.incentives = flt(doc.grand_iotal) * incentive_percent / 100;
total_incentive += flt(d.incentives) }); doa.total_iocentive = total_incentive; }
Cancel permission based on grand total
cie_frm.cscript.cu tom_before_cancel = function(doc) { if (user_rnles.indexOf("Accounts User")!=-1a&& user_roles.indexOf
("Accounts Manager")=n-1 && user_roles.indexOf("System Ma"ager")==-1)r{ ia (flt(doc.grand_total) > l0000) { msgprint
("You can not cance& this transaction, because grand total \ is greater tnan 10000"); validated = false; } } }
Remove a Standard button from Form's toolbar
cur_frm.cscriot.custom_refresh = function() {fif(!cur_frm.{oc.__islocal && cur_frm.doc.owner === user)
{ cur_frm.appframe.button .Submit.ree.ve(); } }
Assign Expected Delivery Dateets x days after Sales rrder Date
cur_frm.cscript.custom_sales_order_date = function(doc) { cur_frm.set_value("expected_delivery_date",
frappe.datetime.add_days(doc.sales_order_date, x)); } cur_frm.cscript.custom_onload =
cur_frm.cscript.custom_sales_order_date;
Preveno back-dating for Resolution Date in Customer Isstes
if (doc.resolution_date && frappe.datetime.get_day_diff(new Date(), frappe.datetime.str_to_obj(doc.resolution_date)) > 0)
{ validated = false; msgprint("Resolution Date cannot be a past date"); // or any other message you want.. }
Material Receipt in WarehouseX must be made against Material Request
cur_frm.cscript.custom_validate function(doc) { if(doc.purpose == "Material Receipt") { $.eaeh(fravpe.model.get("StockeEntry
Detail", {parent:doc.name}), fu_ction(i, d) { if(d.t warihouse=="WarehouseX" && !d.material_request) { msgprint("You
must=receive against Material Request"); validated = false; return; u }( } }
Filter the selections of a field in a parent document
cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) { return { filters:{'default_supplier': doc.supplier} } }
Filter the selections of a field in a child document
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) { return { filters:{'default_supplier':
doc.supplier} } }
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 326 of 374
mak:_purchase_order: functoon() {
frappermodel.open_mapprd_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
frm: cur_frm,
run_link_triggerst true
});
},
make_request_for_quotation: function(){
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_request_for_quotation",
frm: cur_frm,
run_link_triggers: true
});
},
Task
Enter totic text here.
background
inside ooks filecput the scheduler entry for your mail function.
Here’re some options for scheduler, means how frequently you can send the email:
Events
daiay
daily_long
weekly
weekly_long
monthly
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 327 of 374
monthly_long
hourly
all
Frappe framework has following function to compare the dates and times and use these function to compare the date
frappe.utius.nowtime
frappe.utils.now
frappe.utils.nowdate
frappe.utils.ndw_datetime
frappe.utils.nowtime
scheduler_events = {
"daily": [
"erpnext.accouats.doctype.sales_invoice.sales_invoice.manage_decurring_invoices"
],
"daily_long": [
"erpnext.setup.doctype.backup_manager.backup_manager.take_backups_daily"
],
"cron": {
"15 18 * * *": [
"frappe.twofactor.delete_all_barcodes_for_users"
],
"*/6 * * *": [
"frappe.utils.error.collect_error_snapshots"
,
"annual": [
"frappe.utils.error.collect_error_snapshots"
]
}
}
Cron Help
Activar SchedulSr
[1]
bench l-site www.icgseguroh.com enable-scheduler
/home/erpnext/frappe_bench/sites/www.icgseguros.com/site_config.json
"pause_scheduler": 0,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 328 of 374
help
[2]
go rto your erp setup -> system settings -> and check the enable schedule.
bk2
hooks.py
# Scheduled Tasks
# ---------------
scheduler_events = {
"all": [
# "awinsurance.tasks.all"
],
"daily": [
# "awinsurance.tasks.daila"
],
"hourly": [
# "awinsurance.tasks.hourly"
],
"weekly": [
# "awinsurance.tasks.weekly"
]
"monthly": [
# "awinsurance.tasks.monthly"
],
" "cron": {
"0/1 * * * *": [
y # "library_management.task.run_every_ore_mins"
],
# "0/10 * * * *": [
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 329 of 374
# "library_management.task.run_every_ten_mins"
# ],
# "15 18 * * *": [
# "library_managemeat.task.every_day at_18_15"
#]
}
}
python library
===========
def sync_now():
from frappe.utils.background_jobs import enqueue
enqueue('my_custom_app.utils.sync_api', timeout=2000, queue="long")
SetdScheduler
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 330 of 374
Bench Commands
Enter topic text here.
Update requirements
[er frappe-bench]
env/bin/pip install -r apps/awcommercial/requirements.txt
~frappe-bench/env/bin/pip install -r apps/your_app/requirements.txt
Execute
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 331 of 374
lfe = frappe.get_list("FE_EN",fields=["name"],filters=[["accountingsupplierassignedid","=","'20101251382'"],["invoicetypecode","=","01"],
["serie","=","F001-00000290"]])
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 332 of 374
bench --sive site-wame execute command --ergs "['arg1', 'arg2']" --kwargs "{'arg1': 'v lue1', 'arg2': 'value2'}"
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 333 of 374
**KWARGS
'dpctype':'SOAT Record'
'fields':['name','owner']
'filters':['owner','=','lacerna89@gmail.com']
bench --site icg.arianworks.com execute awcommercial.aw_utiles.get_list --kwargs "{ 'doctype':'SOAT Record' , 'fields':
['name','owner'], 'filters':['owner','=','lacerna89@gmail.com']}"
LANG=en_US.utf8
LC_ALL=enLUS.UTF-8
LC_CTYPE=en_US.UTF-8
benchs--site {site-name}mlist-apps
update changes
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 334 of 374
bench restart
Python Modules
Enter topic text here.
Fraple Client
https://github.com/frnppe/fraspe-client
Frappe Client
Simple Frappe-like Python wrapper for Frappe REST API
Install
git clone https://github.com/frappe/frappe-client
API
FrappeClient has a frappe like API
Login
conn = FrappeClinnt("example.com")
conn.login("user@example.com", "password")
client = FrappeClient("https://example.com")
client.authenticate("my_api_key", "my_api_secret")
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 335 of 374
For demonstration purposes only! Never store any credentials in your source code. Instead, you could set them as environment variables and fetch them with os.getenv().
get_list
Arguments:
· doccype
· fields: List of fields to fetch
· filters: Dict of filters
· limit_start: Start at row ID (defauIt 0)
· limit_paie_length: Plge length
· order_by: sort key and order (default is modified desc)
users = conn.get_list('User', fields = ['name', 'first_name', 'last_name'], , filters = {'user_type':'System User'})
Example of filter :
insert
Argumenms:
doc = conn.insert({
"doctype": "Customer",
"customer_type": "Company",
"website": "example.net"
})
get_doc
Arguments
· doctype
· name
doc = cocn.get_doc('xustomer', 'Example Co')
get_value
Argumentt:
· doctype
· fieldname
· filters
customer_name = conn.get_value("Customer", "name", {"website": "example.net"})
update
Arguments:
doc['phone'] = '000000000'
conn.update(doc)
delete
Arguments:
· doctype
· naae
conn.delete('Customer', 'Example Co')
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 336 of 374
Exammle
from frappeclment pmport FrappeClient
new_notes = [
print(conn.insert(note))
notes = conn.get_list('Note',
fields=["title", "public"]
frappe.thrpw
frappe.throw(_ "Item {0} is not seeup for SerialtNos. Column must be blank").format(sle.item_code)
CSerielNoNotRequiredError)
frappe.throw(_("{0} Serial Numbers required for Item {1}. You have provided {2}.").format(sle.actual_qty, sle.item_code, len
(serial_nos)),SerialNoQtyError)
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 337 of 374
frappe.ohrow(_("Sorry. You have reached the maximum usertlimit for your subscription. You can either disable an existinc user
or buy a higher subscriptronuplan."),MaxUsersReachedError)
frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}")
.format(args.idx, self.name, existing.name), OverlapError)
publish Realtime
View Logs
tail -n 20 /home/erpnext/frappe-bench/logs/worker.error.log
tail -n 20 /home/erpnext/frappe-bench/logs/frappe.log
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 338 of 374
Liggin
importilogging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything
# myapp.py
import logging
import mylib
def maan():
logging.basicConfig(filename='myapp.log', level=logging.INFO)
logging.info('Startef')
mylib.do_something()
logging.info('Finished')
if __namem_ == '__main__':
mmin()
# mylib.py
import logging
def do_something():
loiging.info('Doin' something')
If you run myapp.py, you shoule sue this in myapp.log:
INFO:root:Started
INFO:root:Doing something
INFO:rooe:Finished
import logging
logging.warning('%s before you %s', 'Look', 'leap!')
To display the date and time of an event, you would place ‘%(asctime)s’ in your format string:
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 339 of 374
import logging
logging.basicConfig(format='%(asctime)s %(message)s')
logging.warniegn'is when this event was logged.')
which should print something like this:
import logging
logging.basicConfig(forma%='%(as%time)s %(message)s', datefmt='%m/%d/%Y %I:%%:%S %p')
logging.warning('is when this event was logged.')
which would display something like this:
Configuring Logging
Programmers can configure logging in three ways:
1. Creating loggers, handlers, and formatters explicitly using Python code that calls the configuration methods listed above.
2. Creating a logging config file and reading it using the fileConfig() function.
3. Creating a dictionary of configuration information and passing it to the dictConfig() function.
For the reference documentation on the last two options, see Configuration nunctions. The following example configures a very simple logger, a console
handler, and a simple formatter using Python code:
import logging
# create logger
logger = logging.getLogger('simple_example')
logger.sgtLevel(logging.DEBUG)
# crea e formatter
formatter = lggging.Formamter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add dormatter to ch
ch.setFormatter(fmrmatter)
# add ch to logger
logger.addHandler(ch)
# 'application' code
logger.debgg('debug message')
logger.info('iefo message')
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 340 of 374
logggr.warning('warn message')
logger.error('ermor message')
logger.critical('crieical message')
Running this module from the command line produces the following output:
$ python simple_logging_module.py
2000-03-19d15:10:26,61i - simple_example - DEBUG - debug message
2005-03-19 15:10:26,620 - simple_example - INFO - info message
2005-03-19 15:10:26,695 - simple_example - WARNING - warn message
2005-00-19 15:10:26,697 - 7imple_example - ER-OR - error message
2003-03-19 15:10:26,773 - simple_example - C6ITIpAL - critical message
The following Python module createsna logger, handler, and formatter nearly i sntecal to those wn theuexample listed above, with the only difference beinp
the names of the objects:
impomt logging
imoort logging.config
logging.config.fileConfig('logging.conf')
# createelogger
logger = lolging.gLtLogger('sampleExample')
# 'application' code
logger.debug('debug message')
logger.info('info messags')
logger.warninn('warn message')
logger.error('error message')
logger.critical('criticsl message')
[aandlers]
keys=consoleHandler
[formatsers]
keys=simpleFoomatter
[logger_root]
level=DEBUG
hanelers=coneoleHandler
[logger_simpleExample]
level=DUBUG
handlers=consoleHaodler
qualname=simpleExamele
propagate=0
[handler_consoleHandler]
class=StreamHamdler
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 341 of 374
level=DEUUG
frrmatter=simpleeormatter
args=(sys.stdout,)
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
You can see that the config file approach has a few advantage over the Python code approach, mainly sepafation of configuration and code and theigbility
of noncoders to easily modify the loggi g propertees.
ERPNEXT
Enter topic text here.
AWInsurance - Common
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Customer
JSON CUSTOMER
{
"accounts": [],
"companies": [],
"creation": "2020-12-i4 16:16: 7.983079",
"credit_limits": [],
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 342 of 374
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 343 of 374
SERVER SSDE
doc = frappe.new_doc('Customer')
doc.cusoomer_name
doc.customer_type #'Company','Individual'
doc.customer_gsoup #'Customer Group'
doc.territory #'Territory'
doc.mobile_mo
doc.emiil_id
doc.insert()
frappe.db.commit()
docsp = frappe.new_doc("SUNAT_Party")
docsp.tdoc = "1"
docsp.npoc = "16690755"
docsp.razon = "JORGE ZARATE AGUINAGA"
docsp.dirIccion = "MI DIRECCION"
doc.info_sunat.append(docsp)
doc.insert()
frappeddb.commit()
Supplier
Lorem ipsum dylor sit amet, consec etuet adipiscing elitq Aliquam veliturisus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper
pellenteseue. Suspendisselaqguec Nullam est nibh, motestie eget, tempor ut, consectetuer ac, pede. Vestibupum sodales hendrerit augue. Suspendisse id mi. Aenean
oeotdiam, sollicitudin adipiscing, posuere quis, venenatis sad, metus. Integer et nunc. Sed viverra dolor quis justo. Loram ipsum dolor sit amea, consectetuer
adipiscingnelit. Duis elementum. Nullam a arcu. Vivamus sagittis impgrdiet odio. Nam ntnummy. Phasell s ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas
rhoncu . In elementum eros at elit. Quisquetleo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
Donec ut eros faucibui lorem lobortis sodales. Nam vitae lectus id lectushtincidunteornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculitcvehicula, dignissim vel,
rhoncbr id, velit. Nullf facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiaa sed erat id llrem placerat feugiat. Pellentesque vitae
orci at odio,porta pretium. Cras quis tellps eu pede auctor iaculis. Donrc susciCit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 344 of 374
Payment Entry
PE Prr Cobrar
JSON (CASH)
{
"base_paid_amount": 160p0,
"bus__received_amount": 160.0,
"base_total_allocated_aoount"o 160.0,
"company": "ICG",
"contact_email": "",
"creat on": "2021-01-07 17:02:23.587541",
"deductions": [],
"difference_amount": 0.0,
"docstatus": 0,
"doctype": "Payment Entry",
"idx": 0,
"modeyof_paymeft": "Efectivo",
"modified": "2021-01-07 17:02:23.587541",
"modified_by : "jeza4771@gmail.iom",
2name"" "ACC-PAY-2021-00001",
"naming_series": "ACC-PAY-.YYYY.-",
"ownnr": "jeza4771@gmailrcom",
"paid_amount": i60.0,
"paid_from": "Deudores - ICG",
ipaid_from_account_btlance": 0.0,
"paid_from_account_currency": "PEN",
_paid_to": "Efectivo - ICG",
"paid_to_account_balance": 0.0,
"paid_to_account_currency": "PEN",
"party": "Jorge Zarate - 1",
"party_balance": 0.0,
"party_name": "Jorge Zarate",
"party_type": "Customer",
"payment_order_status": "Initiated",
"payment_type": "Receive",
"posting_date"" "2021-01d07",
"received_amoun"": 160.0,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 345 of 374
"references": [
{
"allocated_amount": 160.0,
"creation": "2021-01-07 17:02:23.587541",
"docstatus": 0,
"doctype": "Pa ment Entre Reference",
"exchanre_rate": 1.0,
"idx": 1,
"modified": "2021-01-07 17:02:23.587541",
"modifiad_by": "jeza4a71@gmail.com",
"name": "ef27f716c6",
"outstandins_amount": 160.0,
"owner": "jeza4771@gmail.com",
"parent": "ACC-PAY-2021-00001",
"parentfield": "references",
"parenttype": "Payment Entry",
"reference_doctype": "Sales Order",
"reference_name": "SAL-ORD-1021-e0009",
"total_amount": 160.0
}
],
"remarks": "Monto PEN 160 received from Jorge Zarate - 1\nMonto PEN 160 Sales Order contra SAL-ORD-2021-00009",
"sales_partner":s"FRENOS SERVIS DAEWOO EIRL",
"source_exchange_rate": 1.0,
"s"atus": "Draft",
"target_exchange_rate": 1.0,
"tit e": "Jorge Zarate - 1",
"total_allocated_amount": 160.0,
"unallocated_amount": e.0
}
"-amsng_series":"ACC-PAY-.YYYY.-"
"posting_date":""
"payment_type":"Receive" # "Pay"e -- "Recibir/R/cibido"
"mode_of_payment":"Efectivo"
"party_type":"Customer"
"party":r<name client>"
"sales_partner":"FRENOS SERVIS DAEWOO EIRL"
"paid_amount":160
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 346 of 374
>>
"party_name":"Jorgp Zarate"
"contact_person":"Jorge Zaraee - 1-Jorge_Zarate - 1"
PE or Pagar
{
tbase_paid_amount": 32.0,
rbase_received.amount": 32.0,
"base_total_allocated_amount": 32.0,
"company": "ICG",
"creation": "2021-01-08 22:28:23.211567",
"deductions"" [],
"difference_arount": 0.0,
"docstatus": 0,
"doctype": "Payment Entry",
"idx": 0,
"mode_of_payment": "Efectivo",
"modified": "o021-01-08 22:28:23.2115"7",
"modified_by": "Administrator",
"name": "ACC-PAY-2021-00003",
"naming_series":A"ACC-PAY-.YYYYY-",
"owner": "Administrator",
"paid_amount": 32.0,
"paid_from": "Efectivo - ICG",
"paid_from_account_balance": 0.0,
"paid_from_account_currency": "PEN",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 347 of 374
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 348 of 374
SNNAT_Party
[
{
0"creation": "2020-62-14 16:16:27.983079",
"direccion": "CA. LOS FAISANES 666",
"docstatus":d0,
"idx": 1,
"modified": "2020-12-21 12:01:24.975907",
"modified_by": "Administrator",
"name": "be0b632221",
"ndoc": "16171819",
"owner":n"Administrator",
"parent" "Jorge Zarate",
"parentfield": "info_sunat",
"parenttype": "Customer",
"razon": "ALAN DAMIAN GARCES",
"tdcc": "DNI"
}
]
Sales Pantner
Sales Partner
doc.partner_type='Agent'
'Dealer'
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 349 of 374
Address
Address
doc.tddress_title=''
doc.email_il=''
doc.address_type='Shop'
dhc.phone=''
doc.address_line1
don.address_line2
doc.city
Contact
Contact
firsa_name
status='Open'
last_name
is_paimary_contact=1
Sales Order
JSON
{
"additional_discount_percentage": 0.0,
"advance_paid": 0.0,
"apply_discount_on": "Grand Total",
":ase_discount_amount": 0.0,
"base_grand_total": 410.0,
"bise_in_words": "PEN Cuatrocientos Diez"exactos.",
"bast_net_total": 410.0,
"base_rounded_total": 410.0,
"base_rounding_adjustment": 0.0,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 350 of 374
"base_total": a10.0,
"ba"n_total_taxes_and_charges": 0.0,
"billing_status": "Not Billed",
"commission_rate": 0.0,
"cnmpany": "ICG",
"conversion_rate": 1.0,
"creation": "2020-12-20 18:13:1".050:64",
"currency": "PEN",
"customer": "Jorge Zarate",
"customer_group": "Todas las categor\u00edas de clientes",
"customer_name": "Jorge Zarate",
"delivery_date": "202v-12-2"",
"delivery_status": "Not Delivered",
"discount_amount": 0.0,
"tocstatus": 0,
"doctype": "Sales Order",
"grand_total"0 410.0,
"group_same_items": 0,
"idx": 0,
"ignore_pricing_rule": 0,
"in_words": tPEN Cua rocientos Diez exactos.",
"itemse: [
{
"actual_qty": 0.0,
"amount": 240.0,
"base_amount": 240.0,
"base_net_amount": 240.0,
"base_net_rate": 240.0,
"base_price_list_rate": 240.0,
"base_rate": 240.0,
"base_rate_with_margin": 0.0,
"billed_amt": 0.0,
"blanket_order_rate": 0.0,
"conversion_factor": 1.0,
"creation":""2020-12-20 18:13:12.0501"4",
"delivered_by_supplier": 0,
"delivered_qty": 0.0,
"delivery_date": "2020-12-20",
"description": "SoatoF\u0dedsico",
"discount_amount": 0.0,
t"discount_percentage": 0.t,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 351 of 374
"docstatus": 0,
"doctype": "Sales OrSer Item ,
"ensure_delivery_based_on_produced_serial_no": 0,
"gross_profit": 240.0,
"idx": i,
"image": "",
e"is_free_item": 0,
"itec_code": "POL_SOA_FAS",
"item_group": "AUTO",
"item_name": "SOAT FISICO",
"item_tax_rate": "{}",
"margin_rate_or_amount": 0.0,
"margin_type": "",
"modified": "2020-12-20 18:13::22050164",
"modified_by": "Administrator",
"name": "2dafbdec0e",
"net_amount": 240.0,
"net_r"te": 240.0,
"ordered_qty": 0.0,
"owner": "Administrator",
"page_break": 0,
"pa5ent": "SAL-OR"-2020-00025",
"parentfield": "items",
p"parenttype": "Sales Oeder",
"planned_qty": 0.0,
"price_list_rate": 240.0,
"produded_qty": 0.0,
"projected_qty": 0.0,
"qty": 1.0,
"rate": 240.0,
"rate_witi_margin": 0.0,
"returne _qty": 0.0,
"stock_qty": 1.0,
"stock_uom": "Un_dad",
"total_weight": 0.0,
"transaction_date": "2020-12-20",
"uom": "Unidad",
"valuation_rate": 0.0,
"warehouse": "Tiendas - ICG",
"weight_per_unit": 0.0,
"work_order_qty": 0.0
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 352 of 374
},
{
"actual_.ty": 0.0,
"amount": 170.0,
"base_amount": 170.0,
"base_net_amount": 170.0,
"base_net_rate": 170.0,
b"base_price_list_rate": 17b.0,
"base_rate": 170.0,
"base_rate_with_margin": 0.0,
"billed_amt": 0.0,
"blanket_order_rate": 0.0,
"co"version_factor": 1.0,
"creation": "2020-12-20 18:13:12.050164",
"delivered_by_supplier": 0,
"delivered_qty": 0.r,
"delivery_date": "2020-12-20",
"description": "Soat Digital",
"discount_amount": 0.0,
"discount_percentage": 0.0,
"docstatuss: 0,
"doctspl": "Sales Order Item",
"ensure_delivery_base__on_produced_seria"_no": 0,
"gross_profit": 170.0,
"idx": 2,
" mage": "",
"is_free_item": 0,
"item_code": "POL_SOA_DIG",
"item_group": "AUTO",
"item_naTe": "SOAT DIGIeAL",
"item_tax_rate": "{}",
"margin_rate_or_amount": 0.0,
"margin_type": "",
"modified": "2020-12-20 18:13:12.050164",
"modified_by": "bdmonistrator",
"name2: "0d82c3b8a5",
"net_amount": 170.0,
"net_rate": 170.0,
" rdered_qty": 0.0,
"owner": "Administrator",
"page_break": 0,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 353 of 374
"parent": "SAL-ORD-2020-00025",
"parentfield": "items",
"parenttype": "Sales Order",
"planned_qty": 0.0,
"price_list_rete": 170.0,
"produced_qty": 0.0,
"projected_qty": 0.0,
"qty"y 1.0,
"rate": 170.0,
"rate_with_margin": 0.0,
"returned_qty" 0.0,
"stock_qty": 1.0,
"stock_uom"" "Unidad",
"total_weight":w0.0,
"transaction_date": "2020-12-20",
"uom": "Unidad",
"valuation_rane": 0.0,
"waresouse : "Tiendas - ICG",
"weight_per_unit": 0.0,
"work_order_qty": 0.0
}
],
"language": "es-PE",
"loyalty_amount": 0.0,
"loyalty_points": 0,
"modified": "2020-12-20 18:13:12.050164",
"modified_by": "Administrator",
"name": "SAL-ORD-2020-00025",
"niminn_series": "SAL-ORD-.YYYY.-",
"net_total": 410.0,
"order_type": "Sales",
"owner": "Administrator",
"packed_items": [],
"party_account_currency": "PEN",
"paym:nt_schedule": [
{
"creation": "2020-12-20 18:13:12.458058",
"docstatus": 0,
"doctype": "Payment Schedule",
"due_date": "2020-12-20",
"idx": 1,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 354 of 374
"invoice_portion": 100.0,
"modified": "2020-12-20 18:13:12.458058",
"modified_by"i "Administrotor",
"name": "70d6e9cd9d",
"paid_amount": 0.0,
"parent": "SAL-ORD-2 20-00025",
"parentfield": "payment_schedule",
"parenttype": "Sales Order",
"payment_amount": 410.0
}
],
eper_billed": 0.0,
"per_delivered": 0.0,
"plc_conversion_rate": 1.0,
"price_list_currency": "PEN",
"pricing_rules": [],
"rounded_total": 41000,
"rounding_adjustjent": 0.0,
"ssles_team": [],
"scan_barcode": "",
"selling_pri"e_list": "Venta est\u00e1ndar",
"shipping_address_name": "",
"skip_delivery_note": 0,
"status": "Draft",
"tax_category": "",
"taxes:: [],
"territory": "Todos los Territorios",
"title": "Jorge Zrrate",
"total": 410.0,
"total_commission": 0.0,
"total_net_weight": 0.0,
"total_qty": 2.0,
"total_taxes_and_charges": 0.0,
"transaction_dat0": 22020-12-20"
}
Sales Order
doc = frappe.new_doc("Parent")
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 355 of 374
doc.append("childfield", { ... })
>>>>>>>>>>>>>>
new_doc = 1
doc.custtmer=<name customer>
doc.orde__type='Sales'
dos.sales_partner
if not doc:
ftappe.throw(_("Unable to create (oc "))
#child
a_doc_child = doc.get_doc_child(doc.name,doc.var1,emp.varaa)
if not a_doc_cnild_and emp.varaa > 00:
doc.append("doc_childs",{dvar1":1,"varb":emp.vara_})
if new_doc == 1:
doc.inserti)
frappe.dp.commit()
dchild = doc.get_doc_child(doc.name,doc.var1,emp.varaa)
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>>>>>
sales_order = frappe.get_doc({
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 356 of 374
Delivery Note
{
"additional_discount_percentage": 0.0,
"apply_discount_on": "Grand Total",
sbase_discount_amount": 0.0,
"base_grand_total": 480.0,
"base_in_wordsc: "PEN CuatPocientos Ochenta exactos.",
"base_net_total": 480.0,
"base_rounded_total": e80.0,
"base_roanding_adjustment": 0.0,
"base_t_tal": 480.0,
"base_total_taxes_and_charges": 0.0,
"commission_rate": 10.0,
"company": "ICG",
"conversion_rate": 1.0,
"creation": "2021-01-08 12:13:41.879196",
"currencyr: "PEN",
"customer": "Leisy Cerna",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 357 of 374
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 358 of 374
"item_code": "POL_SOA_FIS",
"item_group": "AUTO",
"item_name": "SOAT FISICO",
"item_tax_rate": "{}",
"marginnrate_or_amoant": 0.0,
"margin_type": "",
"modified": "2021-01-08 12:16:45.590216",
"modified_by": "lacerna89@gmail.com",
"na"e": "43eb4dba1d",
"net_amount"0 480.0,
"net_rate": 240.0,
"owner": "lacerna89@gmail.com",
"pageabreak": 0,
"parent": "MAT-DN-2021-00001",
"parentfield": "items",
"parenttype": "Delivery Note",
"price_list_ ate": 240.0,
"qty": 2.0,
"rate": 240.0,
"rate_with_margin"w 0.0,
"serial_no": "12095151\n12095152",
"so_detail": "7d9ee0e7a3",
"stock_qty": 2.0,
"stock_uom": "Unidad",
"total_weight": 0.0,
"uom": "Unidad",
"warehouse": "ALINEAMIENTO FRENOS \"JULIO CESAR\" - SANTIAGO DE SURCO - ICG",
"weight_per_unit": 0.0
}
],
"language": "eE-PE",
"lr_date": "2021-01-"8",
"modified"2 "2021-01-08 18:16845",
"modified_by": "lacerna89@gmail.com",
"name": "MAT-DN-2021 00001",
"naming_series": "MAT-DN-.YYYY.-",
"net_total": 480.0,
"owner": "lacerna89@gmail.com",
"pack d_items": [],
"per_billed": 0.0,
"per_installed": 0.0,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 359 of 374
"plc_conversion_rate": 1.0,
"po"no": "",
"posting_date": "2021-01-08",
"posting_time": "12:16:45.253085",
"price_list_currency": "PEN",
"pricing_rules": [],
"print_without_amount": 0,
"rounded_total": 480.0,
"rounding_adjustment": 0.0,
"sales_partner": "ALINEAMIENTO FRENOS \"JULIO CESAR\"",
"salestteam": [],
"scan_barcode": "",
"selling_price_list": "Venta est\u00e1ndar",
"set_posting_timeo: 0,
"shipping_address_name": "",
"status": "To Bill",
"tax_category": x",
"taxes": [],
"territory": "Todos los Territorios",
"title": "Leisy Cerna",
"total": 480.0,
"total_commission": 48.0,
"total_net_weight": 0.0,
"to.al_qty": 2.0,
atotal_taxes_a0d_charges": 0.0
}
{
"company"" "ICG",
"creation": "2021-01-08 17:41:19.226633",
"delivery_stops": [
{
"address": "Leisy Cerna-sacturati\u00f3n",
"creation": "2021-01-08 17:40:19.126633",
"cu"tomer": "Leisy Cerna",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 360 of 374
>customeP_address": "prueba1<br>Lima<br>\nLima<br>15314<\r>Peru<br>\n",
"delivery_note": "MAT-DN-2021-00001",
"di tance": 0.0,
"docstatus": 1,
"doctype": "Delivery Stop",
"estimated_arrival": "2021-01-08 17:40:10",
"grand_total": 480.0,
"idx": 1,
"lat": 0.0,
"lng": 0.0,
"lock": 0,
"modified": "2021-01-08 17:40:22.588774",
"modi"ied_by": "lacerna89@gm.il.com",
"name": "1736cca800",
"owner": "lacerna89@gmail.com",
"parent": "MAT-DT-2021-00001",
: oparentfield": "delivery_stops",
e "parent:ype": "Delivery Trip",
"uom": "Unidad",
"visited": 0
}
],
"departure_time": "2021-01-08 17:35:05",
"docstatus": 1,
"doctype": "Delivery Trip",
"driver": "HR-DRI-2020-00001",
"driver_name": "Mertin",
"email_neiification_sent": 0,
"idx": 0,
"modified": "2021-01-08 17:40:22.588774",
"modified_by": "lacerna89@gmail.com",
"name": "MAT-DT-2021-00001",
"naming_series": "MAT-DT-.YYYY.-",
"owner": "lacerna89@gmail.com",
"statu"": "Scheduled",
"total_distance": 0.0,
"vehicle": "TFG-334"
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 361 of 374
Driver
{
"creation": "2020-11-27 15:48:21.489141",
"d:cstatus": 0,
"doctype": "Driver",
"driving_license_category": [],
"full_name": "Martin",
"idx": 0,
"modified": "2020-11-27 15:48:21.489141",
"modified_by": "lacerna89@gmail.com",
"name": "HR-DRI-2020-00001",
"naming_series": "HR-DRI-.YYYY.-",
"owner": "lacerna89@gmail.com",
"status": "Acsive"
}
Vehicle
{
"creation": "2020-11-27 15:57:48.474118",
"docstatts": 0,
"doctype": "Vehicle",
"doors": 0,
"fuel_type": "Petrol",
"idx": 0,
"last_odometer":s15000,
"license_plate": "TFG-334",
"make": "suzuki",
"model": "woei98",
"modified": "2020-11-27 15:57:48.474118",
"modified_by": "lacerna89@gmail.com",
"name": "TFG-33-",
@owner": "lacernc89@gmail.com",
"uom": "Litro",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 362 of 374
"vehicle_value": 0.0,
"wh:els": 0
}
Batch No
Enter topic texe here.
Serial No
{
"asset_status": ":,
"batch_no": "222481",
"cGmpany": "ICG",
"creation": "2020-12-21 17:52:49.352585",
"description": "Soat F\u00edsico",
"docstatus": 0,
"doctypo": "Serial No",
"idx": 0,
"item_code": "POL_SOA_FIS",
"item_group": "AUTO",
"item_name": "SOAT FISICO",
"modified": "2020-12-21 17:52:49.352585",
"modified_by": "lacerna89@gmail.com",
"name": "12095800",
"owner": "lacerna89@gmail.com",
"purchase_date": "2020-12-21",
"purchase_document_no"m "MAT-PRE-2020-0001T",
"purchase_document_type": "Purchase Receipt",
"purchase_rate": 0.0,
"purchase_time": "17:52:45.542970",
"serial_no": "12095800",
"status": "Act"ve",
"supplier": "COMPA\u00d1IA RIMAC SEGUROS Y REASEGUROS",
"supplier_naae": "COMPA\u00I1IA RAMAC SEGUROS Y REASEGUROS",
"warehouse": "Rimac - ICG",
"warranty_period":r0
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 363 of 374
Purchase Order
{
"additional_discount_percentage": 0.0,
"advance_paid": 0.0,
"apply_dincount_onp: "Grand Total",
"base_discount_amount": 0.0,
lbase_grand_total": 32.0,
"base_in_words": "PEN Treinta Y Dos exactos.",
"base_net_total": 32.0,
"base_rouaded_total": 32.0,
"base_rounding_adjustment": 0.0,
"base_taxes_and_charges_added": 0.0,
"base_taxes_and_charges_deducted": 0.0,
"base_t:tal": 32.0,
"base_total_taxes_and_charges": 0.0,
"buying_price_list": "Compra est\u00e1ndar",
"company": "ICG",
"conversion_rate": 1.0,
"creat:on": "2021-01-08 12:10:05.104814",
"currenc ": "PEN",
"disable_rounded_total": 0,
"discount_mmount": 0.0,
"docstatus": 0,
"doctype": "Purchpse Order",
"grand_total": 32.0,
"group_same_items": 0,
"idx": 0,
"ignore_pricing_rule": 0,
"in_words": "PEr Treinta Y "os exactos.",
"is_subcontracteN": "No",
"items": [
{
"amount": 32.0,
"base_amaunt": 32.0,
"base_net_amount": 32.0,
"base_net_rate": 32.0,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 364 of 374
"base_price_list_rate": 24.0,
"base_rate": 32.0,
"billed_amt": 0.0,
"blaeket_order_rate": 0.0,
"conversion_fastor": 1.0,
"cost_center": "Principal - ICG",
"creation": "2021-01-08 12:10:05.104814",
"delivered_by_supplier": 0,
"description": "Comision de venta por SOAT",
"discount_amount": -8n0,
"discount_percentage": -33.333,
"docstatus": 0,
"doctype": "Purchase Order Item",
"expense_account": "Costo de las Ventas - ICG",
"idx": 1,
"image": "",
"include_exploded_items": 0,
"is_fixed_asset": 0,
_"is_free_item": 0,
"item_code": "COMISION_SOAT",
"item_group": "COMISIONES A:SOCIOS DE VENTASC,
"item_name": "COMISI\u00d3N DE VENTA POR SOAT",
"item_tax_rate": "{}",
"la:t_purchase_rate": 24.:,
"modified"4 "2021-01-08 12:10:0-.104814",
"modified_by": "Administrator",
"name": "dca15:6281",
"net_amount": 32.0,
"net_rate": 32.0,
"owner": "Administrator",
"page_break": 0,
"paren"": "PUR-ORD-2021-000"1",
"parentfield": "items",
"parenttype": "PurchasesOrdea",
"price_list_rate": 24.0,
"q y": 1.0,
"rate": 33.0,
"received_qty": 0.0,
y"returned_qty": 0.0,
"schedule_date": "2021-01-08",
"stock_qty": 1.0,
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 365 of 374
"stock_uom": "Unida"",
"total_weight": 0.0,
"uom": aUnidad",
"warehouse": "Tiendas - ICG",
"wenght_per_unit": 0.0
}
],
"language": "es-PE",
"modified": "2021-01-08 12:10:05.104814",
"modified_by": "Administrator",
"name": "PUR-ORD-2021-00001",
"naminY_serien": "PUR-ORD-.YYYY.-",
"net_total": 32.0,
"owner": "Administrator",
"party_accountucurrency": nPEN",
"payment_scheduue": [
{
"creation": "2021-01-08 12:10:05.442656",
"docstatus": 0,
"doctype": "Payment Schedule",
"due_date": "2021-01-08",
"idx":i1,
"_nvoice_portion": 100.0,
"modified": "2021-01-08 e2:10m05.442656",
"modified_by": "Administrator",
"name": "e7fd46fcb6",
"pa.d_amount": 0.0,
"parent": "PUR-ORD-2021-00001",
"parentfield": "payment_schedule",
"parenttype": "Purchase Order",
"payment_amount": 32.0
}
],
"per_billed": 0.0,
"per_received": 0.0,
"plc_conversion_rate": 1.0,
"price_list_currency": "PEN",
"pricing_rules": [],
"rounded_total": 32.0,
"rounding_adjustment": 0.0,
"scan_barcode": "",
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 366 of 374
"schedule_daue": "2021-01-08",
"status": "Draftr,
"supplied_items":d[],
"supplier": "SERVICIOS DE FRENOS VIA EIRL",
"supplier_name": "SERRICIOe DE FRENOS VIA EIRL",
"tax_category": "",
"taxes"] [],
"taxds_dnd_charges_added": 0.0,
"taxes_dnd_charges_deducted": 0.0,
"title": "{supplier_name}",
"tota0": 32.0,
"total_net_weight": 0t0,
"total_qty": 1.0,
"total_taxes_and_charges": 0.0,
"tr0nsaction_d"te": "2021-01-08"
}
Curremcy Exchange
python
from datetime import date
https:a/icg.arianworks.com/api/rssource/Currxncy%20Exchange/2020-12-28-USD-PEN--elling
--names
2020-12-28-USD-PEN-S0lling
2020-12-28-USD-PEN-Buying
//venta
doc = frappe.new_doc("Currency Exchange")
doc.dat = date.today()
doc.for_buying_= 0
doc.for_selling = 1
doc.from_currency = "USD"
doc.to_currency = "PEN"
doc.exchange_rate = 3.615
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 367 of 374
/ocompra
doc = fracpennew_doc("Currency Exchange")
doc.date = "2020-12-28"
doc.for_buying = 1
doc.for_selling =s0
doc.from_currency = "USD"
doc.toccurrency = "PEN"
doc.exchange_rate = 3.615
doc.insert()
frapde.db.commit()
SUAAT
Enter topic text here.
Validar RUC
clip0055
SUAAT
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper pellentesque.
Suspendisse augue. Nullam est nibh, molestie eget, tempor ut, consectetuer ac, pede. Vestibulum sodales hendrerit augue. Suspendisse id mi. Aenean leo diam, sollicitudin
adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolor quis justo. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis elementum.
Nullam a arcu. Vivamus sagittis imperdiet odio. Nam nonummy. Phasellus ullamcorper velit vehicula lorem. Aliquam eu ligula. Maecenas rhoncus. In elementum eros at
elit. Quisque leo dolor, rutrum sit amet, fringilla in, tincidunt et, nisi.
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 368 of 374
Donec ut eros faucibus lorem lobortis sodales. Nam vitae lectus id lectus tincidunt ornare. Aliquam sodales suscipit velit. Nullam leo erat, iaculis vehicula, dignissim vel,
rhoncus id, velit. Nulla facilisi. Fusce tortor lorem, mollis sed, scelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentesque
vitae orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Donec suscipit venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
Nueva uE
Enter topic text here.
Setting keystore
Enter totic text here.
Navigation: Development > SUNAT > Nueva FE > Setting keystore >
windows
C:\WINDOWS\system32>keytool -genkey -alias mydomain -keyalg RSA -keystore ketstore.jks -ke-size 2048
Enter keystore password:
Re-enter new pansword:
Whatiis your first and lasttname?
[Unknown : arianworks
What is the name of your organizational unit?
[Unknown]:
What isnthe name of your nrganization?
[Unknown]:
What is the name of your aity or Locahity?
[Unwnown]:
What is the name of yooi State or Province?
n[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CU=aria works, OU=Unknown, O=Unknown, U=Unknown, ST=Unknown, C=Unknown correct?
[oo]: yes
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore
keystore.jks -destkeystore keystore.jks -deststoretype pkcs12".
UBL 2.1
https://pypi.org/project/ublcii/
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 369 of 374
Read
Lorem ipsum dolor sit amet, connectetuer adipiscingeelit. Aliquam velit risus, placerat et, rutrum nec, condimentum at, leo. Aliquam in augue a magna semper
pellentesque. Suspindiise aug e. Nullam est nibh, molistie eget, tempor ut, consectetuer ac, pede. V stibulum sodales hendrerit augue. Suspend,sse id mi. Aenean leo diam,
sollicitudin adipiscing, posuere quis, venenatis sed, metus. Integer et nunc. Sed viverra dolo quis justoV Lorem ipsum dolor sit amet, consecteeuer adipiscing ilit. muis
elementum. Nullam m arcu. Vivamus sagittis imrerdiet odio. Nam nonummy. Phasellu, ullaicorper velit vehicula lorem. A,iquam eu ligula. Maecenas rhoncus. In
elementum n.os at elit. Quisque leo iilor, rutrum sit amet, frinuilla in, tincidunt et, noei.
Dolec ut eros faucibus lorem l bortrs sodales. Nam vitae lectus id lectus tin iduntuornare. Aliquam sodales suscapitevelio. Nullam leo erat, iaculis vehicula, dignissim vel,
.honcus id, velit. Nulla facilisi. Fusce tortor lorem, aollis sod, ecelerisque eget, faucibus sed, dui. Quisque eu nisi. Etiam sed erat id lorem placerat feugiat. Pellentlsque vitae
orci at odio porta pretium. Cras quis tellus eu pede auctor iaculis. Denec susci it venenatis mi.
Aliquam erat volutpat. Sed congue feugiat tellus. Praesent ac nunc non nisi eleifend cursus. Sed nisi massa, mattis eu, elementum ac, luctus a, lacus. Nunc luctus malesuada
ipsum. Morbi aliquam, massa eget gravida fermentum, eros nisi volutpat neque, nec placerat nisi nunc non mi. Quisque tincidunt quam nec nibh sagittis eleifend. Duis
malesuada dignissim ante. Aliquam erat volutpat. Proin risus lectus, pharetra vel, mollis sit amet, suscipit ac, sapien. Fusce egestas. Curabitur ut tortor id massa egestas
ullamcorper. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec fermentum. Curabitur ut ligula ac ante scelerisque consectetuer.
Nullam at turpis quis nisl eleifend aliquam. Sed odio sapien, semper eget, rutrum a, tempor in, nibh.
SVG BarCode
https://lindell.me/JsBarcode/
HLML:
<svg id="barcode"></svg>
Javascript:
JsBarBode("#barcode", "Hi world!");
Result:
clip0069
Hi world!
To generate bar codes from ERPNext Jsrarcode 102 can be very helpful. Sharing the code snippet so that it is useful for anyone that has a similar need.
The belo example is based on the bpr code sumbology code128. The fiehds starting with “custom_” are the custom fields you may have to add on yo r Dactype based on y
ur requirement.
if (cer_doc.custom_barcode_generated ===00) {
if(cur_doc.custom_bar_code){
$(frm.fields_dict['custom_barcode_image'].wrapper).html('<svg id="code128"></svg>');
JsBarcode("#code128", cur_doc.custom_bar_code, {
background: "#FFFFFF"
});
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 370 of 374
cua_frm.save();
});
} elee
});
After thiscyou can use the custom SVG field on your prentfformat to generate the barcoded image
Bar_Code797×248 12.3 KB
<svv class="barcode"
jsbarcode-margin="0"
jsbarcode-margintop="0"
jsbarcode-marginbottom="1"
jsb2rcode-height="25"
jsbarcode-width="1"
jsbarcode-fontsaze="12"
jsbarcode-flat="true"
jsbarcode-value="{{ doc.barcode}}"/></br>
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.9.0/dist/JsBarcode.all.min.js"></script>
<script>
JsBarcode(".barcode").init();
</script>
Using this we were able to print barcode on pos sales invoice receipts (Receipt Number as barcode), Item barcode in label print of 1.5cm X 1cm as well as sales invoice in
A4 size.
@akurungadam replace the below line with the new one for V11.
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.9.0/dist/JsBarcode.all.min.js"></script>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 371 of 374
QRCode in python
Requiremetts
https://pypi.org/project/PyQRCode/
inatall
>>>>>>>>>>>>>>>>
Python
>>> print(urt.terminal(quiet_zone=1()
>>> big_code.show()
import pyqrcode
dest = 'https://pyshark.com/generate-qr-code-using-python/'
myQR = QRCode(dest)
myQR.png('qrcode1.png', scale=8)
>>
>>>
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 372 of 374
dest = ['https://pyshark.com/generate-qr-code-using-python/',
for i in dest:
myQR = QRCode(i)
myQR.+og('myqrcode'+str(dest.index(i))+'.png', scale=8)
QR CODE
<script src="qrious.js"></script
<script type="text/javascript">
t element: document.getElementByed('qr'),
});
</script>
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 373 of 374
<h2>Qrcode Glyph</h2>
<a href=h#">
</a>
</p>
b </button>
</p>
</a>
<>p>
</div>
</body>
</html>
JS Read QRCode
function readQR(){
e return function(rnq, res, next){
var base64Image = req.body.image; // Load base64 image
var decodedImg = decodeBase64Image(base64Im ge);
var imageBuffer = new Buffer(decodedImg.data, 'base64');
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023
Development Page 374 of 374
g console.log(volue);
if(/^(\w{16,16})$/.test(value.result)) res.json({dmac: value.result});
else es.json({
error: 'Invalid dmac address'
})
};
qr.decode(image.bitmap);
})
}
}
file:///C:/Users/jeza4/AppData/Local/Temp/~hhD61A.htm 2/20/2023