Merge pull request #41942 from frappe/version-14-hotfix

chore: release v14
This commit is contained in:
ruthra kumar
2024-06-19 11:54:25 +05:30
committed by GitHub
39 changed files with 206 additions and 114 deletions

View File

@@ -82,7 +82,7 @@
"icon": "fa fa-calendar",
"idx": 1,
"links": [],
"modified": "2020-11-05 12:16:53.081573",
"modified": "2024-05-27 17:29:55.560840",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Fiscal Year",
@@ -126,6 +126,10 @@
{
"read": 1,
"role": "Stock Manager"
},
{
"read": 1,
"role": "Auditor"
}
],
"show_name_in_global_search": 1,

View File

@@ -171,7 +171,7 @@ frappe.ui.form.on("Journal Entry", {
!(frm.doc.accounts || []).length ||
((frm.doc.accounts || []).length === 1 && !frm.doc.accounts[0].account)
) {
if (in_list(["Bank Entry", "Cash Entry"], frm.doc.voucher_type)) {
if (["Bank Entry", "Cash Entry"].includes(frm.doc.voucher_type)) {
return frappe.call({
type: "GET",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
@@ -283,7 +283,7 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
filters: [[jvd.reference_type, "docstatus", "=", 1]],
};
if (in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
if (["Sales Invoice", "Purchase Invoice"].includes(jvd.reference_type)) {
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
// Filter by cost center
if (jvd.cost_center) {
@@ -295,7 +295,7 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
}
if (in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {
if (["Sales Order", "Purchase Order"].includes(jvd.reference_type)) {
// party_type and party mandatory
frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party");

View File

@@ -21,7 +21,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_query("paid_from", function() {
frm.events.validate_company(frm);
var account_types = in_list(["Pay", "Internal Transfer"], frm.doc.payment_type) ?
var account_types = ["Pay", "Internal Transfer"].includes(frm.doc.payment_type) ?
["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
return {
filters: {
@@ -75,7 +75,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_query("paid_to", function() {
frm.events.validate_company(frm);
var account_types = in_list(["Receive", "Internal Transfer"], frm.doc.payment_type) ?
var account_types = ["Receive", "Internal Transfer"].includes(frm.doc.payment_type) ?
["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
return {
filters: {
@@ -121,7 +121,7 @@ frappe.ui.form.on('Payment Entry', {
frm.set_query('payment_term', 'references', function(frm, cdt, cdn) {
const child = locals[cdt][cdn];
if (in_list(['Purchase Invoice', 'Sales Invoice'], child.reference_doctype) && child.reference_name) {
if (['Purchase Invoice', 'Sales Invoice'].includes(child.reference_doctype) && child.reference_name) {
return {
query: "erpnext.controllers.queries.get_payment_terms_for_references",
filters: {
@@ -485,7 +485,7 @@ frappe.ui.form.on('Payment Entry', {
if (frm.doc.paid_from_account_currency == company_currency) {
frm.set_value("source_exchange_rate", 1);
} else if (frm.doc.paid_from){
if (in_list(["Internal Transfer", "Pay"], frm.doc.payment_type)) {
if (["Internal Transfer", "Pay"].includes(frm.doc.payment_type)) {
let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
frappe.call({
method: "erpnext.setup.utils.get_exchange_rate",
@@ -853,7 +853,7 @@ frappe.ui.form.on('Payment Entry', {
}
var allocated_positive_outstanding = paid_amount + allocated_negative_outstanding;
} else if (in_list(["Customer", "Supplier"], frm.doc.party_type)) {
} else if (["Customer", "Supplier"].includes(frm.doc.party_type)) {
total_negative_outstanding = flt(total_negative_outstanding, precision("outstanding_amount"))
if(paid_amount > total_negative_outstanding) {
if(total_negative_outstanding == 0) {
@@ -988,7 +988,7 @@ frappe.ui.form.on('Payment Entry', {
}
if(frm.doc.party_type=="Customer" &&
!in_list(["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"], row.reference_doctype)
!["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"].includes(row.reference_doctype)
) {
frappe.model.set_value(row.doctype, row.name, "reference_doctype", null);
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Sales Order, Sales Invoice, Journal Entry or Dunning", [row.idx]));
@@ -996,7 +996,7 @@ frappe.ui.form.on('Payment Entry', {
}
if(frm.doc.party_type=="Supplier" &&
!in_list(["Purchase Order", "Purchase Invoice", "Journal Entry"], row.reference_doctype)
!["Purchase Order", "Purchase Invoice", "Journal Entry"].includes(row.reference_doctype)
) {
frappe.model.set_value(row.doctype, row.name, "against_voucher_type", null);
frappe.msgprint(__("Row #{0}: Reference Document Type must be one of Purchase Order, Purchase Invoice or Journal Entry", [row.idx]));
@@ -1080,7 +1080,7 @@ frappe.ui.form.on('Payment Entry', {
bank_account: function(frm) {
const field = frm.doc.payment_type == "Pay" ? "paid_from":"paid_to";
if (frm.doc.bank_account && in_list(['Pay', 'Receive'], frm.doc.payment_type)) {
if (frm.doc.bank_account && ['Pay', 'Receive'].includes(frm.doc.payment_type)) {
frappe.call({
method: "erpnext.accounts.doctype.bank_account.bank_account.get_bank_account_details",
args: {

View File

@@ -28,7 +28,7 @@ frappe.ui.form.on("Payment Request", "refresh", function (frm) {
if (
frm.doc.payment_request_type == "Inward" &&
frm.doc.payment_channel !== "Phone" &&
!in_list(["Initiated", "Paid"], frm.doc.status) &&
!["Initiated", "Paid"].includes(frm.doc.status) &&
!frm.doc.__islocal &&
frm.doc.docstatus == 1
) {

View File

@@ -200,7 +200,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
if(cur_frm.meta._default_print_format) {
cur_frm.meta.default_print_format = cur_frm.meta._default_print_format;
cur_frm.meta._default_print_format = null;
} else if(in_list([cur_frm.pos_print_format, cur_frm.return_print_format], cur_frm.meta.default_print_format)) {
} else if([cur_frm.pos_print_format, cur_frm.return_print_format].includes(cur_frm.meta.default_print_format)) {
cur_frm.meta.default_print_format = null;
cur_frm.meta._default_print_format = null;
}

View File

@@ -78,7 +78,7 @@ frappe.ui.form.on("Asset", {
frm.events.make_schedules_editable(frm);
if (frm.doc.docstatus == 1) {
if (in_list(["Submitted", "Partially Depreciated", "Fully Depreciated"], frm.doc.status)) {
if (["Submitted", "Partially Depreciated", "Fully Depreciated"].includes(frm.doc.status)) {
frm.add_custom_button(
__("Transfer Asset"),
function () {
@@ -280,7 +280,7 @@ frappe.ui.form.on("Asset", {
if (v.journal_entry) {
asset_values.push(asset_value);
} else {
if (in_list(["Scrapped", "Sold"], frm.doc.status)) {
if (["Scrapped", "Sold"].includes(frm.doc.status)) {
asset_values.push(null);
} else {
asset_values.push(asset_value);
@@ -312,7 +312,7 @@ frappe.ui.form.on("Asset", {
});
}
if (in_list(["Scrapped", "Sold"], frm.doc.status)) {
if (["Scrapped", "Sold"].includes(frm.doc.status)) {
x_intervals.push(frappe.format(frm.doc.disposal_date, { fieldtype: "Date" }));
asset_values.push(0);
}

View File

@@ -6,8 +6,8 @@ frappe.provide("erpnext.accounts.dimensions");
{% include 'erpnext/public/js/controllers/buying.js' %};
frappe.ui.form.on("Purchase Order", {
setup: function(frm) {
setup: function (frm) {
frm.ignore_doctypes_on_cancel_all = ["Unreconcile Payment", "Unreconcile Payment Entries"];
if (frm.doc.is_old_subcontracting_flow) {
frm.set_query("reserve_warehouse", "supplied_items", function() {
return {
@@ -180,7 +180,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e
this.frm.fields_dict.items_section.wrapper.removeClass("hide-border");
}
if(!in_list(["Closed", "Delivered"], doc.status)) {
if(!["Closed", "Delivered"].includes(doc.status)) {
if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
// Don't add Update Items button if the PO is following the new subcontracting flow.
if (!(this.frm.doc.is_subcontracted && !this.frm.doc.is_old_subcontracting_flow)) {
@@ -211,7 +211,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e
this.frm.page.set_inner_btn_group_as_primary(__("Status"));
}
} else if(in_list(["Closed", "Delivered"], doc.status)) {
} else if(["Closed", "Delivered"].includes(doc.status)) {
if (this.frm.has_perm("submit")) {
this.frm.add_custom_button(__('Re-open'), () => this.unclose_purchase_order(), __("Status"));
}

View File

@@ -345,7 +345,13 @@ class PurchaseOrder(BuyingController):
update_linked_doc(self.doctype, self.name, self.inter_company_order_reference)
def on_cancel(self):
self.ignore_linked_doctypes = ("GL Entry", "Payment Ledger Entry")
self.ignore_linked_doctypes = (
"GL Entry",
"Payment Ledger Entry",
"Unreconcile Payment",
"Unreconcile Payment Entries",
)
super().on_cancel()
if self.is_against_so():

View File

@@ -8,6 +8,7 @@ from frappe.contacts.doctype.address.address import render_address
from frappe.utils import cint, cstr, flt, getdate
from frappe.utils.data import nowtime
import erpnext
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
from erpnext.accounts.party import get_party_details
from erpnext.buying.utils import update_last_purchase_rate, validate_for_items
@@ -305,6 +306,8 @@ class BuyingController(SubcontractingController):
else:
item.valuation_rate = 0.0
update_regional_item_valuation_rate(self)
def set_incoming_rate(self):
if self.doctype not in ("Purchase Receipt", "Purchase Invoice", "Purchase Order"):
return
@@ -894,3 +897,8 @@ def validate_item_type(doc, fieldname, message):
).format(items, message)
frappe.throw(error_message)
@erpnext.allow_regional
def update_regional_item_valuation_rate(doc):
pass

View File

@@ -51,7 +51,7 @@ class StockController(AccountsController):
self.validate_internal_transfer()
self.validate_putaway_capacity()
def make_gl_entries(self, gl_entries=None, from_repost=False):
def make_gl_entries(self, gl_entries=None, from_repost=False, via_landed_cost_voucher=False):
if self.docstatus == 2:
make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
@@ -72,7 +72,11 @@ class StockController(AccountsController):
if self.docstatus == 1:
if not gl_entries:
gl_entries = self.get_gl_entries(warehouse_account)
gl_entries = (
self.get_gl_entries(warehouse_account, via_landed_cost_voucher)
if self.doctype == "Purchase Receipt"
else self.get_gl_entries(warehouse_account)
)
make_gl_entries(gl_entries, from_repost=from_repost)
def validate_serialized_batch(self):

View File

@@ -400,7 +400,7 @@ frappe.ui.form.on("BOM", {
},
rm_cost_as_per(frm) {
if (in_list(["Valuation Rate", "Last Purchase Rate"], frm.doc.rm_cost_as_per)) {
if (["Valuation Rate", "Last Purchase Rate"].includes(frm.doc.rm_cost_as_per)) {
frm.set_value("plc_conversion_rate", 1.0);
}
},

View File

@@ -129,7 +129,7 @@ frappe.ui.form.on("Production Plan", {
if (
frm.doc.mr_items &&
frm.doc.mr_items.length &&
!in_list(["Material Requested", "Closed"], frm.doc.status)
!["Material Requested", "Closed"].includes(frm.doc.status)
) {
frm.add_custom_button(
__("Material Request"),

View File

@@ -194,7 +194,7 @@ frappe.ui.form.on("Work Order", {
},
add_custom_button_to_return_components: function (frm) {
if (frm.doc.docstatus === 1 && in_list(["Closed", "Completed"], frm.doc.status)) {
if (frm.doc.docstatus === 1 && ["Closed", "Completed"].includes(frm.doc.status)) {
let non_consumed_items = frm.doc.required_items.filter((d) => {
return flt(d.consumed_qty) < flt(d.transferred_qty - d.returned_qty);
});
@@ -594,7 +594,7 @@ erpnext.work_order = {
);
}
if (doc.docstatus === 1 && !in_list(["Closed", "Completed"], doc.status)) {
if (doc.docstatus === 1 && !["Closed", "Completed"].includes(doc.status)) {
if (doc.status != "Stopped" && doc.status != "Completed") {
frm.add_custom_button(
__("Stop"),

View File

@@ -9,15 +9,13 @@ def execute():
dt = frappe.qb.DocType(doctype)
records = (
frappe.qb.from_(dt)
.select(dt.name, dt.notes, dt.modified_by, dt.modified)
.where(dt.notes.isnotnull() & dt.notes != "")
frappe.qb.from_(dt).select(dt.name, dt.notes).where(dt.notes.isnotnull() & dt.notes != "")
).run(as_dict=True)
for d in records:
if strip_html(cstr(d.notes)).strip():
doc = frappe.get_doc(doctype, d.name)
doc.append("notes", {"note": d.notes, "added_by": d.modified_by, "added_on": d.modified})
doc.append("notes", {"note": d.notes})
doc.update_child_table("notes")
frappe.db.sql_ddl(f"alter table `tab{doctype}` drop column `notes`")

View File

@@ -240,7 +240,7 @@ erpnext.AccountTreeGrid = class AccountTreeGrid extends frappe.views.TreeGridRep
flt(account.closing_dr) -
flt(account.closing_cr);
me.set_debit_or_credit(parent_account, "closing", bal);
} else if (in_list(["debit", "credit"], col.field)) {
} else if (["debit", "credit"].includes(col.field)) {
parent_account[col.field] =
flt(parent_account[col.field]) + flt(account[col.field]);
}

View File

@@ -20,7 +20,7 @@ frappe.ui.form.on("Communication", {
);
}
if (!in_list(["Lead", "Opportunity"], frm.doc.reference_doctype)) {
if (!["Lead", "Opportunity"].includes(frm.doc.reference_doctype)) {
frm.add_custom_button(
__("Lead"),
() => {

View File

@@ -9,7 +9,7 @@ frappe.ui.form.on(cur_frm.doctype, {
setup: function(frm) {
// set conditional display for rate column in taxes
$(frm.wrapper).on('grid-row-render', function(e, grid_row) {
if(in_list(['Sales Taxes and Charges', 'Purchase Taxes and Charges'], grid_row.doc.doctype)) {
if(['Sales Taxes and Charges', 'Purchase Taxes and Charges'].includes(grid_row.doc.doctype)) {
erpnext.taxes.set_conditional_mandatory_rate_or_amount(grid_row);
}
});

View File

@@ -136,7 +136,7 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
}
toggle_subcontracting_fields() {
if (in_list(['Purchase Receipt', 'Purchase Invoice'], this.frm.doc.doctype)) {
if (['Purchase Receipt', 'Purchase Invoice'].includes(this.frm.doc.doctype)) {
this.frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty',
'read_only', this.frm.doc.__onload && this.frm.doc.__onload.backflush_based_on === 'BOM');

View File

@@ -9,7 +9,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
apply_pricing_rule_on_item(item) {
let effective_item_rate = item.price_list_rate;
let item_rate = item.rate;
if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) {
if (["Sales Order", "Quotation"].includes(item.parenttype) && item.blanket_order_rate) {
effective_item_rate = item.blanket_order_rate;
}
if (item.margin_type == "Percentage") {
@@ -52,7 +52,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
// Advance calculation applicable to Sales/Purchase Invoice
if (
in_list(["Sales Invoice", "POS Invoice", "Purchase Invoice"], this.frm.doc.doctype)
["Sales Invoice", "POS Invoice", "Purchase Invoice"].includes(this.frm.doc.doctype)
&& this.frm.doc.docstatus < 2
&& !this.frm.doc.is_return
) {
@@ -60,7 +60,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
}
if (
in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype)
["Sales Invoice", "POS Invoice"].includes(this.frm.doc.doctype)
&& this.frm.doc.is_pos
&& this.frm.doc.is_return
) {
@@ -69,7 +69,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
}
// Sales person's commission
if (in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"], this.frm.doc.doctype)) {
if (["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"].includes(this.frm.doc.doctype)) {
this.calculate_commission();
this.calculate_contribution();
}
@@ -547,7 +547,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
? this.frm.doc["taxes"][tax_count - 1].total + flt(this.frm.doc.rounding_adjustment)
: this.frm.doc.net_total);
if(in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"], this.frm.doc.doctype)) {
if(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"].includes(this.frm.doc.doctype)) {
this.frm.doc.base_grand_total = (this.frm.doc.total_taxes_and_charges) ?
flt(this.frm.doc.grand_total * this.frm.doc.conversion_rate) : this.frm.doc.base_net_total;
} else {
@@ -555,7 +555,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
this.frm.doc.taxes_and_charges_added = this.frm.doc.taxes_and_charges_deducted = 0.0;
if(tax_count) {
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
if (in_list(["Valuation and Total", "Total"], tax.category)) {
if (["Valuation and Total", "Total"].includes(tax.category)) {
if(tax.add_deduct_tax == "Add") {
me.frm.doc.taxes_and_charges_added += flt(tax.tax_amount_after_discount_amount);
} else {
@@ -702,7 +702,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
var actual_taxes_dict = {};
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
if (in_list(["Actual", "On Item Quantity"], tax.charge_type)) {
if (["Actual", "On Item Quantity"].includes(tax.charge_type)) {
var tax_amount = (tax.category == "Valuation") ? 0.0 : tax.tax_amount;
tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
actual_taxes_dict[tax.idx] = tax_amount;
@@ -747,7 +747,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
// NOTE:
// paid_amount and write_off_amount is only for POS/Loyalty Point Redemption Invoice
// total_advance is only for non POS Invoice
if(in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype) && this.frm.doc.is_return){
if(["Sales Invoice", "POS Invoice"].includes(this.frm.doc.doctype) && this.frm.doc.is_return){
this.calculate_paid_amount();
}
@@ -755,7 +755,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
if(in_list(["Sales Invoice", "POS Invoice", "Purchase Invoice"], this.frm.doc.doctype)) {
if(["Sales Invoice", "POS Invoice", "Purchase Invoice"].includes(this.frm.doc.doctype)) {
let grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
let base_grand_total = this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total;
@@ -778,7 +778,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
this.frm.refresh_field("base_paid_amount");
}
if(in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype)) {
if(["Sales Invoice", "POS Invoice"].includes(this.frm.doc.doctype)) {
let total_amount_for_payment = (this.frm.doc.redeem_loyalty_points && this.frm.doc.loyalty_amount)
? flt(total_amount_to_pay - this.frm.doc.loyalty_amount, precision("base_grand_total"))
: total_amount_to_pay;
@@ -882,7 +882,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
calculate_change_amount(){
this.frm.doc.change_amount = 0.0;
this.frm.doc.base_change_amount = 0.0;
if(in_list(["Sales Invoice", "POS Invoice"], this.frm.doc.doctype)
if(["Sales Invoice", "POS Invoice"].includes(this.frm.doc.doctype)
&& this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) {
var payment_types = $.map(this.frm.doc.payments, function(d) { return d.type; });

View File

@@ -260,7 +260,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
}
setup_quality_inspection() {
if(!in_list(["Delivery Note", "Sales Invoice", "Purchase Receipt", "Purchase Invoice"], this.frm.doc.doctype)) {
if(!["Delivery Note", "Sales Invoice", "Purchase Receipt", "Purchase Invoice"].includes(this.frm.doc.doctype)) {
return;
}
@@ -272,7 +272,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
this.frm.page.set_inner_btn_group_as_primary(__('Create'));
}
const inspection_type = in_list(["Purchase Receipt", "Purchase Invoice"], this.frm.doc.doctype)
const inspection_type = ["Purchase Receipt", "Purchase Invoice"].includes(this.frm.doc.doctype)
? "Incoming" : "Outgoing";
let quality_inspection_field = this.frm.get_docfield("items", "quality_inspection");
@@ -304,7 +304,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
make_payment_request() {
let me = this;
const payment_request_type = (in_list(['Sales Order', 'Sales Invoice'], this.frm.doc.doctype))
const payment_request_type = (['Sales Order', 'Sales Invoice'].includes(this.frm.doc.doctype))
? "Inward" : "Outward";
frappe.call({
@@ -417,7 +417,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
setup_sms() {
var me = this;
let blacklist = ['Purchase Invoice', 'BOM'];
if(this.frm.doc.docstatus===1 && !in_list(["Lost", "Stopped", "Closed"], this.frm.doc.status)
if(this.frm.doc.docstatus===1 && !["Lost", "Stopped", "Closed"].includes(this.frm.doc.status)
&& !blacklist.includes(this.frm.doctype)) {
this.frm.page.add_menu_item(__('Send SMS'), function() { me.send_sms(); });
}
@@ -780,7 +780,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
}
var set_party_account = function(set_pricing) {
if (in_list(["Sales Invoice", "Purchase Invoice"], me.frm.doc.doctype)) {
if (["Sales Invoice", "Purchase Invoice"].includes(me.frm.doc.doctype)) {
if(me.frm.doc.doctype=="Sales Invoice") {
var party_type = "Customer";
var party_account_field = 'debit_to';
@@ -815,7 +815,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
}
if (frappe.meta.get_docfield(this.frm.doctype, "shipping_address") &&
in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)) {
['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'].includes(this.frm.doctype)) {
erpnext.utils.get_shipping_address(this.frm, function() {
set_party_account(set_pricing);
});
@@ -1482,7 +1482,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
"doctype": me.frm.doc.doctype,
"name": me.frm.doc.name,
"is_return": cint(me.frm.doc.is_return),
"update_stock": in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0,
"update_stock": ['Sales Invoice', 'Purchase Invoice'].includes(me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0,
"conversion_factor": me.frm.doc.conversion_factor,
"pos_profile": me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '',
"coupon_code": me.frm.doc.coupon_code
@@ -2126,7 +2126,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
get_method_for_payment() {
var method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry";
if(cur_frm.doc.__onload && cur_frm.doc.__onload.make_payment_via_journal_entry){
if(in_list(['Sales Invoice', 'Purchase Invoice'], cur_frm.doc.doctype)){
if(['Sales Invoice', 'Purchase Invoice'].includes( cur_frm.doc.doctype)){
method = "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_invoice";
}else {
method= "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_against_order";

View File

@@ -218,7 +218,7 @@ 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 (["change_amount", "write_off_amount"].includes(this.idx)) {
var value = me.selected_mode.val();
if (me.idx == "change_amount") {
me.change_amount(value);

View File

@@ -28,11 +28,11 @@ erpnext.SMSManager = function SMSManager(doc) {
"Purchase Receipt": "Items has been received against purchase receipt: " + doc.name,
};
if (in_list(["Sales Order", "Delivery Note", "Sales Invoice"], doc.doctype))
if (["Sales Order", "Delivery Note", "Sales Invoice"].includes(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))
else if (["Purchase Order", "Purchase Receipt"].includes(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")

View File

@@ -12,6 +12,7 @@
{% for(var i=0, l=notes.length; i<l; i++) { %}
<div class="comment-content p-3 row" name="{{ notes[i].name }}">
<div class="mb-2 head col-xs-3">
{% if (notes[i].added_by && notes[i].added_on) %}
<div class="row">
<div class="col-xs-2">
{{ frappe.avatar(notes[i].added_by) }}
@@ -25,6 +26,7 @@
</div>
</div>
</div>
{% } %}
</div>
<div class="content col-xs-8">
{{ notes[i].note }}

View File

@@ -14,10 +14,10 @@ erpnext.utils.get_party_details = function (frm, method, args, callback) {
if (!args) {
if (
(frm.doctype != "Purchase Order" && frm.doc.customer) ||
(frm.doc.party_name && in_list(["Quotation", "Opportunity"], frm.doc.doctype))
(frm.doc.party_name && ["Quotation", "Opportunity"].includes(frm.doc.doctype))
) {
let party_type = "Customer";
if (frm.doc.quotation_to && in_list(["Lead", "Prospect"], frm.doc.quotation_to)) {
if (frm.doc.quotation_to && ["Lead", "Prospect"].includes(frm.doc.quotation_to)) {
party_type = frm.doc.quotation_to;
}

View File

@@ -34,7 +34,7 @@ frappe.ui.form.on("Import Supplier Invoice", {
},
toggle_read_only_fields: function (frm) {
if (in_list(["File Import Completed", "Processing File Data"], frm.doc.status)) {
if (["File Import Completed", "Processing File Data"].includes(frm.doc.status)) {
cur_frm.set_read_only();
cur_frm.refresh_fields();
frm.set_df_property("import_invoices", "hidden", 1);

View File

@@ -150,7 +150,11 @@ frappe.ui.form.on("Sales Order", {
frm.set_value("advance_paid", 0)
}
frm.ignore_doctypes_on_cancel_all = ['Purchase Order'];
frm.ignore_doctypes_on_cancel_all = [
"Purchase Order",
"Unreconcile Payment",
"Unreconcile Payment Entries",
];
},
delivery_date: function(frm) {

View File

@@ -269,7 +269,13 @@ class SalesOrder(SellingController):
update_coupon_code_count(self.coupon_code, "used")
def on_cancel(self):
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry")
self.ignore_linked_doctypes = (
"GL Entry",
"Stock Ledger Entry",
"Payment Ledger Entry",
"Unreconcile Payment",
"Unreconcile Payment Entries",
)
super().on_cancel()
# Cannot cancel closed SO

View File

@@ -73,7 +73,7 @@ erpnext.PointOfSale.PastOrderSummary = class {
const { status } = doc;
let indicator_color = "";
in_list(["Paid", "Consolidated"], status) && (indicator_color = "green");
["Paid", "Consolidated"].includes(status) && (indicator_color = "green");
status === "Draft" && (indicator_color = "red");
status === "Return" && (indicator_color = "grey");

View File

@@ -219,7 +219,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
serial_no: item.serial_no || "",
},
callback:function(r){
if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
if (['Delivery Note', 'Sales Invoice'].includes(doc.doctype)) {
if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return;
if (has_batch_no) {
me.set_batch_number(cdt, cdn);
@@ -332,7 +332,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
if ((doc.packed_items || []).length) {
$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(true);
if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
if (['Delivery Note', 'Sales Invoice'].includes(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>";
@@ -340,7 +340,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
}
} else {
$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(false);
if (in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
if (['Delivery Note', 'Sales Invoice'].includes(doc.doctype)) {
frappe.meta.get_docfield(doc.doctype, 'product_bundle_help', doc.name).options = '';
}
}
@@ -367,7 +367,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
conversion_factor(doc, cdt, cdn, dont_fetch_price_list_rate) {
super.conversion_factor(doc, cdt, cdn, dont_fetch_price_list_rate);
if(frappe.meta.get_docfield(cdt, "stock_qty", cdn) &&
in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
['Delivery Note', 'Sales Invoice'].includes(doc.doctype)) {
if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return;
this.set_batch_number(cdt, cdn);
}
@@ -376,7 +376,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
qty(doc, cdt, cdn) {
super.qty(doc, cdt, cdn);
if(in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
if(['Delivery Note', 'Sales Invoice'].includes(doc.doctype)) {
if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return;
this.set_batch_number(cdt, cdn);
}
@@ -440,7 +440,7 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran
};
frappe.ui.form.on(cur_frm.doctype,"project", function(frm) {
if(in_list(["Delivery Note", "Sales Invoice"], frm.doc.doctype)) {
if(["Delivery Note", "Sales Invoice"].includes(frm.doc.doctype)) {
if(frm.doc.project) {
frappe.call({
method:'erpnext.projects.doctype.project.project.get_cost_center_name' ,

View File

@@ -712,7 +712,7 @@
"image_field": "company_logo",
"is_tree": 1,
"links": [],
"modified": "2023-10-23 10:19:24.322898",
"modified": "2024-05-27 17:32:49.057386",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",
@@ -768,6 +768,10 @@
"role": "Accounts Manager",
"share": 1,
"write": 1
},
{
"role": "Auditor",
"select": 1
}
],
"show_name_in_global_search": 1,

View File

@@ -90,7 +90,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2023-08-28 17:26:46.826501",
"modified": "2024-06-12 16:10:31.451257",
"modified_by": "Administrator",
"module": "Setup",
"name": "Department",
@@ -132,6 +132,10 @@
"role": "HR Manager",
"share": 1,
"write": 1
},
{
"role": "Employee",
"select": 1
}
],
"show_name_in_global_search": 1,

View File

@@ -8,7 +8,7 @@ frappe.ui.form.on("Closing Stock Balance", {
},
generate_closing_balance(frm) {
if (in_list(["Queued", "Failed"], frm.doc.status)) {
if (["Queued", "Failed"].includes(frm.doc.status)) {
frm.add_custom_button(__("Generate Closing Stock Balance"), () => {
frm.call({
method: "enqueue_job",

View File

@@ -1,9 +1,9 @@
frappe.listview_settings["Delivery Trip"] = {
add_fields: ["status"],
get_indicator: function (doc) {
if (in_list(["Cancelled", "Draft"], doc.status)) {
if (["Cancelled", "Draft"].includes(doc.status)) {
return [__(doc.status), "red", "status,=," + doc.status];
} else if (in_list(["In Transit", "Scheduled"], doc.status)) {
} else if (["In Transit", "Scheduled"].includes(doc.status)) {
return [__(doc.status), "orange", "status,=," + doc.status];
} else if (doc.status === "Completed") {
return [__(doc.status), "green", "status,=," + doc.status];

View File

@@ -224,7 +224,10 @@ class LandedCostVoucher(Document):
# update stock & gl entries for submit state of PR
doc.docstatus = 1
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
doc.make_gl_entries()
if d.receipt_document_type == "Purchase Receipt":
doc.make_gl_entries(via_landed_cost_voucher=True)
else:
doc.make_gl_entries()
doc.repost_future_sle_and_gle()
def validate_asset_qty_and_status(self, receipt_document_type, receipt_document):

View File

@@ -307,13 +307,13 @@ class PurchaseReceipt(BuyingController):
self.delete_auto_created_batches()
self.set_consumed_qty_in_subcontract_order()
def get_gl_entries(self, warehouse_account=None):
def get_gl_entries(self, warehouse_account=None, via_landed_cost_voucher=False):
from erpnext.accounts.general_ledger import process_gl_map
gl_entries = []
self.make_item_gl_entries(gl_entries, warehouse_account=warehouse_account)
self.make_tax_gl_entries(gl_entries)
self.make_tax_gl_entries(gl_entries, via_landed_cost_voucher)
update_regional_gl_entries(gl_entries, self)
return process_gl_map(gl_entries)
@@ -661,7 +661,7 @@ class PurchaseReceipt(BuyingController):
posting_date=posting_date,
)
def make_tax_gl_entries(self, gl_entries):
def make_tax_gl_entries(self, gl_entries, via_landed_cost_voucher=False):
negative_expense_to_be_booked = sum([flt(d.item_tax_amount) for d in self.get("items")])
is_asset_pr = any(d.is_fixed_asset for d in self.get("items"))
# Cost center-wise amount breakup for other charges included for valuation
@@ -696,18 +696,17 @@ class PurchaseReceipt(BuyingController):
i = 1
for tax in self.get("taxes"):
if valuation_tax.get(tax.name):
negative_expense_booked_in_pi = frappe.db.sql(
"""select name from `tabPurchase Invoice Item` pi
where docstatus = 1 and purchase_receipt=%s
and exists(select name from `tabGL Entry` where voucher_type='Purchase Invoice'
and voucher_no=pi.parent and account=%s)""",
(self.name, tax.account_head),
)
if negative_expense_booked_in_pi:
account = stock_rbnb
else:
if via_landed_cost_voucher:
account = tax.account_head
else:
negative_expense_booked_in_pi = frappe.db.sql(
"""select name from `tabPurchase Invoice Item` pi
where docstatus = 1 and purchase_receipt=%s
and exists(select name from `tabGL Entry` where voucher_type='Purchase Invoice'
and voucher_no=pi.parent and account=%s)""",
(self.name, tax.account_head),
)
account = stock_rbnb if negative_expense_booked_in_pi else tax.account_head
if i == len(valuation_tax):
applicable_amount = amount_including_divisional_loss

View File

@@ -9,6 +9,7 @@ from pypika import functions as fn
import erpnext
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.controllers.buying_controller import QtyMismatchError
from erpnext.stock import get_warehouse_account_map
from erpnext.stock.doctype.item.test_item import create_item, make_item
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -1640,7 +1641,6 @@ class TestPurchaseReceipt(FrappeTestCase):
frappe.db.set_single_value("Stock Settings", "over_delivery_receipt_allowance", 0)
def test_internal_pr_gl_entries(self):
from erpnext.stock import get_warehouse_account_map
from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
@@ -2301,6 +2301,54 @@ class TestPurchaseReceipt(FrappeTestCase):
for index, d in enumerate(data):
self.assertEqual(d.qty_after_transaction, 11 + index)
def test_valuation_taxes_lcv_repost_after_billing(self):
from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import (
make_landed_cost_voucher,
)
old_perpetual_inventory = erpnext.is_perpetual_inventory_enabled("_Test Company")
frappe.local.enable_perpetual_inventory["_Test Company"] = 1
frappe.db.set_value(
"Company",
"_Test Company",
"stock_received_but_not_billed",
"Stock Received But Not Billed - _TC",
)
pr = make_purchase_receipt(qty=10, rate=1000, do_not_submit=1)
pr.append(
"taxes",
{
"category": "Valuation and Total",
"charge_type": "Actual",
"account_head": "Freight and Forwarding Charges - _TC",
"tax_amount": 2000,
"description": "Test",
},
)
pr.submit()
pi = make_purchase_invoice(pr.name)
pi.submit()
make_landed_cost_voucher(
company=pr.company,
receipt_document_type="Purchase Receipt",
receipt_document=pr.name,
charges=2000,
distribute_charges_based_on="Qty",
expense_account="Expenses Included In Valuation - _TC",
)
gl_entries = get_gl_entries("Purchase Receipt", pr.name, skip_cancelled=True, as_dict=False)
warehouse_account = get_warehouse_account_map("_Test Company")
expected_gle = (
("Stock Received But Not Billed - _TC", 0, 10000, "Main - _TC"),
("Freight and Forwarding Charges - _TC", 0, 2000, "Main - _TC"),
("Expenses Included In Valuation - _TC", 0, 2000, "Main - _TC"),
(warehouse_account[pr.items[0].warehouse]["account"], 14000, 0, "Main - _TC"),
)
self.assertSequenceEqual(expected_gle, gl_entries)
frappe.local.enable_perpetual_inventory["_Test Company"] = old_perpetual_inventory
def prepare_data_for_internal_transfer():
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
@@ -2347,14 +2395,24 @@ def get_sl_entries(voucher_type, voucher_no):
)
def get_gl_entries(voucher_type, voucher_no):
return frappe.db.sql(
"""select account, debit, credit, cost_center, is_cancelled
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
order by account desc""",
(voucher_type, voucher_no),
as_dict=1,
def get_gl_entries(voucher_type, voucher_no, skip_cancelled=False, as_dict=True):
gl = frappe.qb.DocType("GL Entry")
gl_query = (
frappe.qb.from_(gl)
.select(
gl.account,
gl.debit,
gl.credit,
gl.cost_center,
)
.where((gl.voucher_type == voucher_type) & (gl.voucher_no == voucher_no))
.orderby(gl.account, order=frappe.qb.desc)
)
if skip_cancelled:
gl_query = gl_query.where(gl.is_cancelled == 0)
else:
gl_query = gl_query.select(gl.is_cancelled)
return gl_query.run(as_dict=as_dict)
def get_taxes(**args):

View File

@@ -45,7 +45,7 @@ class RepostItemValuation(Document):
def validate_period_closing_voucher(self):
# Period Closing Voucher
year_end_date = self.get_max_year_end_date(self.company)
year_end_date = self.get_max_period_closing_date(self.company)
if year_end_date and getdate(self.posting_date) <= getdate(year_end_date):
date = frappe.format(year_end_date, "Date")
msg = f"Due to period closing, you cannot repost item valuation before {date}"
@@ -88,24 +88,16 @@ class RepostItemValuation(Document):
return frappe.get_all("Closing Stock Balance", fields=["name", "to_date"], filters=filters)
@staticmethod
def get_max_year_end_date(company):
data = frappe.get_all(
"Period Closing Voucher", fields=["fiscal_year"], filters={"docstatus": 1, "company": company}
)
if not data:
return
fiscal_years = [d.fiscal_year for d in data]
table = frappe.qb.DocType("Fiscal Year")
def get_max_period_closing_date(company):
table = frappe.qb.DocType("Period Closing Voucher")
query = (
frappe.qb.from_(table)
.select(Max(table.year_end_date))
.where((table.name.isin(fiscal_years)) & (table.disabled == 0))
.select(Max(table.posting_date))
.where((table.company == company) & (table.docstatus == 1))
).run()
return query[0][0] if query else None
return query[0][0] if query and query[0][0] else None
def validate_accounts_freeze(self):
acc_settings = frappe.db.get_value(

View File

@@ -77,7 +77,7 @@ frappe.ui.form.on('Stock Entry', {
if(!item.item_code) {
frappe.throw(__("Please enter Item Code to get Batch Number"));
} else {
if (in_list(["Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor"], doc.purpose)) {
if (["Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor"].includes(doc.purpose)) {
var filters = {
'item_code': item.item_code,
'posting_date': frm.doc.posting_date || frappe.datetime.nowdate()

View File

@@ -18,7 +18,7 @@
actual_qty = (frm.doc.doctype==="Sales Order"
? doc.projected_qty : doc.actual_qty);
if(flt(frm.doc.per_delivered) < 100
&& in_list(["Sales Order Item", "Delivery Note Item"], doc.doctype)) {
&& ["Sales Order Item", "Delivery Note Item"].includes(doc.doctype)) {
if(actual_qty != undefined) {
if(actual_qty >= doc.qty) {
var color = "green";