ci: add prettier to pre-commit (backport #40206) (#40362)

* ci: add prettier to pre-commit

(cherry picked from commit 2c16036ef3)

* style: format js files

---------

Co-authored-by: barredterra <14891507+barredterra@users.noreply.github.com>
Co-authored-by: Ankush Menat <ankush@frappe.io>
This commit is contained in:
mergify[bot]
2024-03-11 10:47:18 +05:30
committed by GitHub
parent 5f789d9abe
commit 7d3d2eb928
572 changed files with 24271 additions and 21331 deletions

View File

@@ -2,24 +2,23 @@
// For license information, please see license.txt
frappe.ui.form.on("Address", {
is_your_company_address: function(frm) {
frm.clear_table('links');
if(frm.doc.is_your_company_address) {
frm.add_child('links', {
link_doctype: 'Company',
link_name: frappe.defaults.get_user_default('Company')
is_your_company_address: function (frm) {
frm.clear_table("links");
if (frm.doc.is_your_company_address) {
frm.add_child("links", {
link_doctype: "Company",
link_name: frappe.defaults.get_user_default("Company"),
});
frm.set_query('link_doctype', 'links', () => {
frm.set_query("link_doctype", "links", () => {
return {
filters: {
name: 'Company'
}
name: "Company",
},
};
});
frm.refresh_field('links');
frm.refresh_field("links");
} else {
frm.trigger("refresh");
}
else {
frm.trigger('refresh');
}
}
},
});

View File

@@ -18,12 +18,11 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager {
make_dt() {
var me = this;
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_bank_transactions",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_bank_transactions",
args: {
bank_account: this.bank_account,
from_date: this.bank_statement_from_date,
to_date: this.bank_statement_to_date
to_date: this.bank_statement_to_date,
},
callback: function (response) {
me.format_data(response.message);
@@ -62,18 +61,14 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager {
editable: false,
width: 100,
format: (value) =>
"<span style='color:green;'>" +
format_currency(value, this.currency) +
"</span>",
"<span style='color:green;'>" + format_currency(value, this.currency) + "</span>",
},
{
name: __("Withdrawal"),
editable: false,
width: 100,
format: (value) =>
"<span style='color:red;'>" +
format_currency(value, this.currency) +
"</span>",
"<span style='color:red;'>" + format_currency(value, this.currency) + "</span>",
},
{
name: __("Unallocated Amount"),
@@ -117,13 +112,15 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager {
return [
row["date"],
row["party_type"],
frappe.form.formatters.Link(row["party"], {options: row["party_type"]}),
frappe.form.formatters.Link(row["party"], { options: row["party_type"] }),
row["description"],
row["deposit"],
row["withdrawal"],
row["unallocated_amount"],
row["reference_number"],
`<button class="btn btn-primary btn-xs center" data-name="${row["name"]}">${__("Actions")}</button>`
`<button class="btn btn-primary btn-xs center" data-name="${row["name"]}">${__(
"Actions"
)}</button>`,
];
}
@@ -135,14 +132,8 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager {
checkboxColumn: false,
inlineFilters: true,
};
this.datatable = new frappe.DataTable(
this.$reconciliation_tool_dt.get(0),
datatable_options
);
$(`.${this.datatable.style.scopeClass} .dt-scrollable`).css(
"max-height",
"calc(100vh - 400px)"
);
this.datatable = new frappe.DataTable(this.$reconciliation_tool_dt.get(0), datatable_options);
$(`.${this.datatable.style.scopeClass} .dt-scrollable`).css("max-height", "calc(100vh - 400px)");
if (this.transactions.length > 0) {
this.$reconciliation_tool_dt.show();
@@ -155,27 +146,18 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager {
set_listeners() {
var me = this;
$(`.${this.datatable.style.scopeClass} .dt-scrollable`).on(
"click",
`.btn`,
function () {
me.dialog_manager.show_dialog(
$(this).attr("data-name"),
(bank_transaction) => me.update_dt_cards(bank_transaction)
);
return true;
}
);
$(`.${this.datatable.style.scopeClass} .dt-scrollable`).on("click", `.btn`, function () {
me.dialog_manager.show_dialog($(this).attr("data-name"), (bank_transaction) =>
me.update_dt_cards(bank_transaction)
);
return true;
});
}
update_dt_cards(bank_transaction) {
const transaction_index = this.transaction_dt_map[
bank_transaction.name
];
const transaction_index = this.transaction_dt_map[bank_transaction.name];
if (bank_transaction.unallocated_amount > 0) {
this.transactions[transaction_index] = this.format_row(
bank_transaction
);
this.transactions[transaction_index] = this.format_row(bank_transaction);
} else {
this.transactions.splice(transaction_index, 1);
for (const [k, v] of Object.entries(this.transaction_dt_map)) {
@@ -191,14 +173,9 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager {
// this.make_dt();
this.get_cleared_balance().then(() => {
this.cards_manager.$cards[1].set_value(
format_currency(this.cleared_balance),
this.currency
);
this.cards_manager.$cards[1].set_value(format_currency(this.cleared_balance), this.currency);
this.cards_manager.$cards[2].set_value(
format_currency(
this.bank_statement_closing_balance - this.cleared_balance
),
format_currency(this.bank_statement_closing_balance - this.cleared_balance),
this.currency
);
this.cards_manager.$cards[2].set_value_color(
@@ -212,14 +189,12 @@ erpnext.accounts.bank_reconciliation.DataTableManager = class DataTableManager {
get_cleared_balance() {
if (this.bank_account && this.bank_statement_to_date) {
return frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {
bank_account: this.bank_account,
till_date: this.bank_statement_to_date,
},
callback: (response) =>
(this.cleared_balance = response.message),
callback: (response) => (this.cleared_balance = response.message),
});
}
}

View File

@@ -1,7 +1,15 @@
frappe.provide("erpnext.accounts.bank_reconciliation");
erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
constructor(company, bank_account, bank_statement_from_date, bank_statement_to_date, filter_by_reference_date, from_reference_date, to_reference_date) {
constructor(
company,
bank_account,
bank_statement_from_date,
bank_statement_to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date
) {
this.bank_account = bank_account;
this.company = company;
this.make_dialog();
@@ -61,16 +69,15 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
get_linked_vouchers(document_types) {
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_linked_payments",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_linked_payments",
args: {
bank_transaction_name: this.bank_transaction_name,
document_types: document_types,
from_date: this.bank_statement_from_date,
to_date: this.bank_statement_to_date,
filter_by_reference_date: this.filter_by_reference_date,
from_reference_date:this.from_reference_date,
to_reference_date:this.to_reference_date
from_reference_date: this.from_reference_date,
to_reference_date: this.to_reference_date,
},
callback: (result) => {
@@ -105,7 +112,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
editable: false,
width: 1,
format: (value, row) => {
return frappe.form.formatters.Link(value, {options: row[2].content});
return frappe.form.formatters.Link(value, { options: row[2].content });
},
},
{
@@ -152,10 +159,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
checkboxColumn: true,
inlineFilters: true,
};
this.datatable = new frappe.DataTable(
proposals_wrapper.get(0),
datatable_options
);
this.datatable = new frappe.DataTable(proposals_wrapper.get(0), datatable_options);
} else {
this.datatable.refresh(this.data, this.columns);
this.datatable.rowmanager.checkMap = [];
@@ -217,10 +221,9 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
title: __("Reconcile the Bank Transaction"),
fields: fields,
size: "large",
primary_action: (values) =>
this.reconciliation_dialog_primary_action(values),
primary_action: (values) => this.reconciliation_dialog_primary_action(values),
});
}
},
});
}
@@ -255,7 +258,9 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
{
fieldtype: "HTML",
fieldname: "no_matching_vouchers",
options: __("<div class=\"text-muted text-center\">{0}</div>", [__("No Matching Vouchers Found")])
options: __('<div class="text-muted text-center">{0}</div>', [
__("No Matching Vouchers Found"),
]),
},
{
fieldtype: "Section Break",
@@ -299,8 +304,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
click: () => {
this.edit_in_full_page();
},
depends_on:
"eval:doc.action=='Create Voucher'",
depends_on: "eval:doc.action=='Create Voucher'",
},
{
fieldname: "column_break_7",
@@ -313,8 +317,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
label: "Journal Entry Type",
options:
"Journal Entry\nInter Company Journal Entry\nBank Entry\nCash Entry\nCredit Card Entry\nDebit Note\nCredit Note\nContra Entry\nExcise Entry\nWrite Off Entry\nOpening Entry\nDepreciation Entry\nExchange Rate Revaluation\nDeferred Revenue\nDeferred Expense",
depends_on:
"eval:doc.action=='Create Voucher' && doc.document_type=='Journal Entry'",
depends_on: "eval:doc.action=='Create Voucher' && doc.document_type=='Journal Entry'",
mandatory_depends_on:
"eval:doc.action=='Create Voucher' && doc.document_type=='Journal Entry'",
},
@@ -323,8 +326,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
fieldtype: "Link",
label: "Account",
options: "Account",
depends_on:
"eval:doc.action=='Create Voucher' && doc.document_type=='Journal Entry'",
depends_on: "eval:doc.action=='Create Voucher' && doc.document_type=='Journal Entry'",
mandatory_depends_on:
"eval:doc.action=='Create Voucher' && doc.document_type=='Journal Entry'",
get_query: () => {
@@ -342,14 +344,11 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
label: "Party Type",
options: "DocType",
mandatory_depends_on:
"eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'",
"eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'",
get_query: function () {
return {
filters: {
name: [
"in",
Object.keys(frappe.boot.party_account_types),
],
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
},
@@ -367,16 +366,14 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
fieldtype: "Link",
label: "Project",
options: "Project",
depends_on:
"eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'",
depends_on: "eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'",
},
{
fieldname: "cost_center",
fieldtype: "Link",
label: "Cost Center",
options: "Cost Center",
depends_on:
"eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'",
depends_on: "eval:doc.action=='Create Voucher' && doc.document_type=='Payment Entry'",
},
{
fieldtype: "Section Break",
@@ -435,7 +432,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
options: "Currency",
read_only: 1,
hidden: 1,
}
},
];
}
@@ -457,18 +454,11 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
reconciliation_dialog_primary_action(values) {
if (values.action == "Match Against Voucher") this.match(values);
if (
values.action == "Create Voucher" &&
values.document_type == "Payment Entry"
)
if (values.action == "Create Voucher" && values.document_type == "Payment Entry")
this.add_payment_entry(values);
if (
values.action == "Create Voucher" &&
values.document_type == "Journal Entry"
)
if (values.action == "Create Voucher" && values.document_type == "Journal Entry")
this.add_journal_entry(values);
else if (values.action == "Update Bank Transaction")
this.update_transaction(values);
else if (values.action == "Update Bank Transaction") this.update_transaction(values);
}
match() {
@@ -486,8 +476,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
});
});
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.reconcile_vouchers",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.reconcile_vouchers",
args: {
bank_transaction_name: this.bank_transaction.name,
vouchers: vouchers,
@@ -503,8 +492,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
add_payment_entry(values) {
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_payment_entry_bts",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_payment_entry_bts",
args: {
bank_transaction_name: this.bank_transaction.name,
reference_number: values.reference_number,
@@ -517,7 +505,9 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
cost_center: values.cost_center,
},
callback: (response) => {
const alert_string = __("Bank Transaction {0} added as Payment Entry", [this.bank_transaction.name]);
const alert_string = __("Bank Transaction {0} added as Payment Entry", [
this.bank_transaction.name,
]);
frappe.show_alert(alert_string);
this.update_dt_cards(response.message);
this.dialog.hide();
@@ -527,8 +517,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
add_journal_entry(values) {
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_journal_entry_bts",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_journal_entry_bts",
args: {
bank_transaction_name: this.bank_transaction.name,
reference_number: values.reference_number,
@@ -541,7 +530,9 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
second_account: values.second_account,
},
callback: (response) => {
const alert_string = __("Bank Transaction {0} added as Journal Entry", [this.bank_transaction.name]);
const alert_string = __("Bank Transaction {0} added as Journal Entry", [
this.bank_transaction.name,
]);
frappe.show_alert(alert_string);
this.update_dt_cards(response.message);
this.dialog.hide();
@@ -551,8 +542,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
update_transaction(values) {
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.update_bank_transaction",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.update_bank_transaction",
args: {
bank_transaction_name: this.bank_transaction.name,
reference_number: values.reference_number,
@@ -572,8 +562,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
const values = this.dialog.get_values(true);
if (values.document_type == "Payment Entry") {
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_payment_entry_bts",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_payment_entry_bts",
args: {
bank_transaction_name: this.bank_transaction.name,
reference_number: values.reference_number,
@@ -584,7 +573,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
mode_of_payment: values.mode_of_payment,
project: values.project,
cost_center: values.cost_center,
allow_edit: true
allow_edit: true,
},
callback: (r) => {
const doc = frappe.model.sync(r.message);
@@ -593,8 +582,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
});
} else {
frappe.call({
method:
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_journal_entry_bts",
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.create_journal_entry_bts",
args: {
bank_transaction_name: this.bank_transaction.name,
reference_number: values.reference_number,
@@ -605,7 +593,7 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
mode_of_payment: values.mode_of_payment,
entry_type: values.journal_entry_type,
second_account: values.second_account,
allow_edit: true
allow_edit: true,
},
callback: (r) => {
var doc = frappe.model.sync(r.message);
@@ -614,5 +602,4 @@ erpnext.accounts.bank_reconciliation.DialogManager = class DialogManager {
});
}
}
};

View File

@@ -26,8 +26,7 @@ erpnext.accounts.bank_reconciliation.NumberCardManager = class NumberCardManager
currency: this.currency,
},
{
value:
this.bank_statement_closing_balance - this.cleared_balance,
value: this.bank_statement_closing_balance - this.cleared_balance,
label: __("Difference"),
datatype: "Currency",
currency: this.currency,
@@ -41,11 +40,9 @@ erpnext.accounts.bank_reconciliation.NumberCardManager = class NumberCardManager
number_card.$card.appendTo(this.$summary);
});
this.$cards[2].set_value_color(
this.bank_statement_closing_balance - this.cleared_balance == 0
? "text-success"
: "text-danger"
this.bank_statement_closing_balance - this.cleared_balance == 0 ? "text-success" : "text-danger"
);
this.$summary.css({"border-bottom": "0px", "margin-left": "0px", "margin-right": "0px"});
this.$summary.css({ "border-bottom": "0px", "margin-left": "0px", "margin-right": "0px" });
this.$summary.show();
}
};
@@ -60,16 +57,10 @@ erpnext.accounts.NumberCard = class NumberCard {
}
set_value_color(color) {
this.$card
.find("div")
.removeClass("text-danger text-success")
.addClass(`${color}`);
this.$card.find("div").removeClass("text-danger text-success").addClass(`${color}`);
}
set_indicator(color) {
this.$card
.find("span")
.removeClass("indicator red green")
.addClass(`indicator ${color}`);
this.$card.find("span").removeClass("indicator red green").addClass(`indicator ${color}`);
}
};

View File

@@ -39,14 +39,14 @@ class BOMConfigurator {
edit_qty: this.edit_qty,
load_tree: this.load_tree,
set_default_qty: this.set_default_qty,
}
};
}
tree_options() {
return {
parent: this.$wrapper.get(0),
body: this.$wrapper.get(0),
doctype: 'BOM Configurator',
doctype: "BOM Configurator",
page: this.page,
expandable: true,
title: __("Configure Product Assembly"),
@@ -59,7 +59,7 @@ class BOMConfigurator {
extend_toolbar: false,
do_not_make_page: true,
do_not_setup_menu: true,
}
};
}
tree_methods() {
@@ -67,7 +67,7 @@ class BOMConfigurator {
let view = frappe.views.trees["BOM Configurator"];
return {
onload: function(me) {
onload: function (me) {
me.args["parent_id"] = frm_obj.frm.doc.name;
me.args["parent"] = frm_obj.frm.doc.item_code;
me.parent = frm_obj.$wrapper.get(0);
@@ -103,126 +103,133 @@ class BOMConfigurator {
`).insertBefore(node.$ul);
},
toolbar: this.frm?.doc.docstatus === 0 ? [
{
label:__(frappe.utils.icon('edit', 'sm') + " Qty"),
click: function(node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.edit_qty(node, view);
},
btnClass: "hidden-xs"
},
{
label:__(frappe.utils.icon('add', 'sm') + " Raw Material"),
click: function(node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.add_item(node, view);
},
condition: function(node) {
return node.expandable;
},
btnClass: "hidden-xs"
},
{
label:__(frappe.utils.icon('add', 'sm') + " Sub Assembly"),
click: function(node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.add_sub_assembly(node, view);
},
condition: function(node) {
return node.expandable;
},
btnClass: "hidden-xs"
},
{
label:__("Expand All"),
click: function(node) {
let view = frappe.views.trees["BOM Configurator"];
toolbar:
this.frm?.doc.docstatus === 0
? [
{
label: __(frappe.utils.icon("edit", "sm") + " Qty"),
click: function (node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.edit_qty(node, view);
},
btnClass: "hidden-xs",
},
{
label: __(frappe.utils.icon("add", "sm") + " Raw Material"),
click: function (node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.add_item(node, view);
},
condition: function (node) {
return node.expandable;
},
btnClass: "hidden-xs",
},
{
label: __(frappe.utils.icon("add", "sm") + " Sub Assembly"),
click: function (node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.add_sub_assembly(node, view);
},
condition: function (node) {
return node.expandable;
},
btnClass: "hidden-xs",
},
{
label: __("Expand All"),
click: function (node) {
let view = frappe.views.trees["BOM Configurator"];
if (!node.expanded) {
view.tree.load_children(node, true);
$(node.parent[0]).find(".tree-children").show();
node.$toolbar.find(".expand-all-btn").html("Collapse All");
} else {
node.$tree_link.trigger("click");
node.$toolbar.find(".expand-all-btn").html("Expand All");
}
},
condition: function(node) {
return node.expandable && node.is_root;
},
btnClass: "hidden-xs expand-all-btn"
},
{
label:__(frappe.utils.icon('move', 'sm') + " Sub Assembly"),
click: function(node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.convert_to_sub_assembly(node, view);
},
condition: function(node) {
return !node.expandable;
},
btnClass: "hidden-xs"
},
{
label:__(frappe.utils.icon('delete', 'sm') + __(" Item")),
click: function(node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.delete_node(node, view);
},
condition: function(node) {
return !node.is_root;
},
btnClass: "hidden-xs"
},
] : [{
label:__("Expand All"),
click: function(node) {
let view = frappe.views.trees["BOM Configurator"];
if (!node.expanded) {
view.tree.load_children(node, true);
$(node.parent[0]).find(".tree-children").show();
node.$toolbar.find(".expand-all-btn").html("Collapse All");
} else {
node.$tree_link.trigger("click");
node.$toolbar.find(".expand-all-btn").html("Expand All");
}
},
condition: function (node) {
return node.expandable && node.is_root;
},
btnClass: "hidden-xs expand-all-btn",
},
{
label: __(frappe.utils.icon("move", "sm") + " Sub Assembly"),
click: function (node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.convert_to_sub_assembly(node, view);
},
condition: function (node) {
return !node.expandable;
},
btnClass: "hidden-xs",
},
{
label: __(frappe.utils.icon("delete", "sm") + __(" Item")),
click: function (node) {
let view = frappe.views.trees["BOM Configurator"];
view.events.delete_node(node, view);
},
condition: function (node) {
return !node.is_root;
},
btnClass: "hidden-xs",
},
]
: [
{
label: __("Expand All"),
click: function (node) {
let view = frappe.views.trees["BOM Configurator"];
if (!node.expanded) {
view.tree.load_children(node, true);
$(node.parent[0]).find(".tree-children").show();
node.$toolbar.find(".expand-all-btn").html("Collapse All");
} else {
node.$tree_link.trigger("click");
node.$toolbar.find(".expand-all-btn").html("Expand All");
}
},
condition: function(node) {
return node.expandable && node.is_root;
},
btnClass: "hidden-xs expand-all-btn"
}],
}
if (!node.expanded) {
view.tree.load_children(node, true);
$(node.parent[0]).find(".tree-children").show();
node.$toolbar.find(".expand-all-btn").html("Collapse All");
} else {
node.$tree_link.trigger("click");
node.$toolbar.find(".expand-all-btn").html("Expand All");
}
},
condition: function (node) {
return node.expandable && node.is_root;
},
btnClass: "hidden-xs expand-all-btn",
},
],
};
}
add_item(node, view) {
frappe.prompt([
{ label: __("Item"), fieldname: "item_code", fieldtype: "Link", options: "Item", reqd: 1 },
{ label: __("Qty"), fieldname: "qty", default: 1.0, fieldtype: "Float", reqd: 1 },
],
(data) => {
if (!node.data.parent_id) {
node.data.parent_id = this.frm.doc.name;
}
frappe.call({
method: "erpnext.manufacturing.doctype.bom_creator.bom_creator.add_item",
args: {
parent: node.data.parent_id,
fg_item: node.data.value,
item_code: data.item_code,
fg_reference_id: node.data.name || this.frm.doc.name,
qty: data.qty,
},
callback: (r) => {
view.events.load_tree(r, node);
frappe.prompt(
[
{ label: __("Item"), fieldname: "item_code", fieldtype: "Link", options: "Item", reqd: 1 },
{ label: __("Qty"), fieldname: "qty", default: 1.0, fieldtype: "Float", reqd: 1 },
],
(data) => {
if (!node.data.parent_id) {
node.data.parent_id = this.frm.doc.name;
}
});
},
__("Add Item"),
__("Add"));
frappe.call({
method: "erpnext.manufacturing.doctype.bom_creator.bom_creator.add_item",
args: {
parent: node.data.parent_id,
fg_item: node.data.value,
item_code: data.item_code,
fg_reference_id: node.data.name || this.frm.doc.name,
qty: data.qty,
},
callback: (r) => {
view.events.load_tree(r, node);
},
});
},
__("Add Item"),
__("Add")
);
}
add_sub_assembly(node, view) {
@@ -251,27 +258,58 @@ class BOMConfigurator {
},
callback: (r) => {
view.events.load_tree(r, node);
}
},
});
dialog.hide();
});
}
get_sub_assembly_modal_fields(read_only=false) {
get_sub_assembly_modal_fields(read_only = false) {
return [
{ label: __("Sub Assembly Item"), fieldname: "item_code", fieldtype: "Link", options: "Item", reqd: 1, read_only: read_only },
{ fieldtype: "Column Break" },
{ label: __("Qty"), fieldname: "qty", default: 1.0, fieldtype: "Float", reqd: 1, read_only: read_only },
{ fieldtype: "Section Break" },
{ label: __("Raw Materials"), fieldname: "items", fieldtype: "Table", reqd: 1,
fields: [
{ label: __("Item"), fieldname: "item_code", fieldtype: "Link", options: "Item", reqd: 1, in_list_view: 1 },
{ label: __("Qty"), fieldname: "qty", default: 1.0, fieldtype: "Float", reqd: 1, in_list_view: 1 },
]
{
label: __("Sub Assembly Item"),
fieldname: "item_code",
fieldtype: "Link",
options: "Item",
reqd: 1,
read_only: read_only,
},
]
{ fieldtype: "Column Break" },
{
label: __("Qty"),
fieldname: "qty",
default: 1.0,
fieldtype: "Float",
reqd: 1,
read_only: read_only,
},
{ fieldtype: "Section Break" },
{
label: __("Raw Materials"),
fieldname: "items",
fieldtype: "Table",
reqd: 1,
fields: [
{
label: __("Item"),
fieldname: "item_code",
fieldtype: "Link",
options: "Item",
reqd: 1,
in_list_view: 1,
},
{
label: __("Qty"),
fieldname: "qty",
default: 1.0,
fieldtype: "Float",
reqd: 1,
in_list_view: 1,
},
],
},
];
}
convert_to_sub_assembly(node, view) {
@@ -303,7 +341,7 @@ class BOMConfigurator {
callback: (r) => {
node.expandable = true;
view.events.load_tree(r, node);
}
},
});
dialog.hide();
@@ -313,12 +351,12 @@ class BOMConfigurator {
set_default_qty(dialog) {
dialog.fields_dict.items.grid.fields_map.item_code.onchange = function (event) {
if (event) {
let name = $(event.currentTarget).closest('.grid-row').attr("data-name")
let name = $(event.currentTarget).closest(".grid-row").attr("data-name");
let item_row = dialog.fields_dict.items.grid.grid_rows_by_docname[name].doc;
item_row.qty = 1;
dialog.fields_dict.items.grid.refresh()
dialog.fields_dict.items.grid.refresh();
}
}
};
}
delete_node(node, view) {
@@ -333,38 +371,40 @@ class BOMConfigurator {
},
callback: (r) => {
view.events.load_tree(r, node.parent_node);
}
},
});
});
}
edit_qty(node, view) {
let qty = node.data.qty || this.frm.doc.qty;
frappe.prompt([
{ label: __("Qty"), fieldname: "qty", default: qty, fieldtype: "Float", reqd: 1 },
],
(data) => {
let doctype = node.data.doctype || this.frm.doc.doctype;
let docname = node.data.name || this.frm.doc.name;
frappe.prompt(
[{ label: __("Qty"), fieldname: "qty", default: qty, fieldtype: "Float", reqd: 1 }],
(data) => {
let doctype = node.data.doctype || this.frm.doc.doctype;
let docname = node.data.name || this.frm.doc.name;
frappe.call({
method: "erpnext.manufacturing.doctype.bom_creator.bom_creator.edit_qty",
args: {
doctype: doctype,
docname: docname,
qty: data.qty,
parent: node.data.parent_id,
},
callback: (r) => {
node.data.qty = data.qty;
let uom = node.data.uom || this.frm.doc.uom;
$(node.parent.get(0)).find(`[data-bom-qty-docname='${docname}']`).html(data.qty + " " + uom);
view.events.load_tree(r, node);
}
});
},
__("Edit Qty"),
__("Update"));
frappe.call({
method: "erpnext.manufacturing.doctype.bom_creator.bom_creator.edit_qty",
args: {
doctype: doctype,
docname: docname,
qty: data.qty,
parent: node.data.parent_id,
},
callback: (r) => {
node.data.qty = data.qty;
let uom = node.data.uom || this.frm.doc.uom;
$(node.parent.get(0))
.find(`[data-bom-qty-docname='${docname}']`)
.html(data.qty + " " + uom);
view.events.load_tree(r, node);
},
});
},
__("Edit Qty"),
__("Update")
);
}
prepare_layout() {
@@ -378,35 +418,31 @@ class BOMConfigurator {
load_tree(response, node) {
let item_row = "";
let parent_dom = ""
let parent_dom = "";
let total_amount = response.message.raw_material_cost;
frappe.views.trees["BOM Configurator"].tree.load_children(node);
while (node) {
item_row = response.message.items.filter(item => item.name === node.data.name);
item_row = response.message.items.filter((item) => item.name === node.data.name);
if (item_row?.length) {
node.data.amount = item_row[0].amount;
total_amount = node.data.amount
total_amount = node.data.amount;
} else {
total_amount = response.message.raw_material_cost;
}
parent_dom = $(node.parent.get(0));
total_amount = frappe.format(
total_amount, {
fieldtype: "Currency",
currency: this.frm.doc.currency
}
);
total_amount = frappe.format(total_amount, {
fieldtype: "Currency",
currency: this.frm.doc.currency,
});
$($(parent_dom).find(".fg-item-amt")[0]).html(total_amount);
node = node.parent_node;
}
}
}
frappe.ui.BOMConfigurator = BOMConfigurator;
frappe.ui.BOMConfigurator = BOMConfigurator;

View File

@@ -1,30 +1,33 @@
frappe.provide("erpnext.bulk_transaction_processing");
$.extend(erpnext.bulk_transaction_processing, {
create: function(listview, from_doctype, to_doctype) {
create: function (listview, from_doctype, to_doctype) {
let checked_items = listview.get_checked_items();
const doc_name = [];
checked_items.forEach((Item)=> {
checked_items.forEach((Item) => {
if (Item.docstatus == 0) {
doc_name.push(Item.name);
}
});
let count_of_rows = checked_items.length;
frappe.confirm(__("Create {0} {1} ?", [count_of_rows, __(to_doctype)]), ()=>{
frappe.confirm(__("Create {0} {1} ?", [count_of_rows, __(to_doctype)]), () => {
if (doc_name.length == 0) {
frappe.call({
method: "erpnext.utilities.bulk_transaction.transaction_processing",
args: {data: checked_items, from_doctype: from_doctype, to_doctype: to_doctype}
}).then(()=> {
});
frappe
.call({
method: "erpnext.utilities.bulk_transaction.transaction_processing",
args: { data: checked_items, from_doctype: from_doctype, to_doctype: to_doctype },
})
.then(() => {});
if (count_of_rows > 10) {
frappe.show_alert("Starting a background job to create {0} {1}", [count_of_rows, __(to_doctype)]);
frappe.show_alert("Starting a background job to create {0} {1}", [
count_of_rows,
__(to_doctype),
]);
}
} else {
frappe.msgprint(__("Selected document must be in submitted state"));
}
});
}
},
});

View File

@@ -7,17 +7,17 @@ class CallPopup {
}
make() {
frappe.utils.play_sound('incoming-call');
frappe.utils.play_sound("incoming-call");
this.dialog = new frappe.ui.Dialog({
'static': true,
'minimizable': true
static: true,
minimizable: true,
});
this.dialog.get_close_btn().show();
this.setup_dialog();
this.set_call_status();
frappe.utils.bind_actions_with_object(this.dialog.$body, this);
this.dialog.$wrapper.addClass('call-popup');
this.dialog.get_close_btn().unbind('click').click(this.close_modal.bind(this));
this.dialog.$wrapper.addClass("call-popup");
this.dialog.get_close_btn().unbind("click").click(this.close_modal.bind(this));
this.dialog.show();
}
@@ -26,28 +26,28 @@ class CallPopup {
this.dialog.$body.empty().append(this.caller_info);
}
set_indicator(color, blink=false) {
let classes = `indicator ${color} ${blink ? 'blink': ''}`;
this.dialog.header.find('.indicator').attr('class', classes);
set_indicator(color, blink = false) {
let classes = `indicator ${color} ${blink ? "blink" : ""}`;
this.dialog.header.find(".indicator").attr("class", classes);
}
set_call_status(call_status) {
let title = '';
let title = "";
call_status = call_status || this.call_log.status;
if (['Ringing'].includes(call_status) || !call_status) {
title = __('Incoming call from {0}', [this.get_caller_name() || this.caller_number]);
this.set_indicator('blue', true);
} else if (call_status === 'In Progress') {
title = __('Call Connected');
this.set_indicator('green');
} else if (['No Answer', 'Missed'].includes(call_status)) {
this.set_indicator('yellow');
title = __('Call Missed');
} else if (['Completed', 'Busy', 'Failed'].includes(call_status)) {
this.set_indicator('red');
title = __('Call Ended');
if (["Ringing"].includes(call_status) || !call_status) {
title = __("Incoming call from {0}", [this.get_caller_name() || this.caller_number]);
this.set_indicator("blue", true);
} else if (call_status === "In Progress") {
title = __("Call Connected");
this.set_indicator("green");
} else if (["No Answer", "Missed"].includes(call_status)) {
this.set_indicator("yellow");
title = __("Call Missed");
} else if (["Completed", "Busy", "Failed"].includes(call_status)) {
this.set_indicator("red");
title = __("Call Ended");
} else {
this.set_indicator('blue');
this.set_indicator("blue");
title = call_status;
}
this.dialog.set_title(title);
@@ -55,7 +55,7 @@ class CallPopup {
update_call_log(call_log, missed) {
this.call_log = call_log;
this.set_call_status(missed ? 'Missed': null);
this.set_call_status(missed ? "Missed" : null);
}
close_modal() {
@@ -64,10 +64,10 @@ class CallPopup {
}
call_ended(call_log, missed) {
frappe.utils.play_sound('call-disconnect');
frappe.utils.play_sound("call-disconnect");
this.update_call_log(call_log, missed);
setTimeout(() => {
if (!this.dialog.get_value('call_summary')) {
if (!this.dialog.get_value("call_summary")) {
this.close_modal();
}
}, 60000);
@@ -81,16 +81,16 @@ class CallPopup {
get_contact_link() {
let log = this.call_log;
let contact_link = log.links.find(d => d.link_doctype === 'Contact');
let contact_link = log.links.find((d) => d.link_doctype === "Contact");
return contact_link || {};
}
setup_listener() {
frappe.realtime.on(`call_${this.call_log.id}_ended`, call_log => {
frappe.realtime.on(`call_${this.call_log.id}_ended`, (call_log) => {
this.call_ended(call_log);
});
frappe.realtime.on(`call_${this.call_log.id}_missed`, call_log => {
frappe.realtime.on(`call_${this.call_log.id}_missed`, (call_log) => {
this.call_ended(call_log, true);
});
}
@@ -103,84 +103,102 @@ class CallPopup {
setup_call_details() {
this.caller_info = $(`<div></div>`);
this.call_details = new frappe.ui.FieldGroup({
fields: [{
'fieldname': 'name',
'label': 'Name',
'default': this.get_caller_name() || __('Unknown Caller'),
'fieldtype': 'Data',
'read_only': 1
}, {
'fieldtype': 'Button',
'label': __('Open Contact'),
'click': () => frappe.set_route('Form', 'Contact', this.get_contact_link().link_name),
'depends_on': () => this.get_caller_name()
}, {
'fieldtype': 'Button',
'label': __('Create New Contact'),
'click': this.create_new_contact.bind(this),
'depends_on': () => !this.get_caller_name()
}, {
'fieldtype': 'Button',
'label': __('Create New Customer'),
'click': this.create_new_customer.bind(this),
'depends_on': () => !this.get_caller_name()
}, {
'fieldtype': 'Button',
'label': __('Create New Lead'),
'click': () => frappe.new_doc('Lead', { 'mobile_no': this.caller_number }),
'depends_on': () => !this.get_caller_name()
}, {
'fieldtype': 'Column Break',
}, {
'fieldname': 'number',
'label': 'Phone Number',
'fieldtype': 'Data',
'default': this.caller_number,
'read_only': 1
}, {
'fieldtype': 'Section Break',
'hide_border': 1,
}, {
'fieldname': 'call_type',
'label': 'Call Type',
'fieldtype': 'Link',
'options': 'Telephony Call Type',
}, {
'fieldtype': 'Section Break',
'hide_border': 1,
}, {
'fieldtype': 'Small Text',
'label': __('Call Summary'),
'fieldname': 'call_summary',
}, {
'fieldtype': 'Button',
'label': __('Save'),
'click': () => {
const call_summary = this.call_details.get_value('call_summary');
const call_type = this.call_details.get_value('call_type');
if (!call_summary) return;
frappe.xcall('erpnext.telephony.doctype.call_log.call_log.add_call_summary_and_call_type', {
'call_log': this.call_log.name,
'summary': call_summary,
'call_type': call_type,
}).then(() => {
this.close_modal();
frappe.show_alert({
message: `
${__('Call Summary Saved')}
fields: [
{
fieldname: "name",
label: "Name",
default: this.get_caller_name() || __("Unknown Caller"),
fieldtype: "Data",
read_only: 1,
},
{
fieldtype: "Button",
label: __("Open Contact"),
click: () => frappe.set_route("Form", "Contact", this.get_contact_link().link_name),
depends_on: () => this.get_caller_name(),
},
{
fieldtype: "Button",
label: __("Create New Contact"),
click: this.create_new_contact.bind(this),
depends_on: () => !this.get_caller_name(),
},
{
fieldtype: "Button",
label: __("Create New Customer"),
click: this.create_new_customer.bind(this),
depends_on: () => !this.get_caller_name(),
},
{
fieldtype: "Button",
label: __("Create New Lead"),
click: () => frappe.new_doc("Lead", { mobile_no: this.caller_number }),
depends_on: () => !this.get_caller_name(),
},
{
fieldtype: "Column Break",
},
{
fieldname: "number",
label: "Phone Number",
fieldtype: "Data",
default: this.caller_number,
read_only: 1,
},
{
fieldtype: "Section Break",
hide_border: 1,
},
{
fieldname: "call_type",
label: "Call Type",
fieldtype: "Link",
options: "Telephony Call Type",
},
{
fieldtype: "Section Break",
hide_border: 1,
},
{
fieldtype: "Small Text",
label: __("Call Summary"),
fieldname: "call_summary",
},
{
fieldtype: "Button",
label: __("Save"),
click: () => {
const call_summary = this.call_details.get_value("call_summary");
const call_type = this.call_details.get_value("call_type");
if (!call_summary) return;
frappe
.xcall(
"erpnext.telephony.doctype.call_log.call_log.add_call_summary_and_call_type",
{
call_log: this.call_log.name,
summary: call_summary,
call_type: call_type,
}
)
.then(() => {
this.close_modal();
frappe.show_alert({
message: `
${__("Call Summary Saved")}
<br>
<a
class="text-small text-muted"
href="/app/call-log/${this.call_log.name}">
${__('View call log')}
${__("View call log")}
</a>
`,
indicator: 'green'
});
});
}
}],
body: this.caller_info
indicator: "green",
});
});
},
},
],
body: this.caller_info,
});
this.call_details.make();
}
@@ -191,23 +209,23 @@ class CallPopup {
create_new_customer() {
// to avoid quick entry form
const new_customer = frappe.model.get_new_doc('Customer');
const new_customer = frappe.model.get_new_doc("Customer");
new_customer.mobile_no = this.caller_number;
frappe.set_route('Form', new_customer.doctype, new_customer.name);
frappe.set_route("Form", new_customer.doctype, new_customer.name);
}
create_new_contact() {
// TODO: fix new_doc, it should accept child table values
const new_contact = frappe.model.get_new_doc('Contact');
const phone_no = frappe.model.add_child(new_contact, 'Contact Phone', 'phone_nos');
const new_contact = frappe.model.get_new_doc("Contact");
const phone_no = frappe.model.add_child(new_contact, "Contact Phone", "phone_nos");
phone_no.phone = this.caller_number;
phone_no.is_primary_mobile_no = 1;
frappe.set_route('Form', new_contact.doctype, new_contact.name);
frappe.set_route("Form", new_contact.doctype, new_contact.name);
}
}
$(document).on('app_ready', function () {
frappe.realtime.on('show_call_popup', call_log => {
$(document).on("app_ready", function () {
frappe.realtime.on("show_call_popup", (call_log) => {
let call_popup = erpnext.call_popup;
if (call_popup && call_log.name === call_popup.call_log.name) {
call_popup.update_call_log(call_log);

View File

@@ -1,33 +1,45 @@
frappe.ui.form.on("Communication", {
refresh: (frm) => {
// setup custom Make button only if Communication is Email
if(frm.doc.communication_medium == "Email" && frm.doc.sent_or_received == "Received") {
if (frm.doc.communication_medium == "Email" && frm.doc.sent_or_received == "Received") {
frm.events.setup_custom_buttons(frm);
}
},
setup_custom_buttons: (frm) => {
let confirm_msg = "Are you sure you want to create {0} from this email?";
if(frm.doc.reference_doctype !== "Issue") {
frm.add_custom_button(__("Issue"), () => {
frappe.confirm(__(confirm_msg, [__("Issue")]), () => {
frm.trigger('make_issue_from_communication');
})
}, __("Create"));
if (frm.doc.reference_doctype !== "Issue") {
frm.add_custom_button(
__("Issue"),
() => {
frappe.confirm(__(confirm_msg, [__("Issue")]), () => {
frm.trigger("make_issue_from_communication");
});
},
__("Create")
);
}
if(!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) {
frm.add_custom_button(__("Lead"), () => {
frappe.confirm(__(confirm_msg, [__("Lead")]), () => {
frm.trigger('make_lead_from_communication');
})
}, __('Create'));
if (!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) {
frm.add_custom_button(
__("Lead"),
() => {
frappe.confirm(__(confirm_msg, [__("Lead")]), () => {
frm.trigger("make_lead_from_communication");
});
},
__("Create")
);
frm.add_custom_button(__("Opportunity"), () => {
frappe.confirm(__(confirm_msg, [__("Opportunity")]), () => {
frm.trigger('make_opportunity_from_communication');
})
}, __('Create'));
frm.add_custom_button(
__("Opportunity"),
() => {
frappe.confirm(__(confirm_msg, [__("Opportunity")]), () => {
frm.trigger("make_opportunity_from_communication");
});
},
__("Create")
);
}
},
@@ -35,63 +47,69 @@ frappe.ui.form.on("Communication", {
return frappe.call({
method: "erpnext.crm.doctype.lead.lead.make_lead_from_communication",
args: {
communication: frm.doc.name
communication: frm.doc.name,
},
freeze: true,
callback: (r) => {
if(r.message) {
frm.reload_doc()
if (r.message) {
frm.reload_doc();
}
}
})
},
});
},
make_issue_from_communication: (frm) => {
return frappe.call({
method: "erpnext.support.doctype.issue.issue.make_issue_from_communication",
args: {
communication: frm.doc.name
communication: frm.doc.name,
},
freeze: true,
callback: (r) => {
if(r.message) {
frm.reload_doc()
if (r.message) {
frm.reload_doc();
}
}
})
},
});
},
make_opportunity_from_communication: (frm) => {
const fields = [{
fieldtype: 'Link',
label: __('Select a Company'),
fieldname: 'company',
options: 'Company',
reqd: 1,
default: frappe.defaults.get_user_default("Company")
}];
const fields = [
{
fieldtype: "Link",
label: __("Select a Company"),
fieldname: "company",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("Company"),
},
];
frappe.prompt(fields, data => {
frappe.call({
method: "erpnext.crm.doctype.opportunity.opportunity.make_opportunity_from_communication",
args: {
communication: frm.doc.name,
company: data.company
},
freeze: true,
callback: (r) => {
if(r.message) {
frm.reload_doc();
frappe.show_alert({
message: __("Opportunity {0} created",
['<a href="/app/opportunity/'+r.message+'">' + r.message + '</a>']),
indicator: 'green'
});
}
}
});
},
'Create an Opportunity',
'Create');
}
frappe.prompt(
fields,
(data) => {
frappe.call({
method: "erpnext.crm.doctype.opportunity.opportunity.make_opportunity_from_communication",
args: {
communication: frm.doc.name,
company: data.company,
},
freeze: true,
callback: (r) => {
if (r.message) {
frm.reload_doc();
frappe.show_alert({
message: __("Opportunity {0} created", [
'<a href="/app/opportunity/' + r.message + '">' + r.message + "</a>",
]),
indicator: "green",
});
}
},
});
},
"Create an Opportunity",
"Create"
);
},
});

View File

@@ -1,26 +1,26 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.provide('erpnext');
frappe.provide("erpnext");
// preferred modules for breadcrumbs
$.extend(frappe.breadcrumbs.preferred, {
"Item Group": "Stock",
"Customer Group": "Selling",
"Supplier Group": "Buying",
"Territory": "Selling",
Territory: "Selling",
"Sales Person": "Selling",
"Sales Partner": "Selling",
"Brand": "Stock",
Brand: "Stock",
"Maintenance Schedule": "Support",
"Maintenance Visit": "Support"
"Maintenance Visit": "Support",
});
$.extend(frappe.breadcrumbs.module_map, {
'ERPNext Integrations': 'Integrations',
'Geo': 'Settings',
'Portal': 'Website',
'Utilities': 'Settings',
'E-commerce': 'Website',
'Contacts': 'CRM'
"ERPNext Integrations": "Integrations",
Geo: "Settings",
Portal: "Website",
Utilities: "Settings",
"E-commerce": "Website",
Contacts: "CRM",
});

View File

@@ -1,16 +1,14 @@
frappe.ui.form.on("Contact", {
refresh(frm) {
frm.set_query('link_doctype', "links", function() {
frm.set_query("link_doctype", "links", function () {
return {
query: "frappe.contacts.address_and_contact.filter_dynamic_link_doctypes",
filters: {
fieldtype: ["in", ["HTML", "Text Editor"]],
fieldname: ["in", ["contact_html", "company_description"]],
}
},
};
});
frm.refresh_field("links");
}
},
});

View File

@@ -27,7 +27,7 @@ import "./bulk_transaction_processing";
import "./utils/crm_activities";
import "./templates/crm_activities.html";
import "./templates/crm_notes.html";
import "./controllers/accounts.js"
import "./controllers/accounts.js";
import "./utils/landed_taxes_and_charges_common.js";
import "./utils/sales_common.js";
import "./controllers/buying.js";

View File

@@ -3,33 +3,53 @@
frappe.provide("frappe.desk");
frappe.ui.form.on("Event", {
refresh: function(frm) {
frm.set_query('reference_doctype', "event_participants", function() {
refresh: function (frm) {
frm.set_query("reference_doctype", "event_participants", function () {
return {
"filters": {
"name": ["in", ["Contact", "Lead", "Customer", "Supplier", "Employee", "Sales Partner"]]
}
filters: {
name: ["in", ["Contact", "Lead", "Customer", "Supplier", "Employee", "Sales Partner"]],
},
};
});
frm.add_custom_button(__('Add Leads'), function() {
new frappe.desk.eventParticipants(frm, "Lead");
}, __("Add Participants"));
frm.add_custom_button(
__("Add Leads"),
function () {
new frappe.desk.eventParticipants(frm, "Lead");
},
__("Add Participants")
);
frm.add_custom_button(__('Add Customers'), function() {
new frappe.desk.eventParticipants(frm, "Customer");
}, __("Add Participants"));
frm.add_custom_button(
__("Add Customers"),
function () {
new frappe.desk.eventParticipants(frm, "Customer");
},
__("Add Participants")
);
frm.add_custom_button(__('Add Suppliers'), function() {
new frappe.desk.eventParticipants(frm, "Supplier");
}, __("Add Participants"));
frm.add_custom_button(
__("Add Suppliers"),
function () {
new frappe.desk.eventParticipants(frm, "Supplier");
},
__("Add Participants")
);
frm.add_custom_button(__('Add Employees'), function() {
new frappe.desk.eventParticipants(frm, "Employee");
}, __("Add Participants"));
frm.add_custom_button(
__("Add Employees"),
function () {
new frappe.desk.eventParticipants(frm, "Employee");
},
__("Add Participants")
);
frm.add_custom_button(__('Add Sales Partners'), function() {
new frappe.desk.eventParticipants(frm, "Sales Partners");
}, __("Add Participants"));
}
frm.add_custom_button(
__("Add Sales Partners"),
function () {
new frappe.desk.eventParticipants(frm, "Sales Partners");
},
__("Add Participants")
);
},
});

View File

@@ -1,60 +1,58 @@
frappe.provide("erpnext.financial_statements");
erpnext.financial_statements = {
"filters": get_filters(),
"baseData": null,
"formatter": function(value, row, column, data, default_formatter, filter) {
if(frappe.query_report.get_filter_value("selected_view") == "Growth" && data && column.colIndex >= 3){
filters: get_filters(),
baseData: null,
formatter: function (value, row, column, data, default_formatter, filter) {
if (
frappe.query_report.get_filter_value("selected_view") == "Growth" &&
data &&
column.colIndex >= 3
) {
//Assuming that the first three columns are s.no, account name and the very first year of the accounting values, to calculate the relative percentage values of the successive columns.
const lastAnnualValue = row[column.colIndex - 1].content;
const currentAnnualvalue = data[column.fieldname];
if(currentAnnualvalue == undefined) return 'NA'; //making this not applicable for undefined/null values
if (currentAnnualvalue == undefined) return "NA"; //making this not applicable for undefined/null values
let annualGrowth = 0;
if(lastAnnualValue == 0 && currentAnnualvalue > 0){
if (lastAnnualValue == 0 && currentAnnualvalue > 0) {
//If the previous year value is 0 and the current value is greater than 0
annualGrowth = 1;
}
else if(lastAnnualValue > 0){
annualGrowth = (currentAnnualvalue - lastAnnualValue) / lastAnnualValue;
} else if (lastAnnualValue > 0) {
annualGrowth = (currentAnnualvalue - lastAnnualValue) / lastAnnualValue;
}
const growthPercent = (Math.round(annualGrowth*10000)/100); //calculating the rounded off percentage
const growthPercent = Math.round(annualGrowth * 10000) / 100; //calculating the rounded off percentage
value = $(`<span>${((growthPercent >=0)? '+':'' )+growthPercent+'%'}</span>`);
if(growthPercent < 0){
value = $(`<span>${(growthPercent >= 0 ? "+" : "") + growthPercent + "%"}</span>`);
if (growthPercent < 0) {
value = $(value).addClass("text-danger");
}
else{
} else {
value = $(value).addClass("text-success");
}
value = $(value).wrap("<p></p>").parent().html();
return value;
}
else if(frappe.query_report.get_filter_value("selected_view") == "Margin" && data){
if(column.fieldname =="account" && data.account_name == __("Income")){
} else if (frappe.query_report.get_filter_value("selected_view") == "Margin" && data) {
if (column.fieldname == "account" && data.account_name == __("Income")) {
//Taking the total income from each column (for all the financial years) as the base (100%)
this.baseData = row;
}
if(column.colIndex >= 2){
if (column.colIndex >= 2) {
//Assuming that the first two columns are s.no and account name, to calculate the relative percentage values of the successive columns.
const currentAnnualvalue = data[column.fieldname];
const baseValue = this.baseData[column.colIndex].content;
if(currentAnnualvalue == undefined || baseValue <= 0) return 'NA';
const marginPercent = Math.round((currentAnnualvalue/baseValue)*10000)/100;
if (currentAnnualvalue == undefined || baseValue <= 0) return "NA";
const marginPercent = Math.round((currentAnnualvalue / baseValue) * 10000) / 100;
value = $(`<span>${marginPercent+'%'}</span>`);
if(marginPercent < 0)
value = $(value).addClass("text-danger");
else
value = $(value).addClass("text-success");
value = $(`<span>${marginPercent + "%"}</span>`);
if (marginPercent < 0) value = $(value).addClass("text-danger");
else value = $(value).addClass("text-success");
value = $(value).wrap("<p></p>").parent().html();
return value;
}
}
if (data && column.fieldname=="account") {
if (data && column.fieldname == "account") {
value = data.account_name || value;
if (filter && filter?.text && filter?.type == "contains") {
@@ -85,16 +83,18 @@ erpnext.financial_statements = {
return value;
},
"open_general_ledger": function(data) {
open_general_ledger: function (data) {
if (!data.account) return;
let project = $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; });
let project = $.grep(frappe.query_report.filters, function (e) {
return e.df.fieldname == "project";
});
frappe.route_options = {
"account": data.account,
"company": frappe.query_report.get_filter_value('company'),
"from_date": data.from_date || data.year_start_date,
"to_date": data.to_date || data.year_end_date,
"project": (project && project.length > 0) ? project[0].$input.val() : ""
account: data.account,
company: frappe.query_report.get_filter_value("company"),
from_date: data.from_date || data.year_start_date,
to_date: data.to_date || data.year_end_date,
project: project && project.length > 0 ? project[0].$input.val() : "",
};
let report = "General Ledger";
@@ -107,159 +107,172 @@ erpnext.financial_statements = {
frappe.set_route("query-report", report);
},
"tree": true,
"name_field": "account",
"parent_field": "parent_account",
"initial_depth": 3,
onload: function(report) {
tree: true,
name_field: "account",
parent_field: "parent_account",
initial_depth: 3,
onload: function (report) {
// dropdown for links to other financial statements
erpnext.financial_statements.filters = get_filters()
erpnext.financial_statements.filters = get_filters();
let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today());
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
frappe.model.with_doc("Fiscal Year", fiscal_year, function (r) {
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
frappe.query_report.set_filter_value({
period_start_date: fy.year_start_date,
period_end_date: fy.year_end_date
period_end_date: fy.year_end_date,
});
});
if (report.page){
const views_menu = report.page.add_custom_button_group(__('Financial Statements'));
if (report.page) {
const views_menu = report.page.add_custom_button_group(__("Financial Statements"));
report.page.add_custom_menu_item(views_menu, __("Balance Sheet"), function() {
report.page.add_custom_menu_item(views_menu, __("Balance Sheet"), function () {
var filters = report.get_values();
frappe.set_route('query-report', 'Balance Sheet', {company: filters.company});
frappe.set_route("query-report", "Balance Sheet", { company: filters.company });
});
report.page.add_custom_menu_item(views_menu, __("Profit and Loss"), function() {
report.page.add_custom_menu_item(views_menu, __("Profit and Loss"), function () {
var filters = report.get_values();
frappe.set_route('query-report', 'Profit and Loss Statement', {company: filters.company});
frappe.set_route("query-report", "Profit and Loss Statement", { company: filters.company });
});
report.page.add_custom_menu_item(views_menu, __("Cash Flow Statement"), function() {
report.page.add_custom_menu_item(views_menu, __("Cash Flow Statement"), function () {
var filters = report.get_values();
frappe.set_route('query-report', 'Cash Flow', {company: filters.company});
frappe.set_route("query-report", "Cash Flow", { company: filters.company });
});
}
}
},
};
function get_filters() {
let filters = [
{
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company"),
"reqd": 1
fieldname: "company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
reqd: 1,
},
{
"fieldname":"finance_book",
"label": __("Finance Book"),
"fieldtype": "Link",
"options": "Finance Book"
fieldname: "finance_book",
label: __("Finance Book"),
fieldtype: "Link",
options: "Finance Book",
},
{
"fieldname":"filter_based_on",
"label": __("Filter Based On"),
"fieldtype": "Select",
"options": ["Fiscal Year", "Date Range"],
"default": ["Fiscal Year"],
"reqd": 1,
on_change: function() {
let filter_based_on = frappe.query_report.get_filter_value('filter_based_on');
frappe.query_report.toggle_filter_display('from_fiscal_year', filter_based_on === 'Date Range');
frappe.query_report.toggle_filter_display('to_fiscal_year', filter_based_on === 'Date Range');
frappe.query_report.toggle_filter_display('period_start_date', filter_based_on === 'Fiscal Year');
frappe.query_report.toggle_filter_display('period_end_date', filter_based_on === 'Fiscal Year');
fieldname: "filter_based_on",
label: __("Filter Based On"),
fieldtype: "Select",
options: ["Fiscal Year", "Date Range"],
default: ["Fiscal Year"],
reqd: 1,
on_change: function () {
let filter_based_on = frappe.query_report.get_filter_value("filter_based_on");
frappe.query_report.toggle_filter_display(
"from_fiscal_year",
filter_based_on === "Date Range"
);
frappe.query_report.toggle_filter_display("to_fiscal_year", filter_based_on === "Date Range");
frappe.query_report.toggle_filter_display(
"period_start_date",
filter_based_on === "Fiscal Year"
);
frappe.query_report.toggle_filter_display(
"period_end_date",
filter_based_on === "Fiscal Year"
);
frappe.query_report.refresh();
}
},
},
{
"fieldname":"period_start_date",
"label": __("Start Date"),
"fieldtype": "Date",
"reqd": 1,
"depends_on": "eval:doc.filter_based_on == 'Date Range'"
fieldname: "period_start_date",
label: __("Start Date"),
fieldtype: "Date",
reqd: 1,
depends_on: "eval:doc.filter_based_on == 'Date Range'",
},
{
"fieldname":"period_end_date",
"label": __("End Date"),
"fieldtype": "Date",
"reqd": 1,
"depends_on": "eval:doc.filter_based_on == 'Date Range'"
fieldname: "period_end_date",
label: __("End Date"),
fieldtype: "Date",
reqd: 1,
depends_on: "eval:doc.filter_based_on == 'Date Range'",
},
{
"fieldname":"from_fiscal_year",
"label": __("Start Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"reqd": 1,
"depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
fieldname: "from_fiscal_year",
label: __("Start Year"),
fieldtype: "Link",
options: "Fiscal Year",
reqd: 1,
depends_on: "eval:doc.filter_based_on == 'Fiscal Year'",
},
{
"fieldname":"to_fiscal_year",
"label": __("End Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"reqd": 1,
"depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
fieldname: "to_fiscal_year",
label: __("End Year"),
fieldtype: "Link",
options: "Fiscal Year",
reqd: 1,
depends_on: "eval:doc.filter_based_on == 'Fiscal Year'",
},
{
"fieldname": "periodicity",
"label": __("Periodicity"),
"fieldtype": "Select",
"options": [
{ "value": "Monthly", "label": __("Monthly") },
{ "value": "Quarterly", "label": __("Quarterly") },
{ "value": "Half-Yearly", "label": __("Half-Yearly") },
{ "value": "Yearly", "label": __("Yearly") }
fieldname: "periodicity",
label: __("Periodicity"),
fieldtype: "Select",
options: [
{ value: "Monthly", label: __("Monthly") },
{ value: "Quarterly", label: __("Quarterly") },
{ value: "Half-Yearly", label: __("Half-Yearly") },
{ value: "Yearly", label: __("Yearly") },
],
"default": "Yearly",
"reqd": 1
default: "Yearly",
reqd: 1,
},
// Note:
// If you are modifying this array such that the presentation_currency object
// is no longer the last object, please make adjustments in cash_flow.js
// accordingly.
{
"fieldname": "presentation_currency",
"label": __("Currency"),
"fieldtype": "Select",
"options": erpnext.get_presentation_currency_list()
fieldname: "presentation_currency",
label: __("Currency"),
fieldtype: "Select",
options: erpnext.get_presentation_currency_list(),
},
{
"fieldname": "cost_center",
"label": __("Cost Center"),
"fieldtype": "MultiSelectList",
get_data: function(txt) {
return frappe.db.get_link_options('Cost Center', txt, {
company: frappe.query_report.get_filter_value("company")
});
}
},
{
"fieldname": "project",
"label": __("Project"),
"fieldtype": "MultiSelectList",
get_data: function(txt) {
return frappe.db.get_link_options('Project', txt, {
company: frappe.query_report.get_filter_value("company")
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Cost Center", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
}
]
},
{
fieldname: "project",
label: __("Project"),
fieldtype: "MultiSelectList",
get_data: function (txt) {
return frappe.db.get_link_options("Project", txt, {
company: frappe.query_report.get_filter_value("company"),
});
},
},
];
// Dynamically set 'default' values for fiscal year filters
let fy_filters = filters.filter(x=>{return ["from_fiscal_year", "to_fiscal_year"].includes(x.fieldname);})
let fy_filters = filters.filter((x) => {
return ["from_fiscal_year", "to_fiscal_year"].includes(x.fieldname);
});
let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), false, true);
if (fiscal_year) {
let fy = erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), false, false);
fy_filters.forEach(x=>{x.default = fy;})
fy_filters.forEach((x) => {
x.default = fy;
});
}
return filters;

View File

@@ -332,13 +332,9 @@ frappe.help.help_links["Form/Selling Settings"] = [
//Buying
frappe.help.help_links["List/Supplier"] = [
{ label: "Supplier", url: docsUrl + "user/manual/en/supplier" },
];
frappe.help.help_links["List/Supplier"] = [{ label: "Supplier", url: docsUrl + "user/manual/en/supplier" }];
frappe.help.help_links["Form/Supplier"] = [
{ label: "Supplier", url: docsUrl + "user/manual/en/supplier" },
];
frappe.help.help_links["Form/Supplier"] = [{ label: "Supplier", url: docsUrl + "user/manual/en/supplier" }];
frappe.help.help_links["Form/Request for Quotation"] = [
{
@@ -441,9 +437,7 @@ frappe.help.help_links["Tree/Territory"] = [
},
];
frappe.help.help_links["List/Workflow"] = [
{ label: "Workflow", url: docsUrl + "user/manual/en/workflows" },
];
frappe.help.help_links["List/Workflow"] = [{ label: "Workflow", url: docsUrl + "user/manual/en/workflows" }];
frappe.help.help_links["List/Company"] = [
{
@@ -620,9 +614,7 @@ frappe.help.help_links["List/Item"] = [
},
{
label: "Item Valuation",
url:
docsUrl +
"user/manual/en/calculation-of-valuation-rate-in-fifo-and-moving-average",
url: docsUrl + "user/manual/en/calculation-of-valuation-rate-in-fifo-and-moving-average",
},
];
@@ -706,9 +698,7 @@ frappe.help.help_links["List/Installation Note"] = [
},
];
frappe.help.help_links["List/Budget"] = [
{ label: "Budgeting", url: docsUrl + "user/manual/en/budgeting" },
];
frappe.help.help_links["List/Budget"] = [{ label: "Budgeting", url: docsUrl + "user/manual/en/budgeting" }];
frappe.help.help_links["List/Material Request"] = [
{
@@ -768,13 +758,9 @@ frappe.help.help_links["Form/Serial No"] = [
{ label: "Serial No", url: docsUrl + "user/manual/en/serial-no" },
];
frappe.help.help_links["List/Batch"] = [
{ label: "Batch", url: docsUrl + "user/manual/en/batch" },
];
frappe.help.help_links["List/Batch"] = [{ label: "Batch", url: docsUrl + "user/manual/en/batch" }];
frappe.help.help_links["Form/Batch"] = [
{ label: "Batch", url: docsUrl + "user/manual/en/batch" },
];
frappe.help.help_links["Form/Batch"] = [{ label: "Batch", url: docsUrl + "user/manual/en/batch" }];
frappe.help.help_links["Form/Packing Slip"] = [
{
@@ -827,29 +813,21 @@ frappe.help.help_links["Form/Stock Reconciliation"] = [
//CRM
frappe.help.help_links["Form/Lead"] = [
{ label: "Lead", url: docsUrl + "user/manual/en/lead" },
];
frappe.help.help_links["Form/Lead"] = [{ label: "Lead", url: docsUrl + "user/manual/en/lead" }];
frappe.help.help_links["Form/Opportunity"] = [
{ label: "Opportunity", url: docsUrl + "user/manual/en/opportunity" },
];
frappe.help.help_links["Form/Address"] = [
{ label: "Address", url: docsUrl + "user/manual/en/address" },
];
frappe.help.help_links["Form/Address"] = [{ label: "Address", url: docsUrl + "user/manual/en/address" }];
frappe.help.help_links["Form/Contact"] = [
{ label: "Contact", url: docsUrl + "user/manual/en/contact" },
];
frappe.help.help_links["Form/Contact"] = [{ label: "Contact", url: docsUrl + "user/manual/en/contact" }];
frappe.help.help_links["Form/Newsletter"] = [
{ label: "Newsletter", url: docsUrl + "user/manual/en/newsletter" },
];
frappe.help.help_links["Form/Campaign"] = [
{ label: "Campaign", url: docsUrl + "user/manual/en/campaign" },
];
frappe.help.help_links["Form/Campaign"] = [{ label: "Campaign", url: docsUrl + "user/manual/en/campaign" }];
frappe.help.help_links["Tree/Sales Person"] = [
{

View File

@@ -1,8 +1,8 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on('Newsletter', {
frappe.ui.form.on("Newsletter", {
refresh() {
erpnext.toggle_naming_series();
}
},
});

View File

@@ -6,7 +6,7 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
var me = this;
this.dialog = new frappe.ui.Dialog({
title: 'Payment'
title: "Payment",
});
this.dialog.show();
@@ -17,15 +17,17 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
}
select_text() {
$(this.$body).find('.form-control').click(function() {
$(this).select();
});
$(this.$body)
.find(".form-control")
.click(function () {
$(this).select();
});
}
set_payment_primary_action() {
var me = this;
this.dialog.set_primary_action(__("Submit"), function() {
this.dialog.set_primary_action(__("Submit"), function () {
// Allow no ZERO payment
$.each(me.frm.doc.payments, function (index, data) {
if (data.amount != 0) {
@@ -34,131 +36,147 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
return;
}
});
})
});
}
make_keyboard(){
make_keyboard() {
var me = this;
$(this.$body).empty();
$(this.$body).html(frappe.render_template('pos_payment', this.frm.doc))
$(this.$body).html(frappe.render_template("pos_payment", this.frm.doc));
this.show_payment_details();
this.bind_keyboard_event()
this.clear_amount()
this.bind_keyboard_event();
this.clear_amount();
}
make_multimode_payment(){
make_multimode_payment() {
var me = this;
if (this.frm.doc.change_amount > 0) {
me.payment_val = me.doc.outstanding_amount;
}
this.payments = frappe.model.add_child(this.frm.doc, 'Multi Mode Payment', "payments");
this.payments = frappe.model.add_child(this.frm.doc, "Multi Mode Payment", "payments");
this.payments.mode_of_payment = this.dialog.fields_dict.mode_of_payment.get_value();
this.payments.amount = flt(this.payment_val);
}
show_payment_details(){
show_payment_details() {
var me = this;
var multimode_payments = $(this.$body).find('.multimode-payments').empty();
var multimode_payments = $(this.$body).find(".multimode-payments").empty();
if (this.frm.doc.payments.length) {
$.each(this.frm.doc.payments, function(index, data) {
$(frappe.render_template('payment_details', {
mode_of_payment: data.mode_of_payment,
amount: data.amount,
idx: data.idx,
currency: me.frm.doc.currency,
type: data.type
})).appendTo(multimode_payments)
$.each(this.frm.doc.payments, function (index, data) {
$(
frappe.render_template("payment_details", {
mode_of_payment: data.mode_of_payment,
amount: data.amount,
idx: data.idx,
currency: me.frm.doc.currency,
type: data.type,
})
).appendTo(multimode_payments);
if (data.type == 'Cash' && data.amount == me.frm.doc.paid_amount) {
if (data.type == "Cash" && data.amount == me.frm.doc.paid_amount) {
me.idx = data.idx;
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']",{'idx': me.idx}));
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']", { idx: me.idx }));
me.highlight_selected_row();
me.bind_amount_change_event();
}
})
}else{
$("<p>No payment mode selected in pos profile</p>").appendTo(multimode_payments)
});
} else {
$("<p>No payment mode selected in pos profile</p>").appendTo(multimode_payments);
}
}
set_outstanding_amount(){
this.selected_mode = $(this.$body).find(repl("input[idx='%(idx)s']",{'idx': this.idx}));
set_outstanding_amount() {
this.selected_mode = $(this.$body).find(repl("input[idx='%(idx)s']", { idx: this.idx }));
this.highlight_selected_row();
this.payment_val = 0.0;
if (this.frm.doc.outstanding_amount > 0 && flt(this.selected_mode.val()) == 0.0) {
//When user first time click on row
this.payment_val = flt(this.frm.doc.outstanding_amount / this.frm.doc.conversion_rate, precision("outstanding_amount"))
this.payment_val = flt(
this.frm.doc.outstanding_amount / this.frm.doc.conversion_rate,
precision("outstanding_amount")
);
this.selected_mode.val(format_currency(this.payment_val, this.frm.doc.currency));
this.update_payment_amount();
} else if (flt(this.selected_mode.val()) > 0) {
//If user click on existing row which has value
this.payment_val = flt(this.selected_mode.val());
}
this.selected_mode.select()
this.selected_mode.select();
this.bind_amount_change_event();
}
bind_keyboard_event(){
bind_keyboard_event() {
var me = this;
this.payment_val = '';
this.payment_val = "";
this.bind_form_control_event();
this.bind_numeric_keys_event();
}
bind_form_control_event() {
var me = this;
$(this.$body).find('.pos-payment-row').click(function() {
me.idx = $(this).attr("idx");
me.set_outstanding_amount();
});
$(this.$body)
.find(".pos-payment-row")
.click(function () {
me.idx = $(this).attr("idx");
me.set_outstanding_amount();
});
$(this.$body).find('.form-control').click(function() {
me.idx = $(this).attr("idx");
me.set_outstanding_amount();
me.update_paid_amount(true);
});
$(this.$body)
.find(".form-control")
.click(function () {
me.idx = $(this).attr("idx");
me.set_outstanding_amount();
me.update_paid_amount(true);
});
$(this.$body).find('.write_off_amount').change(function() {
me.write_off_amount(flt($(this).val()), precision("write_off_amount"));
});
$(this.$body)
.find(".write_off_amount")
.change(function () {
me.write_off_amount(flt($(this).val()), precision("write_off_amount"));
});
$(this.$body).find('.change_amount').change(function() {
me.change_amount(flt($(this).val()), precision("change_amount"));
});
$(this.$body)
.find(".change_amount")
.change(function () {
me.change_amount(flt($(this).val()), precision("change_amount"));
});
}
highlight_selected_row() {
var selected_row = $(this.$body).find(repl(".pos-payment-row[idx='%(idx)s']", {'idx': this.idx}));
$(this.$body).find('.pos-payment-row').removeClass('selected-payment-mode');
selected_row.addClass('selected-payment-mode');
$(this.$body).find('.amount').attr('disabled', true);
this.selected_mode.attr('disabled', false);
var selected_row = $(this.$body).find(repl(".pos-payment-row[idx='%(idx)s']", { idx: this.idx }));
$(this.$body).find(".pos-payment-row").removeClass("selected-payment-mode");
selected_row.addClass("selected-payment-mode");
$(this.$body).find(".amount").attr("disabled", true);
this.selected_mode.attr("disabled", false);
}
bind_numeric_keys_event() {
var me = this;
$(this.$body).find('.pos-keyboard-key').click(function(){
me.payment_val += $(this).text();
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_paid_amount();
});
$(this.$body).find('.delete-btn').click(function() {
me.payment_val = cstr(flt(me.selected_mode.val())).slice(0, -1);
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_paid_amount();
})
$(this.$body)
.find(".pos-keyboard-key")
.click(function () {
me.payment_val += $(this).text();
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_paid_amount();
});
$(this.$body)
.find(".delete-btn")
.click(function () {
me.payment_val = cstr(flt(me.selected_mode.val())).slice(0, -1);
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_paid_amount();
});
}
bind_amount_change_event() {
var me = this;
this.selected_mode.change(function() {
me.payment_val = flt($(this).val()) || 0.0;
this.selected_mode.change(function () {
me.payment_val = flt($(this).val()) || 0.0;
me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
me.idx = me.selected_mode.attr("idx");
me.update_payment_amount();
@@ -167,21 +185,25 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
clear_amount() {
var me = this;
$(this.$body).find('.clr').click(function(e) {
e.stopPropagation();
me.idx = $(this).attr("idx");
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']",{'idx': me.idx}));
me.payment_val = 0.0;
me.selected_mode.val(0.0);
me.highlight_selected_row();
me.update_payment_amount();
});
$(this.$body)
.find(".clr")
.click(function (e) {
e.stopPropagation();
me.idx = $(this).attr("idx");
me.selected_mode = $(me.$body).find(repl("input[idx='%(idx)s']", { idx: me.idx }));
me.payment_val = 0.0;
me.selected_mode.val(0.0);
me.highlight_selected_row();
me.update_payment_amount();
});
}
write_off_amount(write_off_amount) {
this.frm.doc.write_off_amount = flt(write_off_amount, precision("write_off_amount"));
this.frm.doc.base_write_off_amount = flt(this.frm.doc.write_off_amount * this.frm.doc.conversion_rate,
precision("base_write_off_amount"));
this.frm.doc.base_write_off_amount = flt(
this.frm.doc.write_off_amount * this.frm.doc.conversion_rate,
precision("base_write_off_amount")
);
this.calculate_outstanding_amount(false);
this.show_amounts();
}
@@ -196,13 +218,16 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
update_paid_amount(update_write_off) {
var me = this;
if (in_list(['change_amount', 'write_off_amount'], this.idx)) {
if (in_list(["change_amount", "write_off_amount"], this.idx)) {
var value = me.selected_mode.val();
if (me.idx == 'change_amount') {
if (me.idx == "change_amount") {
me.change_amount(value);
} else {
if(flt(value) == 0 && update_write_off && me.frm.doc.outstanding_amount > 0) {
value = flt(me.frm.doc.outstanding_amount / me.frm.doc.conversion_rate, precision(me.idx));
if (flt(value) == 0 && update_write_off && me.frm.doc.outstanding_amount > 0) {
value = flt(
me.frm.doc.outstanding_amount / me.frm.doc.conversion_rate,
precision(me.idx)
);
}
me.write_off_amount(value);
}
@@ -211,25 +236,38 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
}
}
update_payment_amount(){
update_payment_amount() {
var me = this;
$.each(this.frm.doc.payments, function(index, data) {
$.each(this.frm.doc.payments, function (index, data) {
if (cint(me.idx) == cint(data.idx)) {
data.amount = flt(me.selected_mode.val(), 2);
}
})
});
this.calculate_outstanding_amount(false);
this.show_amounts();
}
show_amounts(){
show_amounts() {
var me = this;
$(this.$body).find(".write_off_amount").val(format_currency(this.frm.doc.write_off_amount, this.frm.doc.currency));
$(this.$body).find('.paid_amount').text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency));
$(this.$body).find('.change_amount').val(format_currency(this.frm.doc.change_amount, this.frm.doc.currency));
$(this.$body).find('.outstanding_amount').text(format_currency(this.frm.doc.outstanding_amount, frappe.get_doc(":Company", this.frm.doc.company).default_currency));
$(this.$body)
.find(".write_off_amount")
.val(format_currency(this.frm.doc.write_off_amount, this.frm.doc.currency));
$(this.$body)
.find(".paid_amount")
.text(format_currency(this.frm.doc.paid_amount, this.frm.doc.currency));
$(this.$body)
.find(".change_amount")
.val(format_currency(this.frm.doc.change_amount, this.frm.doc.currency));
$(this.$body)
.find(".outstanding_amount")
.text(
format_currency(
this.frm.doc.outstanding_amount,
frappe.get_doc(":Company", this.frm.doc.company).default_currency
)
);
this.update_invoice();
}
}
};

View File

@@ -1,5 +1,5 @@
class VisualPlantFloor {
constructor({wrapper, skip_filters=false, plant_floor=null}, page=null) {
constructor({ wrapper, skip_filters = false, plant_floor = null }, page = null) {
this.wrapper = wrapper;
this.plant_floor = plant_floor;
this.skip_filters = skip_filters;
@@ -23,67 +23,67 @@ class VisualPlantFloor {
`);
if (!this.skip_filters) {
this.filter_wrapper = this.wrapper.find('.plant-floor-filter');
this.visualization_wrapper = this.wrapper.find('.plant-floor-visualization');
} else if(this.plant_floor) {
this.wrapper.find('.plant-floor').css('border', 'none');
this.filter_wrapper = this.wrapper.find(".plant-floor-filter");
this.visualization_wrapper = this.wrapper.find(".plant-floor-visualization");
} else if (this.plant_floor) {
this.wrapper.find(".plant-floor").css("border", "none");
this.prepare_data();
}
}
prepare_data() {
frappe.call({
method: 'erpnext.manufacturing.doctype.workstation.workstation.get_workstations',
method: "erpnext.manufacturing.doctype.workstation.workstation.get_workstations",
args: {
plant_floor: this.plant_floor,
},
callback: (r) => {
this.workstations = r.message;
this.render_workstations();
}
},
});
}
add_filter() {
this.plant_floor = frappe.ui.form.make_control({
df: {
fieldtype: 'Link',
options: 'Plant Floor',
fieldname: 'plant_floor',
label: __('Plant Floor'),
fieldtype: "Link",
options: "Plant Floor",
fieldname: "plant_floor",
label: __("Plant Floor"),
reqd: 1,
onchange: () => {
this.render_plant_visualization();
}
},
},
parent: this.filter_wrapper,
render_input: true,
});
this.plant_floor.$wrapper.addClass('form-column col-sm-2');
this.plant_floor.$wrapper.addClass("form-column col-sm-2");
this.workstation_type = frappe.ui.form.make_control({
df: {
fieldtype: 'Link',
options: 'Workstation Type',
fieldname: 'workstation_type',
label: __('Machine Type'),
fieldtype: "Link",
options: "Workstation Type",
fieldname: "workstation_type",
label: __("Machine Type"),
onchange: () => {
this.render_plant_visualization();
}
},
},
parent: this.filter_wrapper,
render_input: true,
});
this.workstation_type.$wrapper.addClass('form-column col-sm-2');
this.workstation_type.$wrapper.addClass("form-column col-sm-2");
this.workstation = frappe.ui.form.make_control({
df: {
fieldtype: 'Link',
options: 'Workstation',
fieldname: 'workstation',
label: __('Machine'),
fieldtype: "Link",
options: "Workstation",
fieldname: "workstation",
label: __("Machine"),
onchange: () => {
this.render_plant_visualization();
},
@@ -91,24 +91,24 @@ class VisualPlantFloor {
if (this.workstation_type.get_value()) {
return {
filters: {
'workstation_type': this.workstation_type.get_value() || ''
}
}
workstation_type: this.workstation_type.get_value() || "",
},
};
}
}
},
},
parent: this.filter_wrapper,
render_input: true,
});
this.workstation.$wrapper.addClass('form-column col-sm-2');
this.workstation.$wrapper.addClass("form-column col-sm-2");
this.workstation_status = frappe.ui.form.make_control({
df: {
fieldtype: 'Select',
options: '\nProduction\nOff\nIdle\nProblem\nMaintenance\nSetup',
fieldname: 'workstation_status',
label: __('Status'),
fieldtype: "Select",
options: "\nProduction\nOff\nIdle\nProblem\nMaintenance\nSetup",
fieldname: "workstation_status",
label: __("Status"),
onchange: () => {
this.render_plant_visualization();
},
@@ -123,35 +123,35 @@ class VisualPlantFloor {
if (plant_floor) {
frappe.call({
method: 'erpnext.manufacturing.doctype.workstation.workstation.get_workstations',
method: "erpnext.manufacturing.doctype.workstation.workstation.get_workstations",
args: {
plant_floor: plant_floor,
workstation_type: this.workstation_type.get_value(),
workstation: this.workstation.get_value(),
workstation_status: this.workstation_status.get_value()
workstation_status: this.workstation_status.get_value(),
},
callback: (r) => {
this.workstations = r.message;
this.render_workstations();
}
},
});
}
}
render_workstations() {
this.wrapper.find('.plant-floor-container').empty();
let template = frappe.render_template("visual_plant_floor_template", {
workstations: this.workstations
this.wrapper.find(".plant-floor-container").empty();
let template = frappe.render_template("visual_plant_floor_template", {
workstations: this.workstations,
});
$(template).appendTo(this.wrapper.find('.plant-floor-container'));
$(template).appendTo(this.wrapper.find(".plant-floor-container"));
}
prepare_menu() {
this.page.add_menu_item(__('Refresh'), () => {
this.page.add_menu_item(__("Refresh"), () => {
this.render_plant_visualization();
});
}
}
frappe.ui.VisualPlantFloor = VisualPlantFloor;
frappe.ui.VisualPlantFloor = VisualPlantFloor;

View File

@@ -1,26 +1,30 @@
frappe.provide("erpnext.timesheet");
erpnext.timesheet.timer = function(frm, row, timestamp=0) {
erpnext.timesheet.timer = function (frm, row, timestamp = 0) {
let dialog = new frappe.ui.Dialog({
title: __("Timer"),
fields:
[
{"fieldtype": "Link", "label": __("Activity Type"), "fieldname": "activity_type",
"reqd": 1, "options": "Activity Type"},
{"fieldtype": "Link", "label": __("Project"), "fieldname": "project", "options": "Project"},
{"fieldtype": "Link", "label": __("Task"), "fieldname": "task", "options": "Task"},
{"fieldtype": "Float", "label": __("Expected Hrs"), "fieldname": "expected_hours"},
{"fieldtype": "Section Break"},
{"fieldtype": "HTML", "fieldname": "timer_html"}
]
fields: [
{
fieldtype: "Link",
label: __("Activity Type"),
fieldname: "activity_type",
reqd: 1,
options: "Activity Type",
},
{ fieldtype: "Link", label: __("Project"), fieldname: "project", options: "Project" },
{ fieldtype: "Link", label: __("Task"), fieldname: "task", options: "Task" },
{ fieldtype: "Float", label: __("Expected Hrs"), fieldname: "expected_hours" },
{ fieldtype: "Section Break" },
{ fieldtype: "HTML", fieldname: "timer_html" },
],
});
if (row) {
dialog.set_values({
'activity_type': row.activity_type,
'project': row.project,
'task': row.task,
'expected_hours': row.expected_hours
activity_type: row.activity_type,
project: row.project,
task: row.task,
expected_hours: row.expected_hours,
});
}
dialog.get_field("timer_html").$wrapper.append(get_timer_html());
@@ -34,8 +38,8 @@ erpnext.timesheet.timer = function(frm, row, timestamp=0) {
<span class="seconds">00</span>
</div>
<div class="playpause text-center">
<button class= "btn btn-primary btn-start"> ${ __("Start") } </button>
<button class= "btn btn-primary btn-complete"> ${ __("Complete") } </button>
<button class= "btn btn-primary btn-start"> ${__("Start")} </button>
<button class= "btn btn-primary btn-complete"> ${__("Complete")} </button>
</div>
`;
}
@@ -43,7 +47,7 @@ erpnext.timesheet.timer = function(frm, row, timestamp=0) {
dialog.show();
};
erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
erpnext.timesheet.control_timer = function (frm, dialog, row, timestamp = 0) {
var $btn_start = dialog.$wrapper.find(".playpause .btn-start");
var $btn_complete = dialog.$wrapper.find(".playpause .btn-complete");
var interval = null;
@@ -63,12 +67,16 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
$btn_complete.hide();
}
$btn_start.click(function(e) {
$btn_start.click(function (e) {
if (!initialized) {
// New activity if no activities found
var args = dialog.get_values();
if(!args) return;
if (frm.doc.time_logs.length == 1 && !frm.doc.time_logs[0].activity_type && !frm.doc.time_logs[0].from_time) {
if (!args) return;
if (
frm.doc.time_logs.length == 1 &&
!frm.doc.time_logs[0].activity_type &&
!frm.doc.time_logs[0].from_time
) {
frm.doc.time_logs = [];
}
row = frappe.model.add_child(frm.doc, "Timesheet Detail", "time_logs");
@@ -79,7 +87,7 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
row.expected_hours = args.expected_hours;
row.completed = 0;
let d = moment(row.from_time);
if(row.expected_hours) {
if (row.expected_hours) {
d.add(row.expected_hours, "hours");
row.to_time = d.format(frappe.defaultDatetimeFormat);
}
@@ -101,8 +109,8 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
});
// Stop the timer and update the time logged by the timer on click of 'Complete' button
$btn_complete.click(function() {
var grid_row = cur_frm.fields_dict['time_logs'].grid.get_row(row.idx - 1);
$btn_complete.click(function () {
var grid_row = cur_frm.fields_dict["time_logs"].grid.get_row(row.idx - 1);
var args = dialog.get_values();
grid_row.doc.completed = 1;
grid_row.doc.activity_type = args.activity_type;
@@ -119,7 +127,7 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
});
function initializeTimer() {
interval = setInterval(function() {
interval = setInterval(function () {
var current = setCurrentIncrement();
updateStopwatch(current);
}, 1000);
@@ -127,25 +135,24 @@ erpnext.timesheet.control_timer = function(frm, dialog, row, timestamp=0) {
function updateStopwatch(increment) {
var hours = Math.floor(increment / 3600);
var minutes = Math.floor((increment - (hours * 3600)) / 60);
var seconds = increment - (hours * 3600) - (minutes * 60);
var minutes = Math.floor((increment - hours * 3600) / 60);
var seconds = increment - hours * 3600 - minutes * 60;
// If modal is closed by clicking anywhere outside, reset the timer
if (!$('.modal-dialog').is(':visible')) {
if (!$(".modal-dialog").is(":visible")) {
reset();
}
if(hours > 99999)
reset();
if(cur_dialog && cur_dialog.get_value('expected_hours') > 0) {
if(flag && (currentIncrement >= (cur_dialog.get_value('expected_hours') * 3600))) {
if (hours > 99999) reset();
if (cur_dialog && cur_dialog.get_value("expected_hours") > 0) {
if (flag && currentIncrement >= cur_dialog.get_value("expected_hours") * 3600) {
frappe.utils.play_sound("alert");
frappe.msgprint(__("Timer exceeded the given hours."));
flag = false;
}
}
$(".hours").text(hours < 10 ? ("0" + hours.toString()) : hours.toString());
$(".minutes").text(minutes < 10 ? ("0" + minutes.toString()) : minutes.toString());
$(".seconds").text(seconds < 10 ? ("0" + seconds.toString()) : seconds.toString());
$(".hours").text(hours < 10 ? "0" + hours.toString() : hours.toString());
$(".minutes").text(minutes < 10 ? "0" + minutes.toString() : minutes.toString());
$(".seconds").text(seconds < 10 ? "0" + seconds.toString() : seconds.toString());
}
function setCurrentIncrement() {

View File

@@ -1,71 +1,67 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
erpnext.get_purchase_trends_filters = function() {
erpnext.get_purchase_trends_filters = function () {
return [
{
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"reqd": 1,
"default": frappe.defaults.get_user_default("Company")
fieldname: "company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
reqd: 1,
default: frappe.defaults.get_user_default("Company"),
},
{
"fieldname":"period",
"label": __("Period"),
"fieldtype": "Select",
"options": [
{ "value": "Monthly", "label": __("Monthly") },
{ "value": "Quarterly", "label": __("Quarterly") },
{ "value": "Half-Yearly", "label": __("Half-Yearly") },
{ "value": "Yearly", "label": __("Yearly") }
fieldname: "period",
label: __("Period"),
fieldtype: "Select",
options: [
{ value: "Monthly", label: __("Monthly") },
{ value: "Quarterly", label: __("Quarterly") },
{ value: "Half-Yearly", label: __("Half-Yearly") },
{ value: "Yearly", label: __("Yearly") },
],
"default": "Monthly"
default: "Monthly",
},
{
"fieldname":"fiscal_year",
"label": __("Fiscal Year"),
"fieldtype": "Link",
"options":'Fiscal Year',
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today())
fieldname: "fiscal_year",
label: __("Fiscal Year"),
fieldtype: "Link",
options: "Fiscal Year",
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
},
{
"fieldname":"period_based_on",
"label": __("Period based On"),
"fieldtype": "Select",
"options": [
{ "value": "posting_date", "label": __("Posting Date") },
{ "value": "bill_date", "label": __("Billing Date") },
fieldname: "period_based_on",
label: __("Period based On"),
fieldtype: "Select",
options: [
{ value: "posting_date", label: __("Posting Date") },
{ value: "bill_date", label: __("Billing Date") },
],
"default": "posting_date"
default: "posting_date",
},
{
"fieldname":"based_on",
"label": __("Based On"),
"fieldtype": "Select",
"options": [
{ "value": "Item", "label": __("Item") },
{ "value": "Item Group", "label": __("Item Group") },
{ "value": "Supplier", "label": __("Supplier") },
{ "value": "Supplier Group", "label": __("Supplier Group") },
{ "value": "Project", "label": __("Project") }
fieldname: "based_on",
label: __("Based On"),
fieldtype: "Select",
options: [
{ value: "Item", label: __("Item") },
{ value: "Item Group", label: __("Item Group") },
{ value: "Supplier", label: __("Supplier") },
{ value: "Supplier Group", label: __("Supplier Group") },
{ value: "Project", label: __("Project") },
],
"default": "Item",
"dashboard_config": {
"read_only": 1
}
default: "Item",
dashboard_config: {
read_only: 1,
},
},
{
"fieldname":"group_by",
"label": __("Group By"),
"fieldtype": "Select",
"options": [
"",
{ "value": "Item", "label": __("Item") },
{ "value": "Supplier", "label": __("Supplier") }
],
"default": ""
fieldname: "group_by",
label: __("Group By"),
fieldtype: "Select",
options: ["", { value: "Item", label: __("Item") }, { value: "Supplier", label: __("Supplier") }],
default: "",
},
];
}
};

View File

@@ -4,129 +4,139 @@
// searches for enabled users
frappe.provide("erpnext.queries");
$.extend(erpnext.queries, {
user: function() {
user: function () {
return { query: "frappe.core.doctype.user.user.user_query" };
},
lead: function() {
lead: function () {
return { query: "erpnext.controllers.queries.lead_query" };
},
customer: function() {
customer: function () {
return { query: "erpnext.controllers.queries.customer_query" };
},
supplier: function() {
supplier: function () {
return { query: "erpnext.controllers.queries.supplier_query" };
},
item: function(filters) {
item: function (filters) {
var args = { query: "erpnext.controllers.queries.item_query" };
if(filters) args["filters"] = filters;
if (filters) args["filters"] = filters;
return args;
},
bom: function() {
bom: function () {
return { query: "erpnext.controllers.queries.bom" };
},
task: function() {
task: function () {
return { query: "erpnext.projects.utils.query_task" };
},
customer_filter: function(doc) {
if(!doc.customer) {
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "customer", doc.name))]));
customer_filter: function (doc) {
if (!doc.customer) {
frappe.throw(
__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "customer", doc.name))])
);
}
return { filters: { customer: doc.customer } };
},
contact_query: function(doc) {
if(frappe.dynamic_link) {
if(!doc[frappe.dynamic_link.fieldname]) {
frappe.throw(__("Please set {0}",
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
contact_query: function (doc) {
if (frappe.dynamic_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.contact.contact.contact_query',
query: "frappe.contacts.doctype.contact.contact.contact_query",
filters: {
link_doctype: frappe.dynamic_link.doctype,
link_name: doc[frappe.dynamic_link.fieldname]
}
link_name: doc[frappe.dynamic_link.fieldname],
},
};
}
},
address_query: function(doc) {
if(frappe.dynamic_link) {
if(!doc[frappe.dynamic_link.fieldname]) {
frappe.throw(__("Please set {0}",
[__(frappe.meta.get_label(doc.doctype, frappe.dynamic_link.fieldname, doc.name))]));
address_query: function (doc) {
if (frappe.dynamic_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',
query: "frappe.contacts.doctype.address.address.address_query",
filters: {
link_doctype: frappe.dynamic_link.doctype,
link_name: doc[frappe.dynamic_link.fieldname]
}
link_name: doc[frappe.dynamic_link.fieldname],
},
};
}
},
company_address_query: function(doc) {
company_address_query: function (doc) {
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: { is_your_company_address: 1, link_doctype: 'Company', link_name: doc.company || '' }
query: "frappe.contacts.doctype.address.address.address_query",
filters: { is_your_company_address: 1, link_doctype: "Company", link_name: doc.company || "" },
};
},
dispatch_address_query: function(doc) {
dispatch_address_query: function (doc) {
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: { link_doctype: 'Company', link_name: doc.company || '' }
query: "frappe.contacts.doctype.address.address.address_query",
filters: { link_doctype: "Company", link_name: doc.company || "" },
};
},
supplier_filter: function(doc) {
if(!doc.supplier) {
frappe.throw(__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "supplier", doc.name))]));
supplier_filter: function (doc) {
if (!doc.supplier) {
frappe.throw(
__("Please set {0}", [__(frappe.meta.get_label(doc.doctype, "supplier", doc.name))])
);
}
return { filters: { supplier: doc.supplier } };
},
lead_filter: function(doc) {
if(!doc.lead) {
frappe.throw(__("Please specify a {0}",
[__(frappe.meta.get_label(doc.doctype, "lead", doc.name))]));
lead_filter: function (doc) {
if (!doc.lead) {
frappe.throw(
__("Please specify a {0}", [__(frappe.meta.get_label(doc.doctype, "lead", doc.name))])
);
}
return { filters: { lead: doc.lead } };
},
not_a_group_filter: function() {
not_a_group_filter: function () {
return { filters: { is_group: 0 } };
},
employee: function() {
return { query: "erpnext.controllers.queries.employee_query" }
employee: function () {
return { query: "erpnext.controllers.queries.employee_query" };
},
warehouse: function(doc) {
warehouse: function (doc) {
return {
filters: [
["Warehouse", "company", "in", ["", cstr(doc.company)]],
["Warehouse", "is_group", "=",0]
]
["Warehouse", "is_group", "=", 0],
],
};
},
get_filtered_dimensions: function(doc, child_fields, dimension, company) {
let account = '';
get_filtered_dimensions: function (doc, child_fields, dimension, company) {
let account = "";
child_fields.forEach((field) => {
if (!account) {
@@ -137,21 +147,23 @@ $.extend(erpnext.queries, {
return {
query: "erpnext.controllers.queries.get_filtered_dimensions",
filters: {
'dimension': dimension,
'account': account,
'company': company
}
dimension: dimension,
account: account,
company: company,
},
};
}
},
});
erpnext.queries.setup_queries = function(frm, options, query_fn) {
erpnext.queries.setup_queries = function (frm, options, query_fn) {
var me = this;
var set_query = function(doctype, parentfield) {
var link_fields = frappe.meta.get_docfields(doctype, frm.doc.name,
{"fieldtype": "Link", "options": options});
$.each(link_fields, function(i, df) {
if(parentfield) {
var set_query = function (doctype, parentfield) {
var link_fields = frappe.meta.get_docfields(doctype, frm.doc.name, {
fieldtype: "Link",
options: options,
});
$.each(link_fields, function (i, df) {
if (parentfield) {
frm.set_query(df.fieldname, parentfield, query_fn);
} else {
frm.set_query(df.fieldname, query_fn);
@@ -162,24 +174,26 @@ erpnext.queries.setup_queries = function(frm, options, query_fn) {
set_query(frm.doc.doctype);
// warehouse field in tables
$.each(frappe.meta.get_docfields(frm.doc.doctype, frm.doc.name, {"fieldtype": "Table"}),
function(i, df) {
$.each(
frappe.meta.get_docfields(frm.doc.doctype, frm.doc.name, { fieldtype: "Table" }),
function (i, df) {
set_query(df.options, df.fieldname);
});
}
}
);
};
/* if item code is selected in child table
then list down warehouses with its quantity
else apply default filters.
*/
erpnext.queries.setup_warehouse_query = function(frm){
frm.set_query('warehouse', 'items', function(doc, cdt, cdn) {
var row = locals[cdt][cdn];
erpnext.queries.setup_warehouse_query = function (frm) {
frm.set_query("warehouse", "items", function (doc, cdt, cdn) {
var row = locals[cdt][cdn];
var filters = erpnext.queries.warehouse(frm.doc);
if(row.item_code){
$.extend(filters, {"query":"erpnext.controllers.queries.warehouse_query"});
if (row.item_code) {
$.extend(filters, { query: "erpnext.controllers.queries.warehouse_query" });
filters["filters"].push(["Bin", "item_code", "=", row.item_code]);
}
return filters
return filters;
});
}
};

View File

@@ -1,61 +1,57 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
erpnext.get_sales_trends_filters = function() {
return[
erpnext.get_sales_trends_filters = function () {
return [
{
"fieldname":"period",
"label": __("Period"),
"fieldtype": "Select",
"options": [
{ "value": "Monthly", "label": __("Monthly") },
{ "value": "Quarterly", "label": __("Quarterly") },
{ "value": "Half-Yearly", "label": __("Half-Yearly") },
{ "value": "Yearly", "label": __("Yearly") }
fieldname: "period",
label: __("Period"),
fieldtype: "Select",
options: [
{ value: "Monthly", label: __("Monthly") },
{ value: "Quarterly", label: __("Quarterly") },
{ value: "Half-Yearly", label: __("Half-Yearly") },
{ value: "Yearly", label: __("Yearly") },
],
"default": "Monthly"
default: "Monthly",
},
{
"fieldname":"based_on",
"label": __("Based On"),
"fieldtype": "Select",
"options": [
{ "value": "Item", "label": __("Item") },
{ "value": "Item Group", "label": __("Item Group") },
{ "value": "Customer", "label": __("Customer") },
{ "value": "Customer Group", "label": __("Customer Group") },
{ "value": "Territory", "label": __("Territory") },
{ "value": "Project", "label": __("Project") }
fieldname: "based_on",
label: __("Based On"),
fieldtype: "Select",
options: [
{ value: "Item", label: __("Item") },
{ value: "Item Group", label: __("Item Group") },
{ value: "Customer", label: __("Customer") },
{ value: "Customer Group", label: __("Customer Group") },
{ value: "Territory", label: __("Territory") },
{ value: "Project", label: __("Project") },
],
"default": "Item",
"dashboard_config": {
"read_only": 1,
}
default: "Item",
dashboard_config: {
read_only: 1,
},
},
{
"fieldname":"group_by",
"label": __("Group By"),
"fieldtype": "Select",
"options": [
"",
{ "value": "Item", "label": __("Item") },
{ "value": "Customer", "label": __("Customer") }
],
"default": ""
fieldname: "group_by",
label: __("Group By"),
fieldtype: "Select",
options: ["", { value: "Item", label: __("Item") }, { value: "Customer", label: __("Customer") }],
default: "",
},
{
"fieldname":"fiscal_year",
"label": __("Fiscal Year"),
"fieldtype": "Link",
"options":'Fiscal Year',
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
fieldname: "fiscal_year",
label: __("Fiscal Year"),
fieldtype: "Link",
options: "Fiscal Year",
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
},
{
"fieldname":"company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company")
fieldname: "company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
},
];
}
};

View File

@@ -1,7 +1,7 @@
frappe.provide("erpnext.setup");
frappe.pages['setup-wizard'].on_page_load = function(wrapper) {
if(frappe.sys_defaults.company) {
frappe.pages["setup-wizard"].on_page_load = function (wrapper) {
if (frappe.sys_defaults.company) {
frappe.set_route("desk");
return;
}
@@ -14,38 +14,42 @@ frappe.setup.on("before_load", function () {
erpnext.setup.slides_settings = [
{
// Organization
name: 'organization',
name: "organization",
title: __("Setup your organization"),
icon: "fa fa-building",
fields: [
{
fieldname: 'company_name',
label: __('Company Name'),
fieldtype: 'Data',
reqd: 1
fieldname: "company_name",
label: __("Company Name"),
fieldtype: "Data",
reqd: 1,
},
{ fieldtype: "Column Break" },
{
fieldname: 'company_abbr',
label: __('Company Abbreviation'),
fieldtype: 'Data',
reqd: 1
fieldname: "company_abbr",
label: __("Company Abbreviation"),
fieldtype: "Data",
reqd: 1,
},
{ fieldtype: "Section Break" },
{
fieldname: 'chart_of_accounts', label: __('Chart of Accounts'),
options: "", fieldtype: 'Select'
fieldname: "chart_of_accounts",
label: __("Chart of Accounts"),
options: "",
fieldtype: "Select",
},
{ fieldname: 'view_coa', label: __('View Chart of Accounts'), fieldtype: 'Button' },
{ fieldname: 'fy_start_date', label: __('Financial Year Begins On'), fieldtype: 'Date', reqd: 1 },
{ fieldname: "view_coa", label: __("View Chart of Accounts"), fieldtype: "Button" },
{ fieldname: "fy_start_date", label: __("Financial Year Begins On"), fieldtype: "Date", reqd: 1 },
// end date should be hidden (auto calculated)
{ fieldname: 'fy_end_date', label: __('End Date'), fieldtype: 'Date', reqd: 1, hidden: 1 },
{ fieldname: "fy_end_date", label: __("End Date"), fieldtype: "Date", reqd: 1, hidden: 1 },
{ fieldtype: "Section Break" },
{
fieldname: 'setup_demo',
label: __('Generate Demo Data for Exploration'),
fieldtype: 'Check',
description: __('If checked, we will create demo data for you to explore the system. This demo data can be erased later.')
fieldname: "setup_demo",
label: __("Generate Demo Data for Exploration"),
fieldtype: "Check",
description: __(
"If checked, we will create demo data for you to explore the system. This demo data can be erased later."
),
},
],
@@ -73,10 +77,10 @@ erpnext.setup.slides_settings = [
return true;
},
validate_fy_dates: function() {
validate_fy_dates: function () {
// validate fiscal year start and end dates
const invalid = this.values.fy_start_date == 'Invalid date' ||
this.values.fy_end_date == 'Invalid date';
const invalid =
this.values.fy_start_date == "Invalid date" || this.values.fy_end_date == "Invalid date";
const start_greater_than_end = this.values.fy_start_date > this.values.fy_end_date;
if (invalid || start_greater_than_end) {
@@ -104,26 +108,24 @@ erpnext.setup.slides_settings = [
next_year = current_year;
current_year -= 1;
}
slide.get_field("fy_start_date").set_value(current_year + '-' + fy[0]);
slide.get_field("fy_end_date").set_value(next_year + '-' + fy[1]);
slide.get_field("fy_start_date").set_value(current_year + "-" + fy[0]);
slide.get_field("fy_end_date").set_value(next_year + "-" + fy[1]);
}
},
load_chart_of_accounts: function (slide) {
let country = frappe.wizard.values.country;
if (country) {
frappe.call({
method: "erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts.get_charts_for_country",
args: { "country": country, with_standard: true },
args: { country: country, with_standard: true },
callback: function (r) {
if (r.message) {
slide.get_input("chart_of_accounts").empty()
.add_options(r.message);
slide.get_input("chart_of_accounts").empty().add_options(r.message);
}
}
})
},
});
}
},
@@ -131,56 +133,74 @@ erpnext.setup.slides_settings = [
let me = this;
slide.get_input("fy_start_date").on("change", function () {
var start_date = slide.form.fields_dict.fy_start_date.get_value();
var year_end_date =
frappe.datetime.add_days(frappe.datetime.add_months(start_date, 12), -1);
var year_end_date = frappe.datetime.add_days(frappe.datetime.add_months(start_date, 12), -1);
slide.form.fields_dict.fy_end_date.set_value(year_end_date);
});
slide.get_input("view_coa").on("click", function() {
slide.get_input("view_coa").on("click", function () {
let chart_template = slide.form.fields_dict.chart_of_accounts.get_value();
if(!chart_template) return;
if (!chart_template) return;
me.charts_modal(slide, chart_template);
});
slide.get_input("company_name").on("input", function () {
let parts = slide.get_input("company_name").val().split(" ");
let abbr = $.map(parts, function (p) { return p ? p.substr(0, 1) : null }).join("");
slide.get_field("company_abbr").set_value(abbr.slice(0, 10).toUpperCase());
}).val(frappe.boot.sysdefaults.company_name || "").trigger("change");
slide
.get_input("company_name")
.on("input", function () {
let parts = slide.get_input("company_name").val().split(" ");
let abbr = $.map(parts, function (p) {
return p ? p.substr(0, 1) : null;
}).join("");
slide.get_field("company_abbr").set_value(abbr.slice(0, 10).toUpperCase());
})
.val(frappe.boot.sysdefaults.company_name || "")
.trigger("change");
slide.get_input("company_abbr").on("change", function () {
let abbr = slide.get_input("company_abbr").val();
if (abbr.length > 10) {
frappe.msgprint(__("Company Abbreviation cannot have more than 5 characters"));
abbr = abbr.slice(0, 10);
}
slide.get_field("company_abbr").set_value(abbr);
}).val(frappe.boot.sysdefaults.company_abbr || "").trigger("change");
slide
.get_input("company_abbr")
.on("change", function () {
let abbr = slide.get_input("company_abbr").val();
if (abbr.length > 10) {
frappe.msgprint(__("Company Abbreviation cannot have more than 5 characters"));
abbr = abbr.slice(0, 10);
}
slide.get_field("company_abbr").set_value(abbr);
})
.val(frappe.boot.sysdefaults.company_abbr || "")
.trigger("change");
},
charts_modal: function(slide, chart_template) {
let parent = __('All Accounts');
charts_modal: function (slide, chart_template) {
let parent = __("All Accounts");
let dialog = new frappe.ui.Dialog({
title: chart_template,
fields: [
{'fieldname': 'expand_all', 'label': __('Expand All'), 'fieldtype': 'Button',
click: function() {
{
fieldname: "expand_all",
label: __("Expand All"),
fieldtype: "Button",
click: function () {
// expand all nodes on button click
coa_tree.load_children(coa_tree.root_node, true);
}
},
},
{'fieldname': 'collapse_all', 'label': __('Collapse All'), 'fieldtype': 'Button',
click: function() {
{
fieldname: "collapse_all",
label: __("Collapse All"),
fieldtype: "Button",
click: function () {
// collapse all nodes
coa_tree.get_all_nodes(coa_tree.root_node.data.value, coa_tree.root_node.is_root)
.then(data_list => {
data_list.map(d => { coa_tree.toggle_node(coa_tree.nodes[d.parent]); });
coa_tree
.get_all_nodes(coa_tree.root_node.data.value, coa_tree.root_node.is_root)
.then((data_list) => {
data_list.map((d) => {
coa_tree.toggle_node(coa_tree.nodes[d.parent]);
});
});
}
}
]
},
},
],
});
// render tree structure in the dialog modal
@@ -188,49 +208,49 @@ erpnext.setup.slides_settings = [
parent: $(dialog.body),
label: parent,
expandable: true,
method: 'erpnext.accounts.utils.get_coa',
method: "erpnext.accounts.utils.get_coa",
args: {
chart: chart_template,
parent: parent,
doctype: 'Account'
doctype: "Account",
},
onclick: function(node) {
onclick: function (node) {
parent = node.value;
}
},
});
// add class to show buttons side by side
const form_container = $(dialog.body).find('form');
const buttons = $(form_container).find('.frappe-control');
form_container.addClass('flex');
const form_container = $(dialog.body).find("form");
const buttons = $(form_container).find(".frappe-control");
form_container.addClass("flex");
buttons.map((index, button) => {
$(button).css({"margin-right": "1em"});
})
$(button).css({ "margin-right": "1em" });
});
dialog.show();
coa_tree.load_children(coa_tree.root_node, true); // expand all node trigger
}
}
},
},
];
// Source: https://en.wikipedia.org/wiki/Fiscal_year
// default 1st Jan - 31st Dec
erpnext.setup.fiscal_years = {
"Afghanistan": ["12-21", "12-20"],
"Australia": ["07-01", "06-30"],
"Bangladesh": ["07-01", "06-30"],
"Canada": ["04-01", "03-31"],
Afghanistan: ["12-21", "12-20"],
Australia: ["07-01", "06-30"],
Bangladesh: ["07-01", "06-30"],
Canada: ["04-01", "03-31"],
"Costa Rica": ["10-01", "09-30"],
"Egypt": ["07-01", "06-30"],
Egypt: ["07-01", "06-30"],
"Hong Kong": ["04-01", "03-31"],
"India": ["04-01", "03-31"],
"Iran": ["06-23", "06-22"],
"Myanmar": ["04-01", "03-31"],
India: ["04-01", "03-31"],
Iran: ["06-23", "06-22"],
Myanmar: ["04-01", "03-31"],
"New Zealand": ["04-01", "03-31"],
"Pakistan": ["07-01", "06-30"],
"Singapore": ["04-01", "03-31"],
Pakistan: ["07-01", "06-30"],
Singapore: ["04-01", "03-31"],
"South Africa": ["03-01", "02-28"],
"Thailand": ["10-01", "09-30"],
Thailand: ["10-01", "09-30"],
"United Kingdom": ["04-01", "03-31"],
};

View File

@@ -3,104 +3,114 @@
erpnext.SMSManager = function SMSManager(doc) {
var me = this;
this.setup = function() {
this.setup = function () {
var default_msg = {
'Lead' : '',
'Opportunity' : 'Your enquiry has been logged into the system. Ref No: ' + doc.name,
'Quotation' : 'Quotation ' + doc.name + ' has been sent via email. Thanks!',
'Sales Order' : 'Sales Order ' + doc.name + ' has been created against '
+ (doc.quotation_no ? ('Quote No:' + doc.quotation_no) : '')
+ (doc.po_no ? (' for your PO: ' + doc.po_no) : ''),
'Delivery Note' : 'Items has been delivered against delivery note: ' + doc.name
+ (doc.po_no ? (' for your PO: ' + doc.po_no) : ''),
'Sales Invoice': 'Invoice ' + doc.name + ' has been sent via email '
+ (doc.po_no ? (' for your PO: ' + doc.po_no) : ''),
'Material Request' : 'Material Request ' + doc.name + ' has been raised in the system',
'Purchase Order' : 'Purchase Order ' + doc.name + ' has been sent via email',
'Purchase Receipt' : 'Items has been received against purchase receipt: ' + doc.name
}
if (in_list(['Sales Order', 'Delivery Note', 'Sales Invoice'], doc.doctype))
this.show(doc.contact_person, 'Customer', doc.customer, '', default_msg[doc.doctype]);
else if (doc.doctype === 'Quotation')
this.show(doc.contact_person, 'Customer', doc.party_name, '', default_msg[doc.doctype]);
else if (in_list(['Purchase Order', 'Purchase Receipt'], doc.doctype))
this.show(doc.contact_person, 'Supplier', doc.supplier, '', default_msg[doc.doctype]);
else if (doc.doctype == 'Lead')
this.show('', '', '', doc.mobile_no, default_msg[doc.doctype]);
else if (doc.doctype == 'Opportunity')
this.show('', '', '', doc.contact_no, default_msg[doc.doctype]);
else if (doc.doctype == 'Material Request')
this.show('', '', '', '', default_msg[doc.doctype]);
Lead: "",
Opportunity: "Your enquiry has been logged into the system. Ref No: " + doc.name,
Quotation: "Quotation " + doc.name + " has been sent via email. Thanks!",
"Sales Order":
"Sales Order " +
doc.name +
" has been created against " +
(doc.quotation_no ? "Quote No:" + doc.quotation_no : "") +
(doc.po_no ? " for your PO: " + doc.po_no : ""),
"Delivery Note":
"Items has been delivered against delivery note: " +
doc.name +
(doc.po_no ? " for your PO: " + doc.po_no : ""),
"Sales Invoice":
"Invoice " +
doc.name +
" has been sent via email " +
(doc.po_no ? " for your PO: " + doc.po_no : ""),
"Material Request": "Material Request " + doc.name + " has been raised in the system",
"Purchase Order": "Purchase Order " + doc.name + " has been sent via email",
"Purchase Receipt": "Items has been received against purchase receipt: " + doc.name,
};
if (in_list(["Sales Order", "Delivery Note", "Sales Invoice"], doc.doctype))
this.show(doc.contact_person, "Customer", doc.customer, "", default_msg[doc.doctype]);
else if (doc.doctype === "Quotation")
this.show(doc.contact_person, "Customer", doc.party_name, "", default_msg[doc.doctype]);
else if (in_list(["Purchase Order", "Purchase Receipt"], doc.doctype))
this.show(doc.contact_person, "Supplier", doc.supplier, "", default_msg[doc.doctype]);
else if (doc.doctype == "Lead") this.show("", "", "", doc.mobile_no, default_msg[doc.doctype]);
else if (doc.doctype == "Opportunity")
this.show("", "", "", doc.contact_no, default_msg[doc.doctype]);
else if (doc.doctype == "Material Request") this.show("", "", "", "", default_msg[doc.doctype]);
};
this.get_contact_number = function(contact, ref_doctype, ref_name) {
this.get_contact_number = function (contact, ref_doctype, ref_name) {
frappe.call({
method: "frappe.core.doctype.sms_settings.sms_settings.get_contact_number",
args: {
contact_name: contact,
ref_doctype: ref_doctype,
ref_name: ref_name
ref_name: ref_name,
},
callback: function(r) {
if(r.exc) { frappe.msgprint(r.exc); return; }
callback: function (r) {
if (r.exc) {
frappe.msgprint(r.exc);
return;
}
me.number = r.message;
me.show_dialog();
}
},
});
};
this.show = function(contact, ref_doctype, ref_name, mobile_nos, message) {
this.show = function (contact, ref_doctype, ref_name, mobile_nos, message) {
this.message = message;
if (mobile_nos) {
me.number = mobile_nos;
me.show_dialog();
} else if (contact){
this.get_contact_number(contact, ref_doctype, ref_name)
} else if (contact) {
this.get_contact_number(contact, ref_doctype, ref_name);
} else {
me.show_dialog();
}
}
this.show_dialog = function() {
if(!me.dialog)
me.make_dialog();
};
this.show_dialog = function () {
if (!me.dialog) me.make_dialog();
me.dialog.set_values({
'message': me.message,
'number': me.number
})
message: me.message,
number: me.number,
});
me.dialog.show();
}
this.make_dialog = function() {
};
this.make_dialog = function () {
var d = new frappe.ui.Dialog({
title: 'Send SMS',
title: "Send SMS",
width: 400,
fields: [
{fieldname:'number', fieldtype:'Data', label:'Mobile Number', reqd:1},
{fieldname:'message', fieldtype:'Text', label:'Message', reqd:1},
{fieldname:'send', fieldtype:'Button', label:'Send'}
]
})
d.fields_dict.send.input.onclick = function() {
{ fieldname: "number", fieldtype: "Data", label: "Mobile Number", reqd: 1 },
{ fieldname: "message", fieldtype: "Text", label: "Message", reqd: 1 },
{ fieldname: "send", fieldtype: "Button", label: "Send" },
],
});
d.fields_dict.send.input.onclick = function () {
var btn = d.fields_dict.send.input;
var v = me.dialog.get_values();
if(v) {
if (v) {
$(btn).set_working();
frappe.call({
method: "frappe.core.doctype.sms_settings.sms_settings.send_sms",
args: {
receiver_list: [v.number],
msg: v.message
msg: v.message,
},
callback: function(r) {
callback: function (r) {
$(btn).done_working();
if(r.exc) {frappe.msgprint(r.exc); return; }
if (r.exc) {
frappe.msgprint(r.exc);
return;
}
me.dialog.hide();
}
},
});
}
}
};
this.dialog = d;
}
};
this.setup();
}
};

View File

@@ -1,68 +1,104 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
constructor(wrapper, opts) {
var args = {
title: __("Stock Analytics"),
parent: $(wrapper).find('.layout-main'),
parent: $(wrapper).find(".layout-main"),
page: wrapper.page,
doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand",
"Fiscal Year", "Serial No"],
doctypes: [
"Item",
"Item Group",
"Warehouse",
"Stock Ledger Entry",
"Brand",
"Fiscal Year",
"Serial No",
],
tree_grid: {
show: true,
parent_field: "parent_item_group",
formatter: function(item) {
if(!item.is_group) {
return repl("<a \
formatter: function (item) {
if (!item.is_group) {
return repl(
"<a \
onclick='frappe.cur_grid_report.show_stock_ledger(\"%(value)s\")'>\
%(value)s</a>", {
%(value)s</a>",
{
value: item.name,
});
}
);
} else {
return item.name;
}
}
},
},
}
};
if(opts) $.extend(args, opts);
if (opts) $.extend(args, opts);
super(args);
this.filters = [
{fieldtype:"Select", label: __("Value or Qty"), fieldname: "value_or_qty",
options:[{label:__("Value"), value:"Value"}, {label:__("Quantity"), value:"Quantity"}],
filter: function(val, item, opts, me) {
{
fieldtype: "Select",
label: __("Value or Qty"),
fieldname: "value_or_qty",
options: [
{ label: __("Value"), value: "Value" },
{ label: __("Quantity"), value: "Quantity" },
],
filter: function (val, item, opts, me) {
return me.apply_zero_filter(val, item, opts, me);
}},
{fieldtype:"Select", label: __("Brand"), link:"Brand", fieldname: "brand",
default_value: __("Select Brand..."), filter: function(val, item, opts) {
},
},
{
fieldtype: "Select",
label: __("Brand"),
link: "Brand",
fieldname: "brand",
default_value: __("Select Brand..."),
filter: function (val, item, opts) {
return val == opts.default_value || item.brand == val || item._show;
}, link_formatter: {filter_input: "brand"}},
{fieldtype:"Select", label: __("Warehouse"), link:"Warehouse", fieldname: "warehouse",
default_value: __("Select Warehouse...")},
{fieldtype:"Date", label: __("From Date"), fieldname: "from_date"},
{fieldtype:"Date", label: __("To Date"), fieldname: "to_date"},
{fieldtype:"Select", label: __("Range"), fieldname: "range",
options:[
{label:__("Daily"), value:"Daily"},
{label:__("Weekly"), value:"Weekly"},
{label:__("Monthly"), value:"Monthly"},
{label:__("Quarterly"), value:"Quarterly"},
{label:__("Yearly"), value:"Yearly"},
]}
},
link_formatter: { filter_input: "brand" },
},
{
fieldtype: "Select",
label: __("Warehouse"),
link: "Warehouse",
fieldname: "warehouse",
default_value: __("Select Warehouse..."),
},
{ fieldtype: "Date", label: __("From Date"), fieldname: "from_date" },
{ fieldtype: "Date", label: __("To Date"), fieldname: "to_date" },
{
fieldtype: "Select",
label: __("Range"),
fieldname: "range",
options: [
{ label: __("Daily"), value: "Daily" },
{ label: __("Weekly"), value: "Weekly" },
{ label: __("Monthly"), value: "Monthly" },
{ label: __("Quarterly"), value: "Quarterly" },
{ label: __("Yearly"), value: "Yearly" },
],
},
];
}
setup_columns() {
var std_columns = [
{id: "name", name: __("Item"), field: "name", width: 300},
{id: "brand", name: __("Brand"), field: "brand", width: 100},
{id: "stock_uom", name: __("UOM"), field: "stock_uom", width: 100},
{id: "opening", name: __("Opening"), field: "opening", hidden: true,
formatter: this.currency_formatter}
{ id: "name", name: __("Item"), field: "name", width: 300 },
{ id: "brand", name: __("Brand"), field: "brand", width: 100 },
{ id: "stock_uom", name: __("UOM"), field: "stock_uom", width: 100 },
{
id: "opening",
name: __("Opening"),
field: "opening",
hidden: true,
formatter: this.currency_formatter,
},
];
this.make_date_range_columns();
@@ -79,24 +115,24 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
}
init_filter_values() {
super.init_filter_values();
this.filter_inputs.range && this.filter_inputs.range.val('Monthly');
this.filter_inputs.range && this.filter_inputs.range.val("Monthly");
}
prepare_data() {
var me = this;
if(!this.data) {
if (!this.data) {
var items = this.prepare_tree("Item", "Item Group");
me.parent_map = {};
me.item_by_name = {};
me.data = [];
$.each(items, function(i, v) {
$.each(items, function (i, v) {
var d = copy_dict(v);
me.data.push(d);
me.item_by_name[d.name] = d;
if(d.parent_item_group) {
if (d.parent_item_group) {
me.parent_map[d.name] = d.parent_item_group;
}
me.reset_item_values(d);
@@ -105,7 +141,7 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
this.data[0].checked = true;
} else {
// otherwise, only reset values
$.each(this.data, function(i, d) {
$.each(this.data, function (i, d) {
me.reset_item_values(d);
d["closing_qty_value"] = 0;
});
@@ -113,7 +149,6 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
this.prepare_balances();
this.update_groups();
}
prepare_balances() {
var me = this;
@@ -124,24 +159,25 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
this.item_warehouse = {};
this.serialized_buying_rates = this.get_serialized_buying_rates();
for(var i=0, j=data.length; i<j; i++) {
for (var i = 0, j = data.length; i < j; i++) {
let diff = 0;
var sl = data[i];
sl.posting_datetime = sl.posting_date + " " + sl.posting_time;
var posting_datetime = frappe.datetime.str_to_obj(sl.posting_datetime);
if(me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) {
if (me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) {
var item = me.item_by_name[sl.item_code];
if(item.closing_qty_value==undefined) item.closing_qty_value = 0;
if (item.closing_qty_value == undefined) item.closing_qty_value = 0;
if(me.value_or_qty!="Quantity") {
if (me.value_or_qty != "Quantity") {
var wh = me.get_item_warehouse(sl.warehouse, sl.item_code);
var valuation_method = item.valuation_method ?
item.valuation_method : frappe.sys_defaults.valuation_method;
var valuation_method = item.valuation_method
? item.valuation_method
: frappe.sys_defaults.valuation_method;
var is_fifo = valuation_method == "FIFO";
if(sl.voucher_type=="Stock Reconciliation") {
diff = (sl.qty_after_transaction * sl.valuation_rate) - item.closing_qty_value;
if (sl.voucher_type == "Stock Reconciliation") {
diff = sl.qty_after_transaction * sl.valuation_rate - item.closing_qty_value;
wh.fifo_stack = [[sl.qty_after_transaction, sl.valuation_rate, sl.posting_date]];
wh.balance_qty = sl.qty_after_transaction;
wh.balance_value = sl.valuation_rate * sl.qty_after_transaction;
@@ -149,16 +185,16 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
diff = me.get_value_diff(wh, sl, is_fifo);
}
} else {
if(sl.voucher_type=="Stock Reconciliation") {
if (sl.voucher_type == "Stock Reconciliation") {
diff = sl.qty_after_transaction - item.closing_qty_value;
} else {
diff = sl.qty;
}
}
if(posting_datetime < from_date) {
if (posting_datetime < from_date) {
item.opening += diff;
} else if(posting_datetime <= to_date) {
} else if (posting_datetime <= to_date) {
item[me.column_map[sl.posting_date].field] += diff;
} else {
break;
@@ -170,25 +206,23 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
}
update_groups() {
var me = this;
$.each(this.data, function(i, item) {
$.each(this.data, function (i, item) {
// update groups
if(!item.is_group && me.apply_filter(item, "brand")) {
if (!item.is_group && me.apply_filter(item, "brand")) {
var balance = item.opening;
$.each(me.columns, function(i, col) {
if(col.formatter==me.currency_formatter && !col.hidden) {
$.each(me.columns, function (i, col) {
if (col.formatter == me.currency_formatter && !col.hidden) {
item[col.field] = balance + item[col.field];
balance = item[col.field];
}
});
var parent = me.parent_map[item.name];
while(parent) {
while (parent) {
var parent_group = me.item_by_name[parent];
$.each(me.columns, function(c, col) {
$.each(me.columns, function (c, col) {
if (col.formatter == me.currency_formatter) {
parent_group[col.field] =
flt(parent_group[col.field])
+ flt(item[col.field]);
parent_group[col.field] = flt(parent_group[col.field]) + flt(item[col.field]);
}
});
parent = me.parent_map[parent];
@@ -200,7 +234,7 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
frappe.route_options = {
item_code: item_code,
from_date: this.from_date,
to_date: this.to_date
to_date: this.to_date,
};
frappe.set_route("query-report", "Stock Ledger");
}

View File

@@ -3,10 +3,13 @@
erpnext.StockGridReport = class StockGridReport extends frappe.views.TreeGridReport {
get_item_warehouse(warehouse, item) {
if(!this.item_warehouse[item]) this.item_warehouse[item] = {};
if(!this.item_warehouse[item][warehouse]) this.item_warehouse[item][warehouse] = {
balance_qty: 0.0, balance_value: 0.0, fifo_stack: []
};
if (!this.item_warehouse[item]) this.item_warehouse[item] = {};
if (!this.item_warehouse[item][warehouse])
this.item_warehouse[item][warehouse] = {
balance_qty: 0.0,
balance_value: 0.0,
fifo_stack: [],
};
return this.item_warehouse[item][warehouse];
}
@@ -14,47 +17,43 @@ erpnext.StockGridReport = class StockGridReport extends frappe.views.TreeGridRep
// value
let value_diff = 0;
if(sl.qty > 0) {
if (sl.qty > 0) {
// incoming - rate is given
let rate = sl.incoming_rate;
let add_qty = sl.qty;
if(wh.balance_qty < 0) {
if (wh.balance_qty < 0) {
// negative valuation
// only add value of quantity if
// the balance goes above 0
add_qty = wh.balance_qty + sl.qty;
if(add_qty < 0) {
if (add_qty < 0) {
add_qty = 0;
}
}
if(sl.serial_no) {
if (sl.serial_no) {
value_diff = this.get_serialized_value_diff(sl);
} else {
value_diff = (rate * add_qty);
value_diff = rate * add_qty;
}
if(add_qty)
wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]);
if (add_qty) wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]);
} else {
// called everytime for maintaining fifo stack
var fifo_value_diff = this.get_fifo_value_diff(wh, sl);
// outgoing
if(sl.serial_no) {
if (sl.serial_no) {
value_diff = -1 * this.get_serialized_value_diff(sl);
} else if(is_fifo) {
} else if (is_fifo) {
value_diff = fifo_value_diff;
} else {
// average rate for weighted average
let rate = (wh.balance_qty.toFixed(2) == 0.00 ? 0 :
flt(wh.balance_value) / flt(wh.balance_qty));
let rate = wh.balance_qty.toFixed(2) == 0.0 ? 0 : flt(wh.balance_value) / flt(wh.balance_qty);
// no change in value if negative qty
if((wh.balance_qty + sl.qty).toFixed(2) >= 0.00)
value_diff = (rate * sl.qty);
else
value_diff = -wh.balance_value;
if ((wh.balance_qty + sl.qty).toFixed(2) >= 0.0) value_diff = rate * sl.qty;
else value_diff = -wh.balance_value;
}
}
@@ -69,14 +68,14 @@ erpnext.StockGridReport = class StockGridReport extends frappe.views.TreeGridRep
var fifo_value_diff = 0.0;
var qty = -sl.qty;
for(var i=0, j=fifo_stack.length; i<j; i++) {
for (var i = 0, j = fifo_stack.length; i < j; i++) {
var batch = fifo_stack.pop();
if(batch[0] >= qty) {
if (batch[0] >= qty) {
batch[0] = batch[0] - qty;
fifo_value_diff += (qty * batch[1]);
fifo_value_diff += qty * batch[1];
qty = 0.0;
if(batch[0]) {
if (batch[0]) {
// batch still has qty put it back
fifo_stack.push(batch);
}
@@ -85,7 +84,7 @@ erpnext.StockGridReport = class StockGridReport extends frappe.views.TreeGridRep
break;
} else {
// consume this batch fully
fifo_value_diff += (batch[0] * batch[1]);
fifo_value_diff += batch[0] * batch[1];
qty = qty - batch[0];
}
}
@@ -99,8 +98,8 @@ erpnext.StockGridReport = class StockGridReport extends frappe.views.TreeGridRep
var value_diff = 0.0;
$.each(sl.serial_no.trim().split("\n"), function(i, sr) {
if(sr) {
$.each(sl.serial_no.trim().split("\n"), function (i, sr) {
if (sr) {
value_diff += flt(me.serialized_buying_rates[sr.trim().toLowerCase()]);
}
});
@@ -112,7 +111,7 @@ erpnext.StockGridReport = class StockGridReport extends frappe.views.TreeGridRep
var serialized_buying_rates = {};
if (frappe.report_dump.data["Serial No"]) {
$.each(frappe.report_dump.data["Serial No"], function(i, sn) {
$.each(frappe.report_dump.data["Serial No"], function (i, sn) {
serialized_buying_rates[sn.name.toLowerCase()] = flt(sn.incoming_rate);
});
}

View File

@@ -1,13 +1,17 @@
frappe.ui.form.ControlData = class ControlData extends frappe.ui.form.ControlData {
frappe.ui.form.ControlData = class ControlData extends frappe.ui.form.ControlData {
make_input() {
super.make_input();
if (this.df.options == 'Phone') {
if (this.df.options == "Phone") {
this.setup_phone();
}
if (this.frm && this.frm.fields_dict) {
Object.values(this.frm.fields_dict).forEach(function(field) {
if (field.df.read_only === 1 && field.df.options === 'Phone'
&& field.disp_area.style[0] != 'display' && !field.has_icon) {
Object.values(this.frm.fields_dict).forEach(function (field) {
if (
field.df.read_only === 1 &&
field.df.options === "Phone" &&
field.disp_area.style[0] != "display" &&
!field.has_icon
) {
field.setup_phone && field.setup_phone();
field.has_icon = true;
}
@@ -16,15 +20,18 @@ frappe.ui.form.ControlData = class ControlData extends frappe.ui.form.ControlDat
}
setup_phone() {
if (frappe.phone_call.handler) {
let control = this.df.read_only ? '.control-value' : '.control-input';
this.$wrapper.find(control)
.append(`
let control = this.df.read_only ? ".control-value" : ".control-input";
this.$wrapper
.find(control)
.append(
`
<span class="phone-btn">
<a class="btn-open no-decoration" title="${__('Make a call')}">
${frappe.utils.icon('call')}
<a class="btn-open no-decoration" title="${__("Make a call")}">
${frappe.utils.icon("call")}
</span>
`)
.find('.phone-btn')
`
)
.find(".phone-btn")
.click(() => {
frappe.phone_call.handler(this.get_value(), this.frm);
});

File diff suppressed because it is too large Load Diff

View File

@@ -58,13 +58,15 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
return;
}
me.update_table(data).then(row => {
this.play_success_sound();
resolve(row);
}).catch(() => {
this.play_fail_sound();
reject();
});
me.update_table(data)
.then((row) => {
this.play_success_sound();
resolve(row);
})
.catch(() => {
this.play_fail_sound();
reject();
});
});
});
}
@@ -87,7 +89,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
let cur_grid = this.frm.fields_dict[this.items_table_name].grid;
frappe.flags.trigger_from_barcode_scanner = true;
const {item_code, barcode, batch_no, serial_no, uom} = data;
const { item_code, barcode, batch_no, serial_no, uom } = data;
let row = this.get_row_to_modify_on_scan(item_code, batch_no, uom, barcode);
@@ -116,16 +118,17 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
frappe.run_serially([
() => this.set_selector_trigger_flag(data),
() => this.set_item(row, item_code, barcode, batch_no, serial_no).then(qty => {
this.show_scan_message(row.idx, row.item_code, qty);
}),
() =>
this.set_item(row, item_code, barcode, batch_no, serial_no).then((qty) => {
this.show_scan_message(row.idx, row.item_code, qty);
}),
() => this.set_barcode_uom(row, uom),
() => this.set_serial_no(row, serial_no),
() => this.set_batch_no(row, batch_no),
() => this.set_barcode(row, barcode),
() => this.clean_up(),
() => this.revert_selector_flag(),
() => resolve(row)
() => resolve(row),
]);
});
}
@@ -133,7 +136,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
// batch and serial selector is reduandant when all info can be added by scan
// this flag on item row is used by transaction.js to avoid triggering selector
set_selector_trigger_flag(data) {
const {batch_no, serial_no, has_batch_no, has_serial_no} = data;
const { batch_no, serial_no, has_batch_no, has_serial_no } = data;
const require_selecting_batch = has_batch_no && !batch_no;
const require_selecting_serial = has_serial_no && !serial_no;
@@ -149,17 +152,17 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
}
set_item(row, item_code, barcode, batch_no, serial_no) {
return new Promise(resolve => {
return new Promise((resolve) => {
const increment = async (value = 1) => {
const item_data = {item_code: item_code, use_serial_batch_fields: 1.0};
const item_data = { item_code: item_code, use_serial_batch_fields: 1.0 };
frappe.flags.trigger_from_barcode_scanner = true;
item_data[this.qty_field] = Number((row[this.qty_field] || 0)) + Number(value);
item_data[this.qty_field] = Number(row[this.qty_field] || 0) + Number(value);
await frappe.model.set_value(row.doctype, row.name, item_data);
return value;
};
if (this.prompt_qty) {
frappe.prompt(__("Please enter quantity for item {0}", [item_code]), ({value}) => {
frappe.prompt(__("Please enter quantity for item {0}", [item_code]), ({ value }) => {
increment(value).then((value) => resolve(value));
});
} else if (this.frm.has_items) {
@@ -175,14 +178,15 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
this.dialog = new frappe.ui.Dialog({
title: __("Scan barcode for item {0}", [item_code]),
fields: me.get_fields_for_dialog(row, item_code, barcode, batch_no, serial_no),
})
});
this.dialog.set_primary_action(__("Update"), () => {
const item_data = {item_code: item_code};
const item_data = { item_code: item_code };
item_data[this.qty_field] = this.dialog.get_value("scanned_qty");
item_data["has_item_scanned"] = 1;
this.remaining_qty = flt(this.dialog.get_value("qty")) - flt(this.dialog.get_value("scanned_qty"));
this.remaining_qty =
flt(this.dialog.get_value("qty")) - flt(this.dialog.get_value("scanned_qty"));
frappe.model.set_value(row.doctype, row.name, item_data);
frappe.run_serially([
@@ -190,7 +194,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
() => this.set_barcode(row, this.dialog.get_value("barcode")),
() => this.set_serial_no(row, this.dialog.get_value("serial_no")),
() => this.add_child_for_remaining_qty(row),
() => this.clean_up()
() => this.clean_up(),
]);
this.dialog.hide();
@@ -219,9 +223,9 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
if (r.message) {
this.update_dialog_values(item_code, r);
}
})
});
}
}
},
},
{
fieldtype: "Section Break",
@@ -245,8 +249,8 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
},
{
fieldtype: "Section Break",
}
]
},
];
if (batch_no) {
fields.push({
@@ -256,7 +260,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
label: __("Batch No"),
default: batch_no,
read_only: 1,
hidden: 1
hidden: 1,
});
}
@@ -278,7 +282,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
label: __("Barcode"),
default: barcode,
read_only: 1,
hidden: 1
hidden: 1,
});
}
@@ -286,18 +290,18 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
}
update_dialog_values(scanned_item, r) {
const {item_code, barcode, batch_no, serial_no} = r.message;
const { item_code, barcode, batch_no, serial_no } = r.message;
this.dialog.set_value("barcode_scanner", "");
if (item_code === scanned_item &&
(this.dialog.get_value("barcode") === barcode || batch_no || serial_no)) {
if (
item_code === scanned_item &&
(this.dialog.get_value("barcode") === barcode || batch_no || serial_no)
) {
if (batch_no) {
this.dialog.set_value("batch_no", batch_no);
}
if (serial_no) {
this.validate_duplicate_serial_no(serial_no);
let serial_nos = this.dialog.get_value("serial_no") + "\n" + serial_no;
this.dialog.set_value("serial_no", serial_nos);
@@ -309,8 +313,9 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
}
validate_duplicate_serial_no(serial_no) {
let serial_nos = this.dialog.get_value("serial_no") ?
this.dialog.get_value("serial_no").split("\n") : [];
let serial_nos = this.dialog.get_value("serial_no")
? this.dialog.get_value("serial_no").split("\n")
: [];
if (in_list(serial_nos, serial_no)) {
frappe.throw(__("Serial No {0} already scanned", [serial_no]));
@@ -318,12 +323,19 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
}
add_child_for_remaining_qty(prev_row) {
if (this.remaining_qty && this.remaining_qty >0) {
if (this.remaining_qty && this.remaining_qty > 0) {
let cur_grid = this.frm.fields_dict[this.items_table_name].grid;
let row = frappe.model.add_child(this.frm.doc, cur_grid.doctype, this.items_table_name);
let ignore_fields = ["name", "idx", "batch_no", "barcode",
"received_qty", "serial_no", "has_item_scanned"];
let ignore_fields = [
"name",
"idx",
"batch_no",
"barcode",
"received_qty",
"serial_no",
"has_item_scanned",
];
for (let key in prev_row) {
if (in_list(ignore_fields, key)) {
@@ -379,7 +391,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
if (exist) {
this.show_alert(__("Row #{0}: Qty increased by {1}", [idx, qty]), "green");
} else {
this.show_alert(__("Row #{0}: Item added", [idx]), "green")
this.show_alert(__("Row #{0}: Item added", [idx]), "green");
}
}
@@ -401,17 +413,19 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
const matching_row = (row) => {
const item_match = row.item_code == item_code;
const batch_match = (!row[this.batch_no_field] || row[this.batch_no_field] == batch_no);
const batch_match = !row[this.batch_no_field] || row[this.batch_no_field] == batch_no;
const uom_match = !uom || row[this.uom_field] == uom;
const qty_in_limit = flt(row[this.qty_field]) < flt(row[this.max_qty_field]);
const item_scanned = row.has_item_scanned;
return item_match
&& uom_match
&& !item_scanned
&& (!is_batch_no_scan || batch_match)
&& (!check_max_qty || qty_in_limit)
}
return (
item_match &&
uom_match &&
!item_scanned &&
(!is_batch_no_scan || batch_match) &&
(!check_max_qty || qty_in_limit)
);
};
return this.items_table.find(matching_row) || this.get_existing_blank_row();
}
@@ -432,7 +446,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
this.scan_barcode_field.set_value("");
refresh_field(this.items_table_name);
}
show_alert(msg, indicator, duration=3) {
frappe.show_alert({message: msg, indicator: indicator}, duration);
show_alert(msg, indicator, duration = 3) {
frappe.show_alert({ message: msg, indicator: indicator }, duration);
}
};
};

View File

@@ -1,6 +1,8 @@
frappe.provide('frappe.ui.form');
frappe.provide("frappe.ui.form");
frappe.ui.form.ContactAddressQuickEntryForm = class ContactAddressQuickEntryForm extends frappe.ui.form.QuickEntryForm {
frappe.ui.form.ContactAddressQuickEntryForm = class ContactAddressQuickEntryForm extends (
frappe.ui.form.QuickEntryForm
) {
constructor(doctype, after_insert, init_callback, doc, force) {
super(doctype, after_insert, init_callback, doc, force);
this.skip_redirect_on_error = true;
@@ -17,8 +19,8 @@ frappe.ui.form.ContactAddressQuickEntryForm = class ContactAddressQuickEntryForm
* Therefor, resulting in the fields being "hidden".
*/
const map_field_names = {
"email_address": "email_id",
"mobile_number": "mobile_no",
email_address: "email_id",
mobile_number: "mobile_no",
};
Object.entries(map_field_names).forEach(([fieldname, new_fieldname]) => {
@@ -30,71 +32,73 @@ frappe.ui.form.ContactAddressQuickEntryForm = class ContactAddressQuickEntryForm
}
get_variant_fields() {
var variant_fields = [{
fieldtype: "Section Break",
label: __("Primary Contact Details"),
collapsible: 1
},
{
label: __("Email Id"),
fieldname: "email_address",
fieldtype: "Data",
options: "Email",
},
{
fieldtype: "Column Break"
},
{
label: __("Mobile Number"),
fieldname: "mobile_number",
fieldtype: "Data"
},
{
fieldtype: "Section Break",
label: __("Primary Address Details"),
collapsible: 1
},
{
label: __("Address Line 1"),
fieldname: "address_line1",
fieldtype: "Data"
},
{
label: __("Address Line 2"),
fieldname: "address_line2",
fieldtype: "Data"
},
{
label: __("ZIP Code"),
fieldname: "pincode",
fieldtype: "Data"
},
{
fieldtype: "Column Break"
},
{
label: __("City"),
fieldname: "city",
fieldtype: "Data"
},
{
label: __("State"),
fieldname: "state",
fieldtype: "Data"
},
{
label: __("Country"),
fieldname: "country",
fieldtype: "Link",
options: "Country"
},
{
label: __("Customer POS Id"),
fieldname: "customer_pos_id",
fieldtype: "Data",
hidden: 1
}];
var variant_fields = [
{
fieldtype: "Section Break",
label: __("Primary Contact Details"),
collapsible: 1,
},
{
label: __("Email Id"),
fieldname: "email_address",
fieldtype: "Data",
options: "Email",
},
{
fieldtype: "Column Break",
},
{
label: __("Mobile Number"),
fieldname: "mobile_number",
fieldtype: "Data",
},
{
fieldtype: "Section Break",
label: __("Primary Address Details"),
collapsible: 1,
},
{
label: __("Address Line 1"),
fieldname: "address_line1",
fieldtype: "Data",
},
{
label: __("Address Line 2"),
fieldname: "address_line2",
fieldtype: "Data",
},
{
label: __("ZIP Code"),
fieldname: "pincode",
fieldtype: "Data",
},
{
fieldtype: "Column Break",
},
{
label: __("City"),
fieldname: "city",
fieldtype: "Data",
},
{
label: __("State"),
fieldname: "state",
fieldtype: "Data",
},
{
label: __("Country"),
fieldname: "country",
fieldtype: "Link",
options: "Country",
},
{
label: __("Customer POS Id"),
fieldname: "customer_pos_id",
fieldtype: "Data",
hidden: 1,
},
];
return variant_fields;
}
}
};

View File

@@ -6,21 +6,21 @@ erpnext.utils.CRMActivities = class CRMActivities {
refresh() {
var me = this;
$(this.open_activities_wrapper).empty();
let cur_form_footer = this.form_wrapper.find('.form-footer');
let cur_form_footer = this.form_wrapper.find(".form-footer");
// all activities
if (!$(this.all_activities_wrapper).find('.form-footer').length) {
if (!$(this.all_activities_wrapper).find(".form-footer").length) {
this.all_activities_wrapper.empty();
$(cur_form_footer).appendTo(this.all_activities_wrapper);
// remove frappe-control class to avoid absolute position for action-btn
$(this.all_activities_wrapper).removeClass('frappe-control');
$(this.all_activities_wrapper).removeClass("frappe-control");
// hide new event button
$('.timeline-actions').find('.btn-default').hide();
$(".timeline-actions").find(".btn-default").hide();
// hide new comment box
$(".comment-box").hide();
// show only communications by default
$($('.timeline-content').find('.nav-link')[0]).tab('show');
$($(".timeline-content").find(".nav-link")[0]).tab("show");
}
// open activities
@@ -28,66 +28,70 @@ erpnext.utils.CRMActivities = class CRMActivities {
method: "erpnext.crm.utils.get_open_activities",
args: {
ref_doctype: this.frm.doc.doctype,
ref_docname: this.frm.doc.name
ref_docname: this.frm.doc.name,
},
callback: (r) => {
if (!r.exc) {
var activities_html = frappe.render_template('crm_activities', {
var activities_html = frappe.render_template("crm_activities", {
tasks: r.message.tasks,
events: r.message.events
events: r.message.events,
});
$(activities_html).appendTo(me.open_activities_wrapper);
$(".open-tasks").find(".completion-checkbox").on("click", function() {
me.update_status(this, "ToDo");
});
$(".open-tasks")
.find(".completion-checkbox")
.on("click", function () {
me.update_status(this, "ToDo");
});
$(".open-events").find(".completion-checkbox").on("click", function() {
me.update_status(this, "Event");
});
$(".open-events")
.find(".completion-checkbox")
.on("click", function () {
me.update_status(this, "Event");
});
me.create_task();
me.create_event();
}
}
},
});
}
create_task () {
create_task() {
let me = this;
let _create_task = () => {
const args = {
doc: me.frm.doc,
frm: me.frm,
title: __("New Task")
title: __("New Task"),
};
let composer = new frappe.views.InteractionComposer(args);
composer.dialog.get_field('interaction_type').set_value("ToDo");
composer.dialog.get_field("interaction_type").set_value("ToDo");
// hide column having interaction type field
$(composer.dialog.get_field('interaction_type').wrapper).closest('.form-column').hide();
$(composer.dialog.get_field("interaction_type").wrapper).closest(".form-column").hide();
// hide summary field
$(composer.dialog.get_field('summary').wrapper).closest('.form-section').hide();
$(composer.dialog.get_field("summary").wrapper).closest(".form-section").hide();
};
$(".new-task-btn").click(_create_task);
}
create_event () {
create_event() {
let me = this;
let _create_event = () => {
const args = {
doc: me.frm.doc,
frm: me.frm,
title: __("New Event")
title: __("New Event"),
};
let composer = new frappe.views.InteractionComposer(args);
composer.dialog.get_field('interaction_type').set_value("Event");
$(composer.dialog.get_field('interaction_type').wrapper).hide();
composer.dialog.get_field("interaction_type").set_value("Event");
$(composer.dialog.get_field("interaction_type").wrapper).hide();
};
$(".new-event-btn").click(_create_event);
}
async update_status (input_field, doctype) {
async update_status(input_field, doctype) {
let completed = $(input_field).prop("checked") ? 1 : 0;
let docname = $(input_field).attr("name");
if (completed) {
@@ -104,132 +108,129 @@ erpnext.utils.CRMNotes = class CRMNotes {
refresh() {
var me = this;
this.notes_wrapper.find('.notes-section').remove();
this.notes_wrapper.find(".notes-section").remove();
let notes = this.frm.doc.notes || [];
notes.sort(
function(a, b) {
return new Date(b.added_on) - new Date(a.added_on);
}
);
notes.sort(function (a, b) {
return new Date(b.added_on) - new Date(a.added_on);
});
let notes_html = frappe.render_template(
'crm_notes',
{
notes: notes
}
);
let notes_html = frappe.render_template("crm_notes", {
notes: notes,
});
$(notes_html).appendTo(this.notes_wrapper);
this.add_note();
$(".notes-section").find(".edit-note-btn").on("click", function() {
me.edit_note(this);
});
$(".notes-section")
.find(".edit-note-btn")
.on("click", function () {
me.edit_note(this);
});
$(".notes-section").find(".delete-note-btn").on("click", function() {
me.delete_note(this);
});
$(".notes-section")
.find(".delete-note-btn")
.on("click", function () {
me.delete_note(this);
});
}
add_note () {
add_note() {
let me = this;
let _add_note = () => {
var d = new frappe.ui.Dialog({
title: __('Add a Note'),
title: __("Add a Note"),
fields: [
{
"label": "Note",
"fieldname": "note",
"fieldtype": "Text Editor",
"reqd": 1,
"enable_mentions": true,
}
label: "Note",
fieldname: "note",
fieldtype: "Text Editor",
reqd: 1,
enable_mentions: true,
},
],
primary_action: function() {
primary_action: function () {
var data = d.get_values();
frappe.call({
method: "add_note",
doc: me.frm.doc,
args: {
note: data.note
note: data.note,
},
freeze: true,
callback: function(r) {
callback: function (r) {
if (!r.exc) {
me.frm.refresh_field("notes");
me.refresh();
}
d.hide();
}
},
});
},
primary_action_label: __('Add')
primary_action_label: __("Add"),
});
d.show();
};
$(".new-note-btn").click(_add_note);
}
edit_note (edit_btn) {
edit_note(edit_btn) {
var me = this;
let row = $(edit_btn).closest('.comment-content');
let row = $(edit_btn).closest(".comment-content");
let row_id = row.attr("name");
let row_content = $(row).find(".content").html();
if (row_content) {
var d = new frappe.ui.Dialog({
title: __('Edit Note'),
title: __("Edit Note"),
fields: [
{
"label": "Note",
"fieldname": "note",
"fieldtype": "Text Editor",
"default": row_content
}
label: "Note",
fieldname: "note",
fieldtype: "Text Editor",
default: row_content,
},
],
primary_action: function() {
primary_action: function () {
var data = d.get_values();
frappe.call({
method: "edit_note",
doc: me.frm.doc,
args: {
note: data.note,
row_id: row_id
row_id: row_id,
},
freeze: true,
callback: function(r) {
callback: function (r) {
if (!r.exc) {
me.frm.refresh_field("notes");
me.refresh();
d.hide();
}
}
},
});
},
primary_action_label: __('Done')
primary_action_label: __("Done"),
});
d.show();
}
}
delete_note (delete_btn) {
delete_note(delete_btn) {
var me = this;
let row_id = $(delete_btn).closest('.comment-content').attr("name");
let row_id = $(delete_btn).closest(".comment-content").attr("name");
frappe.call({
method: "delete_note",
doc: me.frm.doc,
args: {
row_id: row_id
row_id: row_id,
},
freeze: true,
callback: function(r) {
callback: function (r) {
if (!r.exc) {
me.frm.refresh_field("notes");
me.refresh();
}
}
},
});
}
};

View File

@@ -1,3 +1,3 @@
frappe.provide('frappe.ui.form');
frappe.provide("frappe.ui.form");
frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.ContactAddressQuickEntryForm;

View File

@@ -1,4 +1,4 @@
frappe.provide('erpnext.accounts');
frappe.provide("erpnext.accounts");
erpnext.accounts.dimensions = {
setup_dimension_filters(frm, doctype) {
@@ -12,36 +12,38 @@ erpnext.accounts.dimensions = {
frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimensions",
args: {
'with_cost_center_and_project': true
with_cost_center_and_project: true,
},
callback: function(r) {
callback: function (r) {
me.accounting_dimensions = r.message[0];
// Ignoring "Project" as it is already handled specifically in Sales Order and Delivery Note
me.accounting_dimensions = me.accounting_dimensions.filter(x=>{return x.document_type != "Project"});
me.accounting_dimensions = me.accounting_dimensions.filter((x) => {
return x.document_type != "Project";
});
me.default_dimensions = r.message[1];
me.setup_filters(frm, doctype);
}
},
});
},
setup_filters(frm, doctype) {
if (doctype == 'Payment Entry' && this.accounting_dimensions) {
frm.dimension_filters = this.accounting_dimensions
if (doctype == "Payment Entry" && this.accounting_dimensions) {
frm.dimension_filters = this.accounting_dimensions;
}
if (this.accounting_dimensions) {
this.accounting_dimensions.forEach((dimension) => {
frappe.model.with_doctype(dimension['document_type'], () => {
frappe.model.with_doctype(dimension["document_type"], () => {
let parent_fields = [];
frappe.meta.get_docfields(doctype).forEach((df) => {
if (df.fieldtype === 'Link' && df.options === 'Account') {
if (df.fieldtype === "Link" && df.options === "Account") {
parent_fields.push(df.fieldname);
} else if (df.fieldtype === 'Table') {
this.setup_child_filters(frm, df.options, df.fieldname, dimension['fieldname']);
} else if (df.fieldtype === "Table") {
this.setup_child_filters(frm, df.options, df.fieldname, dimension["fieldname"]);
}
if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
this.setup_account_filters(frm, dimension['fieldname'], parent_fields);
if (frappe.meta.has_field(doctype, dimension["fieldname"])) {
this.setup_account_filters(frm, dimension["fieldname"], parent_fields);
}
});
});
@@ -55,12 +57,12 @@ erpnext.accounts.dimensions = {
if (frappe.meta.has_field(doctype, dimension)) {
frappe.model.with_doctype(doctype, () => {
frappe.meta.get_docfields(doctype).forEach((df) => {
if (df.fieldtype === 'Link' && df.options === 'Account') {
if (df.fieldtype === "Link" && df.options === "Account") {
fields.push(df.fieldname);
}
});
frm.set_query(dimension, parentfield, function(doc, cdt, cdn) {
frm.set_query(dimension, parentfield, function (doc, cdt, cdn) {
let row = locals[cdt][cdn];
return erpnext.queries.get_filtered_dimensions(row, fields, dimension, doc.company);
});
@@ -69,7 +71,7 @@ erpnext.accounts.dimensions = {
},
setup_account_filters(frm, dimension, fields) {
frm.set_query(dimension, function(doc) {
frm.set_query(dimension, function (doc) {
return erpnext.queries.get_filtered_dimensions(doc, fields, dimension, doc.company);
});
},
@@ -78,18 +80,26 @@ erpnext.accounts.dimensions = {
if (this.accounting_dimensions) {
this.accounting_dimensions.forEach((dimension) => {
if (frm.is_new()) {
if (frm.doc.company && Object.keys(this.default_dimensions || {}).length > 0
&& this.default_dimensions[frm.doc.company]) {
let default_dimension = this.default_dimensions[frm.doc.company][dimension['fieldname']];
if (
frm.doc.company &&
Object.keys(this.default_dimensions || {}).length > 0 &&
this.default_dimensions[frm.doc.company]
) {
let default_dimension =
this.default_dimensions[frm.doc.company][dimension["fieldname"]];
if (default_dimension) {
if (frappe.meta.has_field(doctype, dimension['fieldname'])) {
frm.set_value(dimension['fieldname'], default_dimension);
if (frappe.meta.has_field(doctype, dimension["fieldname"])) {
frm.set_value(dimension["fieldname"], default_dimension);
}
$.each(frm.doc.items || frm.doc.accounts || [], function(i, row) {
frappe.model.set_value(row.doctype, row.name, dimension['fieldname'], default_dimension);
$.each(frm.doc.items || frm.doc.accounts || [], function (i, row) {
frappe.model.set_value(
row.doctype,
row.name,
dimension["fieldname"],
default_dimension
);
});
}
}
@@ -102,8 +112,8 @@ erpnext.accounts.dimensions = {
if (frappe.meta.has_field(frm.doctype, fieldname) && this.accounting_dimensions) {
this.accounting_dimensions.forEach((dimension) => {
let row = frappe.get_doc(cdt, cdn);
frm.script_manager.copy_from_first_row(fieldname, row, [dimension['fieldname']]);
frm.script_manager.copy_from_first_row(fieldname, row, [dimension["fieldname"]]);
});
}
}
},
};

View File

@@ -3,7 +3,7 @@ erpnext.ItemSelector = class ItemSelector {
$.extend(this, opts);
if (!this.item_field) {
this.item_field = 'item_code';
this.item_field = "item_code";
}
if (!this.item_query) {
@@ -16,39 +16,43 @@ erpnext.ItemSelector = class ItemSelector {
setup() {
var me = this;
if(!this.grid.add_items_button) {
this.grid.add_items_button = this.grid.add_custom_button(__('Add Items'), function() {
if(!me.dialog) {
if (!this.grid.add_items_button) {
this.grid.add_items_button = this.grid.add_custom_button(__("Add Items"), function () {
if (!me.dialog) {
me.make_dialog();
}
me.dialog.show();
me.render_items();
setTimeout(function() { me.dialog.input.focus(); }, 1000);
setTimeout(function () {
me.dialog.input.focus();
}, 1000);
});
}
}
make_dialog() {
this.dialog = new frappe.ui.Dialog({
title: __('Add Items')
title: __("Add Items"),
});
var body = $(this.dialog.body);
body.html('<div><p><input type="text" class="form-control"></p>\
<br><div class="results"></div></div>');
body.html(
'<div><p><input type="text" class="form-control"></p>\
<br><div class="results"></div></div>'
);
this.dialog.input = body.find('.form-control');
this.dialog.results = body.find('.results');
this.dialog.input = body.find(".form-control");
this.dialog.results = body.find(".results");
var me = this;
this.dialog.results.on('click', '.image-view-item', function() {
me.add_item($(this).attr('data-name'));
this.dialog.results.on("click", ".image-view-item", function () {
me.add_item($(this).attr("data-name"));
});
this.dialog.input.on('keyup', function() {
if(me.timeout_id) {
this.dialog.input.on("keyup", function () {
if (me.timeout_id) {
clearTimeout(me.timeout_id);
}
me.timeout_id = setTimeout(function() {
me.timeout_id = setTimeout(function () {
me.render_items();
me.timeout_id = undefined;
}, 500);
@@ -61,33 +65,34 @@ erpnext.ItemSelector = class ItemSelector {
// find row with item if exists
$.each(this.frm.doc.items || [], (i, d) => {
if(d[this.item_field]===item_code) {
frappe.model.set_value(d.doctype, d.name, 'qty', d.qty + 1);
frappe.show_alert({message: __("Added {0} ({1})", [item_code, d.qty]), indicator: 'green'});
if (d[this.item_field] === item_code) {
frappe.model.set_value(d.doctype, d.name, "qty", d.qty + 1);
frappe.show_alert({ message: __("Added {0} ({1})", [item_code, d.qty]), indicator: "green" });
added = true;
return false;
}
});
if(!added) {
if (!added) {
var d = null;
frappe.run_serially([
() => { d = this.grid.add_new_row(); },
() => {
d = this.grid.add_new_row();
},
() => frappe.model.set_value(d.doctype, d.name, this.item_field, item_code),
() => frappe.timeout(0.1),
() => {
frappe.model.set_value(d.doctype, d.name, 'qty', 1);
frappe.show_alert({message: __("Added {0} ({1})", [item_code, 1]), indicator: 'green'});
}
frappe.model.set_value(d.doctype, d.name, "qty", 1);
frappe.show_alert({ message: __("Added {0} ({1})", [item_code, 1]), indicator: "green" });
},
]);
}
}
render_items() {
let args = {
query: this.item_query,
filters: {}
filters: {},
};
args.txt = this.dialog.input.val();
args.as_dict = 1;
@@ -97,14 +102,14 @@ erpnext.ItemSelector = class ItemSelector {
}
var me = this;
frappe.link_search("Item", args, function(results) {
$.each(results, function(i, d) {
if(!d.image) {
frappe.link_search("Item", args, function (results) {
$.each(results, function (i, d) {
if (!d.image) {
d.abbr = frappe.get_abbr(d.item_name);
d.color = frappe.get_palette(d.item_name);
}
});
me.dialog.results.html(frappe.render_template('item_selector', {'data': results}));
me.dialog.results.html(frappe.render_template("item_selector", { data: results }));
});
}
};

View File

@@ -1,62 +1,74 @@
erpnext.landed_cost_taxes_and_charges = {
setup_triggers: function(doctype) {
setup_triggers: function (doctype) {
frappe.ui.form.on(doctype, {
refresh: function(frm) {
let tax_field = frm.doc.doctype == 'Landed Cost Voucher' ? 'taxes' : 'additional_costs';
frm.set_query("expense_account", tax_field, function() {
refresh: function (frm) {
let tax_field = frm.doc.doctype == "Landed Cost Voucher" ? "taxes" : "additional_costs";
frm.set_query("expense_account", tax_field, function () {
return {
filters: {
"account_type": ['in', ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation", "Expenses Included In Asset Valuation"]],
"company": frm.doc.company
}
account_type: [
"in",
[
"Tax",
"Chargeable",
"Income Account",
"Expenses Included In Valuation",
"Expenses Included In Asset Valuation",
],
],
company: frm.doc.company,
},
};
});
},
set_account_currency: function(frm, cdt, cdn) {
set_account_currency: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
if (row.expense_account) {
frappe.db.get_value('Account', row.expense_account, 'account_currency', function(value) {
frappe.db.get_value("Account", row.expense_account, "account_currency", function (value) {
frappe.model.set_value(cdt, cdn, "account_currency", value.account_currency);
frm.events.set_exchange_rate(frm, cdt, cdn);
});
}
},
set_exchange_rate: function(frm, cdt, cdn) {
set_exchange_rate: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
if (row.account_currency == company_currency) {
row.exchange_rate = 1;
frm.set_df_property('taxes', 'hidden', 1, row.name, 'exchange_rate');
frm.set_df_property("taxes", "hidden", 1, row.name, "exchange_rate");
} else if (!row.exchange_rate || row.exchange_rate == 1) {
frm.set_df_property('taxes', 'hidden', 0, row.name, 'exchange_rate');
frm.set_df_property("taxes", "hidden", 0, row.name, "exchange_rate");
frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_exchange_rate",
args: {
posting_date: frm.doc.posting_date,
account: row.expense_account,
account_currency: row.account_currency,
company: frm.doc.company
company: frm.doc.company,
},
callback: function(r) {
callback: function (r) {
if (r.message) {
frappe.model.set_value(cdt, cdn, "exchange_rate", r.message);
}
}
},
});
}
frm.refresh_field('taxes');
frm.refresh_field("taxes");
},
set_base_amount: function(frm, cdt, cdn) {
set_base_amount: function (frm, cdt, cdn) {
let row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "base_amount",
flt(flt(row.amount)*row.exchange_rate, precision("base_amount", row)));
}
frappe.model.set_value(
cdt,
cdn,
"base_amount",
flt(flt(row.amount) * row.exchange_rate, precision("base_amount", row))
);
},
});
}
}
},
};

View File

@@ -1,60 +1,78 @@
frappe.provide('erpnext.accounts');
frappe.provide("erpnext.accounts");
erpnext.accounts.ledger_preview = {
show_accounting_ledger_preview(frm) {
let me = this;
if(!frm.is_new() && frm.doc.docstatus == 0) {
frm.add_custom_button(__('Accounting Ledger'), function() {
frappe.call({
"type": "GET",
"method": "erpnext.controllers.stock_controller.show_accounting_ledger_preview",
"args": {
"company": frm.doc.company,
"doctype": frm.doc.doctype,
"docname": frm.doc.name
},
"callback": function(response) {
me.make_dialog("Accounting Ledger Preview", "accounting_ledger_preview_html", response.message.gl_columns, response.message.gl_data);
}
})
}, __("Preview"));
if (!frm.is_new() && frm.doc.docstatus == 0) {
frm.add_custom_button(
__("Accounting Ledger"),
function () {
frappe.call({
type: "GET",
method: "erpnext.controllers.stock_controller.show_accounting_ledger_preview",
args: {
company: frm.doc.company,
doctype: frm.doc.doctype,
docname: frm.doc.name,
},
callback: function (response) {
me.make_dialog(
"Accounting Ledger Preview",
"accounting_ledger_preview_html",
response.message.gl_columns,
response.message.gl_data
);
},
});
},
__("Preview")
);
}
},
show_stock_ledger_preview(frm) {
let me = this
if(!frm.is_new() && frm.doc.docstatus == 0) {
frm.add_custom_button(__('Stock Ledger'), function() {
frappe.call({
"type": "GET",
"method": "erpnext.controllers.stock_controller.show_stock_ledger_preview",
"args": {
"company": frm.doc.company,
"doctype": frm.doc.doctype,
"docname": frm.doc.name
},
"callback": function(response) {
me.make_dialog("Stock Ledger Preview", "stock_ledger_preview_html", response.message.sl_columns, response.message.sl_data);
}
})
}, __("Preview"));
let me = this;
if (!frm.is_new() && frm.doc.docstatus == 0) {
frm.add_custom_button(
__("Stock Ledger"),
function () {
frappe.call({
type: "GET",
method: "erpnext.controllers.stock_controller.show_stock_ledger_preview",
args: {
company: frm.doc.company,
doctype: frm.doc.doctype,
docname: frm.doc.name,
},
callback: function (response) {
me.make_dialog(
"Stock Ledger Preview",
"stock_ledger_preview_html",
response.message.sl_columns,
response.message.sl_data
);
},
});
},
__("Preview")
);
}
},
make_dialog(label, fieldname, columns, data) {
let me = this;
let dialog = new frappe.ui.Dialog({
"size": "extra-large",
"title": __(label),
"fields": [
size: "extra-large",
title: __(label),
fields: [
{
"fieldtype": "HTML",
"fieldname": fieldname,
fieldtype: "HTML",
fieldname: fieldname,
},
]
],
});
setTimeout(function() {
setTimeout(function () {
me.get_datatable(columns, data, dialog.get_field(fieldname).wrapper);
}, 200);
@@ -70,9 +88,6 @@ erpnext.accounts.ledger_preview = {
inlineFilters: true,
};
new frappe.DataTable(
wrapper,
datatable_options
);
}
}
new frappe.DataTable(wrapper, datatable_options);
},
};

View File

@@ -3,18 +3,19 @@
frappe.provide("erpnext.utils");
const SALES_DOCTYPES = ['Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice'];
const PURCHASE_DOCTYPES = ['Supplier Quotation','Purchase Order', 'Purchase Receipt', 'Purchase Invoice'];
const SALES_DOCTYPES = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"];
const PURCHASE_DOCTYPES = ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"];
erpnext.utils.get_party_details = function(frm, method, args, callback) {
erpnext.utils.get_party_details = function (frm, method, args, callback) {
if (!method) {
method = "erpnext.accounts.party.get_party_details";
}
if (!args) {
if ((frm.doctype != "Purchase Order" && frm.doc.customer)
|| (frm.doc.party_name && in_list(['Quotation', 'Opportunity'], frm.doc.doctype))) {
if (
(frm.doctype != "Purchase Order" && frm.doc.customer) ||
(frm.doc.party_name && in_list(["Quotation", "Opportunity"], frm.doc.doctype))
) {
let party_type = "Customer";
if (frm.doc.quotation_to && in_list(["Lead", "Prospect"], frm.doc.quotation_to)) {
party_type = frm.doc.quotation_to;
@@ -23,14 +24,14 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
args = {
party: frm.doc.customer || frm.doc.party_name,
party_type: party_type,
price_list: frm.doc.selling_price_list
price_list: frm.doc.selling_price_list,
};
} else if (frm.doc.supplier) {
args = {
party: frm.doc.supplier,
party_type: "Supplier",
bill_date: frm.doc.bill_date,
price_list: frm.doc.buying_price_list
price_list: frm.doc.buying_price_list,
};
}
@@ -38,14 +39,14 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
if (in_list(SALES_DOCTYPES, frm.doc.doctype)) {
args = {
party: frm.doc.customer || frm.doc.party_name,
party_type: 'Customer'
party_type: "Customer",
};
}
if (in_list(PURCHASE_DOCTYPES, frm.doc.doctype)) {
args = {
party: frm.doc.supplier,
party_type: 'Supplier'
party_type: "Supplier",
};
}
}
@@ -72,13 +73,26 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
}
}
if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
args.posting_date, args.party_type=="Customer" ? "customer": "supplier")) return;
if (
!erpnext.utils.validate_mandatory(
frm,
"Posting / Transaction Date",
args.posting_date,
args.party_type == "Customer" ? "customer" : "supplier"
)
)
return;
}
if (!erpnext.utils.validate_mandatory(frm, "Company", frm.doc.company, args.party_type=="Customer" ? "customer": "supplier")) {
if (
!erpnext.utils.validate_mandatory(
frm,
"Company",
frm.doc.company,
args.party_type == "Customer" ? "customer" : "supplier"
)
) {
return;
}
@@ -88,7 +102,7 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
frappe.call({
method: method,
args: args,
callback: function(r) {
callback: function (r) {
if (r.message) {
frm.supplier_tds = r.message.supplier_tds;
frm.updating_party_details = true;
@@ -99,28 +113,28 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
if (callback) callback();
frm.refresh();
erpnext.utils.add_item(frm);
}
},
]);
}
}
},
});
}
};
erpnext.utils.add_item = function(frm) {
erpnext.utils.add_item = function (frm) {
if (frm.is_new()) {
var prev_route = frappe.get_prev_route();
if (prev_route[1]==='Item' && !(frm.doc.items && frm.doc.items.length)) {
if (prev_route[1] === "Item" && !(frm.doc.items && frm.doc.items.length)) {
// add row
var item = frm.add_child('items');
frm.refresh_field('items');
var item = frm.add_child("items");
frm.refresh_field("items");
// set item
frappe.model.set_value(item.doctype, item.name, 'item_code', prev_route[2]);
frappe.model.set_value(item.doctype, item.name, "item_code", prev_route[2]);
}
}
}
};
erpnext.utils.get_address_display = function(frm, address_field, display_field, is_your_company_address) {
erpnext.utils.get_address_display = function (frm, address_field, display_field, is_your_company_address) {
if (frm.updating_party_details) return;
if (!address_field) {
@@ -135,29 +149,46 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field,
if (frm.doc[address_field]) {
frappe.call({
method: "frappe.contacts.doctype.address.address.get_address_display",
args: {"address_dict": frm.doc[address_field] },
callback: function(r) {
args: { address_dict: frm.doc[address_field] },
callback: function (r) {
if (r.message) {
frm.set_value(display_field, r.message)
frm.set_value(display_field, r.message);
}
}
})
},
});
} else {
frm.set_value(display_field, '');
frm.set_value(display_field, "");
}
};
erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billing_address_field, shipping_address_field) {
erpnext.utils.set_taxes_from_address = function (
frm,
triggered_from_field,
billing_address_field,
shipping_address_field
) {
if (frm.updating_party_details) return;
if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
if (!erpnext.utils.validate_mandatory(frm, "Lead / Customer / Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) {
if (
!erpnext.utils.validate_mandatory(
frm,
"Lead / Customer / Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name,
triggered_from_field
)
) {
return;
}
if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
if (
!erpnext.utils.validate_mandatory(
frm,
"Posting / Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date,
triggered_from_field
)
) {
return;
}
} else {
@@ -167,35 +198,47 @@ erpnext.utils.set_taxes_from_address = function(frm, triggered_from_field, billi
frappe.call({
method: "erpnext.accounts.party.get_address_tax_category",
args: {
"tax_category": frm.doc.tax_category,
"billing_address": frm.doc[billing_address_field],
"shipping_address": frm.doc[shipping_address_field]
tax_category: frm.doc.tax_category,
billing_address: frm.doc[billing_address_field],
shipping_address: frm.doc[shipping_address_field],
},
callback: function(r) {
if (!r.exc){
callback: function (r) {
if (!r.exc) {
if (frm.doc.tax_category != r.message) {
frm.set_value("tax_category", r.message);
} else {
erpnext.utils.set_taxes(frm, triggered_from_field);
}
}
}
},
});
};
erpnext.utils.set_taxes = function(frm, triggered_from_field) {
erpnext.utils.set_taxes = function (frm, triggered_from_field) {
if (frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
if (!erpnext.utils.validate_mandatory(frm, "Company", frm.doc.company, triggered_from_field)) {
return;
}
if (!erpnext.utils.validate_mandatory(frm, "Lead / Customer / Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name, triggered_from_field)) {
if (
!erpnext.utils.validate_mandatory(
frm,
"Lead / Customer / Supplier",
frm.doc.customer || frm.doc.supplier || frm.doc.lead || frm.doc.party_name,
triggered_from_field
)
) {
return;
}
if (!erpnext.utils.validate_mandatory(frm, "Posting / Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date, triggered_from_field)) {
if (
!erpnext.utils.validate_mandatory(
frm,
"Posting / Transaction Date",
frm.doc.posting_date || frm.doc.transaction_date,
triggered_from_field
)
) {
return;
}
} else {
@@ -204,15 +247,15 @@ erpnext.utils.set_taxes = function(frm, triggered_from_field) {
var party_type, party;
if (frm.doc.lead) {
party_type = 'Lead';
party_type = "Lead";
party = frm.doc.lead;
} else if (frm.doc.customer) {
party_type = 'Customer';
party_type = "Customer";
party = frm.doc.customer;
} else if (frm.doc.supplier) {
party_type = 'Supplier';
party_type = "Supplier";
party = frm.doc.supplier;
} else if (frm.doc.quotation_to){
} else if (frm.doc.quotation_to) {
party_type = frm.doc.quotation_to;
party = frm.doc.party_name;
}
@@ -224,21 +267,22 @@ erpnext.utils.set_taxes = function(frm, triggered_from_field) {
frappe.call({
method: "erpnext.accounts.party.set_taxes",
args: {
"party": party,
"party_type": party_type,
"posting_date": frm.doc.posting_date || frm.doc.transaction_date,
"company": frm.doc.company,
"customer_group": frm.doc.customer_group,
"supplier_group": frm.doc.supplier_group,
"tax_category": frm.doc.tax_category,
"billing_address": ((frm.doc.customer || frm.doc.lead) ? (frm.doc.customer_address) : (frm.doc.supplier_address)),
"shipping_address": frm.doc.shipping_address_name
party: party,
party_type: party_type,
posting_date: frm.doc.posting_date || frm.doc.transaction_date,
company: frm.doc.company,
customer_group: frm.doc.customer_group,
supplier_group: frm.doc.supplier_group,
tax_category: frm.doc.tax_category,
billing_address:
frm.doc.customer || frm.doc.lead ? frm.doc.customer_address : frm.doc.supplier_address,
shipping_address: frm.doc.shipping_address_name,
},
callback: function(r) {
if (r.message){
frm.set_value("taxes_and_charges", r.message)
callback: function (r) {
if (r.message) {
frm.set_value("taxes_and_charges", r.message);
}
}
},
});
};
@@ -266,20 +310,23 @@ erpnext.utils.get_contact_details = function (frm) {
}
};
erpnext.utils.validate_mandatory = function(frm, label, value, trigger_on) {
erpnext.utils.validate_mandatory = function (frm, label, value, trigger_on) {
if (!value) {
frm.doc[trigger_on] = "";
refresh_field(trigger_on);
frappe.throw({message:__("Please enter {0} first", [label]), title:__("Mandatory")});
frappe.throw({ message: __("Please enter {0} first", [label]), title: __("Mandatory") });
return false;
}
return true;
}
};
erpnext.utils.get_shipping_address = function(frm, callback) {
erpnext.utils.get_shipping_address = function (frm, callback) {
if (frm.doc.company) {
if ((frm.doc.inter_company_order_reference || frm.doc.internal_invoice_reference ||
frm.doc.internal_order_reference)) {
if (
frm.doc.inter_company_order_reference ||
frm.doc.internal_invoice_reference ||
frm.doc.internal_order_reference
) {
if (callback) {
return callback();
}
@@ -288,20 +335,20 @@ erpnext.utils.get_shipping_address = function(frm, callback) {
method: "erpnext.accounts.custom.address.get_shipping_address",
args: {
company: frm.doc.company,
address: frm.doc.shipping_address
address: frm.doc.shipping_address,
},
callback: function(r) {
callback: function (r) {
if (r.message) {
frm.set_value("shipping_address", r.message[0]) //Address title or name
frm.set_value("shipping_address_display", r.message[1]) //Address to be displayed on the page
frm.set_value("shipping_address", r.message[0]); //Address title or name
frm.set_value("shipping_address_display", r.message[1]); //Address to be displayed on the page
}
if (callback){
if (callback) {
return callback();
}
}
},
});
} else {
frappe.msgprint(__("Select company first"));
}
}
};

View File

@@ -4,7 +4,7 @@
frappe.provide("erpnext.selling");
erpnext.sales_common = {
setup_selling_controller:function() {
setup_selling_controller: function () {
erpnext.selling.SellingController = class SellingController extends erpnext.TransactionController {
setup() {
super.setup();
@@ -15,107 +15,123 @@ erpnext.sales_common = {
onload() {
super.onload();
this.setup_queries();
this.frm.set_query('shipping_rule', function() {
this.frm.set_query("shipping_rule", function () {
return {
filters: {
"shipping_rule_type": "Selling"
}
shipping_rule_type: "Selling",
},
};
});
this.frm.set_query('project', function(doc) {
this.frm.set_query("project", function (doc) {
return {
query: "erpnext.controllers.queries.get_project_name",
filters: {
'customer': doc.customer
}
}
customer: doc.customer,
},
};
});
}
setup_queries() {
var me = this;
$.each([["customer", "customer"],
["lead", "lead"]],
function(i, opts) {
if(me.frm.fields_dict[opts[0]])
me.frm.set_query(opts[0], erpnext.queries[opts[1]]);
});
$.each(
[
["customer", "customer"],
["lead", "lead"],
],
function (i, opts) {
if (me.frm.fields_dict[opts[0]]) me.frm.set_query(opts[0], erpnext.queries[opts[1]]);
}
);
me.frm.set_query('contact_person', erpnext.queries.contact_query);
me.frm.set_query('customer_address', erpnext.queries.address_query);
me.frm.set_query('shipping_address_name', erpnext.queries.address_query);
me.frm.set_query('dispatch_address_name', erpnext.queries.dispatch_address_query);
me.frm.set_query("contact_person", erpnext.queries.contact_query);
me.frm.set_query("customer_address", erpnext.queries.address_query);
me.frm.set_query("shipping_address_name", erpnext.queries.address_query);
me.frm.set_query("dispatch_address_name", erpnext.queries.dispatch_address_query);
erpnext.accounts.dimensions.setup_dimension_filters(me.frm, me.frm.doctype);
if(this.frm.fields_dict.selling_price_list) {
this.frm.set_query("selling_price_list", function() {
if (this.frm.fields_dict.selling_price_list) {
this.frm.set_query("selling_price_list", function () {
return { filters: { selling: 1 } };
});
}
if(this.frm.fields_dict.tc_name) {
this.frm.set_query("tc_name", function() {
if (this.frm.fields_dict.tc_name) {
this.frm.set_query("tc_name", function () {
return { filters: { selling: 1 } };
});
}
if(!this.frm.fields_dict["items"]) {
if (!this.frm.fields_dict["items"]) {
return;
}
if(this.frm.fields_dict["items"].grid.get_field('item_code')) {
this.frm.set_query("item_code", "items", function() {
if (this.frm.fields_dict["items"].grid.get_field("item_code")) {
this.frm.set_query("item_code", "items", function () {
return {
query: "erpnext.controllers.queries.item_query",
filters: {'is_sales_item': 1, 'customer': me.frm.doc.customer, 'has_variants': 0}
}
filters: { is_sales_item: 1, customer: me.frm.doc.customer, has_variants: 0 },
};
});
}
if(this.frm.fields_dict["packed_items"] &&
this.frm.fields_dict["packed_items"].grid.get_field('batch_no')) {
this.frm.set_query("batch_no", "packed_items", function(doc, cdt, cdn) {
return me.set_query_for_batch(doc, cdt, cdn)
if (
this.frm.fields_dict["packed_items"] &&
this.frm.fields_dict["packed_items"].grid.get_field("batch_no")
) {
this.frm.set_query("batch_no", "packed_items", function (doc, cdt, cdn) {
return me.set_query_for_batch(doc, cdt, cdn);
});
}
if(this.frm.fields_dict["items"].grid.get_field('item_code')) {
this.frm.set_query("item_tax_template", "items", function(doc, cdt, cdn) {
return me.set_query_for_item_tax_template(doc, cdt, cdn)
if (this.frm.fields_dict["items"].grid.get_field("item_code")) {
this.frm.set_query("item_tax_template", "items", function (doc, cdt, cdn) {
return me.set_query_for_item_tax_template(doc, cdt, cdn);
});
}
}
refresh() {
super.refresh();
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
frappe.dynamic_link = { doc: this.frm.doc, fieldname: "customer", doctype: "Customer" };
this.frm.toggle_display("customer_name",
(this.frm.doc.customer_name && this.frm.doc.customer_name!==this.frm.doc.customer));
this.frm.toggle_display(
"customer_name",
this.frm.doc.customer_name && this.frm.doc.customer_name !== this.frm.doc.customer
);
this.toggle_editable_price_list_rate();
}
customer() {
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function() {
erpnext.utils.get_party_details(this.frm, null, null, function () {
me.apply_price_list();
});
}
customer_address() {
erpnext.utils.get_address_display(this.frm, "customer_address");
erpnext.utils.set_taxes_from_address(this.frm, "customer_address", "customer_address", "shipping_address_name");
erpnext.utils.set_taxes_from_address(
this.frm,
"customer_address",
"customer_address",
"shipping_address_name"
);
}
shipping_address_name() {
erpnext.utils.get_address_display(this.frm, "shipping_address_name", "shipping_address");
erpnext.utils.set_taxes_from_address(this.frm, "shipping_address_name", "customer_address", "shipping_address_name");
erpnext.utils.set_taxes_from_address(
this.frm,
"shipping_address_name",
"customer_address",
"shipping_address_name"
);
}
dispatch_address_name() {
@@ -138,18 +154,17 @@ erpnext.sales_common = {
discount_percentage(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
item.discount_amount = 0.0;
this.apply_discount_on_item(doc, cdt, cdn, 'discount_percentage');
this.apply_discount_on_item(doc, cdt, cdn, "discount_percentage");
}
discount_amount(doc, cdt, cdn) {
if(doc.name === cdn) {
if (doc.name === cdn) {
return;
}
var item = frappe.get_doc(cdt, cdn);
item.discount_percentage = 0.0;
this.apply_discount_on_item(doc, cdt, cdn, 'discount_amount');
this.apply_discount_on_item(doc, cdt, cdn, "discount_amount");
}
commission_rate() {
@@ -157,40 +172,48 @@ erpnext.sales_common = {
}
total_commission() {
frappe.model.round_floats_in(this.frm.doc, ["amount_eligible_for_commission", "total_commission"]);
frappe.model.round_floats_in(this.frm.doc, [
"amount_eligible_for_commission",
"total_commission",
]);
const { amount_eligible_for_commission } = this.frm.doc;
if(!amount_eligible_for_commission) return;
if (!amount_eligible_for_commission) return;
this.frm.set_value(
"commission_rate", flt(
this.frm.doc.total_commission * 100.0 / amount_eligible_for_commission
)
"commission_rate",
flt((this.frm.doc.total_commission * 100.0) / amount_eligible_for_commission)
);
}
allocated_percentage(doc, cdt, cdn) {
var sales_person = frappe.get_doc(cdt, cdn);
if(sales_person.allocated_percentage) {
if (sales_person.allocated_percentage) {
sales_person.allocated_percentage = flt(
sales_person.allocated_percentage,
precision("allocated_percentage", sales_person)
);
sales_person.allocated_percentage = flt(sales_person.allocated_percentage,
precision("allocated_percentage", sales_person));
sales_person.allocated_amount = flt(this.frm.doc.amount_eligible_for_commission *
sales_person.allocated_percentage / 100.0,
precision("allocated_amount", sales_person));
refresh_field(["allocated_amount"], sales_person);
sales_person.allocated_amount = flt(
(this.frm.doc.amount_eligible_for_commission * sales_person.allocated_percentage) /
100.0,
precision("allocated_amount", sales_person)
);
refresh_field(["allocated_amount"], sales_person);
this.calculate_incentive(sales_person);
refresh_field(["allocated_percentage", "allocated_amount", "commission_rate","incentives"], sales_person.name,
sales_person.parentfield);
refresh_field(
["allocated_percentage", "allocated_amount", "commission_rate", "incentives"],
sales_person.name,
sales_person.parentfield
);
}
}
sales_person(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.calculate_incentive(row);
refresh_field("incentives",row.name,row.parentfield);
refresh_field("incentives", row.name, row.parentfield);
}
warehouse(doc, cdt, cdn) {
@@ -200,35 +223,47 @@ erpnext.sales_common = {
}
toggle_editable_price_list_rate() {
var df = frappe.meta.get_docfield(this.frm.doc.doctype + " Item", "price_list_rate", this.frm.doc.name);
var df = frappe.meta.get_docfield(
this.frm.doc.doctype + " Item",
"price_list_rate",
this.frm.doc.name
);
var editable_price_list_rate = cint(frappe.defaults.get_default("editable_price_list_rate"));
if(df && editable_price_list_rate) {
const parent_field = frappe.meta.get_parentfield(this.frm.doc.doctype, this.frm.doc.doctype + " Item");
if (df && editable_price_list_rate) {
const parent_field = frappe.meta.get_parentfield(
this.frm.doc.doctype,
this.frm.doc.doctype + " Item"
);
if (!this.frm.fields_dict[parent_field]) return;
this.frm.fields_dict[parent_field].grid.update_docfield_property(
'price_list_rate', 'read_only', 0
"price_list_rate",
"read_only",
0
);
}
}
calculate_commission() {
if(!this.frm.fields_dict.commission_rate || this.frm.doc.docstatus === 1) return;
if (!this.frm.fields_dict.commission_rate || this.frm.doc.docstatus === 1) return;
if(this.frm.doc.commission_rate > 100) {
if (this.frm.doc.commission_rate > 100) {
this.frm.set_value("commission_rate", 100);
frappe.throw(`${__(frappe.meta.get_label(
this.frm.doc.doctype, "commission_rate", this.frm.doc.name
))} ${__("cannot be greater than 100")}`);
frappe.throw(
`${__(
frappe.meta.get_label(this.frm.doc.doctype, "commission_rate", this.frm.doc.name)
)} ${__("cannot be greater than 100")}`
);
}
this.frm.doc.amount_eligible_for_commission = this.frm.doc.items.reduce(
(sum, item) => item.grant_commission ? sum + item.base_net_amount : sum, 0
)
(sum, item) => (item.grant_commission ? sum + item.base_net_amount : sum),
0
);
this.frm.doc.total_commission = flt(
this.frm.doc.amount_eligible_for_commission * this.frm.doc.commission_rate / 100.0,
(this.frm.doc.amount_eligible_for_commission * this.frm.doc.commission_rate) / 100.0,
precision("total_commission")
);
@@ -237,25 +272,24 @@ erpnext.sales_common = {
calculate_contribution() {
var me = this;
$.each(this.frm.doc.doctype.sales_team || [], function(i, sales_person) {
$.each(this.frm.doc.doctype.sales_team || [], function (i, sales_person) {
frappe.model.round_floats_in(sales_person);
if (!sales_person.allocated_percentage) return;
sales_person.allocated_amount = flt(
me.frm.doc.amount_eligible_for_commission
* sales_person.allocated_percentage
/ 100.0,
(me.frm.doc.amount_eligible_for_commission * sales_person.allocated_percentage) /
100.0,
precision("allocated_amount", sales_person)
);
});
}
calculate_incentive(row) {
if(row.allocated_amount)
{
if (row.allocated_amount) {
row.incentives = flt(
row.allocated_amount * row.commission_rate / 100.0,
precision("incentives", row));
(row.allocated_amount * row.commission_rate) / 100.0,
precision("incentives", row)
);
}
}
@@ -265,37 +299,41 @@ erpnext.sales_common = {
}
set_product_bundle_help(doc) {
if(!this.frm.fields_dict.packing_list) return;
if (!this.frm.fields_dict.packing_list) return;
if ((doc.packed_items || []).length) {
$(this.frm.fields_dict.packing_list.row.wrapper).toggle(true);
if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
var help_msg = "<div class='alert alert-warning'>" +
__("For 'Product Bundle' items, Warehouse, Serial No and Batch No will be considered from the 'Packing List' table. If Warehouse and Batch No are same for all packing items for any 'Product Bundle' item, those values can be entered in the main Item table, values will be copied to 'Packing List' table.")+
"</div>";
frappe.meta.get_docfield(doc.doctype, 'product_bundle_help', doc.name).options = help_msg;
if (in_list(["Delivery Note", "Sales Invoice"], doc.doctype)) {
var help_msg =
"<div class='alert alert-warning'>" +
__(
"For 'Product Bundle' items, Warehouse, Serial No and Batch No will be considered from the 'Packing List' table. If Warehouse and Batch No are same for all packing items for any 'Product Bundle' item, those values can be entered in the main Item table, values will be copied to 'Packing List' table."
) +
"</div>";
frappe.meta.get_docfield(doc.doctype, "product_bundle_help", doc.name).options =
help_msg;
}
} else {
$(this.frm.fields_dict.packing_list.row.wrapper).toggle(false);
if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
frappe.meta.get_docfield(doc.doctype, 'product_bundle_help', doc.name).options = '';
if (in_list(["Delivery Note", "Sales Invoice"], doc.doctype)) {
frappe.meta.get_docfield(doc.doctype, "product_bundle_help", doc.name).options = "";
}
}
refresh_field('product_bundle_help');
refresh_field("product_bundle_help");
}
company_address() {
var me = this;
if(this.frm.doc.company_address) {
if (this.frm.doc.company_address) {
frappe.call({
method: "frappe.contacts.doctype.address.address.get_address_display",
args: {"address_dict": this.frm.doc.company_address },
callback: function(r) {
if(r.message) {
me.frm.set_value("company_address_display", r.message)
args: { address_dict: this.frm.doc.company_address },
callback: function (r) {
if (r.message) {
me.frm.set_value("company_address_display", r.message);
}
}
})
},
});
} else {
this.frm.set_value("company_address_display", "");
}
@@ -314,79 +352,96 @@ erpnext.sales_common = {
let me = this;
let path = "assets/erpnext/js/utils/serial_no_batch_selector.js";
frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"])
.then((r) => {
if (r.message && (r.message.has_batch_no || r.message.has_serial_no)) {
item.has_serial_no = r.message.has_serial_no;
item.has_batch_no = r.message.has_batch_no;
item.type_of_transaction = item.qty > 0 ? "Outward":"Inward";
frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"]).then((r) => {
if (r.message && (r.message.has_batch_no || r.message.has_serial_no)) {
item.has_serial_no = r.message.has_serial_no;
item.has_batch_no = r.message.has_batch_no;
item.type_of_transaction = item.qty > 0 ? "Outward" : "Inward";
item.title = item.has_serial_no ?
__("Select Serial No") : __("Select Batch No");
item.title = item.has_serial_no ? __("Select Serial No") : __("Select Batch No");
if (item.has_serial_no && item.has_batch_no) {
item.title = __("Select Serial and Batch");
}
frappe.require(path, function() {
new erpnext.SerialBatchPackageSelector(
me.frm, item, (r) => {
if (r) {
let qty = Math.abs(r.total_qty);
if (doc.is_return) {
qty = qty * -1;
}
frappe.model.set_value(item.doctype, item.name, {
"serial_and_batch_bundle": r.name,
"use_serial_batch_fields": 0,
"qty": qty / flt(item.conversion_factor || 1, precision("conversion_factor", item))
});
}
}
);
});
if (item.has_serial_no && item.has_batch_no) {
item.title = __("Select Serial and Batch");
}
});
frappe.require(path, function () {
new erpnext.SerialBatchPackageSelector(me.frm, item, (r) => {
if (r) {
let qty = Math.abs(r.total_qty);
if (doc.is_return) {
qty = qty * -1;
}
frappe.model.set_value(item.doctype, item.name, {
serial_and_batch_bundle: r.name,
use_serial_batch_fields: 0,
qty:
qty /
flt(
item.conversion_factor || 1,
precision("conversion_factor", item)
),
});
}
});
});
}
});
}
update_auto_repeat_reference(doc) {
if (doc.auto_repeat) {
frappe.call({
method:"frappe.automation.doctype.auto_repeat.auto_repeat.update_reference",
args:{
method: "frappe.automation.doctype.auto_repeat.auto_repeat.update_reference",
args: {
docname: doc.auto_repeat,
reference:doc.name
reference: doc.name,
},
callback: function(r){
if (r.message=="success") {
frappe.show_alert({message:__("Auto repeat document updated"), indicator:'green'});
callback: function (r) {
if (r.message == "success") {
frappe.show_alert({
message: __("Auto repeat document updated"),
indicator: "green",
});
} else {
frappe.show_alert({message:__("An error occurred during the update process"), indicator:'red'});
frappe.show_alert({
message: __("An error occurred during the update process"),
indicator: "red",
});
}
}
})
},
});
}
}
project() {
let me = this;
if(in_list(["Delivery Note", "Sales Invoice", "Sales Order"], this.frm.doc.doctype)) {
if(this.frm.doc.project) {
if (in_list(["Delivery Note", "Sales Invoice", "Sales Order"], this.frm.doc.doctype)) {
if (this.frm.doc.project) {
frappe.call({
method:'erpnext.projects.doctype.project.project.get_cost_center_name' ,
args: {project: this.frm.doc.project},
callback: function(r, rt) {
if(!r.exc) {
$.each(me.frm.doc["items"] || [], function(i, row) {
if(r.message) {
frappe.model.set_value(row.doctype, row.name, "cost_center", r.message);
frappe.msgprint(__("Cost Center For Item with Item Code {0} has been Changed to {1}", [row.item_name, r.message]));
method: "erpnext.projects.doctype.project.project.get_cost_center_name",
args: { project: this.frm.doc.project },
callback: function (r, rt) {
if (!r.exc) {
$.each(me.frm.doc["items"] || [], function (i, row) {
if (r.message) {
frappe.model.set_value(
row.doctype,
row.name,
"cost_center",
r.message
);
frappe.msgprint(
__(
"Cost Center For Item with Item Code {0} has been Changed to {1}",
[row.item_name, r.message]
)
);
}
})
});
}
}
})
},
});
}
}
}
@@ -396,57 +451,60 @@ erpnext.sales_common = {
this.frm.set_value("additional_discount_percentage", 0);
}
};
}
}
},
};
erpnext.pre_sales = {
set_as_lost: function(doctype) {
set_as_lost: function (doctype) {
frappe.ui.form.on(doctype, {
set_as_lost_dialog: function(frm) {
set_as_lost_dialog: function (frm) {
var dialog = new frappe.ui.Dialog({
title: __("Set as Lost"),
fields: [
{
"fieldtype": "Table MultiSelect",
"label": __("Lost Reasons"),
"fieldname": "lost_reason",
"options": frm.doctype === 'Opportunity' ? 'Opportunity Lost Reason Detail': 'Quotation Lost Reason Detail',
"reqd": 1
fieldtype: "Table MultiSelect",
label: __("Lost Reasons"),
fieldname: "lost_reason",
options:
frm.doctype === "Opportunity"
? "Opportunity Lost Reason Detail"
: "Quotation Lost Reason Detail",
reqd: 1,
},
{
"fieldtype": "Table MultiSelect",
"label": __("Competitors"),
"fieldname": "competitors",
"options": "Competitor Detail"
fieldtype: "Table MultiSelect",
label: __("Competitors"),
fieldname: "competitors",
options: "Competitor Detail",
},
{
"fieldtype": "Small Text",
"label": __("Detailed Reason"),
"fieldname": "detailed_reason"
fieldtype: "Small Text",
label: __("Detailed Reason"),
fieldname: "detailed_reason",
},
],
primary_action: function() {
primary_action: function () {
let values = dialog.get_values();
frm.call({
doc: frm.doc,
method: 'declare_enquiry_lost',
method: "declare_enquiry_lost",
args: {
'lost_reasons_list': values.lost_reason,
'competitors': values.competitors ? values.competitors : [],
'detailed_reason': values.detailed_reason
lost_reasons_list: values.lost_reason,
competitors: values.competitors ? values.competitors : [],
detailed_reason: values.detailed_reason,
},
callback: function(r) {
callback: function (r) {
dialog.hide();
frm.reload_doc();
},
});
},
primary_action_label: __('Declare Lost')
primary_action_label: __("Declare Lost"),
});
dialog.show();
}
},
});
}
}
},
};

View File

@@ -4,30 +4,30 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
this.item = item;
this.qty = item.qty;
this.callback = callback;
this.bundle = this.item?.is_rejected ?
this.item.rejected_serial_and_batch_bundle : this.item.serial_and_batch_bundle;
this.bundle = this.item?.is_rejected
? this.item.rejected_serial_and_batch_bundle
: this.item.serial_and_batch_bundle;
this.make();
this.render_data();
}
make() {
let label = this.item?.has_serial_no ? __('Serial Nos') : __('Batch Nos');
let primary_label = this.bundle
? __('Update') : __('Add');
let label = this.item?.has_serial_no ? __("Serial Nos") : __("Batch Nos");
let primary_label = this.bundle ? __("Update") : __("Add");
if (this.item?.has_serial_no && this.item?.batch_no) {
label = __('Serial Nos / Batch Nos');
label = __("Serial Nos / Batch Nos");
}
primary_label += ' ' + label;
primary_label += " " + label;
this.dialog = new frappe.ui.Dialog({
title: this.item?.title || primary_label,
fields: this.get_dialog_fields(),
primary_action_label: primary_label,
primary_action: () => this.update_bundle_entries(),
secondary_action_label: __('Edit Full Form'),
secondary_action_label: __("Edit Full Form"),
secondary_action: () => this.edit_full_form(),
});
@@ -45,21 +45,21 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
if (qty > 0) {
this.dialog.set_value("qty", qty).then(() => {
if (this.item.serial_no && !this.item.serial_and_batch_bundle) {
let serial_nos = this.item.serial_no.split('\n');
let serial_nos = this.item.serial_no.split("\n");
if (serial_nos.length > 1) {
serial_nos.forEach(serial_no => {
serial_nos.forEach((serial_no) => {
this.dialog.fields_dict.entries.df.data.push({
serial_no: serial_no,
batch_no: this.item.batch_no
batch_no: this.item.batch_no,
});
});
} else {
this.dialog.set_value("scan_serial_no", this.item.serial_no);
}
frappe.model.set_value(this.item.doctype, this.item.name, 'serial_no', '');
frappe.model.set_value(this.item.doctype, this.item.name, "serial_no", "");
} else if (this.item.batch_no && !this.item.serial_and_batch_bundle) {
this.dialog.set_value("scan_batch_no", this.item.batch_no);
frappe.model.set_value(this.item.doctype, this.item.name, 'batch_no', '');
frappe.model.set_value(this.item.doctype, this.item.name, "batch_no", "");
}
this.dialog.fields_dict.entries.grid.refresh();
@@ -68,20 +68,20 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
}
get_serial_no_filters() {
let warehouse = this.item?.type_of_transaction === "Outward" ?
(this.item.warehouse || this.item.s_warehouse) : "";
let warehouse =
this.item?.type_of_transaction === "Outward" ? this.item.warehouse || this.item.s_warehouse : "";
if (this.frm.doc.doctype === 'Stock Entry') {
if (this.frm.doc.doctype === "Stock Entry") {
warehouse = this.item.s_warehouse || this.item.t_warehouse;
}
if (!warehouse && this.frm.doc.doctype === 'Stock Reconciliation') {
if (!warehouse && this.frm.doc.doctype === "Stock Reconciliation") {
warehouse = this.get_warehouse();
}
return {
'item_code': this.item.item_code,
'warehouse': ["=", warehouse]
item_code: this.item.item_code,
warehouse: ["=", warehouse],
};
}
@@ -89,71 +89,70 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
let fields = [];
fields.push({
fieldtype: 'Link',
fieldname: 'warehouse',
label: __('Warehouse'),
options: 'Warehouse',
fieldtype: "Link",
fieldname: "warehouse",
label: __("Warehouse"),
options: "Warehouse",
default: this.get_warehouse(),
onchange: () => {
this.item.warehouse = this.dialog.get_value('warehouse');
this.get_auto_data()
this.item.warehouse = this.dialog.get_value("warehouse");
this.get_auto_data();
},
get_query: () => {
return {
filters: {
'is_group': 0,
'company': this.frm.doc.company,
}
is_group: 0,
company: this.frm.doc.company,
},
};
}
},
});
if (this.frm.doc.doctype === 'Stock Entry'
&& this.frm.doc.purpose === 'Manufacture') {
if (this.frm.doc.doctype === "Stock Entry" && this.frm.doc.purpose === "Manufacture") {
fields.push({
fieldtype: 'Column Break',
fieldtype: "Column Break",
});
fields.push({
fieldtype: 'Link',
fieldname: 'work_order',
label: __('For Work Order'),
options: 'Work Order',
fieldtype: "Link",
fieldname: "work_order",
label: __("For Work Order"),
options: "Work Order",
read_only: 1,
default: this.frm.doc.work_order,
});
fields.push({
fieldtype: 'Section Break',
fieldtype: "Section Break",
});
}
fields.push({
fieldtype: 'Column Break',
fieldtype: "Column Break",
});
if (this.item.has_serial_no) {
fields.push({
fieldtype: 'Data',
options: 'Barcode',
fieldname: 'scan_serial_no',
label: __('Scan Serial No'),
fieldtype: "Data",
options: "Barcode",
fieldname: "scan_serial_no",
label: __("Scan Serial No"),
get_query: () => {
return {
filters: this.get_serial_no_filters()
filters: this.get_serial_no_filters(),
};
},
onchange: () => this.scan_barcode_data()
onchange: () => this.scan_barcode_data(),
});
}
if (this.item.has_batch_no && !this.item.has_serial_no) {
fields.push({
fieldtype: 'Data',
options: 'Barcode',
fieldname: 'scan_batch_no',
label: __('Scan Batch No'),
onchange: () => this.scan_barcode_data()
fieldtype: "Data",
options: "Barcode",
fieldname: "scan_batch_no",
label: __("Scan Batch No"),
onchange: () => this.scan_barcode_data(),
});
}
@@ -164,12 +163,12 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
}
fields.push({
fieldtype: 'Section Break',
fieldtype: "Section Break",
});
fields.push({
fieldname: 'entries',
fieldtype: 'Table',
fieldname: "entries",
fieldtype: "Table",
allow_bulk_edit: true,
data: [],
fields: this.get_dialog_table_fields(),
@@ -179,94 +178,95 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
}
get_attach_field() {
let label = this.item?.has_serial_no ? __('Serial Nos') : __('Batch Nos');
let primary_label = this.bundle
? __('Update') : __('Add');
let label = this.item?.has_serial_no ? __("Serial Nos") : __("Batch Nos");
let primary_label = this.bundle ? __("Update") : __("Add");
if (this.item?.has_serial_no && this.item?.has_batch_no) {
label = __('Serial Nos / Batch Nos');
label = __("Serial Nos / Batch Nos");
}
let fields = [
{
fieldtype: 'Section Break',
label: __('{0} {1} via CSV File', [primary_label, label])
}
]
fieldtype: "Section Break",
label: __("{0} {1} via CSV File", [primary_label, label]),
},
];
if (this.item?.has_serial_no) {
fields = [...fields,
fields = [
...fields,
{
fieldtype: 'Check',
label: __('Import Using CSV file'),
fieldname: 'import_using_csv_file',
fieldtype: "Check",
label: __("Import Using CSV file"),
fieldname: "import_using_csv_file",
default: 0,
},
{
fieldtype: 'Section Break',
label: __('{0} {1} Manually', [primary_label, label]),
depends_on: 'eval:doc.import_using_csv_file === 0',
fieldtype: "Section Break",
label: __("{0} {1} Manually", [primary_label, label]),
depends_on: "eval:doc.import_using_csv_file === 0",
},
{
fieldtype: 'Small Text',
label: __('Enter Serial Nos'),
fieldname: 'upload_serial_nos',
depends_on: 'eval:doc.import_using_csv_file === 0',
description: __('Enter each serial no in a new line'),
fieldtype: "Small Text",
label: __("Enter Serial Nos"),
fieldname: "upload_serial_nos",
depends_on: "eval:doc.import_using_csv_file === 0",
description: __("Enter each serial no in a new line"),
},
{
fieldtype: 'Column Break',
depends_on: 'eval:doc.import_using_csv_file === 0',
fieldtype: "Column Break",
depends_on: "eval:doc.import_using_csv_file === 0",
},
{
fieldtype: 'Button',
fieldname: 'make_serial_nos',
label: __('Create Serial Nos'),
depends_on: 'eval:doc.import_using_csv_file === 0',
fieldtype: "Button",
fieldname: "make_serial_nos",
label: __("Create Serial Nos"),
depends_on: "eval:doc.import_using_csv_file === 0",
click: () => {
this.create_serial_nos();
}
},
},
{
fieldtype: 'Section Break',
depends_on: 'eval:doc.import_using_csv_file === 1',
}
fieldtype: "Section Break",
depends_on: "eval:doc.import_using_csv_file === 1",
},
];
}
fields = [...fields,
fields = [
...fields,
{
fieldtype: 'Button',
fieldname: 'download_csv',
label: __('Download CSV Template'),
click: () => this.download_csv_file()
fieldtype: "Button",
fieldname: "download_csv",
label: __("Download CSV Template"),
click: () => this.download_csv_file(),
},
{
fieldtype: 'Column Break',
fieldtype: "Column Break",
},
{
fieldtype: 'Attach',
fieldname: 'attach_serial_batch_csv',
label: __('Attach CSV File'),
onchange: () => this.upload_csv_file()
}
fieldtype: "Attach",
fieldname: "attach_serial_batch_csv",
label: __("Attach CSV File"),
onchange: () => this.upload_csv_file(),
},
];
return fields;
}
create_serial_nos() {
let {upload_serial_nos} = this.dialog.get_values();
let { upload_serial_nos } = this.dialog.get_values();
if (!upload_serial_nos) {
frappe.throw(__('Please enter Serial Nos'));
frappe.throw(__("Please enter Serial Nos"));
}
frappe.call({
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.create_serial_nos',
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.create_serial_nos",
args: {
item_code: this.item.item_code,
serial_nos: upload_serial_nos
serial_nos: upload_serial_nos,
},
callback: (r) => {
if (r.message) {
@@ -274,20 +274,22 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
this.set_data(r.message);
this.update_bundle_entries();
}
}
},
});
}
download_csv_file() {
let csvFileData = ['Serial No'];
let csvFileData = ["Serial No"];
if (this.item.has_serial_no && this.item.has_batch_no) {
csvFileData = ['Serial No', 'Batch No', 'Quantity'];
csvFileData = ["Serial No", "Batch No", "Quantity"];
} else if (this.item.has_batch_no) {
csvFileData = ['Batch No', 'Quantity'];
csvFileData = ["Batch No", "Quantity"];
}
const method = `/api/method/erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.download_blank_csv_template?content=${encodeURIComponent(JSON.stringify(csvFileData))}`;
const method = `/api/method/erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.download_blank_csv_template?content=${encodeURIComponent(
JSON.stringify(csvFileData)
)}`;
const w = window.open(frappe.urllib.get_full_url(method));
if (!w) {
frappe.msgprint(__("Please enable pop-ups"));
@@ -295,13 +297,13 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
}
upload_csv_file() {
const file_path = this.dialog.get_value("attach_serial_batch_csv")
const file_path = this.dialog.get_value("attach_serial_batch_csv");
frappe.call({
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.upload_csv_file',
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.upload_csv_file",
args: {
item_code: this.item.item_code,
file_path: file_path
file_path: file_path,
},
callback: (r) => {
if (r.message.serial_nos && r.message.serial_nos.length) {
@@ -309,102 +311,106 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
} else if (r.message.batch_nos && r.message.batch_nos.length) {
this.set_data(r.message.batch_nos);
}
}
},
});
}
get_filter_fields() {
return [
{
fieldtype: 'Section Break',
label: __('Auto Fetch')
fieldtype: "Section Break",
label: __("Auto Fetch"),
},
{
fieldtype: 'Float',
fieldname: 'qty',
label: __('Qty to Fetch'),
onchange: () => this.get_auto_data()
fieldtype: "Float",
fieldname: "qty",
label: __("Qty to Fetch"),
onchange: () => this.get_auto_data(),
},
{
fieldtype: 'Column Break',
fieldtype: "Column Break",
},
{
fieldtype: 'Select',
options: ['FIFO', 'LIFO', 'Expiry'],
default: 'FIFO',
fieldname: 'based_on',
label: __('Fetch Based On'),
onchange: () => this.get_auto_data()
fieldtype: "Select",
options: ["FIFO", "LIFO", "Expiry"],
default: "FIFO",
fieldname: "based_on",
label: __("Fetch Based On"),
onchange: () => this.get_auto_data(),
},
{
fieldtype: 'Section Break',
fieldtype: "Section Break",
},
]
];
}
get_dialog_table_fields() {
let fields = []
let fields = [];
if (this.item.has_serial_no) {
fields.push({
fieldtype: 'Link',
options: 'Serial No',
fieldname: 'serial_no',
label: __('Serial No'),
fieldtype: "Link",
options: "Serial No",
fieldname: "serial_no",
label: __("Serial No"),
in_list_view: 1,
get_query: () => {
return {
filters: this.get_serial_no_filters()
}
}
})
filters: this.get_serial_no_filters(),
};
},
});
}
let batch_fields = []
let batch_fields = [];
if (this.item.has_batch_no) {
batch_fields = [
{
fieldtype: 'Link',
options: 'Batch',
fieldname: 'batch_no',
label: __('Batch No'),
fieldtype: "Link",
options: "Batch",
fieldname: "batch_no",
label: __("Batch No"),
in_list_view: 1,
get_query: () => {
let is_inward = false;
if ((["Purchase Receipt", "Purchase Invoice"].includes(this.frm.doc.doctype) && !this.frm.doc.is_return)
|| (this.frm.doc.doctype === 'Stock Entry' && this.frm.doc.purpose === 'Material Receipt')) {
if (
(["Purchase Receipt", "Purchase Invoice"].includes(this.frm.doc.doctype) &&
!this.frm.doc.is_return) ||
(this.frm.doc.doctype === "Stock Entry" &&
this.frm.doc.purpose === "Material Receipt")
) {
is_inward = true;
}
return {
query : "erpnext.controllers.queries.get_batch_no",
query: "erpnext.controllers.queries.get_batch_no",
filters: {
'item_code': this.item.item_code,
'warehouse': this.item.s_warehouse || this.item.t_warehouse || this.item.warehouse,
'is_inward': is_inward
}
}
item_code: this.item.item_code,
warehouse:
this.item.s_warehouse || this.item.t_warehouse || this.item.warehouse,
is_inward: is_inward,
},
};
},
}
]
},
];
if (!this.item.has_serial_no) {
batch_fields.push({
fieldtype: 'Float',
fieldname: 'qty',
label: __('Quantity'),
fieldtype: "Float",
fieldname: "qty",
label: __("Quantity"),
in_list_view: 1,
})
});
}
}
fields = [...fields, ...batch_fields];
fields.push({
fieldtype: 'Data',
fieldname: 'name',
label: __('Name'),
fieldtype: "Data",
fieldname: "name",
label: __("Name"),
hidden: 1,
});
@@ -425,26 +431,26 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
}
if (!based_on) {
based_on = 'FIFO';
based_on = "FIFO";
}
if (qty) {
frappe.call({
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_auto_data',
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_auto_data",
args: {
item_code: this.item.item_code,
warehouse: this.item.warehouse || this.item.s_warehouse,
has_serial_no: this.item.has_serial_no,
has_batch_no: this.item.has_batch_no,
qty: qty,
based_on: based_on
based_on: based_on,
},
callback: (r) => {
if (r.message) {
this.dialog.fields_dict.entries.df.data = r.message;
this.dialog.fields_dict.entries.grid.refresh();
}
}
},
});
}
}
@@ -454,7 +460,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
if (scan_serial_no || scan_batch_no) {
frappe.call({
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.is_serial_batch_no_exists',
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.is_serial_batch_no_exists",
args: {
item_code: this.item.item_code,
type_of_transaction: this.item.type_of_transaction,
@@ -463,9 +469,8 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
},
callback: (r) => {
this.update_serial_batch_no();
}
})
},
});
}
}
@@ -473,25 +478,25 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
const { scan_serial_no, scan_batch_no } = this.dialog.get_values();
if (scan_serial_no) {
let existing_row = this.dialog.fields_dict.entries.df.data.filter(d => {
let existing_row = this.dialog.fields_dict.entries.df.data.filter((d) => {
if (d.serial_no === scan_serial_no) {
return d
return d;
}
});
if (existing_row?.length) {
frappe.throw(__('Serial No {0} already exists', [scan_serial_no]));
frappe.throw(__("Serial No {0} already exists", [scan_serial_no]));
}
if (!this.item.has_batch_no) {
this.dialog.fields_dict.entries.df.data.push({
serial_no: scan_serial_no
serial_no: scan_serial_no,
});
this.dialog.fields_dict.scan_serial_no.set_value('');
this.dialog.fields_dict.scan_serial_no.set_value("");
} else {
frappe.call({
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_batch_no_from_serial_no',
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_batch_no_from_serial_no",
args: {
serial_no: scan_serial_no,
},
@@ -499,19 +504,18 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
if (r.message) {
this.dialog.fields_dict.entries.df.data.push({
serial_no: scan_serial_no,
batch_no: r.message
batch_no: r.message,
});
this.dialog.fields_dict.scan_serial_no.set_value('');
this.dialog.fields_dict.scan_serial_no.set_value("");
}
}
})
},
});
}
} else if (scan_batch_no) {
let existing_row = this.dialog.fields_dict.entries.df.data.filter(d => {
let existing_row = this.dialog.fields_dict.entries.df.data.filter((d) => {
if (d.batch_no === scan_batch_no) {
return d
return d;
}
});
@@ -520,11 +524,11 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
} else {
this.dialog.fields_dict.entries.df.data.push({
batch_no: scan_batch_no,
qty: 1
qty: 1,
});
}
this.dialog.fields_dict.scan_batch_no.set_value('');
this.dialog.fields_dict.scan_batch_no.set_value("");
}
this.dialog.fields_dict.entries.grid.refresh();
@@ -532,33 +536,33 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
update_bundle_entries() {
let entries = this.dialog.get_values().entries;
let warehouse = this.dialog.get_value('warehouse');
let warehouse = this.dialog.get_value("warehouse");
if (entries && !entries.length || !entries) {
frappe.throw(__('Please add atleast one Serial No / Batch No'));
if ((entries && !entries.length) || !entries) {
frappe.throw(__("Please add atleast one Serial No / Batch No"));
}
frappe.call({
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_ledgers',
args: {
entries: entries,
child_row: this.item,
doc: this.frm.doc,
warehouse: warehouse,
}
}).then(r => {
this.callback && this.callback(r.message);
this.frm.save();
this.dialog.hide();
})
frappe
.call({
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_ledgers",
args: {
entries: entries,
child_row: this.item,
doc: this.frm.doc,
warehouse: warehouse,
},
})
.then((r) => {
this.callback && this.callback(r.message);
this.frm.save();
this.dialog.hide();
});
}
edit_full_form() {
let bundle_id = this.item.serial_and_batch_bundle
let bundle_id = this.item.serial_and_batch_bundle;
if (!bundle_id) {
let _new = frappe.model.get_new_doc(
"Serial and Batch Bundle", null, null, true
);
let _new = frappe.model.get_new_doc("Serial and Batch Bundle", null, null, true);
_new.item_code = this.item.item_code;
_new.warehouse = this.get_warehouse();
@@ -575,34 +579,36 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate {
}
get_warehouse() {
return (this.item?.type_of_transaction === "Outward" ?
(this.item.warehouse || this.item.s_warehouse)
: (this.item.warehouse || this.item.t_warehouse));
return this.item?.type_of_transaction === "Outward"
? this.item.warehouse || this.item.s_warehouse
: this.item.warehouse || this.item.t_warehouse;
}
render_data() {
if (this.bundle) {
frappe.call({
method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_serial_batch_ledgers',
args: {
item_code: this.item.item_code,
name: this.bundle,
voucher_no: !this.frm.is_new() ? this.item.parent : "",
}
}).then(r => {
if (r.message) {
this.set_data(r.message);
}
})
frappe
.call({
method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_serial_batch_ledgers",
args: {
item_code: this.item.item_code,
name: this.bundle,
voucher_no: !this.frm.is_new() ? this.item.parent : "",
},
})
.then((r) => {
if (r.message) {
this.set_data(r.message);
}
});
}
}
set_data(data) {
data.forEach(d => {
data.forEach((d) => {
d.qty = Math.abs(d.qty);
this.dialog.fields_dict.entries.df.data.push(d);
});
this.dialog.fields_dict.entries.grid.refresh();
}
}
};

View File

@@ -1,3 +1,3 @@
frappe.provide('frappe.ui.form');
frappe.provide("frappe.ui.form");
frappe.ui.form.SupplierQuickEntryForm = frappe.ui.form.ContactAddressQuickEntryForm;

View File

@@ -1,27 +1,34 @@
frappe.provide('erpnext.accounts');
frappe.provide("erpnext.accounts");
erpnext.accounts.unreconcile_payment = {
add_unreconcile_btn(frm) {
if (frm.doc.docstatus == 1) {
if(((frm.doc.doctype == "Journal Entry") && (frm.doc.voucher_type != "Journal Entry"))
|| !["Purchase Invoice", "Sales Invoice", "Journal Entry", "Payment Entry"].includes(frm.doc.doctype)
) {
if (
(frm.doc.doctype == "Journal Entry" && frm.doc.voucher_type != "Journal Entry") ||
!["Purchase Invoice", "Sales Invoice", "Journal Entry", "Payment Entry"].includes(
frm.doc.doctype
)
) {
return;
}
frappe.call({
"method": "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.doc_has_references",
"args": {
"doctype": frm.doc.doctype,
"docname": frm.doc.name
method: "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.doc_has_references",
args: {
doctype: frm.doc.doctype,
docname: frm.doc.name,
},
callback: function(r) {
callback: function (r) {
if (r.message) {
frm.add_custom_button(__("UnReconcile"), function() {
erpnext.accounts.unreconcile_payment.build_unreconcile_dialog(frm);
}, __('Actions'));
frm.add_custom_button(
__("UnReconcile"),
function () {
erpnext.accounts.unreconcile_payment.build_unreconcile_dialog(frm);
},
__("Actions")
);
}
}
},
});
}
},
@@ -30,18 +37,18 @@ erpnext.accounts.unreconcile_payment = {
// assuming each row is an individual voucher
// pass this to server side method that creates unreconcile doc for each row
let selection_map = [];
if (['Sales Invoice', 'Purchase Invoice'].includes(frm.doc.doctype)) {
selection_map = selections.map(function(elem) {
if (["Sales Invoice", "Purchase Invoice"].includes(frm.doc.doctype)) {
selection_map = selections.map(function (elem) {
return {
company: elem.company,
voucher_type: elem.voucher_type,
voucher_no: elem.voucher_no,
against_voucher_type: frm.doc.doctype,
against_voucher_no: frm.doc.name
against_voucher_no: frm.doc.name,
};
});
} else if (['Payment Entry', 'Journal Entry'].includes(frm.doc.doctype)) {
selection_map = selections.map(function(elem) {
} else if (["Payment Entry", "Journal Entry"].includes(frm.doc.doctype)) {
selection_map = selections.map(function (elem) {
return {
company: elem.company,
voucher_type: frm.doc.doctype,
@@ -55,18 +62,41 @@ erpnext.accounts.unreconcile_payment = {
},
build_unreconcile_dialog(frm) {
if (['Sales Invoice', 'Purchase Invoice', 'Payment Entry', 'Journal Entry'].includes(frm.doc.doctype)) {
if (
["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"].includes(frm.doc.doctype)
) {
let child_table_fields = [
{ label: __("Voucher Type"), fieldname: "voucher_type", fieldtype: "Dynamic Link", options: "DocType", in_list_view: 1, read_only: 1},
{ label: __("Voucher No"), fieldname: "voucher_no", fieldtype: "Link", options: "voucher_type", in_list_view: 1, read_only: 1 },
{ label: __("Allocated Amount"), fieldname: "allocated_amount", fieldtype: "Currency", in_list_view: 1, read_only: 1 , options: "account_currency"},
{ label: __("Currency"), fieldname: "account_currency", fieldtype: "Currency", read_only: 1},
]
{
label: __("Voucher Type"),
fieldname: "voucher_type",
fieldtype: "Dynamic Link",
options: "DocType",
in_list_view: 1,
read_only: 1,
},
{
label: __("Voucher No"),
fieldname: "voucher_no",
fieldtype: "Link",
options: "voucher_type",
in_list_view: 1,
read_only: 1,
},
{
label: __("Allocated Amount"),
fieldname: "allocated_amount",
fieldtype: "Currency",
in_list_view: 1,
read_only: 1,
options: "account_currency",
},
{ label: __("Currency"), fieldname: "account_currency", fieldtype: "Currency", read_only: 1 },
];
let unreconcile_dialog_fields = [
{
label: __('Allocations'),
fieldname: 'allocations',
fieldtype: 'Table',
label: __("Allocations"),
fieldname: "allocations",
fieldtype: "Table",
read_only: 1,
fields: child_table_fields,
},
@@ -74,54 +104,57 @@ erpnext.accounts.unreconcile_payment = {
// get linked payments
frappe.call({
"method": "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.get_linked_payments_for_doc",
"args": {
"company": frm.doc.company,
"doctype": frm.doc.doctype,
"docname": frm.doc.name
method: "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.get_linked_payments_for_doc",
args: {
company: frm.doc.company,
doctype: frm.doc.doctype,
docname: frm.doc.name,
},
callback: function(r) {
callback: function (r) {
if (r.message) {
// populate child table with allocations
unreconcile_dialog_fields[0].data = r.message;
unreconcile_dialog_fields[0].get_data = function(){ return r.message};
unreconcile_dialog_fields[0].get_data = function () {
return r.message;
};
let d = new frappe.ui.Dialog({
title: 'UnReconcile Allocations',
title: "UnReconcile Allocations",
fields: unreconcile_dialog_fields,
size: 'large',
size: "large",
cannot_add_rows: true,
primary_action_label: 'UnReconcile',
primary_action_label: "UnReconcile",
primary_action(values) {
let selected_allocations = values.allocations.filter(x=>x.__checked);
let selected_allocations = values.allocations.filter((x) => x.__checked);
if (selected_allocations.length > 0) {
let selection_map = erpnext.accounts.unreconcile_payment.build_selection_map(frm, selected_allocations);
erpnext.accounts.unreconcile_payment.create_unreconcile_docs(selection_map);
let selection_map =
erpnext.accounts.unreconcile_payment.build_selection_map(
frm,
selected_allocations
);
erpnext.accounts.unreconcile_payment.create_unreconcile_docs(
selection_map
);
d.hide();
} else {
frappe.msgprint("No Selection");
}
}
},
});
d.show();
}
}
},
});
}
},
create_unreconcile_docs(selection_map) {
frappe.call({
"method": "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.create_unreconcile_doc_for_selection",
"args": {
"selections": selection_map
method: "erpnext.accounts.doctype.unreconcile_payment.unreconcile_payment.create_unreconcile_doc_for_selection",
args: {
selections: selection_map,
},
});
}
}
},
};

View File

@@ -1,14 +1,15 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt
frappe.ui.form.on('Website Theme', {
frappe.ui.form.on("Website Theme", {
validate(frm) {
let theme_scss = frm.doc.theme_scss;
if (theme_scss && theme_scss.includes('frappe/public/scss/website')
&& !theme_scss.includes('erpnext/public/scss/website')
if (
theme_scss &&
theme_scss.includes("frappe/public/scss/website") &&
!theme_scss.includes("erpnext/public/scss/website")
) {
frm.set_value('theme_scss',
`${frm.doc.theme_scss}\n@import "erpnext/public/scss/website";`);
frm.set_value("theme_scss", `${frm.doc.theme_scss}\n@import "erpnext/public/scss/website";`);
}
}
},
});

View File

@@ -1,14 +1,14 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
if(!window.erpnext) window.erpnext = {};
if (!window.erpnext) window.erpnext = {};
erpnext.subscribe_to_newsletter = function(opts, btn) {
erpnext.subscribe_to_newsletter = function (opts, btn) {
return frappe.call({
type: "POST",
method: "frappe.email.doctype.newsletter.newsletter.subscribe",
btn: btn,
args: {"email": opts.email},
callback: opts.callback
args: { email: opts.email },
callback: opts.callback,
});
}
};