From 1fe891b287a1b3f225d29ee3d07e7b1824aba9e7 Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Fri, 23 Apr 2021 08:04:00 +0530
Subject: [PATCH 001/262] refactor: Replace Class.extend with native class
---
.../doctype/journal_entry/journal_entry.js | 36 +-
.../payment_reconciliation.js | 38 +-
.../doctype/pos_invoice/pos_invoice.js | 50 +--
.../purchase_invoice/purchase_invoice.js | 98 ++---
.../doctype/sales_invoice/sales_invoice.js | 127 ++++---
.../doctype/purchase_order/purchase_order.js | 90 ++---
.../request_for_quotation.js | 22 +-
.../supplier_quotation/supplier_quotation.js | 22 +-
erpnext/crm/doctype/lead/lead.js | 38 +-
.../crm/doctype/opportunity/opportunity.js | 14 +-
.../student_attendance_tool.js | 14 +-
.../doctype/exercise_type/exercise_type.js | 26 +-
erpnext/hr/doctype/employee/employee.js | 20 +-
.../employee_attendance_tool.js | 20 +-
.../upload_attendance/upload_attendance.js | 18 +-
.../maintenance_schedule.js | 24 +-
.../maintenance_visit/maintenance_visit.js | 10 +-
erpnext/manufacturing/doctype/bom/bom.js | 24 +-
erpnext/public/js/account_tree_grid.js | 81 ++--
erpnext/public/js/controllers/buying.js | 122 +++---
.../public/js/controllers/stock_controller.js | 22 +-
.../public/js/controllers/taxes_and_totals.js | 146 +++----
erpnext/public/js/controllers/transaction.js | 358 +++++++++---------
erpnext/public/js/payment/payments.js | 92 ++---
erpnext/public/js/stock_analytics.js | 46 +--
erpnext/public/js/stock_grid_report.js | 24 +-
erpnext/public/js/telephony.js | 10 +-
.../public/js/utils/customer_quick_entry.js | 20 +-
erpnext/public/js/utils/item_quick_entry.js | 90 ++---
erpnext/public/js/utils/item_selector.js | 22 +-
.../js/utils/serial_no_batch_selector.js | 48 +--
.../installation_note/installation_note.js | 8 +-
.../selling/doctype/quotation/quotation.js | 44 +--
.../doctype/sales_order/sales_order.js | 90 ++---
erpnext/selling/sales_common.js | 144 +++----
erpnext/stock/dashboard/item_dashboard.js | 26 +-
.../doctype/delivery_note/delivery_note.js | 60 +--
.../landed_cost_voucher.js | 34 +-
.../material_request/material_request.js | 42 +-
.../purchase_receipt/purchase_receipt.js | 38 +-
.../stock/doctype/stock_entry/stock_entry.js | 82 ++--
.../stock_reconciliation.js | 12 +-
.../doctype/warranty_claim/warranty_claim.js | 10 +-
erpnext/templates/includes/rfq.js | 34 +-
44 files changed, 1200 insertions(+), 1196 deletions(-)
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js
index 37b03f3f0e..2f8d3e31d9 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js
@@ -194,19 +194,19 @@ var update_jv_details = function(doc, r) {
refresh_field("accounts");
}
-erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
- onload: function() {
+erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Controller {
+ onload() {
this.load_defaults();
this.setup_queries();
this.setup_balance_formatter();
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
- },
+ }
- onload_post_render: function() {
+ onload_post_render() {
cur_frm.get_field("accounts").grid.set_multiple_add("account");
- },
+ }
- load_defaults: function() {
+ load_defaults() {
//this.frm.show_print_first = true;
if(this.frm.doc.__islocal && this.frm.doc.company) {
frappe.model.set_default_values(this.frm.doc);
@@ -216,9 +216,9 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
var posting_date = this.frm.doc.posting_date;
if(!this.frm.doc.amended_from) this.frm.set_value('posting_date', posting_date || frappe.datetime.get_today());
}
- },
+ }
- setup_queries: function() {
+ setup_queries() {
var me = this;
me.frm.set_query("account", "accounts", function(doc, cdt, cdn) {
@@ -324,9 +324,9 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
});
- },
+ }
- setup_balance_formatter: function() {
+ setup_balance_formatter() {
var me = this;
$.each(["balance", "party_balance"], function(i, field) {
var df = frappe.meta.get_docfield("Journal Entry Account", field, me.frm.doc.name);
@@ -339,9 +339,9 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
+ "";
}
})
- },
+ }
- reference_name: function(doc, cdt, cdn) {
+ reference_name(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if(d.reference_name) {
@@ -353,9 +353,9 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
this.get_outstanding('Journal Entry', d.reference_name, doc.company, d);
}
}
- },
+ }
- get_outstanding: function(doctype, docname, company, child, due_date) {
+ get_outstanding(doctype, docname, company, child, due_date) {
var me = this;
var args = {
"doctype": doctype,
@@ -377,9 +377,9 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
}
}
});
- },
+ }
- accounts_add: function(doc, cdt, cdn) {
+ accounts_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
$.each(doc.accounts, function(i, d) {
if(d.account && d.party && d.party_type) {
@@ -402,9 +402,9 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
cur_frm.cscript.update_totals(doc);
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, 'accounts');
- },
+ }
-});
+};
cur_frm.script_manager.make(erpnext.accounts.JournalEntry);
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index 6b07197ec1..dd91fec3c1 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -34,8 +34,8 @@ frappe.ui.form.on("Payment Reconciliation Payment", {
}
});
-erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.extend({
- onload: function() {
+erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationController extends frappe.ui.form.Controller {
+ onload() {
var me = this;
this.frm.set_query("party", function() {
@@ -84,18 +84,18 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
frappe.throw({message: __("Please Select Both Company and Party Type First"), title: title});
}
};
- },
+ }
- refresh: function() {
+ refresh() {
this.frm.disable_save();
this.toggle_primary_action();
- },
+ }
- onload_post_render: function() {
+ onload_post_render() {
this.toggle_primary_action();
- },
+ }
- party: function() {
+ party() {
var me = this
if (!me.frm.doc.receivable_payable_account && me.frm.doc.party_type && me.frm.doc.party) {
return frappe.call({
@@ -112,9 +112,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
}
});
}
- },
+ }
- get_unreconciled_entries: function() {
+ get_unreconciled_entries() {
var me = this;
return this.frm.call({
doc: me.frm.doc,
@@ -125,9 +125,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
}
});
- },
+ }
- reconcile: function() {
+ reconcile() {
var me = this;
var show_dialog = me.frm.doc.payments.filter(d => d.difference_amount && !d.difference_account);
@@ -209,9 +209,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
} else {
this.reconcile_payment_entries();
}
- },
+ }
- reconcile_payment_entries: function() {
+ reconcile_payment_entries() {
var me = this;
return this.frm.call({
@@ -222,9 +222,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
me.toggle_primary_action();
}
});
- },
+ }
- set_invoice_options: function() {
+ set_invoice_options() {
var me = this;
var invoices = [];
@@ -243,9 +243,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
}
refresh_field("payments");
- },
+ }
- toggle_primary_action: function() {
+ toggle_primary_action() {
if ((this.frm.doc.payments || []).length) {
this.frm.fields_dict.reconcile.$input
&& this.frm.fields_dict.reconcile.$input.addClass("btn-primary");
@@ -259,6 +259,6 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
}
}
-});
+};
$.extend(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.js b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
index 493bd44802..72d587afb5 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
@@ -4,18 +4,18 @@
{% include 'erpnext/selling/sales_common.js' %};
frappe.provide("erpnext.accounts");
-erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend({
+erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnext.selling.SellingController {
setup(doc) {
this.setup_posting_date_time_check();
- this._super(doc);
- },
+ super.setup(doc);
+ }
- company: function() {
+ company() {
erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype);
- },
+ }
onload(doc) {
- this._super();
+ super.onload();
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log'];
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
this.frm.script_manager.trigger("is_pos");
@@ -23,10 +23,10 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
}
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
- },
+ }
refresh(doc) {
- this._super();
+ super.refresh();
if (doc.docstatus == 1 && !doc.is_return) {
this.frm.add_custom_button(__('Return'), this.make_sales_return, __('Create'));
this.frm.page.set_inner_btn_group_as_primary(__('Create'));
@@ -36,13 +36,13 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
this.frm.return_print_format = "Sales Invoice Return";
this.frm.set_value('consolidated_invoice', '');
}
- },
+ }
- is_pos: function() {
+ is_pos() {
this.set_pos_data();
- },
+ }
- set_pos_data: async function() {
+ async set_pos_data() {
if(this.frm.doc.is_pos) {
this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) {
@@ -69,7 +69,7 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
}
}
}
- },
+ }
customer() {
if (!this.frm.doc.customer) return
@@ -86,13 +86,13 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
}, () => {
this.apply_pricing_rule();
});
- },
+ }
- amount: function(){
+ amount(){
this.write_off_outstanding_amount_automatically()
- },
+ }
- change_amount: function(){
+ change_amount(){
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
this.calculate_write_off_amount();
}else {
@@ -101,16 +101,16 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
}
this.frm.refresh_fields();
- },
+ }
- loyalty_amount: function(){
+ loyalty_amount(){
this.calculate_outstanding_amount();
this.frm.refresh_field("outstanding_amount");
this.frm.refresh_field("paid_amount");
this.frm.refresh_field("base_paid_amount");
- },
+ }
- write_off_outstanding_amount_automatically: function() {
+ write_off_outstanding_amount_automatically() {
if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
// this will make outstanding amount 0
@@ -125,15 +125,15 @@ erpnext.selling.POSInvoiceController = erpnext.selling.SellingController.extend(
this.calculate_outstanding_amount(false);
this.frm.refresh_fields();
- },
+ }
- make_sales_return: function() {
+ make_sales_return() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.pos_invoice.pos_invoice.make_sales_return",
frm: cur_frm
})
- },
-})
+ }
+}
$.extend(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm }))
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 06aa20bfc5..b31cdce0b2 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -4,10 +4,10 @@
frappe.provide("erpnext.accounts");
{% include 'erpnext/public/js/controllers/buying.js' %};
-erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
- setup: function(doc) {
+erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.BuyingController {
+ setup(doc) {
this.setup_posting_date_time_check();
- this._super(doc);
+ super.setup(doc);
// formatter for purchase invoice item
if(this.frm.doc.update_stock) {
@@ -25,14 +25,14 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
};
});
- },
+ }
- company: function() {
+ company() {
erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype);
- },
+ }
- onload: function() {
- this._super();
+ onload() {
+ super.onload();
if(!this.frm.doc.__islocal) {
// show credit_to in print format
@@ -48,11 +48,11 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
- },
+ }
- refresh: function(doc) {
+ refresh(doc) {
const me = this;
- this._super();
+ super.refresh();
hide_fields(this.frm.doc);
// Show / Hide button
@@ -161,26 +161,26 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
this.frm.set_df_property("tax_withholding_category", "hidden", doc.apply_tds ? 0 : 1);
- },
+ }
- unblock_invoice: function() {
+ unblock_invoice() {
const me = this;
frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.unblock_invoice',
'args': {'name': me.frm.doc.name},
'callback': (r) => me.frm.reload_doc()
});
- },
+ }
- block_invoice: function() {
+ block_invoice() {
this.make_comment_dialog_and_block_invoice();
- },
+ }
- change_release_date: function() {
+ change_release_date() {
this.make_dialog_and_set_release_date();
- },
+ }
- can_change_release_date: function(date) {
+ can_change_release_date(date) {
const diff = frappe.datetime.get_diff(date, frappe.datetime.nowdate());
if (diff < 0) {
frappe.throw(__('New release date should be in the future'));
@@ -188,9 +188,9 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
} else {
return true;
}
- },
+ }
- make_comment_dialog_and_block_invoice: function(){
+ make_comment_dialog_and_block_invoice(){
const me = this;
const title = __('Block Invoice');
@@ -232,9 +232,9 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
});
this.dialog.show();
- },
+ }
- make_dialog_and_set_release_date: function() {
+ make_dialog_and_set_release_date() {
const me = this;
const title = __('Set New Release Date');
@@ -263,17 +263,17 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
});
this.dialog.show();
- },
+ }
- set_release_date: function(data) {
+ set_release_date(data) {
return frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.change_release_date',
'args': data,
'callback': (r) => this.frm.reload_doc()
});
- },
+ }
- supplier: function() {
+ supplier() {
var me = this;
// Do not update if inter company reference is there as the details will already be updated
@@ -295,9 +295,9 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
me.frm.set_df_property("apply_tds", "read_only", me.frm.supplier_tds ? 0 : 1);
me.frm.set_df_property("tax_withholding_category", "hidden", me.frm.supplier_tds ? 0 : 1);
})
- },
+ }
- apply_tds: function(frm) {
+ apply_tds(frm) {
var me = this;
if (!me.frm.doc.apply_tds) {
@@ -307,9 +307,9 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
me.frm.set_value("tax_withholding_category", me.frm.supplier_tds);
me.frm.set_df_property("tax_withholding_category", "hidden", 0);
}
- },
+ }
- credit_to: function() {
+ credit_to() {
var me = this;
if(this.frm.doc.credit_to) {
me.frm.call({
@@ -327,16 +327,16 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
});
}
- },
+ }
- make_inter_company_invoice: function(frm) {
+ make_inter_company_invoice(frm) {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_inter_company_sales_invoice",
frm: frm
});
- },
+ }
- is_paid: function() {
+ is_paid() {
hide_fields(this.frm.doc);
if(cint(this.frm.doc.is_paid)) {
this.frm.set_value("allocate_advances_automatically", 0);
@@ -347,44 +347,44 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
this.calculate_outstanding_amount();
this.frm.refresh_fields();
- },
+ }
- write_off_amount: function() {
+ write_off_amount() {
this.set_in_company_currency(this.frm.doc, ["write_off_amount"]);
this.calculate_outstanding_amount();
this.frm.refresh_fields();
- },
+ }
- paid_amount: function() {
+ paid_amount() {
this.set_in_company_currency(this.frm.doc, ["paid_amount"]);
this.write_off_amount();
this.frm.refresh_fields();
- },
+ }
- allocated_amount: function() {
+ allocated_amount() {
this.calculate_total_advance();
this.frm.refresh_fields();
- },
+ }
- items_add: function(doc, cdt, cdn) {
+ items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("items", row,
["expense_account", "cost_center", "project"]);
- },
+ }
- on_submit: function() {
+ on_submit() {
$.each(this.frm.doc["items"] || [], function(i, row) {
if(row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt)
})
- },
+ }
- make_debit_note: function() {
+ make_debit_note() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_debit_note",
frm: cur_frm
})
- },
-});
+ }
+};
cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index b361c0c345..8e8f85a3e4 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -2,23 +2,24 @@
// License: GNU General Public License v3. See license.txt
// print heading
+frappe.provide('cur_frm.pformat')
cur_frm.pformat.print_heading = 'Invoice';
{% include 'erpnext/selling/sales_common.js' %};
frappe.provide("erpnext.accounts");
-erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({
- setup: function(doc) {
+erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends erpnext.selling.SellingController {
+ setup(doc) {
this.setup_posting_date_time_check();
- this._super(doc);
- },
- company: function() {
+ super.setup(doc);
+ }
+ company() {
erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype);
- },
- onload: function() {
+ }
+ onload() {
var me = this;
- this._super();
+ super.onload();
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice'];
if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) {
@@ -38,11 +39,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
erpnext.queries.setup_warehouse_query(this.frm);
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
- },
+ }
- refresh: function(doc, dt, dn) {
+ refresh(doc, dt, dn) {
const me = this;
- this._super();
+ super.refresh();
if(cur_frm.msgbox && cur_frm.msgbox.$wrapper.is(":visible")) {
// hide new msgbox
cur_frm.msgbox.hide();
@@ -141,16 +142,16 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}, __('Create'));
}
}
- },
+ }
- make_maintenance_schedule: function() {
+ make_maintenance_schedule() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_maintenance_schedule",
frm: cur_frm
})
- },
+ }
- on_submit: function(doc, dt, dn) {
+ on_submit(doc, dt, dn) {
var me = this;
if (frappe.get_route()[0] != 'Form') {
@@ -160,9 +161,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
$.each(doc["items"], function(i, row) {
if(row.delivery_note) frappe.model.clear_doc("Delivery Note", row.delivery_note)
})
- },
+ }
- set_default_print_format: function() {
+ set_default_print_format() {
// set default print format to POS type or Credit Note
if(cur_frm.doc.is_pos) {
if(cur_frm.pos_print_format) {
@@ -183,9 +184,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
cur_frm.meta._default_print_format = null;
}
}
- },
+ }
- sales_order_btn: function() {
+ sales_order_btn() {
var me = this;
this.$sales_order_btn = this.frm.add_custom_button(__('Sales Order'),
function() {
@@ -204,9 +205,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
})
}, __("Get Items From"));
- },
+ }
- quotation_btn: function() {
+ quotation_btn() {
var me = this;
this.$quotation_btn = this.frm.add_custom_button(__('Quotation'),
function() {
@@ -228,9 +229,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
})
}, __("Get Items From"));
- },
+ }
- delivery_note_btn: function() {
+ delivery_note_btn() {
var me = this;
this.$delivery_note_btn = this.frm.add_custom_button(__('Delivery Note'),
function() {
@@ -256,12 +257,12 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
});
}, __("Get Items From"));
- },
+ }
- tc_name: function() {
+ tc_name() {
this.get_terms();
- },
- customer: function() {
+ }
+ customer() {
if (this.frm.doc.is_pos){
var pos_profile = this.frm.doc.pos_profile;
}
@@ -292,16 +293,16 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
});
}
- },
+ }
- make_inter_company_invoice: function() {
+ make_inter_company_invoice() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_inter_company_purchase_invoice",
frm: me.frm
});
- },
+ }
- debit_to: function() {
+ debit_to() {
var me = this;
if(this.frm.doc.debit_to) {
me.frm.call({
@@ -319,14 +320,14 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
});
}
- },
+ }
- allocated_amount: function() {
+ allocated_amount() {
this.calculate_total_advance();
this.frm.refresh_fields();
- },
+ }
- write_off_outstanding_amount_automatically: function() {
+ write_off_outstanding_amount_automatically() {
if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
// this will make outstanding amount 0
@@ -341,39 +342,39 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
this.calculate_outstanding_amount(false);
this.frm.refresh_fields();
- },
+ }
- write_off_amount: function() {
+ write_off_amount() {
this.set_in_company_currency(this.frm.doc, ["write_off_amount"]);
this.write_off_outstanding_amount_automatically();
- },
+ }
- items_add: function(doc, cdt, cdn) {
+ items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("items", row, ["income_account", "cost_center"]);
- },
+ }
- set_dynamic_labels: function() {
- this._super();
+ set_dynamic_labels() {
+ super.set_dynamic_labels();
this.frm.events.hide_fields(this.frm)
- },
+ }
- items_on_form_rendered: function() {
+ items_on_form_rendered() {
erpnext.setup_serial_no();
- },
+ }
- packed_items_on_form_rendered: function(doc, grid_row) {
+ packed_items_on_form_rendered(doc, grid_row) {
erpnext.setup_serial_no();
- },
+ }
- make_sales_return: function() {
+ make_sales_return() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_sales_return",
frm: cur_frm
})
- },
+ }
- asset: function(frm, cdt, cdn) {
+ asset(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if(row.asset) {
frappe.call({
@@ -387,18 +388,18 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
})
}
- },
+ }
- is_pos: function(frm){
+ is_pos(frm){
this.set_pos_data();
- },
+ }
- pos_profile: function() {
+ pos_profile() {
this.frm.doc.taxes = []
this.set_pos_data();
- },
+ }
- set_pos_data: function() {
+ set_pos_data() {
if(this.frm.doc.is_pos) {
this.frm.set_value("allocate_advances_automatically", 0);
if(!this.frm.doc.company) {
@@ -428,13 +429,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
}
else this.frm.trigger("refresh");
- },
+ }
- amount: function(){
+ amount(){
this.write_off_outstanding_amount_automatically()
- },
+ }
- change_amount: function(){
+ change_amount(){
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
this.calculate_write_off_amount();
}else {
@@ -443,15 +444,15 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
this.frm.refresh_fields();
- },
+ }
- loyalty_amount: function(){
+ loyalty_amount(){
this.calculate_outstanding_amount();
this.frm.refresh_field("outstanding_amount");
this.frm.refresh_field("paid_amount");
this.frm.refresh_field("base_paid_amount");
}
-});
+};
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm}));
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index dd0f065848..c0e19e9c3d 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -61,8 +61,8 @@ frappe.ui.form.on("Purchase Order Item", {
}
});
-erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
- setup: function() {
+erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends erpnext.buying.BuyingController {
+ setup() {
this.frm.custom_make_buttons = {
'Purchase Receipt': 'Purchase Receipt',
'Purchase Invoice': 'Purchase Invoice',
@@ -70,13 +70,13 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
'Payment Entry': 'Payment',
}
- this._super();
+ super.setup();
- },
+ }
- refresh: function(doc, cdt, cdn) {
+ refresh(doc, cdt, cdn) {
var me = this;
- this._super();
+ super.refresh();
var allow_receipt = false;
var is_drop_ship = false;
@@ -182,9 +182,9 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
} else if(doc.docstatus===0) {
cur_frm.cscript.add_from_mappers();
}
- },
+ }
- get_items_from_open_material_requests: function() {
+ get_items_from_open_material_requests() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order_based_on_supplier",
args: {
@@ -202,17 +202,17 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
},
get_query_method: "erpnext.stock.doctype.material_request.material_request.get_material_requests_based_on_supplier"
});
- },
+ }
- validate: function() {
+ validate() {
set_schedule_date(this.frm);
- },
+ }
- has_unsupplied_items: function() {
+ has_unsupplied_items() {
return this.frm.doc['supplied_items'].some(item => item.required_qty != item.supplied_qty)
- },
+ }
- make_stock_entry: function() {
+ make_stock_entry() {
var items = $.map(cur_frm.doc.items, function(d) { return d.bom ? d.item_code : false; });
var me = this;
@@ -326,9 +326,9 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
me.dialog.hide();
});
- },
+ }
- _make_rm_stock_entry: function(rm_items) {
+ _make_rm_stock_entry(rm_items) {
frappe.call({
method:"erpnext.buying.doctype.purchase_order.purchase_order.make_rm_stock_entry",
args: {
@@ -341,31 +341,31 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
- },
+ }
- make_inter_company_order: function(frm) {
+ make_inter_company_order(frm) {
frappe.model.open_mapped_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_inter_company_sales_order",
frm: frm
});
- },
+ }
- make_purchase_receipt: function() {
+ make_purchase_receipt() {
frappe.model.open_mapped_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
frm: cur_frm,
freeze_message: __("Creating Purchase Receipt ...")
})
- },
+ }
- make_purchase_invoice: function() {
+ make_purchase_invoice() {
frappe.model.open_mapped_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
frm: cur_frm
})
- },
+ }
- add_from_mappers: function() {
+ add_from_mappers() {
var me = this;
this.frm.add_custom_button(__('Material Request'),
function() {
@@ -471,13 +471,13 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
}
});
}, __("Tools"));
- },
+ }
- tc_name: function() {
+ tc_name() {
this.get_terms();
- },
+ }
- items_add: function(doc, cdt, cdn) {
+ items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
if(doc.schedule_date) {
row.schedule_date = doc.schedule_date;
@@ -485,13 +485,13 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
} else {
this.frm.script_manager.copy_from_first_row("items", row, ["schedule_date"]);
}
- },
+ }
- unhold_purchase_order: function(){
+ unhold_purchase_order(){
cur_frm.cscript.update_status("Resume", "Draft")
- },
+ }
- hold_purchase_order: function(){
+ hold_purchase_order(){
var me = this;
var d = new frappe.ui.Dialog({
title: __('Reason for Hold'),
@@ -523,28 +523,28 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
}
});
d.show();
- },
+ }
- unclose_purchase_order: function(){
+ unclose_purchase_order(){
cur_frm.cscript.update_status('Re-open', 'Submitted')
- },
+ }
- close_purchase_order: function(){
+ close_purchase_order(){
cur_frm.cscript.update_status('Close', 'Closed')
- },
+ }
- delivered_by_supplier: function(){
+ delivered_by_supplier(){
cur_frm.cscript.update_status('Deliver', 'Delivered')
- },
+ }
- items_on_form_rendered: function() {
- set_schedule_date(this.frm);
- },
-
- schedule_date: function() {
+ items_on_form_rendered() {
set_schedule_date(this.frm);
}
-});
+
+ schedule_date() {
+ set_schedule_date(this.frm);
+ }
+};
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.buying.PurchaseOrderController({frm: cur_frm}));
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index b76c3784a4..ee0e1ef576 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -205,10 +205,10 @@ frappe.ui.form.on("Request for Quotation Supplier",{
})
-erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.extend({
- refresh: function() {
+erpnext.buying.RequestforQuotationController = class RequestforQuotationController extends erpnext.buying.BuyingController {
+ refresh() {
var me = this;
- this._super();
+ super.refresh();
if (this.frm.doc.docstatus===0) {
this.frm.add_custom_button(__('Material Request'),
function() {
@@ -302,17 +302,17 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
me.get_suppliers_button(me.frm);
}, __("Tools"));
}
- },
+ }
- calculate_taxes_and_totals: function() {
+ calculate_taxes_and_totals() {
return;
- },
+ }
- tc_name: function() {
+ tc_name() {
this.get_terms();
- },
+ }
- get_suppliers_button: function (frm) {
+ get_suppliers_button (frm) {
var doc = frm.doc;
var dialog = new frappe.ui.Dialog({
title: __("Get Suppliers"),
@@ -410,8 +410,8 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
});
dialog.show();
- },
-});
+ }
+};
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.buying.RequestforQuotationController({frm: cur_frm}));
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index a0187b0a82..a3ba52e67b 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -4,19 +4,19 @@
// attach required files
{% include 'erpnext/public/js/controllers/buying.js' %};
-erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
- setup: function() {
+erpnext.buying.SupplierQuotationController = class SupplierQuotationController extends erpnext.buying.BuyingController {
+ setup() {
this.frm.custom_make_buttons = {
'Purchase Order': 'Purchase Order',
'Quotation': 'Quotation'
}
- this._super();
- },
+ super.setup();
+ }
- refresh: function() {
+ refresh() {
var me = this;
- this._super();
+ super.refresh();
if (this.frm.doc.__islocal && !this.frm.doc.valid_till) {
this.frm.set_value('valid_till', frappe.datetime.add_months(this.frm.doc.transaction_date, 1));
@@ -77,22 +77,22 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
})
}, __("Get Items From"));
}
- },
+ }
- make_purchase_order: function() {
+ make_purchase_order() {
frappe.model.open_mapped_doc({
method: "erpnext.buying.doctype.supplier_quotation.supplier_quotation.make_purchase_order",
frm: cur_frm
})
- },
- make_quotation: function() {
+ }
+ make_quotation() {
frappe.model.open_mapped_doc({
method: "erpnext.buying.doctype.supplier_quotation.supplier_quotation.make_quotation",
frm: cur_frm
})
}
-});
+};
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.buying.SupplierQuotationController({frm: cur_frm}));
diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js
index 0c88d2826f..8dfee1d6c7 100644
--- a/erpnext/crm/doctype/lead/lead.js
+++ b/erpnext/crm/doctype/lead/lead.js
@@ -4,8 +4,8 @@
frappe.provide("erpnext");
cur_frm.email_field = "email_id";
-erpnext.LeadController = frappe.ui.form.Controller.extend({
- setup: function () {
+erpnext.LeadController = class LeadController extends frappe.ui.form.Controller {
+ setup () {
this.frm.make_methods = {
'Customer': this.make_customer,
'Quotation': this.make_quotation,
@@ -13,9 +13,9 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
};
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
- },
+ }
- onload: function () {
+ onload () {
this.frm.set_query("customer", function (doc, cdt, cdn) {
return { query: "erpnext.controllers.queries.customer_query" }
});
@@ -27,9 +27,9 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
this.frm.set_query("contact_by", function (doc, cdt, cdn) {
return { query: "frappe.core.doctype.user.user.user_query" }
});
- },
+ }
- refresh: function () {
+ refresh () {
let doc = this.frm.doc;
erpnext.toggle_naming_series();
frappe.dynamic_link = { doc: doc, fieldname: 'name', doctype: 'Lead' }
@@ -45,47 +45,47 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
} else {
frappe.contacts.clear_address_and_contact(this.frm);
}
- },
+ }
- make_customer: function () {
+ make_customer () {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.lead.lead.make_customer",
frm: cur_frm
})
- },
+ }
- make_opportunity: function () {
+ make_opportunity () {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.lead.lead.make_opportunity",
frm: cur_frm
})
- },
+ }
- make_quotation: function () {
+ make_quotation () {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.lead.lead.make_quotation",
frm: cur_frm
})
- },
+ }
- organization_lead: function () {
+ organization_lead () {
this.frm.toggle_reqd("lead_name", !this.frm.doc.organization_lead);
this.frm.toggle_reqd("company_name", this.frm.doc.organization_lead);
- },
+ }
- company_name: function () {
+ company_name () {
if (this.frm.doc.organization_lead && !this.frm.doc.lead_name) {
this.frm.set_value("lead_name", this.frm.doc.company_name);
}
- },
+ }
- contact_date: function () {
+ contact_date () {
if (this.frm.doc.contact_date) {
let d = moment(this.frm.doc.contact_date);
d.add(1, "day");
this.frm.set_value("ends_on", d.format(frappe.defaultDatetimeFormat));
}
}
-});
+};
$.extend(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm }));
diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js
index ac374a95f4..925c30b451 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.js
+++ b/erpnext/crm/doctype/opportunity/opportunity.js
@@ -145,8 +145,8 @@ frappe.ui.form.on("Opportunity", {
})
// TODO commonify this code
-erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
- onload: function() {
+erpnext.crm.Opportunity = class Opportunity extends frappe.ui.form.Controller {
+ onload() {
if(!this.frm.doc.status) {
frm.set_value('status', 'Open');
@@ -159,9 +159,9 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
}
this.setup_queries();
- },
+ }
- setup_queries: function() {
+ setup_queries() {
var me = this;
if(this.frm.fields_dict.contact_by.df.options.match(/^User/)) {
@@ -185,15 +185,15 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
else if (me.frm.doc.opportunity_from == "Customer") {
me.frm.set_query('party_name', erpnext.queries['customer']);
}
- },
+ }
- create_quotation: function() {
+ create_quotation() {
frappe.model.open_mapped_doc({
method: "erpnext.crm.doctype.opportunity.opportunity.make_quotation",
frm: cur_frm
})
}
-});
+};
$.extend(cur_frm.cscript, new erpnext.crm.Opportunity({frm: cur_frm}));
diff --git a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
index b59d848828..68e7780039 100644
--- a/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
+++ b/erpnext/education/doctype/student_attendance_tool/student_attendance_tool.js
@@ -72,8 +72,8 @@ frappe.ui.form.on('Student Attendance Tool', {
});
-education.StudentsEditor = Class.extend({
- init: function(frm, wrapper, students) {
+education.StudentsEditor = class StudentsEditor {
+ constructor(frm, wrapper, students) {
this.wrapper = wrapper;
this.frm = frm;
if(students.length > 0) {
@@ -81,8 +81,8 @@ education.StudentsEditor = Class.extend({
} else {
this.show_empty_state();
}
- },
- make: function(frm, students) {
+ }
+ make(frm, students) {
var me = this;
$(this.wrapper).empty();
@@ -173,13 +173,13 @@ education.StudentsEditor = Class.extend({
});
$(htmls.join("")).appendTo(me.wrapper);
- },
+ }
- show_empty_state: function() {
+ show_empty_state() {
$(this.wrapper).html(
`
${__("No Students in")} ${this.frm.doc.student_group}
`
);
}
-});
+};
diff --git a/erpnext/healthcare/doctype/exercise_type/exercise_type.js b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
index b49b00e219..06146047eb 100644
--- a/erpnext/healthcare/doctype/exercise_type/exercise_type.js
+++ b/erpnext/healthcare/doctype/exercise_type/exercise_type.js
@@ -9,14 +9,14 @@ frappe.ui.form.on('Exercise Type', {
}
});
-erpnext.ExerciseEditor = Class.extend({
- init: function(frm, wrapper) {
+erpnext.ExerciseEditor = class ExerciseEditor {
+ constructor(frm, wrapper) {
this.wrapper = wrapper;
this.frm = frm;
this.make(frm, wrapper);
- },
+ }
- make: function(frm, wrapper) {
+ make(frm, wrapper) {
$(this.wrapper).empty();
this.exercise_toolbar = $('\
@@ -38,9 +38,9 @@ erpnext.ExerciseEditor = Class.extend({
this.make_cards(frm);
this.make_buttons(frm);
}
- },
+ }
- make_cards: function(frm) {
+ make_cards(frm) {
var me = this;
$(me.exercise_cards).empty();
@@ -60,9 +60,9 @@ erpnext.ExerciseEditor = Class.extend({
`, {image_src: step.image, title: step.title, description: step.description, col_id: "col-"+i, card_id: "card-"+i, id: i})).appendTo(me.row);
});
- },
+ }
- make_buttons: function(frm) {
+ make_buttons(frm) {
let me = this;
$('.btn-edit').on('click', function() {
let id = $(this).attr('data-id');
@@ -82,9 +82,9 @@ erpnext.ExerciseEditor = Class.extend({
frm.dirty();
}, 300);
});
- },
+ }
- show_add_card_dialog: function(frm) {
+ show_add_card_dialog(frm) {
let me = this;
let d = new frappe.ui.Dialog({
title: __('Add Exercise Step'),
@@ -137,9 +137,9 @@ erpnext.ExerciseEditor = Class.extend({
primary_action_label: __('Add')
});
d.show();
- },
+ }
- show_edit_card_dialog: function(frm, id) {
+ show_edit_card_dialog(frm, id) {
let new_dialog = new frappe.ui.Dialog({
title: __("Edit Exercise Step"),
fields: [
@@ -183,4 +183,4 @@ erpnext.ExerciseEditor = Class.extend({
});
new_dialog.show();
}
-});
+};
diff --git a/erpnext/hr/doctype/employee/employee.js b/erpnext/hr/doctype/employee/employee.js
index c21d4b893c..5639cc9ea4 100755
--- a/erpnext/hr/doctype/employee/employee.js
+++ b/erpnext/hr/doctype/employee/employee.js
@@ -2,8 +2,8 @@
// License: GNU General Public License v3. See license.txt
frappe.provide("erpnext.hr");
-erpnext.hr.EmployeeController = frappe.ui.form.Controller.extend({
- setup: function() {
+erpnext.hr.EmployeeController = class EmployeeController extends frappe.ui.form.Controller {
+ setup() {
this.frm.fields_dict.user_id.get_query = function(doc, cdt, cdn) {
return {
query: "frappe.core.doctype.user.user.user_query",
@@ -12,30 +12,30 @@ erpnext.hr.EmployeeController = frappe.ui.form.Controller.extend({
}
this.frm.fields_dict.reports_to.get_query = function(doc, cdt, cdn) {
return { query: "erpnext.controllers.queries.employee_query"} }
- },
+ }
- refresh: function() {
+ refresh() {
var me = this;
erpnext.toggle_naming_series();
- },
+ }
- date_of_birth: function() {
+ date_of_birth() {
return cur_frm.call({
method: "get_retirement_date",
args: {date_of_birth: this.frm.doc.date_of_birth}
});
- },
+ }
- salutation: function() {
+ salutation() {
if(this.frm.doc.salutation) {
this.frm.set_value("gender", {
"Mr": "Male",
"Ms": "Female"
}[this.frm.doc.salutation]);
}
- },
+ }
-});
+};
frappe.ui.form.on('Employee',{
setup: function(frm) {
frm.set_query("leave_policy", function() {
diff --git a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
index 3205a92b1b..ab965d54e3 100644
--- a/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
+++ b/erpnext/hr/doctype/employee_attendance_tool/employee_attendance_tool.js
@@ -68,13 +68,13 @@ erpnext.employee_attendance_tool = {
}
}
-erpnext.MarkedEmployee = Class.extend({
- init: function(frm, wrapper, employee) {
+erpnext.MarkedEmployee = class MarkedEmployee {
+ constructor(frm, wrapper, employee) {
this.wrapper = wrapper;
this.frm = frm;
this.make(frm, employee);
- },
- make: function(frm, employee) {
+ }
+ make(frm, employee) {
var me = this;
$(this.wrapper).empty();
@@ -104,16 +104,16 @@ erpnext.MarkedEmployee = Class.extend({
})).appendTo(row);
});
}
-});
+};
-erpnext.EmployeeSelector = Class.extend({
- init: function(frm, wrapper, employee) {
+erpnext.EmployeeSelector = class EmployeeSelector {
+ constructor(frm, wrapper, employee) {
this.wrapper = wrapper;
this.frm = frm;
this.make(frm, employee);
- },
- make: function(frm, employee) {
+ }
+ make(frm, employee) {
var me = this;
$(this.wrapper).empty();
@@ -266,6 +266,6 @@ erpnext.EmployeeSelector = Class.extend({
mark_employee_toolbar.appendTo($(this.wrapper));
}
-});
+};
diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.js b/erpnext/hr/doctype/upload_attendance/upload_attendance.js
index 29aa85484a..bbafc82076 100644
--- a/erpnext/hr/doctype/upload_attendance/upload_attendance.js
+++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.js
@@ -5,19 +5,19 @@
frappe.provide("erpnext.hr");
-erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
- onload: function() {
+erpnext.hr.AttendanceControlPanel = class AttendanceControlPanel extends frappe.ui.form.Controller {
+ onload() {
this.frm.set_value("att_fr_date", frappe.datetime.get_today());
this.frm.set_value("att_to_date", frappe.datetime.get_today());
- },
+ }
- refresh: function() {
+ refresh() {
this.frm.disable_save();
this.show_upload();
this.setup_import_progress();
- },
+ }
- get_template:function() {
+ get_template() {
if(!this.frm.doc.att_fr_date || !this.frm.doc.att_to_date) {
frappe.msgprint(__("Attendance From Date and Attendance To Date is mandatory"));
return;
@@ -28,7 +28,7 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
from_date: this.frm.doc.att_fr_date,
to_date: this.frm.doc.att_to_date,
});
- },
+ }
show_upload() {
var $wrapper = $(cur_frm.fields_dict.upload_html.wrapper).empty();
@@ -36,7 +36,7 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
wrapper: $wrapper,
method: 'erpnext.hr.doctype.upload_attendance.upload_attendance.upload'
});
- },
+ }
setup_import_progress() {
var $log_wrapper = $(this.frm.fields_dict.import_log.wrapper).empty();
@@ -64,6 +64,6 @@ erpnext.hr.AttendanceControlPanel = frappe.ui.form.Controller.extend({
}
});
}
-})
+}
cur_frm.cscript = new erpnext.hr.AttendanceControlPanel({frm: cur_frm});
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
index ddbcdfde57..2adfaf45ef 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
@@ -45,8 +45,8 @@ frappe.ui.form.on('Maintenance Schedule', {
})
// TODO commonify this code
-erpnext.maintenance.MaintenanceSchedule = frappe.ui.form.Controller.extend({
- refresh: function() {
+erpnext.maintenance.MaintenanceSchedule = class MaintenanceSchedule extends frappe.ui.form.Controller {
+ refresh() {
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
var me = this;
@@ -76,21 +76,21 @@ erpnext.maintenance.MaintenanceSchedule = frappe.ui.form.Controller.extend({
});
}, __('Create'));
}
- },
+ }
- start_date: function(doc, cdt, cdn) {
+ start_date(doc, cdt, cdn) {
this.set_no_of_visits(doc, cdt, cdn);
- },
+ }
- end_date: function(doc, cdt, cdn) {
+ end_date(doc, cdt, cdn) {
this.set_no_of_visits(doc, cdt, cdn);
- },
+ }
- periodicity: function(doc, cdt, cdn) {
+ periodicity(doc, cdt, cdn) {
this.set_no_of_visits(doc, cdt, cdn);
- },
+ }
- set_no_of_visits: function(doc, cdt, cdn) {
+ set_no_of_visits(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if (item.start_date && item.end_date && item.periodicity) {
@@ -112,8 +112,8 @@ erpnext.maintenance.MaintenanceSchedule = frappe.ui.form.Controller.extend({
var no_of_visits = cint(date_diff / days_in_period[item.periodicity]);
frappe.model.set_value(item.doctype, item.name, "no_of_visits", no_of_visits);
}
- },
-});
+ }
+};
$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceSchedule({frm: cur_frm}));
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
index 4cbb02a5b3..12dc59ccfc 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
@@ -41,8 +41,8 @@ frappe.ui.form.on('Maintenance Visit', {
})
// TODO commonify this code
-erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({
- refresh: function() {
+erpnext.maintenance.MaintenanceVisit = class MaintenanceVisit extends frappe.ui.form.Controller {
+ refresh() {
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
var me = this;
@@ -96,7 +96,7 @@ erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({
})
}, __("Get Items From"));
}
- },
-});
+ }
+};
-$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceVisit({frm: cur_frm}));
\ No newline at end of file
+$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceVisit({frm: cur_frm}));
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index fbfd801a11..2b329448fb 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -357,16 +357,16 @@ frappe.ui.form.on("BOM", {
}
});
-erpnext.bom.BomController = erpnext.TransactionController.extend({
- conversion_rate: function(doc) {
+erpnext.bom.BomController = class BomController extends erpnext.TransactionController {
+ conversion_rate(doc) {
if(this.frm.doc.currency === this.get_company_currency()) {
this.frm.set_value("conversion_rate", 1.0);
} else {
erpnext.bom.update_cost(doc);
}
- },
+ }
- item_code: function(doc, cdt, cdn){
+ item_code(doc, cdt, cdn){
var scrap_items = false;
var child = locals[cdt][cdn];
if (child.doctype == 'BOM Scrap Item') {
@@ -378,19 +378,19 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({
}
get_bom_material_detail(doc, cdt, cdn, scrap_items);
- },
+ }
- buying_price_list: function(doc) {
+ buying_price_list(doc) {
this.apply_price_list();
- },
+ }
- plc_conversion_rate: function(doc) {
+ plc_conversion_rate(doc) {
if (!this.in_apply_price_list) {
this.apply_price_list(null, true);
}
- },
+ }
- conversion_factor: function(doc, cdt, cdn) {
+ conversion_factor(doc, cdt, cdn) {
if (frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
@@ -399,8 +399,8 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({
this.toggle_conversion_factor(item);
this.frm.events.update_cost(this.frm);
}
- },
-});
+ }
+};
$.extend(cur_frm.cscript, new erpnext.bom.BomController({frm: cur_frm}));
diff --git a/erpnext/public/js/account_tree_grid.js b/erpnext/public/js/account_tree_grid.js
index 757f33eecc..413a5ee971 100644
--- a/erpnext/public/js/account_tree_grid.js
+++ b/erpnext/public/js/account_tree_grid.js
@@ -14,9 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
- init: function(wrapper, title) {
- this._super({
+erpnext.AccountTreeGrid = class AccountTreeGrid extends frappe.views.TreeGridReport {
+ constructor(wrapper, title) {
+ super({
title: title,
parent: $(wrapper).find('.layout-main'),
page: wrapper.page,
@@ -33,8 +33,24 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
}
},
});
- },
- setup_columns: function() {
+
+ this.filters = [
+ {fieldtype: "Select", label: __("Company"), link:"Company", fieldname: "company",
+ default_value: __("Select Company..."),
+ filter: function(val, item, opts, me) {
+ if (item.company == val || val == opts.default_value) {
+ return me.apply_zero_filter(val, item, opts, me);
+ }
+ return false;
+ }},
+ {fieldtype: "Select", label: "Fiscal Year", link:"Fiscal Year", fieldname: "fiscal_year",
+ default_value: __("Select Fiscal Year...")},
+ {fieldtype: "Date", label: __("From Date"), fieldname: "from_date"},
+ {fieldtype: "Label", label: __("To")},
+ {fieldtype: "Date", label: __("To Date"), fieldname: "to_date"}
+ ]
+ }
+ setup_columns() {
this.columns = [
{id: "name", name: __("Account"), field: "name", width: 300, cssClass: "cell-title"},
{id: "opening_dr", name: __("Opening (Dr)"), field: "opening_dr", width: 100,
@@ -50,25 +66,10 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
{id: "closing_cr", name: __("Closing (Cr)"), field: "closing_cr", width: 100,
formatter: this.currency_formatter}
];
+ }
- },
- filters: [
- {fieldtype: "Select", label: __("Company"), link:"Company", fieldname: "company",
- default_value: __("Select Company..."),
- filter: function(val, item, opts, me) {
- if (item.company == val || val == opts.default_value) {
- return me.apply_zero_filter(val, item, opts, me);
- }
- return false;
- }},
- {fieldtype: "Select", label: "Fiscal Year", link:"Fiscal Year", fieldname: "fiscal_year",
- default_value: __("Select Fiscal Year...")},
- {fieldtype: "Date", label: __("From Date"), fieldname: "from_date"},
- {fieldtype: "Label", label: __("To")},
- {fieldtype: "Date", label: __("To Date"), fieldname: "to_date"}
- ],
- setup_filters: function() {
- this._super();
+ setup_filters() {
+ super.setup_filters();
var me = this;
// default filters
this.filter_inputs.fiscal_year.change(function() {
@@ -83,8 +84,8 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
});
me.show_zero_check()
if(me.ignore_closing_entry) me.ignore_closing_entry();
- },
- prepare_data: function() {
+ }
+ prepare_data() {
var me = this;
if(!this.primary_data) {
// make accounts list
@@ -113,12 +114,12 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
this.set_indent();
this.prepare_balances();
- },
- init_account: function(d) {
+ }
+ init_account(d) {
this.reset_item_values(d);
- },
+ }
- prepare_balances: function() {
+ prepare_balances() {
var gl = frappe.report_dump.data['GL Entry'];
var me = this;
@@ -139,8 +140,8 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
});
this.update_groups();
- },
- update_balances: function(account, posting_date, v) {
+ }
+ update_balances(account, posting_date, v) {
// opening
if (posting_date < this.opening_date || v.is_opening === "Yes") {
if (account.report_type === "Profit and Loss" &&
@@ -161,8 +162,8 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
var closing_bal = flt(account.opening_dr) - flt(account.opening_cr) +
flt(account.debit) - flt(account.credit);
this.set_debit_or_credit(account, "closing", closing_bal);
- },
- set_debit_or_credit: function(account, field, balance) {
+ }
+ set_debit_or_credit(account, field, balance) {
if(balance > 0) {
account[field+"_dr"] = balance;
account[field+"_cr"] = 0;
@@ -170,8 +171,8 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
account[field+"_cr"] = Math.abs(balance);
account[field+"_dr"] = 0;
}
- },
- update_groups: function() {
+ }
+ update_groups() {
// update groups
var me= this;
$.each(this.data, function(i, account) {
@@ -202,9 +203,9 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
}
}
});
- },
+ }
- set_fiscal_year: function() {
+ set_fiscal_year() {
if (this.opening_date > this.closing_date) {
frappe.msgprint(__("Opening Date should be before Closing Date"));
return;
@@ -223,9 +224,9 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
frappe.msgprint(__("Opening Date and Closing Date should be within same Fiscal Year"));
return;
}
- },
+ }
- show_general_ledger: function(account) {
+ show_general_ledger(account) {
frappe.route_options = {
account: account,
company: this.company,
@@ -234,4 +235,4 @@ erpnext.AccountTreeGrid = frappe.views.TreeGridReport.extend({
};
frappe.set_route("query-report", "General Ledger");
}
-});
+};
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index 67b12fbca4..8ceae83620 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -9,14 +9,14 @@ cur_frm.cscript.tax_table = "Purchase Taxes and Charges";
cur_frm.email_field = "contact_email";
-erpnext.buying.BuyingController = erpnext.TransactionController.extend({
- setup: function() {
- this._super();
- },
+erpnext.buying.BuyingController = class BuyingController extends erpnext.TransactionController {
+ setup() {
+ super.setup();
+ }
- onload: function(doc, cdt, cdn) {
+ onload(doc, cdt, cdn) {
this.setup_queries(doc, cdt, cdn);
- this._super();
+ super.onload();
this.frm.set_query('shipping_rule', function() {
return {
@@ -48,9 +48,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
});
}
/* eslint-enable */
- },
+ }
- setup_queries: function(doc, cdt, cdn) {
+ setup_queries(doc, cdt, cdn) {
var me = this;
if(this.frm.fields_dict.buying_price_list) {
@@ -109,9 +109,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
return me.set_query_for_item_tax_template(doc, cdt, cdn)
});
}
- },
+ }
- refresh: function(doc) {
+ refresh(doc) {
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'supplier', doctype: 'Supplier'};
this.frm.toggle_display("supplier_name",
@@ -122,38 +122,38 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
this.set_from_product_bundle();
}
- this._super();
- },
+ super.refresh();
+ }
- supplier: function() {
+ supplier() {
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function(){
me.apply_price_list();
});
- },
+ }
- supplier_address: function() {
+ supplier_address() {
erpnext.utils.get_address_display(this.frm);
erpnext.utils.set_taxes_from_address(this.frm, "supplier_address", "supplier_address", "supplier_address");
- },
+ }
- buying_price_list: function() {
+ buying_price_list() {
this.apply_price_list();
- },
+ }
- discount_percentage: function(doc, cdt, cdn) {
+ discount_percentage(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
item.discount_amount = 0.0;
this.price_list_rate(doc, cdt, cdn);
- },
+ }
- discount_amount: function(doc, cdt, cdn) {
+ discount_amount(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
item.discount_percentage = 0.0;
this.price_list_rate(doc, cdt, cdn);
- },
+ }
- qty: function(doc, cdt, cdn) {
+ qty(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if ((doc.doctype == "Purchase Receipt") || (doc.doctype == "Purchase Invoice" && (doc.update_stock || doc.is_return))) {
frappe.model.round_floats_in(item, ["qty", "received_qty"]);
@@ -168,22 +168,22 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
item.rejected_qty = flt(item.received_qty - item.qty, precision("rejected_qty", item));
item.received_stock_qty = flt(item.conversion_factor, precision("conversion_factor", item)) * flt(item.received_qty);
}
- this._super(doc, cdt, cdn);
- },
+ super.qty(doc, cdt, cdn);
+ }
- batch_no: function(doc, cdt, cdn) {
- this._super(doc, cdt, cdn);
- },
+ batch_no(doc, cdt, cdn) {
+ super.batch_no(doc, cdt, cdn);
+ }
- received_qty: function(doc, cdt, cdn) {
+ received_qty(doc, cdt, cdn) {
this.calculate_accepted_qty(doc, cdt, cdn)
- },
+ }
- rejected_qty: function(doc, cdt, cdn) {
+ rejected_qty(doc, cdt, cdn) {
this.calculate_accepted_qty(doc, cdt, cdn)
- },
+ }
- calculate_accepted_qty: function(doc, cdt, cdn){
+ calculate_accepted_qty(doc, cdt, cdn){
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["received_qty", "rejected_qty"]);
@@ -191,9 +191,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
item.qty = flt(item.received_qty - item.rejected_qty, precision("qty", item));
this.qty(doc, cdt, cdn);
- },
+ }
- validate_negative_quantity: function(cdt, cdn, item, fieldnames){
+ validate_negative_quantity(cdt, cdn, item, fieldnames){
if(!item || !fieldnames) { return }
var is_negative_qty = false;
@@ -206,9 +206,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
return is_negative_qty
- },
+ }
- warehouse: function(doc, cdt, cdn) {
+ warehouse(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if(item.item_code && item.warehouse) {
return this.frm.call({
@@ -220,9 +220,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
});
}
- },
+ }
- project: function(doc, cdt, cdn) {
+ project(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if(item.project) {
$.each(this.frm.doc["items"] || [],
@@ -233,48 +233,48 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
});
}
- },
+ }
- rejected_warehouse: function(doc, cdt) {
+ rejected_warehouse(doc, cdt) {
// trigger autofill_warehouse only if parent rejected_warehouse field is triggered
if (["Purchase Invoice", "Purchase Receipt"].includes(cdt)) {
this.autofill_warehouse(doc.items, "rejected_warehouse", doc.rejected_warehouse);
}
- },
+ }
- category: function(doc, cdt, cdn) {
+ category(doc, cdt, cdn) {
// should be the category field of tax table
if(cdt != doc.doctype) {
this.calculate_taxes_and_totals();
}
- },
- add_deduct_tax: function(doc, cdt, cdn) {
+ }
+ add_deduct_tax(doc, cdt, cdn) {
this.calculate_taxes_and_totals();
- },
+ }
- set_from_product_bundle: function() {
+ set_from_product_bundle() {
var me = this;
this.frm.add_custom_button(__("Product Bundle"), function() {
erpnext.buying.get_items_from_product_bundle(me.frm);
}, __("Get Items From"));
- },
+ }
- shipping_address: function(){
+ shipping_address(){
var me = this;
erpnext.utils.get_address_display(this.frm, "shipping_address",
"shipping_address_display", true);
- },
+ }
- billing_address: function() {
+ billing_address() {
erpnext.utils.get_address_display(this.frm, "billing_address",
"billing_address_display", true);
- },
+ }
- tc_name: function() {
+ tc_name() {
this.get_terms();
- },
+ }
- update_auto_repeat_reference: function(doc) {
+ update_auto_repeat_reference(doc) {
if (doc.auto_repeat) {
frappe.call({
method:"frappe.automation.doctype.auto_repeat.auto_repeat.update_reference",
@@ -291,9 +291,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
})
}
- },
+ }
- manufacturer: function(doc, cdt, cdn) {
+ manufacturer(doc, cdt, cdn) {
const row = locals[cdt][cdn];
if(row.manufacturer) {
@@ -310,9 +310,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
});
}
- },
+ }
- manufacturer_part_no: function(doc, cdt, cdn) {
+ manufacturer_part_no(doc, cdt, cdn) {
const row = locals[cdt][cdn];
if (row.manufacturer_part_no) {
@@ -335,7 +335,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
}
-});
+};
cur_frm.add_fetch('project', 'cost_center', 'cost_center');
@@ -496,4 +496,4 @@ erpnext.buying.get_items_from_product_bundle = function(frm) {
});
dialog.show();
-}
\ No newline at end of file
+}
diff --git a/erpnext/public/js/controllers/stock_controller.js b/erpnext/public/js/controllers/stock_controller.js
index 87b21b78de..d346357a8f 100644
--- a/erpnext/public/js/controllers/stock_controller.js
+++ b/erpnext/public/js/controllers/stock_controller.js
@@ -3,22 +3,22 @@
frappe.provide("erpnext.stock");
-erpnext.stock.StockController = frappe.ui.form.Controller.extend({
- onload: function() {
+erpnext.stock.StockController = class StockController extends frappe.ui.form.Controller {
+ onload() {
// warehouse query if company
if (this.frm.fields_dict.company) {
this.setup_warehouse_query();
}
- },
+ }
- setup_warehouse_query: function() {
+ setup_warehouse_query() {
var me = this;
erpnext.queries.setup_queries(this.frm, "Warehouse", function() {
return erpnext.queries.warehouse(me.frm.doc);
});
- },
+ }
- setup_posting_date_time_check: function() {
+ setup_posting_date_time_check() {
// make posting date default and read only unless explictly checked
frappe.ui.form.on(this.frm.doctype, 'set_posting_date_and_time_read_only', function(frm) {
if(frm.doc.docstatus == 0 && frm.doc.set_posting_time) {
@@ -46,9 +46,9 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
frm.trigger('set_posting_date_and_time_read_only');
}
});
- },
+ }
- show_stock_ledger: function() {
+ show_stock_ledger() {
var me = this;
if(this.frm.doc.docstatus > 0) {
cur_frm.add_custom_button(__("Stock Ledger"), function() {
@@ -63,9 +63,9 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
}, __("View"));
}
- },
+ }
- show_general_ledger: function() {
+ show_general_ledger() {
var me = this;
if(this.frm.doc.docstatus > 0) {
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
@@ -81,4 +81,4 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
}, __("View"));
}
}
-});
+};
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 3a3ee3858b..448bb65364 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -1,12 +1,12 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-erpnext.taxes_and_totals = erpnext.payments.extend({
- setup: function() {
+erpnext.taxes_and_totals = class taxes_and_totals extends erpnext.payments {
+ setup() {
this.fetch_round_off_accounts();
- },
+ }
- apply_pricing_rule_on_item: function(item) {
+ 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) {
@@ -32,9 +32,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
frappe.model.set_value(item.doctype, item.name, "rate", item_rate);
- },
+ }
- calculate_taxes_and_totals: function(update_paid_amount) {
+ calculate_taxes_and_totals(update_paid_amount) {
this.discount_amount_applied = false;
this._calculate_taxes_and_totals();
this.calculate_discount_amount();
@@ -63,16 +63,16 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
this.frm.refresh_fields();
- },
+ }
- calculate_discount_amount: function(){
+ calculate_discount_amount(){
if (frappe.meta.get_docfield(this.frm.doc.doctype, "discount_amount")) {
this.set_discount_amount();
this.apply_discount_amount();
}
- },
+ }
- _calculate_taxes_and_totals: function() {
+ _calculate_taxes_and_totals() {
this.validate_conversion_rate();
this.calculate_item_values();
this.initialize_taxes();
@@ -82,9 +82,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.manipulate_grand_total_for_inclusive_tax();
this.calculate_totals();
this._cleanup();
- },
+ }
- validate_conversion_rate: function() {
+ validate_conversion_rate() {
this.frm.doc.conversion_rate = flt(this.frm.doc.conversion_rate, (cur_frm) ? precision("conversion_rate") : 9);
var conversion_rate_label = frappe.meta.get_label(this.frm.doc.doctype, "conversion_rate",
this.frm.doc.name);
@@ -99,9 +99,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
frappe.throw(err_message);
}
}
- },
+ }
- calculate_item_values: function() {
+ calculate_item_values() {
var me = this;
if (!this.discount_amount_applied) {
$.each(this.frm.doc["items"] || [], function(i, item) {
@@ -121,16 +121,16 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
me.set_in_company_currency(item, ["price_list_rate", "rate", "amount", "net_rate", "net_amount"]);
});
}
- },
+ }
- set_in_company_currency: function(doc, fields) {
+ set_in_company_currency(doc, fields) {
var me = this;
$.each(fields, function(i, f) {
doc["base_"+f] = flt(flt(doc[f], precision(f, doc)) * me.frm.doc.conversion_rate, precision("base_" + f, doc));
});
- },
+ }
- initialize_taxes: function() {
+ initialize_taxes() {
var me = this;
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
@@ -152,9 +152,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
frappe.model.round_floats_in(tax);
});
- },
+ }
- fetch_round_off_accounts: function() {
+ fetch_round_off_accounts() {
let me = this;
frappe.flags.round_off_applicable_accounts = [];
@@ -170,9 +170,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
});
}
- },
+ }
- determine_exclusive_rate: function() {
+ determine_exclusive_rate() {
var me = this;
var has_inclusive_tax = false;
@@ -210,9 +210,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
me.set_in_company_currency(item, ["net_rate", "net_amount"]);
}
});
- },
+ }
- get_current_tax_fraction: function(tax, item_tax_map) {
+ get_current_tax_fraction(tax, item_tax_map) {
// Get tax fraction for calculating tax exclusive amount
// from tax inclusive amount
var current_tax_fraction = 0.0;
@@ -241,14 +241,14 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
inclusive_tax_amount_per_qty *= -1;
}
return [current_tax_fraction, inclusive_tax_amount_per_qty];
- },
+ }
- _get_tax_rate: function(tax, item_tax_map) {
+ _get_tax_rate(tax, item_tax_map) {
return (Object.keys(item_tax_map).indexOf(tax.account_head) != -1) ?
flt(item_tax_map[tax.account_head], precision("rate", tax)) : tax.rate;
- },
+ }
- calculate_net_total: function() {
+ calculate_net_total() {
var me = this;
this.frm.doc.total_qty = this.frm.doc.total = this.frm.doc.base_total = this.frm.doc.net_total = this.frm.doc.base_net_total = 0.0;
@@ -261,9 +261,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
});
frappe.model.round_floats_in(this.frm.doc, ["total", "base_total", "net_total", "base_net_total"]);
- },
+ }
- calculate_taxes: function() {
+ calculate_taxes() {
var me = this;
this.frm.doc.rounding_adjustment = 0;
var actual_tax_dict = {};
@@ -339,9 +339,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
});
});
- },
+ }
- set_cumulative_total: function(row_idx, tax) {
+ set_cumulative_total(row_idx, tax) {
var tax_amount = tax.tax_amount_after_discount_amount;
if (tax.category == 'Valuation') {
tax_amount = 0;
@@ -354,13 +354,13 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
} else {
tax.total = flt(this.frm.doc["taxes"][row_idx-1].total + tax_amount, precision("total", tax));
}
- },
+ }
- _load_item_tax_rate: function(item_tax_rate) {
+ _load_item_tax_rate(item_tax_rate) {
return item_tax_rate ? JSON.parse(item_tax_rate) : {};
- },
+ }
- get_current_tax_amount: function(item, tax, item_tax_map) {
+ get_current_tax_amount(item, tax, item_tax_map) {
var tax_rate = this._get_tax_rate(tax, item_tax_map);
var current_tax_amount = 0.0;
@@ -397,17 +397,17 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount);
return current_tax_amount;
- },
+ }
- get_final_tax_amount: function(tax, current_tax_amount) {
+ get_final_tax_amount(tax, current_tax_amount) {
if (frappe.flags.round_off_applicable_accounts.includes(tax.account_head)) {
current_tax_amount = Math.round(current_tax_amount);
}
return current_tax_amount;
- },
+ }
- set_item_wise_tax: function(item, tax, tax_rate, current_tax_amount) {
+ set_item_wise_tax(item, tax, tax_rate, current_tax_amount) {
// store tax breakup for each item
let tax_detail = tax.item_wise_tax_detail;
let key = item.item_code || item.item_name;
@@ -417,14 +417,14 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
item_wise_tax_amount += tax_detail[key][1];
tax_detail[key] = [tax_rate, flt(item_wise_tax_amount, precision("base_tax_amount", tax))];
- },
+ }
- round_off_totals: function(tax) {
+ round_off_totals(tax) {
tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount, precision("tax_amount", tax));
- },
+ }
- manipulate_grand_total_for_inclusive_tax: function() {
+ manipulate_grand_total_for_inclusive_tax() {
var me = this;
// if fully inclusive taxes and diff
if (this.frm.doc["taxes"] && this.frm.doc["taxes"].length) {
@@ -455,9 +455,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
}
}
- },
+ }
- calculate_totals: function() {
+ calculate_totals() {
// Changing sequence can cause rounding_adjustmentng issue and on-screen discrepency
var me = this;
var tax_count = this.frm.doc["taxes"] ? this.frm.doc["taxes"].length : 0;
@@ -503,9 +503,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
// rounded totals
this.set_rounded_total();
- },
+ }
- set_rounded_total: function() {
+ set_rounded_total() {
var disable_rounded_total = 0;
if(frappe.meta.get_docfield(this.frm.doc.doctype, "disable_rounded_total", this.frm.doc.name)) {
disable_rounded_total = this.frm.doc.disable_rounded_total;
@@ -527,9 +527,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.set_in_company_currency(this.frm.doc, ["rounding_adjustment", "rounded_total"]);
}
- },
+ }
- _cleanup: function() {
+ _cleanup() {
this.frm.doc.base_in_words = this.frm.doc.in_words = "";
if(this.frm.doc["items"] && this.frm.doc["items"].length) {
@@ -556,16 +556,16 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
tax.item_wise_tax_detail = JSON.stringify(tax.item_wise_tax_detail);
});
}
- },
+ }
- set_discount_amount: function() {
+ set_discount_amount() {
if(this.frm.doc.additional_discount_percentage) {
this.frm.doc.discount_amount = flt(flt(this.frm.doc[frappe.scrub(this.frm.doc.apply_discount_on)])
* this.frm.doc.additional_discount_percentage / 100, precision("discount_amount"));
}
- },
+ }
- apply_discount_amount: function() {
+ apply_discount_amount() {
var me = this;
var distributed_amount = 0.0;
this.frm.doc.base_discount_amount = 0.0;
@@ -603,9 +603,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this._calculate_taxes_and_totals();
}
}
- },
+ }
- get_total_for_discount_amount: function() {
+ get_total_for_discount_amount() {
if(this.frm.doc.apply_discount_on == "Net Total") {
return this.frm.doc.net_total;
} else {
@@ -629,27 +629,27 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
return flt(this.frm.doc.grand_total - total_actual_tax, precision("grand_total"));
}
- },
+ }
- calculate_total_advance: function(update_paid_amount) {
+ calculate_total_advance(update_paid_amount) {
var total_allocated_amount = frappe.utils.sum($.map(this.frm.doc["advances"] || [], function(adv) {
return flt(adv.allocated_amount, precision("allocated_amount", adv));
}));
this.frm.doc.total_advance = flt(total_allocated_amount, precision("total_advance"));
this.calculate_outstanding_amount(update_paid_amount);
- },
+ }
- is_internal_invoice: function() {
+ is_internal_invoice() {
if (['Sales Invoice', 'Purchase Invoice'].includes(this.frm.doc.doctype)) {
if (this.frm.doc.company === this.frm.doc.represents_company) {
return true;
}
}
return false;
- },
+ }
- calculate_outstanding_amount: function(update_paid_amount) {
+ calculate_outstanding_amount(update_paid_amount) {
// NOTE:
// paid_amount and write_off_amount is only for POS/Loyalty Point Redemption Invoice
// total_advance is only for non POS Invoice
@@ -697,9 +697,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.frm.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) +
flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate), precision("outstanding_amount"));
}
- },
+ }
- update_paid_amount_for_return: function() {
+ update_paid_amount_for_return() {
var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total;
if(this.frm.doc.party_account_currency == this.frm.doc.currency) {
@@ -723,9 +723,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.frm.refresh_fields();
this.calculate_paid_amount();
- },
+ }
- set_default_payment: function(total_amount_to_pay, update_paid_amount) {
+ set_default_payment(total_amount_to_pay, update_paid_amount) {
var me = this;
var payment_status = true;
if(this.frm.doc.is_pos && (update_paid_amount===undefined || update_paid_amount)) {
@@ -741,9 +741,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
});
}
- },
+ }
- calculate_paid_amount: function() {
+ calculate_paid_amount() {
var me = this;
var paid_amount = 0.0;
var base_paid_amount = 0.0;
@@ -763,9 +763,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.frm.set_value('paid_amount', flt(paid_amount, precision("paid_amount")));
this.frm.set_value('base_paid_amount', flt(base_paid_amount, precision("base_paid_amount")));
- },
+ }
- calculate_change_amount: function(){
+ 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)
@@ -784,9 +784,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
precision("base_change_amount"));
}
}
- },
+ }
- calculate_write_off_amount: function(){
+ calculate_write_off_amount(){
if(this.frm.doc.paid_amount > this.frm.doc.grand_total){
this.frm.doc.write_off_amount = flt(this.frm.doc.grand_total - this.frm.doc.paid_amount
+ this.frm.doc.change_amount, precision("write_off_amount"));
@@ -798,4 +798,4 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
}
this.calculate_outstanding_amount(false);
}
-});
+};
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 1c0abdffcf..a4c165e9ee 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -3,9 +3,9 @@
frappe.provide('erpnext.accounts.dimensions');
-erpnext.TransactionController = erpnext.taxes_and_totals.extend({
- setup: function() {
- this._super();
+erpnext.TransactionController = class TransactionController extends erpnext.taxes_and_totals {
+ setup() {
+ super.setup();
frappe.flags.hide_serial_batch_dialog = true;
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
@@ -222,8 +222,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
}
- },
- onload: function() {
+ }
+ onload() {
var me = this;
if(this.frm.doc.__islocal) {
@@ -249,15 +249,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
]);
}
- },
+ }
- is_return: function() {
+ is_return() {
if(!this.frm.doc.is_return && this.frm.doc.return_against) {
this.frm.set_value('return_against', '');
}
- },
+ }
- setup_quality_inspection: function() {
+ setup_quality_inspection() {
if(!in_list(["Delivery Note", "Sales Invoice", "Purchase Receipt", "Purchase Invoice"], this.frm.doc.doctype)) {
return;
}
@@ -290,9 +290,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
}
});
- },
+ }
- make_payment_request: function() {
+ make_payment_request() {
var me = this;
const payment_request_type = (in_list(['Sales Order', 'Sales Invoice'], this.frm.doc.doctype))
? "Inward" : "Outward";
@@ -314,9 +314,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
}
})
- },
+ }
- onload_post_render: function() {
+ onload_post_render() {
if(this.frm.doc.__islocal && !(this.frm.doc.taxes || []).length
&& !(this.frm.doc.__onload ? this.frm.doc.__onload.load_after_mapping : false)) {
frappe.after_ajax(() => this.apply_default_taxes());
@@ -328,9 +328,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
this.setup_item_selector();
this.frm.get_field("items").grid.set_multiple_add("item_code", "qty");
}
- },
+ }
- refresh: function() {
+ refresh() {
erpnext.toggle_naming_series();
erpnext.hide_company();
this.set_dynamic_labels();
@@ -360,9 +360,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
.appendTo($input_group);
}
}
- },
+ }
- scan_barcode: function() {
+ scan_barcode() {
let scan_barcode_field = this.frm.fields_dict["scan_barcode"];
let show_description = function(idx, exist = null) {
@@ -434,9 +434,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
}
return false;
- },
+ }
- apply_default_taxes: function() {
+ apply_default_taxes() {
var me = this;
var taxes_and_charges_field = frappe.meta.get_docfield(me.frm.doc.doctype, "taxes_and_charges",
me.frm.doc.name);
@@ -475,22 +475,22 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
}
- },
+ }
- setup_sms: function() {
+ 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)
&& !blacklist.includes(this.frm.doctype)) {
this.frm.page.add_menu_item(__('Send SMS'), function() { me.send_sms(); });
}
- },
+ }
- send_sms: function() {
+ send_sms() {
var sms_man = new erpnext.SMSManager(this.frm.doc);
- },
+ }
- barcode: function(doc, cdt, cdn) {
+ barcode(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if(d.barcode=="" || d.barcode==null) {
// barcode cleared, remove item
@@ -499,9 +499,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
this.frm.from_barcode = this.frm.from_barcode ? this.frm.from_barcode + 1 : 1;
this.item_code(doc, cdt, cdn);
- },
+ }
- item_code: function(doc, cdt, cdn) {
+ item_code(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
var update_stock = 0, show_batch_dialog = 0;
@@ -647,9 +647,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
}
}
- },
+ }
- price_list_rate: function(doc, cdt, cdn) {
+ price_list_rate(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["price_list_rate", "discount_percentage"]);
@@ -661,17 +661,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
precision("rate", item));
this.calculate_taxes_and_totals();
- },
+ }
- margin_rate_or_amount: function(doc, cdt, cdn) {
+ margin_rate_or_amount(doc, cdt, cdn) {
// calculated the revised total margin and rate on margin rate changes
let item = frappe.get_doc(cdt, cdn);
this.apply_pricing_rule_on_item(item);
this.calculate_taxes_and_totals();
cur_frm.refresh_fields();
- },
+ }
- margin_type: function(doc, cdt, cdn) {
+ margin_type(doc, cdt, cdn) {
// calculate the revised total margin and rate on margin type changes
let item = frappe.get_doc(cdt, cdn);
if (!item.margin_type) {
@@ -681,9 +681,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
this.calculate_taxes_and_totals();
cur_frm.refresh_fields();
}
- },
+ }
- get_incoming_rate: function(item, posting_date, posting_time, voucher_type, company) {
+ get_incoming_rate(item, posting_date, posting_time, voucher_type, company) {
let item_args = {
'item_code': item.item_code,
@@ -706,9 +706,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
frappe.model.set_value(item.doctype, item.name, 'rate', r.message * item.conversion_factor);
}
});
- },
+ }
- add_taxes_from_item_tax_template: function(item_tax_map) {
+ add_taxes_from_item_tax_template(item_tax_map) {
let me = this;
if(item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) {
@@ -726,9 +726,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
}
- },
+ }
- serial_no: function(doc, cdt, cdn) {
+ serial_no(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
@@ -763,17 +763,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
}
}
- },
+ }
- validate: function() {
+ validate() {
this.calculate_taxes_and_totals(false);
- },
+ }
- update_stock: function() {
+ update_stock() {
this.frm.trigger('set_default_internal_warehouse');
- },
+ }
- set_default_internal_warehouse: function() {
+ set_default_internal_warehouse() {
let me = this;
if ((this.frm.doc.doctype === 'Sales Invoice' && me.frm.doc.update_stock)
|| this.frm.doc.doctype == 'Delivery Note') {
@@ -792,9 +792,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
}
}
- },
+ }
- company: function() {
+ company() {
var me = this;
var set_pricing = function() {
if(me.frm.doc.company && me.frm.fields_dict.currency) {
@@ -901,16 +901,16 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(this.frm.doc.company) {
erpnext.last_selected_company = this.frm.doc.company;
}
- },
+ }
- transaction_date: function() {
+ transaction_date() {
if (this.frm.doc.transaction_date) {
this.frm.transaction_date = this.frm.doc.transaction_date;
frappe.ui.form.trigger(this.frm.doc.doctype, "currency");
}
- },
+ }
- posting_date: function() {
+ posting_date() {
var me = this;
if (this.frm.doc.posting_date) {
this.frm.posting_date = this.frm.doc.posting_date;
@@ -939,9 +939,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
frappe.ui.form.trigger(me.frm.doc.doctype, "currency");
}
}
- },
+ }
- due_date: function() {
+ due_date() {
// due_date is to be changed, payment terms template and/or payment schedule must
// be removed as due_date is automatically changed based on payment terms
if (this.frm.doc.due_date && !this.frm.updating_party_details && !this.frm.doc.is_pos) {
@@ -964,13 +964,13 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
frappe.msgprint(final_message);
}
}
- },
+ }
- bill_date: function() {
+ bill_date() {
this.posting_date();
- },
+ }
- recalculate_terms: function() {
+ recalculate_terms() {
const doc = this.frm.doc;
if (doc.payment_terms_template) {
this.payment_terms_template();
@@ -989,17 +989,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
);
}
- },
+ }
- get_company_currency: function() {
+ get_company_currency() {
return erpnext.get_currency(this.frm.doc.company);
- },
+ }
- contact_person: function() {
+ contact_person() {
erpnext.utils.get_contact_details(this.frm);
- },
+ }
- currency: function() {
+ currency() {
/* manqala 19/09/2016: let the translation date be whichever of the transaction_date or posting_date is available */
var transaction_date = this.frm.doc.transaction_date || this.frm.doc.posting_date;
/* end manqala */
@@ -1021,9 +1021,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
} else {
this.conversion_rate();
}
- },
+ }
- conversion_rate: function() {
+ conversion_rate() {
const me = this.frm;
if(this.frm.doc.currency === this.get_company_currency()) {
this.frm.set_value("conversion_rate", 1.0);
@@ -1043,9 +1043,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
// Make read only if Accounts Settings doesn't allow stale rates
this.frm.set_df_property("conversion_rate", "read_only", erpnext.stale_rate_allowed() ? 0 : 1);
- },
+ }
- shipping_rule: function() {
+ shipping_rule() {
var me = this;
if(this.frm.doc.shipping_rule) {
return this.frm.call({
@@ -1061,9 +1061,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
else {
me.calculate_taxes_and_totals();
}
- },
+ }
- set_margin_amount_based_on_currency: function(exchange_rate) {
+ set_margin_amount_based_on_currency(exchange_rate) {
if (in_list(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "Purchase Invoice", "Purchase Order", "Purchase Receipt"]), this.frm.doc.doctype) {
var me = this;
$.each(this.frm.doc.items || [], function(i, d) {
@@ -1073,9 +1073,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
}
- },
+ }
- set_actual_charges_based_on_currency: function(exchange_rate) {
+ set_actual_charges_based_on_currency(exchange_rate) {
var me = this;
$.each(this.frm.doc.taxes || [], function(i, d) {
if(d.charge_type == "Actual") {
@@ -1083,9 +1083,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
flt(d.tax_amount) / flt(exchange_rate));
}
});
- },
+ }
- get_exchange_rate: function(transaction_date, from_currency, to_currency, callback) {
+ get_exchange_rate(transaction_date, from_currency, to_currency, callback) {
var args;
if (["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"].includes(this.frm.doctype)) {
args = "for_selling";
@@ -1107,9 +1107,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
callback(flt(r.message));
}
});
- },
+ }
- price_list_currency: function() {
+ price_list_currency() {
var me=this;
this.set_dynamic_labels();
@@ -1123,9 +1123,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
} else {
this.plc_conversion_rate();
}
- },
+ }
- plc_conversion_rate: function() {
+ plc_conversion_rate() {
if(this.frm.doc.price_list_currency === this.get_company_currency()) {
this.frm.set_value("plc_conversion_rate", 1.0);
} else if(this.frm.doc.price_list_currency === this.frm.doc.currency
@@ -1137,9 +1137,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(!this.in_apply_price_list) {
this.apply_price_list(null, true);
}
- },
+ }
- uom: function(doc, cdt, cdn) {
+ uom(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
if(item.item_code && item.uom) {
@@ -1157,9 +1157,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
}
me.calculate_stock_uom_rate(doc, cdt, cdn);
- },
+ }
- conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
+ conversion_factor(doc, cdt, cdn, dont_fetch_price_list_rate) {
if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
@@ -1179,35 +1179,35 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
this.calculate_stock_uom_rate(doc, cdt, cdn);
}
- },
+ }
- batch_no: function(doc, cdt, cdn) {
+ batch_no(doc, cdt, cdn) {
let item = frappe.get_doc(cdt, cdn);
this.apply_price_list(item, true);
- },
+ }
- toggle_conversion_factor: function(item) {
+ toggle_conversion_factor(item) {
// toggle read only property for conversion factor field if the uom and stock uom are same
if(this.frm.get_field('items').grid.fields_map.conversion_factor) {
this.frm.fields_dict.items.grid.toggle_enable("conversion_factor",
((item.uom != item.stock_uom) && !frappe.meta.get_docfield(cur_frm.fields_dict.items.grid.doctype, "conversion_factor").read_only)? true: false);
}
- },
+ }
- qty: function(doc, cdt, cdn) {
+ qty(doc, cdt, cdn) {
let item = frappe.get_doc(cdt, cdn);
this.conversion_factor(doc, cdt, cdn, true);
this.calculate_stock_uom_rate(doc, cdt, cdn);
this.apply_pricing_rule(item, true);
- },
+ }
- calculate_stock_uom_rate: function(doc, cdt, cdn) {
+ calculate_stock_uom_rate(doc, cdt, cdn) {
let item = frappe.get_doc(cdt, cdn);
- item.stock_uom_rate = flt(item.rate)/flt(item.conversion_factor);
+ item.stock_uom_rate = flt(item.rate)/flt(item.conversion_factor);
refresh_field("stock_uom_rate", item.name, item.parentfield);
- },
- service_stop_date: function(frm, cdt, cdn) {
+ }
+ service_stop_date(frm, cdt, cdn) {
var child = locals[cdt][cdn];
if(child.service_stop_date) {
@@ -1223,9 +1223,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
frappe.throw(__("Service Stop Date cannot be after Service End Date"));
}
}
- },
+ }
- service_start_date: function(frm, cdt, cdn) {
+ service_start_date(frm, cdt, cdn) {
var child = locals[cdt][cdn];
if(child.service_start_date) {
@@ -1237,9 +1237,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
})
}
- },
+ }
- calculate_net_weight: function(){
+ calculate_net_weight(){
/* Calculate Total Net Weight then further applied shipping rule to calculate shipping charges.*/
var me = this;
this.frm.doc.total_net_weight= 0.0;
@@ -1249,9 +1249,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
refresh_field("total_net_weight");
this.shipping_rule();
- },
+ }
- set_dynamic_labels: function() {
+ set_dynamic_labels() {
// What TODO? should we make price list system non-mandatory?
this.frm.toggle_reqd("plc_conversion_rate",
!!(this.frm.doc.price_list_name && this.frm.doc.price_list_currency));
@@ -1260,9 +1260,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
this.change_form_labels(company_currency);
this.change_grid_labels(company_currency);
this.frm.refresh_fields();
- },
+ }
- change_form_labels: function(company_currency) {
+ change_form_labels(company_currency) {
var me = this;
this.frm.set_currency_labels(["base_total", "base_net_total", "base_total_taxes_and_charges",
@@ -1309,9 +1309,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(frappe.meta.get_docfield(cur_frm.doctype, "base_net_total"))
cur_frm.toggle_display("base_net_total", (show && (me.frm.doc.currency != company_currency)));
- },
+ }
- change_grid_labels: function(company_currency) {
+ change_grid_labels(company_currency) {
var me = this;
this.frm.set_currency_labels(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount", "base_rate_with_margin"],
@@ -1375,21 +1375,21 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
// set labels
var $wrapper = $(this.frm.wrapper);
- },
+ }
- recalculate: function() {
+ recalculate() {
this.calculate_taxes_and_totals();
- },
+ }
- recalculate_values: function() {
+ recalculate_values() {
this.calculate_taxes_and_totals();
- },
+ }
- calculate_charges: function() {
+ calculate_charges() {
this.calculate_taxes_and_totals();
- },
+ }
- ignore_pricing_rule: function() {
+ ignore_pricing_rule() {
if(this.frm.doc.ignore_pricing_rule) {
var me = this;
var item_list = [];
@@ -1423,9 +1423,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
} else {
this.apply_pricing_rule();
}
- },
+ }
- apply_pricing_rule: function(item, calculate_taxes_and_totals) {
+ apply_pricing_rule(item, calculate_taxes_and_totals) {
var me = this;
var args = this._get_args(item);
if (!(args.items && args.items.length)) {
@@ -1444,9 +1444,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
}
});
- },
+ }
- _get_args: function(item) {
+ _get_args(item) {
var me = this;
return {
"items": this._get_item_list(item),
@@ -1474,9 +1474,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
"pos_profile": me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '',
"coupon_code": me.frm.doc.coupon_code
};
- },
+ }
- _get_item_list: function(item) {
+ _get_item_list(item) {
var item_list = [];
var append_item = function(d) {
if (d.item_code) {
@@ -1517,9 +1517,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
}
return item_list;
- },
+ }
- _set_values_for_item_list: function(children) {
+ _set_values_for_item_list(children) {
var me = this;
var price_list_rate_changed = false;
var items_rule_dict = {};
@@ -1556,9 +1556,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
me.apply_rule_on_other_items(items_rule_dict);
if(!price_list_rate_changed) me.calculate_taxes_and_totals();
- },
+ }
- apply_rule_on_other_items: function(args) {
+ apply_rule_on_other_items(args) {
const me = this;
const fields = ["discount_percentage", "pricing_rules", "discount_amount", "rate"];
@@ -1577,9 +1577,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
}
}
- },
+ }
- apply_product_discount: function(free_item_data) {
+ apply_product_discount(free_item_data) {
const items = this.frm.doc.items.filter(d => (d.item_code == free_item_data.item_code
&& d.is_free_item)) || [];
@@ -1593,9 +1593,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
} if (items && items.length && free_item_data) {
items[0].qty = free_item_data.qty
}
- },
+ }
- apply_price_list: function(item, reset_plc_conversion) {
+ apply_price_list(item, reset_plc_conversion) {
// We need to reset plc_conversion_rate sometimes because the call to
// `erpnext.stock.get_item_details.apply_price_list` is sensitive to its value
if (!reset_plc_conversion) {
@@ -1634,9 +1634,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}).always(() => {
me.in_apply_price_list = false;
});
- },
+ }
- remove_pricing_rule: function(item) {
+ remove_pricing_rule(item) {
let me = this;
const fields = ["discount_percentage",
"discount_amount", "margin_rate_or_amount", "rate_with_margin"];
@@ -1670,18 +1670,18 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
me.trigger_price_list_rate();
}
- },
+ }
- trigger_price_list_rate: function() {
+ trigger_price_list_rate() {
var me = this;
this.frm.doc.items.forEach(child_row => {
me.frm.script_manager.trigger("price_list_rate",
child_row.doctype, child_row.name);
})
- },
+ }
- validate_company_and_party: function() {
+ validate_company_and_party() {
var me = this;
var valid = true;
@@ -1696,9 +1696,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
return valid;
- },
+ }
- get_terms: function() {
+ get_terms() {
var me = this;
erpnext.utils.get_terms(this.frm.doc.tc_name, this.frm.doc, function(r) {
@@ -1706,9 +1706,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
me.frm.set_value("terms", r.message);
}
});
- },
+ }
- taxes_and_charges: function() {
+ taxes_and_charges() {
var me = this;
if(this.frm.doc.taxes_and_charges) {
return this.frm.call({
@@ -1734,9 +1734,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
}
- },
+ }
- tax_category: function() {
+ tax_category() {
var me = this;
if(me.frm.updating_party_details) return;
@@ -1744,9 +1744,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
() => this.update_item_tax_map(),
() => erpnext.utils.set_taxes(this.frm, "tax_category"),
]);
- },
+ }
- item_tax_template: function(doc, cdt, cdn) {
+ item_tax_template(doc, cdt, cdn) {
var me = this;
if(me.frm.updating_party_details) return;
@@ -1772,9 +1772,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
item.item_tax_rate = "{}";
me.calculate_taxes_and_totals();
}
- },
+ }
- update_item_tax_map: function() {
+ update_item_tax_map() {
var me = this;
var item_codes = [];
$.each(this.frm.doc.items || [], function(i, item) {
@@ -1810,9 +1810,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
}
- },
+ }
- is_recurring: function() {
+ is_recurring() {
// set default values for recurring documents
if(this.frm.doc.is_recurring && this.frm.doc.__islocal) {
frappe.msgprint(__("Please set recurring after saving"));
@@ -1835,9 +1835,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
refresh_many(["notification_email_address", "repeat_on_day_of_month"]);
- },
+ }
- from_date: function() {
+ from_date() {
// set to_date
if(this.frm.doc.from_date) {
var recurring_type_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6,
@@ -1851,25 +1851,25 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
refresh_field('to_date');
}
}
- },
+ }
- set_gross_profit: function(item) {
+ set_gross_profit(item) {
if (["Sales Order", "Quotation"].includes(this.frm.doc.doctype) && item.valuation_rate) {
var rate = flt(item.rate) * flt(this.frm.doc.conversion_rate || 1);
item.gross_profit = flt(((rate - item.valuation_rate) * item.stock_qty), precision("amount", item));
}
- },
+ }
- setup_item_selector: function() {
+ setup_item_selector() {
// TODO: remove item selector
return;
// if(!this.item_selector) {
// this.item_selector = new erpnext.ItemSelector({frm: this.frm});
// }
- },
+ }
- get_advances: function() {
+ get_advances() {
if(!this.frm.is_return) {
return this.frm.call({
method: "set_advances",
@@ -1879,9 +1879,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
})
}
- },
+ }
- make_payment_entry: function() {
+ make_payment_entry() {
return frappe.call({
method: cur_frm.cscript.get_method_for_payment(),
args: {
@@ -1894,9 +1894,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
// cur_frm.refresh_fields()
}
});
- },
+ }
- get_method_for_payment: function(){
+ 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)){
@@ -1907,9 +1907,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
return method
- },
+ }
- set_query_for_batch: function(doc, cdt, cdn) {
+ set_query_for_batch(doc, cdt, cdn) {
// Show item's batches in the dropdown of batch no
var me = this;
@@ -1939,9 +1939,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
filters: filters
}
}
- },
+ }
- set_query_for_item_tax_template: function(doc, cdt, cdn) {
+ set_query_for_item_tax_template(doc, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
if(!item.item_code) {
return doc.company ? {filters: {company: doc.company}} : {};
@@ -1961,9 +1961,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
filters: filters
}
}
- },
+ }
- payment_terms_template: function() {
+ payment_terms_template() {
var me = this;
const doc = this.frm.doc;
if(doc.payment_terms_template && doc.doctype !== 'Delivery Note') {
@@ -1983,9 +1983,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
})
}
- },
+ }
- payment_term: function(doc, cdt, cdn) {
+ payment_term(doc, cdt, cdn) {
var row = locals[cdt][cdn];
if(row.payment_term) {
frappe.call({
@@ -2005,17 +2005,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
})
}
- },
+ }
- against_blanket_order: function(doc, cdt, cdn) {
+ against_blanket_order(doc, cdt, cdn) {
var item = locals[cdt][cdn];
if(!item.against_blanket_order) {
frappe.model.set_value(this.frm.doctype + " Item", item.name, "blanket_order", null);
frappe.model.set_value(this.frm.doctype + " Item", item.name, "blanket_order_rate", 0.00);
}
- },
+ }
- blanket_order: function(doc, cdt, cdn) {
+ blanket_order(doc, cdt, cdn) {
var me = this;
var item = locals[cdt][cdn];
if (item.blanket_order && (item.parenttype=="Sales Order" || item.parenttype=="Purchase Order")) {
@@ -2043,34 +2043,34 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
})
}
- },
+ }
- set_reserve_warehouse: function() {
+ set_reserve_warehouse() {
this.autofill_warehouse(this.frm.doc.supplied_items, "reserve_warehouse", this.frm.doc.set_reserve_warehouse);
- },
+ }
- set_warehouse: function() {
+ set_warehouse() {
this.autofill_warehouse(this.frm.doc.items, "warehouse", this.frm.doc.set_warehouse);
- },
+ }
- set_target_warehouse: function() {
+ set_target_warehouse() {
this.autofill_warehouse(this.frm.doc.items, "target_warehouse", this.frm.doc.set_target_warehouse);
- },
+ }
- set_from_warehouse: function() {
+ set_from_warehouse() {
this.autofill_warehouse(this.frm.doc.items, "from_warehouse", this.frm.doc.set_from_warehouse);
- },
+ }
- autofill_warehouse : function (child_table, warehouse_field, warehouse) {
+ autofill_warehouse(child_table, warehouse_field, warehouse) {
if (warehouse && child_table && child_table.length) {
let doctype = child_table[0].doctype;
$.each(child_table || [], function(i, item) {
frappe.model.set_value(doctype, item.name, warehouse_field, warehouse);
});
}
- },
+ }
- coupon_code: function() {
+ coupon_code() {
var me = this;
frappe.run_serially([
() => this.frm.doc.ignore_pricing_rule=1,
@@ -2079,7 +2079,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
() => me.apply_pricing_rule()
]);
}
-});
+};
erpnext.show_serial_batch_selector = function (frm, d, callback, on_close, show_dialog) {
let warehouse, receiving_stock, existing_stock;
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index 0d656bc1fb..7df976c1be 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -1,31 +1,31 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-erpnext.payments = erpnext.stock.StockController.extend({
- make_payment: function() {
+erpnext.payments = class payments extends erpnext.stock.StockController {
+ make_payment() {
var me = this;
this.dialog = new frappe.ui.Dialog({
title: 'Payment'
});
-
+
this.dialog.show();
this.$body = this.dialog.body;
this.set_payment_primary_action();
this.make_keyboard();
this.select_text()
- },
+ }
- select_text: function(){
+ select_text(){
var me = this;
$(this.$body).find('.form-control').click(function(){
$(this).select();
})
- },
+ }
- set_payment_primary_action: function(){
+ set_payment_primary_action(){
var me = this;
-
+
this.dialog.set_primary_action(__("Submit"), function() {
// Allow no ZERO payment
$.each(me.frm.doc.payments, function (index, data) {
@@ -36,18 +36,18 @@ erpnext.payments = erpnext.stock.StockController.extend({
}
});
})
- },
+ }
- make_keyboard: function(){
+ make_keyboard(){
var me = this;
$(this.$body).empty();
$(this.$body).html(frappe.render_template('pos_payment', this.frm.doc))
this.show_payment_details();
this.bind_keyboard_event()
this.clear_amount()
- },
+ }
- make_multimode_payment: function(){
+ make_multimode_payment(){
var me = this;
if(this.frm.doc.change_amount > 0){
@@ -57,9 +57,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
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: function(){
+ show_payment_details(){
var me = this;
var multimode_payments = $(this.$body).find('.multimode-payments').empty();
if(this.frm.doc.payments.length){
@@ -82,9 +82,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
}else{
$("
No payment mode selected in pos profile
").appendTo(multimode_payments)
}
- },
+ }
- set_outstanding_amount: function(){
+ 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
@@ -99,47 +99,47 @@ erpnext.payments = erpnext.stock.StockController.extend({
}
this.selected_mode.select()
this.bind_amount_change_event();
- },
-
- bind_keyboard_event: function(){
+ }
+
+ bind_keyboard_event(){
var me = this;
this.payment_val = '';
this.bind_form_control_event();
this.bind_numeric_keys_event();
- },
+ }
- bind_form_control_event: function(){
+ 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('.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('.change_amount').change(function(){
me.change_amount(flt($(this).val()), precision("change_amount"));
})
- },
+ }
- highlight_selected_row: function(){
+ highlight_selected_row(){
var me = this;
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: function(){
+ }
+
+ bind_numeric_keys_event(){
var me = this;
$(this.$body).find('.pos-keyboard-key').click(function(){
me.payment_val += $(this).text();
@@ -147,7 +147,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
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));
@@ -155,9 +155,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
me.update_paid_amount();
})
- },
-
- bind_amount_change_event: function(){
+ }
+
+ bind_amount_change_event(){
var me = this;
this.selected_mode.change(function(){
me.payment_val = flt($(this).val()) || 0.0;
@@ -165,9 +165,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
me.idx = me.selected_mode.attr("idx")
me.update_payment_amount()
})
- },
+ }
- clear_amount: function() {
+ clear_amount() {
var me = this;
$(this.$body).find('.clr').click(function(e){
e.stopPropagation();
@@ -178,9 +178,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
me.highlight_selected_row();
me.update_payment_amount();
})
- },
+ }
- write_off_amount: function(write_off_amount) {
+ write_off_amount(write_off_amount) {
var me = this;
this.frm.doc.write_off_amount = flt(write_off_amount, precision("write_off_amount"));
@@ -188,17 +188,17 @@ erpnext.payments = erpnext.stock.StockController.extend({
precision("base_write_off_amount"));
this.calculate_outstanding_amount(false)
this.show_amounts()
- },
+ }
- change_amount: function(change_amount) {
+ change_amount(change_amount) {
var me = this;
this.frm.doc.change_amount = flt(change_amount, precision("change_amount"));
this.calculate_write_off_amount()
this.show_amounts()
- },
+ }
- update_paid_amount: function(update_write_off) {
+ update_paid_amount(update_write_off) {
var me = this;
if(in_list(['change_amount', 'write_off_amount'], this.idx)){
var value = me.selected_mode.val();
@@ -213,9 +213,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
}else{
this.update_payment_amount()
}
- },
+ }
- update_payment_amount: function(){
+ update_payment_amount(){
var me = this;
$.each(this.frm.doc.payments, function(index, data){
@@ -226,9 +226,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.calculate_outstanding_amount(false);
this.show_amounts();
- },
+ }
- show_amounts: function(){
+ 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));
@@ -236,4 +236,4 @@ erpnext.payments = erpnext.stock.StockController.extend({
$(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();
}
-})
\ No newline at end of file
+}
diff --git a/erpnext/public/js/stock_analytics.js b/erpnext/public/js/stock_analytics.js
index 140c9dc90b..c74b45e6db 100644
--- a/erpnext/public/js/stock_analytics.js
+++ b/erpnext/public/js/stock_analytics.js
@@ -2,8 +2,8 @@
// License: GNU General Public License v3. See license.txt
-erpnext.StockAnalytics = erpnext.StockGridReport.extend({
- init: function(wrapper, opts) {
+erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
+ constructor(wrapper, opts) {
var args = {
title: __("Stock Analytics"),
parent: $(wrapper).find('.layout-main'),
@@ -30,9 +30,9 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
if(opts) $.extend(args, opts);
- this._super(args);
- },
- setup_columns: function() {
+ super(args);
+ }
+ setup_columns() {
var std_columns = [
{id: "name", name: __("Item"), field: "name", width: 300},
{id: "brand", name: __("Brand"), field: "brand", width: 100},
@@ -43,8 +43,9 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
this.make_date_range_columns();
this.columns = std_columns.concat(this.columns);
- },
- filters: [
+ }
+
+ 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) {
@@ -66,20 +67,21 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
{label:__("Quarterly"), value:"Quarterly"},
{label:__("Yearly"), value:"Yearly"},
]}
- ],
- setup_filters: function() {
+ ]
+
+ setup_filters() {
var me = this;
- this._super();
+ super.setup_filters();
this.trigger_refresh_on_change(["value_or_qty", "brand", "warehouse", "range"]);
this.show_zero_check();
- },
- init_filter_values: function() {
- this._super();
+ }
+ init_filter_values() {
+ super.init_filter_values();
this.filter_inputs.range && this.filter_inputs.range.val('Monthly');
- },
- prepare_data: function() {
+ }
+ prepare_data() {
var me = this;
if(!this.data) {
@@ -112,8 +114,8 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
this.prepare_balances();
this.update_groups();
- },
- prepare_balances: function() {
+ }
+ prepare_balances() {
var me = this;
var from_date = frappe.datetime.str_to_obj(this.from_date);
var to_date = frappe.datetime.str_to_obj(this.to_date);
@@ -164,8 +166,8 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
item.closing_qty_value += diff;
}
}
- },
- update_groups: function() {
+ }
+ update_groups() {
var me = this;
$.each(this.data, function(i, item) {
// update groups
@@ -192,8 +194,8 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
}
}
});
- },
- show_stock_ledger: function(item_code) {
+ }
+ show_stock_ledger(item_code) {
frappe.route_options = {
item_code: item_code,
from_date: this.from_date,
@@ -201,5 +203,5 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
};
frappe.set_route("query-report", "Stock Ledger");
}
-});
+};
diff --git a/erpnext/public/js/stock_grid_report.js b/erpnext/public/js/stock_grid_report.js
index 832fd3eccf..752fafdb97 100644
--- a/erpnext/public/js/stock_grid_report.js
+++ b/erpnext/public/js/stock_grid_report.js
@@ -1,16 +1,16 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-erpnext.StockGridReport = frappe.views.TreeGridReport.extend({
- get_item_warehouse: function(warehouse, item) {
+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: []
};
return this.item_warehouse[item][warehouse];
- },
+ }
- get_value_diff: function(wh, sl, is_fifo) {
+ get_value_diff(wh, sl, is_fifo) {
// value
if(sl.qty > 0) {
// incoming - rate is given
@@ -59,8 +59,8 @@ erpnext.StockGridReport = frappe.views.TreeGridReport.extend({
wh.balance_qty += sl.qty;
wh.balance_value += value_diff;
return value_diff;
- },
- get_fifo_value_diff: function(wh, sl) {
+ }
+ get_fifo_value_diff(wh, sl) {
// get exact rate from fifo stack
var fifo_stack = (wh.fifo_stack || []).reverse();
var fifo_value_diff = 0.0;
@@ -89,9 +89,9 @@ erpnext.StockGridReport = frappe.views.TreeGridReport.extend({
// reset the updated stack
wh.fifo_stack = fifo_stack.reverse();
return -fifo_value_diff;
- },
+ }
- get_serialized_value_diff: function(sl) {
+ get_serialized_value_diff(sl) {
var me = this;
var value_diff = 0.0;
@@ -103,9 +103,9 @@ erpnext.StockGridReport = frappe.views.TreeGridReport.extend({
});
return value_diff;
- },
+ }
- get_serialized_buying_rates: function() {
+ get_serialized_buying_rates() {
var serialized_buying_rates = {};
if (frappe.report_dump.data["Serial No"]) {
@@ -115,5 +115,5 @@ erpnext.StockGridReport = frappe.views.TreeGridReport.extend({
}
return serialized_buying_rates;
- },
-});
+ }
+};
diff --git a/erpnext/public/js/telephony.js b/erpnext/public/js/telephony.js
index 9548d6c5f3..1c3e314797 100644
--- a/erpnext/public/js/telephony.js
+++ b/erpnext/public/js/telephony.js
@@ -1,19 +1,19 @@
-frappe.ui.form.ControlData = frappe.ui.form.ControlData.extend( {
+frappe.ui.form.ControlData = class ControlData extends frappe.ui.form.ControlData {
make_input() {
- this._super();
+ super.make_input();
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'
+ if (field.df.read_only === 1 && field.df.options === 'Phone'
&& field.disp_area.style[0] != 'display' && !field.has_icon) {
field.setup_phone();
field.has_icon = true;
}
});
}
- },
+ }
setup_phone() {
if (frappe.phone_call.handler) {
let control = this.df.read_only ? '.control-value' : '.control-input';
@@ -30,4 +30,4 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlData.extend( {
});
}
}
-});
+};
diff --git a/erpnext/public/js/utils/customer_quick_entry.js b/erpnext/public/js/utils/customer_quick_entry.js
index ebe6cd98f8..efb8dd9d5c 100644
--- a/erpnext/public/js/utils/customer_quick_entry.js
+++ b/erpnext/public/js/utils/customer_quick_entry.js
@@ -1,17 +1,17 @@
frappe.provide('frappe.ui.form');
-frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
- init: function(doctype, after_insert) {
+frappe.ui.form.CustomerQuickEntryForm = class CustomerQuickEntryForm extends frappe.ui.form.QuickEntryForm {
+ constructor(doctype, after_insert) {
+ super(doctype, after_insert);
this.skip_redirect_on_error = true;
- this._super(doctype, after_insert);
- },
+ }
- render_dialog: function() {
+ render_dialog() {
this.mandatory = this.mandatory.concat(this.get_variant_fields());
- this._super();
- },
+ super.render_dialog();
+ }
- get_variant_fields: function() {
+ get_variant_fields() {
var variant_fields = [{
fieldtype: "Section Break",
label: __("Primary Contact Details"),
@@ -77,5 +77,5 @@ frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
}];
return variant_fields;
- },
-})
\ No newline at end of file
+ }
+}
diff --git a/erpnext/public/js/utils/item_quick_entry.js b/erpnext/public/js/utils/item_quick_entry.js
index 27ef107ace..7e0198d33b 100644
--- a/erpnext/public/js/utils/item_quick_entry.js
+++ b/erpnext/public/js/utils/item_quick_entry.js
@@ -1,27 +1,27 @@
frappe.provide('frappe.ui.form');
-frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
- init: function(doctype, after_insert) {
- this._super(doctype, after_insert);
- },
+frappe.ui.form.ItemQuickEntryForm = class ItemQuickEntryForm extends frappe.ui.form.QuickEntryForm {
+ constructor(doctype, after_insert) {
+ super(doctype, after_insert);
+ }
- render_dialog: function() {
+ render_dialog() {
this.mandatory = this.get_variant_fields().concat(this.mandatory);
this.mandatory = this.mandatory.concat(this.get_attributes_fields());
this.check_naming_series_based_on();
- this._super();
+ super.render_dialog();
this.init_post_render_dialog_operations();
this.preset_fields_for_template();
this.dialog.$wrapper.find('.edit-full').text(__('Edit in full page for more options like assets, serial nos, batches etc.'))
- },
+ }
- check_naming_series_based_on: function() {
+ check_naming_series_based_on() {
if (frappe.defaults.get_default("item_naming_by") === "Naming Series") {
this.mandatory = this.mandatory.filter(d => d.fieldname !== "item_code");
}
- },
+ }
- init_post_render_dialog_operations: function() {
+ init_post_render_dialog_operations() {
this.dialog.fields_dict.attribute_html.$wrapper.append(frappe.render_template("item_quick_entry"));
this.init_for_create_variant_trigger();
this.init_for_item_template_trigger();
@@ -29,9 +29,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
this.toggle_manufacturer_fields();
this.dialog.get_field("item_template").df.hidden = 1;
this.dialog.get_field("item_template").refresh();
- },
+ }
- register_primary_action: function() {
+ register_primary_action() {
var me = this;
this.dialog.set_primary_action(__('Save'), function() {
if (me.dialog.working) return;
@@ -59,9 +59,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
me.insert(variant_values);
}
});
- },
+ }
- insert: function(variant_values) {
+ insert(variant_values) {
let me = this;
return new Promise(resolve => {
frappe.call({
@@ -94,9 +94,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
freeze: true
});
});
- },
+ }
- open_doc: function() {
+ open_doc() {
this.dialog.hide();
this.update_doc();
if (this.dialog.fields_dict.create_variant.$input.prop("checked")) {
@@ -106,9 +106,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
} else {
frappe.set_route('Form', this.doctype, this.doc.name);
}
- },
+ }
- get_variant_fields: function() {
+ get_variant_fields() {
var variant_fields = [{
fieldname: "create_variant",
fieldtype: "Check",
@@ -130,9 +130,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
}];
return variant_fields;
- },
+ }
- get_manufacturing_fields: function() {
+ get_manufacturing_fields() {
this.manufacturer_fields = [{
fieldtype: 'Link',
options: 'Manufacturer',
@@ -148,9 +148,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
reqd: 0
}];
return this.manufacturer_fields;
- },
+ }
- get_attributes_fields: function() {
+ get_attributes_fields() {
var attribute_fields = [{
fieldname: 'attribute_html',
fieldtype: 'HTML'
@@ -158,18 +158,18 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
attribute_fields = attribute_fields.concat(this.get_manufacturing_fields());
return attribute_fields;
- },
+ }
- init_for_create_variant_trigger: function() {
+ init_for_create_variant_trigger() {
var me = this;
this.dialog.fields_dict.create_variant.$input.on("click", function() {
me.preset_fields_for_template();
me.init_post_template_trigger_operations(false, [], true);
});
- },
+ }
- preset_fields_for_template: function() {
+ preset_fields_for_template() {
var for_variant = this.dialog.get_value('create_variant');
// setup template field, seen and mandatory if variant
@@ -195,9 +195,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
f.refresh();
});
- },
+ }
- init_for_item_template_trigger: function() {
+ init_for_item_template_trigger() {
var me = this;
me.dialog.fields_dict["item_template"].df.onchange = () => {
@@ -228,9 +228,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
me.init_post_template_trigger_operations(false, [], true);
}
}
- },
+ }
- init_post_template_trigger_operations: function(is_manufacturer, attributes, attributes_flag) {
+ init_post_template_trigger_operations(is_manufacturer, attributes, attributes_flag) {
this.attributes = attributes;
this.attribute_values = {};
this.attributes_count = attributes.length;
@@ -240,23 +240,23 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
this.toggle_manufacturer_fields();
this.dialog.fields_dict.attribute_html.$wrapper.find(".attributes").toggleClass("hide-control", attributes_flag);
this.dialog.fields_dict.attribute_html.$wrapper.find(".attributes-header").toggleClass("hide-control", attributes_flag);
- },
+ }
- toggle_manufacturer_fields: function() {
+ toggle_manufacturer_fields() {
var me = this;
$.each(this.manufacturer_fields, function(i, dialog_field) {
me.dialog.get_field(dialog_field.fieldname).df.hidden = !me.is_manufacturer;
me.dialog.get_field(dialog_field.fieldname).df.reqd = dialog_field.fieldname == 'manufacturer' ? me.is_manufacturer : false;
me.dialog.get_field(dialog_field.fieldname).refresh();
});
- },
+ }
- initiate_render_attributes: function() {
+ initiate_render_attributes() {
this.dialog.fields_dict.attribute_html.$wrapper.find(".attributes").empty();
this.render_attributes(this.attributes);
- },
+ }
- render_attributes: function(attributes) {
+ render_attributes(attributes) {
var me = this;
this.dialog.get_field('attribute_html').toggle(true);
@@ -291,9 +291,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
});
}
});
- },
+ }
- init_make_control: function(fieldtype, row) {
+ init_make_control(fieldtype, row) {
this[row.attribute] = frappe.ui.form.make_control({
df: {
"fieldtype": fieldtype,
@@ -305,9 +305,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
only_input: false
});
this[row.attribute].make_input();
- },
+ }
- init_awesomplete_for_attribute: function(row) {
+ init_awesomplete_for_attribute(row) {
var me = this;
this[row.attribute].input.awesomplete = new Awesomplete(this[row.attribute].input, {
@@ -343,9 +343,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
me.attribute_values[$(e.target).attr("data-fieldname")] = e.target.value;
$(e.target).closest(".frappe-control").toggleClass("has-error", e.target.value ? false : true);
});
- },
+ }
- get_variant_doc: function() {
+ get_variant_doc() {
var me = this;
var variant_doc = {};
var attribute = this.validate_mandatory_attributes();
@@ -381,9 +381,9 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
})
}
return variant_doc;
- },
+ }
- validate_mandatory_attributes: function() {
+ validate_mandatory_attributes() {
var me = this;
var attribute = {};
var mandatory = [];
@@ -404,4 +404,4 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
}
return attribute;
}
-});
\ No newline at end of file
+};
diff --git a/erpnext/public/js/utils/item_selector.js b/erpnext/public/js/utils/item_selector.js
index d04c488a59..9fc264086a 100644
--- a/erpnext/public/js/utils/item_selector.js
+++ b/erpnext/public/js/utils/item_selector.js
@@ -1,5 +1,5 @@
-erpnext.ItemSelector = Class.extend({
- init: function(opts) {
+erpnext.ItemSelector = class ItemSelector {
+ constructor(opts) {
$.extend(this, opts);
if (!this.item_field) {
@@ -12,9 +12,9 @@ erpnext.ItemSelector = Class.extend({
this.grid = this.frm.get_field("items").grid;
this.setup();
- },
+ }
- setup: function() {
+ setup() {
var me = this;
if(!this.grid.add_items_button) {
this.grid.add_items_button = this.grid.add_custom_button(__('Add Items'), function() {
@@ -26,9 +26,9 @@ erpnext.ItemSelector = Class.extend({
setTimeout(function() { me.dialog.input.focus(); }, 1000);
});
}
- },
+ }
- make_dialog: function() {
+ make_dialog() {
this.dialog = new frappe.ui.Dialog({
title: __('Add Items')
});
@@ -53,9 +53,9 @@ erpnext.ItemSelector = Class.extend({
me.timeout_id = undefined;
}, 500);
});
- },
+ }
- add_item: function(item_code) {
+ add_item(item_code) {
// add row or update qty
var added = false;
@@ -82,9 +82,9 @@ erpnext.ItemSelector = Class.extend({
]);
}
- },
+ }
- render_items: function() {
+ render_items() {
let args = {
query: this.item_query,
filters: {}
@@ -107,4 +107,4 @@ erpnext.ItemSelector = Class.extend({
me.dialog.results.html(frappe.render_template('item_selector', {'data':r.values}));
});
}
-});
\ No newline at end of file
+};
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index d49a8138fb..d44c708356 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -1,6 +1,6 @@
-erpnext.SerialNoBatchSelector = Class.extend({
- init: function(opts, show_dialog) {
+erpnext.SerialNoBatchSelector = class SerialNoBatchSelector {
+ constructor(opts, show_dialog) {
$.extend(this, opts);
this.show_dialog = show_dialog;
// frm, item, warehouse_details, has_batch, oldest
@@ -12,16 +12,16 @@ erpnext.SerialNoBatchSelector = Class.extend({
if(d && d.has_serial_no && !(this.show_dialog == false)) this.has_serial_no = 1;
this.setup();
- },
+ }
- setup: function() {
+ setup() {
this.item_code = this.item.item_code;
this.qty = this.item.qty;
this.make_dialog();
this.on_close_dialog();
- },
+ }
- make_dialog: function() {
+ make_dialog() {
var me = this;
this.data = this.oldest ? this.oldest : [];
@@ -176,15 +176,15 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
this.dialog.show();
- },
+ }
- on_close_dialog: function() {
+ on_close_dialog() {
this.dialog.get_close_btn().on('click', () => {
this.on_close && this.on_close(this.item);
});
- },
+ }
- validate: function() {
+ validate() {
let values = this.values;
if(!values.warehouse) {
frappe.throw(__("Please select a warehouse"));
@@ -210,7 +210,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
return true;
}
- },
+ }
update_batch_items() {
// clones an items if muliple batches are selected.
@@ -233,14 +233,14 @@ erpnext.SerialNoBatchSelector = Class.extend({
'selected_qty', this.values.warehouse);
});
}
- },
+ }
update_serial_no_item() {
// just updates serial no for the item
if(this.has_serial_no && !this.has_batch) {
this.map_row_values(this.item, this.values, 'serial_no', 'qty');
}
- },
+ }
update_batch_serial_no_items() {
// if serial no selected is from different batches, adds new rows for each batch.
@@ -281,14 +281,14 @@ erpnext.SerialNoBatchSelector = Class.extend({
});
})
}
- },
+ }
- batch_exists: function(batch) {
+ batch_exists(batch) {
const batches = this.frm.doc.items.map(data => data.batch_no);
return (batches && in_list(batches, batch)) ? true : false;
- },
+ }
- map_row_values: function(row, values, number, qty_field, warehouse) {
+ map_row_values(row, values, number, qty_field, warehouse) {
row.qty = values[qty_field];
row.transfer_qty = flt(values[qty_field]) * flt(row.conversion_factor);
row[number] = values[number];
@@ -301,9 +301,9 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
this.frm.dirty();
- },
+ }
- update_total_qty: function() {
+ update_total_qty() {
let qty_field = this.dialog.fields_dict.qty;
let total_qty = 0;
@@ -312,9 +312,9 @@ erpnext.SerialNoBatchSelector = Class.extend({
});
qty_field.set_input(total_qty);
- },
+ }
- get_batch_fields: function() {
+ get_batch_fields() {
var me = this;
return [
@@ -425,9 +425,9 @@ erpnext.SerialNoBatchSelector = Class.extend({
},
}
];
- },
+ }
- get_serial_no_fields: function() {
+ get_serial_no_fields() {
var me = this;
this.serial_list = [];
@@ -510,4 +510,4 @@ erpnext.SerialNoBatchSelector = Class.extend({
}
];
}
-});
+};
diff --git a/erpnext/selling/doctype/installation_note/installation_note.js b/erpnext/selling/doctype/installation_note/installation_note.js
index 7fd0877d11..ffa185baf6 100644
--- a/erpnext/selling/doctype/installation_note/installation_note.js
+++ b/erpnext/selling/doctype/installation_note/installation_note.js
@@ -30,8 +30,8 @@ frappe.ui.form.on('Installation Note', {
frappe.provide("erpnext.selling");
// TODO commonify this code
-erpnext.selling.InstallationNote = frappe.ui.form.Controller.extend({
- refresh: function() {
+erpnext.selling.InstallationNote = class InstallationNote extends frappe.ui.form.Controller {
+ refresh() {
var me = this;
if (this.frm.doc.docstatus===0) {
this.frm.add_custom_button(__('From Delivery Note'),
@@ -54,7 +54,7 @@ erpnext.selling.InstallationNote = frappe.ui.form.Controller.extend({
}, "fa fa-download", "btn-default"
);
}
- },
-});
+ }
+};
$.extend(cur_frm.cscript, new erpnext.selling.InstallationNote({frm: cur_frm}));
\ No newline at end of file
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 5a0d9c9065..10606bf81e 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -36,13 +36,13 @@ frappe.ui.form.on('Quotation', {
}
});
-erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
- onload: function(doc, dt, dn) {
+erpnext.selling.QuotationController = class QuotationController extends erpnext.selling.SellingController {
+ onload(doc, dt, dn) {
var me = this;
- this._super(doc, dt, dn);
+ super.(doc, dt, dn);
- },
- party_name: function() {
+ }
+ party_name() {
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function() {
me.apply_price_list();
@@ -51,9 +51,9 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
if(me.frm.doc.quotation_to=="Lead" && me.frm.doc.party_name) {
me.frm.trigger("get_lead_details");
}
- },
- refresh: function(doc, dt, dn) {
- this._super(doc, dt, dn);
+ }
+ refresh(doc, dt, dn) {
+ super.refresh(doc, dt, dn);
doctype = doc.quotation_to == 'Customer' ? 'Customer':'Lead';
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'party_name', doctype: doctype}
@@ -121,9 +121,9 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
this.toggle_reqd_lead_customer();
- },
+ }
- set_dynamic_field_label: function(){
+ set_dynamic_field_label(){
if (this.frm.doc.quotation_to == "Customer")
{
this.frm.set_df_property("party_name", "label", "Customer");
@@ -138,22 +138,22 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
return{ query: "erpnext.controllers.queries.lead_query" }
}
}
- },
+ }
- toggle_reqd_lead_customer: function() {
+ toggle_reqd_lead_customer() {
var me = this;
// to overwrite the customer_filter trigger from queries.js
this.frm.toggle_reqd("party_name", this.frm.doc.quotation_to);
this.frm.set_query('customer_address', this.address_query);
this.frm.set_query('shipping_address_name', this.address_query);
- },
+ }
- tc_name: function() {
+ tc_name() {
this.get_terms();
- },
+ }
- address_query: function(doc) {
+ address_query(doc) {
return {
query: 'frappe.contacts.doctype.address.address.address_query',
filters: {
@@ -161,20 +161,20 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
link_name: doc.party_name
}
};
- },
+ }
- validate_company_and_party: function(party_field) {
+ validate_company_and_party(party_field) {
if(!this.frm.doc.quotation_to) {
frappe.msgprint(__("Please select a value for {0} quotation_to {1}", [this.frm.doc.doctype, this.frm.doc.name]));
return false;
} else if (this.frm.doc.quotation_to == "Lead") {
return true;
} else {
- return this._super(party_field);
+ return super.validate_company_and_party(party_field);
}
- },
+ }
- get_lead_details: function() {
+ get_lead_details() {
var me = this;
if(!this.frm.doc.quotation_to === "Lead") {
return;
@@ -198,7 +198,7 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
}
})
}
-});
+};
cur_frm.script_manager.make(erpnext.selling.QuotationController);
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index e3b41e66fb..d5ceca8ec8 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -102,14 +102,14 @@ frappe.ui.form.on("Sales Order Item", {
}
});
-erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
- onload: function(doc, dt, dn) {
- this._super();
- },
+erpnext.selling.SalesOrderController = class SalesOrderController extends erpnext.selling.SellingController {
+ onload(doc, dt, dn) {
+ super.onload();
+ }
- refresh: function(doc, dt, dn) {
+ refresh(doc, dt, dn) {
var me = this;
- this._super();
+ super.refresh();
let allow_delivery = false;
if (doc.docstatus==1) {
@@ -241,14 +241,14 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
}
this.order_type(doc);
- },
+ }
create_pick_list() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.create_pick_list",
frm: this.frm
})
- },
+ }
make_work_order() {
var me = this;
@@ -343,33 +343,33 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
}
}
});
- },
+ }
- order_type: function() {
+ order_type() {
this.toggle_delivery_date();
- },
+ }
- tc_name: function() {
+ tc_name() {
this.get_terms();
- },
+ }
- make_material_request: function() {
+ make_material_request() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
frm: this.frm
})
- },
+ }
- skip_delivery_note: function() {
+ skip_delivery_note() {
this.toggle_delivery_date();
- },
+ }
- toggle_delivery_date: function() {
+ toggle_delivery_date() {
this.frm.fields_dict.items.grid.toggle_reqd("delivery_date",
(this.frm.doc.order_type == "Sales" && !this.frm.doc.skip_delivery_note));
- },
+ }
- make_raw_material_request: function() {
+ make_raw_material_request() {
var me = this;
this.frm.call({
doc: this.frm.doc,
@@ -390,9 +390,9 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
}
}
});
- },
+ }
- make_raw_material_request_dialog: function(r) {
+ make_raw_material_request_dialog(r) {
var fields = [
{fieldtype:'Check', fieldname:'include_exploded_items',
label: __('Include Exploded Items')},
@@ -447,9 +447,9 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
primary_action_label: __('Create')
});
d.show();
- },
+ }
- make_delivery_note_based_on_delivery_date: function() {
+ make_delivery_note_based_on_delivery_date() {
var me = this;
var delivery_dates = [];
@@ -509,51 +509,51 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
} else {
this.make_delivery_note();
}
- },
+ }
- make_delivery_note: function() {
+ make_delivery_note() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
frm: this.frm
})
- },
+ }
- make_sales_invoice: function() {
+ make_sales_invoice() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_sales_invoice",
frm: this.frm
})
- },
+ }
- make_maintenance_schedule: function() {
+ make_maintenance_schedule() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_schedule",
frm: this.frm
})
- },
+ }
- make_project: function() {
+ make_project() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_project",
frm: this.frm
})
- },
+ }
- make_inter_company_order: function() {
+ make_inter_company_order() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_inter_company_purchase_order",
frm: this.frm
});
- },
+ }
- make_maintenance_visit: function() {
+ make_maintenance_visit() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_visit",
frm: this.frm
})
- },
+ }
- make_purchase_order: function(){
+ make_purchase_order(){
let pending_items = this.frm.doc.items.some((item) =>{
let pending_qty = flt(item.stock_qty) - flt(item.ordered_qty);
return pending_qty > 0;
@@ -690,9 +690,9 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
dialog.get_field("items_for_po").refresh();
dialog.wrapper.find('.grid-heading-row .grid-row-check').click();
dialog.show();
- },
+ }
- hold_sales_order: function(){
+ hold_sales_order(){
var me = this;
var d = new frappe.ui.Dialog({
title: __('Reason for Hold'),
@@ -724,11 +724,11 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
}
});
d.show();
- },
- close_sales_order: function(){
+ }
+ close_sales_order(){
this.frm.cscript.update_status("Close", "Closed")
- },
- update_status: function(label, status){
+ }
+ update_status(label, status){
var doc = this.frm.doc;
var me = this;
frappe.ui.form.is_saving = true;
@@ -743,5 +743,5 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
}
});
}
-});
+};
$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 04285735ab..eb02867720 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -9,15 +9,15 @@ cur_frm.cscript.tax_table = "Sales Taxes and Charges";
cur_frm.email_field = "contact_email";
frappe.provide("erpnext.selling");
-erpnext.selling.SellingController = erpnext.TransactionController.extend({
- setup: function() {
- this._super();
+erpnext.selling.SellingController = class SellingController extends erpnext.TransactionController {
+ setup() {
+ super.setup();
this.frm.add_fetch("sales_partner", "commission_rate", "commission_rate");
this.frm.add_fetch("sales_person", "commission_rate", "commission_rate");
- },
+ }
- onload: function() {
- this._super();
+ onload() {
+ super.onload();
this.setup_queries();
this.frm.set_query('shipping_rule', function() {
return {
@@ -26,9 +26,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
}
};
});
- },
+ }
- setup_queries: function() {
+ setup_queries() {
var me = this;
$.each([["customer", "customer"],
@@ -81,10 +81,10 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
});
}
- },
+ }
- refresh: function() {
- this._super();
+ refresh() {
+ super.refresh();
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
@@ -95,45 +95,45 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
this.frm.toggle_display("packing_list", packing_list_exists ? true : false);
}
this.toggle_editable_price_list_rate();
- },
+ }
- customer: function() {
+ customer() {
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function() {
me.apply_price_list();
});
- },
+ }
- customer_address: function() {
+ 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");
- },
+ }
- shipping_address_name: function() {
+ 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");
- },
+ }
- sales_partner: function() {
+ sales_partner() {
this.apply_pricing_rule();
- },
+ }
- campaign: function() {
+ campaign() {
this.apply_pricing_rule();
- },
+ }
- selling_price_list: function() {
+ selling_price_list() {
this.apply_price_list();
this.set_dynamic_labels();
- },
+ }
- discount_percentage: function(doc, cdt, cdn) {
+ 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');
- },
+ }
- discount_amount: function(doc, cdt, cdn) {
+ discount_amount(doc, cdt, cdn) {
if(doc.name === cdn) {
return;
@@ -142,9 +142,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
var item = frappe.get_doc(cdt, cdn);
item.discount_percentage = 0.0;
this.apply_discount_on_item(doc, cdt, cdn, 'discount_amount');
- },
+ }
- apply_discount_on_item: function(doc, cdt, cdn, field) {
+ apply_discount_on_item(doc, cdt, cdn, field) {
var item = frappe.get_doc(cdt, cdn);
if(!item.price_list_rate) {
item[field] = 0.0;
@@ -152,14 +152,14 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
this.price_list_rate(doc, cdt, cdn);
}
this.set_gross_profit(item);
- },
+ }
- commission_rate: function() {
+ commission_rate() {
this.calculate_commission();
refresh_field("total_commission");
- },
+ }
- total_commission: function() {
+ total_commission() {
if(this.frm.doc.base_net_total) {
frappe.model.round_floats_in(this.frm.doc, ["base_net_total", "total_commission"]);
@@ -175,9 +175,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
this.frm.set_value("commission_rate",
flt(this.frm.doc.total_commission * 100.0 / this.frm.doc.base_net_total));
}
- },
+ }
- allocated_percentage: function(doc, cdt, cdn) {
+ allocated_percentage(doc, cdt, cdn) {
var sales_person = frappe.get_doc(cdt, cdn);
if(sales_person.allocated_percentage) {
@@ -193,15 +193,15 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
refresh_field(["allocated_percentage", "allocated_amount", "commission_rate","incentives"], sales_person.name,
sales_person.parentfield);
}
- },
+ }
- sales_person: function(doc, cdt, cdn) {
+ sales_person(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.calculate_incentive(row);
refresh_field("incentives",row.name,row.parentfield);
- },
+ }
- warehouse: function(doc, cdt, cdn) {
+ warehouse(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
@@ -239,18 +239,18 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
});
}
})
- },
+ }
- toggle_editable_price_list_rate: function() {
+ toggle_editable_price_list_rate() {
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) {
df.read_only = 0;
}
- },
+ }
- calculate_commission: function() {
+ calculate_commission() {
if(this.frm.fields_dict.commission_rate) {
if(this.frm.doc.commission_rate > 100) {
var msg = __(frappe.meta.get_label(this.frm.doc.doctype, "commission_rate", this.frm.doc.name)) +
@@ -262,9 +262,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
this.frm.doc.total_commission = flt(this.frm.doc.base_net_total * this.frm.doc.commission_rate / 100.0,
precision("total_commission"));
}
- },
+ }
- calculate_contribution: function() {
+ calculate_contribution() {
var me = this;
$.each(this.frm.doc.doctype.sales_team || [], function(i, sales_person) {
frappe.model.round_floats_in(sales_person);
@@ -274,18 +274,18 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
precision("allocated_amount", sales_person));
}
});
- },
+ }
- calculate_incentive: function(row) {
+ calculate_incentive(row) {
if(row.allocated_amount)
{
row.incentives = flt(
row.allocated_amount * row.commission_rate / 100.0,
precision("incentives", row));
}
- },
+ }
- batch_no: function(doc, cdt, cdn) {
+ batch_no(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
@@ -312,14 +312,14 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
});
}
})
- },
+ }
- set_dynamic_labels: function() {
- this._super();
+ set_dynamic_labels() {
+ super.set_dynamic_labels();
this.set_product_bundle_help(this.frm.doc);
- },
+ }
- set_product_bundle_help: function(doc) {
+ set_product_bundle_help(doc) {
if(!cur_frm.fields_dict.packing_list) return;
if ((doc.packed_items || []).length) {
$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(true);
@@ -337,9 +337,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
}
}
refresh_field('product_bundle_help');
- },
+ }
- company_address: function() {
+ company_address() {
var me = this;
if(this.frm.doc.company_address) {
frappe.call({
@@ -354,42 +354,42 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
} else {
this.frm.set_value("company_address_display", "");
}
- },
+ }
- conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
- this._super(doc, cdt, cdn, dont_fetch_price_list_rate);
+ 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)) {
if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return;
this.set_batch_number(cdt, cdn);
}
- },
+ }
- batch_no: function(doc, cdt, cdn) {
- this._super(doc, cdt, cdn);
- },
+ batch_no(doc, cdt, cdn) {
+ super.batch_no(doc, cdt, cdn);
+ }
- qty: function(doc, cdt, cdn) {
- this._super(doc, cdt, cdn);
+ qty(doc, cdt, cdn) {
+ super.qty(doc, cdt, cdn);
if(in_list(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
if (doc.doctype === 'Sales Invoice' && (!doc.update_stock)) return;
this.set_batch_number(cdt, cdn);
}
- },
+ }
/* Determine appropriate batch number and set it in the form.
* @param {string} cdt - Document Doctype
* @param {string} cdn - Document name
*/
- set_batch_number: function(cdt, cdn) {
+ set_batch_number(cdt, cdn) {
const doc = frappe.get_doc(cdt, cdn);
if (doc && doc.has_batch_no && doc.warehouse) {
this._set_batch_number(doc);
}
- },
+ }
- _set_batch_number: function(doc) {
+ _set_batch_number(doc) {
let args = {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)};
if (doc.has_serial_no && doc.serial_no) {
args['serial_no'] = doc.serial_no
@@ -406,9 +406,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
}
}
});
- },
+ }
- update_auto_repeat_reference: function(doc) {
+ update_auto_repeat_reference(doc) {
if (doc.auto_repeat) {
frappe.call({
method:"frappe.automation.doctype.auto_repeat.auto_repeat.update_reference",
@@ -426,7 +426,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
})
}
}
-});
+};
frappe.ui.form.on(cur_frm.doctype,"project", function(frm) {
if(in_list(["Delivery Note", "Sales Invoice"], frm.doc.doctype)) {
diff --git a/erpnext/stock/dashboard/item_dashboard.js b/erpnext/stock/dashboard/item_dashboard.js
index 95cb92b1b3..30e0b762bd 100644
--- a/erpnext/stock/dashboard/item_dashboard.js
+++ b/erpnext/stock/dashboard/item_dashboard.js
@@ -1,11 +1,11 @@
frappe.provide('erpnext.stock');
-erpnext.stock.ItemDashboard = Class.extend({
- init: function(opts) {
+erpnext.stock.ItemDashboard = class ItemDashboard {
+ constructor(opts) {
$.extend(this, opts);
this.make();
- },
- make: function() {
+ }
+ make() {
var me = this;
this.start = 0;
if(!this.sort_by) {
@@ -73,8 +73,8 @@ erpnext.stock.ItemDashboard = Class.extend({
me.refresh();
});
- },
- refresh: function() {
+ }
+ refresh() {
if(this.before_refresh) {
this.before_refresh();
}
@@ -98,8 +98,8 @@ erpnext.stock.ItemDashboard = Class.extend({
me.render(r.message);
}
});
- },
- render: function(data) {
+ }
+ render(data) {
if (this.start===0) {
this.max_count = 0;
this.result.empty();
@@ -135,9 +135,9 @@ erpnext.stock.ItemDashboard = Class.extend({
$(`
${message}
`).appendTo(this.result);
}
- },
+ }
- get_item_dashboard_data: function(data, max_count, show_item) {
+ get_item_dashboard_data(data, max_count, show_item) {
if(!max_count) max_count = 0;
if(!data) data = [];
@@ -164,9 +164,9 @@ erpnext.stock.ItemDashboard = Class.extend({
can_write:can_write,
show_item: show_item || false
};
- },
+ }
- get_capacity_dashboard_data: function(data) {
+ get_capacity_dashboard_data(data) {
if (!data) data = [];
data.forEach(function(d) {
@@ -183,7 +183,7 @@ erpnext.stock.ItemDashboard = Class.extend({
can_write: can_write,
};
}
-});
+};
erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callback) {
var dialog = new frappe.ui.Dialog({
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 334bdeac9d..63ea198c59 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -123,17 +123,17 @@ frappe.ui.form.on("Delivery Note Item", {
}
});
-erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend({
- setup: function(doc) {
+erpnext.stock.DeliveryNoteController = class DeliveryNoteController extends erpnext.selling.SellingController {
+ setup(doc) {
this.setup_posting_date_time_check();
- this._super(doc);
+ super.setup(doc);
this.frm.make_methods = {
'Delivery Trip': this.make_delivery_trip,
};
- },
- refresh: function(doc, dt, dn) {
+ }
+ refresh(doc, dt, dn) {
var me = this;
- this._super();
+ super.refresh();
if ((!doc.is_return) && (doc.status!="Closed" || this.frm.is_new())) {
if (this.frm.doc.docstatus===0) {
this.frm.add_custom_button(__('Sales Order'),
@@ -231,64 +231,64 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
erpnext.utils.make_subscription(doc.doctype, doc.name)
}, __('Create'))
}
- },
+ }
- make_shipment: function() {
+ make_shipment() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_shipment",
frm: this.frm
})
- },
+ }
- make_sales_invoice: function() {
+ make_sales_invoice() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice",
frm: this.frm
})
- },
+ }
- make_installation_note: function() {
+ make_installation_note() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_installation_note",
frm: this.frm
});
- },
+ }
- make_sales_return: function() {
+ make_sales_return() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_return",
frm: this.frm
})
- },
+ }
- make_delivery_trip: function() {
+ make_delivery_trip() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_delivery_trip",
frm: cur_frm
})
- },
+ }
- tc_name: function() {
+ tc_name() {
this.get_terms();
- },
+ }
- items_on_form_rendered: function(doc, grid_row) {
+ items_on_form_rendered(doc, grid_row) {
erpnext.setup_serial_no();
- },
+ }
- packed_items_on_form_rendered: function(doc, grid_row) {
+ packed_items_on_form_rendered(doc, grid_row) {
erpnext.setup_serial_no();
- },
+ }
- close_delivery_note: function(doc){
+ close_delivery_note(doc){
this.update_status("Closed")
- },
+ }
- reopen_delivery_note : function() {
+ reopen_delivery_note() {
this.update_status("Submitted")
- },
+ }
- update_status: function(status) {
+ update_status(status) {
var me = this;
frappe.ui.form.is_saving = true;
frappe.call({
@@ -302,8 +302,8 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
frappe.ui.form.is_saving = false;
}
})
- },
-});
+ }
+};
$.extend(cur_frm.cscript, new erpnext.stock.DeliveryNoteController({frm: cur_frm}));
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
index 1abbc35334..433f78adc9 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
@@ -5,8 +5,8 @@
frappe.provide("erpnext.stock");
-erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
- setup: function() {
+erpnext.stock.LandedCostVoucher = class LandedCostVoucher extends erpnext.stock.StockController {
+ setup() {
var me = this;
this.frm.fields_dict.purchase_receipts.grid.get_field('receipt_document').get_query =
function (doc, cdt, cdn) {
@@ -30,9 +30,9 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
this.frm.add_fetch("receipt_document", "supplier", "supplier");
this.frm.add_fetch("receipt_document", "posting_date", "posting_date");
this.frm.add_fetch("receipt_document", "base_grand_total", "grand_total");
- },
+ }
- refresh: function() {
+ refresh() {
var help_content =
`
@@ -67,9 +67,9 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
let company_currency = frappe.get_doc(":Company", this.frm.doc.company).default_currency;
this.frm.set_currency_labels(["total_taxes_and_charges"], company_currency);
}
- },
+ }
- get_items_from_purchase_receipts: function() {
+ get_items_from_purchase_receipts() {
var me = this;
if(!this.frm.doc.purchase_receipts.length) {
frappe.msgprint(__("Please enter Purchase Receipt first"));
@@ -82,22 +82,22 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
}
});
}
- },
+ }
- amount: function(frm) {
+ amount(frm) {
this.set_total_taxes_and_charges();
this.set_applicable_charges_for_item();
- },
+ }
- set_total_taxes_and_charges: function() {
+ set_total_taxes_and_charges() {
var total_taxes_and_charges = 0.0;
$.each(this.frm.doc.taxes || [], function(i, d) {
total_taxes_and_charges += flt(d.base_amount);
});
this.frm.set_value("total_taxes_and_charges", total_taxes_and_charges);
- },
+ }
- set_applicable_charges_for_item: function() {
+ set_applicable_charges_for_item() {
var me = this;
if(this.frm.doc.taxes.length) {
@@ -123,15 +123,15 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
refresh_field("items");
}
}
- },
- distribute_charges_based_on: function (frm) {
+ }
+ distribute_charges_based_on (frm) {
this.set_applicable_charges_for_item();
- },
+ }
- items_remove: () => {
+ items_remove() {
this.trigger('set_applicable_charges_for_item');
}
-});
+};
cur_frm.script_manager.make(erpnext.stock.LandedCostVoucher);
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 527b0d3ea9..86936b4db3 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -403,28 +403,28 @@ frappe.ui.form.on("Material Request Item", {
}
});
-erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.extend({
- tc_name: function() {
+erpnext.buying.MaterialRequestController = class MaterialRequestController extends erpnext.buying.BuyingController {
+ tc_name() {
this.get_terms();
- },
+ }
- item_code: function() {
+ item_code() {
// to override item code trigger from transaction.js
- },
+ }
- validate_company_and_party: function() {
+ validate_company_and_party() {
return true;
- },
+ }
- calculate_taxes_and_totals: function() {
+ calculate_taxes_and_totals() {
return;
- },
+ }
- validate: function() {
+ validate() {
set_schedule_date(this.frm);
- },
+ }
- onload: function(doc, cdt, cdn) {
+ onload(doc, cdt, cdn) {
this.frm.set_query("item_code", "items", function() {
if (doc.material_request_type == "Customer Provided") {
return{
@@ -438,9 +438,9 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
}
}
});
- },
+ }
- items_add: function(doc, cdt, cdn) {
+ items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
if(doc.schedule_date) {
row.schedule_date = doc.schedule_date;
@@ -448,16 +448,16 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
} else {
this.frm.script_manager.copy_from_first_row("items", row, ["schedule_date"]);
}
- },
+ }
- items_on_form_rendered: function() {
- set_schedule_date(this.frm);
- },
-
- schedule_date: function() {
+ items_on_form_rendered() {
set_schedule_date(this.frm);
}
-});
+
+ schedule_date() {
+ set_schedule_date(this.frm);
+ }
+};
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.buying.MaterialRequestController({frm: cur_frm}));
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 57cc3504a9..f87b273d64 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -86,15 +86,15 @@ frappe.ui.form.on("Purchase Receipt", {
}
});
-erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend({
- setup: function(doc) {
+erpnext.stock.PurchaseReceiptController = class PurchaseReceiptController extends erpnext.buying.BuyingController {
+ setup(doc) {
this.setup_posting_date_time_check();
- this._super(doc);
- },
+ super.setup(doc);
+ }
- refresh: function() {
+ refresh() {
var me = this;
- this._super();
+ super.refresh();
if(this.frm.doc.docstatus > 0) {
this.show_stock_ledger();
//removed for temporary
@@ -173,31 +173,31 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
}
this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
- },
+ }
- make_purchase_invoice: function() {
+ make_purchase_invoice() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
frm: cur_frm
})
- },
+ }
- make_purchase_return: function() {
+ make_purchase_return() {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_return",
frm: cur_frm
})
- },
+ }
- close_purchase_receipt: function() {
+ close_purchase_receipt() {
cur_frm.cscript.update_status("Closed");
- },
+ }
- reopen_purchase_receipt: function() {
+ reopen_purchase_receipt() {
cur_frm.cscript.update_status("Submitted");
- },
+ }
- make_retention_stock_entry: function() {
+ make_retention_stock_entry() {
frappe.call({
method: "erpnext.stock.doctype.stock_entry.stock_entry.move_sample_to_retention_warehouse",
args:{
@@ -214,13 +214,13 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
}
}
});
- },
+ }
- apply_putaway_rule: function() {
+ apply_putaway_rule() {
if (this.frm.doc.apply_putaway_rule) erpnext.apply_putaway_rule(this.frm);
}
-});
+};
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.stock.PurchaseReceiptController({frm: cur_frm}));
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 64dcbed1d8..16e74636ce 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -777,8 +777,8 @@ frappe.ui.form.on('Landed Cost Taxes and Charges', {
}
});
-erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
- setup: function() {
+erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockController {
+ setup() {
var me = this;
this.setup_posting_date_time_check();
@@ -825,9 +825,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
frappe.dynamic_link = { doc: this.frm.doc, fieldname: 'supplier', doctype: 'Supplier' }
this.frm.set_query("supplier_address", erpnext.queries.address_query)
- },
+ }
- onload_post_render: function() {
+ onload_post_render() {
var me = this;
this.set_default_account(function() {
if(me.frm.doc.__islocal && me.frm.doc.company && !me.frm.doc.amended_from) {
@@ -836,9 +836,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
});
this.frm.get_field("items").grid.set_multiple_add("item_code", "qty");
- },
+ }
- refresh: function() {
+ refresh() {
var me = this;
erpnext.toggle_naming_series();
this.toggle_related_fields(this.frm.doc);
@@ -850,22 +850,22 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
erpnext.hide_company();
erpnext.utils.add_item(this.frm);
this.frm.trigger('add_to_transit');
- },
+ }
- scan_barcode: function() {
+ scan_barcode() {
let transaction_controller= new erpnext.TransactionController({frm:this.frm});
transaction_controller.scan_barcode();
- },
+ }
- on_submit: function() {
+ on_submit() {
this.clean_up();
- },
+ }
- after_cancel: function() {
+ after_cancel() {
this.clean_up();
- },
+ }
- set_default_account: function(callback) {
+ set_default_account(callback) {
var me = this;
if(this.frm.doc.company && erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
@@ -885,9 +885,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
}
});
}
- },
+ }
- clean_up: function() {
+ clean_up() {
// Clear Work Order record from locals, because it is updated via Stock Entry
if(this.frm.doc.work_order &&
in_list(["Manufacture", "Material Transfer for Manufacture", "Material Consumption for Manufacture"],
@@ -895,13 +895,13 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
frappe.model.remove_from_locals("Work Order",
this.frm.doc.work_order);
}
- },
+ }
- fg_completed_qty: function() {
+ fg_completed_qty() {
this.get_items();
- },
+ }
- get_items: function() {
+ get_items() {
var me = this;
if(!this.frm.doc.fg_completed_qty || !this.frm.doc.bom_no)
frappe.throw(__("BOM and Manufacturing Quantity are required"));
@@ -917,9 +917,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
}
});
}
- },
+ }
- work_order: function() {
+ work_order() {
var me = this;
this.toggle_enable_bom();
if(!me.frm.doc.work_order || me.frm.doc.job_card) {
@@ -952,13 +952,13 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
}
}
});
- },
+ }
- toggle_enable_bom: function() {
+ toggle_enable_bom() {
this.frm.toggle_enable("bom_no", !!!this.frm.doc.work_order);
- },
+ }
- add_excise_button: function() {
+ add_excise_button() {
if(frappe.boot.sysdefaults.country === "India")
this.frm.add_custom_button(__("Excise Invoice"), function() {
var excise = frappe.model.make_new_doc_and_get_name('Journal Entry');
@@ -966,35 +966,35 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
excise.voucher_type = 'Excise Entry';
frappe.set_route('Form', 'Journal Entry', excise.name);
}, __('Create'));
- },
+ }
- items_add: function(doc, cdt, cdn) {
+ items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]);
if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse;
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
- },
+ }
- from_warehouse: function(doc) {
+ from_warehouse(doc) {
this.frm.trigger('set_tansit_warehouse');
this.set_warehouse_in_children(doc.items, "s_warehouse", doc.from_warehouse);
- },
+ }
- to_warehouse: function(doc) {
+ to_warehouse(doc) {
this.set_warehouse_in_children(doc.items, "t_warehouse", doc.to_warehouse);
- },
+ }
- set_warehouse_in_children: function(child_table, warehouse_field, warehouse) {
+ set_warehouse_in_children(child_table, warehouse_field, warehouse) {
let transaction_controller = new erpnext.TransactionController();
transaction_controller.autofill_warehouse(child_table, warehouse_field, warehouse);
- },
+ }
- items_on_form_rendered: function(doc, grid_row) {
+ items_on_form_rendered(doc, grid_row) {
erpnext.setup_serial_no();
- },
+ }
- toggle_related_fields: function(doc) {
+ toggle_related_fields(doc) {
this.frm.toggle_enable("from_warehouse", doc.purpose!='Material Receipt');
this.frm.toggle_enable("to_warehouse", doc.purpose!='Material Issue');
@@ -1021,12 +1021,12 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
doc.purpose!='Material Issue');
this.frm.fields_dict["items"].grid.set_column_disp("additional_cost", doc.purpose!='Material Issue');
- },
+ }
- supplier: function(doc) {
+ supplier(doc) {
erpnext.utils.get_party_details(this.frm, null, null, null);
}
-});
+};
erpnext.stock.select_batch_and_serial_no = (frm, item) => {
let get_warehouse_type_and_name = (item) => {
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index ac4ed5e75d..3badc7ee60 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
@@ -220,8 +220,8 @@ frappe.ui.form.on("Stock Reconciliation Item", {
});
-erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
- setup: function() {
+erpnext.stock.StockReconciliation = class StockReconciliation extends erpnext.stock.StockController {
+ setup() {
var me = this;
this.setup_posting_date_time_check();
@@ -249,17 +249,17 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
}
}
}
- },
+ }
- refresh: function() {
+ refresh() {
if(this.frm.doc.docstatus > 0) {
this.show_stock_ledger();
if (erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
this.show_general_ledger();
}
}
- },
+ }
-});
+};
cur_frm.cscript = new erpnext.stock.StockReconciliation({frm: cur_frm});
diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.js b/erpnext/support/doctype/warranty_claim/warranty_claim.js
index 79f46758d1..c9aa41fdae 100644
--- a/erpnext/support/doctype/warranty_claim/warranty_claim.js
+++ b/erpnext/support/doctype/warranty_claim/warranty_claim.js
@@ -36,8 +36,8 @@ frappe.ui.form.on("Warranty Claim", {
}
});
-erpnext.support.WarrantyClaim = frappe.ui.form.Controller.extend({
- refresh: function() {
+erpnext.support.WarrantyClaim = class WarrantyClaim extends frappe.ui.form.Controller {
+ refresh() {
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
if(!cur_frm.doc.__islocal &&
@@ -45,15 +45,15 @@ erpnext.support.WarrantyClaim = frappe.ui.form.Controller.extend({
cur_frm.add_custom_button(__('Maintenance Visit'),
this.make_maintenance_visit);
}
- },
+ }
- make_maintenance_visit: function() {
+ make_maintenance_visit() {
frappe.model.open_mapped_doc({
method: "erpnext.support.doctype.warranty_claim.warranty_claim.make_maintenance_visit",
frm: cur_frm
})
}
-});
+};
$.extend(cur_frm.cscript, new erpnext.support.WarrantyClaim({frm: cur_frm}));
diff --git a/erpnext/templates/includes/rfq.js b/erpnext/templates/includes/rfq.js
index b56c416dbd..37beb5a584 100644
--- a/erpnext/templates/includes/rfq.js
+++ b/erpnext/templates/includes/rfq.js
@@ -11,23 +11,23 @@ $(document).ready(function() {
doc.buying_price_list = "{{ doc.buying_price_list }}"
});
-rfq = Class.extend({
- init: function(){
+rfq = class rfq {
+ constructor(){
this.onfocus_select_all();
this.change_qty();
this.change_rate();
this.terms();
this.submit_rfq();
this.navigate_quotations();
- },
+ }
- onfocus_select_all: function(){
+ onfocus_select_all(){
$("input").click(function(){
$(this).select();
})
- },
+ }
- change_qty: function(){
+ change_qty(){
var me = this;
$('.rfq-items').on("change", ".rfq-qty", function(){
me.idx = parseFloat($(this).attr('data-idx'));
@@ -36,9 +36,9 @@ rfq = Class.extend({
me.update_qty_rate();
$(this).val(format_number(me.qty, doc.number_format, 2));
})
- },
+ }
- change_rate: function(){
+ change_rate(){
var me = this;
$(".rfq-items").on("change", ".rfq-rate", function(){
me.idx = parseFloat($(this).attr('data-idx'));
@@ -47,15 +47,15 @@ rfq = Class.extend({
me.update_qty_rate();
$(this).val(format_number(me.rate, doc.number_format, 2));
})
- },
+ }
- terms: function(){
+ terms(){
$(".terms").on("change", ".terms-feedback", function(){
doc.terms = $(this).val();
})
- },
+ }
- update_qty_rate: function(){
+ update_qty_rate(){
var me = this;
doc.grand_total = 0.0;
$.each(doc.items, function(idx, data){
@@ -69,9 +69,9 @@ rfq = Class.extend({
doc.grand_total += flt(data.amount);
$('.tax-grand-total').text(format_number(doc.grand_total, doc.number_format, 2));
})
- },
+ }
- submit_rfq: function(){
+ submit_rfq(){
$('.btn-sm').click(function(){
frappe.freeze();
frappe.call({
@@ -90,12 +90,12 @@ rfq = Class.extend({
}
})
})
- },
+ }
- navigate_quotations: function() {
+ navigate_quotations() {
$('.quotations').click(function(){
name = $(this).attr('idx')
window.location.href = "/quotations/" + encodeURIComponent(name);
})
}
-})
+}
From 16da87a307178da1a179b7f9a4a5726467e8b2b6 Mon Sep 17 00:00:00 2001
From: Anurag Mishra
Date: Tue, 4 May 2021 17:05:42 +0530
Subject: [PATCH 002/262] fix: created new section for deatils
---
.../employee_referral/employee_referral.json | 21 ++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/erpnext/hr/doctype/employee_referral/employee_referral.json b/erpnext/hr/doctype/employee_referral/employee_referral.json
index bfd404b435..3ae73a9e4d 100644
--- a/erpnext/hr/doctype/employee_referral/employee_referral.json
+++ b/erpnext/hr/doctype/employee_referral/employee_referral.json
@@ -9,16 +9,18 @@
"first_name",
"last_name",
"full_name",
- "email",
- "contact_no",
- "resume",
- "resume_link",
"column_break_6",
"date",
"status",
"for_designation",
+ "referral_details_section",
+ "email",
+ "contact_no",
+ "resume_link",
+ "column_break_12",
"current_employer",
"current_job_title",
+ "resume",
"referrer_details_section",
"referrer",
"referrer_name",
@@ -189,12 +191,21 @@
"label": "Referral Bonus Payment Status",
"options": "\nUnpaid\nPaid",
"read_only": 1
+ },
+ {
+ "fieldname": "referral_details_section",
+ "fieldtype": "Section Break",
+ "label": "Referral Details"
+ },
+ {
+ "fieldname": "column_break_12",
+ "fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-26 21:21:38.094086",
+ "modified": "2021-05-04 17:03:26.134560",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Referral",
From cd8ee8ea97bcf899e23438991fed1bdfd540a490 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Tue, 4 May 2021 18:36:45 +0530
Subject: [PATCH 003/262] ci: Try Parallel tests
---
.github/helper/install.sh | 2 +-
.github/workflows/ci-tests.yml | 55 ++++++++++++++++++----------------
2 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index 7b0f944c66..fd32624c2d 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -12,7 +12,7 @@ sudo apt install npm
pip install frappe-bench
-git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1
+git clone https://github.com/surajshetty3416/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
mkdir ~/frappe-bench/sites/test_site
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 84ecfb1457..de8d7ac503 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -13,7 +13,10 @@ jobs:
include:
- TYPE: "server"
JOB_NAME: "Server"
- RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-tests --app erpnext --coverage
+ RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
+ - TYPE: "server"
+ JOB_NAME: "Server"
+ RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- TYPE: "patch"
JOB_NAME: "Patch"
RUN_COMMAND: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
@@ -80,29 +83,29 @@ jobs:
env:
TYPE: ${{ matrix.TYPE }}
- - name: Coverage - Pull Request
- if: matrix.TYPE == 'server' && github.event_name == 'pull_request'
- run: |
- cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
- cd ${GITHUB_WORKSPACE}
- pip install coveralls==2.2.0
- pip install coverage==4.5.4
- coveralls --service=github
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
- COVERALLS_SERVICE_NAME: github
-
- - name: Coverage - Push
- if: matrix.TYPE == 'server' && github.event_name == 'push'
- run: |
- cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
- cd ${GITHUB_WORKSPACE}
- pip install coveralls==2.2.0
- pip install coverage==4.5.4
- coveralls --service=github-actions
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
- COVERALLS_SERVICE_NAME: github-actions
+ # - name: Coverage - Pull Request
+ # if: matrix.TYPE == 'server' && github.event_name == 'pull_request'
+ # run: |
+ # cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
+ # cd ${GITHUB_WORKSPACE}
+ # pip install coveralls==2.2.0
+ # pip install coverage==4.5.4
+ # coveralls --service=github
+ # env:
+ # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
+ # COVERALLS_SERVICE_NAME: github
+
+ # - name: Coverage - Push
+ # if: matrix.TYPE == 'server' && github.event_name == 'push'
+ # run: |
+ # cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
+ # cd ${GITHUB_WORKSPACE}
+ # pip install coveralls==2.2.0
+ # pip install coverage==4.5.4
+ # coveralls --service=github-actions
+ # env:
+ # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
+ # COVERALLS_SERVICE_NAME: github-actions
From ee35444c3fc029e3032befaebda61925248a53f7 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Tue, 4 May 2021 18:58:20 +0530
Subject: [PATCH 004/262] fix: Frappe branch
---
.github/helper/install.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index fd32624c2d..44659f22fa 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -12,7 +12,7 @@ sudo apt install npm
pip install frappe-bench
-git clone https://github.com/surajshetty3416/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1
+git clone https://github.com/surajshetty3416/frappe --branch "python-distributed-testing" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
mkdir ~/frappe-bench/sites/test_site
From 05f9df6c10bb85ab3973893e39b953ef67579015 Mon Sep 17 00:00:00 2001
From: Hendy Irawan
Date: Tue, 4 May 2021 13:32:16 +0000
Subject: [PATCH 005/262] fix(accounts): Get balance for Profit and Loss
accounts, only including valid transactions (not cancelled)
Fixed #25572 Period Closing Voucher incorrect journal entry amount for
Income/Expenses Accounts containing canceled transactions.
---
.../doctype/period_closing_voucher/period_closing_voucher.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
index a74fa062b6..fdb4f6fc71 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
@@ -102,14 +102,14 @@ class PeriodClosingVoucher(AccountsController):
make_gl_entries(gl_entries)
def get_pl_balances(self, dimension_fields):
- """Get balance for pl accounts"""
+ """Get balance for Profit and Loss accounts, only including valid transactions (not cancelled)"""
return frappe.db.sql("""
select
t1.account, t2.account_currency, {dimension_fields},
sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as balance_in_account_currency,
sum(t1.debit) - sum(t1.credit) as balance_in_company_currency
from `tabGL Entry` t1, `tabAccount` t2
- where t1.account = t2.name and t2.report_type = 'Profit and Loss'
+ where t1.is_cancelled = 0 and t1.account = t2.name and t2.report_type = 'Profit and Loss'
and t2.docstatus < 2 and t2.company = %s
and t1.posting_date between %s and %s
group by t1.account, {dimension_fields}
From c432766a70a3fa66ec33e0a0c770b77f87bf8806 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Wed, 5 May 2021 10:16:21 +0530
Subject: [PATCH 006/262] fix: stock reconciliation getting time out error
during submission
---
.../stock/doctype/stock_reconciliation/stock_reconciliation.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 0ee6dc7877..7c5f4ece0b 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -469,7 +469,7 @@ class StockReconciliation(StockController):
def submit(self):
if len(self.items) > 100:
msgprint(_("The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Reconciliation and revert to the Draft stage"))
- self.queue_action('submit', timeout=2000)
+ self.queue_action('submit', timeout=4600)
else:
self._submit()
From 60f3e9ee2930001f8007a09f5b1383589f01c481 Mon Sep 17 00:00:00 2001
From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com>
Date: Wed, 5 May 2021 13:23:42 +0530
Subject: [PATCH 007/262] fix: default value for Templates (#25591)
---
erpnext/hr/doctype/hr_settings/hr_settings.json | 4 +++-
erpnext/payroll/doctype/salary_slip/salary_slip.json | 4 ++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json
index 3db6c239ef..48cef04a8d 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.json
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.json
@@ -71,6 +71,7 @@
"label": "Leave Settings"
},
{
+ "default": "Leave Approval Notification",
"depends_on": "eval: doc.send_leave_notification == 1",
"fieldname": "leave_approval_notification_template",
"fieldtype": "Link",
@@ -79,6 +80,7 @@
"options": "Email Template"
},
{
+ "default": "Leave Status Notification",
"depends_on": "eval: doc.send_leave_notification == 1",
"fieldname": "leave_status_notification_template",
"fieldtype": "Link",
@@ -155,7 +157,7 @@
"idx": 1,
"issingle": 1,
"links": [],
- "modified": "2021-04-26 10:52:56.192773",
+ "modified": "2021-05-05 12:25:24.082705",
"modified_by": "Administrator",
"module": "HR",
"name": "HR Settings",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 42a0f290cb..27409ccff2 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -423,7 +423,7 @@
{
"fieldname": "net_pay_info",
"fieldtype": "Section Break",
- "label": "net pay info"
+ "label": "Net Pay Info"
},
{
"fieldname": "net_pay",
@@ -631,7 +631,7 @@
"idx": 9,
"is_submittable": 1,
"links": [],
- "modified": "2021-03-31 22:44:09.772331",
+ "modified": "2021-05-05 12:21:27.836273",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Slip",
From c981969446d82b7aa67fdc8a80b630b8c8ef5f49 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 6 May 2021 13:04:12 +0530
Subject: [PATCH 008/262] test: Fix dependency
---
erpnext/tests/__init__.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/erpnext/tests/__init__.py b/erpnext/tests/__init__.py
index e69de29bb2..dcc4f5336d 100644
--- a/erpnext/tests/__init__.py
+++ b/erpnext/tests/__init__.py
@@ -0,0 +1 @@
+global_test_dependencies = ['User', 'Company']
From af4af7737f7bd3d227487a5ac9a34da03e840e28 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 6 May 2021 13:05:03 +0530
Subject: [PATCH 009/262] chore: Debug
---
.github/workflows/ci-tests.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index de8d7ac503..7373c1efa6 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -1,6 +1,6 @@
name: CI
-on: [pull_request, workflow_dispatch, push]
+on: [pull_request, workflow_dispatch]
jobs:
test:
From 5f7546d876e778c4b0c700a2be78c0f7b4badf68 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 6 May 2021 15:13:09 +0530
Subject: [PATCH 010/262] chore: Debug
---
.github/workflows/ci-tests.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index 7373c1efa6..b03aad794b 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -17,6 +17,9 @@ jobs:
- TYPE: "server"
JOB_NAME: "Server"
RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
+ - TYPE: "server"
+ JOB_NAME: "Server"
+ RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- TYPE: "patch"
JOB_NAME: "Patch"
RUN_COMMAND: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
From a0ed517c85a7585b75d158cd9194696c9ab168db Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 4 May 2021 21:01:12 +0530
Subject: [PATCH 011/262] fix: function call to update payment schedule labels
---
erpnext/public/js/controllers/transaction.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index a2b95cb757..2ac2c46eac 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1384,7 +1384,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
company_currency, "payment_schedule");
this.frm.set_currency_labels(["payment_amount", "outstanding", "paid_amount"],
this.frm.doc.currency, "payment_schedule");
-
+
var schedule_grid = this.frm.fields_dict["payment_schedule"].grid;
$.each(["base_payment_amount", "base_outstanding", "base_paid_amount"], function(i, fname) {
if (frappe.meta.get_docfield(schedule_grid.doctype, fname))
@@ -2034,7 +2034,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(r.message && !r.exc) {
me.frm.set_value("payment_schedule", r.message);
const company_currency = me.get_company_currency();
- this.update_payment_schedule_grid_labels(company_currency);
+ me.update_payment_schedule_grid_labels(company_currency);
}
}
})
From be66ee9723fa01fd213809c9ddf76daf8ad2d1a5 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 5 May 2021 12:19:57 +0530
Subject: [PATCH 012/262] fix: Check if payment schedule exits before updating
label
---
erpnext/public/js/controllers/transaction.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 2ac2c46eac..9f1ea19b08 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1379,7 +1379,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
update_payment_schedule_grid_labels: function(company_currency) {
const me = this;
- if (this.frm.fields_dict["payment_schedule"]) {
+ if (this.frm.doc.payment_schedule.length > 0) {
this.frm.set_currency_labels(["base_payment_amount", "base_outstanding", "base_paid_amount"],
company_currency, "payment_schedule");
this.frm.set_currency_labels(["payment_amount", "outstanding", "paid_amount"],
From daf6c124a98e426fe300f9f0c34f3f1dc78d116c Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 5 May 2021 12:28:40 +0530
Subject: [PATCH 013/262] fix: Check if payment schedule exists
---
erpnext/public/js/controllers/transaction.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 9f1ea19b08..121e9d0cf0 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1379,7 +1379,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
update_payment_schedule_grid_labels: function(company_currency) {
const me = this;
- if (this.frm.doc.payment_schedule.length > 0) {
+ if (this.frm.doc.payment_schedule && this.frm.doc.payment_schedule.length > 0) {
this.frm.set_currency_labels(["base_payment_amount", "base_outstanding", "base_paid_amount"],
company_currency, "payment_schedule");
this.frm.set_currency_labels(["payment_amount", "outstanding", "paid_amount"],
From 92cefd565568cf3e24c49f079696d55281071ea3 Mon Sep 17 00:00:00 2001
From: Saqib
Date: Thu, 6 May 2021 17:03:16 +0530
Subject: [PATCH 014/262] feat(pos): ability to retry on pos closing failure
(#25604)
* feat(pos): ability to retry on pos closing failure
* fix: sider issues
* fix: sider issues
* fix: mark all queued closing entry as failed
* feat: add headline message
---
.../pos_closing_entry/pos_closing_entry.js | 104 ++++++++++--------
.../pos_closing_entry/pos_closing_entry.json | 21 +++-
.../pos_closing_entry/pos_closing_entry.py | 4 +
.../pos_closing_entry_list.js | 1 +
.../pos_invoice_merge_log.py | 87 +++++++++++----
erpnext/controllers/status_updater.py | 1 +
erpnext/patches.txt | 1 +
.../v13_0/set_pos_closing_as_failed.py | 7 ++
8 files changed, 158 insertions(+), 68 deletions(-)
create mode 100644 erpnext/patches/v13_0/set_pos_closing_as_failed.py
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
index 9ea616f8e7..aa0c53e228 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
@@ -22,7 +22,43 @@ frappe.ui.form.on('POS Closing Entry', {
});
if (frm.doc.docstatus === 0 && !frm.doc.amended_from) frm.set_value("period_end_date", frappe.datetime.now_datetime());
- if (frm.doc.docstatus === 1) set_html_data(frm);
+
+ frappe.realtime.on('closing_process_complete', async function(data) {
+ await frm.reload_doc();
+ if (frm.doc.status == 'Failed' && frm.doc.error_message && data.user == frappe.session.user) {
+ frappe.msgprint({
+ title: __('POS Closing Failed'),
+ message: frm.doc.error_message,
+ indicator: 'orange',
+ clear: true
+ });
+ }
+ });
+
+ set_html_data(frm);
+ },
+
+ refresh: function(frm) {
+ if (frm.doc.docstatus == 1 && frm.doc.status == 'Failed') {
+ const issue = 'issue';
+ frm.dashboard.set_headline(
+ __('POS Closing failed while running in a background process. You can resolve the {0} and retry the process again.', [issue]));
+
+ $('#jump_to_error').on('click', (e) => {
+ e.preventDefault();
+ frappe.utils.scroll_to(
+ cur_frm.get_field("error_message").$wrapper,
+ true,
+ 30
+ );
+ });
+
+ frm.add_custom_button(__('Retry'), function () {
+ frm.call('retry', {}, () => {
+ frm.reload_doc();
+ });
+ });
+ }
},
pos_opening_entry(frm) {
@@ -61,44 +97,24 @@ frappe.ui.form.on('POS Closing Entry', {
refresh_fields(frm);
set_html_data(frm);
}
- })
+ });
+ },
+
+ before_save: function(frm) {
+ for (let row of frm.doc.pos_transactions) {
+ frappe.db.get_doc("POS Invoice", row.pos_invoice).then(doc => {
+ cur_frm.doc.grand_total -= flt(doc.grand_total);
+ cur_frm.doc.net_total -= flt(doc.net_total);
+ cur_frm.doc.total_quantity -= flt(doc.total_qty);
+ refresh_payments(doc, cur_frm, 1);
+ refresh_taxes(doc, cur_frm, 1);
+ refresh_fields(cur_frm);
+ set_html_data(cur_frm);
+ });
+ }
}
});
-cur_frm.cscript.before_pos_transactions_remove = function(doc, cdt, cdn) {
- const removed_row = locals[cdt][cdn];
-
- if (!removed_row.pos_invoice) return;
-
- frappe.db.get_doc("POS Invoice", removed_row.pos_invoice).then(doc => {
- cur_frm.doc.grand_total -= flt(doc.grand_total);
- cur_frm.doc.net_total -= flt(doc.net_total);
- cur_frm.doc.total_quantity -= flt(doc.total_qty);
- refresh_payments(doc, cur_frm, 1);
- refresh_taxes(doc, cur_frm, 1);
- refresh_fields(cur_frm);
- set_html_data(cur_frm);
- });
-}
-
-frappe.ui.form.on('POS Invoice Reference', {
- pos_invoice(frm, cdt, cdn) {
- const added_row = locals[cdt][cdn];
-
- if (!added_row.pos_invoice) return;
-
- frappe.db.get_doc("POS Invoice", added_row.pos_invoice).then(doc => {
- frm.doc.grand_total += flt(doc.grand_total);
- frm.doc.net_total += flt(doc.net_total);
- frm.doc.total_quantity += flt(doc.total_qty);
- refresh_payments(doc, frm);
- refresh_taxes(doc, frm);
- refresh_fields(frm);
- set_html_data(frm);
- });
- }
-})
-
frappe.ui.form.on('POS Closing Entry Detail', {
closing_amount: (frm, cdt, cdn) => {
const row = locals[cdt][cdn];
@@ -177,11 +193,13 @@ function refresh_fields(frm) {
}
function set_html_data(frm) {
- frappe.call({
- method: "get_payment_reconciliation_details",
- doc: frm.doc,
- callback: (r) => {
- frm.get_field("payment_reconciliation_details").$wrapper.html(r.message);
- }
- })
+ if (frm.doc.docstatus === 1 && frm.doc.status == 'Submitted') {
+ frappe.call({
+ method: "get_payment_reconciliation_details",
+ doc: frm.doc,
+ callback: (r) => {
+ frm.get_field("payment_reconciliation_details").$wrapper.html(r.message);
+ }
+ });
+ }
}
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
index a9b91e02a9..4d6e4a2ba0 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
@@ -30,6 +30,8 @@
"total_quantity",
"column_break_16",
"taxes",
+ "failure_description_section",
+ "error_message",
"section_break_14",
"amended_from"
],
@@ -195,7 +197,7 @@
"fieldtype": "Select",
"hidden": 1,
"label": "Status",
- "options": "Draft\nSubmitted\nQueued\nCancelled",
+ "options": "Draft\nSubmitted\nQueued\nFailed\nCancelled",
"print_hide": 1,
"read_only": 1
},
@@ -203,6 +205,21 @@
"fieldname": "period_details_section",
"fieldtype": "Section Break",
"label": "Period Details"
+ },
+ {
+ "collapsible": 1,
+ "collapsible_depends_on": "error_message",
+ "depends_on": "error_message",
+ "fieldname": "failure_description_section",
+ "fieldtype": "Section Break",
+ "label": "Failure Description"
+ },
+ {
+ "depends_on": "error_message",
+ "fieldname": "error_message",
+ "fieldtype": "Small Text",
+ "label": "Error",
+ "read_only": 1
}
],
"is_submittable": 1,
@@ -212,7 +229,7 @@
"link_fieldname": "pos_closing_entry"
}
],
- "modified": "2021-02-01 13:47:20.722104",
+ "modified": "2021-05-05 16:59:49.723261",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Closing Entry",
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
index 1065168a50..82528728dd 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.py
@@ -60,6 +60,10 @@ class POSClosingEntry(StatusUpdater):
def on_cancel(self):
unconsolidate_pos_invoices(closing_entry=self)
+ @frappe.whitelist()
+ def retry(self):
+ consolidate_pos_invoices(closing_entry=self)
+
def update_opening_entry(self, for_cancel=False):
opening_entry = frappe.get_doc("POS Opening Entry", self.pos_opening_entry)
opening_entry.pos_closing_entry = self.name if not for_cancel else None
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry_list.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry_list.js
index 20fd610899..cffeb4d535 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry_list.js
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry_list.js
@@ -8,6 +8,7 @@ frappe.listview_settings['POS Closing Entry'] = {
"Draft": "red",
"Submitted": "blue",
"Queued": "orange",
+ "Failed": "red",
"Cancelled": "red"
};
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
index 4d5472df4b..bc7874305c 100644
--- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
@@ -13,8 +13,7 @@ from frappe.model.mapper import map_doc, map_child_doc
from frappe.utils.scheduler import is_scheduler_inactive
from frappe.core.page.background_jobs.background_jobs import get_info
import json
-
-from six import iteritems
+import six
class POSInvoiceMergeLog(Document):
def validate(self):
@@ -239,7 +238,7 @@ def consolidate_pos_invoices(pos_invoices=None, closing_entry=None):
invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) or get_all_unconsolidated_invoices()
invoice_by_customer = get_invoice_customer_map(invoices)
- if len(invoices) >= 1 and closing_entry:
+ if len(invoices) >= 10 and closing_entry:
closing_entry.set_status(update=True, status='Queued')
enqueue_job(create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry)
else:
@@ -252,36 +251,68 @@ def unconsolidate_pos_invoices(closing_entry):
pluck='name'
)
- if len(merge_logs) >= 1:
+ if len(merge_logs) >= 10:
closing_entry.set_status(update=True, status='Queued')
enqueue_job(cancel_merge_logs, merge_logs=merge_logs, closing_entry=closing_entry)
else:
cancel_merge_logs(merge_logs, closing_entry)
def create_merge_logs(invoice_by_customer, closing_entry=None):
- for customer, invoices in iteritems(invoice_by_customer):
- merge_log = frappe.new_doc('POS Invoice Merge Log')
- merge_log.posting_date = getdate(closing_entry.get('posting_date')) if closing_entry else nowdate()
- merge_log.customer = customer
- merge_log.pos_closing_entry = closing_entry.get('name') if closing_entry else None
+ try:
+ for customer, invoices in six.iteritems(invoice_by_customer):
+ merge_log = frappe.new_doc('POS Invoice Merge Log')
+ merge_log.posting_date = getdate(closing_entry.get('posting_date')) if closing_entry else nowdate()
+ merge_log.customer = customer
+ merge_log.pos_closing_entry = closing_entry.get('name') if closing_entry else None
- merge_log.set('pos_invoices', invoices)
- merge_log.save(ignore_permissions=True)
- merge_log.submit()
+ merge_log.set('pos_invoices', invoices)
+ merge_log.save(ignore_permissions=True)
+ merge_log.submit()
- if closing_entry:
- closing_entry.set_status(update=True, status='Submitted')
- closing_entry.update_opening_entry()
+ if closing_entry:
+ closing_entry.set_status(update=True, status='Submitted')
+ closing_entry.db_set('error_message', '')
+ closing_entry.update_opening_entry()
+
+ except Exception:
+ frappe.db.rollback()
+ message_log = frappe.message_log.pop()
+ error_message = safe_load_json(message_log)
+
+ if closing_entry:
+ closing_entry.set_status(update=True, status='Failed')
+ closing_entry.db_set('error_message', error_message)
+ raise
+
+ finally:
+ frappe.db.commit()
+ frappe.publish_realtime('closing_process_complete', {'user': frappe.session.user})
def cancel_merge_logs(merge_logs, closing_entry=None):
- for log in merge_logs:
- merge_log = frappe.get_doc('POS Invoice Merge Log', log)
- merge_log.flags.ignore_permissions = True
- merge_log.cancel()
+ try:
+ for log in merge_logs:
+ merge_log = frappe.get_doc('POS Invoice Merge Log', log)
+ merge_log.flags.ignore_permissions = True
+ merge_log.cancel()
- if closing_entry:
- closing_entry.set_status(update=True, status='Cancelled')
- closing_entry.update_opening_entry(for_cancel=True)
+ if closing_entry:
+ closing_entry.set_status(update=True, status='Cancelled')
+ closing_entry.db_set('error_message', '')
+ closing_entry.update_opening_entry(for_cancel=True)
+
+ except Exception:
+ frappe.db.rollback()
+ message_log = frappe.message_log.pop()
+ error_message = safe_load_json(message_log)
+
+ if closing_entry:
+ closing_entry.set_status(update=True, status='Submitted')
+ closing_entry.db_set('error_message', error_message)
+ raise
+
+ finally:
+ frappe.db.commit()
+ frappe.publish_realtime('closing_process_complete', {'user': frappe.session.user})
def enqueue_job(job, **kwargs):
check_scheduler_status()
@@ -314,4 +345,14 @@ def check_scheduler_status():
def job_already_enqueued(job_name):
enqueued_jobs = [d.get("job_name") for d in get_info()]
if job_name in enqueued_jobs:
- return True
\ No newline at end of file
+ return True
+
+def safe_load_json(message):
+ JSONDecodeError = ValueError if six.PY2 else json.JSONDecodeError
+
+ try:
+ json_message = json.loads(message).get('message')
+ except JSONDecodeError:
+ json_message = message
+
+ return json_message
\ No newline at end of file
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 5276da9720..4bb6138e5d 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -98,6 +98,7 @@ status_map = {
["Draft", None],
["Submitted", "eval:self.docstatus == 1"],
["Queued", "eval:self.status == 'Queued'"],
+ ["Failed", "eval:self.status == 'Failed'"],
["Cancelled", "eval:self.docstatus == 2"],
]
}
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index de9f6e31f8..9ef949c2c7 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -774,3 +774,4 @@ erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing
erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021
erpnext.patches.v13_0.update_shipment_status
erpnext.patches.v13_0.remove_attribute_field_from_item_variant_setting
+erpnext.patches.v13_0.set_pos_closing_as_failed
diff --git a/erpnext/patches/v13_0/set_pos_closing_as_failed.py b/erpnext/patches/v13_0/set_pos_closing_as_failed.py
new file mode 100644
index 0000000000..1c576db1c7
--- /dev/null
+++ b/erpnext/patches/v13_0/set_pos_closing_as_failed.py
@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+import frappe
+
+def execute():
+ frappe.reload_doc('accounts', 'doctype', 'pos_closing_entry')
+
+ frappe.db.sql("update `tabPOS Closing Entry` set `status` = 'Failed' where `status` = 'Queued'")
\ No newline at end of file
From c5430afe2d77e30544460f555611b92df3de4fca Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 6 May 2021 17:44:26 +0530
Subject: [PATCH 015/262] test: Fix test_dependencies
---
erpnext/accounts/doctype/budget/test_budget.py | 2 ++
erpnext/education/doctype/fees/test_fees.py | 3 +--
erpnext/tests/__init__.py | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/erpnext/accounts/doctype/budget/test_budget.py b/erpnext/accounts/doctype/budget/test_budget.py
index c5ec23c829..603e21ea24 100644
--- a/erpnext/accounts/doctype/budget/test_budget.py
+++ b/erpnext/accounts/doctype/budget/test_budget.py
@@ -11,6 +11,8 @@ from erpnext.buying.doctype.purchase_order.test_purchase_order import create_pur
from erpnext.accounts.doctype.budget.budget import get_actual_expense, BudgetError
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
+test_dependencies = ['Monthly Distribution']
+
class TestBudget(unittest.TestCase):
def test_monthly_budget_crossed_ignore(self):
set_total_expense_zero(nowdate(), "cost_center")
diff --git a/erpnext/education/doctype/fees/test_fees.py b/erpnext/education/doctype/fees/test_fees.py
index eedc2ae730..c6bb704b41 100644
--- a/erpnext/education/doctype/fees/test_fees.py
+++ b/erpnext/education/doctype/fees/test_fees.py
@@ -9,8 +9,7 @@ from frappe.utils import nowdate
from frappe.utils.make_random import get_random
from erpnext.education.doctype.program.test_program import make_program_and_linked_courses
-# test_records = frappe.get_test_records('Fees')
-
+test_dependencies = ['Company']
class TestFees(unittest.TestCase):
def test_fees(self):
diff --git a/erpnext/tests/__init__.py b/erpnext/tests/__init__.py
index dcc4f5336d..593bc7c71b 100644
--- a/erpnext/tests/__init__.py
+++ b/erpnext/tests/__init__.py
@@ -1 +1 @@
-global_test_dependencies = ['User', 'Company']
+global_test_dependencies = ['User', 'Company', 'Cost Center', 'Account', 'Warehouse', 'Item']
From 80c5c866dbecbb17ab5aa943d506612d640e3453 Mon Sep 17 00:00:00 2001
From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com>
Date: Thu, 6 May 2021 17:45:58 +0530
Subject: [PATCH 016/262] Revert "fix: default value for Templates (#25591)"
(#25608)
This reverts commit 60f3e9ee2930001f8007a09f5b1383589f01c481.
---
erpnext/hr/doctype/hr_settings/hr_settings.json | 4 +---
erpnext/payroll/doctype/salary_slip/salary_slip.json | 4 ++--
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/erpnext/hr/doctype/hr_settings/hr_settings.json b/erpnext/hr/doctype/hr_settings/hr_settings.json
index 48cef04a8d..3db6c239ef 100644
--- a/erpnext/hr/doctype/hr_settings/hr_settings.json
+++ b/erpnext/hr/doctype/hr_settings/hr_settings.json
@@ -71,7 +71,6 @@
"label": "Leave Settings"
},
{
- "default": "Leave Approval Notification",
"depends_on": "eval: doc.send_leave_notification == 1",
"fieldname": "leave_approval_notification_template",
"fieldtype": "Link",
@@ -80,7 +79,6 @@
"options": "Email Template"
},
{
- "default": "Leave Status Notification",
"depends_on": "eval: doc.send_leave_notification == 1",
"fieldname": "leave_status_notification_template",
"fieldtype": "Link",
@@ -157,7 +155,7 @@
"idx": 1,
"issingle": 1,
"links": [],
- "modified": "2021-05-05 12:25:24.082705",
+ "modified": "2021-04-26 10:52:56.192773",
"modified_by": "Administrator",
"module": "HR",
"name": "HR Settings",
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.json b/erpnext/payroll/doctype/salary_slip/salary_slip.json
index 27409ccff2..42a0f290cb 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.json
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.json
@@ -423,7 +423,7 @@
{
"fieldname": "net_pay_info",
"fieldtype": "Section Break",
- "label": "Net Pay Info"
+ "label": "net pay info"
},
{
"fieldname": "net_pay",
@@ -631,7 +631,7 @@
"idx": 9,
"is_submittable": 1,
"links": [],
- "modified": "2021-05-05 12:21:27.836273",
+ "modified": "2021-03-31 22:44:09.772331",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Slip",
From bdf8c528f17a57fc3a46eab5e26bb0bf040d8c7e Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 6 May 2021 18:37:14 +0530
Subject: [PATCH 017/262] test: Fix dependencies
---
.../doctype/accounting_dimension/test_accounting_dimension.py | 3 ++-
.../test_accounting_dimension_filter.py | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
index fc1d7e344a..6fb661eb54 100644
--- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
@@ -7,7 +7,8 @@ import frappe
import unittest
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
-from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import delete_accounting_dimension
+
+test_dependencies = ['Location']
class TestAccountingDimension(unittest.TestCase):
def setUp(self):
diff --git a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
index 7877abd026..78a88eb48c 100644
--- a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
+++ b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
@@ -9,6 +9,8 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import create_dimension, disable_dimension
from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError
+test_dependencies = ['Location']
+
class TestAccountingDimensionFilter(unittest.TestCase):
def setUp(self):
create_dimension()
From c702408f9939da15ede122531d86e0a7d479b40b Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 6 May 2021 18:37:45 +0530
Subject: [PATCH 018/262] chore: Remove unnecessary print statements
---
erpnext/controllers/accounts_controller.py | 1 -
erpnext/setup/doctype/email_digest/email_digest.py | 3 +--
erpnext/stock/stock_balance.py | 5 +----
erpnext/utilities/__init__.py | 1 -
4 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index c409850734..913458fa35 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1006,7 +1006,6 @@ class AccountsController(TransactionBase):
else:
grand_total -= self.get("total_advance")
base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
- print(grand_total, base_grand_total)
if total != flt(grand_total, self.precision("grand_total")) or \
base_total != flt(base_grand_total, self.precision("base_grand_total")):
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py
index 8c97322a71..5db54eeee1 100644
--- a/erpnext/setup/doctype/email_digest/email_digest.py
+++ b/erpnext/setup/doctype/email_digest/email_digest.py
@@ -808,7 +808,6 @@ def get_incomes_expenses_for_period(account, from_date, to_date):
val = balance_on_to_date - balance_before_from_date
else:
last_year_closing_balance = get_balance_on(account, date=fy_start_date - timedelta(days=1))
- print(fy_start_date - timedelta(days=1), last_year_closing_balance)
val = balance_on_to_date + (last_year_closing_balance - balance_before_from_date)
return val
@@ -837,4 +836,4 @@ def get_future_date_for_calendaer_event(frequency):
elif frequency == "Monthly":
to_date = add_to_date(from_date, months=1)
- return from_date, to_date
\ No newline at end of file
+ return from_date, to_date
diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py
index 8ba1f1ca5c..8917bfeae4 100644
--- a/erpnext/stock/stock_balance.py
+++ b/erpnext/stock/stock_balance.py
@@ -194,9 +194,6 @@ def set_stock_balance_as_per_serial_no(item_code=None, posting_date=None, postin
serial_nos = frappe.db.sql("""select count(name) from `tabSerial No`
where item_code=%s and warehouse=%s and docstatus < 2""", (d[0], d[1]))
- if serial_nos and flt(serial_nos[0][0]) != flt(d[2]):
- print(d[0], d[1], d[2], serial_nos[0][0])
-
sle = frappe.db.sql("""select valuation_rate, company from `tabStock Ledger Entry`
where item_code = %s and warehouse = %s and is_cancelled = 0
order by posting_date desc limit 1""", (d[0], d[1]))
@@ -230,7 +227,7 @@ def set_stock_balance_as_per_serial_no(item_code=None, posting_date=None, postin
})
update_bin(args)
-
+
create_repost_item_valuation_entry({
"item_code": d[0],
"warehouse": d[1],
diff --git a/erpnext/utilities/__init__.py b/erpnext/utilities/__init__.py
index 618cc985ae..0a5aa3c49b 100644
--- a/erpnext/utilities/__init__.py
+++ b/erpnext/utilities/__init__.py
@@ -12,7 +12,6 @@ def update_doctypes():
for f in dt.fields:
if f.fieldname == d.fieldname and f.fieldtype in ("Text", "Small Text"):
- print(f.parent, f.fieldname)
f.fieldtype = "Text Editor"
dt.save()
break
From 0e41295c0e6d2f541e161dee9ae1e8d9985311ce Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Thu, 6 May 2021 19:14:06 +0530
Subject: [PATCH 019/262] perf: Performance enhancement on setup wizard
(#25606)
* perf: Performance enhancement on setup wizard
* fix: create departments without updating nsm
---
erpnext/accounts/doctype/account/account.py | 2 +-
.../chart_of_accounts/chart_of_accounts.py | 4 +-
.../accounts_settings/accounts_settings.py | 4 +-
.../education_settings/education_settings.py | 4 +-
erpnext/hr/doctype/department/department.py | 3 +-
.../payroll_settings/payroll_settings.py | 4 +-
.../selling_settings/selling_settings.py | 4 +-
.../global_defaults/global_defaults.py | 12 +-
.../doctype/naming_series/naming_series.py | 16 +--
.../operations/install_fixtures.py | 134 ++++++++++--------
erpnext/setup/setup_wizard/setup_wizard.py | 9 --
.../doctype/stock_settings/stock_settings.py | 10 +-
12 files changed, 105 insertions(+), 101 deletions(-)
diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py
index 0606823821..1be2fbf5c8 100644
--- a/erpnext/accounts/doctype/account/account.py
+++ b/erpnext/accounts/doctype/account/account.py
@@ -13,7 +13,7 @@ class BalanceMismatchError(frappe.ValidationError): pass
class Account(NestedSet):
nsm_parent_field = 'parent_account'
def on_update(self):
- if frappe.local.flags.ignore_on_update:
+ if frappe.local.flags.ignore_update_nsm:
return
else:
super(Account, self).on_update()
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
index 0e3b24cda3..927adc7086 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
@@ -57,10 +57,10 @@ def create_charts(company, chart_template=None, existing_company=None, custom_ch
# Rebuild NestedSet HSM tree for Account Doctype
# after all accounts are already inserted.
- frappe.local.flags.ignore_on_update = True
+ frappe.local.flags.ignore_update_nsm = True
_import_accounts(chart, None, None, root_account=True)
rebuild_tree("Account", "parent_account")
- frappe.local.flags.ignore_on_update = False
+ frappe.local.flags.ignore_update_nsm = False
def add_suffix_if_duplicate(account_name, account_number, accounts):
if account_number:
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
index 5593466fc2..4d3388090d 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py
@@ -30,5 +30,5 @@ class AccountsSettings(Document):
def enable_payment_schedule_in_print(self):
show_in_print = cint(self.show_payment_schedule_in_print)
for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):
- make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check")
- make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check")
+ make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check", validate_fields_for_doctype=False)
diff --git a/erpnext/education/doctype/education_settings/education_settings.py b/erpnext/education/doctype/education_settings/education_settings.py
index a85d3e70f3..658380ea42 100644
--- a/erpnext/education/doctype/education_settings/education_settings.py
+++ b/erpnext/education/doctype/education_settings/education_settings.py
@@ -31,9 +31,9 @@ class EducationSettings(Document):
def validate(self):
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
if self.get('instructor_created_by')=='Naming Series':
- make_property_setter('Instructor', "naming_series", "hidden", 0, "Check")
+ make_property_setter('Instructor', "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False)
else:
- make_property_setter('Instructor', "naming_series", "hidden", 1, "Check")
+ make_property_setter('Instructor', "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False)
def update_website_context(context):
context["lms_enabled"] = frappe.get_doc("Education Settings").enable_lms
\ No newline at end of file
diff --git a/erpnext/hr/doctype/department/department.py b/erpnext/hr/doctype/department/department.py
index 2cef509276..539a360269 100644
--- a/erpnext/hr/doctype/department/department.py
+++ b/erpnext/hr/doctype/department/department.py
@@ -31,7 +31,8 @@ class Department(NestedSet):
return new
def on_update(self):
- NestedSet.on_update(self)
+ if not frappe.local.flags.ignore_update_nsm:
+ super(Department, self).on_update()
def on_trash(self):
super(Department, self).on_trash()
diff --git a/erpnext/payroll/doctype/payroll_settings/payroll_settings.py b/erpnext/payroll/doctype/payroll_settings/payroll_settings.py
index 5efa41db1f..459b7eacb4 100644
--- a/erpnext/payroll/doctype/payroll_settings/payroll_settings.py
+++ b/erpnext/payroll/doctype/payroll_settings/payroll_settings.py
@@ -28,5 +28,5 @@ class PayrollSettings(Document):
def toggle_rounded_total(self):
self.disable_rounded_total = cint(self.disable_rounded_total)
- make_property_setter("Salary Slip", "rounded_total", "hidden", self.disable_rounded_total, "Check")
- make_property_setter("Salary Slip", "rounded_total", "print_hide", self.disable_rounded_total, "Check")
+ make_property_setter("Salary Slip", "rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
+ make_property_setter("Salary Slip", "rounded_total", "print_hide", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.py b/erpnext/selling/doctype/selling_settings/selling_settings.py
index d297883876..b219e7ecce 100644
--- a/erpnext/selling/doctype/selling_settings/selling_settings.py
+++ b/erpnext/selling/doctype/selling_settings/selling_settings.py
@@ -30,8 +30,8 @@ class SellingSettings(Document):
# Make property setters to hide tax_id fields
for doctype in ("Sales Order", "Sales Invoice", "Delivery Note"):
- make_property_setter(doctype, "tax_id", "hidden", self.hide_tax_id, "Check")
- make_property_setter(doctype, "tax_id", "print_hide", self.hide_tax_id, "Check")
+ make_property_setter(doctype, "tax_id", "hidden", self.hide_tax_id, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, "tax_id", "print_hide", self.hide_tax_id, "Check", validate_fields_for_doctype=False)
def set_default_customer_group_and_territory(self):
if not self.customer_group:
diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py
index 76a8450829..e587217181 100644
--- a/erpnext/setup/doctype/global_defaults/global_defaults.py
+++ b/erpnext/setup/doctype/global_defaults/global_defaults.py
@@ -60,11 +60,11 @@ class GlobalDefaults(Document):
# Make property setters to hide rounded total fields
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
"Supplier Quotation", "Purchase Order", "Purchase Invoice"):
- make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check")
- make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check")
+ make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check", validate_fields_for_doctype=False)
- make_property_setter(doctype, "rounded_total", "hidden", self.disable_rounded_total, "Check")
- make_property_setter(doctype, "rounded_total", "print_hide", self.disable_rounded_total, "Check")
+ make_property_setter(doctype, "rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, "rounded_total", "print_hide", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
def toggle_in_words(self):
self.disable_in_words = cint(self.disable_in_words)
@@ -72,5 +72,5 @@ class GlobalDefaults(Document):
# Make property setters to hide in words fields
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
"Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"):
- make_property_setter(doctype, "in_words", "hidden", self.disable_in_words, "Check")
- make_property_setter(doctype, "in_words", "print_hide", self.disable_in_words, "Check")
+ make_property_setter(doctype, "in_words", "hidden", self.disable_in_words, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, "in_words", "print_hide", self.disable_in_words, "Check", validate_fields_for_doctype=False)
diff --git a/erpnext/setup/doctype/naming_series/naming_series.py b/erpnext/setup/doctype/naming_series/naming_series.py
index 373b0a58c9..c1f9433b41 100644
--- a/erpnext/setup/doctype/naming_series/naming_series.py
+++ b/erpnext/setup/doctype/naming_series/naming_series.py
@@ -183,8 +183,8 @@ class NamingSeries(Document):
def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True):
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
if naming_series:
- make_property_setter(doctype, "naming_series", "hidden", 0, "Check")
- make_property_setter(doctype, "naming_series", "reqd", 1, "Check")
+ make_property_setter(doctype, "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, "naming_series", "reqd", 1, "Check", validate_fields_for_doctype=False)
# set values for mandatory
try:
@@ -195,15 +195,15 @@ def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True
pass
if hide_name_field:
- make_property_setter(doctype, fieldname, "reqd", 0, "Check")
- make_property_setter(doctype, fieldname, "hidden", 1, "Check")
+ make_property_setter(doctype, fieldname, "reqd", 0, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False)
else:
- make_property_setter(doctype, "naming_series", "reqd", 0, "Check")
- make_property_setter(doctype, "naming_series", "hidden", 1, "Check")
+ make_property_setter(doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False)
if hide_name_field:
- make_property_setter(doctype, fieldname, "hidden", 0, "Check")
- make_property_setter(doctype, fieldname, "reqd", 1, "Check")
+ make_property_setter(doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False)
+ make_property_setter(doctype, fieldname, "reqd", 1, "Check", validate_fields_for_doctype=False)
# set values for mandatory
frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=`name` where
diff --git a/erpnext/setup/setup_wizard/operations/install_fixtures.py b/erpnext/setup/setup_wizard/operations/install_fixtures.py
index 5053c6a512..f21d55fe21 100644
--- a/erpnext/setup/setup_wizard/operations/install_fixtures.py
+++ b/erpnext/setup/setup_wizard/operations/install_fixtures.py
@@ -12,6 +12,7 @@ from frappe.desk.doctype.global_search_settings.global_search_settings import up
from erpnext.accounts.doctype.account.account import RootNotEditable
from erpnext.regional.address_template.setup import set_up_address_templates
+from frappe.utils.nestedset import rebuild_tree
default_lead_sources = ["Existing Customer", "Reference", "Advertisement",
"Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing",
@@ -280,13 +281,15 @@ def install(country=None):
set_more_defaults()
update_global_search_doctypes()
- # path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
- # if os.path.exists(path.encode("utf-8")):
- # frappe.get_attr("erpnext.regional.{0}.setup.setup_company_independent_fixtures".format(frappe.scrub(country)))()
-
-
def set_more_defaults():
# Do more setup stuff that can be done here with no dependencies
+ update_selling_defaults()
+ update_buying_defaults()
+ update_hr_defaults()
+ add_uom_data()
+ update_item_variant_settings()
+
+def update_selling_defaults():
selling_settings = frappe.get_doc("Selling Settings")
selling_settings.set_default_customer_group_and_territory()
selling_settings.cust_master_name = "Customer Name"
@@ -296,13 +299,7 @@ def set_more_defaults():
selling_settings.sales_update_frequency = "Each Transaction"
selling_settings.save()
- add_uom_data()
-
- # set no copy fields of an item doctype to item variant settings
- doc = frappe.get_doc('Item Variant Settings')
- doc.set_default_fields()
- doc.save()
-
+def update_buying_defaults():
buying_settings = frappe.get_doc("Buying Settings")
buying_settings.supp_master_name = "Supplier Name"
buying_settings.po_required = "No"
@@ -311,12 +308,19 @@ def set_more_defaults():
buying_settings.allow_multiple_items = 1
buying_settings.save()
+def update_hr_defaults():
hr_settings = frappe.get_doc("HR Settings")
hr_settings.emp_created_by = "Naming Series"
hr_settings.leave_approval_notification_template = _("Leave Approval Notification")
hr_settings.leave_status_notification_template = _("Leave Status Notification")
hr_settings.save()
+def update_item_variant_settings():
+ # set no copy fields of an item doctype to item variant settings
+ doc = frappe.get_doc('Item Variant Settings')
+ doc.set_default_fields()
+ doc.save()
+
def add_uom_data():
# add UOMs
uoms = json.loads(open(frappe.get_app_path("erpnext", "setup", "setup_wizard", "data", "uom_data.json")).read())
@@ -327,7 +331,7 @@ def add_uom_data():
"uom_name": _(d.get("uom_name")),
"name": _(d.get("uom_name")),
"must_be_whole_number": d.get("must_be_whole_number")
- }).insert(ignore_permissions=True)
+ }).db_insert()
# bootstrap uom conversion factors
uom_conversions = json.loads(open(frappe.get_app_path("erpnext", "setup", "setup_wizard", "data", "uom_conversion_data.json")).read())
@@ -336,7 +340,7 @@ def add_uom_data():
frappe.get_doc({
"doctype": "UOM Category",
"category_name": _(d.get("category"))
- }).insert(ignore_permissions=True)
+ }).db_insert()
if not frappe.db.exists("UOM Conversion Factor", {"from_uom": _(d.get("from_uom")), "to_uom": _(d.get("to_uom"))}):
uom_conversion = frappe.get_doc({
@@ -369,8 +373,8 @@ def add_sale_stages():
{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")},
{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")}
]
-
- make_records(records)
+ for sales_stage in records:
+ frappe.get_doc(sales_stage).db_insert()
def install_company(args):
records = [
@@ -418,7 +422,14 @@ def install_post_company_fixtures(args=None):
{'doctype': 'Department', 'department_name': _('Legal'), 'parent_department': _('All Departments'), 'company': args.company_name},
]
- make_records(records)
+ # Make root department with NSM updation
+ make_records(records[:1])
+
+ frappe.local.flags.ignore_update_nsm = True
+ make_records(records[1:])
+ frappe.local.flags.ignore_update_nsm = False
+
+ rebuild_tree("Department", "parent_department")
def install_defaults(args=None):
@@ -432,7 +443,15 @@ def install_defaults(args=None):
# enable default currency
frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
+ frappe.db.set_value("Stock Settings", None, "email_footer_address", args.get("company_name"))
+ set_global_defaults(args)
+ set_active_domains(args)
+ update_stock_settings()
+ update_shopping_cart_settings(args)
+ create_bank_account(args)
+
+def set_global_defaults(args):
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
current_fiscal_year = frappe.get_all("Fiscal Year")[0]
@@ -445,13 +464,10 @@ def install_defaults(args=None):
global_defaults.save()
- system_settings = frappe.get_doc("System Settings")
- system_settings.email_footer_address = args.get("company_name")
- system_settings.save()
-
- domain_settings = frappe.get_single('Domain Settings')
- domain_settings.set_active_domains(args.get('domains'))
+def set_active_domains(args):
+ frappe.get_single('Domain Settings').set_active_domains(args.get('domains'))
+def update_stock_settings():
stock_settings = frappe.get_doc("Stock Settings")
stock_settings.item_naming_by = "Item Code"
stock_settings.valuation_method = "FIFO"
@@ -463,48 +479,44 @@ def install_defaults(args=None):
stock_settings.set_qty_in_transactions_based_on_serial_no_input = 1
stock_settings.save()
- if args.bank_account:
- company_name = args.company_name
- bank_account_group = frappe.db.get_value("Account",
- {"account_type": "Bank", "is_group": 1, "root_type": "Asset",
- "company": company_name})
- if bank_account_group:
- bank_account = frappe.get_doc({
- "doctype": "Account",
- 'account_name': args.bank_account,
- 'parent_account': bank_account_group,
- 'is_group':0,
- 'company': company_name,
- "account_type": "Bank",
- })
- try:
- doc = bank_account.insert()
+def create_bank_account(args):
+ if not args.bank_account:
+ return
- frappe.db.set_value("Company", args.company_name, "default_bank_account", bank_account.name, update_modified=False)
+ company_name = args.company_name
+ bank_account_group = frappe.db.get_value("Account",
+ {"account_type": "Bank", "is_group": 1, "root_type": "Asset",
+ "company": company_name})
+ if bank_account_group:
+ bank_account = frappe.get_doc({
+ "doctype": "Account",
+ 'account_name': args.bank_account,
+ 'parent_account': bank_account_group,
+ 'is_group':0,
+ 'company': company_name,
+ "account_type": "Bank",
+ })
+ try:
+ doc = bank_account.insert()
- except RootNotEditable:
- frappe.throw(_("Bank account cannot be named as {0}").format(args.bank_account))
- except frappe.DuplicateEntryError:
- # bank account same as a CoA entry
- pass
+ frappe.db.set_value("Company", args.company_name, "default_bank_account", bank_account.name, update_modified=False)
- # Now, with fixtures out of the way, onto concrete stuff
- records = [
-
- # Shopping cart: needs price lists
- {
- "doctype": "Shopping Cart Settings",
- "enabled": 1,
- 'company': args.company_name,
- # uh oh
- 'price_list': frappe.db.get_value("Price List", {"selling": 1}),
- 'default_customer_group': _("Individual"),
- 'quotation_series': "QTN-",
- },
- ]
-
- make_records(records)
+ except RootNotEditable:
+ frappe.throw(_("Bank account cannot be named as {0}").format(args.bank_account))
+ except frappe.DuplicateEntryError:
+ # bank account same as a CoA entry
+ pass
+def update_shopping_cart_settings(args):
+ shopping_cart = frappe.get_doc("Shopping Cart Settings")
+ shopping_cart.update({
+ "enabled": 1,
+ 'company': args.company_name,
+ 'price_list': frappe.db.get_value("Price List", {"selling": 1}),
+ 'default_customer_group': _("Individual"),
+ 'quotation_series': "QTN-",
+ })
+ shopping_cart.update_single(shopping_cart.get_valid_dict())
def get_fy_details(fy_start_date, fy_end_date):
start_year = getdate(fy_start_date).year
diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py
index e74d837ef5..f63d2695aa 100644
--- a/erpnext/setup/setup_wizard/setup_wizard.py
+++ b/erpnext/setup/setup_wizard/setup_wizard.py
@@ -51,11 +51,6 @@ def get_setup_stages(args=None):
'status': _('Setting defaults'),
'fail_msg': 'Failed to set defaults',
'tasks': [
- {
- 'fn': setup_post_company_fixtures,
- 'args': args,
- 'fail_msg': _("Failed to setup post company fixtures")
- },
{
'fn': setup_defaults,
'args': args,
@@ -94,9 +89,6 @@ def stage_fixtures(args):
def setup_company(args):
fixtures.install_company(args)
-def setup_post_company_fixtures(args):
- fixtures.install_post_company_fixtures(args)
-
def setup_defaults(args):
fixtures.install_defaults(frappe._dict(args))
@@ -129,7 +121,6 @@ def login_as_first_user(args):
def setup_complete(args=None):
stage_fixtures(args)
setup_company(args)
- setup_post_company_fixtures(args)
setup_defaults(args)
stage_four(args)
fin(args)
diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.py b/erpnext/stock/doctype/stock_settings/stock_settings.py
index 3b9608b805..2dd7c6f35b 100644
--- a/erpnext/stock/doctype/stock_settings/stock_settings.py
+++ b/erpnext/stock/doctype/stock_settings/stock_settings.py
@@ -30,7 +30,7 @@ class StockSettings(Document):
# show/hide barcode field
for name in ["barcode", "barcodes", "scan_barcode"]:
frappe.make_property_setter({'fieldname': name, 'property': 'hidden',
- 'value': 0 if self.show_barcode_field else 1})
+ 'value': 0 if self.show_barcode_field else 1}, validate_fields_for_doctype=False)
self.validate_warehouses()
self.cant_change_valuation_method()
@@ -67,10 +67,10 @@ class StockSettings(Document):
self.toggle_warehouse_field_for_inter_warehouse_transfer()
def toggle_warehouse_field_for_inter_warehouse_transfer(self):
- make_property_setter("Sales Invoice Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check")
- make_property_setter("Delivery Note Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check")
- make_property_setter("Purchase Invoice Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check")
- make_property_setter("Purchase Receipt Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check")
+ make_property_setter("Sales Invoice Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check", validate_fields_for_doctype=False)
+ make_property_setter("Delivery Note Item", "target_warehouse", "hidden", 1 - cint(self.allow_from_dn), "Check", validate_fields_for_doctype=False)
+ make_property_setter("Purchase Invoice Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check", validate_fields_for_doctype=False)
+ make_property_setter("Purchase Receipt Item", "from_warehouse", "hidden", 1 - cint(self.allow_from_pr), "Check", validate_fields_for_doctype=False)
def clean_all_descriptions():
From ae18efaa0aaa2434395eac0cbe3483fc7e82a1e1 Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Thu, 6 May 2021 19:38:17 +0550
Subject: [PATCH 020/262] bumped to version 13.2.1
---
erpnext/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index a988d7217d..6775398532 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '13.2.0'
+__version__ = '13.2.1'
def get_default_company(user=None):
'''Get default company for user'''
From 5117cbc08ce86a911f10feee742c63ab39e78aba Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Fri, 7 May 2021 00:32:00 +0530
Subject: [PATCH 021/262] ci: Enable coveralls
---
.github/workflows/ci-tests.yml | 62 +++++++++++++++++++---------------
1 file changed, 35 insertions(+), 27 deletions(-)
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml
index b03aad794b..4d955190be 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/ci-tests.yml
@@ -12,13 +12,13 @@ jobs:
matrix:
include:
- TYPE: "server"
- JOB_NAME: "Server"
+ JOB_NAME: "Server.1"
RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- TYPE: "server"
- JOB_NAME: "Server"
+ JOB_NAME: "Server.2"
RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- TYPE: "server"
- JOB_NAME: "Server"
+ JOB_NAME: "Server.3"
RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- TYPE: "patch"
JOB_NAME: "Patch"
@@ -86,29 +86,37 @@ jobs:
env:
TYPE: ${{ matrix.TYPE }}
- # - name: Coverage - Pull Request
- # if: matrix.TYPE == 'server' && github.event_name == 'pull_request'
- # run: |
- # cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
- # cd ${GITHUB_WORKSPACE}
- # pip install coveralls==2.2.0
- # pip install coverage==4.5.4
- # coveralls --service=github
- # env:
- # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- # COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
- # COVERALLS_SERVICE_NAME: github
+ - name: Upload Coverage Data
+ if: matrix.TYPE == 'server'
+ run: |
+ cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
+ cd ${GITHUB_WORKSPACE}
+ pip3 install coverage==5.5
+ pip3 install coveralls==3.0.1
+ coveralls --service=github-actions
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
+ COVERALLS_FLAG_NAME: run-${{ matrix.container }}
+ COVERALLS_SERVICE_NAME: github-actions
+ COVERALLS_PARALLEL: true
- # - name: Coverage - Push
- # if: matrix.TYPE == 'server' && github.event_name == 'push'
- # run: |
- # cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
- # cd ${GITHUB_WORKSPACE}
- # pip install coveralls==2.2.0
- # pip install coverage==4.5.4
- # coveralls --service=github-actions
- # env:
- # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- # COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
- # COVERALLS_SERVICE_NAME: github-actions
+ coveralls:
+ name: Coverage Wrap Up
+ needs: test
+ container: python:3-slim
+ runs-on: ubuntu-18.04
+ steps:
+ - name: Clone
+ uses: actions/checkout@v2
+
+ - name: Coveralls Finished
+ run: |
+ cd ${GITHUB_WORKSPACE}
+ ls -al
+ pip3 install coverage==5.5
+ pip3 install coveralls==3.0.1
+ coveralls --finish
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
From ef9f126cb2651c5c37b5f060d7574a22cad42bb5 Mon Sep 17 00:00:00 2001
From: Nikhil Ponnuru
Date: Fri, 7 May 2021 10:06:29 +0530
Subject: [PATCH 022/262] fix: change get_all to get_list in employee leave
balance summary report to hide descendants when hide descendants is selected
in user permissions (#25599)
Co-authored-by: nikhilponnuru
Co-authored-by: Rucha Mahabal
---
.../employee_leave_balance_summary.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
index 92715d3445..e86fa2b1c4 100644
--- a/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
+++ b/erpnext/hr/report/employee_leave_balance_summary/employee_leave_balance_summary.py
@@ -47,7 +47,7 @@ def get_data(filters, leave_types):
user = frappe.session.user
conditions = get_conditions(filters)
- active_employees = frappe.get_all("Employee",
+ active_employees = frappe.get_list("Employee",
filters=conditions,
fields=["name", "employee_name", "department", "user_id", "leave_approver"])
@@ -72,4 +72,4 @@ def get_data(filters, leave_types):
data.append(row)
- return data
\ No newline at end of file
+ return data
From ad3edc83ecd6ca75551931f6e0ab036ab353ca56 Mon Sep 17 00:00:00 2001
From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com>
Date: Fri, 7 May 2021 12:25:40 +0530
Subject: [PATCH 023/262] fix: Render timesheet template on timer field
(#25565)
* fix: Render timesheet template on timer field
* fix: sider fix
---
erpnext/projects/doctype/timesheet/timesheet.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index b123af5d18..43a57e5d4a 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -174,9 +174,10 @@ frappe.ui.form.on("Timesheet Detail", {
var $trigger_again = $('.form-grid').find('.grid-row').find('.btn-open-row');
$trigger_again.on('click', () => {
- $('.form-grid')
- .find('[data-fieldname="timer"]')
- .append(frappe.render_template("timesheet"));
+ let $timer = $('.form-grid').find('[data-fieldname="timer"]');
+ if ($timer.get(0)) {
+ $timer.append(frappe.render_template("timesheet"));
+ }
frm.trigger("control_timer");
});
},
From 3ecd7ac4c78697939c201af5bf271cc79e4ca6c5 Mon Sep 17 00:00:00 2001
From: HENRY Florian
Date: Fri, 7 May 2021 10:03:12 +0200
Subject: [PATCH 024/262] fix: Add french chart accounts with account number
(#25009)
* fix: Add french chart accounts with account number
* fix actual franch plan
---
.../verified/fr_plan_comptable_general.json | 1574 ++++-----
.../fr_plan_comptable_general_avec_code.json | 3144 +++++++++++++++++
2 files changed, 3931 insertions(+), 787 deletions(-)
create mode 100644 erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general_avec_code.json
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json
index da1d10deb9..d60c559661 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json
@@ -1,1609 +1,1609 @@
{
- "country_code": "fr",
- "name": "France - Plan Comptable General",
+ "country_code": "fr",
+ "name": "France - Plan Comptable General",
"tree": {
"1-Comptes de Capitaux": {
"10-Capital et R\u00e9serves": {
"101-Capital": {
- "1011-Capital souscrit - non appel\u00e9": {},
- "1012-Capital souscrit - appel\u00e9, non vers\u00e9": {},
+ "1011-Capital souscrit - non appel\u00e9": {},
+ "1012-Capital souscrit - appel\u00e9, non vers\u00e9": {},
"1013-Capital souscrit - appel\u00e9, vers\u00e9": {
- "10131-Capital non amorti": {},
+ "10131-Capital non amorti": {},
"10132-Capital amorti": {}
- },
+ },
"1018-Capital souscrit soumis \u00e0 des r\u00e9glementations particuli\u00e8res": {}
- },
- "102-Fonds fiduciaires": {},
+ },
+ "102-Fonds fiduciaires": {},
"104-Primes li\u00e9es au capital social": {
- "1041-Primes d'\u00e9mission": {},
- "1042-Primes de fusion": {},
- "1043-Primes d'apport": {},
- "1044-Primes de conversion d'obligations en actions": {},
+ "1041-Primes d'\u00e9mission": {},
+ "1042-Primes de fusion": {},
+ "1043-Primes d'apport": {},
+ "1044-Primes de conversion d'obligations en actions": {},
"1045-Bons de souscription d'actions": {}
- },
+ },
"105-Ecarts de r\u00e9\u00e9valuation": {
- "1051-R\u00e9serve sp\u00e9ciale de r\u00e9\u00e9valuation": {},
- "1052-Ecart de r\u00e9\u00e9valuation libre": {},
- "1053-R\u00e9serve de r\u00e9\u00e9valuation": {},
- "1055-Ecarts de r\u00e9\u00e9valuation (autres op\u00e9rations l\u00e9gales)": {},
- "1057-Autres \u00e9carts de r\u00e9\u00e9valuation en France": {},
+ "1051-R\u00e9serve sp\u00e9ciale de r\u00e9\u00e9valuation": {},
+ "1052-Ecart de r\u00e9\u00e9valuation libre": {},
+ "1053-R\u00e9serve de r\u00e9\u00e9valuation": {},
+ "1055-Ecarts de r\u00e9\u00e9valuation (autres op\u00e9rations l\u00e9gales)": {},
+ "1057-Autres \u00e9carts de r\u00e9\u00e9valuation en France": {},
"1058-Autres \u00e9carts de r\u00e9\u00e9valuation \u00e0 l'\u00e9tranger": {}
- },
+ },
"106-R\u00e9serves": {
"1061-R\u00e9serve l\u00e9gale": {
- "10611-R\u00e9serve l\u00e9gale proprement dite": {},
+ "10611-R\u00e9serve l\u00e9gale proprement dite": {},
"10612-Plus-values nettes \u00e0 long terme": {}
- },
- "1062-R\u00e9serves indisponibles": {},
- "1063-R\u00e9serves statutaires ou contractuelles": {},
+ },
+ "1062-R\u00e9serves indisponibles": {},
+ "1063-R\u00e9serves statutaires ou contractuelles": {},
"1064-R\u00e9serves r\u00e9glement\u00e9es": {
- "10641-Plus-values nettes \u00e0 long terme": {},
- "10643-R\u00e9serves cons\u00e9cutives \u00e0 l'octroi de subventions d'investissement": {},
+ "10641-Plus-values nettes \u00e0 long terme": {},
+ "10643-R\u00e9serves cons\u00e9cutives \u00e0 l'octroi de subventions d'investissement": {},
"10648-Autres r\u00e9serves r\u00e9glement\u00e9es": {}
- },
+ },
"1068-Autres r\u00e9serves": {
- "10681-R\u00e9serve de propre assureur": {},
+ "10681-R\u00e9serve de propre assureur": {},
"10688-R\u00e9serves diverses": {}
}
- },
- "107-Ecarts d'\u00e9quivalence": {},
- "108-Compte de l'exploitant": {},
+ },
+ "107-Ecarts d'\u00e9quivalence": {},
+ "108-Compte de l'exploitant": {},
"109-Actionnaires: Capital souscrit - non appel\u00e9": {}
- },
+ },
"11-Report \u00e0 Nouveau": {
- "110-Report \u00e0 nouveau (solde cr\u00e9diteur)": {},
+ "110-Report \u00e0 nouveau (solde cr\u00e9diteur)": {},
"119-Report \u00e0 nouveau (solde d\u00e9biteur)": {}
- },
+ },
"12-R\u00e9sultat de l'Exercice": {
- "120-R\u00e9sultat de l'exercice (b\u00e9n\u00e9fice)": {},
+ "120-R\u00e9sultat de l'exercice (b\u00e9n\u00e9fice)": {},
"129-R\u00e9sultat de l'exercice (perte)": {}
- },
+ },
"13-Subventions d'Investissement": {
"131-Subventions d'\u00e9quipement": {
- "1311-Etat": {},
- "1312-R\u00e9gions": {},
- "1313-D\u00e9partements": {},
- "1314-Communes": {},
- "1315-Collectivit\u00e9s publiques": {},
- "1316-Entreprises publiques": {},
- "1317-Entreprises et organismes priv\u00e9s": {},
+ "1311-Etat": {},
+ "1312-R\u00e9gions": {},
+ "1313-D\u00e9partements": {},
+ "1314-Communes": {},
+ "1315-Collectivit\u00e9s publiques": {},
+ "1316-Entreprises publiques": {},
+ "1317-Entreprises et organismes priv\u00e9s": {},
"1318-Autres": {}
- },
- "138-Autres subventions d'investissement (m\u00eame ventilation que celle du compte 131)": {},
+ },
+ "138-Autres subventions d'investissement (m\u00eame ventilation que celle du compte 131)": {},
"139-Subventions d'investissement inscrites au compte de r\u00e9sultat": {
"1391-Subventions d'\u00e9quipement": {
- "13911-Subventions d'\u00e9quipement": {
- "13911-Etat": {},
- "13912-R\u00e9gions": {},
- "13913-D\u00e9partements": {},
- "13914-Communes": {},
- "13915-Collectivit\u00e9s publiques": {},
- "13916-Entreprises publiques": {},
- "13917-Entreprises et organismes priv\u00e9s": {},
- "13918-Autres": {}
- }
- },
+ "13911-Etat": {},
+ "13912-R\u00e9gions": {},
+ "13913-D\u00e9partements": {},
+ "13914-Communes": {},
+ "13915-Collectivit\u00e9s publiques": {},
+ "13916-Entreprises publiques": {},
+ "13917-Entreprises et organismes priv\u00e9s": {},
+ "13918-Autres": {}
+ },
"1398-Autres subventions d'investissement (m\u00eame ventilation que celle du compte 1391)": {}
}
- },
+ },
"14-Provisions R\u00e9glement\u00e9es": {
"142-Provisions r\u00e9glement\u00e9es relative aux immobilisations": {
- "1423-Provisions pour reconstitution des gisements miniers et p\u00e9troliers": {},
+ "1423-Provisions pour reconstitution des gisements miniers et p\u00e9troliers": {},
"1424-Provisions pour investissement (participation des salari\u00e9s)": {}
- },
+ },
"143-Provisions r\u00e9glement\u00e9es relatives aux stocks": {
- "1431-Hausse des prix": {},
+ "1431-Hausse des prix": {},
"1432-Fluctuation des cours": {}
- },
- "144-Provisions r\u00e9glement\u00e9es relatives aux autres \u00e9l\u00e9ments de l'actif": {},
- "145-Amortissements d\u00e9rogatoires": {},
- "146-Provision sp\u00e9ciale de r\u00e9\u00e9valuation": {},
- "147-Plus-values r\u00e9investies": {},
+ },
+ "144-Provisions r\u00e9glement\u00e9es relatives aux autres \u00e9l\u00e9ments de l'actif": {},
+ "145-Amortissements d\u00e9rogatoires": {},
+ "146-Provision sp\u00e9ciale de r\u00e9\u00e9valuation": {},
+ "147-Plus-values r\u00e9investies": {},
"148-Autres provisions r\u00e9glement\u00e9es": {}
- },
+ },
"15-Provisions": {
"151-Provisions pour risques": {
- "1511-Provisions pour litiges": {},
- "1512-Provisions pour garanties donn\u00e9es aux clients": {},
- "1513-Provisions pour pertes sur march\u00e9s \u00e0 terme": {},
- "1514-Provisions pour amendes et p\u00e9nalit\u00e9s": {},
- "1515-Provisions pour pertes de change": {},
- "1516-Provisions pour pertes sur contrats": {},
+ "1511-Provisions pour litiges": {},
+ "1512-Provisions pour garanties donn\u00e9es aux clients": {},
+ "1513-Provisions pour pertes sur march\u00e9s \u00e0 terme": {},
+ "1514-Provisions pour amendes et p\u00e9nalit\u00e9s": {},
+ "1515-Provisions pour pertes de change": {},
+ "1516-Provisions pour pertes sur contrats": {},
"1518-Autres provisions pour risques": {}
- },
- "153-Provisions pour pensions et obligations similaires": {},
- "154-Provisions pour restructurations": {},
- "155-Provisions pour imp\u00f4ts": {},
- "156-Provisions pour renouvellement des immobilisations (entreprises concessionnaires) ": {},
+ },
+ "153-Provisions pour pensions et obligations similaires": {},
+ "154-Provisions pour restructurations": {},
+ "155-Provisions pour imp\u00f4ts": {},
+ "156-Provisions pour renouvellement des immobilisations (entreprises concessionnaires) ": {},
"157-Provisions pour charges \u00e0 r\u00e9partir sur plusieurs exercices": {
"1572-Provisions pour gros entretien ou grandes r\u00e9visions": {}
- },
+ },
"158-Autres provisions pour charges": {
"1581-Provisions pour remises en \u00e9tat": {}
}
- },
+ },
"16-Emprunts et Dettes Assimil\u00e9es": {
- "161-Emprunts obligataires convertibles": {},
- "162-Obligations repr\u00e9sentatives de passifs nets remis en fiducie": {},
- "163-Autres emprunts obligataires": {},
- "164-Emprunts aupr\u00e8s des \u00e9tablissements de cr\u00e9dit": {},
+ "161-Emprunts obligataires convertibles": {},
+ "162-Obligations repr\u00e9sentatives de passifs nets remis en fiducie": {},
+ "163-Autres emprunts obligataires": {},
+ "164-Emprunts aupr\u00e8s des \u00e9tablissements de cr\u00e9dit": {},
"165-D\u00e9p\u00f4ts et cautionnements re\u00e7us": {
- "1651-D\u00e9p\u00f4ts": {},
+ "1651-D\u00e9p\u00f4ts": {},
"1655-Cautionnements": {}
- },
+ },
"166-Participation des salari\u00e9s aux r\u00e9sultats": {
- "1661-Comptes bloqu\u00e9s": {},
+ "1661-Comptes bloqu\u00e9s": {},
"1662-Fonds de participation": {}
- },
+ },
"167-Emprunts et dettes assortis de conditions particuli\u00e8res": {
- "1671-Emissions de titres participatifs": {},
- "1674-Avances conditionn\u00e9es de l'Etat": {},
+ "1671-Emissions de titres participatifs": {},
+ "1674-Avances conditionn\u00e9es de l'Etat": {},
"1675-Emprunts participatifs": {}
- },
+ },
"168-Autres emprunts et dettes assimil\u00e9es": {
- "1681-Autres emprunts": {},
- "1685-Rentes viag\u00e8res capitalis\u00e9es": {},
- "1687-Autres dettes": {},
+ "1681-Autres emprunts": {},
+ "1685-Rentes viag\u00e8res capitalis\u00e9es": {},
+ "1687-Autres dettes": {},
"1688-Int\u00e9r\u00eats courus": {
- "16881-Int\u00e9r\u00eats courus sur emprunts obligataires convertibles": {},
- "16883-Int\u00e9r\u00eats courus sur autres emprunts obligataires": {},
- "16884-Int\u00e9r\u00eats courus sur emprunts aupr\u00e8s des \u00e9tablissements de cr\u00e9dit": {},
- "16885-Int\u00e9r\u00eats courus sur d\u00e9p\u00f4ts et cautionnements re\u00e7us": {},
- "16886-Int\u00e9r\u00eats courus sur participation des salari\u00e9s aux r\u00e9sultats": {},
- "16887-Int\u00e9r\u00eats courus sur emprunts et dettes assortis de conditions particuli\u00e8res": {},
+ "16881-Int\u00e9r\u00eats courus sur emprunts obligataires convertibles": {},
+ "16883-Int\u00e9r\u00eats courus sur autres emprunts obligataires": {},
+ "16884-Int\u00e9r\u00eats courus sur emprunts aupr\u00e8s des \u00e9tablissements de cr\u00e9dit": {},
+ "16885-Int\u00e9r\u00eats courus sur d\u00e9p\u00f4ts et cautionnements re\u00e7us": {},
+ "16886-Int\u00e9r\u00eats courus sur participation des salari\u00e9s aux r\u00e9sultats": {},
+ "16887-Int\u00e9r\u00eats courus sur emprunts et dettes assortis de conditions particuli\u00e8res": {},
"16888-Int\u00e9r\u00eats courus sur autres emprunts et dettes assimil\u00e9es": {}
- },
+ },
"169-Primes de remboursement des obligations": {}
}
- },
+ },
"17-Dettes Rattach\u00e9es \u00e0 des Participations": {
- "171-Dettes rattach\u00e9es \u00e0 des participations (groupe)": {},
- "174-Dettes rattach\u00e9es \u00e0 des participations (hors groupe)": {},
+ "171-Dettes rattach\u00e9es \u00e0 des participations (groupe)": {},
+ "174-Dettes rattach\u00e9es \u00e0 des participations (hors groupe)": {},
"178-Dettes rattach\u00e9es \u00e0 des soci\u00e9t\u00e9s en participation": {
- "1781-Principal": {},
+ "1781-Principal": {},
"1788-Int\u00e9r\u00eats courus": {}
}
- },
+ },
"18-Comptes de liaison des \u00e9tablisssements et soci\u00e9t\u00e9s en participation": {
- "181-Comptes de liaison des \u00e9tablissements": {},
- "186-Biens et prestations de services \u00e9chang\u00e9s entre \u00e9tablissements (charges)": {},
- "187-Biens et prestations de services \u00e9chang\u00e9s entre \u00e9tablissements (produits)": {},
+ "181-Comptes de liaison des \u00e9tablissements": {},
+ "186-Biens et prestations de services \u00e9chang\u00e9s entre \u00e9tablissements (charges)": {},
+ "187-Biens et prestations de services \u00e9chang\u00e9s entre \u00e9tablissements (produits)": {},
"188-Comptes de liaison des soci\u00e9t\u00e9s en participation": {}
- },
+ },
"root_type": "Equity"
- },
+ },
"2-Comptes d'Immobilisations": {
"20-Immobilisations incorporelles": {
"201-Frais \u00e9tablissement": {
- "2011-Frais de constitution": {},
+ "2011-Frais de constitution": {},
"2012-Frais de premier \u00e9tablissement": {
- "20121-Frais de prospection": {},
+ "20121-Frais de prospection": {},
"20122-Frais de publicit\u00e9": {}
- },
+ },
"2013-Frais d'augmentation de capital et d'op\u00e9rations diverses (fusions, scissions, transformations)": {}
- },
- "203-Frais de recherche et de d\u00e9veloppement": {},
- "205-Concessions et droits similaires, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels, droits et valeurs similaires": {},
- "206-Droit au bail": {},
- "207-Fonds commercial": {},
+ },
+ "203-Frais de recherche et de d\u00e9veloppement": {},
+ "205-Concessions et droits similaires, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels, droits et valeurs similaires": {},
+ "206-Droit au bail": {},
+ "207-Fonds commercial": {},
"208-Autres immobilisations incorporelles": {
"2081-Mali de fusion sur actifs incorporels": {}
}
- },
+ },
"21-Immobilisations corporelles": {
"211-Terrains": {
"2111-Terrains nus": {
"account_type": "Fixed Asset"
- },
+ },
"2112-Terrains am\u00e9nag\u00e9s": {
"account_type": "Fixed Asset"
- },
+ },
"2113-Sous-sols et sur-sols": {
"account_type": "Fixed Asset"
- },
+ },
"2114-Terrains de carri\u00e8res (tr\u00e9fonds)": {
"account_type": "Fixed Asset"
- },
+ },
"2115-Terrains b\u00e2tis": {
"21151-Ensembles immobiliers industriels (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"21155-Ensembles immobiliers administratifs et commerciaux (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"21158-Autres ensembles immobiliers": {
"211581-Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations professionnelles (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"211588-Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations non professionnelles (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"212-Agencements et am\u00e9nagements de terrains (m\u00eame ventilation que celle du compte 211)": {
"account_type": "Fixed Asset"
- },
+ },
"213-Constructions": {
"2131-B\u00e2timents": {
"21311-Ensembles immobiliers industriels (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"21315-Ensembles immobiliers administratifs et commerciaux (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"21318-Autres ensembles immobiliers": {
"213181-Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations professionnelles (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"213188-Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations non professionnelles (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"2135-Installations g\u00e9n\u00e9rales, agencements, am\u00e9nagements des constructions": {
"21351-Ensembles immobiliers industriels (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"21355-Ensembles immobiliers administratifs et commerciaux (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"21358-Autres ensembles immobiliers": {
"213581-Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations professionnelles (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"213588-Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations non professionnelles (A, B)": {
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"2138-Ouvrages d'infrastructure": {
"21381-Voies de terre": {
"account_type": "Fixed Asset"
- },
+ },
"21382-Voies de fer": {
"account_type": "Fixed Asset"
- },
+ },
"21383-Voies d'eau": {
"account_type": "Fixed Asset"
- },
+ },
"21384-Barrages": {
"account_type": "Fixed Asset"
- },
+ },
"21385-Pistes d'a\u00e9rodromes": {
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"214-Constructions sur sol d'autrui (m\u00eame ventilation que celle du compte 213)": {
"account_type": "Fixed Asset"
- },
+ },
"215-Installations techniques, mat\u00e9riel et outillage industriels": {
"2151-Installations complexes sp\u00e9cialis\u00e9es": {
"21511-Installations complexes sp\u00e9cialis\u00e9es - sur sol propre": {
"account_type": "Fixed Asset"
- },
+ },
"21514-Installations complexes sp\u00e9cialis\u00e9es - sur sol d'autrui": {
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"2153-Installations \u00e0 caract\u00e8re sp\u00e9cifique": {
"21531-Installations \u00e0 caract\u00e8re sp\u00e9cifique - sur sol propre": {
"account_type": "Fixed Asset"
- },
+ },
"21534-Installations \u00e0 caract\u00e8re sp\u00e9cifique - sur sol d'autrui": {
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"2154-Mat\u00e9riel industriel": {
"account_type": "Fixed Asset"
- },
+ },
"2155-Outillage industriel": {
"account_type": "Fixed Asset"
- },
+ },
"2157-Agencements et am\u00e9nagements du mat\u00e9riel et outillage industriel": {
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
+ },
"218-Autres immobilisations corporelles": {
"2181-Installations g\u00e9n\u00e9rales, agencements, am\u00e9nagements divers": {
"account_type": "Fixed Asset"
- },
+ },
"2182-Mat\u00e9riel de transport": {
"account_type": "Fixed Asset"
- },
+ },
"2183-Mat\u00e9riel de bureau et mat\u00e9riel informatique": {
"account_type": "Fixed Asset"
- },
+ },
"2184-Mobilier": {
"account_type": "Fixed Asset"
- },
+ },
"2185-Cheptel": {
"account_type": "Fixed Asset"
- },
+ },
"2186-Emballages r\u00e9cup\u00e9rables": {
"account_type": "Fixed Asset"
- },
- "2187-Mali de fusion sur actifs corporels": {},
+ },
+ "2187-Mali de fusion sur actifs corporels": {},
"account_type": "Fixed Asset"
- },
+ },
"account_type": "Fixed Asset"
- },
- "22-Immobilisations mises en concession": {},
+ },
+ "22-Immobilisations mises en concession": {},
"23-Immobilisations en cours": {
"231-Immobilisations corporelles en cours": {
- "2312-Terrains": {},
- "2313-Constructions": {},
- "2315-Installations techniques, mat\u00e9riel et outillage industriels": {},
+ "2312-Terrains": {},
+ "2313-Constructions": {},
+ "2315-Installations techniques, mat\u00e9riel et outillage industriels": {},
"2318-Autres immobilisations corporelles": {}
- },
- "232-Immobilisations incorporelles en cours": {},
- "237-Avances et acomptes vers\u00e9s sur commandes d'immobilisations incorporelles": {},
+ },
+ "232-Immobilisations incorporelles en cours": {},
+ "237-Avances et acomptes vers\u00e9s sur commandes d'immobilisations incorporelles": {},
"238-Avances et acomptes vers\u00e9s sur commandes d'immobilisations corporelles": {
- "2382-Terrains": {},
- "2383-Constructions": {},
- "2385-Installations techniques, mat\u00e9riel et outillage industriels": {},
+ "2382-Terrains": {},
+ "2383-Constructions": {},
+ "2385-Installations techniques, mat\u00e9riel et outillage industriels": {},
"2388-Autres immobilisations corporelles": {}
}
- },
+ },
"25-Parts dans des entreprises li\u00e9es et cr\u00e9ances sur des entreprises li\u00e9es": {
"is_group": 1
- },
+ },
"26-Participations et cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
"261-Titres de participation": {
- "2611-Actions": {},
+ "2611-Actions": {},
"2618-Autres titres": {}
- },
+ },
"266-Autres formes de participation": {
"2661-Droit repr\u00e9sentatifs d'actifs nets remis en fiducie": {}
- },
+ },
"267-Cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
- "2671-Cr\u00e9ances rattach\u00e9es \u00e0 des participations (groupe)": {},
- "2674-Cr\u00e9ances rattach\u00e9es \u00e0 des participations (hors groupe)": {},
- "2675-Versements repr\u00e9sentatifs d'apports non capitalis\u00e9s (appel de fonds)": {},
- "2676-Avances consolidables": {},
- "2677-Autres cr\u00e9ances rattach\u00e9es \u00e0 des participations": {},
+ "2671-Cr\u00e9ances rattach\u00e9es \u00e0 des participations (groupe)": {},
+ "2674-Cr\u00e9ances rattach\u00e9es \u00e0 des participations (hors groupe)": {},
+ "2675-Versements repr\u00e9sentatifs d'apports non capitalis\u00e9s (appel de fonds)": {},
+ "2676-Avances consolidables": {},
+ "2677-Autres cr\u00e9ances rattach\u00e9es \u00e0 des participations": {},
"2678-Int\u00e9r\u00eats courus": {}
- },
+ },
"268-Cr\u00e9ances rattach\u00e9es \u00e0 des soci\u00e9t\u00e9s en participation": {
- "2681-Principal": {},
+ "2681-Principal": {},
"2688-Int\u00e9r\u00eats courus": {}
- },
+ },
"269-Versements restant \u00e0 effectuer sur titres de participation non lib\u00e9r\u00e9s": {}
- },
+ },
"27-Autres immobilisations financi\u00e8res": {
"271-Titres immobilis\u00e9s autres que les titres immobilis\u00e9s de l'activit\u00e9 de portefeuille (droit de propri\u00e9t\u00e9)": {
- "2711-Actions": {},
+ "2711-Actions": {},
"2718-Autres titres": {}
- },
+ },
"272-Titres immobilis\u00e9s (droit de cr\u00e9ance)": {
- "2721-Obligations": {},
+ "2721-Obligations": {},
"2722-Bons": {}
- },
- "273-Titres immobilis\u00e9s de l'activit\u00e9 de portefeuille": {},
+ },
+ "273-Titres immobilis\u00e9s de l'activit\u00e9 de portefeuille": {},
"274-Pr\u00eats": {
- "2741-Pr\u00eats participatifs": {},
- "2742-Pr\u00eats aux associ\u00e9s": {},
- "2743-Pr\u00eats au personnel": {},
+ "2741-Pr\u00eats participatifs": {},
+ "2742-Pr\u00eats aux associ\u00e9s": {},
+ "2743-Pr\u00eats au personnel": {},
"2748-Autres pr\u00eats": {}
- },
+ },
"275-D\u00e9p\u00f4ts et cautionnements vers\u00e9s": {
- "2751-D\u00e9p\u00f4ts": {},
+ "2751-D\u00e9p\u00f4ts": {},
"2755-Cautionnements": {}
- },
+ },
"276-Autres cr\u00e9ances immobilis\u00e9es": {
- "2761-Cr\u00e9ances diverses": {},
+ "2761-Cr\u00e9ances diverses": {},
"2768-Int\u00e9r\u00eats courus": {
- "27682-Int\u00e9r\u00eats courus sur titres immobilis\u00e9s (droit de cr\u00e9ance)": {},
- "27684-Int\u00e9r\u00eats courus sur pr\u00eats": {},
- "27685-Int\u00e9r\u00eats courus sur d\u00e9p\u00f4ts et cautionnements": {},
+ "27682-Int\u00e9r\u00eats courus sur titres immobilis\u00e9s (droit de cr\u00e9ance)": {},
+ "27684-Int\u00e9r\u00eats courus sur pr\u00eats": {},
+ "27685-Int\u00e9r\u00eats courus sur d\u00e9p\u00f4ts et cautionnements": {},
"27688-Int\u00e9r\u00eats courus sur cr\u00e9ances diverses": {}
}
- },
+ },
"277-(Actions propres ou parts propres)": {
- "2771-Actions propres ou parts propres": {},
+ "2771-Actions propres ou parts propres": {},
"2772-Actions propres ou parts propres en voie d'annulation": {}
- },
- "278-Mali de fusion sur actifs financiers": {},
+ },
+ "278-Mali de fusion sur actifs financiers": {},
"279-Versements restant \u00e0 effectuer sur titres immobilis\u00e9s non lib\u00e9r\u00e9s": {}
- },
+ },
"28-Amortissements des immobilisations": {
"280-Amortissements des immobilisations incorporelles": {
"2801-Frais d'\u00e9tablissement (m\u00eame ventilation que celle du compte 212)": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2803-Frais de recherche et de d\u00e9veloppement": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2805-Concessions et droits similaires, brevets, licences, logiciels, droits et valeurs similaires": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2807-Fonds commercial": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2808-Autres immobilisations incorporelles": {
"28081-Mali de fusion sur actifs incorporels": {
"account_type": "Accumulated Depreciation"
- },
+ },
"account_type": "Accumulated Depreciation"
- },
+ },
"account_type": "Accumulated Depreciation"
- },
+ },
"281-Amortissements des immobilisations corporelles": {
"2811-Terrains de gisement": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2812-Agencements, am\u00e9nagements de terrains (m\u00eame ventilation que celle du compte 212)": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2813-Constructions (m\u00eame ventilation que celle du compte 213)": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2814-Constructions sur sol d'autrui (m\u00eame ventilation que celle du compte du 214)": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2815-Installations techniques, mat\u00e9riel et outillage industriels (m\u00eame ventilation que celle du compte 218)": {
"account_type": "Accumulated Depreciation"
- },
+ },
"2818-Autres immobilisations corporelles (m\u00eame ventilation que celle du compte 218)": {
"28187-Mali de fusion sur actifs corporels": {
"account_type": "Accumulated Depreciation"
- },
+ },
"account_type": "Accumulated Depreciation"
- },
+ },
"account_type": "Accumulated Depreciation"
- },
- "282-Amortissements des immobilisations mises en concession": {},
+ },
+ "282-Amortissements des immobilisations mises en concession": {},
"account_type": "Accumulated Depreciation"
- },
+ },
"29-D\u00e9pr\u00e9ciations des immobilisations": {
"290-D\u00e9pr\u00e9ciations des immobilisations incorporelles": {
- "2905-Marques, proc\u00e9d\u00e9s, droits et valeurs similaires": {},
- "2906-Droit au bail": {},
- "2907-Fonds commercial": {},
+ "2905-Marques, proc\u00e9d\u00e9s, droits et valeurs similaires": {},
+ "2906-Droit au bail": {},
+ "2907-Fonds commercial": {},
"2908-Autres immobilisations incorporelles": {
"29081-Mali de fusion sur actifs incorporels": {}
}
- },
+ },
"291-D\u00e9pr\u00e9ciations des immobilisations corporelles (m\u00eame ventilation que celle du compte 21)": {
"2911-Terrains (autres que terrains de gisement)": {
"29187-Mali de fusion sur actifs corporels": {}
}
- },
- "292-D\u00e9pr\u00e9ciations des immobilisations mises en concession": {},
+ },
+ "292-D\u00e9pr\u00e9ciations des immobilisations mises en concession": {},
"293-D\u00e9pr\u00e9ciations des immobilisations en cours": {
- "2931-Immobilisations corporelles en cours": {},
+ "2931-Immobilisations corporelles en cours": {},
"2932-Immobilisations incorporelles en cours": {}
- },
+ },
"296-D\u00e9pr\u00e9ciations des participations et cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
- "2961-Titres de participation": {},
- "2966-Autres formes de participation": {},
- "2967-Cr\u00e9ances rattach\u00e9es \u00e0 des participations (m\u00eame ventilation que celle du compte 267)": {},
+ "2961-Titres de participation": {},
+ "2966-Autres formes de participation": {},
+ "2967-Cr\u00e9ances rattach\u00e9es \u00e0 des participations (m\u00eame ventilation que celle du compte 267)": {},
"2968-Cr\u00e9ances rattach\u00e9es \u00e0 des soci\u00e9t\u00e9s en participation (m\u00eame ventilation que celle du compte 268)": {}
- },
+ },
"297-D\u00e9pr\u00e9ciations des autres immobilisations financi\u00e8res": {
- "2971-Titres immobilis\u00e9s autres que les titres immobilis\u00e9s de l'activit\u00e9 de portefeuille - droit de propri\u00e9t\u00e9": {},
- "2972-Titres immobilis\u00e9s - droit de cr\u00e9ance (m\u00eame ventilation que celle du compte 272)": {},
- "2973- Titres immobilis\u00e9s de l'activit\u00e9 de portefuille": {},
- "2974-Pr\u00eats (m\u00eame ventilation que celle du compte 274)": {},
- "2975-D\u00e9p\u00f4ts et cautionnements vers\u00e9s (m\u00eame ventilation que celle du compte 275)": {},
+ "2971-Titres immobilis\u00e9s autres que les titres immobilis\u00e9s de l'activit\u00e9 de portefeuille - droit de propri\u00e9t\u00e9": {},
+ "2972-Titres immobilis\u00e9s - droit de cr\u00e9ance (m\u00eame ventilation que celle du compte 272)": {},
+ "2973- Titres immobilis\u00e9s de l'activit\u00e9 de portefuille": {},
+ "2974-Pr\u00eats (m\u00eame ventilation que celle du compte 274)": {},
+ "2975-D\u00e9p\u00f4ts et cautionnements vers\u00e9s (m\u00eame ventilation que celle du compte 275)": {},
"2976-Autres cr\u00e9ances immobilis\u00e9es (m\u00eame ventilation que celle du compte 276)": {
"29787-Mali de fusion sur actifs financiers": {}
}
}
- },
+ },
"root_type": "Asset"
- },
+ },
"3-Comptes de Stocks et En-Cours": {
"31-Mati\u00e8res premi\u00e8res (et fournitures)": {
- "311-Mati\u00e8res (ou groupe) A": {},
- "312-Mati\u00e8res (ou groupe) B": {},
+ "311-Mati\u00e8res (ou groupe) A": {},
+ "312-Mati\u00e8res (ou groupe) B": {},
"317-Fournitures A, B, C, ...": {}
- },
+ },
"32-Autres approvisionnements": {
"321-Mat\u00e8res consommables": {
- "3211-Mati\u00e8res (ou groupe) C": {},
+ "3211-Mati\u00e8res (ou groupe) C": {},
"3212-Mati\u00e8res (ou groupe) D": {}
- },
+ },
"322-Fournitures consommables": {
- "3221-Combustibles": {},
- "3222-Produits d'entretien": {},
- "3223-Fournitures d'atelier et d'usine": {},
- "3224-Fournitures de magasin": {},
+ "3221-Combustibles": {},
+ "3222-Produits d'entretien": {},
+ "3223-Fournitures d'atelier et d'usine": {},
+ "3224-Fournitures de magasin": {},
"3225-Fournitures de bureau": {}
- },
+ },
"326-Emballages": {
- "3261-Emballages perdus": {},
- "3265-Emballages r\u00e9cup\u00e9rables non identifiables": {},
+ "3261-Emballages perdus": {},
+ "3265-Emballages r\u00e9cup\u00e9rables non identifiables": {},
"3267-Emballages \u00e0 usage mixte": {}
}
- },
+ },
"33-En-cours de production de biens": {
"331-Produits en cours": {
- "3311-Produits en cours P1": {},
+ "3311-Produits en cours P1": {},
"3312-Produits en cours P2": {}
- },
+ },
"335-Travaux en cours": {
- "Travaux en cours T1": {},
- "Travaux en cours T2": {}
+ "3351-Travaux en cours T1": {},
+ "3352-Travaux en cours T2": {}
}
- },
+ },
"34-En-cours de production de services": {
"341-Etudes en cours": {
- "3411-Etudes en cours E1": {},
+ "3411-Etudes en cours E1": {},
"3412-Etudes en cours E2": {}
- },
+ },
"345-Prestations de services en cours": {
- "3451-Prestations de services S1": {},
+ "3451-Prestations de services S1": {},
"3452-Prestations de services S2": {}
}
- },
+ },
"35-Stocks de produits": {
"351-Produits interm\u00e9diaires": {
"3511-Produits interm\u00e9diaires (ou groupe) A": {
- "account_type": "Stock",
+ "account_type": "Stock",
"is_group": 1
- },
+ },
"3512-Produits interm\u00e9diaires (ou groupe) B": {
- "account_type": "Stock",
+ "account_type": "Stock",
"is_group": 1
- },
+ },
"account_type": "Stock"
- },
+ },
"355-Produits finis": {
"3551-Produits finis (ou groupe) A": {
- "account_type": "Stock",
+ "account_type": "Stock",
"is_group": 1
- },
+ },
"3552-Produits finis (ou groupe) B": {
- "account_type": "Stock",
+ "account_type": "Stock",
"is_group": 1
- },
+ },
"account_type": "Stock"
- },
+ },
"358-Produits r\u00e9siduels (ou mati\u00e8res de r\u00e9cup\u00e9ration)": {
"3581-D\u00e9chets": {
- "account_type": "Stock",
+ "account_type": "Stock",
"is_group": 1
- },
+ },
"3585-Rebuts": {
- "account_type": "Stock",
+ "account_type": "Stock",
"is_group": 1
- },
+ },
"3586-Mati\u00e8res de r\u00e9cup\u00e9ration": {
- "account_type": "Stock",
+ "account_type": "Stock",
"is_group": 1
- },
+ },
"account_type": "Stock"
- },
+ },
"account_type": "Stock"
- },
- "36-(Compte \u00e0 ouvrir, le cas \u00e9ch\u00e9ant, sous l'intitul\u00e9 \"stocks provenant d'immobilisations\")": {},
+ },
+ "36-(Compte \u00e0 ouvrir, le cas \u00e9ch\u00e9ant, sous l'intitul\u00e9 \"stocks provenant d'immobilisations\")": {},
"37-Stocks de marchandises": {
- "371-Marchandises (ou groupe) A": {},
+ "371-Marchandises (ou groupe) A": {},
"372-Marchandises (ou groupe) B": {}
- },
- "38-Stocks en voie d'acheminement, mis en d\u00e9p\u00f4t ou donn\u00e9s en consignation (en cas d'inventaire permanent en comptabilit\u00e9 g\u00e9n\u00e9rale)": {},
+ },
+ "38-Stocks en voie d'acheminement, mis en d\u00e9p\u00f4t ou donn\u00e9s en consignation (en cas d'inventaire permanent en comptabilit\u00e9 g\u00e9n\u00e9rale)": {
+ "account_type": "Stock"
+ },
"39-D\u00e9pr\u00e9ciations des stocks et en-cours": {
"391-D\u00e9pr\u00e9ciations des mati\u00e8res premi\u00e8res (et fournitures)": {
- "3911-Mati\u00e8res (ou groupe) A": {},
- "3912-Mati\u00e8res (ou groupe) B": {},
+ "3911-Mati\u00e8res (ou groupe) A": {},
+ "3912-Mati\u00e8res (ou groupe) B": {},
"3917-Fournitures A, B, C, ...": {}
- },
+ },
"392-D\u00e9pr\u00e9ciations des autres approvisionnements": {
- "3921-Mati\u00e8res consommables (m\u00eame ventilation que celle du compte 321)": {},
- "3922-Fournitures consommables (m\u00eame ventilation que celle du compte 322)": {},
+ "3921-Mati\u00e8res consommables (m\u00eame ventilation que celle du compte 321)": {},
+ "3922-Fournitures consommables (m\u00eame ventilation que celle du compte 322)": {},
"3926-Emballages (m\u00eame ventilation que celle du compte 326)": {}
- },
+ },
"393-D\u00e9pr\u00e9ciations des en-cours de production de biens": {
- "3931-Etudes en cours (m\u00eame ventilation que celle du compte 341)": {},
+ "3931-Etudes en cours (m\u00eame ventilation que celle du compte 341)": {},
"3935-Travaux en cours (m\u00eame ventilation que celle du compte 335)": {}
- },
+ },
"394-D\u00e9pr\u00e9ciations des en-cours de production de services": {
- "3941-Etudes en cours (m\u00eame ventilation que celle du compte 341)": {},
+ "3941-Etudes en cours (m\u00eame ventilation que celle du compte 341)": {},
"3945-Prestations de services en cours (m\u00eame ventilation que celle du compte 345)": {}
- },
+ },
"395-D\u00e9pr\u00e9ciations des stocks de produits": {
- "3951-Produits interm\u00e9diaires (m\u00eame ventilation que celle du compte 351)": {},
+ "3951-Produits interm\u00e9diaires (m\u00eame ventilation que celle du compte 351)": {},
"3955-Produits finis (m\u00eame ventilation que celle du compte 355)": {}
- },
+ },
"397-D\u00e9pr\u00e9ciations des stocks de marchandises": {
- "3971-Marchandise (ou groupe) A": {},
+ "3971-Marchandise (ou groupe) A": {},
"3972-Marchandise (ou groupe) B": {}
}
- },
+ },
"root_type": "Asset"
- },
+ },
"4-Comptes de Tiers (ACTIF)": {
"40-Fournisseurs et Comptes Rattach\u00e9s (ACTIF)": {
"409-Fournisseurs d\u00e9biteurs": {
- "4091-Fournisseurs - Avances et acomptes vers\u00e9s sur commandes": {},
- "4096-Fournisseurs - Cr\u00e9ances pour emballages et mat\u00e9riel \u00e0 rendre": {},
+ "4091-Fournisseurs - Avances et acomptes vers\u00e9s sur commandes": {},
+ "4096-Fournisseurs - Cr\u00e9ances pour emballages et mat\u00e9riel \u00e0 rendre": {},
"4097-Fournisseurs - Autres avoirs": {
- "40971-Fournisseurs d'exploitation": {},
+ "40971-Fournisseurs d'exploitation": {},
"40974-Fournisseurs d'immobilisation": {}
- },
+ },
"4098-Rabais, remises, ristournes \u00e0 obtenir et autres avoirs non encore re\u00e7us": {}
}
- },
+ },
"41-Clients et comptes rattach\u00e9s (ACTIF)": {
"410-Clients et Comptes rattach\u00e9s": {
"account_type": "Receivable"
- },
+ },
"411-Clients": {
"4111-Clients - Ventes de biens ou de prestations de services": {
"account_type": "Receivable"
- },
+ },
"4117-Clients - Retenues de garantie": {
"account_type": "Receivable"
- },
+ },
"account_type": "Receivable"
- },
+ },
"413-Clients - Effets \u00e0 recevoir": {
"account_type": "Receivable"
- },
+ },
"416-Clients douteux ou litigieux": {
"account_type": "Receivable"
- },
+ },
"418-Clients - Produits non encore factur\u00e9s": {
"4181-Clients - Factures \u00e0 \u00e9tablir": {
"account_type": "Receivable"
- },
+ },
"4188-Clients - Int\u00e9r\u00eats courus": {
"account_type": "Receivable"
- },
+ },
"account_type": "Receivable"
- },
+ },
"account_type": "Receivable"
- },
+ },
"42-Personnel et comptes rattach\u00e9s (ACTIF)": {
"425-Personnel - Avances et acomptes": {}
- },
+ },
"43-S\u00e9curit\u00e9 sociale et autres organismes sociaux (ACTIF)": {
- "431-S\u00e9curit\u00e9 sociale": {},
- "437-Autres organismes sociaux": {},
+ "431-S\u00e9curit\u00e9 sociale": {},
+ "437-Autres organismes sociaux": {},
"438-Organismes sociaux - Produits \u00e0 recevoir": {
"4387-Produits \u00e0 recevoir": {}
}
- },
+ },
"44-Etat et autres collectivit\u00e9s publiques (ACTIF)": {
"441-Etat - Subventions \u00e0 recevoir": {
- "4411-Subventions d'investissement": {},
- "4417-Subventions d'exploitation": {},
- "4418-Subventions d'\u00e9quilibre": {},
+ "4411-Subventions d'investissement": {},
+ "4417-Subventions d'exploitation": {},
+ "4418-Subventions d'\u00e9quilibre": {},
"4419-Avances sur subventions": {}
- },
+ },
"443-Op\u00e9rations particuli\u00e8res avec l'Etat, les collectivit\u00e9s publiques, les organismes internationaux": {
- "4431-Cr\u00e9ances sur l'Etat r\u00e9sultant de la suppression de la r\u00e8gle du d\u00e9calage d'un mois en mati\u00e8re de TVA": {},
+ "4431-Cr\u00e9ances sur l'Etat r\u00e9sultant de la suppression de la r\u00e8gle du d\u00e9calage d'un mois en mati\u00e8re de TVA": {},
"4438-Int\u00e9r\u00eats courus sur cr\u00e9ances figurant au compte 4431": {}
- },
+ },
"445-Etat - Taxes sur le chiffre d'affaires (ACTIF)": {
- "4452-TVA due intracommunautaire": {},
+ "4452-TVA due intracommunautaire": {},
"4456-Taxes sur le chiffre d'affaires d\u00e9ductibles": {
- "44562-TVA sur immobilisations": {},
- "44563-TVA transf\u00e9r\u00e9e par d'autres entreprises": {},
+ "44562-TVA sur immobilisations": {},
+ "44563-TVA transf\u00e9r\u00e9e par d'autres entreprises": {},
"44566-TVA sur autres biens et services": {
"tax_rate": 20.0
- },
- "44567-Cr\u00e9dit de TVA \u00e0 reporter": {},
+ },
+ "44567-Cr\u00e9dit de TVA \u00e0 reporter": {},
"44568-Taxes assimil\u00e9es \u00e0 la TVA": {}
- },
+ },
"4458-Taxes sur le chiffre d'affaires \u00e0 r\u00e9gulariser ou en attente (ACTIF)": {
- "44581-Acomptes - R\u00e9gime simplifi\u00e9 d'imposition": {},
- "44582-Acomptes - R\u00e9gime du forfait": {},
- "44583-Remboursement de taxes sur le chiffre d'affaires demand\u00e9": {},
+ "44581-Acomptes - R\u00e9gime simplifi\u00e9 d'imposition": {},
+ "44582-Acomptes - R\u00e9gime du forfait": {},
+ "44583-Remboursement de taxes sur le chiffre d'affaires demand\u00e9": {},
"44586-Taxes sur le chiffre d'affaires sur factures non parvenues": {}
}
- },
+ },
"448-Etat - Charges \u00e0 payer et produits \u00e0 recevoir": {
- "4482-Charges fiscales sur cong\u00e9s \u00e0 payer": {},
- "4486-Charges \u00e0 payer": {},
+ "4482-Charges fiscales sur cong\u00e9s \u00e0 payer": {},
+ "4486-Charges \u00e0 payer": {},
"4487-Produits \u00e0 recevoir": {}
}
- },
+ },
"45-Groupe et associ\u00e9s (ACTIF)": {
"456-Associ\u00e9s - Op\u00e9rations sur le capital (ACTIF)": {
"4562-Apporteurs - Capital appel\u00e9, non vers\u00e9": {
- "45621-Actionnaires - Capital souscrit et appel\u00e9, non vers\u00e9": {},
+ "45621-Actionnaires - Capital souscrit et appel\u00e9, non vers\u00e9": {},
"45625-Associ\u00e9s - Capital appel\u00e9, non vers\u00e9": {}
}
}
- },
+ },
"46-D\u00e9biteurs divers et cr\u00e9diteurs divers (ACTIF)": {
- "462-Cr\u00e9ances sur cessions d'immobilisations": {},
- "465-Cr\u00e9ances sur cessions de valeurs mobili\u00e8res de placement": {},
- "467-Autres comptes d\u00e9biteurs ou cr\u00e9diteurs (ACTIF)": {},
+ "462-Cr\u00e9ances sur cessions d'immobilisations": {},
+ "465-Cr\u00e9ances sur cessions de valeurs mobili\u00e8res de placement": {},
+ "467-Autres comptes d\u00e9biteurs ou cr\u00e9diteurs (ACTIF)": {},
"468-Divers - Charges \u00e0 payer et produits \u00e0 recevoir (ACTIF)": {
"4687-Produits \u00e0 recevoir": {}
}
- },
+ },
"47-Comptes transitoires ou d'attente (ACTIF)": {
"471-Comptes d'attente (ACTIF)": {
"account_type": "Temporary"
- },
+ },
"476-Diff\u00e9rences de conversion (ACTIF)": {
- "4761-Diminution des cr\u00e9ances": {},
- "4762-Augmentation des dettes": {},
+ "4761-Diminution des cr\u00e9ances": {},
+ "4762-Augmentation des dettes": {},
"4768-Diff\u00e9rences compens\u00e9es par couverture de change": {}
- },
+ },
"478-Autres comptes transitoires (ACTIF)": {
- "4781-Mali de fusion sur actif circulant": {},
+ "4781-Mali de fusion sur actif circulant": {},
"4786-Diff\u00e9rences d'\u00e9valuation sur instruments de tr\u00e9sorerie (ACTIF)": {}
}
- },
+ },
"48-Comptes de r\u00e9gularisation (ACTIF)": {
"481-Charges \u00e0 r\u00e9partir sur plusieurs exercices": {
"4816-Frais d'\u00e9mission des emprunts": {}
- },
- "486-Charges constat\u00e9es d'avance": {},
+ },
+ "486-Charges constat\u00e9es d'avance": {},
"488-Comptes de r\u00e9partition p\u00e9riodique des charges et des produits (ACTIF)": {
"4886-Charges": {}
}
- },
+ },
"49-D\u00e9pr\u00e9ciation des comptes de tiers (ACTIF)": {
- "491-D\u00e9pr\u00e9ciations des comptes clients": {},
+ "491-D\u00e9pr\u00e9ciations des comptes clients": {},
"495-D\u00e9pr\u00e9ciations des comptes du groupe et des associ\u00e9s": {
- "4951-Comptes du groupe": {},
- "4955-Comptes courants des associ\u00e9s": {},
+ "4951-Comptes du groupe": {},
+ "4955-Comptes courants des associ\u00e9s": {},
"4958-Op\u00e9rations faites en commun et en GIE": {}
- },
+ },
"496-D\u00e9pr\u00e9ciations des comptes de d\u00e9biteurs divers": {
- "4962-Cr\u00e9ances sur cessions d'immobilisations": {},
- "4965-Cr\u00e9ances sur cessions de valeurs mobili\u00e8res de placement": {},
+ "4962-Cr\u00e9ances sur cessions d'immobilisations": {},
+ "4965-Cr\u00e9ances sur cessions de valeurs mobili\u00e8res de placement": {},
"4967-Autres comptes d\u00e9biteurs": {}
}
- },
+ },
"root_type": "Asset"
- },
+ },
"4-Comptes de Tiers (PASSIF)": {
"40-Fournisseurs et Comptes Rattach\u00e9s (PASSIF)": {
"401-Fournisseurs": {
"4011-Fournisseurs - Achats de biens ou de prestations de services": {
"account_type": "Payable"
- },
+ },
"4017-Fournisseurs - Retenues de garantie": {
"account_type": "Payable"
- },
+ },
"account_type": "Payable"
- },
+ },
"403-Fournisseurs - Effets \u00e0 payer": {
"account_type": "Payable"
- },
+ },
"404-Fournisseurs d'immobilisations": {
"4041-Fournisseurs - Achats d'immobilisations": {
"account_type": "Payable"
- },
+ },
"4047-Fournisseurs d'immobilisations - Retenues de garantie": {
"account_type": "Payable"
- },
+ },
"account_type": "Payable"
- },
+ },
"405-Fournisseurs d'immobilisations - Effets \u00e0 payer": {
"account_type": "Payable"
- },
+ },
"408-Fournisseurs - Factures non parvenues": {
"4081-Fournisseurs": {
"account_type": "Stock Received But Not Billed"
- },
+ },
"4084-Fournisseurs d'immobilisations": {
"account_type": "Stock Received But Not Billed"
- },
+ },
"4088-Fournisseurs - Int\u00e9r\u00eats courus": {
"account_type": "Stock Received But Not Billed"
- },
+ },
"account_type": "Stock Received But Not Billed"
- },
+ },
"account_type": "Payable"
- },
+ },
"41-Clients et comptes rattach\u00e9s (PASSIF)": {
"419-Clients cr\u00e9diteurs": {
- "4191-Clients - Avances et acomptes re\u00e7us sur commandes": {},
- "4196-Clients - Dettes pour emballages et mat\u00e9riels consign\u00e9s": {},
- "4197-Clients - Autres avoirs": {},
+ "4191-Clients - Avances et acomptes re\u00e7us sur commandes": {},
+ "4196-Clients - Dettes pour emballages et mat\u00e9riels consign\u00e9s": {},
+ "4197-Clients - Autres avoirs": {},
"4198-Rabais, remises, ristournes \u00e0 accorder et autres avoirs \u00e0 \u00e9tablir": {}
}
- },
+ },
"42-Personnel et comptes rattach\u00e9s (PASSIF)": {
- "421-Personnel - R\u00e9mun\u00e9rations dues": {},
- "422-Comit\u00e9s d'entreprises, d'\u00e9tablissement...": {},
+ "421-Personnel - R\u00e9mun\u00e9rations dues": {},
+ "422-Comit\u00e9s d'entreprises, d'\u00e9tablissement...": {},
"424-Participation des salari\u00e9s aux r\u00e9sultats": {
- "4246-R\u00e9serve sp\u00e9ciale": {},
+ "4246-R\u00e9serve sp\u00e9ciale": {},
"4248-Comptes courants": {}
- },
- "426-Personnel - D\u00e9p\u00f4ts": {},
- "427-Personnel - Oppositions": {},
+ },
+ "426-Personnel - D\u00e9p\u00f4ts": {},
+ "427-Personnel - Oppositions": {},
"428-Personnel - Charges \u00e0 payer et produits \u00e0 recevoir": {
- "4282-Dettes provisionn\u00e9es pour cong\u00e9s \u00e0 payer": {},
- "4284-Dettes provisionn\u00e9es pour participation des salari\u00e9s aux r\u00e9sultats": {},
- "4286-Autres charges \u00e0 payer": {},
+ "4282-Dettes provisionn\u00e9es pour cong\u00e9s \u00e0 payer": {},
+ "4284-Dettes provisionn\u00e9es pour participation des salari\u00e9s aux r\u00e9sultats": {},
+ "4286-Autres charges \u00e0 payer": {},
"4287-Produits \u00e0 recevoir": {}
}
- },
+ },
"43-S\u00e9curit\u00e9 sociale et autres organismes sociaux (PASSIF)": {
"438-Organismes sociaux - Charges \u00e0 payer": {
- "4382-Charges sociales sur cong\u00e9s \u00e0 payer": {},
+ "4382-Charges sociales sur cong\u00e9s \u00e0 payer": {},
"4386-Autres charges \u00e0 payer": {}
}
- },
+ },
"44-Etat et autres collectivit\u00e9s publiques (PASSIF)": {
"442-Etat - Imp\u00f4ts et taxes recouvrables sur des tiers": {
- "4424-Obligataires": {},
+ "4424-Obligataires": {},
"4425-Associ\u00e9s": {}
- },
- "444-Etat - Imp\u00f4ts sur les b\u00e9n\u00e9fices": {},
+ },
+ "444-Etat - Imp\u00f4ts sur les b\u00e9n\u00e9fices": {},
"445-Etat - Taxes sur le chiffre d'affaires (PASSIF)": {
"4455-Taxes sur le chiffre d'affaires \u00e0 d\u00e9caisser": {
- "44551-TVA \u00e0 d\u00e9caisser": {},
+ "44551-TVA \u00e0 d\u00e9caisser": {},
"44558-Taxes assimil\u00e9es \u00e0 la TVA": {}
- },
+ },
"4457-Taxes sur le chiffre d'affaires collect\u00e9es par l'entreprise": {
"44571-TVA collect\u00e9e": {
- "account_type": "Tax",
+ "account_type": "Tax",
"is_group": 1
- },
+ },
"44578-Taxes assimil\u00e9es \u00e0 la TVA": {}
- },
+ },
"4458-Taxes sur le chiffre d'affaires \u00e0 r\u00e9gulariser ou en attente (PASSIF)": {
- "44584-TVA r\u00e9cup\u00e9r\u00e9e d'avance": {},
+ "44584-TVA r\u00e9cup\u00e9r\u00e9e d'avance": {},
"44587-Taxes sur le chiffre d'affaires sur factures \u00e0 \u00e9tablir": {}
}
- },
- "446-Obligations cautionn\u00e9es": {},
- "447-Autres imp\u00f4ts, taxes et versements assimil\u00e9s": {},
+ },
+ "446-Obligations cautionn\u00e9es": {},
+ "447-Autres imp\u00f4ts, taxes et versements assimil\u00e9s": {},
"449-Quotas d'\u00e9mission \u00e0 acqu\u00e9rir": {}
- },
+ },
"45-Groupe et associ\u00e9s (PASSIF)": {
- "451-Groupe (PASSIF)": {},
+ "451-Groupe (PASSIF)": {},
"455-Associ\u00e9s - Comptes courants (PASSIF)": {
- "4551-Principal (PASSIF)": {},
+ "4551-Principal (PASSIF)": {},
"4558-Int\u00e9r\u00eats courus (PASSIF)": {}
- },
+ },
"456-Associ\u00e9s - Op\u00e9rations sur le capital (PASSIF)": {
"4561-Associ\u00e9s - Comptes d'apport en soci\u00e9t\u00e9": {
- "45611-Apports en nature": {},
+ "45611-Apports en nature": {},
"45615-Apports en num\u00e9raire": {}
- },
- "4563-Associ\u00e9s - Versements re\u00e7us sur augmentation de capital": {},
- "4564-Associ\u00e9s - Versements anticip\u00e9s": {},
- "4566-Actionnaires d\u00e9faillants": {},
+ },
+ "4563-Associ\u00e9s - Versements re\u00e7us sur augmentation de capital": {},
+ "4564-Associ\u00e9s - Versements anticip\u00e9s": {},
+ "4566-Actionnaires d\u00e9faillants": {},
"4567-Associ\u00e9s - Capital \u00e0 rembourser": {}
- },
- "457-Associ\u00e9s - Dividendes \u00e0 payer": {},
+ },
+ "457-Associ\u00e9s - Dividendes \u00e0 payer": {},
"458-Associ\u00e9s - Op\u00e9rations faites en commun et en GIE": {
- "4581-Op\u00e9rations courantes": {},
+ "4581-Op\u00e9rations courantes": {},
"4588-Int\u00e9r\u00eats courus": {}
}
- },
+ },
"46-D\u00e9biteurs divers et cr\u00e9diteurs divers (PASSIF)": {
- "464-Dettes sur acquisitions de valeurs mobili\u00e8res de placement": {},
- "467-Autres comptes d\u00e9biteurs ou cr\u00e9diteurs (PASSIF)": {},
+ "464-Dettes sur acquisitions de valeurs mobili\u00e8res de placement": {},
+ "467-Autres comptes d\u00e9biteurs ou cr\u00e9diteurs (PASSIF)": {},
"468-Divers - Charges \u00e0 payer et produits \u00e0 recevoir (PASSIF)": {
"4686-Charges \u00e0 payer": {}
}
- },
+ },
"47-Comptes transitoires ou d'attente (PASSIF)": {
"471-Comptes d'attente (PASSIF)": {
"account_type": "Temporary"
- },
+ },
"477-Diff\u00e9rences de conversion (PASSIF)": {
- "4771-Augmentation des cr\u00e9ances": {},
- "4772-Diminution des dettes": {},
+ "4771-Augmentation des cr\u00e9ances": {},
+ "4772-Diminution des dettes": {},
"4778-Diff\u00e9rences compens\u00e9es par couverture de change": {}
- },
+ },
"478-Autres comptes transitoires (PASSIF)": {
"4787-Diff\u00e9rences d'\u00e9valuation sur instruments de tr\u00e9sorerie (PASSIF)": {}
}
- },
+ },
"48-Comptes de r\u00e9gularisation (PASSIF)": {
- "487-Produits constat\u00e9s d'avance": {},
+ "487-Produits constat\u00e9s d'avance": {},
"488-Comptes de r\u00e9partition p\u00e9riodique des charges et des produits (PASSIF)": {
"4887-Produits": {}
}
- },
+ },
"root_type": "Liability"
- },
+ },
"5-Comptes Financiers": {
"50-Valeurs mobili\u00e8res de placement": {
- "501-Parts dans des entreprises li\u00e9es": {},
+ "501-Parts dans des entreprises li\u00e9es": {},
"502-Actions propres": {
- "5021-Actions destin\u00e9es \u00e0 \u00eatre attribu\u00e9es aux employ\u00e9s et affect\u00e9es \u00e0 des plans d\u00e9termin\u00e9s": {},
+ "5021-Actions destin\u00e9es \u00e0 \u00eatre attribu\u00e9es aux employ\u00e9s et affect\u00e9es \u00e0 des plans d\u00e9termin\u00e9s": {},
"5022-Actions disponibles pour \u00eatre attribu\u00e9es aux employ\u00e9s ou pour la r\u00e9gularisation des cours de bourse": {}
- },
+ },
"503-Actions": {
- "5031-Titres cot\u00e9s": {},
+ "5031-Titres cot\u00e9s": {},
"5035-Titres non cot\u00e9s": {}
- },
- "504-Autres titres conf\u00e9rant un droit de propri\u00e9t\u00e9": {},
- "505-Obligations et bons \u00e9mis par la soci\u00e9t\u00e9 et rachet\u00e9s par elle": {},
+ },
+ "504-Autres titres conf\u00e9rant un droit de propri\u00e9t\u00e9": {},
+ "505-Obligations et bons \u00e9mis par la soci\u00e9t\u00e9 et rachet\u00e9s par elle": {},
"506-Obligations": {
- "5061-Titres cot\u00e9s": {},
+ "5061-Titres cot\u00e9s": {},
"5065-Titres non cot\u00e9s": {}
- },
- "507-Bons du Tr\u00e9sor et bons de caisse \u00e0 court terme": {},
+ },
+ "507-Bons du Tr\u00e9sor et bons de caisse \u00e0 court terme": {},
"508-Autres valeurs mobili\u00e8res de placement et autres cr\u00e9ances assimil\u00e9es": {
- "5081-Autres valeurs mobili\u00e8res": {},
- "5082-Bons de souscription": {},
+ "5081-Autres valeurs mobili\u00e8res": {},
+ "5082-Bons de souscription": {},
"5088-Int\u00e9r\u00eats courus sur obligations, bons et valeurs assimil\u00e9es": {}
- },
+ },
"509-Versements restant \u00e0 effectuer sur valeurs mobili\u00e8res de placement non lib\u00e9r\u00e9es": {}
- },
+ },
"51-Banques, \u00e9tablissements financiers et assimil\u00e9s": {
"511-Valeurs \u00e0 l'encaissement": {
- "5111-Coupons \u00e9chus \u00e0 l'encaissement": {},
- "5112-Ch\u00e8ques \u00e0 encaisser": {},
- "5113-Effets \u00e0 l'encaissement": {},
+ "5111-Coupons \u00e9chus \u00e0 l'encaissement": {},
+ "5112-Ch\u00e8ques \u00e0 encaisser": {},
+ "5113-Effets \u00e0 l'encaissement": {},
"5114-Effets \u00e0 l'escompte": {}
- },
+ },
"512-Banques": {
"5121-Comptes en monnaie nationale": {
"account_type": "Bank"
- },
+ },
"5124-Comptes en devises": {
"account_type": "Bank"
- },
+ },
"account_type": "Bank"
- },
- "514-Ch\u00e8ques postaux": {},
- "515-\"Caisses\" du Tr\u00e9sor et des \u00e9tablissements publics": {},
- "516-Soci\u00e9t\u00e9s de bourse": {},
- "517-Autres organismes financiers": {},
+ },
+ "514-Ch\u00e8ques postaux": {},
+ "515-\"Caisses\" du Tr\u00e9sor et des \u00e9tablissements publics": {},
+ "516-Soci\u00e9t\u00e9s de bourse": {},
+ "517-Autres organismes financiers": {},
"518-Int\u00e9r\u00eats courus": {
- "5181-Int\u00e9r\u00eats courus \u00e0 payer": {},
+ "5181-Int\u00e9r\u00eats courus \u00e0 payer": {},
"5188-Int\u00e9r\u00eats courus \u00e0 recevoir": {}
- },
+ },
"519-Concours bancaires courants": {
- "5191-Cr\u00e9dit de mobilisation des cr\u00e9ances commerciales (CMCC)": {},
- "5193-Mobilisation de cr\u00e9ances n\u00e9es \u00e0 l'\u00e9tranger": {},
+ "5191-Cr\u00e9dit de mobilisation des cr\u00e9ances commerciales (CMCC)": {},
+ "5193-Mobilisation de cr\u00e9ances n\u00e9es \u00e0 l'\u00e9tranger": {},
"5198-Int\u00e9r\u00eats courus sur concours bancaires courants": {}
}
- },
+ },
"52-Instruments de tr\u00e9sorerie": {
"is_group": 1
- },
+ },
"53-Caisse": {
"531-Caisse si\u00e8ge social": {
"5311-Caisse en monnaie nationale": {
"account_type": "Cash"
- },
+ },
"5314-Caisse en devises": {
"account_type": "Cash"
- },
+ },
"account_type": "Cash"
- },
+ },
"532-Caisse succursale (ou usine) A": {
"account_type": "Cash"
- },
+ },
"533-Caisse succursale (ou usine) B": {
"account_type": "Cash"
- },
+ },
"account_type": "Cash"
- },
+ },
"54-R\u00e9gies d'avance et accr\u00e9ditifs": {
"is_group": 1
- },
+ },
"58-Virements internes": {
"is_group": 1
- },
+ },
"59-D\u00e9pr\u00e9ciations des comptes financiers": {
"590-D\u00e9pr\u00e9ciations des valeurs mobili\u00e8res de placement": {
- "5903-Actions": {},
- "5904-Autres titres conf\u00e9rant un droit de propri\u00e9t\u00e9": {},
- "5906-Obligations": {},
+ "5903-Actions": {},
+ "5904-Autres titres conf\u00e9rant un droit de propri\u00e9t\u00e9": {},
+ "5906-Obligations": {},
"5908-Autres valeurs mobili\u00e8res de placement et cr\u00e9ances assimil\u00e9es": {}
}
- },
+ },
"root_type": "Asset"
- },
+ },
"6-Comptes de Charges": {
"60-Achats (sauf 603)": {
"601-Achats stock\u00e9s - Mati\u00e8res premi\u00e8res (et fournitures)": {
"6011-Mati\u00e8res (ou groupe) A": {
"account_type": "Cost of Goods Sold"
- },
+ },
"6012-Mati\u00e8res (ou groupe) B": {
"account_type": "Cost of Goods Sold"
- },
+ },
"6017-Fournitures A, B, C...": {
"account_type": "Cost of Goods Sold"
- },
+ },
"account_type": "Cost of Goods Sold"
- },
+ },
"602-Achats stock\u00e9s - Autres approvisionnements": {
"6021-Mati\u00e8res consommables": {
"60211-Mati\u00e8res (ou groupe) C": {
"account_type": "Cost of Goods Sold"
- },
+ },
"60212-Mati\u00e8res (ou groupe) D": {
"account_type": "Cost of Goods Sold"
- },
+ },
"account_type": "Cost of Goods Sold"
- },
+ },
"6022-Fournitures consommables": {
"60221-Combustibles": {
"account_type": "Cost of Goods Sold"
- },
+ },
"60222-Produits d'entretien": {
"account_type": "Cost of Goods Sold"
- },
+ },
"60223-Fournitures d'atelier et d'usine": {
"account_type": "Cost of Goods Sold"
- },
+ },
"60224-Fournitures de magasin": {
"account_type": "Cost of Goods Sold"
- },
+ },
"60225-Fournitures de bureau": {
"account_type": "Cost of Goods Sold"
- },
+ },
"account_type": "Cost of Goods Sold"
- },
+ },
"6026-Emballages": {
"60261-Emballages perdus": {
"account_type": "Cost of Goods Sold"
- },
+ },
"60265-Emballages r\u00e9cup\u00e9rables non identifiables": {
"account_type": "Cost of Goods Sold"
- },
+ },
"60267-Emballages \u00e0 usage mixte": {
"account_type": "Cost of Goods Sold"
- },
+ },
"account_type": "Cost of Goods Sold"
- },
+ },
"account_type": "Cost of Goods Sold"
- },
+ },
"603-Variations des stocks (approvisionnements et marchandises)": {
"6031-Variation des stocks de mati\u00e8res premi\u00e8res (et fournitures)": {
"account_type": "Stock Adjustment"
- },
+ },
"6032-Variation des stocks des autres approvisionnements": {
"account_type": "Stock Adjustment"
- },
+ },
"6037-Variation des stocks de marchandises": {
"account_type": "Stock Adjustment"
- },
+ },
"account_type": "Stock Adjustment"
- },
+ },
"604-Achats d'\u00e9tudes et prestations de service": {
"account_type": "Cost of Goods Sold"
- },
+ },
"605-Achats de mat\u00e9riel, \u00e9quipements et travaux": {
"account_type": "Cost of Goods Sold"
- },
+ },
"606-Achats non stock\u00e9s de mati\u00e8res et founitures": {
"6061-Fournitures non stockables (eau, \u00e9nergie...)": {
"account_type": "Cost of Goods Sold"
- },
+ },
"6063-Fournitures d'entretien et de petit \u00e9quipement": {
"account_type": "Cost of Goods Sold"
- },
+ },
"6064-Fournitures administratives": {
"account_type": "Cost of Goods Sold"
- },
+ },
"6068-Autres mati\u00e8res et fournitures": {
"account_type": "Cost of Goods Sold"
- },
+ },
"account_type": "Cost of Goods Sold"
- },
+ },
"607-Achats de marchandises": {
"6071-Marchandises (ou groupe) A": {
"account_type": "Cost of Goods Sold"
- },
+ },
"6072-Marchandises (ou groupe) B": {
"account_type": "Cost of Goods Sold"
- },
+ },
"account_type": "Cost of Goods Sold"
- },
+ },
"608-(Compte r\u00e9serv\u00e9, le cas \u00e9ch\u00e9ant, \u00e0 la recapitulation des Frais accessoires incorpor\u00e9s aux achats)": {
"account_type": "Expenses Included In Valuation"
- },
+ },
"609-Rabais, remises et ristournes obtenus sur achats": {
- "6091-Rabais, remises et ristournes obtenus sur achats - de mati\u00e8res premi\u00e8res (et fournitures)": {},
- "6092-Rabais, remises et ristournes obtenus sur achats - d'autres approvisionnements stock\u00e9s": {},
- "6094-Rabais, remises et ristournes obtenus sur achats - d'\u00e9tudes et prestations de services": {},
- "6095-Rabais, remises et ristournes obtenus sur achats - de mat\u00e9riel, \u00e9quipements et travaux": {},
- "6096-Rabais, remises et ristournes obtenus sur achats - d'approvisionnements non stock\u00e9s": {},
- "6097-Rabais, remises et ristournes obtenus sur achats - de marchandises": {},
+ "6091-Rabais, remises et ristournes obtenus sur achats - de mati\u00e8res premi\u00e8res (et fournitures)": {},
+ "6092-Rabais, remises et ristournes obtenus sur achats - d'autres approvisionnements stock\u00e9s": {},
+ "6094-Rabais, remises et ristournes obtenus sur achats - d'\u00e9tudes et prestations de services": {},
+ "6095-Rabais, remises et ristournes obtenus sur achats - de mat\u00e9riel, \u00e9quipements et travaux": {},
+ "6096-Rabais, remises et ristournes obtenus sur achats - d'approvisionnements non stock\u00e9s": {},
+ "6097-Rabais, remises et ristournes obtenus sur achats - de marchandises": {},
"6098-Rabais, remises et ristournes non affect\u00e9s": {}
}
- },
+ },
"61-Services ext\u00e9rieurs": {
- "611-Sous-traitance g\u00e9n\u00e9rale": {},
+ "611-Sous-traitance g\u00e9n\u00e9rale": {},
"612-Redevances de cr\u00e9dit-bail": {
- "6122-Cr\u00e9dit-bail mobilier": {},
+ "6122-Cr\u00e9dit-bail mobilier": {},
"6125-Cr\u00e9dit-bail immobilier": {}
- },
+ },
"613-Locations": {
- "6132-Locations immobili\u00e8res": {},
- "6135-Locations mobili\u00e8res": {},
+ "6132-Locations immobili\u00e8res": {},
+ "6135-Locations mobili\u00e8res": {},
"6136-Malis sur emballages": {}
- },
- "614-Charges locatives et de copropri\u00e9t\u00e9": {},
+ },
+ "614-Charges locatives et de copropri\u00e9t\u00e9": {},
"615-Entretiens et r\u00e9parations": {
- "6152-Entretiens et r\u00e9parations - sur biens immobiliers": {},
- "6155-Entretiens et r\u00e9parations - sur biens mobiliers": {},
+ "6152-Entretiens et r\u00e9parations - sur biens immobiliers": {},
+ "6155-Entretiens et r\u00e9parations - sur biens mobiliers": {},
"6156-Maintenance": {}
- },
+ },
"616-Primes d'assurance": {
- "6161-Multirisques": {},
- "6162-Assurance obligatoire dommage construction": {},
+ "6161-Multirisques": {},
+ "6162-Assurance obligatoire dommage construction": {},
"6163-Assurance-transport": {
- "61636-Assurance-transport - sur achats": {},
- "61637-Assurance-transport - sur ventes": {},
+ "61636-Assurance-transport - sur achats": {},
+ "61637-Assurance-transport - sur ventes": {},
"61638-Assurance-transport - sur autres biens": {}
- },
- "6164-Risques d'exploitation": {},
+ },
+ "6164-Risques d'exploitation": {},
"6165-Insolvabilit\u00e9 clients": {}
- },
- "617-Etudes et recherches": {},
+ },
+ "617-Etudes et recherches": {},
"618-Divers": {
- "6181-Documentation g\u00e9n\u00e9rale": {},
- "6183-Documentation technique": {},
+ "6181-Documentation g\u00e9n\u00e9rale": {},
+ "6183-Documentation technique": {},
"6185-Frais de colloques, s\u00e9minaires, conf\u00e9rences": {}
- },
+ },
"619-Rabais, remises et ristournes obtenus sur services ext\u00e9rieurs": {}
- },
+ },
"62-Autres services ext\u00e9rieurs": {
"621-Personnel ext\u00e9rieur \u00e0 l'entreprise": {
- "6211-Personnel int\u00e9rimaire": {},
+ "6211-Personnel int\u00e9rimaire": {},
"6214-Personnel d\u00e9tach\u00e9 ou pr\u00eat\u00e9 \u00e0 l'entreprise": {}
- },
+ },
"622-R\u00e9mun\u00e9rations d'interm\u00e9diaires et honoraires": {
- "6221-Commissions et courtages sur achats": {},
- "6222-Commissions et courtages sur ventes": {},
- "6224-R\u00e9mun\u00e9rations des transitaires": {},
- "6225-R\u00e9mun\u00e9rations d'affacturage": {},
- "6226-Honoraires": {},
- "6227-Frais d'actes et de contentieux": {},
+ "6221-Commissions et courtages sur achats": {},
+ "6222-Commissions et courtages sur ventes": {},
+ "6224-R\u00e9mun\u00e9rations des transitaires": {},
+ "6225-R\u00e9mun\u00e9rations d'affacturage": {},
+ "6226-Honoraires": {},
+ "6227-Frais d'actes et de contentieux": {},
"6228-Divers": {}
- },
+ },
"623-Publicit\u00e9, publications, relations publiques": {
- "6231-Annonces et insertions": {},
- "6232-Echantillons": {},
- "6233-Foires et expositions": {},
- "6234-Cadeaux \u00e0 la client\u00e8le": {},
- "6235-Primes": {},
- "6236-Catalogues et imprim\u00e9s": {},
- "6237-Publications": {},
+ "6231-Annonces et insertions": {},
+ "6232-Echantillons": {},
+ "6233-Foires et expositions": {},
+ "6234-Cadeaux \u00e0 la client\u00e8le": {},
+ "6235-Primes": {},
+ "6236-Catalogues et imprim\u00e9s": {},
+ "6237-Publications": {},
"6238-Divers (pourboires, dons courants...)": {}
- },
+ },
"624-Transports de biens et transports collectifs du personnel": {
- "6241-Transports sur achats": {},
+ "6241-Transports sur achats": {},
"6242-Transports sur ventes": {
"account_type": "Chargeable"
- },
- "6243-Transports entre \u00e9tablissements ou chantiers": {},
- "6244-Transports administratifs": {},
- "6247-Transports collectifs du personnel": {},
+ },
+ "6243-Transports entre \u00e9tablissements ou chantiers": {},
+ "6244-Transports administratifs": {},
+ "6247-Transports collectifs du personnel": {},
"6248-Divers": {}
- },
+ },
"625-D\u00e9placements, missions et r\u00e9ceptions": {
- "6251-Voyages et d\u00e9placements": {},
- "6255-Frais de d\u00e9m\u00e9nagement": {},
- "6256-Missions": {},
+ "6251-Voyages et d\u00e9placements": {},
+ "6255-Frais de d\u00e9m\u00e9nagement": {},
+ "6256-Missions": {},
"6257-R\u00e9ceptions": {}
- },
- "626-Frais postaux et de t\u00e9l\u00e9communications": {},
+ },
+ "626-Frais postaux et de t\u00e9l\u00e9communications": {},
"627-Services bancaires et assimil\u00e9s": {
- "6271-Frais sur titres (achat, vente, garde)": {},
- "6272-Commissions et frais sur \u00e9mission d'emprunts": {},
- "6275-Frais sur effets": {},
- "6276-Location de coffres": {},
+ "6271-Frais sur titres (achat, vente, garde)": {},
+ "6272-Commissions et frais sur \u00e9mission d'emprunts": {},
+ "6275-Frais sur effets": {},
+ "6276-Location de coffres": {},
"6278-Autres frais et commissions sur prestations de services": {}
- },
+ },
"628-Divers": {
- "6281-Concours divers (cotisations...)": {},
+ "6281-Concours divers (cotisations...)": {},
"6284-Frais de recrutement de personnel": {}
- },
+ },
"629-Rabais, remises et ristournes obtenus sur autres services ext\u00e9rieurs": {}
- },
+ },
"63-Imp\u00f4ts, taxes et versements assimil\u00e9s": {
"631-Imp\u00f4ts, taxes et versements assimil\u00e9s sur r\u00e9mun\u00e9rations (administrations des imp\u00f4ts)": {
- "6311-Taxes sur les salaires": {},
- "6312-Taxe d'apprentissage": {},
- "6313-Participation des employeurs \u00e0 la formation professionnelle continue": {},
- "6314-Cotisation pour d\u00e9faut d'investissement obligatoire dans la construction": {},
+ "6311-Taxes sur les salaires": {},
+ "6312-Taxe d'apprentissage": {},
+ "6313-Participation des employeurs \u00e0 la formation professionnelle continue": {},
+ "6314-Cotisation pour d\u00e9faut d'investissement obligatoire dans la construction": {},
"6318-Autres": {}
- },
+ },
"633-Imp\u00f4ts, taxes et versements assimil\u00e9s sur r\u00e9mun\u00e9rations (autres organismes)": {
- "6331-Versement de transport": {},
- "6332-Allocations logement": {},
- "6333-Participation des employeurs \u00e0 la formation professionnelle continue": {},
- "6334-Participation des employeurs \u00e0 l'effort de construction": {},
- "6335-Versements lib\u00e9ratoires ouvrant droit \u00e0 l'\u00e9xon\u00e9ration de la taxe d'apprentissage": {},
+ "6331-Versement de transport": {},
+ "6332-Allocations logement": {},
+ "6333-Participation des employeurs \u00e0 la formation professionnelle continue": {},
+ "6334-Participation des employeurs \u00e0 l'effort de construction": {},
+ "6335-Versements lib\u00e9ratoires ouvrant droit \u00e0 l'\u00e9xon\u00e9ration de la taxe d'apprentissage": {},
"6338-Autres": {}
- },
+ },
"635-Autres imp\u00f4ts, taxes et versements assimil\u00e9s (administrations des imp\u00f4ts)": {
"6351-Imp\u00f4ts directs (sauf imp\u00f4ts sur les b\u00e9n\u00e9fices)": {
- "63511-Contribution \u00e9conomique territoriale": {},
- "63512-Taxes fonci\u00e8res": {},
- "63513-Autres imp\u00f4ts locaux": {},
+ "63511-Contribution \u00e9conomique territoriale": {},
+ "63512-Taxes fonci\u00e8res": {},
+ "63513-Autres imp\u00f4ts locaux": {},
"63514-Taxe sur les v\u00e9hicules des soci\u00e9t\u00e9s": {}
- },
- "6352-Taxes sur le chiffre d'affaires non r\u00e9cup\u00e9rables": {},
- "6353-Imp\u00f4ts indirects": {},
+ },
+ "6352-Taxes sur le chiffre d'affaires non r\u00e9cup\u00e9rables": {},
+ "6353-Imp\u00f4ts indirects": {},
"6354-Droits d'enregistrement et de timbre": {
"63541-Droits de mutation": {}
- },
+ },
"6358-Autres droits": {}
- },
+ },
"637-Autres imp\u00f4ts, taxes et versements assimil\u00e9s (autres organismes)": {
- "6371-Contribution sociale de solidarit\u00e9 \u00e0 la charge des soci\u00e9t\u00e9s": {},
- "6372-Taxes per\u00e7ues par les organismes publics internationaux": {},
- "6374-Imp\u00f4ts et taxes exigibles \u00e0 l'\u00e9tranger": {},
+ "6371-Contribution sociale de solidarit\u00e9 \u00e0 la charge des soci\u00e9t\u00e9s": {},
+ "6372-Taxes per\u00e7ues par les organismes publics internationaux": {},
+ "6374-Imp\u00f4ts et taxes exigibles \u00e0 l'\u00e9tranger": {},
"6378-Taxes diverses": {}
}
- },
+ },
"64-Charges de personnel": {
"641-R\u00e9mun\u00e9rations du personnel": {
- "6411-Salaires, appointements": {},
- "6412-Cong\u00e9s pay\u00e9s": {},
- "6413-Primes et gratifications": {},
- "6414-Indemnit\u00e9s et avantages divers": {},
+ "6411-Salaires, appointements": {},
+ "6412-Cong\u00e9s pay\u00e9s": {},
+ "6413-Primes et gratifications": {},
+ "6414-Indemnit\u00e9s et avantages divers": {},
"6415-Suppl\u00e9ment familial": {}
- },
- "644-R\u00e9mun\u00e9ration du travail de l'exploitant": {},
+ },
+ "644-R\u00e9mun\u00e9ration du travail de l'exploitant": {},
"645-Charges de s\u00e9curit\u00e9 sociale et de pr\u00e9voyance": {
- "6451-Cotisations \u00e0 l'URSSAF": {},
- "6452-Cotisations aux mutuelles": {},
- "6453-Cotisations aux caisses de retraites": {},
+ "6451-Cotisations \u00e0 l'URSSAF": {},
+ "6452-Cotisations aux mutuelles": {},
+ "6453-Cotisations aux caisses de retraites": {},
"6454-Cotisations aux ASSEDIC": {}
- },
- "646-Cotisations sociales personnelles de l'exploitant": {},
+ },
+ "646-Cotisations sociales personnelles de l'exploitant": {},
"647-Autres charges sociales": {
"is_group": 1
- },
+ },
"648-Autres charges de personnel": {}
- },
+ },
"65-Autres charges de gestion courante": {
"651-Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels, droits et valeurs similaires": {
- "6511-Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels": {},
- "6516-Droits d'auteur et de reproduction": {},
+ "6511-Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels": {},
+ "6516-Droits d'auteur et de reproduction": {},
"6518-Autres droits et valeurs similaires": {}
- },
- "653-Jetons de pr\u00e9sence": {},
+ },
+ "653-Jetons de pr\u00e9sence": {},
"654-Pertes sur cr\u00e9ances irr\u00e9couvrables": {
- "6541-Cr\u00e9ances de l'exercice": {},
+ "6541-Cr\u00e9ances de l'exercice": {},
"6544-Cr\u00e9ances des exercices ant\u00e9rieurs": {}
- },
+ },
"655-Quotes-parts de r\u00e9sultat sur op\u00e9rations faites en commun": {
- "6551-Quote-part de b\u00e9n\u00e9fice transf\u00e9r\u00e9e (comptabilit\u00e9 du g\u00e9rant)": {},
+ "6551-Quote-part de b\u00e9n\u00e9fice transf\u00e9r\u00e9e (comptabilit\u00e9 du g\u00e9rant)": {},
"6555-Quote-part de perte support\u00e9e (comptabilit\u00e9 des associ\u00e9s non g\u00e9rants)": {}
- },
- "656-Pertes de change sur cr\u00e9ances et dettes commerciales": {},
+ },
+ "656-Pertes de change sur cr\u00e9ances et dettes commerciales": {},
"658-Charges diverses de gestion courante": {}
- },
+ },
"66-Charges financi\u00e8res": {
"661-Charges d'int\u00e9r\u00eats": {
"6611-Int\u00e9r\u00eats des emprunts et dettes": {
- "66116-Int\u00e9r\u00eats des emprunts et dettes - des emprunts et dettes assimil\u00e9es": {},
+ "66116-Int\u00e9r\u00eats des emprunts et dettes - des emprunts et dettes assimil\u00e9es": {},
"66117-Int\u00e9r\u00eats des emprunts et dettes - des dettes rattach\u00e9es \u00e0 des participations": {}
- },
- "6612-Charges de la fiducie, r\u00e9sultat de la p\u00e9riode": {},
- "6615-Int\u00e9r\u00eats des comptes courants et des d\u00e9p\u00f4ts cr\u00e9diteurs": {},
- "6616-Int\u00e9r\u00eats bancaires et sur op\u00e9rations de financement (escompte...)": {},
- "6617-Int\u00e9r\u00eats des obligations cautionn\u00e9es": {},
+ },
+ "6612-Charges de la fiducie, r\u00e9sultat de la p\u00e9riode": {},
+ "6615-Int\u00e9r\u00eats des comptes courants et des d\u00e9p\u00f4ts cr\u00e9diteurs": {},
+ "6616-Int\u00e9r\u00eats bancaires et sur op\u00e9rations de financement (escompte...)": {},
+ "6617-Int\u00e9r\u00eats des obligations cautionn\u00e9es": {},
"6618-Int\u00e9r\u00eats des autres dettes": {
- "66181-Int\u00e9r\u00eats des autres dettes - des dettes commerciales": {},
+ "66181-Int\u00e9r\u00eats des autres dettes - des dettes commerciales": {},
"66188-Int\u00e9r\u00eats des autres dettes - des dettes diverses": {}
}
- },
- "664-Pertes sur cr\u00e9ances li\u00e9es \u00e0 des participations": {},
- "665-Escomptes accord\u00e9s": {},
+ },
+ "664-Pertes sur cr\u00e9ances li\u00e9es \u00e0 des participations": {},
+ "665-Escomptes accord\u00e9s": {},
"666-Pertes de change financi\u00e8res": {
"account_type": "Round Off"
- },
- "667-Charges nettes sur cessions de valeurs mobili\u00e8res de placement": {},
+ },
+ "667-Charges nettes sur cessions de valeurs mobili\u00e8res de placement": {},
"668-Autres charges financi\u00e8res": {}
- },
+ },
"67-Charges exceptionnelles": {
"671-Charges exceptionnelles sur op\u00e9rations de gestion": {
- "6711-P\u00e9nalit\u00e9s sur march\u00e9s (et d\u00e9dits pay\u00e9s sur achats et ventes)": {},
- "6712-P\u00e9nalit\u00e9s, amendes fiscales et p\u00e9nales": {},
- "6713-Dons, lib\u00e9ralit\u00e9s": {},
- "6714-Cr\u00e9ances devenues irr\u00e9couvrables dans l'exercice": {},
- "6715-Subventions accord\u00e9es": {},
- "6717-Rappel d'imp\u00f4ts (autres qu'imp\u00f4ts sur les b\u00e9n\u00e9fices)": {},
+ "6711-P\u00e9nalit\u00e9s sur march\u00e9s (et d\u00e9dits pay\u00e9s sur achats et ventes)": {},
+ "6712-P\u00e9nalit\u00e9s, amendes fiscales et p\u00e9nales": {},
+ "6713-Dons, lib\u00e9ralit\u00e9s": {},
+ "6714-Cr\u00e9ances devenues irr\u00e9couvrables dans l'exercice": {},
+ "6715-Subventions accord\u00e9es": {},
+ "6717-Rappel d'imp\u00f4ts (autres qu'imp\u00f4ts sur les b\u00e9n\u00e9fices)": {},
"6718-Autres charges exceptionnelles sur op\u00e9rations de gestion": {}
- },
- "672-(Compte \u00e0 la disposition des entit\u00e9s pour enregistrer, en cours d'exercice, les charges sur exercices ant\u00e9rieurs)": {},
+ },
+ "672-(Compte \u00e0 la disposition des entit\u00e9s pour enregistrer, en cours d'exercice, les charges sur exercices ant\u00e9rieurs)": {},
"674-Op\u00e9rations de constitution ou liquidation des fiducies": {
- "6741-Op\u00e9rations li\u00e9es \u00e0 la constitution de la fiducie - transfert des \u00e9l\u00e9ments": {},
+ "6741-Op\u00e9rations li\u00e9es \u00e0 la constitution de la fiducie - transfert des \u00e9l\u00e9ments": {},
"6742-Op\u00e9rations li\u00e9es \u00e0 la liquidation de la fiducie": {}
- },
+ },
"675-Valeurs comptables des \u00e9l\u00e9ments d'actif c\u00e9d\u00e9s": {
- "6751-Immobilisations incorporelles": {},
- "6752-Immobilisations corporelles": {},
- "6756-Immobilisations financi\u00e8res": {},
+ "6751-Immobilisations incorporelles": {},
+ "6752-Immobilisations corporelles": {},
+ "6756-Immobilisations financi\u00e8res": {},
"6758-Autres \u00e9l\u00e9ments d'actif": {}
- },
+ },
"678-Autres charges exceptionnelles": {
- "6781-Mali provenant de clauses d'indexation": {},
- "6782-Lots": {},
- "6783-Malis provenant du rachat par l'entreprise d'actions et obligations \u00e9mises par elles-m\u00eame": {},
+ "6781-Mali provenant de clauses d'indexation": {},
+ "6782-Lots": {},
+ "6783-Malis provenant du rachat par l'entreprise d'actions et obligations \u00e9mises par elles-m\u00eame": {},
"6788-Charges exceptionnelles diverses": {}
}
- },
+ },
"68-Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions": {
"681-Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions - Charges d'exploitation": {
"6811-Dotations aux amortissements sur immobilisations incorporelles et corporelles": {
"68111-Immobilisations incorporelles": {
"account_type": "Depreciation"
- },
+ },
"68112-Immobilisations corporelles": {
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"6812-Dotations aux amortissements des charges d'exploitation \u00e0 r\u00e9partir": {
"account_type": "Depreciation"
- },
+ },
"6815-Dotations aux provisions d'exploitation": {
"account_type": "Depreciation"
- },
+ },
"6816-Dotations aux d\u00e9pr\u00e9ciations des immobilisations incorporelles et corporelles": {
"68161-Immobilisations incorporelles": {
"account_type": "Depreciation"
- },
+ },
"68162-Immobilisations corporelles": {
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"6817-Dotations pour d\u00e9pr\u00e9ciations des actifs circulants": {
"68173-Stocks et en-cours": {
"account_type": "Depreciation"
- },
+ },
"68174-Cr\u00e9ances": {
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"686-Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions - Charges financi\u00e8res": {
"6861-Dotations aux amortissements des primes de remboursement des obligations": {
"account_type": "Depreciation"
- },
+ },
"6865-Dotations aux provisions financi\u00e8res": {
"account_type": "Depreciation"
- },
+ },
"6866-Dotations aux d\u00e9pr\u00e9ciations des \u00e9l\u00e9ments financiers": {
"68662-Immobilisations financi\u00e8res": {
"account_type": "Depreciation"
- },
+ },
"68665-Valeurs mobili\u00e8res de placement": {
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"6868-Autres dotations": {
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"687-Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions - Charges exceptionnelles": {
"6871-Dotations aux amortissements exceptionnels des immobilisations": {
"account_type": "Depreciation"
- },
+ },
"6872-Dotations aux provisions r\u00e9glement\u00e9es (immobilisations)": {
"68725-Amortissements d\u00e9rogatoires": {
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"6873-Dotations aux provisions r\u00e9glement\u00e9es (stocks)": {
"account_type": "Depreciation"
- },
+ },
"6874-Dotations aux autres provisions r\u00e9glement\u00e9es": {
"account_type": "Depreciation"
- },
+ },
"6875-Dotations aux provisions exceptionnelles": {
"account_type": "Depreciation"
- },
+ },
"6876-Dotations aux d\u00e9pr\u00e9ciations exceptionnelles": {
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"account_type": "Depreciation"
- },
+ },
"69-Participation des salari\u00e9s, imp\u00f4ts sur les b\u00e9n\u00e9fices et assimil\u00e9s": {
- "691-Participation des salari\u00e9s aux r\u00e9sultats": {},
+ "691-Participation des salari\u00e9s aux r\u00e9sultats": {},
"695-Imp\u00f4ts sur les b\u00e9n\u00e9fices": {
- "6951-Imp\u00f4ts dus en France": {},
- "6952-Contribution additionnelle \u00e0 l'imp\u00f4t sur les b\u00e9n\u00e9fices": {},
+ "6951-Imp\u00f4ts dus en France": {},
+ "6952-Contribution additionnelle \u00e0 l'imp\u00f4t sur les b\u00e9n\u00e9fices": {},
"6954-Imp\u00f4ts dus \u00e0 l'\u00e9tranger": {}
- },
- "696-Suppl\u00e9ments d'imp\u00f4ts sur les soci\u00e9t\u00e9s, li\u00e9s aux distributions": {},
+ },
+ "696-Suppl\u00e9ments d'imp\u00f4ts sur les soci\u00e9t\u00e9s, li\u00e9s aux distributions": {},
"698-Int\u00e9gration fiscale": {
- "6981-Int\u00e9gration fiscale - Charges": {},
+ "6981-Int\u00e9gration fiscale - Charges": {},
"6989-Int\u00e9gration fiscale - Produits": {}
- },
+ },
"699-Produits - Report en arri\u00e8re des d\u00e9ficits": {}
- },
+ },
"root_type": "Expense"
- },
+ },
"7-Comptes de Produits": {
"70-Ventes de produits fabriqu\u00e9s, prestations de services, marchandises": {
"701-Ventes de produits finis": {
- "7011-Produits finis (ou groupe) A": {},
+ "7011-Produits finis (ou groupe) A": {},
"7012-Produits (ou groupe) B": {}
- },
- "702-Ventes de produits interm\u00e9diaires": {},
- "703-Ventes de produits r\u00e9siduels": {},
+ },
+ "702-Ventes de produits interm\u00e9diaires": {},
+ "703-Ventes de produits r\u00e9siduels": {},
"704-Travaux": {
- "7041-Travaux de cat\u00e9gorie (ou activit\u00e9) A": {},
+ "7041-Travaux de cat\u00e9gorie (ou activit\u00e9) A": {},
"7042-Travaux de cat\u00e9gorie (ou activit\u00e9) B": {}
- },
- "705-Etudes": {},
- "706-Prestations de services": {},
+ },
+ "705-Etudes": {},
+ "706-Prestations de services": {},
"707-Ventes de marchandises": {
- "7071-Marchandises (ou groupe) A": {},
+ "7071-Marchandises (ou groupe) A": {},
"7072-Marchandises (ou groupe) B": {}
- },
+ },
"708-Produits des activit\u00e9s annexes": {
- "7081-Produits des services exploit\u00e9s dans l'int\u00e9r\u00eat du personnel": {},
- "7082-Commissions et courtages": {},
- "7083-Locations diverses": {},
- "7084-Mise \u00e0 disposition de personnel factur\u00e9e": {},
- "7085-Ports et frais accessoires factur\u00e9s": {},
- "7086-Bonis sur reprises d'emballages consign\u00e9s": {},
- "7087-Bonifications obtenues des clients et primes sur ventes": {},
+ "7081-Produits des services exploit\u00e9s dans l'int\u00e9r\u00eat du personnel": {},
+ "7082-Commissions et courtages": {},
+ "7083-Locations diverses": {},
+ "7084-Mise \u00e0 disposition de personnel factur\u00e9e": {},
+ "7085-Ports et frais accessoires factur\u00e9s": {},
+ "7086-Bonis sur reprises d'emballages consign\u00e9s": {},
+ "7087-Bonifications obtenues des clients et primes sur ventes": {},
"7088-Autres produits d'activit\u00e9s annexes (cessions d'approvisionnements...)": {}
- },
+ },
"709-Rabais, remises et ristournes accord\u00e9s par l'entreprise": {
- "7091-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de produits finis": {},
- "7092-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de produits interm\u00e9diaires": {},
- "7094-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur travaux": {},
- "7095-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur \u00e9tudes": {},
- "7096-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur prestations de services": {},
- "7097-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de marchandises": {},
+ "7091-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de produits finis": {},
+ "7092-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de produits interm\u00e9diaires": {},
+ "7094-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur travaux": {},
+ "7095-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur \u00e9tudes": {},
+ "7096-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur prestations de services": {},
+ "7097-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de marchandises": {},
"7098-Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur produits des activit\u00e9s annexes": {}
}
- },
+ },
"71-Production stock\u00e9e (ou d\u00e9stockage)": {
"713-Variation des stocks (en-cours de production, produits)": {
"7133-Variation des en-cours de production de biens": {
- "71331-Produits en cours": {},
+ "71331-Produits en cours": {},
"71335-Travaux en cours": {}
- },
+ },
"7134-Variation des en-cours de production de services": {
- "71341-Etudes en cours": {},
+ "71341-Etudes en cours": {},
"71345-Prestations de services en cours": {}
- },
+ },
"7135-Variation des stocks de produits": {
- "71351-Produits interm\u00e9diaires": {},
- "71355-Produits finis": {},
+ "71351-Produits interm\u00e9diaires": {},
+ "71355-Produits finis": {},
"71358-Produits r\u00e9siduels": {}
}
}
- },
+ },
"72-Production immobilis\u00e9e": {
- "721-Immobilisations incorporelles": {},
+ "721-Immobilisations incorporelles": {},
"722-Immobilisations corporelles": {}
- },
+ },
"74-Subventions d'exploitation": {
"is_group": 1
- },
+ },
"75-Autres produits de gestion courante": {
"751-Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels, droits et valeurs similaires": {
- "7511-Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels": {},
- "7516-Droits d'auteur et de reproduction": {},
+ "7511-Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels": {},
+ "7516-Droits d'auteur et de reproduction": {},
"7518-Autres droits et valeurs similaires": {}
- },
- "752-Revenus des immeubles non affect\u00e9s aux activit\u00e9s professionnelles": {},
- "753-Jetons de pr\u00e9sence et r\u00e9mun\u00e9rations d'administrateurs, g\u00e9rants...": {},
- "754-Ristournes per\u00e7ues des coop\u00e9ratives (provenant des exc\u00e9dents)": {},
+ },
+ "752-Revenus des immeubles non affect\u00e9s aux activit\u00e9s professionnelles": {},
+ "753-Jetons de pr\u00e9sence et r\u00e9mun\u00e9rations d'administrateurs, g\u00e9rants...": {},
+ "754-Ristournes per\u00e7ues des coop\u00e9ratives (provenant des exc\u00e9dents)": {},
"755-Quotes-parts de r\u00e9sultats sur op\u00e9rations faites en commun": {
- "7551-Quote-part de perte transf\u00e9r\u00e9e (comptabilit\u00e9 du g\u00e9rant)": {},
+ "7551-Quote-part de perte transf\u00e9r\u00e9e (comptabilit\u00e9 du g\u00e9rant)": {},
"7555-Quote-part de b\u00e9n\u00e9fice attribu\u00e9 (comptabilit\u00e9 des associ\u00e9s non g\u00e9rants)": {}
- },
- "756-Gains de change sur cr\u00e9ances et dettes commerciales": {},
+ },
+ "756-Gains de change sur cr\u00e9ances et dettes commerciales": {},
"758-Produits divers de gestion courante": {}
- },
+ },
"76-Produits financiers": {
"761-Produits de participations": {
- "7611-Revenus des titres de participation": {},
- "7612-Produits de la fiducie, r\u00e9sultat de la p\u00e9riode": {},
- "7616-Revenus sur autres formes de participation": {},
+ "7611-Revenus des titres de participation": {},
+ "7612-Produits de la fiducie, r\u00e9sultat de la p\u00e9riode": {},
+ "7616-Revenus sur autres formes de participation": {},
"7617-Revenus des cr\u00e9ances rattach\u00e9es \u00e0 des participations": {}
- },
+ },
"762-Produits des autres immobilisations financi\u00e8res": {
- "7621-Revenus des titres immobilis\u00e9s": {},
- "7626-Revenus des pr\u00eats": {},
+ "7621-Revenus des titres immobilis\u00e9s": {},
+ "7626-Revenus des pr\u00eats": {},
"7627-Revenus des cr\u00e9ances immobilis\u00e9es": {}
- },
+ },
"763-Revenus des autres cr\u00e9ances": {
- "7631-Revenus des cr\u00e9ances commerciales": {},
+ "7631-Revenus des cr\u00e9ances commerciales": {},
"7638-Revenus des cr\u00e9ances diverses": {}
- },
- "764-Revenus des valeurs mobili\u00e8res de placement": {},
- "765-Escomptes obtenus": {},
+ },
+ "764-Revenus des valeurs mobili\u00e8res de placement": {},
+ "765-Escomptes obtenus": {},
"766-Gains de change financi\u00e8res": {
"account_type": "Round Off"
- },
- "767-Produits nets sur cessions de valeurs mobili\u00e8res de placement": {},
+ },
+ "767-Produits nets sur cessions de valeurs mobili\u00e8res de placement": {},
"768-Autres produits financiers": {}
- },
+ },
"77-Produits exceptionnels": {
"771-Produits exceptionnels sur op\u00e9rations de gestion": {
- "7711-D\u00e9dits et p\u00e9nalit\u00e9s per\u00e7us sur achats et sur ventes": {},
- "7713-Lib\u00e9ralit\u00e9s re\u00e7ues": {},
- "7714-Rentr\u00e9es sur cr\u00e9ances amorties": {},
- "7715-Subventions d'\u00e9quilibre": {},
- "7717-D\u00e9gr\u00e8vements d'imp\u00f4ts autres qu'imp\u00f4ts sur les b\u00e9n\u00e9fices": {},
+ "7711-D\u00e9dits et p\u00e9nalit\u00e9s per\u00e7us sur achats et sur ventes": {},
+ "7713-Lib\u00e9ralit\u00e9s re\u00e7ues": {},
+ "7714-Rentr\u00e9es sur cr\u00e9ances amorties": {},
+ "7715-Subventions d'\u00e9quilibre": {},
+ "7717-D\u00e9gr\u00e8vements d'imp\u00f4ts autres qu'imp\u00f4ts sur les b\u00e9n\u00e9fices": {},
"7718-Autres produits exceptionnels sur op\u00e9rations de gestion": {}
- },
- "772-(Compte \u00e0 la disposition des entit\u00e9s pour enregistrer, en cours d'exercice, les Produits sur exercices ant\u00e9rieurs)": {},
+ },
+ "772-(Compte \u00e0 la disposition des entit\u00e9s pour enregistrer, en cours d'exercice, les Produits sur exercices ant\u00e9rieurs)": {},
"774-Op\u00e9rations de constitution ou liquidation des fiducies": {
- "7741-Op\u00e9rations li\u00e9es \u00e0 la constitution de la fiducie - transfert des \u00e9l\u00e9ments": {},
+ "7741-Op\u00e9rations li\u00e9es \u00e0 la constitution de la fiducie - transfert des \u00e9l\u00e9ments": {},
"7742-Op\u00e9rations li\u00e9es \u00e0 la liquidation de la fiducie": {}
- },
+ },
"775-Produits des cessions d'\u00e9l\u00e9ments d'actif": {
- "7751-Immobilisations incorporelles": {},
- "7752-Immobilisations corporelles": {},
- "7756-Immobilisations financi\u00e8res": {},
+ "7751-Immobilisations incorporelles": {},
+ "7752-Immobilisations corporelles": {},
+ "7756-Immobilisations financi\u00e8res": {},
"7758-Autres \u00e9l\u00e9ments d'actif": {}
- },
- "777-Quote-part des subventions d'investissement vir\u00e9e au r\u00e9sultat de l'exercice": {},
+ },
+ "777-Quote-part des subventions d'investissement vir\u00e9e au r\u00e9sultat de l'exercice": {},
"778-Autres produits exceptionnels": {
- "7781-Bonis provenant de clauses d'indexation": {},
- "7782-Lots": {},
- "7783-Bonis provenant du rachat par l'entreprise d'actions et d'obligations \u00e9mises par elle-m\u00eame": {},
+ "7781-Bonis provenant de clauses d'indexation": {},
+ "7782-Lots": {},
+ "7783-Bonis provenant du rachat par l'entreprise d'actions et d'obligations \u00e9mises par elle-m\u00eame": {},
"7788-Produits exceptionnels divers": {}
}
- },
+ },
"78-Reprises sur amortissements, d\u00e9pr\u00e9ciations et provisions": {
"781-Reprises sur amortissements, d\u00e9pr\u00e9ciations et provisions (\u00e0 inscrire dans les produits d'exploitation)": {
"7811-Reprises sur amortissements des immobilisations incorporelles et corporelles": {
- "78111-Immobilisations incorporelles": {},
+ "78111-Immobilisations incorporelles": {},
"78112-Immobilisations corporelles": {}
- },
- "7815-Reprises sur provisions d'exploitation": {},
+ },
+ "7815-Reprises sur provisions d'exploitation": {},
"7816-Reprises sur d\u00e9pr\u00e9ciations des immobilisations corporelles et incorporelles": {
- "78161-Immobilisations incorporelles": {},
+ "78161-Immobilisations incorporelles": {},
"78162-Immobilisations corporelles": {}
- },
+ },
"7817-Reprises sur d\u00e9pr\u00e9ciations des actifs circulants": {
- "78173-Stocks et en-cours": {},
+ "78173-Stocks et en-cours": {},
"78174-Cr\u00e9ances": {}
}
- },
+ },
"786-Reprises sur d\u00e9pr\u00e9ciations et provisions (\u00e0 inscrire dans les produits financiers)": {
- "7865-Reprises sur provisions financi\u00e8res": {},
+ "7865-Reprises sur provisions financi\u00e8res": {},
"7866-Reprises sur d\u00e9pr\u00e9ciations des \u00e9l\u00e9ments financiers": {
- "78662-Immobilisations financi\u00e8res": {},
+ "78662-Immobilisations financi\u00e8res": {},
"78665-Valeurs mobili\u00e8res de placement": {}
}
- },
+ },
"787-Reprises sur d\u00e9pr\u00e9ciations et provisions (\u00e0 inscrire dans les produits exceptionnels)": {
"7872-Reprises sur provisions r\u00e9glement\u00e9es (immobilisations)": {
- "78725-Amortissements d\u00e9rogatoires": {},
- "78726-Provision sp\u00e9ciale de r\u00e9\u00e9valuation": {},
+ "78725-Amortissements d\u00e9rogatoires": {},
+ "78726-Provision sp\u00e9ciale de r\u00e9\u00e9valuation": {},
"78727-Plus-values r\u00e9investies": {}
- },
- "7873-Reprises sur provisions r\u00e9glement\u00e9es (stocks)": {},
- "7874-Reprises sur autres provisions r\u00e9glement\u00e9es": {},
- "7875-Reprises sur provisions exceptionnelles": {},
+ },
+ "7873-Reprises sur provisions r\u00e9glement\u00e9es (stocks)": {},
+ "7874-Reprises sur autres provisions r\u00e9glement\u00e9es": {},
+ "7875-Reprises sur provisions exceptionnelles": {},
"7876-Reprises sur d\u00e9pr\u00e9ciations exceptionnelles": {}
}
- },
+ },
"79-Transferts de charges": {
- "791-Transferts de charges d'exploitation": {},
- "796-Transferts de charges financi\u00e8res": {},
+ "791-Transferts de charges d'exploitation": {},
+ "796-Transferts de charges financi\u00e8res": {},
"797-Transferts de charges exceptionnelles": {}
- },
+ },
"root_type": "Income"
}
}
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general_avec_code.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general_avec_code.json
new file mode 100644
index 0000000000..b6673795be
--- /dev/null
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general_avec_code.json
@@ -0,0 +1,3144 @@
+{
+ "country_code": "fr",
+ "name": "France - Plan Comptable General avec code",
+ "tree": {
+ "Comptes de Capitaux": {
+ "root_type": "Equity",
+ "Capital et R\u00e9serves": {
+ "Capital": {
+ "Capital souscrit - non appel\u00e9": {
+ "account_number": "1011"
+ },
+ "Capital souscrit - appel\u00e9, non vers\u00e9": {
+ "account_number": "1012"
+ },
+ "Capital souscrit - appel\u00e9, vers\u00e9": {
+ "Capital non amorti": {
+ "account_number": "10131"
+ },
+ "Capital amorti": {
+ "account_number": "10132"
+ },
+ "account_number": "1013"
+ },
+ "Capital souscrit soumis \u00e0 des r\u00e9glementations particuli\u00e8res": {
+ "account_number": "1018"
+ },
+ "account_number": "101"
+ },
+ "Fonds fiduciaires": {
+ "account_number": "102"
+ },
+ "Primes li\u00e9es au capital social": {
+ "Primes d'\u00e9mission": {
+ "account_number": "1041"
+ },
+ "Primes de fusion": {
+ "account_number": "1042"
+ },
+ "Primes d'apport": {
+ "account_number": "1043"
+ },
+ "Primes de conversion d'obligations en actions": {
+ "account_number": "1044"
+ },
+ "Bons de souscription d'actions": {
+ "account_number": "1045"
+ },
+ "account_number": "104"
+ },
+ "Ecarts de r\u00e9\u00e9valuation": {
+ "R\u00e9serve sp\u00e9ciale de r\u00e9\u00e9valuation": {
+ "account_number": "1051"
+ },
+ "Ecart de r\u00e9\u00e9valuation libre": {
+ "account_number": "1052"
+ },
+ "R\u00e9serve de r\u00e9\u00e9valuation": {
+ "account_number": "1053"
+ },
+ "Ecarts de r\u00e9\u00e9valuation (autres op\u00e9rations l\u00e9gales)": {
+ "account_number": "1055"
+ },
+ "Autres \u00e9carts de r\u00e9\u00e9valuation en France": {
+ "account_number": "1057"
+ },
+ "Autres \u00e9carts de r\u00e9\u00e9valuation \u00e0 l'\u00e9tranger": {
+ "account_number": "1058"
+ },
+ "account_number": "105"
+ },
+ "R\u00e9serves": {
+ "R\u00e9serve l\u00e9gale": {
+ "R\u00e9serve l\u00e9gale proprement dite": {
+ "account_number": "10611"
+ },
+ "Plus-values nettes \u00e0 long terme": {
+ "account_number": "10612"
+ },
+ "account_number": "1061"
+ },
+ "R\u00e9serves indisponibles": {
+ "account_number": "1062"
+ },
+ "R\u00e9serves statutaires ou contractuelles": {
+ "account_number": "1063"
+ },
+ "R\u00e9serves r\u00e9glement\u00e9es": {
+ "Plus-values nettes \u00e0 long terme": {
+ "account_number": "10641"
+ },
+ "R\u00e9serves cons\u00e9cutives \u00e0 l'octroi de subventions d'investissement": {
+ "account_number": "10643"
+ },
+ "Autres r\u00e9serves r\u00e9glement\u00e9es": {
+ "account_number": "10648"
+ },
+ "account_number": "1064"
+ },
+ "Autres r\u00e9serves": {
+ "R\u00e9serve de propre assureur": {
+ "account_number": "10681"
+ },
+ "R\u00e9serves diverses": {
+ "account_number": "10688"
+ },
+ "account_number": "1068"
+ },
+ "account_number": "106"
+ },
+ "Ecarts d'\u00e9quivalence": {
+ "account_number": "107"
+ },
+ "Compte de l'exploitant": {
+ "account_number": "108"
+ },
+ "Actionnaires: Capital souscrit - non appel\u00e9": {
+ "account_number": "109"
+ },
+ "account_number": "10"
+ },
+ "Report \u00e0 Nouveau": {
+ "Report \u00e0 nouveau (solde cr\u00e9diteur)": {
+ "account_number": "110"
+ },
+ "Report \u00e0 nouveau (solde d\u00e9biteur)": {
+ "account_number": "119"
+ },
+ "account_number": "11"
+ },
+ "R\u00e9sultat de l'Exercice": {
+ "R\u00e9sultat de l'exercice (b\u00e9n\u00e9fice)": {
+ "account_number": "120"
+ },
+ "R\u00e9sultat de l'exercice (perte)": {
+ "account_number": "129"
+ },
+ "account_number": "12"
+ },
+ "Subventions d'Investissement": {
+ "Subventions d'\u00e9quipement": {
+ "Etat": {
+ "account_number": "1311"
+ },
+ "R\u00e9gions": {
+ "account_number": "1312"
+ },
+ "D\u00e9partements": {
+ "account_number": "1313"
+ },
+ "Communes": {
+ "account_number": "1314"
+ },
+ "Collectivit\u00e9s publiques": {
+ "account_number": "1315"
+ },
+ "Entreprises publiques": {
+ "account_number": "1316"
+ },
+ "Entreprises et organismes priv\u00e9s": {
+ "account_number": "1317"
+ },
+ "Autres": {
+ "account_number": "1318"
+ },
+ "account_number": "131"
+ },
+ "Autres subventions d'investissement (m\u00eame ventilation que celle du compte 131)": {
+ "account_number": "138"
+ },
+ "Subventions d'investissement inscrites au compte de r\u00e9sultat": {
+ "Subventions d'\u00e9quipement": {
+ "Etat": {
+ "account_number": "13911"
+ },
+ "R\u00e9gions": {
+ "account_number": "13912"
+ },
+ "D\u00e9partements": {
+ "account_number": "13913"
+ },
+ "Communes": {
+ "account_number": "13914"
+ },
+ "Collectivit\u00e9s publiques": {
+ "account_number": "13915"
+ },
+ "Entreprises publiques": {
+ "account_number": "13916"
+ },
+ "Entreprises et organismes priv\u00e9s": {
+ "account_number": "13917"
+ },
+ "Autres": {
+ "account_number": "13918"
+ },
+ "account_number": "1391"
+ },
+ "Autres subventions d'investissement (m\u00eame ventilation que celle du compte 1391)": {
+ "account_number": "1398"
+ },
+ "account_number": "139"
+ },
+ "account_number": "13"
+ },
+ "Provisions R\u00e9glement\u00e9es": {
+ "Provisions r\u00e9glement\u00e9es relative aux immobilisations": {
+ "Provisions pour reconstitution des gisements miniers et p\u00e9troliers": {
+ "account_number": "1423"
+ },
+ "Provisions pour investissement (participation des salari\u00e9s)": {
+ "account_number": "1424"
+ },
+ "account_number": "142"
+ },
+ "Provisions r\u00e9glement\u00e9es relatives aux stocks": {
+ "Hausse des prix": {
+ "account_number": "1431"
+ },
+ "Fluctuation des cours": {
+ "account_number": "1432"
+ },
+ "account_number": "143"
+ },
+ "Provisions r\u00e9glement\u00e9es relatives aux autres \u00e9l\u00e9ments de l'actif": {
+ "account_number": "144"
+ },
+ "Amortissements d\u00e9rogatoires": {
+ "account_number": "145"
+ },
+ "Provision sp\u00e9ciale de r\u00e9\u00e9valuation": {
+ "account_number": "146"
+ },
+ "Plus-values r\u00e9investies": {
+ "account_number": "147"
+ },
+ "Autres provisions r\u00e9glement\u00e9es": {
+ "account_number": "148"
+ },
+ "account_number": "14"
+ },
+ "Provisions": {
+ "Provisions pour risques": {
+ "Provisions pour litiges": {
+ "account_number": "1511"
+ },
+ "Provisions pour garanties donn\u00e9es aux clients": {
+ "account_number": "1512"
+ },
+ "Provisions pour pertes sur march\u00e9s \u00e0 terme": {
+ "account_number": "1513"
+ },
+ "Provisions pour amendes et p\u00e9nalit\u00e9s": {
+ "account_number": "1514"
+ },
+ "Provisions pour pertes de change": {
+ "account_number": "1515"
+ },
+ "Provisions pour pertes sur contrats": {
+ "account_number": "1516"
+ },
+ "Autres provisions pour risques": {
+ "account_number": "1518"
+ },
+ "account_number": "151"
+ },
+ "Provisions pour pensions et obligations similaires": {
+ "account_number": "153"
+ },
+ "Provisions pour restructurations": {
+ "account_number": "154"
+ },
+ "Provisions pour imp\u00f4ts": {
+ "account_number": "155"
+ },
+ "Provisions pour renouvellement des immobilisations (entreprises concessionnaires) ": {
+ "account_number": "156"
+ },
+ "Provisions pour charges \u00e0 r\u00e9partir sur plusieurs exercices": {
+ "Provisions pour gros entretien ou grandes r\u00e9visions": {
+ "account_number": "1572"
+ },
+ "account_number": "157"
+ },
+ "Autres provisions pour charges": {
+ "Provisions pour remises en \u00e9tat": {
+ "account_number": "1581"
+ },
+ "account_number": "158"
+ },
+ "account_number": "15"
+ },
+ "Emprunts et Dettes Assimil\u00e9es": {
+ "Emprunts obligataires convertibles": {
+ "account_number": "161"
+ },
+ "Obligations repr\u00e9sentatives de passifs nets remis en fiducie": {
+ "account_number": "162"
+ },
+ "Autres emprunts obligataires": {
+ "account_number": "163"
+ },
+ "Emprunts aupr\u00e8s des \u00e9tablissements de cr\u00e9dit": {
+ "account_number": "164"
+ },
+ "D\u00e9p\u00f4ts et cautionnements re\u00e7us": {
+ "D\u00e9p\u00f4ts": {
+ "account_number": "1651"
+ },
+ "Cautionnements": {
+ "account_number": "1655"
+ },
+ "account_number": "165"
+ },
+ "Participation des salari\u00e9s aux r\u00e9sultats": {
+ "Comptes bloqu\u00e9s": {
+ "account_number": "1661"
+ },
+ "Fonds de participation": {
+ "account_number": "1662"
+ },
+ "account_number": "166"
+ },
+ "Emprunts et dettes assortis de conditions particuli\u00e8res": {
+ "Emissions de titres participatifs": {
+ "account_number": "1671"
+ },
+ "Avances conditionn\u00e9es de l'Etat": {
+ "account_number": "1674"
+ },
+ "Emprunts participatifs": {
+ "account_number": "1675"
+ },
+ "account_number": "167"
+ },
+ "Autres emprunts et dettes assimil\u00e9es": {
+ "Autres emprunts": {
+ "account_number": "1681"
+ },
+ "Rentes viag\u00e8res capitalis\u00e9es": {
+ "account_number": "1685"
+ },
+ "Autres dettes": {
+ "account_number": "1687"
+ },
+ "Int\u00e9r\u00eats courus": {
+ "Int\u00e9r\u00eats courus sur emprunts obligataires convertibles": {
+ "account_number": "16881"
+ },
+ "Int\u00e9r\u00eats courus sur autres emprunts obligataires": {
+ "account_number": "16883"
+ },
+ "Int\u00e9r\u00eats courus sur emprunts aupr\u00e8s des \u00e9tablissements de cr\u00e9dit": {
+ "account_number": "16884"
+ },
+ "Int\u00e9r\u00eats courus sur d\u00e9p\u00f4ts et cautionnements re\u00e7us": {
+ "account_number": "16885"
+ },
+ "Int\u00e9r\u00eats courus sur participation des salari\u00e9s aux r\u00e9sultats": {
+ "account_number": "16886"
+ },
+ "Int\u00e9r\u00eats courus sur emprunts et dettes assortis de conditions particuli\u00e8res": {
+ "account_number": "16887"
+ },
+ "Int\u00e9r\u00eats courus sur autres emprunts et dettes assimil\u00e9es": {
+ "account_number": "16888"
+ },
+ "account_number": "1688"
+ },
+ "Primes de remboursement des obligations": {
+ "account_number": "169"
+ },
+ "account_number": "168"
+ },
+ "account_number": "16"
+ },
+ "Dettes Rattach\u00e9es \u00e0 des Participations": {
+ "Dettes rattach\u00e9es \u00e0 des participations (groupe)": {
+ "account_number": "171"
+ },
+ "Dettes rattach\u00e9es \u00e0 des participations (hors groupe)": {
+ "account_number": "174"
+ },
+ "Dettes rattach\u00e9es \u00e0 des soci\u00e9t\u00e9s en participation": {
+ "Principal": {
+ "account_number": "1781"
+ },
+ "Int\u00e9r\u00eats courus": {
+ "account_number": "1788"
+ },
+ "account_number": "178"
+ },
+ "account_number": "17"
+ },
+ "Comptes de liaison des \u00e9tablisssements et soci\u00e9t\u00e9s en participation": {
+ "Comptes de liaison des \u00e9tablissements": {
+ "account_number": "181"
+ },
+ "Biens et prestations de services \u00e9chang\u00e9s entre \u00e9tablissements (charges)": {
+ "account_number": "186"
+ },
+ "Biens et prestations de services \u00e9chang\u00e9s entre \u00e9tablissements (produits)": {
+ "account_number": "187"
+ },
+ "Comptes de liaison des soci\u00e9t\u00e9s en participation": {
+ "account_number": "188"
+ },
+ "account_number": "18"
+ },
+ "account_number": "1"
+ },
+ "Comptes d'Immobilisations": {
+ "root_type": "Asset",
+ "Immobilisations incorporelles": {
+ "Frais \u00e9tablissement": {
+ "Frais de constitution": {
+ "account_number": "2011"
+ },
+ "Frais de premier \u00e9tablissement": {
+ "Frais de prospection": {
+ "account_number": "20121"
+ },
+ "Frais de publicit\u00e9": {
+ "account_number": "20122"
+ },
+ "account_number": "2012"
+ },
+ "Frais d'augmentation de capital et d'op\u00e9rations diverses (fusions, scissions, transformations)": {
+ "account_number": "2013"
+ },
+ "account_number": "201"
+ },
+ "Frais de recherche et de d\u00e9veloppement": {
+ "account_number": "203"
+ },
+ "Concessions et droits similaires, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels, droits et valeurs similaires": {
+ "account_number": "205"
+ },
+ "Droit au bail": {
+ "account_number": "206"
+ },
+ "Fonds commercial": {
+ "account_number": "207"
+ },
+ "Autres immobilisations incorporelles": {
+ "Mali de fusion sur actifs incorporels": {
+ "account_number": "2081"
+ },
+ "account_number": "208"
+ },
+ "account_number": "20"
+ },
+ "Immobilisations corporelles": {
+ "account_type": "Fixed Asset",
+ "Terrains": {
+ "account_type": "Fixed Asset",
+ "Terrains nus": {
+ "account_type": "Fixed Asset",
+ "account_number": "2111"
+ },
+ "Terrains am\u00e9nag\u00e9s": {
+ "account_type": "Fixed Asset",
+ "account_number": "2112"
+ },
+ "Sous-sols et sur-sols": {
+ "account_type": "Fixed Asset",
+ "account_number": "2113"
+ },
+ "Terrains de carri\u00e8res (tr\u00e9fonds)": {
+ "account_type": "Fixed Asset",
+ "account_number": "2114"
+ },
+ "Terrains b\u00e2tis": {
+ "account_type": "Fixed Asset",
+ "Ensembles immobiliers industriels (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "21151"
+ },
+ "Ensembles immobiliers administratifs et commerciaux (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "21155"
+ },
+ "Autres ensembles immobiliers": {
+ "account_type": "Fixed Asset",
+ "Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations professionnelles (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "211581"
+ },
+ "Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations non professionnelles (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "211588"
+ },
+ "account_number": "21158"
+ },
+ "account_number": "2115"
+ },
+ "account_number": "211"
+ },
+ "Agencements et am\u00e9nagements de terrains (m\u00eame ventilation que celle du compte 211)": {
+ "account_type": "Fixed Asset",
+ "account_number": "212"
+ },
+ "Constructions": {
+ "account_type": "Fixed Asset",
+ "B\u00e2timents": {
+ "account_type": "Fixed Asset",
+ "Ensembles immobiliers industriels (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "21311"
+ },
+ "Ensembles immobiliers administratifs et commerciaux (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "21315"
+ },
+ "Autres ensembles immobiliers": {
+ "account_type": "Fixed Asset",
+ "Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations professionnelles (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "213181"
+ },
+ "Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations non professionnelles (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "213188"
+ },
+ "account_number": "21318"
+ },
+ "account_number": "2131"
+ },
+ "Installations g\u00e9n\u00e9rales, agencements, am\u00e9nagements des constructions": {
+ "account_type": "Fixed Asset",
+ "Ensembles immobiliers industriels (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "21351"
+ },
+ "Ensembles immobiliers administratifs et commerciaux (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "21355"
+ },
+ "Autres ensembles immobiliers": {
+ "account_type": "Fixed Asset",
+ "Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations professionnelles (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "213581"
+ },
+ "Autres ensembles immobiliers affect\u00e9s aux op\u00e9rations non professionnelles (A, B)": {
+ "account_type": "Fixed Asset",
+ "account_number": "213588"
+ },
+ "account_number": "21358"
+ },
+ "account_number": "2135"
+ },
+ "Ouvrages d'infrastructure": {
+ "account_type": "Fixed Asset",
+ "Voies de terre": {
+ "account_type": "Fixed Asset",
+ "account_number": "21381"
+ },
+ "Voies de fer": {
+ "account_type": "Fixed Asset",
+ "account_number": "21382"
+ },
+ "Voies d'eau": {
+ "account_type": "Fixed Asset",
+ "account_number": "21383"
+ },
+ "Barrages": {
+ "account_type": "Fixed Asset",
+ "account_number": "21384"
+ },
+ "Pistes d'a\u00e9rodromes": {
+ "account_type": "Fixed Asset",
+ "account_number": "21385"
+ },
+ "account_number": "2138"
+ },
+ "account_number": "213"
+ },
+ "Constructions sur sol d'autrui (m\u00eame ventilation que celle du compte 213)": {
+ "account_type": "Fixed Asset",
+ "account_number": "214"
+ },
+ "Installations techniques, mat\u00e9riel et outillage industriels": {
+ "account_type": "Fixed Asset",
+ "Installations complexes sp\u00e9cialis\u00e9es": {
+ "account_type": "Fixed Asset",
+ "Installations complexes sp\u00e9cialis\u00e9es - sur sol propre": {
+ "account_type": "Fixed Asset",
+ "account_number": "21511"
+ },
+ "Installations complexes sp\u00e9cialis\u00e9es - sur sol d'autrui": {
+ "account_type": "Fixed Asset",
+ "account_number": "21514"
+ },
+ "account_number": "2151"
+ },
+ "Installations \u00e0 caract\u00e8re sp\u00e9cifique": {
+ "account_type": "Fixed Asset",
+ "Installations \u00e0 caract\u00e8re sp\u00e9cifique - sur sol propre": {
+ "account_type": "Fixed Asset",
+ "account_number": "21531"
+ },
+ "Installations \u00e0 caract\u00e8re sp\u00e9cifique - sur sol d'autrui": {
+ "account_type": "Fixed Asset",
+ "account_number": "21534"
+ },
+ "account_number": "2153"
+ },
+ "Mat\u00e9riel industriel": {
+ "account_type": "Fixed Asset",
+ "account_number": "2154"
+ },
+ "Outillage industriel": {
+ "account_type": "Fixed Asset",
+ "account_number": "2155"
+ },
+ "Agencements et am\u00e9nagements du mat\u00e9riel et outillage industriel": {
+ "account_type": "Fixed Asset",
+ "account_number": "2157"
+ },
+ "account_number": "215"
+ },
+ "Autres immobilisations corporelles": {
+ "account_type": "Fixed Asset",
+ "Installations g\u00e9n\u00e9rales, agencements, am\u00e9nagements divers": {
+ "account_type": "Fixed Asset",
+ "account_number": "2181"
+ },
+ "Mat\u00e9riel de transport": {
+ "account_type": "Fixed Asset",
+ "account_number": "2182"
+ },
+ "Mat\u00e9riel de bureau et mat\u00e9riel informatique": {
+ "account_type": "Fixed Asset",
+ "account_number": "2183"
+ },
+ "Mobilier": {
+ "account_type": "Fixed Asset",
+ "account_number": "2184"
+ },
+ "Cheptel": {
+ "account_type": "Fixed Asset",
+ "account_number": "2185"
+ },
+ "Emballages r\u00e9cup\u00e9rables": {
+ "account_type": "Fixed Asset",
+ "account_number": "2186"
+ },
+ "Mali de fusion sur actifs corporels": {
+ "account_number": "2187"
+ },
+ "account_number": "218"
+ },
+ "account_number": "21"
+ },
+ "Immobilisations mises en concession": {
+ "account_number": "22"
+ },
+ "Immobilisations en cours": {
+ "Immobilisations corporelles en cours": {
+ "Terrains": {
+ "account_number": "2312"
+ },
+ "Constructions": {
+ "account_number": "2313"
+ },
+ "Installations techniques, mat\u00e9riel et outillage industriels": {
+ "account_number": "2315"
+ },
+ "Autres immobilisations corporelles": {
+ "account_number": "2318"
+ },
+ "account_number": "231"
+ },
+ "Immobilisations incorporelles en cours": {
+ "account_number": "232"
+ },
+ "Avances et acomptes vers\u00e9s sur commandes d'immobilisations incorporelles": {
+ "account_number": "237"
+ },
+ "Avances et acomptes vers\u00e9s sur commandes d'immobilisations corporelles": {
+ "Terrains": {
+ "account_number": "2382"
+ },
+ "Constructions": {
+ "account_number": "2383"
+ },
+ "Installations techniques, mat\u00e9riel et outillage industriels": {
+ "account_number": "2385"
+ },
+ "Autres immobilisations corporelles": {
+ "account_number": "2388"
+ },
+ "account_number": "238"
+ },
+ "account_number": "23"
+ },
+ "Parts dans des entreprises li\u00e9es et cr\u00e9ances sur des entreprises li\u00e9es": {
+ "is_group": 1,
+ "account_number": "25"
+ },
+ "Participations et cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
+ "Titres de participation": {
+ "Actions": {
+ "account_number": "2611"
+ },
+ "Autres titres": {
+ "account_number": "2618"
+ },
+ "account_number": "261"
+ },
+ "Autres formes de participation": {
+ "Droit repr\u00e9sentatifs d'actifs nets remis en fiducie": {
+ "account_number": "2661"
+ },
+ "account_number": "266"
+ },
+ "Cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
+ "Cr\u00e9ances rattach\u00e9es \u00e0 des participations (groupe)": {
+ "account_number": "2671"
+ },
+ "Cr\u00e9ances rattach\u00e9es \u00e0 des participations (hors groupe)": {
+ "account_number": "2674"
+ },
+ "Versements repr\u00e9sentatifs d'apports non capitalis\u00e9s (appel de fonds)": {
+ "account_number": "2675"
+ },
+ "Avances consolidables": {
+ "account_number": "2676"
+ },
+ "Autres cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
+ "account_number": "2677"
+ },
+ "Int\u00e9r\u00eats courus": {
+ "account_number": "2678"
+ },
+ "account_number": "267"
+ },
+ "Cr\u00e9ances rattach\u00e9es \u00e0 des soci\u00e9t\u00e9s en participation": {
+ "Principal": {
+ "account_number": "2681"
+ },
+ "Int\u00e9r\u00eats courus": {
+ "account_number": "2688"
+ },
+ "account_number": "268"
+ },
+ "Versements restant \u00e0 effectuer sur titres de participation non lib\u00e9r\u00e9s": {
+ "account_number": "269"
+ },
+ "account_number": "26"
+ },
+ "Autres immobilisations financi\u00e8res": {
+ "Titres immobilis\u00e9s autres que les titres immobilis\u00e9s de l'activit\u00e9 de portefeuille (droit de propri\u00e9t\u00e9)": {
+ "Actions": {
+ "account_number": "2711"
+ },
+ "Autres titres": {
+ "account_number": "2718"
+ },
+ "account_number": "271"
+ },
+ "Titres immobilis\u00e9s (droit de cr\u00e9ance)": {
+ "Obligations": {
+ "account_number": "2721"
+ },
+ "Bons": {
+ "account_number": "2722"
+ },
+ "account_number": "272"
+ },
+ "Titres immobilis\u00e9s de l'activit\u00e9 de portefeuille": {
+ "account_number": "273"
+ },
+ "Pr\u00eats": {
+ "Pr\u00eats participatifs": {
+ "account_number": "2741"
+ },
+ "Pr\u00eats aux associ\u00e9s": {
+ "account_number": "2742"
+ },
+ "Pr\u00eats au personnel": {
+ "account_number": "2743"
+ },
+ "Autres pr\u00eats": {
+ "account_number": "2748"
+ },
+ "account_number": "274"
+ },
+ "D\u00e9p\u00f4ts et cautionnements vers\u00e9s": {
+ "D\u00e9p\u00f4ts": {
+ "account_number": "2751"
+ },
+ "Cautionnements": {
+ "account_number": "2755"
+ },
+ "account_number": "275"
+ },
+ "Autres cr\u00e9ances immobilis\u00e9es": {
+ "Cr\u00e9ances diverses": {
+ "account_number": "2761"
+ },
+ "Int\u00e9r\u00eats courus": {
+ "Int\u00e9r\u00eats courus sur titres immobilis\u00e9s (droit de cr\u00e9ance)": {
+ "account_number": "27682"
+ },
+ "Int\u00e9r\u00eats courus sur pr\u00eats": {
+ "account_number": "27684"
+ },
+ "Int\u00e9r\u00eats courus sur d\u00e9p\u00f4ts et cautionnements": {
+ "account_number": "27685"
+ },
+ "Int\u00e9r\u00eats courus sur cr\u00e9ances diverses": {
+ "account_number": "27688"
+ },
+ "account_number": "2768"
+ },
+ "account_number": "276"
+ },
+ "(Actions propres ou parts propres)": {
+ "Actions propres ou parts propres": {
+ "account_number": "2771"
+ },
+ "Actions propres ou parts propres en voie d'annulation": {
+ "account_number": "2772"
+ },
+ "account_number": "277"
+ },
+ "Mali de fusion sur actifs financiers": {
+ "account_number": "278"
+ },
+ "Versements restant \u00e0 effectuer sur titres immobilis\u00e9s non lib\u00e9r\u00e9s": {
+ "account_number": "279"
+ },
+ "account_number": "27"
+ },
+ "Amortissements des immobilisations": {
+ "account_type": "Accumulated Depreciation",
+ "Amortissements des immobilisations incorporelles": {
+ "account_type": "Accumulated Depreciation",
+ "Frais d'\u00e9tablissement (m\u00eame ventilation que celle du compte 212)": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2801"
+ },
+ "Frais de recherche et de d\u00e9veloppement": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2803"
+ },
+ "Concessions et droits similaires, brevets, licences, logiciels, droits et valeurs similaires": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2805"
+ },
+ "Fonds commercial": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2807"
+ },
+ "Autres immobilisations incorporelles": {
+ "account_type": "Accumulated Depreciation",
+ "Mali de fusion sur actifs incorporels": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "28081"
+ },
+ "account_number": "2808"
+ },
+ "account_number": "280"
+ },
+ "Amortissements des immobilisations corporelles": {
+ "account_type": "Accumulated Depreciation",
+ "Terrains de gisement": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2811"
+ },
+ "Agencements, am\u00e9nagements de terrains (m\u00eame ventilation que celle du compte 212)": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2812"
+ },
+ "Constructions (m\u00eame ventilation que celle du compte 213)": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2813"
+ },
+ "Constructions sur sol d'autrui (m\u00eame ventilation que celle du compte du 214)": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2814"
+ },
+ "Installations techniques, mat\u00e9riel et outillage industriels (m\u00eame ventilation que celle du compte 218)": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "2815"
+ },
+ "Autres immobilisations corporelles (m\u00eame ventilation que celle du compte 218)": {
+ "account_type": "Accumulated Depreciation",
+ "Mali de fusion sur actifs corporels": {
+ "account_type": "Accumulated Depreciation",
+ "account_number": "28187"
+ },
+ "account_number": "2818"
+ },
+ "account_number": "281"
+ },
+ "Amortissements des immobilisations mises en concession": {
+ "account_number": "282"
+ },
+ "account_number": "28"
+ },
+ "D\u00e9pr\u00e9ciations des immobilisations": {
+ "D\u00e9pr\u00e9ciations des immobilisations incorporelles": {
+ "Marques, proc\u00e9d\u00e9s, droits et valeurs similaires": {
+ "account_number": "2905"
+ },
+ "Droit au bail": {
+ "account_number": "2906"
+ },
+ "Fonds commercial": {
+ "account_number": "2907"
+ },
+ "Autres immobilisations incorporelles": {
+ "Mali de fusion sur actifs incorporels": {
+ "account_number": "29081"
+ },
+ "account_number": "2908"
+ },
+ "account_number": "290"
+ },
+ "D\u00e9pr\u00e9ciations des immobilisations corporelles (m\u00eame ventilation que celle du compte 21)": {
+ "Terrains (autres que terrains de gisement)": {
+ "Mali de fusion sur actifs corporels": {
+ "account_number": "29187"
+ },
+ "account_number": "2911"
+ },
+ "account_number": "291"
+ },
+ "D\u00e9pr\u00e9ciations des immobilisations mises en concession": {
+ "account_number": "292"
+ },
+ "D\u00e9pr\u00e9ciations des immobilisations en cours": {
+ "Immobilisations corporelles en cours": {
+ "account_number": "2931"
+ },
+ "Immobilisations incorporelles en cours": {
+ "account_number": "2932"
+ },
+ "account_number": "293"
+ },
+ "D\u00e9pr\u00e9ciations des participations et cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
+ "Titres de participation": {
+ "account_number": "2961"
+ },
+ "Autres formes de participation": {
+ "account_number": "2966"
+ },
+ "Cr\u00e9ances rattach\u00e9es \u00e0 des participations (m\u00eame ventilation que celle du compte 267)": {
+ "account_number": "2967"
+ },
+ "Cr\u00e9ances rattach\u00e9es \u00e0 des soci\u00e9t\u00e9s en participation (m\u00eame ventilation que celle du compte 268)": {
+ "account_number": "2968"
+ },
+ "account_number": "296"
+ },
+ "D\u00e9pr\u00e9ciations des autres immobilisations financi\u00e8res": {
+ "Titres immobilis\u00e9s autres que les titres immobilis\u00e9s de l'activit\u00e9 de portefeuille - droit de propri\u00e9t\u00e9": {
+ "account_number": "2971"
+ },
+ "Titres immobilis\u00e9s - droit de cr\u00e9ance (m\u00eame ventilation que celle du compte 272)": {
+ "account_number": "2972"
+ },
+ " Titres immobilis\u00e9s de l'activit\u00e9 de portefuille": {
+ "account_number": "2973"
+ },
+ "Pr\u00eats (m\u00eame ventilation que celle du compte 274)": {
+ "account_number": "2974"
+ },
+ "D\u00e9p\u00f4ts et cautionnements vers\u00e9s (m\u00eame ventilation que celle du compte 275)": {
+ "account_number": "2975"
+ },
+ "Autres cr\u00e9ances immobilis\u00e9es (m\u00eame ventilation que celle du compte 276)": {
+ "Mali de fusion sur actifs financiers": {
+ "account_number": "29787"
+ },
+ "account_number": "2976"
+ },
+ "account_number": "297"
+ },
+ "account_number": "29"
+ },
+ "account_number": "2"
+ },
+ "Comptes de Stocks et En-Cours": {
+ "root_type": "Asset",
+ "Mati\u00e8res premi\u00e8res (et fournitures)": {
+ "Mati\u00e8res (ou groupe) A": {
+ "account_number": "311"
+ },
+ "Mati\u00e8res (ou groupe) B": {
+ "account_number": "312"
+ },
+ "Fournitures A, B, C, ...": {
+ "account_number": "317"
+ },
+ "account_number": "31"
+ },
+ "Autres approvisionnements": {
+ "Mat\u00e8res consommables": {
+ "Mati\u00e8res (ou groupe) C": {
+ "account_number": "3211"
+ },
+ "Mati\u00e8res (ou groupe) D": {
+ "account_number": "3212"
+ },
+ "account_number": "321"
+ },
+ "Fournitures consommables": {
+ "Combustibles": {
+ "account_number": "3221"
+ },
+ "Produits d'entretien": {
+ "account_number": "3222"
+ },
+ "Fournitures d'atelier et d'usine": {
+ "account_number": "3223"
+ },
+ "Fournitures de magasin": {
+ "account_number": "3224"
+ },
+ "Fournitures de bureau": {
+ "account_number": "3225"
+ },
+ "account_number": "322"
+ },
+ "Emballages": {
+ "Emballages perdus": {
+ "account_number": "3261"
+ },
+ "Emballages r\u00e9cup\u00e9rables non identifiables": {
+ "account_number": "3265"
+ },
+ "Emballages \u00e0 usage mixte": {
+ "account_number": "3267"
+ },
+ "account_number": "326"
+ },
+ "account_number": "32"
+ },
+ "En-cours de production de biens": {
+ "Produits en cours": {
+ "Produits en cours P1": {
+ "account_number": "3311"
+ },
+ "Produits en cours P2": {
+ "account_number": "3312"
+ },
+ "account_number": "331"
+ },
+ "Travaux en cours": {
+ "Travaux en cours T1": {
+ "account_number": "3351"
+ },
+ "Travaux en cours T2": {
+ "account_number": "3352"
+ },
+ "account_number": "335"
+ },
+ "account_number": "33"
+ },
+ "En-cours de production de services": {
+ "Etudes en cours": {
+ "Etudes en cours E1": {
+ "account_number": "3411"
+ },
+ "Etudes en cours E2": {
+ "account_number": "3412"
+ },
+ "account_number": "341"
+ },
+ "Prestations de services en cours": {
+ "Prestations de services S1": {
+ "account_number": "3451"
+ },
+ "Prestations de services S2": {
+ "account_number": "3452"
+ },
+ "account_number": "345"
+ },
+ "account_number": "34"
+ },
+ "Stocks de produits": {
+ "account_type": "Stock",
+ "Produits interm\u00e9diaires": {
+ "account_type": "Stock",
+ "Produits interm\u00e9diaires (ou groupe) A": {
+ "account_type": "Stock",
+ "is_group": 1,
+ "account_number": "3511"
+ },
+ "Produits interm\u00e9diaires (ou groupe) B": {
+ "account_type": "Stock",
+ "is_group": 1,
+ "account_number": "3512"
+ },
+ "account_number": "351"
+ },
+ "Produits finis": {
+ "account_type": "Stock",
+ "Produits finis (ou groupe) A": {
+ "account_type": "Stock",
+ "is_group": 1,
+ "account_number": "3551"
+ },
+ "Produits finis (ou groupe) B": {
+ "account_type": "Stock",
+ "is_group": 1,
+ "account_number": "3552"
+ },
+ "account_number": "355"
+ },
+ "Produits r\u00e9siduels (ou mati\u00e8res de r\u00e9cup\u00e9ration)": {
+ "account_type": "Stock",
+ "D\u00e9chets": {
+ "account_type": "Stock",
+ "is_group": 1,
+ "account_number": "3581"
+ },
+ "Rebuts": {
+ "account_type": "Stock",
+ "is_group": 1,
+ "account_number": "3585"
+ },
+ "Mati\u00e8res de r\u00e9cup\u00e9ration": {
+ "account_type": "Stock",
+ "is_group": 1,
+ "account_number": "3586"
+ },
+ "account_number": "358"
+ },
+ "account_number": "35"
+ },
+ "(Compte \u00e0 ouvrir, le cas \u00e9ch\u00e9ant, sous l'intitul\u00e9 \"stocks provenant d'immobilisations\")": {
+ "account_number": "36"
+ },
+ "Stocks de marchandises": {
+ "Marchandises (ou groupe) A": {
+ "account_number": "371"
+ },
+ "Marchandises (ou groupe) B": {
+ "account_number": "372"
+ },
+ "account_number": "37"
+ },
+ "Stocks en voie d'acheminement, mis en d\u00e9p\u00f4t ou donn\u00e9s en consignation (en cas d'inventaire permanent en comptabilit\u00e9 g\u00e9n\u00e9rale)": {
+ "account_type": "Stock",
+ "account_number": "38"
+ },
+ "D\u00e9pr\u00e9ciations des stocks et en-cours": {
+ "D\u00e9pr\u00e9ciations des mati\u00e8res premi\u00e8res (et fournitures)": {
+ "Mati\u00e8res (ou groupe) A": {
+ "account_number": "3911"
+ },
+ "Mati\u00e8res (ou groupe) B": {
+ "account_number": "3912"
+ },
+ "Fournitures A, B, C, ...": {
+ "account_number": "3917"
+ },
+ "account_number": "391"
+ },
+ "D\u00e9pr\u00e9ciations des autres approvisionnements": {
+ "Mati\u00e8res consommables (m\u00eame ventilation que celle du compte 321)": {
+ "account_number": "3921"
+ },
+ "Fournitures consommables (m\u00eame ventilation que celle du compte 322)": {
+ "account_number": "3922"
+ },
+ "Emballages (m\u00eame ventilation que celle du compte 326)": {
+ "account_number": "3926"
+ },
+ "account_number": "392"
+ },
+ "D\u00e9pr\u00e9ciations des en-cours de production de biens": {
+ "Etudes en cours (m\u00eame ventilation que celle du compte 341)": {
+ "account_number": "3931"
+ },
+ "Travaux en cours (m\u00eame ventilation que celle du compte 335)": {
+ "account_number": "3935"
+ },
+ "account_number": "393"
+ },
+ "D\u00e9pr\u00e9ciations des en-cours de production de services": {
+ "Etudes en cours (m\u00eame ventilation que celle du compte 341)": {
+ "account_number": "3941"
+ },
+ "Prestations de services en cours (m\u00eame ventilation que celle du compte 345)": {
+ "account_number": "3945"
+ },
+ "account_number": "394"
+ },
+ "D\u00e9pr\u00e9ciations des stocks de produits": {
+ "Produits interm\u00e9diaires (m\u00eame ventilation que celle du compte 351)": {
+ "account_number": "3951"
+ },
+ "Produits finis (m\u00eame ventilation que celle du compte 355)": {
+ "account_number": "3955"
+ },
+ "account_number": "395"
+ },
+ "D\u00e9pr\u00e9ciations des stocks de marchandises": {
+ "Marchandise (ou groupe) A": {
+ "account_number": "3971"
+ },
+ "Marchandise (ou groupe) B": {
+ "account_number": "3972"
+ },
+ "account_number": "397"
+ },
+ "account_number": "39"
+ },
+ "account_number": "3"
+ },
+ "4-Comptes de Tiers (ACTIF)": {
+ "root_type": "Asset",
+ "40-Fournisseurs et Comptes Rattach\u00e9s (ACTIF)": {
+ "Fournisseurs d\u00e9biteurs": {
+ "Fournisseurs - Avances et acomptes vers\u00e9s sur commandes": {
+ "account_number": "4091"
+ },
+ "Fournisseurs - Cr\u00e9ances pour emballages et mat\u00e9riel \u00e0 rendre": {
+ "account_number": "4096"
+ },
+ "Fournisseurs - Autres avoirs": {
+ "Fournisseurs d'exploitation": {
+ "account_number": "40971"
+ },
+ "Fournisseurs d'immobilisation": {
+ "account_number": "40974"
+ },
+ "account_number": "4097"
+ },
+ "Rabais, remises, ristournes \u00e0 obtenir et autres avoirs non encore re\u00e7us": {
+ "account_number": "4098"
+ },
+ "account_number": "409"
+ }
+ },
+ "41-Clients et comptes rattach\u00e9s (ACTIF)": {
+ "account_type": "Receivable",
+ "Clients et Comptes rattach\u00e9s": {
+ "account_type": "Receivable",
+ "account_number": "410"
+ },
+ "Clients": {
+ "account_type": "Receivable",
+ "Clients - Ventes de biens ou de prestations de services": {
+ "account_type": "Receivable",
+ "account_number": "4111"
+ },
+ "Clients - Retenues de garantie": {
+ "account_type": "Receivable",
+ "account_number": "4117"
+ },
+ "account_number": "411"
+ },
+ "Clients - Effets \u00e0 recevoir": {
+ "account_type": "Receivable",
+ "account_number": "413"
+ },
+ "Clients douteux ou litigieux": {
+ "account_type": "Receivable",
+ "account_number": "416"
+ },
+ "Clients - Produits non encore factur\u00e9s": {
+ "account_type": "Receivable",
+ "Clients - Factures \u00e0 \u00e9tablir": {
+ "account_type": "Receivable",
+ "account_number": "4181"
+ },
+ "Clients - Int\u00e9r\u00eats courus": {
+ "account_type": "Receivable",
+ "account_number": "4188"
+ },
+ "account_number": "418"
+ }
+ },
+ "42-Personnel et comptes rattach\u00e9s (ACTIF)": {
+ "Personnel - Avances et acomptes": {
+ "account_number": "425"
+ }
+ },
+ "43-S\u00e9curit\u00e9 sociale et autres organismes sociaux (ACTIF)": {
+ "S\u00e9curit\u00e9 sociale": {
+ "account_number": "431"
+ },
+ "Autres organismes sociaux": {
+ "account_number": "437"
+ },
+ "438-Organismes sociaux - Produits \u00e0 recevoir": {
+ "Produits \u00e0 recevoir": {
+ "account_number": "4387"
+ }
+ }
+ },
+ "44-Etat et autres collectivit\u00e9s publiques (ACTIF)": {
+ "Etat - Subventions \u00e0 recevoir": {
+ "Subventions d'investissement": {
+ "account_number": "4411"
+ },
+ "Subventions d'exploitation": {
+ "account_number": "4417"
+ },
+ "Subventions d'\u00e9quilibre": {
+ "account_number": "4418"
+ },
+ "Avances sur subventions": {
+ "account_number": "4419"
+ },
+ "account_number": "441"
+ },
+ "Op\u00e9rations particuli\u00e8res avec l'Etat, les collectivit\u00e9s publiques, les organismes internationaux": {
+ "Cr\u00e9ances sur l'Etat r\u00e9sultant de la suppression de la r\u00e8gle du d\u00e9calage d'un mois en mati\u00e8re de TVA": {
+ "account_number": "4431"
+ },
+ "Int\u00e9r\u00eats courus sur cr\u00e9ances figurant au compte 4431": {
+ "account_number": "4438"
+ },
+ "account_number": "443"
+ },
+ "Etat - Taxes sur le chiffre d'affaires (ACTIF)": {
+ "TVA due intracommunautaire": {
+ "account_number": "4452"
+ },
+ "Taxes sur le chiffre d'affaires d\u00e9ductibles": {
+ "TVA sur immobilisations": {
+ "account_number": "44562"
+ },
+ "TVA transf\u00e9r\u00e9e par d'autres entreprises": {
+ "account_number": "44563"
+ },
+ "TVA sur autres biens et services": {
+ "tax_rate": 20,
+ "account_number": "44566"
+ },
+ "Cr\u00e9dit de TVA \u00e0 reporter": {
+ "account_number": "44567"
+ },
+ "Taxes assimil\u00e9es \u00e0 la TVA": {
+ "account_number": "44568"
+ },
+ "account_number": "4456"
+ },
+ "4458-Taxes sur le chiffre d'affaires \u00e0 r\u00e9gulariser ou en attente (ACTIF)": {
+ "Acomptes - R\u00e9gime simplifi\u00e9 d'imposition": {
+ "account_number": "44581"
+ },
+ "Acomptes - R\u00e9gime du forfait": {
+ "account_number": "44582"
+ },
+ "Remboursement de taxes sur le chiffre d'affaires demand\u00e9": {
+ "account_number": "44583"
+ },
+ "Taxes sur le chiffre d'affaires sur factures non parvenues": {
+ "account_number": "44586"
+ }
+ }
+ },
+ "Etat - Charges \u00e0 payer et produits \u00e0 recevoir": {
+ "Charges fiscales sur cong\u00e9s \u00e0 payer": {
+ "account_number": "4482"
+ },
+ "Charges \u00e0 payer": {
+ "account_number": "4486"
+ },
+ "Produits \u00e0 recevoir": {
+ "account_number": "4487"
+ },
+ "account_number": "448"
+ }
+ },
+ "45-Groupe et associ\u00e9s (ACTIF)": {
+ "Associ\u00e9s - Op\u00e9rations sur le capital (ACTIF)": {
+ "456-Apporteurs - Capital appel\u00e9, non vers\u00e9": {
+ "Actionnaires - Capital souscrit et appel\u00e9, non vers\u00e9": {
+ "account_number": "45621"
+ },
+ "Associ\u00e9s - Capital appel\u00e9, non vers\u00e9": {
+ "account_number": "45625"
+ },
+ "account_number": "4562"
+ }
+ }
+ },
+ "46-D\u00e9biteurs divers et cr\u00e9diteurs divers (ACTIF)": {
+ "Cr\u00e9ances sur cessions d'immobilisations": {
+ "account_number": "462"
+ },
+ "Cr\u00e9ances sur cessions de valeurs mobili\u00e8res de placement": {
+ "account_number": "465"
+ },
+ "467-Autres comptes d\u00e9biteurs ou cr\u00e9diteurs (ACTIF)": {},
+ "468-Divers - Charges \u00e0 payer et produits \u00e0 recevoir (ACTIF)": {
+ "Produits \u00e0 recevoir": {
+ "account_number": "4687"
+ }
+ }
+ },
+ "47-Comptes transitoires ou d'attente (ACTIF)": {
+ "471-Comptes d'attente (ACTIF)": {
+ "account_type": "Temporary"
+ },
+ "Diff\u00e9rences de conversion (ACTIF)": {
+ "Diminution des cr\u00e9ances": {
+ "account_number": "4761"
+ },
+ "Augmentation des dettes": {
+ "account_number": "4762"
+ },
+ "Diff\u00e9rences compens\u00e9es par couverture de change": {
+ "account_number": "4768"
+ },
+ "account_number": "476"
+ },
+ "Autres comptes transitoires (ACTIF)": {
+ "Mali de fusion sur actif circulant": {
+ "account_number": "4781"
+ },
+ "478-Diff\u00e9rences d'\u00e9valuation sur instruments de tr\u00e9sorerie (ACTIF)": {
+ "account_number": "4786"
+ }
+ }
+ },
+ "48-Comptes de r\u00e9gularisation (ACTIF)": {
+ "Charges \u00e0 r\u00e9partir sur plusieurs exercices": {
+ "Frais d'\u00e9mission des emprunts": {
+ "account_number": "4816"
+ },
+ "account_number": "481"
+ },
+ "Charges constat\u00e9es d'avance": {
+ "account_number": "486"
+ },
+ "488-Comptes de r\u00e9partition p\u00e9riodique des charges et des produits (ACTIF)": {
+ "Charges": {
+ "account_number": "4886"
+ }
+ }
+ },
+ "49-D\u00e9pr\u00e9ciation des comptes de tiers (ACTIF)": {
+ "D\u00e9pr\u00e9ciations des comptes clients": {
+ "account_number": "491"
+ },
+ "D\u00e9pr\u00e9ciations des comptes du groupe et des associ\u00e9s": {
+ "Comptes du groupe": {
+ "account_number": "4951"
+ },
+ "Comptes courants des associ\u00e9s": {
+ "account_number": "4955"
+ },
+ "Op\u00e9rations faites en commun et en GIE": {
+ "account_number": "4958"
+ },
+ "account_number": "495"
+ },
+ "D\u00e9pr\u00e9ciations des comptes de d\u00e9biteurs divers": {
+ "Cr\u00e9ances sur cessions d'immobilisations": {
+ "account_number": "4962"
+ },
+ "Cr\u00e9ances sur cessions de valeurs mobili\u00e8res de placement": {
+ "account_number": "4965"
+ },
+ "Autres comptes d\u00e9biteurs": {
+ "account_number": "4967"
+ },
+ "account_number": "496"
+ }
+ }
+ },
+ "4-Comptes de Tiers (PASSIF)": {
+ "root_type": "Liability",
+ "40-Fournisseurs et Comptes Rattach\u00e9s (PASSIF)": {
+ "account_type": "Payable",
+ "Fournisseurs": {
+ "account_type": "Payable",
+ "Fournisseurs - Achats de biens ou de prestations de services": {
+ "account_type": "Payable",
+ "account_number": "4011"
+ },
+ "Fournisseurs - Retenues de garantie": {
+ "account_type": "Payable",
+ "account_number": "4017"
+ },
+ "account_number": "401"
+ },
+ "Fournisseurs - Effets \u00e0 payer": {
+ "account_type": "Payable",
+ "account_number": "403"
+ },
+ "Fournisseurs d'immobilisations": {
+ "account_type": "Payable",
+ "Fournisseurs - Achats d'immobilisations": {
+ "account_type": "Payable",
+ "account_number": "4041"
+ },
+ "Fournisseurs d'immobilisations - Retenues de garantie": {
+ "account_type": "Payable",
+ "account_number": "4047"
+ },
+ "account_number": "404"
+ },
+ "Fournisseurs d'immobilisations - Effets \u00e0 payer": {
+ "account_type": "Payable",
+ "account_number": "405"
+ },
+ "Fournisseurs - Factures non parvenues": {
+ "account_type": "Stock Received But Not Billed",
+ "Fournisseurs": {
+ "account_type": "Stock Received But Not Billed",
+ "account_number": "4081"
+ },
+ "Fournisseurs d'immobilisations": {
+ "account_type": "Stock Received But Not Billed",
+ "account_number": "4084"
+ },
+ "Fournisseurs - Int\u00e9r\u00eats courus": {
+ "account_type": "Stock Received But Not Billed",
+ "account_number": "4088"
+ },
+ "account_number": "408"
+ }
+ },
+ "41-Clients et comptes rattach\u00e9s (PASSIF)": {
+ "Clients cr\u00e9diteurs": {
+ "Clients - Avances et acomptes re\u00e7us sur commandes": {
+ "account_number": "4191"
+ },
+ "Clients - Dettes pour emballages et mat\u00e9riels consign\u00e9s": {
+ "account_number": "4196"
+ },
+ "Clients - Autres avoirs": {
+ "account_number": "4197"
+ },
+ "Rabais, remises, ristournes \u00e0 accorder et autres avoirs \u00e0 \u00e9tablir": {
+ "account_number": "4198"
+ },
+ "account_number": "419"
+ }
+ },
+ "42-Personnel et comptes rattach\u00e9s (PASSIF)": {
+ "Personnel - R\u00e9mun\u00e9rations dues": {
+ "account_number": "421"
+ },
+ "Comit\u00e9s d'entreprises, d'\u00e9tablissement...": {
+ "account_number": "422"
+ },
+ "Participation des salari\u00e9s aux r\u00e9sultats": {
+ "R\u00e9serve sp\u00e9ciale": {
+ "account_number": "4246"
+ },
+ "Comptes courants": {
+ "account_number": "4248"
+ },
+ "account_number": "424"
+ },
+ "Personnel - D\u00e9p\u00f4ts": {
+ "account_number": "426"
+ },
+ "Personnel - Oppositions": {
+ "account_number": "427"
+ },
+ "Personnel - Charges \u00e0 payer et produits \u00e0 recevoir": {
+ "Dettes provisionn\u00e9es pour cong\u00e9s \u00e0 payer": {
+ "account_number": "4282"
+ },
+ "Dettes provisionn\u00e9es pour participation des salari\u00e9s aux r\u00e9sultats": {
+ "account_number": "4284"
+ },
+ "Autres charges \u00e0 payer": {
+ "account_number": "4286"
+ },
+ "Produits \u00e0 recevoir": {
+ "account_number": "4287"
+ },
+ "account_number": "428"
+ }
+ },
+ "43-S\u00e9curit\u00e9 sociale et autres organismes sociaux (PASSIF)": {
+ "438-Organismes sociaux - Charges \u00e0 payer": {
+ "Charges sociales sur cong\u00e9s \u00e0 payer": {
+ "account_number": "4382"
+ },
+ "Autres charges \u00e0 payer": {
+ "account_number": "4386"
+ }
+ }
+ },
+ "44-Etat et autres collectivit\u00e9s publiques (PASSIF)": {
+ "Etat - Imp\u00f4ts et taxes recouvrables sur des tiers": {
+ "Obligataires": {
+ "account_number": "4424"
+ },
+ "Associ\u00e9s": {
+ "account_number": "4425"
+ },
+ "account_number": "442"
+ },
+ "Etat - Imp\u00f4ts sur les b\u00e9n\u00e9fices": {
+ "account_number": "444"
+ },
+ "Etat - Taxes sur le chiffre d'affaires (PASSIF)": {
+ "Taxes sur le chiffre d'affaires \u00e0 d\u00e9caisser": {
+ "TVA \u00e0 d\u00e9caisser": {
+ "account_number": "44551"
+ },
+ "Taxes assimil\u00e9es \u00e0 la TVA": {
+ "account_number": "44558"
+ },
+ "account_number": "4455"
+ },
+ "Taxes sur le chiffre d'affaires collect\u00e9es par l'entreprise": {
+ "TVA collect\u00e9e": {
+ "account_type": "Tax",
+ "is_group": 1,
+ "account_number": "44571"
+ },
+ "Taxes assimil\u00e9es \u00e0 la TVA": {
+ "account_number": "44578"
+ },
+ "account_number": "4457"
+ },
+ "4458-Taxes sur le chiffre d'affaires \u00e0 r\u00e9gulariser ou en attente (PASSIF)": {
+ "TVA r\u00e9cup\u00e9r\u00e9e d'avance": {
+ "account_number": "44584"
+ },
+ "Taxes sur le chiffre d'affaires sur factures \u00e0 \u00e9tablir": {
+ "account_number": "44587"
+ }
+ }
+ },
+ "Obligations cautionn\u00e9es": {
+ "account_number": "446"
+ },
+ "Autres imp\u00f4ts, taxes et versements assimil\u00e9s": {
+ "account_number": "447"
+ },
+ "Quotas d'\u00e9mission \u00e0 acqu\u00e9rir": {
+ "account_number": "449"
+ }
+ },
+ "45-Groupe et associ\u00e9s (PASSIF)": {
+ "Groupe (PASSIF)": {
+ "account_number": "451"
+ },
+ "Associ\u00e9s - Comptes courants (PASSIF)": {
+ "Principal (PASSIF)": {
+ "account_number": "4551"
+ },
+ "Int\u00e9r\u00eats courus (PASSIF)": {
+ "account_number": "4558"
+ },
+ "account_number": "455"
+ },
+ "Associ\u00e9s - Op\u00e9rations sur le capital (PASSIF)": {
+ "456-Associ\u00e9s - Comptes d'apport en soci\u00e9t\u00e9": {
+ "Apports en nature": {
+ "account_number": "45611"
+ },
+ "Apports en num\u00e9raire": {
+ "account_number": "45615"
+ },
+ "account_number": "4561"
+ },
+ "Associ\u00e9s - Versements re\u00e7us sur augmentation de capital": {
+ "account_number": "4563"
+ },
+ "Associ\u00e9s - Versements anticip\u00e9s": {
+ "account_number": "4564"
+ },
+ "Actionnaires d\u00e9faillants": {
+ "account_number": "4566"
+ },
+ "Associ\u00e9s - Capital \u00e0 rembourser": {
+ "account_number": "4567"
+ }
+ },
+ "Associ\u00e9s - Dividendes \u00e0 payer": {
+ "account_number": "457"
+ },
+ "Associ\u00e9s - Op\u00e9rations faites en commun et en GIE": {
+ "Op\u00e9rations courantes": {
+ "account_number": "4581"
+ },
+ "Int\u00e9r\u00eats courus": {
+ "account_number": "4588"
+ },
+ "account_number": "458"
+ }
+ },
+ "46-D\u00e9biteurs divers et cr\u00e9diteurs divers (PASSIF)": {
+ "Dettes sur acquisitions de valeurs mobili\u00e8res de placement": {
+ "account_number": "464"
+ },
+ "467-Autres comptes d\u00e9biteurs ou cr\u00e9diteurs (PASSIF)": {},
+ "468-Divers - Charges \u00e0 payer et produits \u00e0 recevoir (PASSIF)": {
+ "Charges \u00e0 payer": {
+ "account_number": "4686"
+ }
+ }
+ },
+ "47-Comptes transitoires ou d'attente (PASSIF)": {
+ "471-Comptes d'attente (PASSIF)": {
+ "account_type": "Temporary"
+ },
+ "Diff\u00e9rences de conversion (PASSIF)": {
+ "Augmentation des cr\u00e9ances": {
+ "account_number": "4771"
+ },
+ "Diminution des dettes": {
+ "account_number": "4772"
+ },
+ "Diff\u00e9rences compens\u00e9es par couverture de change": {
+ "account_number": "4778"
+ },
+ "account_number": "477"
+ },
+ "478-Autres comptes transitoires (PASSIF)": {
+ "Diff\u00e9rences d'\u00e9valuation sur instruments de tr\u00e9sorerie (PASSIF)": {
+ "account_number": "4787"
+ }
+ }
+ },
+ "48-Comptes de r\u00e9gularisation (PASSIF)": {
+ "Produits constat\u00e9s d'avance": {
+ "account_number": "487"
+ },
+ "448-Comptes de r\u00e9partition p\u00e9riodique des charges et des produits (PASSIF)": {
+ "Produits": {
+ "account_number": "4887"
+ }
+ }
+ }
+ },
+ "Comptes Financiers": {
+ "root_type": "Asset",
+ "Valeurs mobili\u00e8res de placement": {
+ "Parts dans des entreprises li\u00e9es": {
+ "account_number": "501"
+ },
+ "Actions propres": {
+ "Actions destin\u00e9es \u00e0 \u00eatre attribu\u00e9es aux employ\u00e9s et affect\u00e9es \u00e0 des plans d\u00e9termin\u00e9s": {
+ "account_number": "5021"
+ },
+ "Actions disponibles pour \u00eatre attribu\u00e9es aux employ\u00e9s ou pour la r\u00e9gularisation des cours de bourse": {
+ "account_number": "5022"
+ },
+ "account_number": "502"
+ },
+ "Actions": {
+ "Titres cot\u00e9s": {
+ "account_number": "5031"
+ },
+ "Titres non cot\u00e9s": {
+ "account_number": "5035"
+ },
+ "account_number": "503"
+ },
+ "Autres titres conf\u00e9rant un droit de propri\u00e9t\u00e9": {
+ "account_number": "504"
+ },
+ "Obligations et bons \u00e9mis par la soci\u00e9t\u00e9 et rachet\u00e9s par elle": {
+ "account_number": "505"
+ },
+ "Obligations": {
+ "Titres cot\u00e9s": {
+ "account_number": "5061"
+ },
+ "Titres non cot\u00e9s": {
+ "account_number": "5065"
+ },
+ "account_number": "506"
+ },
+ "Bons du Tr\u00e9sor et bons de caisse \u00e0 court terme": {
+ "account_number": "507"
+ },
+ "Autres valeurs mobili\u00e8res de placement et autres cr\u00e9ances assimil\u00e9es": {
+ "Autres valeurs mobili\u00e8res": {
+ "account_number": "5081"
+ },
+ "Bons de souscription": {
+ "account_number": "5082"
+ },
+ "Int\u00e9r\u00eats courus sur obligations, bons et valeurs assimil\u00e9es": {
+ "account_number": "5088"
+ },
+ "account_number": "508"
+ },
+ "Versements restant \u00e0 effectuer sur valeurs mobili\u00e8res de placement non lib\u00e9r\u00e9es": {
+ "account_number": "509"
+ },
+ "account_number": "50"
+ },
+ "Banques, \u00e9tablissements financiers et assimil\u00e9s": {
+ "Valeurs \u00e0 l'encaissement": {
+ "Coupons \u00e9chus \u00e0 l'encaissement": {
+ "account_number": "5111"
+ },
+ "Ch\u00e8ques \u00e0 encaisser": {
+ "account_number": "5112"
+ },
+ "Effets \u00e0 l'encaissement": {
+ "account_number": "5113"
+ },
+ "Effets \u00e0 l'escompte": {
+ "account_number": "5114"
+ },
+ "account_number": "511"
+ },
+ "Banques": {
+ "account_type": "Bank",
+ "Comptes en monnaie nationale": {
+ "account_type": "Bank",
+ "account_number": "5121"
+ },
+ "Comptes en devises": {
+ "account_type": "Bank",
+ "account_number": "5124"
+ },
+ "account_number": "512"
+ },
+ "Ch\u00e8ques postaux": {
+ "account_number": "514"
+ },
+ "\"Caisses\" du Tr\u00e9sor et des \u00e9tablissements publics": {
+ "account_number": "515"
+ },
+ "Soci\u00e9t\u00e9s de bourse": {
+ "account_number": "516"
+ },
+ "Autres organismes financiers": {
+ "account_number": "517"
+ },
+ "Int\u00e9r\u00eats courus": {
+ "Int\u00e9r\u00eats courus \u00e0 payer": {
+ "account_number": "5181"
+ },
+ "Int\u00e9r\u00eats courus \u00e0 recevoir": {
+ "account_number": "5188"
+ },
+ "account_number": "518"
+ },
+ "Concours bancaires courants": {
+ "Cr\u00e9dit de mobilisation des cr\u00e9ances commerciales (CMCC)": {
+ "account_number": "5191"
+ },
+ "Mobilisation de cr\u00e9ances n\u00e9es \u00e0 l'\u00e9tranger": {
+ "account_number": "5193"
+ },
+ "Int\u00e9r\u00eats courus sur concours bancaires courants": {
+ "account_number": "5198"
+ },
+ "account_number": "519"
+ },
+ "account_number": "51"
+ },
+ "Instruments de tr\u00e9sorerie": {
+ "is_group": 1,
+ "account_number": "52"
+ },
+ "Caisse": {
+ "account_type": "Cash",
+ "Caisse si\u00e8ge social": {
+ "account_type": "Cash",
+ "Caisse en monnaie nationale": {
+ "account_type": "Cash",
+ "account_number": "5311"
+ },
+ "Caisse en devises": {
+ "account_type": "Cash",
+ "account_number": "5314"
+ },
+ "account_number": "531"
+ },
+ "Caisse succursale (ou usine) A": {
+ "account_type": "Cash",
+ "account_number": "532"
+ },
+ "Caisse succursale (ou usine) B": {
+ "account_type": "Cash",
+ "account_number": "533"
+ },
+ "account_number": "53"
+ },
+ "R\u00e9gies d'avance et accr\u00e9ditifs": {
+ "is_group": 1,
+ "account_number": "54"
+ },
+ "Virements internes": {
+ "is_group": 1,
+ "account_number": "58"
+ },
+ "D\u00e9pr\u00e9ciations des comptes financiers": {
+ "D\u00e9pr\u00e9ciations des valeurs mobili\u00e8res de placement": {
+ "Actions": {
+ "account_number": "5903"
+ },
+ "Autres titres conf\u00e9rant un droit de propri\u00e9t\u00e9": {
+ "account_number": "5904"
+ },
+ "Obligations": {
+ "account_number": "5906"
+ },
+ "Autres valeurs mobili\u00e8res de placement et cr\u00e9ances assimil\u00e9es": {
+ "account_number": "5908"
+ },
+ "account_number": "590"
+ },
+ "account_number": "59"
+ },
+ "account_number": "5"
+ },
+ "Comptes de Charges": {
+ "root_type": "Expense",
+ "Achats (sauf 603)": {
+ "Achats stock\u00e9s - Mati\u00e8res premi\u00e8res (et fournitures)": {
+ "account_type": "Cost of Goods Sold",
+ "Mati\u00e8res (ou groupe) A": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6011"
+ },
+ "Mati\u00e8res (ou groupe) B": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6012"
+ },
+ "Fournitures A, B, C...": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6017"
+ },
+ "account_number": "601"
+ },
+ "Achats stock\u00e9s - Autres approvisionnements": {
+ "account_type": "Cost of Goods Sold",
+ "Mati\u00e8res consommables": {
+ "account_type": "Cost of Goods Sold",
+ "Mati\u00e8res (ou groupe) C": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60211"
+ },
+ "Mati\u00e8res (ou groupe) D": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60212"
+ },
+ "account_number": "6021"
+ },
+ "Fournitures consommables": {
+ "account_type": "Cost of Goods Sold",
+ "Combustibles": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60221"
+ },
+ "Produits d'entretien": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60222"
+ },
+ "Fournitures d'atelier et d'usine": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60223"
+ },
+ "Fournitures de magasin": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60224"
+ },
+ "Fournitures de bureau": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60225"
+ },
+ "account_number": "6022"
+ },
+ "Emballages": {
+ "account_type": "Cost of Goods Sold",
+ "Emballages perdus": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60261"
+ },
+ "Emballages r\u00e9cup\u00e9rables non identifiables": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60265"
+ },
+ "Emballages \u00e0 usage mixte": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "60267"
+ },
+ "account_number": "6026"
+ },
+ "account_number": "602"
+ },
+ "Variations des stocks (approvisionnements et marchandises)": {
+ "account_type": "Stock Adjustment",
+ "Variation des stocks de mati\u00e8res premi\u00e8res (et fournitures)": {
+ "account_type": "Stock Adjustment",
+ "account_number": "6031"
+ },
+ "Variation des stocks des autres approvisionnements": {
+ "account_type": "Stock Adjustment",
+ "account_number": "6032"
+ },
+ "Variation des stocks de marchandises": {
+ "account_type": "Stock Adjustment",
+ "account_number": "6037"
+ },
+ "account_number": "603"
+ },
+ "Achats d'\u00e9tudes et prestations de service": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "604"
+ },
+ "Achats de mat\u00e9riel, \u00e9quipements et travaux": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "605"
+ },
+ "Achats non stock\u00e9s de mati\u00e8res et founitures": {
+ "account_type": "Cost of Goods Sold",
+ "Fournitures non stockables (eau, \u00e9nergie...)": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6061"
+ },
+ "Fournitures d'entretien et de petit \u00e9quipement": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6063"
+ },
+ "Fournitures administratives": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6064"
+ },
+ "Autres mati\u00e8res et fournitures": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6068"
+ },
+ "account_number": "606"
+ },
+ "Achats de marchandises": {
+ "account_type": "Cost of Goods Sold",
+ "Marchandises (ou groupe) A": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6071"
+ },
+ "Marchandises (ou groupe) B": {
+ "account_type": "Cost of Goods Sold",
+ "account_number": "6072"
+ },
+ "account_number": "607"
+ },
+ "(Compte r\u00e9serv\u00e9, le cas \u00e9ch\u00e9ant, \u00e0 la recapitulation des Frais accessoires incorpor\u00e9s aux achats)": {
+ "account_type": "Expenses Included In Valuation",
+ "account_number": "608"
+ },
+ "Rabais, remises et ristournes obtenus sur achats": {
+ "Rabais, remises et ristournes obtenus sur achats - de mati\u00e8res premi\u00e8res (et fournitures)": {
+ "account_number": "6091"
+ },
+ "Rabais, remises et ristournes obtenus sur achats - d'autres approvisionnements stock\u00e9s": {
+ "account_number": "6092"
+ },
+ "Rabais, remises et ristournes obtenus sur achats - d'\u00e9tudes et prestations de services": {
+ "account_number": "6094"
+ },
+ "Rabais, remises et ristournes obtenus sur achats - de mat\u00e9riel, \u00e9quipements et travaux": {
+ "account_number": "6095"
+ },
+ "Rabais, remises et ristournes obtenus sur achats - d'approvisionnements non stock\u00e9s": {
+ "account_number": "6096"
+ },
+ "Rabais, remises et ristournes obtenus sur achats - de marchandises": {
+ "account_number": "6097"
+ },
+ "Rabais, remises et ristournes non affect\u00e9s": {
+ "account_number": "6098"
+ },
+ "account_number": "609"
+ },
+ "account_number": "60"
+ },
+ "Services ext\u00e9rieurs": {
+ "Sous-traitance g\u00e9n\u00e9rale": {
+ "account_number": "611"
+ },
+ "Redevances de cr\u00e9dit-bail": {
+ "Cr\u00e9dit-bail mobilier": {
+ "account_number": "6122"
+ },
+ "Cr\u00e9dit-bail immobilier": {
+ "account_number": "6125"
+ },
+ "account_number": "612"
+ },
+ "Locations": {
+ "Locations immobili\u00e8res": {
+ "account_number": "6132"
+ },
+ "Locations mobili\u00e8res": {
+ "account_number": "6135"
+ },
+ "Malis sur emballages": {
+ "account_number": "6136"
+ },
+ "account_number": "613"
+ },
+ "Charges locatives et de copropri\u00e9t\u00e9": {
+ "account_number": "614"
+ },
+ "Entretiens et r\u00e9parations": {
+ "Entretiens et r\u00e9parations - sur biens immobiliers": {
+ "account_number": "6152"
+ },
+ "Entretiens et r\u00e9parations - sur biens mobiliers": {
+ "account_number": "6155"
+ },
+ "Maintenance": {
+ "account_number": "6156"
+ },
+ "account_number": "615"
+ },
+ "Primes d'assurance": {
+ "Multirisques": {
+ "account_number": "6161"
+ },
+ "Assurance obligatoire dommage construction": {
+ "account_number": "6162"
+ },
+ "Assurance-transport": {
+ "Assurance-transport - sur achats": {
+ "account_number": "61636"
+ },
+ "Assurance-transport - sur ventes": {
+ "account_number": "61637"
+ },
+ "Assurance-transport - sur autres biens": {
+ "account_number": "61638"
+ },
+ "account_number": "6163"
+ },
+ "Risques d'exploitation": {
+ "account_number": "6164"
+ },
+ "Insolvabilit\u00e9 clients": {
+ "account_number": "6165"
+ },
+ "account_number": "616"
+ },
+ "Etudes et recherches": {
+ "account_number": "617"
+ },
+ "Divers": {
+ "Documentation g\u00e9n\u00e9rale": {
+ "account_number": "6181"
+ },
+ "Documentation technique": {
+ "account_number": "6183"
+ },
+ "Frais de colloques, s\u00e9minaires, conf\u00e9rences": {
+ "account_number": "6185"
+ },
+ "account_number": "618"
+ },
+ "Rabais, remises et ristournes obtenus sur services ext\u00e9rieurs": {
+ "account_number": "619"
+ },
+ "account_number": "61"
+ },
+ "Autres services ext\u00e9rieurs": {
+ "Personnel ext\u00e9rieur \u00e0 l'entreprise": {
+ "Personnel int\u00e9rimaire": {
+ "account_number": "6211"
+ },
+ "Personnel d\u00e9tach\u00e9 ou pr\u00eat\u00e9 \u00e0 l'entreprise": {
+ "account_number": "6214"
+ },
+ "account_number": "621"
+ },
+ "R\u00e9mun\u00e9rations d'interm\u00e9diaires et honoraires": {
+ "Commissions et courtages sur achats": {
+ "account_number": "6221"
+ },
+ "Commissions et courtages sur ventes": {
+ "account_number": "6222"
+ },
+ "R\u00e9mun\u00e9rations des transitaires": {
+ "account_number": "6224"
+ },
+ "R\u00e9mun\u00e9rations d'affacturage": {
+ "account_number": "6225"
+ },
+ "Honoraires": {
+ "account_number": "6226"
+ },
+ "Frais d'actes et de contentieux": {
+ "account_number": "6227"
+ },
+ "Divers": {
+ "account_number": "6228"
+ },
+ "account_number": "622"
+ },
+ "Publicit\u00e9, publications, relations publiques": {
+ "Annonces et insertions": {
+ "account_number": "6231"
+ },
+ "Echantillons": {
+ "account_number": "6232"
+ },
+ "Foires et expositions": {
+ "account_number": "6233"
+ },
+ "Cadeaux \u00e0 la client\u00e8le": {
+ "account_number": "6234"
+ },
+ "Primes": {
+ "account_number": "6235"
+ },
+ "Catalogues et imprim\u00e9s": {
+ "account_number": "6236"
+ },
+ "Publications": {
+ "account_number": "6237"
+ },
+ "Divers (pourboires, dons courants...)": {
+ "account_number": "6238"
+ },
+ "account_number": "623"
+ },
+ "Transports de biens et transports collectifs du personnel": {
+ "Transports sur achats": {
+ "account_number": "6241"
+ },
+ "Transports sur ventes": {
+ "account_type": "Chargeable",
+ "account_number": "6242"
+ },
+ "Transports entre \u00e9tablissements ou chantiers": {
+ "account_number": "6243"
+ },
+ "Transports administratifs": {
+ "account_number": "6244"
+ },
+ "Transports collectifs du personnel": {
+ "account_number": "6247"
+ },
+ "Divers": {
+ "account_number": "6248"
+ },
+ "account_number": "624"
+ },
+ "D\u00e9placements, missions et r\u00e9ceptions": {
+ "Voyages et d\u00e9placements": {
+ "account_number": "6251"
+ },
+ "Frais de d\u00e9m\u00e9nagement": {
+ "account_number": "6255"
+ },
+ "Missions": {
+ "account_number": "6256"
+ },
+ "R\u00e9ceptions": {
+ "account_number": "6257"
+ },
+ "account_number": "625"
+ },
+ "Frais postaux et de t\u00e9l\u00e9communications": {
+ "account_number": "626"
+ },
+ "Services bancaires et assimil\u00e9s": {
+ "Frais sur titres (achat, vente, garde)": {
+ "account_number": "6271"
+ },
+ "Commissions et frais sur \u00e9mission d'emprunts": {
+ "account_number": "6272"
+ },
+ "Frais sur effets": {
+ "account_number": "6275"
+ },
+ "Location de coffres": {
+ "account_number": "6276"
+ },
+ "Autres frais et commissions sur prestations de services": {
+ "account_number": "6278"
+ },
+ "account_number": "627"
+ },
+ "Divers": {
+ "Concours divers (cotisations...)": {
+ "account_number": "6281"
+ },
+ "Frais de recrutement de personnel": {
+ "account_number": "6284"
+ },
+ "account_number": "628"
+ },
+ "Rabais, remises et ristournes obtenus sur autres services ext\u00e9rieurs": {
+ "account_number": "629"
+ },
+ "account_number": "62"
+ },
+ "Imp\u00f4ts, taxes et versements assimil\u00e9s": {
+ "Imp\u00f4ts, taxes et versements assimil\u00e9s sur r\u00e9mun\u00e9rations (administrations des imp\u00f4ts)": {
+ "Taxes sur les salaires": {
+ "account_number": "6311"
+ },
+ "Taxe d'apprentissage": {
+ "account_number": "6312"
+ },
+ "Participation des employeurs \u00e0 la formation professionnelle continue": {
+ "account_number": "6313"
+ },
+ "Cotisation pour d\u00e9faut d'investissement obligatoire dans la construction": {
+ "account_number": "6314"
+ },
+ "Autres": {
+ "account_number": "6318"
+ },
+ "account_number": "631"
+ },
+ "Imp\u00f4ts, taxes et versements assimil\u00e9s sur r\u00e9mun\u00e9rations (autres organismes)": {
+ "Versement de transport": {
+ "account_number": "6331"
+ },
+ "Allocations logement": {
+ "account_number": "6332"
+ },
+ "Participation des employeurs \u00e0 la formation professionnelle continue": {
+ "account_number": "6333"
+ },
+ "Participation des employeurs \u00e0 l'effort de construction": {
+ "account_number": "6334"
+ },
+ "Versements lib\u00e9ratoires ouvrant droit \u00e0 l'\u00e9xon\u00e9ration de la taxe d'apprentissage": {
+ "account_number": "6335"
+ },
+ "Autres": {
+ "account_number": "6338"
+ },
+ "account_number": "633"
+ },
+ "Autres imp\u00f4ts, taxes et versements assimil\u00e9s (administrations des imp\u00f4ts)": {
+ "Imp\u00f4ts directs (sauf imp\u00f4ts sur les b\u00e9n\u00e9fices)": {
+ "Contribution \u00e9conomique territoriale": {
+ "account_number": "63511"
+ },
+ "Taxes fonci\u00e8res": {
+ "account_number": "63512"
+ },
+ "Autres imp\u00f4ts locaux": {
+ "account_number": "63513"
+ },
+ "Taxe sur les v\u00e9hicules des soci\u00e9t\u00e9s": {
+ "account_number": "63514"
+ },
+ "account_number": "6351"
+ },
+ "Taxes sur le chiffre d'affaires non r\u00e9cup\u00e9rables": {
+ "account_number": "6352"
+ },
+ "Imp\u00f4ts indirects": {
+ "account_number": "6353"
+ },
+ "Droits d'enregistrement et de timbre": {
+ "Droits de mutation": {
+ "account_number": "63541"
+ },
+ "account_number": "6354"
+ },
+ "Autres droits": {
+ "account_number": "6358"
+ },
+ "account_number": "635"
+ },
+ "Autres imp\u00f4ts, taxes et versements assimil\u00e9s (autres organismes)": {
+ "Contribution sociale de solidarit\u00e9 \u00e0 la charge des soci\u00e9t\u00e9s": {
+ "account_number": "6371"
+ },
+ "Taxes per\u00e7ues par les organismes publics internationaux": {
+ "account_number": "6372"
+ },
+ "Imp\u00f4ts et taxes exigibles \u00e0 l'\u00e9tranger": {
+ "account_number": "6374"
+ },
+ "Taxes diverses": {
+ "account_number": "6378"
+ },
+ "account_number": "637"
+ },
+ "account_number": "63"
+ },
+ "Charges de personnel": {
+ "R\u00e9mun\u00e9rations du personnel": {
+ "Salaires, appointements": {
+ "account_number": "6411"
+ },
+ "Cong\u00e9s pay\u00e9s": {
+ "account_number": "6412"
+ },
+ "Primes et gratifications": {
+ "account_number": "6413"
+ },
+ "Indemnit\u00e9s et avantages divers": {
+ "account_number": "6414"
+ },
+ "Suppl\u00e9ment familial": {
+ "account_number": "6415"
+ },
+ "account_number": "641"
+ },
+ "R\u00e9mun\u00e9ration du travail de l'exploitant": {
+ "account_number": "644"
+ },
+ "Charges de s\u00e9curit\u00e9 sociale et de pr\u00e9voyance": {
+ "Cotisations \u00e0 l'URSSAF": {
+ "account_number": "6451"
+ },
+ "Cotisations aux mutuelles": {
+ "account_number": "6452"
+ },
+ "Cotisations aux caisses de retraites": {
+ "account_number": "6453"
+ },
+ "Cotisations aux ASSEDIC": {
+ "account_number": "6454"
+ },
+ "account_number": "645"
+ },
+ "Cotisations sociales personnelles de l'exploitant": {
+ "account_number": "646"
+ },
+ "Autres charges sociales": {
+ "is_group": 1,
+ "account_number": "647"
+ },
+ "Autres charges de personnel": {
+ "account_number": "648"
+ },
+ "account_number": "64"
+ },
+ "Autres charges de gestion courante": {
+ "Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels, droits et valeurs similaires": {
+ "Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels": {
+ "account_number": "6511"
+ },
+ "Droits d'auteur et de reproduction": {
+ "account_number": "6516"
+ },
+ "Autres droits et valeurs similaires": {
+ "account_number": "6518"
+ },
+ "account_number": "651"
+ },
+ "Jetons de pr\u00e9sence": {
+ "account_number": "653"
+ },
+ "Pertes sur cr\u00e9ances irr\u00e9couvrables": {
+ "Cr\u00e9ances de l'exercice": {
+ "account_number": "6541"
+ },
+ "Cr\u00e9ances des exercices ant\u00e9rieurs": {
+ "account_number": "6544"
+ },
+ "account_number": "654"
+ },
+ "Quotes-parts de r\u00e9sultat sur op\u00e9rations faites en commun": {
+ "Quote-part de b\u00e9n\u00e9fice transf\u00e9r\u00e9e (comptabilit\u00e9 du g\u00e9rant)": {
+ "account_number": "6551"
+ },
+ "Quote-part de perte support\u00e9e (comptabilit\u00e9 des associ\u00e9s non g\u00e9rants)": {
+ "account_number": "6555"
+ },
+ "account_number": "655"
+ },
+ "Pertes de change sur cr\u00e9ances et dettes commerciales": {
+ "account_number": "656"
+ },
+ "Charges diverses de gestion courante": {
+ "account_number": "658"
+ },
+ "account_number": "65"
+ },
+ "Charges financi\u00e8res": {
+ "Charges d'int\u00e9r\u00eats": {
+ "Int\u00e9r\u00eats des emprunts et dettes": {
+ "Int\u00e9r\u00eats des emprunts et dettes - des emprunts et dettes assimil\u00e9es": {
+ "account_number": "66116"
+ },
+ "Int\u00e9r\u00eats des emprunts et dettes - des dettes rattach\u00e9es \u00e0 des participations": {
+ "account_number": "66117"
+ },
+ "account_number": "6611"
+ },
+ "Charges de la fiducie, r\u00e9sultat de la p\u00e9riode": {
+ "account_number": "6612"
+ },
+ "Int\u00e9r\u00eats des comptes courants et des d\u00e9p\u00f4ts cr\u00e9diteurs": {
+ "account_number": "6615"
+ },
+ "Int\u00e9r\u00eats bancaires et sur op\u00e9rations de financement (escompte...)": {
+ "account_number": "6616"
+ },
+ "Int\u00e9r\u00eats des obligations cautionn\u00e9es": {
+ "account_number": "6617"
+ },
+ "Int\u00e9r\u00eats des autres dettes": {
+ "Int\u00e9r\u00eats des autres dettes - des dettes commerciales": {
+ "account_number": "66181"
+ },
+ "Int\u00e9r\u00eats des autres dettes - des dettes diverses": {
+ "account_number": "66188"
+ },
+ "account_number": "6618"
+ },
+ "account_number": "661"
+ },
+ "Pertes sur cr\u00e9ances li\u00e9es \u00e0 des participations": {
+ "account_number": "664"
+ },
+ "Escomptes accord\u00e9s": {
+ "account_number": "665"
+ },
+ "Pertes de change financi\u00e8res": {
+ "account_type": "Round Off",
+ "account_number": "666"
+ },
+ "Charges nettes sur cessions de valeurs mobili\u00e8res de placement": {
+ "account_number": "667"
+ },
+ "Autres charges financi\u00e8res": {
+ "account_number": "668"
+ },
+ "account_number": "66"
+ },
+ "Charges exceptionnelles": {
+ "Charges exceptionnelles sur op\u00e9rations de gestion": {
+ "P\u00e9nalit\u00e9s sur march\u00e9s (et d\u00e9dits pay\u00e9s sur achats et ventes)": {
+ "account_number": "6711"
+ },
+ "P\u00e9nalit\u00e9s, amendes fiscales et p\u00e9nales": {
+ "account_number": "6712"
+ },
+ "Dons, lib\u00e9ralit\u00e9s": {
+ "account_number": "6713"
+ },
+ "Cr\u00e9ances devenues irr\u00e9couvrables dans l'exercice": {
+ "account_number": "6714"
+ },
+ "Subventions accord\u00e9es": {
+ "account_number": "6715"
+ },
+ "Rappel d'imp\u00f4ts (autres qu'imp\u00f4ts sur les b\u00e9n\u00e9fices)": {
+ "account_number": "6717"
+ },
+ "Autres charges exceptionnelles sur op\u00e9rations de gestion": {
+ "account_number": "6718"
+ },
+ "account_number": "671"
+ },
+ "(Compte \u00e0 la disposition des entit\u00e9s pour enregistrer, en cours d'exercice, les charges sur exercices ant\u00e9rieurs)": {
+ "account_number": "672"
+ },
+ "Op\u00e9rations de constitution ou liquidation des fiducies": {
+ "Op\u00e9rations li\u00e9es \u00e0 la constitution de la fiducie - transfert des \u00e9l\u00e9ments": {
+ "account_number": "6741"
+ },
+ "Op\u00e9rations li\u00e9es \u00e0 la liquidation de la fiducie": {
+ "account_number": "6742"
+ },
+ "account_number": "674"
+ },
+ "Valeurs comptables des \u00e9l\u00e9ments d'actif c\u00e9d\u00e9s": {
+ "Immobilisations incorporelles": {
+ "account_number": "6751"
+ },
+ "Immobilisations corporelles": {
+ "account_number": "6752"
+ },
+ "Immobilisations financi\u00e8res": {
+ "account_number": "6756"
+ },
+ "Autres \u00e9l\u00e9ments d'actif": {
+ "account_number": "6758"
+ },
+ "account_number": "675"
+ },
+ "Autres charges exceptionnelles": {
+ "Mali provenant de clauses d'indexation": {
+ "account_number": "6781"
+ },
+ "Lots": {
+ "account_number": "6782"
+ },
+ "Malis provenant du rachat par l'entreprise d'actions et obligations \u00e9mises par elles-m\u00eame": {
+ "account_number": "6783"
+ },
+ "Charges exceptionnelles diverses": {
+ "account_number": "6788"
+ },
+ "account_number": "678"
+ },
+ "account_number": "67"
+ },
+ "Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions": {
+ "account_type": "Depreciation",
+ "Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions - Charges d'exploitation": {
+ "account_type": "Depreciation",
+ "Dotations aux amortissements sur immobilisations incorporelles et corporelles": {
+ "account_type": "Depreciation",
+ "Immobilisations incorporelles": {
+ "account_type": "Depreciation",
+ "account_number": "68111"
+ },
+ "Immobilisations corporelles": {
+ "account_type": "Depreciation",
+ "account_number": "68112"
+ },
+ "account_number": "6811"
+ },
+ "Dotations aux amortissements des charges d'exploitation \u00e0 r\u00e9partir": {
+ "account_type": "Depreciation",
+ "account_number": "6812"
+ },
+ "Dotations aux provisions d'exploitation": {
+ "account_type": "Depreciation",
+ "account_number": "6815"
+ },
+ "Dotations aux d\u00e9pr\u00e9ciations des immobilisations incorporelles et corporelles": {
+ "account_type": "Depreciation",
+ "Immobilisations incorporelles": {
+ "account_type": "Depreciation",
+ "account_number": "68161"
+ },
+ "Immobilisations corporelles": {
+ "account_type": "Depreciation",
+ "account_number": "68162"
+ },
+ "account_number": "6816"
+ },
+ "Dotations pour d\u00e9pr\u00e9ciations des actifs circulants": {
+ "account_type": "Depreciation",
+ "Stocks et en-cours": {
+ "account_type": "Depreciation",
+ "account_number": "68173"
+ },
+ "Cr\u00e9ances": {
+ "account_type": "Depreciation",
+ "account_number": "68174"
+ },
+ "account_number": "6817"
+ },
+ "account_number": "681"
+ },
+ "Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions - Charges financi\u00e8res": {
+ "account_type": "Depreciation",
+ "Dotations aux amortissements des primes de remboursement des obligations": {
+ "account_type": "Depreciation",
+ "account_number": "6861"
+ },
+ "Dotations aux provisions financi\u00e8res": {
+ "account_type": "Depreciation",
+ "account_number": "6865"
+ },
+ "Dotations aux d\u00e9pr\u00e9ciations des \u00e9l\u00e9ments financiers": {
+ "account_type": "Depreciation",
+ "Immobilisations financi\u00e8res": {
+ "account_type": "Depreciation",
+ "account_number": "68662"
+ },
+ "Valeurs mobili\u00e8res de placement": {
+ "account_type": "Depreciation",
+ "account_number": "68665"
+ },
+ "account_number": "6866"
+ },
+ "Autres dotations": {
+ "account_type": "Depreciation",
+ "account_number": "6868"
+ },
+ "account_number": "686"
+ },
+ "Dotations aux amortissements, d\u00e9pr\u00e9ciations et provisions - Charges exceptionnelles": {
+ "account_type": "Depreciation",
+ "Dotations aux amortissements exceptionnels des immobilisations": {
+ "account_type": "Depreciation",
+ "account_number": "6871"
+ },
+ "Dotations aux provisions r\u00e9glement\u00e9es (immobilisations)": {
+ "account_type": "Depreciation",
+ "Amortissements d\u00e9rogatoires": {
+ "account_type": "Depreciation",
+ "account_number": "68725"
+ },
+ "account_number": "6872"
+ },
+ "Dotations aux provisions r\u00e9glement\u00e9es (stocks)": {
+ "account_type": "Depreciation",
+ "account_number": "6873"
+ },
+ "Dotations aux autres provisions r\u00e9glement\u00e9es": {
+ "account_type": "Depreciation",
+ "account_number": "6874"
+ },
+ "Dotations aux provisions exceptionnelles": {
+ "account_type": "Depreciation",
+ "account_number": "6875"
+ },
+ "Dotations aux d\u00e9pr\u00e9ciations exceptionnelles": {
+ "account_type": "Depreciation",
+ "account_number": "6876"
+ },
+ "account_number": "687"
+ },
+ "account_number": "68"
+ },
+ "Participation des salari\u00e9s, imp\u00f4ts sur les b\u00e9n\u00e9fices et assimil\u00e9s": {
+ "Participation des salari\u00e9s aux r\u00e9sultats": {
+ "account_number": "691"
+ },
+ "Imp\u00f4ts sur les b\u00e9n\u00e9fices": {
+ "Imp\u00f4ts dus en France": {
+ "account_number": "6951"
+ },
+ "Contribution additionnelle \u00e0 l'imp\u00f4t sur les b\u00e9n\u00e9fices": {
+ "account_number": "6952"
+ },
+ "Imp\u00f4ts dus \u00e0 l'\u00e9tranger": {
+ "account_number": "6954"
+ },
+ "account_number": "695"
+ },
+ "Suppl\u00e9ments d'imp\u00f4ts sur les soci\u00e9t\u00e9s, li\u00e9s aux distributions": {
+ "account_number": "696"
+ },
+ "Int\u00e9gration fiscale": {
+ "Int\u00e9gration fiscale - Charges": {
+ "account_number": "6981"
+ },
+ "Int\u00e9gration fiscale - Produits": {
+ "account_number": "6989"
+ },
+ "account_number": "698"
+ },
+ "Produits - Report en arri\u00e8re des d\u00e9ficits": {
+ "account_number": "699"
+ },
+ "account_number": "69"
+ },
+ "account_number": "6"
+ },
+ "Comptes de Produits": {
+ "root_type": "Income",
+ "Ventes de produits fabriqu\u00e9s, prestations de services, marchandises": {
+ "Ventes de produits finis": {
+ "Produits finis (ou groupe) A": {
+ "account_number": "7011"
+ },
+ "Produits (ou groupe) B": {
+ "account_number": "7012"
+ },
+ "account_number": "701"
+ },
+ "Ventes de produits interm\u00e9diaires": {
+ "account_number": "702"
+ },
+ "Ventes de produits r\u00e9siduels": {
+ "account_number": "703"
+ },
+ "Travaux": {
+ "Travaux de cat\u00e9gorie (ou activit\u00e9) A": {
+ "account_number": "7041"
+ },
+ "Travaux de cat\u00e9gorie (ou activit\u00e9) B": {
+ "account_number": "7042"
+ },
+ "account_number": "704"
+ },
+ "Etudes": {
+ "account_number": "705"
+ },
+ "Prestations de services": {
+ "account_number": "706"
+ },
+ "Ventes de marchandises": {
+ "Marchandises (ou groupe) A": {
+ "account_number": "7071"
+ },
+ "Marchandises (ou groupe) B": {
+ "account_number": "7072"
+ },
+ "account_number": "707"
+ },
+ "Produits des activit\u00e9s annexes": {
+ "Produits des services exploit\u00e9s dans l'int\u00e9r\u00eat du personnel": {
+ "account_number": "7081"
+ },
+ "Commissions et courtages": {
+ "account_number": "7082"
+ },
+ "Locations diverses": {
+ "account_number": "7083"
+ },
+ "Mise \u00e0 disposition de personnel factur\u00e9e": {
+ "account_number": "7084"
+ },
+ "Ports et frais accessoires factur\u00e9s": {
+ "account_number": "7085"
+ },
+ "Bonis sur reprises d'emballages consign\u00e9s": {
+ "account_number": "7086"
+ },
+ "Bonifications obtenues des clients et primes sur ventes": {
+ "account_number": "7087"
+ },
+ "Autres produits d'activit\u00e9s annexes (cessions d'approvisionnements...)": {
+ "account_number": "7088"
+ },
+ "account_number": "708"
+ },
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise": {
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de produits finis": {
+ "account_number": "7091"
+ },
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de produits interm\u00e9diaires": {
+ "account_number": "7092"
+ },
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur travaux": {
+ "account_number": "7094"
+ },
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur \u00e9tudes": {
+ "account_number": "7095"
+ },
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur prestations de services": {
+ "account_number": "7096"
+ },
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur ventes de marchandises": {
+ "account_number": "7097"
+ },
+ "Rabais, remises et ristournes accord\u00e9s par l'entreprise - sur produits des activit\u00e9s annexes": {
+ "account_number": "7098"
+ },
+ "account_number": "709"
+ },
+ "account_number": "70"
+ },
+ "Production stock\u00e9e (ou d\u00e9stockage)": {
+ "Variation des stocks (en-cours de production, produits)": {
+ "Variation des en-cours de production de biens": {
+ "Produits en cours": {
+ "account_number": "71331"
+ },
+ "Travaux en cours": {
+ "account_number": "71335"
+ },
+ "account_number": "7133"
+ },
+ "Variation des en-cours de production de services": {
+ "Etudes en cours": {
+ "account_number": "71341"
+ },
+ "Prestations de services en cours": {
+ "account_number": "71345"
+ },
+ "account_number": "7134"
+ },
+ "Variation des stocks de produits": {
+ "Produits interm\u00e9diaires": {
+ "account_number": "71351"
+ },
+ "Produits finis": {
+ "account_number": "71355"
+ },
+ "Produits r\u00e9siduels": {
+ "account_number": "71358"
+ },
+ "account_number": "7135"
+ },
+ "account_number": "713"
+ },
+ "account_number": "71"
+ },
+ "Production immobilis\u00e9e": {
+ "Immobilisations incorporelles": {
+ "account_number": "721"
+ },
+ "Immobilisations corporelles": {
+ "account_number": "722"
+ },
+ "account_number": "72"
+ },
+ "Subventions d'exploitation": {
+ "is_group": 1,
+ "account_number": "74"
+ },
+ "Autres produits de gestion courante": {
+ "Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels, droits et valeurs similaires": {
+ "Redevances pour concessions, brevets, licences, marques, proc\u00e9d\u00e9s, logiciels": {
+ "account_number": "7511"
+ },
+ "Droits d'auteur et de reproduction": {
+ "account_number": "7516"
+ },
+ "Autres droits et valeurs similaires": {
+ "account_number": "7518"
+ },
+ "account_number": "751"
+ },
+ "Revenus des immeubles non affect\u00e9s aux activit\u00e9s professionnelles": {
+ "account_number": "752"
+ },
+ "Jetons de pr\u00e9sence et r\u00e9mun\u00e9rations d'administrateurs, g\u00e9rants...": {
+ "account_number": "753"
+ },
+ "Ristournes per\u00e7ues des coop\u00e9ratives (provenant des exc\u00e9dents)": {
+ "account_number": "754"
+ },
+ "Quotes-parts de r\u00e9sultats sur op\u00e9rations faites en commun": {
+ "Quote-part de perte transf\u00e9r\u00e9e (comptabilit\u00e9 du g\u00e9rant)": {
+ "account_number": "7551"
+ },
+ "Quote-part de b\u00e9n\u00e9fice attribu\u00e9 (comptabilit\u00e9 des associ\u00e9s non g\u00e9rants)": {
+ "account_number": "7555"
+ },
+ "account_number": "755"
+ },
+ "Gains de change sur cr\u00e9ances et dettes commerciales": {
+ "account_number": "756"
+ },
+ "Produits divers de gestion courante": {
+ "account_number": "758"
+ },
+ "account_number": "75"
+ },
+ "Produits financiers": {
+ "Produits de participations": {
+ "Revenus des titres de participation": {
+ "account_number": "7611"
+ },
+ "Produits de la fiducie, r\u00e9sultat de la p\u00e9riode": {
+ "account_number": "7612"
+ },
+ "Revenus sur autres formes de participation": {
+ "account_number": "7616"
+ },
+ "Revenus des cr\u00e9ances rattach\u00e9es \u00e0 des participations": {
+ "account_number": "7617"
+ },
+ "account_number": "761"
+ },
+ "Produits des autres immobilisations financi\u00e8res": {
+ "Revenus des titres immobilis\u00e9s": {
+ "account_number": "7621"
+ },
+ "Revenus des pr\u00eats": {
+ "account_number": "7626"
+ },
+ "Revenus des cr\u00e9ances immobilis\u00e9es": {
+ "account_number": "7627"
+ },
+ "account_number": "762"
+ },
+ "Revenus des autres cr\u00e9ances": {
+ "Revenus des cr\u00e9ances commerciales": {
+ "account_number": "7631"
+ },
+ "Revenus des cr\u00e9ances diverses": {
+ "account_number": "7638"
+ },
+ "account_number": "763"
+ },
+ "Revenus des valeurs mobili\u00e8res de placement": {
+ "account_number": "764"
+ },
+ "Escomptes obtenus": {
+ "account_number": "765"
+ },
+ "Gains de change financi\u00e8res": {
+ "account_type": "Round Off",
+ "account_number": "766"
+ },
+ "Produits nets sur cessions de valeurs mobili\u00e8res de placement": {
+ "account_number": "767"
+ },
+ "Autres produits financiers": {
+ "account_number": "768"
+ },
+ "account_number": "76"
+ },
+ "Produits exceptionnels": {
+ "Produits exceptionnels sur op\u00e9rations de gestion": {
+ "D\u00e9dits et p\u00e9nalit\u00e9s per\u00e7us sur achats et sur ventes": {
+ "account_number": "7711"
+ },
+ "Lib\u00e9ralit\u00e9s re\u00e7ues": {
+ "account_number": "7713"
+ },
+ "Rentr\u00e9es sur cr\u00e9ances amorties": {
+ "account_number": "7714"
+ },
+ "Subventions d'\u00e9quilibre": {
+ "account_number": "7715"
+ },
+ "D\u00e9gr\u00e8vements d'imp\u00f4ts autres qu'imp\u00f4ts sur les b\u00e9n\u00e9fices": {
+ "account_number": "7717"
+ },
+ "Autres produits exceptionnels sur op\u00e9rations de gestion": {
+ "account_number": "7718"
+ },
+ "account_number": "771"
+ },
+ "(Compte \u00e0 la disposition des entit\u00e9s pour enregistrer, en cours d'exercice, les Produits sur exercices ant\u00e9rieurs)": {
+ "account_number": "772"
+ },
+ "Op\u00e9rations de constitution ou liquidation des fiducies": {
+ "Op\u00e9rations li\u00e9es \u00e0 la constitution de la fiducie - transfert des \u00e9l\u00e9ments": {
+ "account_number": "7741"
+ },
+ "Op\u00e9rations li\u00e9es \u00e0 la liquidation de la fiducie": {
+ "account_number": "7742"
+ },
+ "account_number": "774"
+ },
+ "Produits des cessions d'\u00e9l\u00e9ments d'actif": {
+ "Immobilisations incorporelles": {
+ "account_number": "7751"
+ },
+ "Immobilisations corporelles": {
+ "account_number": "7752"
+ },
+ "Immobilisations financi\u00e8res": {
+ "account_number": "7756"
+ },
+ "Autres \u00e9l\u00e9ments d'actif": {
+ "account_number": "7758"
+ },
+ "account_number": "775"
+ },
+ "Quote-part des subventions d'investissement vir\u00e9e au r\u00e9sultat de l'exercice": {
+ "account_number": "777"
+ },
+ "Autres produits exceptionnels": {
+ "Bonis provenant de clauses d'indexation": {
+ "account_number": "7781"
+ },
+ "Lots": {
+ "account_number": "7782"
+ },
+ "Bonis provenant du rachat par l'entreprise d'actions et d'obligations \u00e9mises par elle-m\u00eame": {
+ "account_number": "7783"
+ },
+ "Produits exceptionnels divers": {
+ "account_number": "7788"
+ },
+ "account_number": "778"
+ },
+ "account_number": "77"
+ },
+ "Reprises sur amortissements, d\u00e9pr\u00e9ciations et provisions": {
+ "Reprises sur amortissements, d\u00e9pr\u00e9ciations et provisions (\u00e0 inscrire dans les produits d'exploitation)": {
+ "Reprises sur amortissements des immobilisations incorporelles et corporelles": {
+ "Immobilisations incorporelles": {
+ "account_number": "78111"
+ },
+ "Immobilisations corporelles": {
+ "account_number": "78112"
+ },
+ "account_number": "7811"
+ },
+ "Reprises sur provisions d'exploitation": {
+ "account_number": "7815"
+ },
+ "Reprises sur d\u00e9pr\u00e9ciations des immobilisations corporelles et incorporelles": {
+ "Immobilisations incorporelles": {
+ "account_number": "78161"
+ },
+ "Immobilisations corporelles": {
+ "account_number": "78162"
+ },
+ "account_number": "7816"
+ },
+ "Reprises sur d\u00e9pr\u00e9ciations des actifs circulants": {
+ "Stocks et en-cours": {
+ "account_number": "78173"
+ },
+ "Cr\u00e9ances": {
+ "account_number": "78174"
+ },
+ "account_number": "7817"
+ },
+ "account_number": "781"
+ },
+ "Reprises sur d\u00e9pr\u00e9ciations et provisions (\u00e0 inscrire dans les produits financiers)": {
+ "Reprises sur provisions financi\u00e8res": {
+ "account_number": "7865"
+ },
+ "Reprises sur d\u00e9pr\u00e9ciations des \u00e9l\u00e9ments financiers": {
+ "Immobilisations financi\u00e8res": {
+ "account_number": "78662"
+ },
+ "Valeurs mobili\u00e8res de placement": {
+ "account_number": "78665"
+ },
+ "account_number": "7866"
+ },
+ "account_number": "786"
+ },
+ "Reprises sur d\u00e9pr\u00e9ciations et provisions (\u00e0 inscrire dans les produits exceptionnels)": {
+ "Reprises sur provisions r\u00e9glement\u00e9es (immobilisations)": {
+ "Amortissements d\u00e9rogatoires": {
+ "account_number": "78725"
+ },
+ "Provision sp\u00e9ciale de r\u00e9\u00e9valuation": {
+ "account_number": "78726"
+ },
+ "Plus-values r\u00e9investies": {
+ "account_number": "78727"
+ },
+ "account_number": "7872"
+ },
+ "Reprises sur provisions r\u00e9glement\u00e9es (stocks)": {
+ "account_number": "7873"
+ },
+ "Reprises sur autres provisions r\u00e9glement\u00e9es": {
+ "account_number": "7874"
+ },
+ "Reprises sur provisions exceptionnelles": {
+ "account_number": "7875"
+ },
+ "Reprises sur d\u00e9pr\u00e9ciations exceptionnelles": {
+ "account_number": "7876"
+ },
+ "account_number": "787"
+ },
+ "account_number": "78"
+ },
+ "Transferts de charges": {
+ "Transferts de charges d'exploitation": {
+ "account_number": "791"
+ },
+ "Transferts de charges financi\u00e8res": {
+ "account_number": "796"
+ },
+ "Transferts de charges exceptionnelles": {
+ "account_number": "797"
+ },
+ "account_number": "79"
+ },
+ "account_number": "7"
+ }
+ }
+}
\ No newline at end of file
From bcf3f3dd29ca2d3022b0fb59c628928a3d993d6b Mon Sep 17 00:00:00 2001
From: Syed Mujeer Hashmi
Date: Fri, 7 May 2021 13:34:21 +0530
Subject: [PATCH 025/262] fix: Monthly Attendance Sheet Summarized view
(#24976)
* fix: Monthly Attendance Sheet Summarized view
This fixes the count of different leave types in the monthly
attendance sheet summarized view.
Signed-off-by: Syed Mujeer Hashmi
* fix: Avoid using raw sql query
Signed-off-by: Syed Mujeer Hashmi
Co-authored-by: Anurag Mishra <32095923+Anurag810@users.noreply.github.com>
---
.../monthly_attendance_sheet.py | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
index c5929c6bf9..bcb0ee4d0d 100644
--- a/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
+++ b/erpnext/hr/report/monthly_attendance_sheet/monthly_attendance_sheet.py
@@ -57,10 +57,10 @@ def execute(filters=None):
data = []
+ leave_types = frappe.db.get_list("Leave Type")
leave_list = None
if filters.summarized_view:
- leave_types = frappe.db.sql("""select name from `tabLeave Type`""", as_list=True)
- leave_list = [d[0] + ":Float:120" for d in leave_types]
+ leave_list = [d.name + ":Float:120" for d in leave_types]
columns.extend(leave_list)
columns.extend([_("Total Late Entries") + ":Float:120", _("Total Early Exits") + ":Float:120"])
@@ -72,11 +72,11 @@ def execute(filters=None):
if (att_map_set & emp_map_set):
parameter_row = [""+ parameter + ""] + ['' for day in range(filters["total_days_in_month"] + 2)]
data.append(parameter_row)
- record, emp_att_data = add_data(emp_map[parameter], att_map, filters, holiday_map, conditions, default_holiday_list, leave_list=leave_list)
+ record, emp_att_data = add_data(emp_map[parameter], att_map, filters, holiday_map, conditions, default_holiday_list, leave_types=leave_types)
emp_att_map.update(emp_att_data)
data += record
else:
- record, emp_att_map = add_data(emp_map, att_map, filters, holiday_map, conditions, default_holiday_list, leave_list=leave_list)
+ record, emp_att_map = add_data(emp_map, att_map, filters, holiday_map, conditions, default_holiday_list, leave_types=leave_types)
data += record
chart_data = get_chart_data(emp_att_map, days)
@@ -126,7 +126,7 @@ def get_chart_data(emp_att_map, days):
return chart
-def add_data(employee_map, att_map, filters, holiday_map, conditions, default_holiday_list, leave_list=None):
+def add_data(employee_map, att_map, filters, holiday_map, conditions, default_holiday_list, leave_types=None):
record = []
emp_att_map = {}
@@ -204,9 +204,9 @@ def add_data(employee_map, att_map, filters, holiday_map, conditions, default_ho
else:
leaves[d.leave_type] = d.count
- for d in leave_list:
- if d in leaves:
- row.append(leaves[d])
+ for d in leave_types:
+ if d.name in leaves:
+ row.append(leaves[d.name])
else:
row.append("0.0")
From f75173826707e10815cfd91bc167c00434a0a6c8 Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Fri, 7 May 2021 14:51:05 +0530
Subject: [PATCH 026/262] fix: Make js bundles
---
.../js/bank-reconciliation-tool.bundle.js | 3 +++
erpnext/public/js/erpnext-web.bundle.js | 2 ++
erpnext/public/js/erpnext.bundle.js | 27 +++++++++++++++++++
.../{marketplace.js => marketplace.bundle.js} | 0
erpnext/public/js/item-dashboard.bundle.js | 5 ++++
erpnext/public/js/point-of-sale.bundle.js | 8 ++++++
6 files changed, 45 insertions(+)
create mode 100644 erpnext/public/js/bank-reconciliation-tool.bundle.js
create mode 100644 erpnext/public/js/erpnext-web.bundle.js
create mode 100644 erpnext/public/js/erpnext.bundle.js
rename erpnext/public/js/hub/{marketplace.js => marketplace.bundle.js} (100%)
create mode 100644 erpnext/public/js/item-dashboard.bundle.js
create mode 100644 erpnext/public/js/point-of-sale.bundle.js
diff --git a/erpnext/public/js/bank-reconciliation-tool.bundle.js b/erpnext/public/js/bank-reconciliation-tool.bundle.js
new file mode 100644
index 0000000000..636ef18a51
--- /dev/null
+++ b/erpnext/public/js/bank-reconciliation-tool.bundle.js
@@ -0,0 +1,3 @@
+import "./bank_reconciliation_tool/data_table_manager";
+import "./bank_reconciliation_tool/number_card";
+import "./bank_reconciliation_tool/dialog_manager";
diff --git a/erpnext/public/js/erpnext-web.bundle.js b/erpnext/public/js/erpnext-web.bundle.js
new file mode 100644
index 0000000000..7db6967923
--- /dev/null
+++ b/erpnext/public/js/erpnext-web.bundle.js
@@ -0,0 +1,2 @@
+import "./website_utils";
+import "./shopping_cart";
diff --git a/erpnext/public/js/erpnext.bundle.js b/erpnext/public/js/erpnext.bundle.js
new file mode 100644
index 0000000000..519cfcac72
--- /dev/null
+++ b/erpnext/public/js/erpnext.bundle.js
@@ -0,0 +1,27 @@
+import "./conf";
+import "./utils";
+import "./queries";
+import "./sms_manager";
+import "./utils/party";
+import "./controllers/stock_controller";
+import "./payment/payments";
+import "./controllers/taxes_and_totals";
+import "./controllers/transaction";
+import "./templates/item_selector.html";
+import "./templates/employees_to_mark_attendance.html";
+import "./utils/item_selector";
+import "./help_links";
+import "./agriculture/ternary_plot";
+import "./templates/item_quick_entry.html";
+import "./utils/item_quick_entry";
+import "./utils/customer_quick_entry";
+import "./education/student_button.html";
+import "./education/assessment_result_tool.html";
+import "./hub/hub_factory";
+import "./call_popup/call_popup";
+import "./utils/dimension_tree_filter";
+import "./telephony";
+import "./templates/call_link.html";
+
+// import { sum } from 'frappe/public/utils/util.js'
+
diff --git a/erpnext/public/js/hub/marketplace.js b/erpnext/public/js/hub/marketplace.bundle.js
similarity index 100%
rename from erpnext/public/js/hub/marketplace.js
rename to erpnext/public/js/hub/marketplace.bundle.js
diff --git a/erpnext/public/js/item-dashboard.bundle.js b/erpnext/public/js/item-dashboard.bundle.js
new file mode 100644
index 0000000000..2d329e26aa
--- /dev/null
+++ b/erpnext/public/js/item-dashboard.bundle.js
@@ -0,0 +1,5 @@
+import "../../stock/dashboard/item_dashboard.html";
+import "../../stock/dashboard/item_dashboard_list.html";
+import "../../stock/dashboard/item_dashboard.js";
+import "../../stock/page/warehouse_capacity_summary/warehouse_capacity_summary.html";
+import "../../stock/page/warehouse_capacity_summary/warehouse_capacity_summary_header.html";
diff --git a/erpnext/public/js/point-of-sale.bundle.js b/erpnext/public/js/point-of-sale.bundle.js
new file mode 100644
index 0000000000..fbc4bbbbb3
--- /dev/null
+++ b/erpnext/public/js/point-of-sale.bundle.js
@@ -0,0 +1,8 @@
+import "../../selling/page/point_of_sale/pos_item_selector.js";
+import "../../selling/page/point_of_sale/pos_item_cart.js";
+import "../../selling/page/point_of_sale/pos_item_details.js";
+import "../../selling/page/point_of_sale/pos_number_pad.js";
+import "../../selling/page/point_of_sale/pos_payment.js";
+import "../../selling/page/point_of_sale/pos_past_order_list.js";
+import "../../selling/page/point_of_sale/pos_past_order_summary.js";
+import "../../selling/page/point_of_sale/pos_controller.js";
From ff3b71d2e7ad0897ca1a641febf88cba7c212fbb Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Fri, 7 May 2021 14:52:13 +0530
Subject: [PATCH 027/262] fix: Make css bundles
---
erpnext/public/css/email.css | 29 -
erpnext/public/css/erpnext.css | 408 ------------
erpnext/public/css/leaflet/leaflet.css | 611 ------------------
erpnext/public/css/leaflet/leaflet.draw.css | 316 ---------
erpnext/public/less/hub.less | 375 -----------
erpnext/public/less/pos.less | 229 -------
erpnext/public/less/products.less | 71 --
erpnext/public/less/website.less | 388 -----------
.../email.less => scss/email.bundle.scss} | 16 +-
erpnext/public/scss/erpnext-web.bundle.scss | 2 +
erpnext/public/scss/erpnext.bundle.scss | 3 +
.../{less/erpnext.less => scss/erpnext.scss} | 62 +-
12 files changed, 44 insertions(+), 2466 deletions(-)
delete mode 100644 erpnext/public/css/email.css
delete mode 100644 erpnext/public/css/erpnext.css
delete mode 100755 erpnext/public/css/leaflet/leaflet.css
delete mode 100755 erpnext/public/css/leaflet/leaflet.draw.css
delete mode 100644 erpnext/public/less/hub.less
delete mode 100644 erpnext/public/less/pos.less
delete mode 100644 erpnext/public/less/products.less
delete mode 100644 erpnext/public/less/website.less
rename erpnext/public/{less/email.less => scss/email.bundle.scss} (60%)
create mode 100644 erpnext/public/scss/erpnext-web.bundle.scss
create mode 100644 erpnext/public/scss/erpnext.bundle.scss
rename erpnext/public/{less/erpnext.less => scss/erpnext.scss} (82%)
diff --git a/erpnext/public/css/email.css b/erpnext/public/css/email.css
deleted file mode 100644
index 8cf1a31ad6..0000000000
--- a/erpnext/public/css/email.css
+++ /dev/null
@@ -1,29 +0,0 @@
-.panel-header {
- background-color: #fafbfc;
- border: 1px solid #d1d8dd;
- border-radius: 3px 3px 0 0;
-}
-.panel-body {
- background-color: #fff;
- border: 1px solid #d1d8dd;
- border-top: none;
- border-radius: 0 0 3px 3px;
- overflow-wrap: break-word;
-}
-.sender-avatar {
- width: 24px;
- height: 24px;
- border-radius: 3px;
- vertical-align: middle;
-}
-.sender-avatar-placeholder {
- width: 24px;
- height: 24px;
- border-radius: 3px;
- vertical-align: middle;
- line-height: 24px;
- text-align: center;
- color: #d1d8dd;
- border: 1px solid #d1d8dd;
- background-color: #fff;
-}
diff --git a/erpnext/public/css/erpnext.css b/erpnext/public/css/erpnext.css
deleted file mode 100644
index 6e4efcb668..0000000000
--- a/erpnext/public/css/erpnext.css
+++ /dev/null
@@ -1,408 +0,0 @@
-.erpnext-footer {
- margin: 11px auto;
- text-align: center;
-}
-.show-all-reports {
- margin-top: 5px;
- font-size: 11px;
-}
-/* toolbar */
-.toolbar-splash {
- width: 32px;
- height: 32px;
- margin: -10px auto;
-}
-.erpnext-icon {
- width: 24px;
- margin-right: 0px;
- margin-top: -3px;
-}
-.dashboard-list-item {
- background-color: inherit;
- padding: 5px 0px;
- border-bottom: 1px solid #d1d8dd;
-}
-#page-stock-balance .dashboard-list-item {
- padding: 5px 15px;
-}
-.dashboard-list-item:last-child {
- border-bottom: none;
-}
-.frappe-control[data-fieldname='result_html'] {
- overflow: scroll;
-}
-.assessment-result-tool {
- table-layout: fixed;
-}
-.assessment-result-tool input {
- width: 100%;
- border: 0;
- outline: none;
- text-align: right;
-}
-.assessment-result-tool th {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-.assessment-result-tool .total-score,
-.assessment-result-tool .grade,
-.assessment-result-tool .score {
- text-align: right;
-}
-/* pos */
-body[data-route="pos"] .pos-bill-toolbar {
- padding: 10px 0px;
- height: 51px;
-}
-body[data-route="pos"] .pos-bill-item:hover,
-body[data-route="pos"] .list-customers-table > .pos-list-row:hover {
- background-color: #f5f7fa;
- cursor: pointer;
-}
-body[data-route="pos"] .pos-item-qty {
- display: inline-block;
-}
-body[data-route="pos"] .pos-qty-row > div {
- padding: 5px 0px;
-}
-body[data-route="pos"] .pos-qty-btn {
- margin-top: 3px;
- cursor: pointer;
- font-size: 120%;
-}
-body[data-route="pos"] .search-area .form-group {
- max-width: 100% !important;
-}
-body[data-route="pos"] .tax-table {
- margin-bottom: 10px;
-}
-body[data-route="pos"] .discount-field-col {
- padding-left: 24px;
-}
-body[data-route="pos"] .discount-amount-area .input-group:first-child {
- margin-bottom: 2px;
-}
-body[data-route="pos"] .payment-toolbar .row {
- width: 323px;
- margin: 0 auto;
-}
-body[data-route="pos"] .payment-mode {
- cursor: pointer;
- font-family: sans-serif;
- font-size: 15px;
-}
-body[data-route="pos"] .pos-payment-row .col-xs-6 {
- padding: 15px;
-}
-body[data-route="pos"] .pos-payment-row {
- border-bottom: 1px solid #d1d8dd;
- margin: 2px 0px 5px 0px;
- height: 60px;
- margin-top: 0px;
- margin-bottom: 0px;
-}
-body[data-route="pos"] .pos-payment-row:hover,
-body[data-route="pos"] .pos-keyboard-key:hover {
- background-color: #fafbfc;
- cursor: pointer;
-}
-body[data-route="pos"] .pos-keyboard-key,
-body[data-route="pos"] .delete-btn {
- border: 1px solid #d1d8dd;
- height: 85px;
- width: 85px;
- margin: 10px 10px;
- font-size: 24px;
- font-weight: 200;
- background-color: #FDFDFD;
- border-color: #e8e8e8;
-}
-body[data-route="pos"] .numeric-keypad {
- border: 1px solid #d1d8dd;
- height: 69px;
- width: 69px;
- font-size: 20px;
- font-weight: 200;
- background-color: #FDFDFD;
- border-color: #e8e8e8;
- margin-left: -4px;
-}
-body[data-route="pos"] .pos-pay {
- height: 69px;
- width: 69px;
- font-size: 17px;
- font-weight: 200;
- margin-left: -4px;
-}
-body[data-route="pos"] .numeric-keypad {
- height: 60px;
- width: 60px;
- font-size: 20px;
- font-weight: 200;
- border-radius: 0;
- background-color: #fff;
- margin-left: -4px;
-}
-@media (max-width: 1199px) {
- body[data-route="pos"] .numeric-keypad {
- height: 45px;
- width: 45px;
- font-size: 14px;
- }
-}
-@media (max-width: 991px) {
- body[data-route="pos"] .numeric-keypad {
- height: 40px;
- width: 40px;
- }
-}
-body[data-route="pos"] .numeric_keypad {
- margin-left: -15px;
-}
-body[data-route="pos"] .numeric_keypad > .row > button {
- border: none;
- border-right: 1px solid #d1d8dd;
- border-bottom: 1px solid #d1d8dd;
-}
-body[data-route="pos"] .numeric_keypad > .row > button:first-child {
- border-left: 1px solid #d1d8dd;
-}
-body[data-route="pos"] .numeric_keypad > .row:first-child > button {
- border-top: 1px solid #d1d8dd;
-}
-body[data-route="pos"] .pos-pay {
- background-color: #5E64FF;
- border: none;
-}
-body[data-route="pos"] .multimode-payments {
- padding-left: 30px;
-}
-body[data-route="pos"] .payment-toolbar {
- padding-right: 30px;
-}
-body[data-route="pos"] .list-row-head.pos-invoice-list {
- border-top: 1px solid #d1d8dd;
-}
-body[data-route="pos"] .modal-dialog {
- width: 750px;
-}
-@media (max-width: 767px) {
- body[data-route="pos"] .modal-dialog {
- width: auto;
- }
- body[data-route="pos"] .modal-dialog .modal-content {
- height: auto;
- }
-}
-@media (max-width: 767px) {
- body[data-route="pos"] .amount-row h3 {
- font-size: 15px;
- }
- body[data-route="pos"] .pos-keyboard-key,
- body[data-route="pos"] .delete-btn {
- height: 50px;
- }
- body[data-route="pos"] .multimode-payments {
- padding-left: 15px;
- }
- body[data-route="pos"] .payment-toolbar {
- padding-right: 15px;
- }
-}
-body[data-route="pos"] .amount-label {
- font-size: 16px;
-}
-body[data-route="pos"] .selected-payment-mode {
- background-color: #fafbfc;
- cursor: pointer;
-}
-body[data-route="pos"] .pos-invoice-list {
- padding: 15px 10px;
-}
-body[data-route="pos"] .write_off_amount,
-body[data-route="pos"] .change_amount {
- margin: 15px;
- width: 130px;
-}
-body[data-route="pos"] .pos-list-row {
- display: table;
- table-layout: fixed;
- width: 100%;
- padding: 9px 15px;
- font-size: 12px;
- margin: 0px;
- border-bottom: 1px solid #d1d8dd;
-}
-body[data-route="pos"] .pos-list-row .cell {
- display: table-cell;
- vertical-align: middle;
-}
-body[data-route="pos"] .pos-list-row .cell.price-cell {
- width: 50%;
-}
-body[data-route="pos"] .pos-list-row .subject {
- width: 40%;
-}
-body[data-route="pos"] .pos-list-row .list-row-checkbox,
-body[data-route="pos"] .pos-list-row .list-select-all {
- margin-right: 7px;
-}
-body[data-route="pos"] .pos-bill-header {
- background-color: #f5f7fa;
- border: 1px solid #d1d8dd;
- padding: 13px 15px;
-}
-body[data-route="pos"] .pos-list-row.active {
- background-color: #fffce7;
-}
-body[data-route="pos"] .totals-area {
- border-right: 1px solid #d1d8dd;
- border-left: 1px solid #d1d8dd;
- margin-bottom: 15px;
-}
-body[data-route="pos"] .tax-area .pos-list-row {
- border: none;
-}
-body[data-route="pos"] .item-cart-items {
- height: calc(100vh - 526px);
- overflow: auto;
- border: 1px solid #d1d8dd;
- border-top: none;
-}
-@media (max-width: 767px) {
- body[data-route="pos"] .item-cart-items {
- height: 30vh;
- }
-}
-body[data-route="pos"] .no-items-message {
- min-height: 200px;
- display: flex;
- align-items: center;
- justify-content: center;
- height: 100%;
-}
-body[data-route="pos"] .pos-list-row:last-child {
- border-bottom: none;
-}
-body[data-route="pos"] .form-section-heading {
- padding: 0;
-}
-body[data-route="pos"] .item-list {
- border: 1px solid #d1d8dd;
- border-top: none;
- max-height: calc(100vh - 190px);
- overflow: auto;
-}
-@media (max-width: 767px) {
- body[data-route="pos"] .item-list {
- max-height: initial;
- }
-}
-body[data-route="pos"] .item-list .image-field {
- height: 140px;
-}
-body[data-route="pos"] .item-list .image-field .placeholder-text {
- font-size: 50px;
-}
-body[data-route="pos"] .item-list .pos-item-wrapper {
- position: relative;
-}
-body[data-route="pos"] .pos-bill-toolbar {
- margin-top: 10px;
-}
-body[data-route="pos"] .search-item .form-group {
- margin: 0;
-}
-body[data-route="pos"] .item-list-area .pos-bill-header {
- padding: 5px;
- padding-left: 15px;
-}
-body[data-route="pos"] .pos-selected-item-action .pos-list-row:first-child {
- padding-top: 0;
-}
-body[data-route="pos"] .pos-selected-item-action > .pos-list-row {
- border: none;
-}
-@media (max-width: 1199px) {
- body[data-route="pos"] .pos-selected-item-action > .pos-list-row {
- padding: 5px 15px;
- }
-}
-body[data-route="pos"] .edit-customer-btn {
- position: absolute;
- right: 57px;
- top: 15px;
- z-index: 100;
-}
-body[data-route="pos"] .btn-more {
- display: flex;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- background-color: #fafbfc;
- min-height: 200px;
-}
-body[data-route="pos"] .collapse-btn {
- cursor: pointer;
-}
-@media (max-width: 767px) {
- body[data-route="pos"] .page-actions {
- max-width: 110px;
- }
-}
-.price-info {
- position: absolute;
- left: 0;
- bottom: 0;
- margin: 0 0 15px 15px;
- background-color: rgba(141, 153, 166, 0.6);
- padding: 5px 9px;
- border-radius: 3px;
- color: #fff;
-}
-.leaderboard .result {
- border-top: 1px solid #d1d8dd;
-}
-.leaderboard .list-item {
- padding-left: 45px;
-}
-.leaderboard .list-item_content {
- padding-right: 45px;
-}
-.exercise-card {
- box-shadow: 0 1px 3px rgba(0,0,0,0.30);
- border-radius: 2px;
- padding: 6px 6px 6px 8px;
- margin-top: 10px;
- height: 100% !important;
-}
-.exercise-card .card-img-top {
- width: 100%;
- height: 15vw;
- object-fit: cover;
-}
-.exercise-card .btn-edit {
- position: absolute;
- bottom: 10px;
- left: 20px;
-}
-.exercise-card .btn-del {
- position: absolute;
- bottom: 10px;
- left: 50px;
-}
-.exercise-card .card-body {
- margin-bottom: 10px;
-}
-.exercise-card .card-footer {
- padding: 10px;
-}
-.exercise-row {
- height: 100% !important;
- display: flex;
- flex-wrap: wrap;
-}
-.exercise-col {
- padding: 10px;
-}
diff --git a/erpnext/public/css/leaflet/leaflet.css b/erpnext/public/css/leaflet/leaflet.css
deleted file mode 100755
index 979a8bd712..0000000000
--- a/erpnext/public/css/leaflet/leaflet.css
+++ /dev/null
@@ -1,611 +0,0 @@
-/* required styles */
-
-.leaflet-pane,
-.leaflet-tile,
-.leaflet-marker-icon,
-.leaflet-marker-shadow,
-.leaflet-tile-container,
-.leaflet-map-pane svg,
-.leaflet-map-pane canvas,
-.leaflet-zoom-box,
-.leaflet-image-layer,
-.leaflet-layer {
- position: absolute;
- left: 0;
- top: 0;
-}
-
-.leaflet-container {
- overflow: hidden;
- -ms-touch-action: none;
- touch-action: none;
-}
-
-.leaflet-tile,
-.leaflet-marker-icon,
-.leaflet-marker-shadow {
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- -webkit-user-drag: none;
-}
-
-
-/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
-
-.leaflet-safari .leaflet-tile {
- image-rendering: -webkit-optimize-contrast;
-}
-
-
-/* hack that prevents hw layers "stretching" when loading new tiles */
-
-.leaflet-safari .leaflet-tile-container {
- width: 1600px;
- height: 1600px;
- -webkit-transform-origin: 0 0;
-}
-
-.leaflet-marker-icon,
-.leaflet-marker-shadow {
- display: block;
-}
-
-
-/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
-
-
-/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
-
-.leaflet-container .leaflet-overlay-pane svg,
-.leaflet-container .leaflet-marker-pane img,
-.leaflet-container .leaflet-tile-pane img,
-.leaflet-container img.leaflet-image-layer {
- max-width: none !important;
-}
-
-.leaflet-tile {
- filter: inherit;
- visibility: hidden;
-}
-
-.leaflet-tile-loaded {
- visibility: inherit;
-}
-
-.leaflet-zoom-box {
- width: 0;
- height: 0;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
- z-index: 800;
-}
-
-
-/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
-
-.leaflet-overlay-pane svg {
- -moz-user-select: none;
-}
-
-.leaflet-pane {
- z-index: 400;
-}
-
-.leaflet-tile-pane {
- z-index: 200;
-}
-
-.leaflet-overlay-pane {
- z-index: 400;
-}
-
-.leaflet-shadow-pane {
- z-index: 500;
-}
-
-.leaflet-marker-pane {
- z-index: 600;
-}
-
-.leaflet-popup-pane {
- z-index: 700;
-}
-
-.leaflet-map-pane canvas {
- z-index: 100;
-}
-
-.leaflet-map-pane svg {
- z-index: 200;
-}
-
-.leaflet-vml-shape {
- width: 1px;
- height: 1px;
-}
-
-.lvml {
- behavior: url(#default#VML);
- display: inline-block;
- position: absolute;
-}
-
-
-/* control positioning */
-
-.leaflet-control {
- position: relative;
- z-index: 800;
- pointer-events: auto;
-}
-
-.leaflet-top,
-.leaflet-bottom {
- position: absolute;
- z-index: 1000;
- pointer-events: none;
-}
-
-.leaflet-top {
- top: 0;
-}
-
-.leaflet-right {
- right: 0;
-}
-
-.leaflet-bottom {
- bottom: 0;
-}
-
-.leaflet-left {
- left: 0;
-}
-
-.leaflet-control {
- float: left;
- clear: both;
-}
-
-.leaflet-right .leaflet-control {
- float: right;
-}
-
-.leaflet-top .leaflet-control {
- margin-top: 10px;
-}
-
-.leaflet-bottom .leaflet-control {
- margin-bottom: 10px;
-}
-
-.leaflet-left .leaflet-control {
- margin-left: 10px;
-}
-
-.leaflet-right .leaflet-control {
- margin-right: 10px;
-}
-
-
-/* zoom and fade animations */
-
-.leaflet-fade-anim .leaflet-tile {
- will-change: opacity;
-}
-
-.leaflet-fade-anim .leaflet-popup {
- opacity: 0;
- -webkit-transition: opacity 0.2s linear;
- -moz-transition: opacity 0.2s linear;
- -o-transition: opacity 0.2s linear;
- transition: opacity 0.2s linear;
-}
-
-.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
- opacity: 1;
-}
-
-.leaflet-zoom-animated {
- -webkit-transform-origin: 0 0;
- -ms-transform-origin: 0 0;
- transform-origin: 0 0;
-}
-
-.leaflet-zoom-anim .leaflet-zoom-animated {
- will-change: transform;
-}
-
-.leaflet-zoom-anim .leaflet-zoom-animated {
- -webkit-transition: -webkit-transform 0.25s cubic-bezier(0, 0, 0.25, 1);
- -moz-transition: -moz-transform 0.25s cubic-bezier(0, 0, 0.25, 1);
- -o-transition: -o-transform 0.25s cubic-bezier(0, 0, 0.25, 1);
- transition: transform 0.25s cubic-bezier(0, 0, 0.25, 1);
-}
-
-.leaflet-zoom-anim .leaflet-tile,
-.leaflet-pan-anim .leaflet-tile {
- -webkit-transition: none;
- -moz-transition: none;
- -o-transition: none;
- transition: none;
-}
-
-.leaflet-zoom-anim .leaflet-zoom-hide {
- visibility: hidden;
-}
-
-
-/* cursors */
-
-.leaflet-interactive {
- cursor: pointer;
-}
-
-.leaflet-grab {
- cursor: -webkit-grab;
- cursor: -moz-grab;
-}
-
-.leaflet-crosshair,
-.leaflet-crosshair .leaflet-interactive {
- cursor: crosshair;
-}
-
-.leaflet-popup-pane,
-.leaflet-control {
- cursor: auto;
-}
-
-.leaflet-dragging .leaflet-grab,
-.leaflet-dragging .leaflet-grab .leaflet-interactive,
-.leaflet-dragging .leaflet-marker-draggable {
- cursor: move;
- cursor: -webkit-grabbing;
- cursor: -moz-grabbing;
-}
-
-
-/* visual tweaks */
-
-.leaflet-container {
- background: #ddd;
- outline: 0;
-}
-
-.leaflet-container a {
- color: #0078A8;
-}
-
-.leaflet-container a.leaflet-active {
- outline: 2px solid orange;
-}
-
-.leaflet-zoom-box {
- border: 2px dotted #38f;
- background: rgba(255, 255, 255, 0.5);
-}
-
-
-/* general typography */
-
-.leaflet-container {
- font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
-}
-
-
-/* general toolbar styles */
-
-.leaflet-bar {
- box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
- border-radius: 4px;
-}
-
-.leaflet-bar a,
-.leaflet-bar a:hover {
- background-color: #fff;
- border-bottom: 1px solid #ccc;
- width: 26px;
- height: 26px;
- line-height: 26px;
- display: block;
- text-align: center;
- text-decoration: none;
- color: black;
-}
-
-.leaflet-bar a,
-.leaflet-control-layers-toggle {
- background-position: 50% 50%;
- background-repeat: no-repeat;
- display: block;
-}
-
-.leaflet-bar a:hover {
- background-color: #f4f4f4;
-}
-
-.leaflet-bar a:first-child {
- border-top-left-radius: 4px;
- border-top-right-radius: 4px;
-}
-
-.leaflet-bar a:last-child {
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
- border-bottom: none;
-}
-
-.leaflet-bar a.leaflet-disabled {
- cursor: default;
- background-color: #f4f4f4;
- color: #bbb;
-}
-
-.leaflet-touch .leaflet-bar a {
- width: 30px;
- height: 30px;
- line-height: 30px;
-}
-
-
-/* zoom control */
-
-.leaflet-control-zoom-in,
-.leaflet-control-zoom-out {
- font: bold 18px 'Lucida Console', Monaco, monospace;
- text-indent: 1px;
-}
-
-.leaflet-control-zoom-out {
- font-size: 20px;
-}
-
-.leaflet-touch .leaflet-control-zoom-in {
- font-size: 22px;
-}
-
-.leaflet-touch .leaflet-control-zoom-out {
- font-size: 24px;
-}
-
-
-/* layers control */
-
-.leaflet-control-layers {
- box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4);
- background: #fff;
- border-radius: 5px;
-}
-
-.leaflet-control-layers-toggle {
- background-image: url('assets/erpnext/images/leaflet/layers.png');
- width: 36px;
- height: 36px;
-}
-
-.leaflet-retina .leaflet-control-layers-toggle {
- background-image: url('assets/erpnext/images/leaflet/layers-2x.png');
- background-size: 26px 26px;
-}
-
-.leaflet-touch .leaflet-control-layers-toggle {
- width: 44px;
- height: 44px;
-}
-
-.leaflet-control-layers .leaflet-control-layers-list,
-.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
- display: none;
-}
-
-.leaflet-control-layers-expanded .leaflet-control-layers-list {
- display: block;
- position: relative;
-}
-
-.leaflet-control-layers-expanded {
- padding: 6px 10px 6px 6px;
- color: #333;
- background: #fff;
-}
-
-.leaflet-control-layers-scrollbar {
- overflow-y: scroll;
- padding-right: 5px;
-}
-
-.leaflet-control-layers-selector {
- margin-top: 2px;
- position: relative;
- top: 1px;
-}
-
-.leaflet-control-layers label {
- display: block;
-}
-
-.leaflet-control-layers-separator {
- height: 0;
- border-top: 1px solid #ddd;
- margin: 5px -10px 5px -6px;
-}
-
-
-/* attribution and scale controls */
-
-.leaflet-container .leaflet-control-attribution {
- background: #fff;
- background: rgba(255, 255, 255, 0.7);
- margin: 0;
-}
-
-.leaflet-control-attribution,
-.leaflet-control-scale-line {
- padding: 0 5px;
- color: #333;
-}
-
-.leaflet-control-attribution a {
- text-decoration: none;
-}
-
-.leaflet-control-attribution a:hover {
- text-decoration: underline;
-}
-
-.leaflet-container .leaflet-control-attribution,
-.leaflet-container .leaflet-control-scale {
- font-size: 11px;
-}
-
-.leaflet-left .leaflet-control-scale {
- margin-left: 5px;
-}
-
-.leaflet-bottom .leaflet-control-scale {
- margin-bottom: 5px;
-}
-
-.leaflet-control-scale-line {
- border: 2px solid #777;
- border-top: none;
- line-height: 1.1;
- padding: 2px 5px 1px;
- font-size: 11px;
- white-space: nowrap;
- overflow: hidden;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
- background: #fff;
- background: rgba(255, 255, 255, 0.5);
-}
-
-.leaflet-control-scale-line:not(:first-child) {
- border-top: 2px solid #777;
- border-bottom: none;
- margin-top: -2px;
-}
-
-.leaflet-control-scale-line:not(:first-child):not(:last-child) {
- border-bottom: 2px solid #777;
-}
-
-.leaflet-touch .leaflet-control-attribution,
-.leaflet-touch .leaflet-control-layers,
-.leaflet-touch .leaflet-bar {
- box-shadow: none;
-}
-
-.leaflet-touch .leaflet-control-layers,
-.leaflet-touch .leaflet-bar {
- border: 2px solid rgba(0, 0, 0, 0.2);
- background-clip: padding-box;
-}
-
-
-/* popup */
-
-.leaflet-popup {
- position: absolute;
- text-align: center;
-}
-
-.leaflet-popup-content-wrapper {
- padding: 1px;
- text-align: left;
- border-radius: 12px;
-}
-
-.leaflet-popup-content {
- margin: 13px 19px;
- line-height: 1.4;
-}
-
-.leaflet-popup-content p {
- margin: 18px 0;
-}
-
-.leaflet-popup-tip-container {
- margin: 0 auto;
- width: 40px;
- height: 20px;
- position: relative;
- overflow: hidden;
-}
-
-.leaflet-popup-tip {
- width: 17px;
- height: 17px;
- padding: 1px;
- margin: -10px auto 0;
- -webkit-transform: rotate(45deg);
- -moz-transform: rotate(45deg);
- -ms-transform: rotate(45deg);
- -o-transform: rotate(45deg);
- transform: rotate(45deg);
-}
-
-.leaflet-popup-content-wrapper,
-.leaflet-popup-tip {
- background: white;
- color: #333;
- box-shadow: 0 3px 14px rgba(0, 0, 0, 0.4);
-}
-
-.leaflet-container a.leaflet-popup-close-button {
- position: absolute;
- top: 0;
- right: 0;
- padding: 4px 4px 0 0;
- border: none;
- text-align: center;
- width: 18px;
- height: 14px;
- font: 16px/14px Tahoma, Verdana, sans-serif;
- color: #c3c3c3;
- text-decoration: none;
- font-weight: bold;
- background: transparent;
-}
-
-.leaflet-container a.leaflet-popup-close-button:hover {
- color: #999;
-}
-
-.leaflet-popup-scrolled {
- overflow: auto;
- border-bottom: 1px solid #ddd;
- border-top: 1px solid #ddd;
-}
-
-.leaflet-oldie .leaflet-popup-content-wrapper {
- zoom: 1;
-}
-
-.leaflet-oldie .leaflet-popup-tip {
- width: 24px;
- margin: 0 auto;
- -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
- filter: progid: DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
-}
-
-.leaflet-oldie .leaflet-popup-tip-container {
- margin-top: -1px;
-}
-
-.leaflet-oldie .leaflet-control-zoom,
-.leaflet-oldie .leaflet-control-layers,
-.leaflet-oldie .leaflet-popup-content-wrapper,
-.leaflet-oldie .leaflet-popup-tip {
- border: 1px solid #999;
-}
-
-
-/* div icon */
-
-.leaflet-div-icon {
- background: #fff;
- border: 1px solid #666;
-}
\ No newline at end of file
diff --git a/erpnext/public/css/leaflet/leaflet.draw.css b/erpnext/public/css/leaflet/leaflet.draw.css
deleted file mode 100755
index 6fb7db0e64..0000000000
--- a/erpnext/public/css/leaflet/leaflet.draw.css
+++ /dev/null
@@ -1,316 +0,0 @@
-/* ================================================================== */
-
-
-/* Toolbars
-/* ================================================================== */
-
-.leaflet-draw-section {
- position: relative;
-}
-
-.leaflet-draw-toolbar {
- margin-top: 12px;
-}
-
-.leaflet-draw-toolbar-top {
- margin-top: 0;
-}
-
-.leaflet-draw-toolbar-notop a:first-child {
- border-top-right-radius: 0;
-}
-
-.leaflet-draw-toolbar-nobottom a:last-child {
- border-bottom-right-radius: 0;
-}
-
-.leaflet-draw-toolbar a {
- background-image: url('assets/erpnext/images/leaflet/spritesheet.png');
- background-repeat: no-repeat;
-}
-
-.leaflet-retina .leaflet-draw-toolbar a {
- background-image: url('assets/erpnext/images/leaflet/spritesheet-2x.png');
- background-size: 270px 30px;
-}
-
-.leaflet-draw a {
- display: block;
- text-align: center;
- text-decoration: none;
-}
-
-
-/* ================================================================== */
-
-
-/* Toolbar actions menu
-/* ================================================================== */
-
-.leaflet-draw-actions {
- display: none;
- list-style: none;
- margin: 0;
- padding: 0;
- position: absolute;
- left: 26px;
- /* leaflet-draw-toolbar.left + leaflet-draw-toolbar.width */
- top: 0;
- white-space: nowrap;
-}
-
-.leaflet-right .leaflet-draw-actions {
- right: 26px;
- left: auto;
-}
-
-.leaflet-draw-actions li {
- display: inline-block;
-}
-
-.leaflet-draw-actions li:first-child a {
- border-left: none;
-}
-
-.leaflet-draw-actions li:last-child a {
- -webkit-border-radius: 0 4px 4px 0;
- border-radius: 0 4px 4px 0;
-}
-
-.leaflet-right .leaflet-draw-actions li:last-child a {
- -webkit-border-radius: 0;
- border-radius: 0;
-}
-
-.leaflet-right .leaflet-draw-actions li:first-child a {
- -webkit-border-radius: 4px 0 0 4px;
- border-radius: 4px 0 0 4px;
-}
-
-.leaflet-draw-actions a {
- background-color: #919187;
- border-left: 1px solid #AAA;
- color: #FFF;
- font: 11px/19px "Helvetica Neue", Arial, Helvetica, sans-serif;
- line-height: 28px;
- text-decoration: none;
- padding-left: 10px;
- padding-right: 10px;
- height: 28px;
-}
-
-.leaflet-draw-actions-bottom {
- margin-top: 0;
-}
-
-.leaflet-draw-actions-top {
- margin-top: 1px;
-}
-
-.leaflet-draw-actions-top a,
-.leaflet-draw-actions-bottom a {
- height: 27px;
- line-height: 27px;
-}
-
-.leaflet-draw-actions a:hover {
- background-color: #A0A098;
-}
-
-.leaflet-draw-actions-top.leaflet-draw-actions-bottom a {
- height: 26px;
- line-height: 26px;
-}
-
-
-/* ================================================================== */
-
-
-/* Draw toolbar
-/* ================================================================== */
-
-.leaflet-draw-toolbar .leaflet-draw-draw-polyline {
- background-position: -2px -2px;
-}
-
-.leaflet-draw-toolbar .leaflet-draw-draw-polygon {
- background-position: -31px -2px;
-}
-
-.leaflet-draw-toolbar .leaflet-draw-draw-rectangle {
- background-position: -62px -2px;
-}
-
-.leaflet-draw-toolbar .leaflet-draw-draw-circle {
- background-position: -92px -2px;
-}
-
-.leaflet-draw-toolbar .leaflet-draw-draw-marker {
- background-position: -122px -2px;
-}
-
-
-/* ================================================================== */
-
-
-/* Edit toolbar
-/* ================================================================== */
-
-.leaflet-draw-toolbar .leaflet-draw-edit-edit {
- background-position: -152px -2px;
-}
-
-.leaflet-draw-toolbar .leaflet-draw-edit-remove {
- background-position: -182px -2px;
-}
-
-.leaflet-draw-toolbar .leaflet-draw-edit-edit.leaflet-disabled {
- background-position: -212px -2px;
-}
-
-.leaflet-draw-toolbar .leaflet-draw-edit-remove.leaflet-disabled {
- background-position: -242px -2px;
-}
-
-
-/* ================================================================== */
-
-
-/* Drawing styles
-/* ================================================================== */
-
-.leaflet-mouse-marker {
- background-color: #fff;
- cursor: crosshair;
-}
-
-.leaflet-draw-tooltip {
- background: rgb(54, 54, 54);
- background: rgba(0, 0, 0, 0.5);
- border: 1px solid transparent;
- -webkit-border-radius: 4px;
- border-radius: 4px;
- color: #fff;
- font: 12px/18px "Helvetica Neue", Arial, Helvetica, sans-serif;
- margin-left: 20px;
- margin-top: -21px;
- padding: 4px 8px;
- position: absolute;
- visibility: hidden;
- white-space: nowrap;
- z-index: 6;
-}
-
-.leaflet-draw-tooltip:before {
- border-right: 6px solid black;
- border-right-color: rgba(0, 0, 0, 0.5);
- border-top: 6px solid transparent;
- border-bottom: 6px solid transparent;
- content: "";
- position: absolute;
- top: 7px;
- left: -7px;
-}
-
-.leaflet-error-draw-tooltip {
- background-color: #F2DEDE;
- border: 1px solid #E6B6BD;
- color: #B94A48;
-}
-
-.leaflet-error-draw-tooltip:before {
- border-right-color: #E6B6BD;
-}
-
-.leaflet-draw-tooltip-single {
- margin-top: -12px
-}
-
-.leaflet-draw-tooltip-subtext {
- color: #f8d5e4;
-}
-
-.leaflet-draw-guide-dash {
- font-size: 1%;
- opacity: 0.6;
- position: absolute;
- width: 5px;
- height: 5px;
-}
-
-
-/* ================================================================== */
-
-
-/* Edit styles
-/* ================================================================== */
-
-.leaflet-edit-marker-selected {
- background: rgba(254, 87, 161, 0.1);
- border: 4px dashed rgba(254, 87, 161, 0.6);
- -webkit-border-radius: 4px;
- border-radius: 4px;
-}
-
-.leaflet-edit-move {
- cursor: move;
-}
-
-.leaflet-edit-resize {
- cursor: pointer;
-}
-
-
-/* ================================================================== */
-
-
-/* Old IE styles
-/* ================================================================== */
-
-.leaflet-oldie .leaflet-draw-toolbar {
- border: 3px solid #999;
-}
-
-.leaflet-oldie .leaflet-draw-toolbar a {
- background-color: #eee;
-}
-
-.leaflet-oldie .leaflet-draw-toolbar a:hover {
- background-color: #fff;
-}
-
-.leaflet-oldie .leaflet-draw-actions {
- left: 32px;
- margin-top: 3px;
-}
-
-.leaflet-oldie .leaflet-draw-actions li {
- display: inline;
- zoom: 1;
-}
-
-.leaflet-oldie .leaflet-edit-marker-selected {
- border: 4px dashed #fe93c2;
-}
-
-.leaflet-oldie .leaflet-draw-actions a {
- background-color: #999;
-}
-
-.leaflet-oldie .leaflet-draw-actions a:hover {
- background-color: #a5a5a5;
-}
-
-.leaflet-oldie .leaflet-draw-actions-top a {
- margin-top: 1px;
-}
-
-.leaflet-oldie .leaflet-draw-actions-bottom a {
- height: 28px;
- line-height: 28px;
-}
-
-.leaflet-oldie .leaflet-draw-actions-top.leaflet-draw-actions-bottom a {
- height: 27px;
- line-height: 27px;
-}
\ No newline at end of file
diff --git a/erpnext/public/less/hub.less b/erpnext/public/less/hub.less
deleted file mode 100644
index 29deada8a4..0000000000
--- a/erpnext/public/less/hub.less
+++ /dev/null
@@ -1,375 +0,0 @@
-@import "variables.less";
-@import (reference) "desk.less";
-
-body[data-route*="marketplace"] {
- .layout-side-section {
- padding-top: 25px;
- padding-left: 5px;
- padding-right: 25px;
- }
-
- [data-route], [data-action] {
- cursor: pointer;
- }
-
- .layout-main-section {
- border: none;
- font-size: @text-medium;
- padding-top: 25px;
-
- @media (max-width: @screen-xs) {
- padding-left: 20px;
- padding-right: 20px;
- }
- }
-
- input, textarea {
- font-size: @text-medium;
- }
-
- .hub-image {
- height: 200px;
- }
-
- .hub-image-loading, .hub-image-broken {
- content: " ";
- position: absolute;
- left: 0;
- height: 100%;
- width: 100%;
- background-color: var(--bg-light-gray);
- display: flex;
- align-items: center;
- justify-content: center;
-
- span {
- font-size: 32px;
- color: @text-extra-muted;
- }
- }
-
- .progress-bar {
- background-color: #89da28;
- }
-
- .subpage-title.flex {
- align-items: flex-start;
- justify-content: space-between;
- }
-
- .hub-card {
- margin-bottom: 25px;
- position: relative;
- border: 1px solid @border-color;
- border-radius: 4px;
- overflow: hidden;
-
- &:hover .hub-card-overlay {
- display: block;
- }
- }
-
- .hub-card.is-local {
- &.active {
- .hub-card-header {
- background-color: #f4ffe5;
- }
-
- .octicon-check {
- display: inline;
- }
- }
-
- .octicon-check {
- display: none;
- position: absolute;
- font-size: 20px;
- right: 15px;
- top: 50%;
- transform: translateY(-50%);
- }
- }
-
- .hub-card-header {
- position: relative;
- padding: 12px 15px;
- height: 60px;
- border-bottom: 1px solid @border-color;
- }
-
- .hub-card-body {
- position: relative;
- height: 200px;
- }
-
- .hub-card-overlay {
- display: none;
- position: absolute;
- top: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.05);
- }
-
- .hub-card-overlay-body {
- position: relative;
- height: 100%;
- }
-
- .hub-card-overlay-button {
- position: absolute;
- right: 15px;
- bottom: 15px;
- }
-
- .hub-card-image {
- position: relative;
- width: 100%;
- height: 100%;
- object-fit: contain;
- }
-
- .hub-search-container {
- margin-bottom: 20px;
-
- input {
- height: 32px;
- }
- }
-
- .hub-sidebar {
- padding-top: 25px;
- padding-right: 15px;
- }
-
- .hub-sidebar-group {
- margin-bottom: 10px;
- }
-
- .hub-sidebar-item {
- padding: 5px 8px;
- margin-bottom: 3px;
- border-radius: 4px;
- border: 1px solid transparent;
-
- &.active, &:hover:not(.is-title) {
- border-color: @border-color;
- }
- }
-
- .hub-item-image {
- position: relative;
- border: 1px solid @border-color;
- border-radius: 4px;
- overflow: hidden;
- height: 200px;
- width: 200px;
- display: flex;
- align-items: center;
- }
-
- .hub-item-skeleton-image {
- border-radius: 4px;
- background-color: @light-bg;
- overflow: hidden;
- height: 200px;
- width: 200px;
- }
-
- .hub-skeleton {
- background-color: @light-bg;
- color: @light-bg;
- max-width: 500px;
- }
-
- .hub-item-seller img {
- width: 50px;
- height: 50px;
- border-radius: 4px;
- border: 1px solid @border-color;
- }
-
- .register-title {
- font-size: @text-regular;
- }
-
- .register-form {
- border: 1px solid @border-color;
- border-radius: 4px;
- padding: 15px 25px;
- }
-
- .publish-area.filled {
- .empty-items-container {
- display: none;
- }
- }
-
- .publish-area.empty {
- .hub-items-container {
- display: none;
- }
- }
-
- .publish-area-head {
- display: flex;
- justify-content: space-between;
- margin-bottom: 20px;
- }
-
- .hub-list-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- border: 1px solid @border-color;
- margin-bottom: -1px;
- overflow: hidden;
- }
-
- .hub-list-item:first-child {
- border-top-left-radius: 4px;
- border-top-right-radius: 4px;
- }
- .hub-list-item:last-child {
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px;
- }
-
- .hub-list-left {
- display: flex;
- align-items: center;
- max-width: 90%;
- }
-
- .hub-list-right {
- padding-right: 15px;
- }
-
- .hub-list-image {
- position: relative;
- width: 58px;
- height: 58px;
- border-right: 1px solid @border-color;
-
- &::after {
- font-size: 12px;
- }
- }
-
- .hub-list-body {
- padding: 12px 15px;
- }
-
- .hub-list-title {
- font-weight: bold;
- }
-
- .hub-list-subtitle {
- color: @text-muted;
- }
-
- .selling-item-message-card {
- max-width: 500px;
- margin-bottom: 15px;
- border-radius: 3px;
- border: 1px solid @border-color;
- .selling-item-detail {
- overflow: auto;
- .item-image {
- float: left;
- height: 80px;
- width: 80px;
- object-fit: contain;
- margin: 5px;
- }
- .item-name {
- margin-left: 10px;
- }
- }
- .received-message-container {
- clear: left;
- background-color: @light-bg;
- .received-message {
- border-top: 1px solid @border-color;
- padding: 10px;
- }
- .frappe-timestamp {
- float: right;
- }
- }
- }
-
- .form-container {
- .frappe-control {
- max-width: 100% !important;
- }
- }
-
- .form-message {
- padding-top: 0;
- padding-bottom: 0;
- border-bottom: none;
- }
-
- .hub-items-container {
- .hub-items-header {
- justify-content: space-between;
- align-items: baseline;
- }
- }
-
- .hub-item-container {
- overflow: hidden;
- }
-
- .hub-item-review-container {
- margin-top: calc(30vh);
- }
-
- .hub-item-dropdown {
- margin-top: 20px;
- }
-
- /* messages page */
-
- .message-list-item {
- display: flex;
- align-items: center;
- padding: 8px 12px;
-
- &:not(.active) {
- filter: grayscale(1);
- color: @text-muted;
- }
-
- &:hover {
- background-color: @light-bg;
- }
-
- .list-item-left {
- width: 30px;
- border-radius: 4px;
- overflow: hidden;
- margin-right: 15px;
- }
-
- .list-item-body {
- font-weight: bold;
- padding-bottom: 1px;
- }
- }
-
- .message-container {
- display: flex;
- flex-direction: column;
- border: 1px solid @border-color;
- border-radius: 3px;
- height: calc(100vh - 300px);
- justify-content: space-between;
- padding: 15px;
- }
-
- .message-list {
- overflow: scroll;
- }
-}
diff --git a/erpnext/public/less/pos.less b/erpnext/public/less/pos.less
deleted file mode 100644
index b081ed4414..0000000000
--- a/erpnext/public/less/pos.less
+++ /dev/null
@@ -1,229 +0,0 @@
-@import "../../../../frappe/frappe/public/less/variables.less";
-
-[data-route="point-of-sale"] {
- .layout-main-section-wrapper {
- margin-bottom: 0;
- }
-
- .pos-items-wrapper {
- max-height: ~"calc(100vh - 210px)";
- }
-}
-
-.pos {
- // display: flex;
- padding: 15px;
-}
-
-.list-item {
- min-height: 40px;
- height: auto;
-}
-
-.cart-container {
- padding: 0 15px;
- // flex: 2;
- display: inline-block;
- width: 39%;
- vertical-align: top;
-}
-
-.item-container {
- padding: 0 15px;
- // flex: 3;
- display: inline-block;
- width: 60%;
- vertical-align: top;
-}
-
-.search-field {
- width: 60%;
-
- input::placeholder {
- font-size: @text-medium;
- }
-}
-
-.item-group-field {
- width: 40%;
- margin-left: 15px;
-}
-
-.cart-wrapper {
- margin-bottom: 12px;
- .list-item__content:not(:first-child) {
- justify-content: flex-end;
- }
-
- .list-item--head .list-item__content:nth-child(2) {
- flex: 1.5;
- }
-}
-
-.cart-items {
- height: 150px;
- overflow: auto;
-
- .list-item.current-item {
- background-color: @light-yellow;
- }
-
- .list-item.current-item.qty input {
- border: 1px solid @brand-primary;
- font-weight: bold;
- }
-
- .list-item.current-item.disc .discount {
- font-weight: bold;
- }
-
- .list-item.current-item.rate .rate {
- font-weight: bold;
- }
-
- .list-item .quantity {
- flex: 1.5;
- }
-
- input {
- text-align: right;
- height: 22px;
- font-size: @text-medium;
- }
-}
-
-.fields {
- display: flex;
-}
-
-.pos-items-wrapper {
- max-height: 480px;
- overflow-y: auto;
-}
-
-.pos-items {
- overflow: hidden;
-}
-
-.pos-item-wrapper {
- display: flex;
- flex-direction: column;
- position: relative;
- width: 25%;
-}
-
-.image-view-container {
- display: block;
-}
-
-.image-view-container .image-field {
- height: auto;
-}
-
-.empty-state {
- height: 100%;
- position: relative;
-
- span {
- position: absolute;
- color: @text-muted;
- font-size: @text-medium;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
-}
-
-@keyframes yellow-fade {
- 0% {background-color: @light-yellow;}
- 100% {background-color: transparent;}
-}
-
-.highlight {
- animation: yellow-fade 1s ease-in 1;
-}
-
-input[type=number]::-webkit-inner-spin-button,
-input[type=number]::-webkit-outer-spin-button {
- -webkit-appearance: none;
- margin: 0;
-}
-
-// number pad
-
-.number-pad {
- border-collapse: collapse;
- cursor: pointer;
- display: table;
-}
-.num-row {
- display: table-row;
-}
-.num-col {
- display: table-cell;
- border: 1px solid @border-color;
-
- & > div {
- width: 50px;
- height: 50px;
- text-align: center;
- line-height: 50px;
- }
-
- &.active {
- background-color: @light-yellow;
- }
-
- &.brand-primary {
- background-color: @brand-primary;
- color: #ffffff;
- }
-}
-
-// taxes, totals and discount area
-.discount-amount {
- .discount-inputs {
- display: flex;
- flex-direction: column;
- padding: 15px 0;
- }
-
- input:first-child {
- margin-bottom: 10px;
- }
-}
-
-.taxes-and-totals {
- border-top: 1px solid @border-color;
-
- .taxes {
- display: flex;
- flex-direction: column;
- padding: 15px 0;
- align-items: flex-end;
-
- & > div:first-child {
- margin-bottom: 10px;
- }
- }
-}
-
-.grand-total {
- border-top: 1px solid @border-color;
-
- .list-item {
- height: 60px;
- }
-
- .grand-total-value {
- font-size: 18px;
- }
-}
-
-.rounded-total-value {
- font-size: 18px;
-}
-
-.quantity-total {
- font-size: 18px;
-}
\ No newline at end of file
diff --git a/erpnext/public/less/products.less b/erpnext/public/less/products.less
deleted file mode 100644
index 5e744ceac5..0000000000
--- a/erpnext/public/less/products.less
+++ /dev/null
@@ -1,71 +0,0 @@
-@import "variables.less";
-
-.products-list .product-image {
- display: inline-block;
- width: 160px;
- height: 160px;
- object-fit: contain;
- margin-right: 1rem;
-}
-
-.product-image.no-image {
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 3rem;
- color: var(--gray);
- background: var(--light);
-}
-
-.product-image a {
- text-decoration: none;
-}
-
-.filter-options {
- margin-left: -5px;
- padding-left: 5px;
- max-height: 300px;
- overflow: auto;
-}
-
-.item-slideshow-image {
- height: 3rem;
- width: 3rem;
- object-fit: contain;
- padding: 0.5rem;
- border: 1px solid @border-color;
- border-radius: 4px;
- cursor: pointer;
-
- &:hover, &.active {
- border-color: var(--primary);
- }
-}
-
-.address-card {
- cursor: pointer;
- position: relative;
-
- .check {
- display: none;
- }
-
- &.active {
- border-color: var(--primary);
-
- .check {
- display: inline-flex;
- }
- }
-}
-
-.check {
- display: inline-flex;
- padding: 0.25rem;
- background: var(--primary);
- color: white;
- border-radius: 50%;
- font-size: 12px;
- width: 24px;
- height: 24px;
-}
\ No newline at end of file
diff --git a/erpnext/public/less/website.less b/erpnext/public/less/website.less
deleted file mode 100644
index ac878de105..0000000000
--- a/erpnext/public/less/website.less
+++ /dev/null
@@ -1,388 +0,0 @@
-@import "variables.less";
-
-.web-long-description {
- font-size: 18px;
- line-height: 200%;
-}
-
-.web-page-content {
- margin-bottom: 30px;
-}
-
-.item-stock {
- margin-bottom: 10px !important;
-}
-
-.product-link {
- display: block;
- text-align: center;
-}
-
-
-.product-image img {
- max-height: 500px;
- margin: 0 auto;
-}
-
-@media (max-width: 767px) {
- .product-image {
- height: 0px;
- padding: 0px 0px 100%;
- overflow: hidden;
- }
-}
-
-.product-image-square {
- width: 100%;
- height: 0;
- padding: 50% 0px;
- background-size: cover;
- background-repeat: no-repeat;
- background-position: center top;
-}
-
-.product-image.missing-image {
- .product-image-square;
- position: relative;
- background-color: @light-border-color;
-}
-
-.product-image.missing-image .octicon {
- font-size: 32px;
- color: @border-color;
-}
-
-.product-search {
- margin-bottom: 15px;
-}
-
-
-@media (max-width: 767px) {
- .product-search {
- width: 100%;
- }
-}
-
-.borderless td, .borderless th {
- border-bottom: 1px solid @light-border-color;
- padding-left:0px !important;
- line-height: 1.8em !important;
-}
-
-.item-desc {
- border-top: 2px solid @light-border-color;
- padding-top:10px;
-}
-
-.featured-products {
- border-top: 1px solid @light-border-color;
-}
-
-.transaction-list-item {
- .indicator {
- font-weight: inherit;
- color: @text-muted;
- }
-
- .transaction-time {
- margin-top: 5px;
- }
-
-}
-
-// order.html
-.transaction-subheading {
- .indicator {
- font-weight: inherit;
- color: @text-muted;
- }
-}
-
-.order-container {
- margin: 50px 0px;
-
- .order-item-header .h6 {
- padding: 7px 15px;
- }
-
- .order-items {
- margin: 30px 0px 0px;
- }
-
- .order-item-table {
- margin: 0px -15px;
- }
-
- .order-item-header {
- border-bottom: 1px solid #d1d8dd;
- }
-
- .order-image-col {
- padding-right: 0px;
- }
-
- .order-image {
- max-width: 55px;
- max-height: 55px;
- margin-top: -5px;
- }
-
- .order-taxes {
- margin-top: 30px;
-
- .row {
- margin-top: 15px;
- }
- }
-
- .tax-grand-total-row {
- padding-top: 15px;
- padding-bottom: 30px;
- }
-
- .tax-grand-total {
- display: inline-block;
- font-size: 16px;
- font-weight: bold;
- margin-top: 5px;
- }
-}
-
-.cart-container {
- margin: 50px 0px;
-
- .checkout {
- margin-bottom:15px;
- }
-
- .cart-item-header .h6 {
- padding: 7px 15px;
- }
-
- .cart-items {
- margin: 30px 0px 0px;
- }
-
- .cart-item-table {
- margin: 0px -15px;
- }
-
- .cart-item-header {
- border-bottom: 1px solid #d1d8dd;
- }
-
- .cart-image-col {
- padding-right: 0px;
- }
-
- .cart-image {
- max-width: 55px;
- max-height: 55px;
- margin-top: -5px;
- }
-
- .cart-taxes {
- margin-top: 30px;
-
- .row {
- margin-top: 15px;
- }
- }
-
- .tax-grand-total-row {
- border-top: 1px solid @border-color;
- padding-top: 15px;
- }
-
- .cart-addresses {
- margin-top: 50px;
- }
-}
-
-.cart-items-dropdown .cart-dropdown,
-.item_name_dropdown {
- display: none;
-
-}
-
-.cart-dropdown-container {
- width: 400px;
- padding: 15px;
-
- .item-price {
- display: block !important;
- padding-bottom: 10px;
- }
-
- .cart-item-header {
- border-bottom: 1px solid #d1d8dd;
- }
-
- .cart-items-dropdown {
- max-height: 350px;
- }
-
- .cart-items-dropdown .cart-dropdown {
- display:block;
- margin-top:15px;
- }
-
- .item_name_dropdown {
- display:block;
- }
-
- .item-description,
- .cart-items .checkout,
- .item_name_and_description {
- display: none;
- }
-
- .checkout-btn {
- padding-bottom:25px;
- }
- .col-name-description {
- margin-bottom:8px;
- }
-}
-
-// .number-spinner {
-// width:100px;
-// margin-top:5px;
-// }
-
-.cart-btn {
- border-color: #ccc;
-}
-.cart-qty {
- text-align:center;
-}
-
-.product-list-link {
- .row {
- border-bottom: 1px solid @light-border-color;
- }
-
- .row:hover {
- background-color: @light-bg;
- }
-
- .row > div {
- padding-top: 15px;
- padding-bottom: 15px;
- }
-}
-
-.product-list-link:first-child .row {
- border-top: 1px solid @light-border-color;
-}
-
-.item-group-nav-buttons {
- margin-top: 15px;
-}
-
-.footer-subscribe {
- .btn-default {
- background-color: transparent;
- border: 1px solid @border-color;
- }
-}
-
-@media (min-width: 992px) {
- .footer-subscribe {
- max-width: 350px;
- }
-}
-
-.item-group-content {
- margin-top: 30px;
-}
-
-.item-group-slideshow {
- margin-bottom: 1rem;
-}
-
-.product-image-img {
- border: 1px solid @light-border-color;
- border-radius: 3px;
-}
-
-.product-text {
- word-wrap: break-word;
- height: 75px;
- display: block; /* Fallback for non-webkit */
- display: -webkit-box;
- max-width: 100%;
- margin: 0 auto;
- -webkit-line-clamp: 3;
- -webkit-box-orient: vertical;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.product-image-wrapper {
- padding-bottom: 40px;
-}
-
-.duration-bar {
- display: inline-block;
- color: white;
- background: #8FD288;
- padding: 3px;
-}
-
-.duration-invisible {
- visibility: hidden;
-}
-
-.duration-value {
- float: right;
-}
-
-.bar-outer-text {
- color: #8FD288;
- background: none;
- float: none;
- border: none;
-}
-
-.bom-spec {
- margin-bottom: 20px;
-}
-
-.modal-title {
- margin-top: 5px;
-}
-
-.modal-header {
- padding: 10px 15px;
-}
-// For Item Alternate Image
-.item-alternative-image {
- padding: 5px;
- margin-bottom: 5px;
-
- &:hover {
- border-color: @brand-primary;
- }
-}
-
-.item-slideshow-image {
- height: 3rem;
- width: 3rem;
- object-fit: contain;
- padding: 0.5rem;
- border: 1px solid @border-color;
- border-radius: 4px;
- cursor: pointer;
-
- &:hover, &.active {
- border-color: @brand-primary;
- }
-}
-
-.section-products {
- .card-img-top {
- max-height: 300px;
- object-fit: contain;
- }
-}
\ No newline at end of file
diff --git a/erpnext/public/less/email.less b/erpnext/public/scss/email.bundle.scss
similarity index 60%
rename from erpnext/public/less/email.less
rename to erpnext/public/scss/email.bundle.scss
index 4077c4940d..3c0b918dae 100644
--- a/erpnext/public/less/email.less
+++ b/erpnext/public/scss/email.bundle.scss
@@ -1,14 +1,14 @@
-@import "../../../../frappe/frappe/public/less/variables.less";
+@import "frappe/public/scss/desk/variables";
.panel-header {
- background-color: @light-bg;
- border: 1px solid @border-color;
+ background-color: var(--bg-color);
+ border: 1px solid $border-color;
border-radius: 3px 3px 0 0;
}
.panel-body {
background-color: #fff;
- border: 1px solid @border-color;
+ border: 1px solid $border-color;
border-top: none;
border-radius: 0 0 3px 3px;
overflow-wrap: break-word;
@@ -22,11 +22,11 @@
}
.sender-avatar-placeholder {
- .sender-avatar;
+ @extend .sender-avatar;
line-height: 24px;
text-align: center;
- color: @border-color;
- border: 1px solid @border-color;
+ color: $border-color;
+ border: 1px solid $border-color;
background-color: #fff;
-}
\ No newline at end of file
+}
diff --git a/erpnext/public/scss/erpnext-web.bundle.scss b/erpnext/public/scss/erpnext-web.bundle.scss
new file mode 100644
index 0000000000..6ef1892a3d
--- /dev/null
+++ b/erpnext/public/scss/erpnext-web.bundle.scss
@@ -0,0 +1,2 @@
+@import "./shopping_cart";
+@import "./website";
diff --git a/erpnext/public/scss/erpnext.bundle.scss b/erpnext/public/scss/erpnext.bundle.scss
new file mode 100644
index 0000000000..d3313c7cee
--- /dev/null
+++ b/erpnext/public/scss/erpnext.bundle.scss
@@ -0,0 +1,3 @@
+@import "./erpnext";
+@import "./call_popup";
+@import "./point-of-sale";
diff --git a/erpnext/public/less/erpnext.less b/erpnext/public/scss/erpnext.scss
similarity index 82%
rename from erpnext/public/less/erpnext.less
rename to erpnext/public/scss/erpnext.scss
index 4076ebec1f..0e6186138f 100644
--- a/erpnext/public/less/erpnext.less
+++ b/erpnext/public/scss/erpnext.scss
@@ -1,4 +1,4 @@
-@import "variables.less";
+@import "frappe/public/scss/desk/variables";
.erpnext-footer {
margin: 11px auto;
@@ -141,7 +141,7 @@ body[data-route="pos"] {
}
.pos-payment-row {
- border-bottom:1px solid @border-color;
+ border-bottom:1px solid $border-color;
margin: 2px 0px 5px 0px;
height: 60px;
margin-top: 0px;
@@ -149,12 +149,12 @@ body[data-route="pos"] {
}
.pos-payment-row:hover, .pos-keyboard-key:hover{
- background-color: @light-bg;
+ background-color: var(--bg-color);
cursor: pointer;
}
.pos-keyboard-key, .delete-btn {
- border: 1px solid @border-color;
+ border: 1px solid $border-color;
height:85px;
width:85px;
margin:10px 10px;
@@ -165,7 +165,7 @@ body[data-route="pos"] {
}
.numeric-keypad {
- border: 1px solid @border-color;
+ border: 1px solid $border-color;
height:69px;
width:69px;
font-size:20px;
@@ -192,13 +192,13 @@ body[data-route="pos"] {
background-color: #fff;
margin-left:-4px;
- @media (max-width: @screen-md) {
+ @media (max-width: map-get($grid-breakpoints, "xl")) {
height: 45px;
width: 45px;
font-size: 14px;
}
- @media (max-width: @screen-sm) {
+ @media (max-width: map-get($grid-breakpoints, "lg")) {
height: 40px;
width: 40px;
}
@@ -209,21 +209,21 @@ body[data-route="pos"] {
& > .row > button {
border: none;
- border-right: 1px solid @border-color;
- border-bottom: 1px solid @border-color;
+ border-right: 1px solid $border-color;
+ border-bottom: 1px solid $border-color;
&:first-child {
- border-left: 1px solid @border-color;
+ border-left: 1px solid $border-color;
}
}
& > .row:first-child > button {
- border-top: 1px solid @border-color;
+ border-top: 1px solid $border-color;
}
}
.pos-pay {
- background-color: @brand-primary;
+ background-color: var(--primary);
border: none;
}
@@ -236,13 +236,13 @@ body[data-route="pos"] {
}
.list-row-head.pos-invoice-list {
- border-top: 1px solid @border-color;
+ border-top: 1px solid $border-color;
}
.modal-dialog {
width: 750px;
- @media (max-width: @screen-xs) {
+ @media (max-width: map-get($grid-breakpoints, 'md')) {
width: auto;
.modal-content {
@@ -251,7 +251,7 @@ body[data-route="pos"] {
}
}
- @media (max-width: @screen-xs) {
+ @media (max-width: map-get($grid-breakpoints, 'md')) {
.amount-row h3 {
font-size: 15px;
}
@@ -271,7 +271,7 @@ body[data-route="pos"] {
}
.selected-payment-mode {
- background-color: @light-bg;
+ background-color: var(--bg-color);
cursor: pointer;
}
@@ -291,7 +291,7 @@ body[data-route="pos"] {
padding: 9px 15px;
font-size: 12px;
margin: 0px;
- border-bottom: 1px solid @border-color;
+ border-bottom: 1px solid $border-color;
.cell {
display: table-cell;
@@ -313,17 +313,17 @@ body[data-route="pos"] {
.pos-bill-header {
background-color: #f5f7fa;
- border: 1px solid @border-color;
+ border: 1px solid $border-color;
padding: 13px 15px;
}
.pos-list-row.active {
- background-color: @light-yellow;
+ background-color: var(--fg-hover-color);
}
.totals-area {
- border-right: 1px solid @border-color;
- border-left: 1px solid @border-color;
+ border-right: 1px solid $border-color;
+ border-left: 1px solid $border-color;
margin-bottom: 15px;
}
@@ -332,12 +332,12 @@ body[data-route="pos"] {
}
.item-cart-items {
- height: ~"calc(100vh - 526px)";
+ height: calc(100vh - 526px);
overflow: auto;
- border: 1px solid @border-color;
+ border: 1px solid $border-color;
border-top: none;
- @media (max-width: @screen-xs) {
+ @media (max-width: map-get($grid-breakpoints, 'md')) {
height: 30vh;
}
}
@@ -359,12 +359,12 @@ body[data-route="pos"] {
}
.item-list {
- border: 1px solid @border-color;
+ border: 1px solid $border-color;
border-top: none;
- max-height: ~"calc(100vh - 190px)";
+ max-height: calc(100vh - 190px);
overflow: auto;
- @media (max-width: @screen-xs) {
+ @media (max-width: map-get($grid-breakpoints, 'md')) {
max-height: initial;
}
@@ -402,7 +402,7 @@ body[data-route="pos"] {
&> .pos-list-row {
border: none;
- @media (max-width: @screen-md) {
+ @media (max-width: map-get($grid-breakpoints, 'xl')) {
padding: 5px 15px;
}
}
@@ -420,7 +420,7 @@ body[data-route="pos"] {
justify-content: center;
align-items: center;
cursor: pointer;
- background-color: @light-bg;
+ background-color: var(--bg-color);
min-height: 200px;
}
@@ -428,7 +428,7 @@ body[data-route="pos"] {
cursor: pointer;
}
- @media (max-width: @screen-xs) {
+ @media (max-width: map-get($grid-breakpoints, 'md')) {
.page-actions {
max-width: 110px;
}
@@ -491,4 +491,4 @@ body[data-route="pos"] {
.exercise-col {
padding: 10px;
-}
\ No newline at end of file
+}
From 464d838447fe4876df25d2ee328fa6d655ce4d6b Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Fri, 7 May 2021 14:53:42 +0530
Subject: [PATCH 028/262] fix: Update bundle paths
---
.../bank_reconciliation_tool.js | 2 +-
.../bank_statement_import/bank_statement_import.js | 2 +-
erpnext/hooks.py | 9 +++++----
erpnext/public/js/hub/hub_factory.js | 6 +-----
erpnext/selling/page/point_of_sale/point_of_sale.js | 4 ++--
erpnext/stock/doctype/item/item.js | 2 +-
erpnext/stock/page/stock_balance/stock_balance.js | 2 +-
.../warehouse_capacity_summary.js | 4 ++--
erpnext/templates/generators/item/item.html | 10 ++++------
erpnext/templates/pages/cart.html | 8 +++-----
10 files changed, 21 insertions(+), 28 deletions(-)
diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
index 10f660a140..f2c3dea116 100644
--- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
+++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js
@@ -15,7 +15,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
refresh: function (frm) {
- frappe.require("assets/js/bank-reconciliation-tool.min.js", () =>
+ frappe.require("bank-reconciliation-tool.bundle.js", () =>
frm.trigger("make_reconciliation_tool")
);
frm.upload_statement_button = frm.page.set_secondary_action(
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
index ad4ff9ee60..2b6aeee1bc 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
@@ -319,7 +319,7 @@ frappe.ui.form.on("Bank Statement Import", {
return;
}
- frappe.require("/assets/js/data_import_tools.min.js", () => {
+ frappe.require("data_import_tools.bundle.js", () => {
frm.import_preview = new frappe.data_import.ImportPreview({
wrapper: frm.get_field("import_preview").$wrapper,
doctype: frm.doc.reference_doctype,
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 4b3597afd7..3f145dc958 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -15,10 +15,11 @@ app_logo_url = "/assets/erpnext/images/erpnext-logo.svg"
develop_version = '13.x.x-develop'
-app_include_js = "/assets/js/erpnext.min.js"
-app_include_css = "/assets/css/erpnext.css"
-web_include_js = "/assets/js/erpnext-web.min.js"
-web_include_css = "/assets/css/erpnext-web.css"
+app_include_js = "erpnext.bundle.js"
+app_include_css = "erpnext.bundle.css"
+web_include_js = "erpnext-web.bundle.js"
+web_include_css = "erpnext-web.bundle.css"
+email_css = "email.bundle.css"
doctype_js = {
"Address": "public/js/address.js",
diff --git a/erpnext/public/js/hub/hub_factory.js b/erpnext/public/js/hub/hub_factory.js
index 8dab2d6251..9c67c1cf9f 100644
--- a/erpnext/public/js/hub/hub_factory.js
+++ b/erpnext/public/js/hub/hub_factory.js
@@ -19,11 +19,7 @@ frappe.views.MarketplaceFactory = class MarketplaceFactory extends frappe.views.
}
make(page_name) {
- const assets = [
- '/assets/js/marketplace.min.js'
- ];
-
- frappe.require(assets, () => {
+ frappe.require('marketplace.bundle.js', () => {
erpnext.hub.marketplace = new erpnext.hub.Marketplace({
parent: this.make_page(true, page_name)
});
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index e3405e0ce8..6db4150be9 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -7,7 +7,7 @@ frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
single_column: true
});
- frappe.require('assets/js/point-of-sale.min.js', function() {
+ frappe.require('point-of-sale.bundle.js', function() {
wrapper.pos = new erpnext.PointOfSale.Controller(wrapper);
window.cur_pos = wrapper.pos;
});
@@ -19,4 +19,4 @@ frappe.pages['point-of-sale'].refresh = function(wrapper) {
wrapper.pos.wrapper.html("");
wrapper.pos.check_opening_entry();
}
-};
\ No newline at end of file
+};
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 2079cf88dd..2aa42e66f8 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -379,7 +379,7 @@ $.extend(erpnext.item, {
// Show Stock Levels only if is_stock_item
if (frm.doc.is_stock_item) {
- frappe.require('assets/js/item-dashboard.min.js', function() {
+ frappe.require('item-dashboard.bundle.js', function() {
const section = frm.dashboard.add_section('', __("Stock Levels"));
erpnext.item.item_dashboard = new erpnext.stock.ItemDashboard({
parent: section,
diff --git a/erpnext/stock/page/stock_balance/stock_balance.js b/erpnext/stock/page/stock_balance/stock_balance.js
index bddffd465e..f00dd3e791 100644
--- a/erpnext/stock/page/stock_balance/stock_balance.js
+++ b/erpnext/stock/page/stock_balance/stock_balance.js
@@ -62,7 +62,7 @@ frappe.pages['stock-balance'].on_page_load = function(wrapper) {
// page.sort_selector.wrapper.css({'margin-right': '15px', 'margin-top': '4px'});
- frappe.require('assets/js/item-dashboard.min.js', function() {
+ frappe.require('item-dashboard.bundle.js', function() {
page.item_dashboard = new erpnext.stock.ItemDashboard({
parent: page.main,
page_length: 20,
diff --git a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js
index b610e7dd58..c0ffdc9d51 100644
--- a/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js
+++ b/erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js
@@ -79,7 +79,7 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) {
}
});
- frappe.require('assets/js/item-dashboard.min.js', function() {
+ frappe.require('item-dashboard.bundle.js', function() {
$(frappe.render_template('warehouse_capacity_summary_header')).appendTo(page.main);
page.capacity_dashboard = new erpnext.stock.ItemDashboard({
@@ -117,4 +117,4 @@ frappe.pages['warehouse-capacity-summary'].on_page_load = function(wrapper) {
setup_click('Item');
setup_click('Warehouse');
});
-};
\ No newline at end of file
+};
diff --git a/erpnext/templates/generators/item/item.html b/erpnext/templates/generators/item/item.html
index 135982d709..17f6880293 100644
--- a/erpnext/templates/generators/item/item.html
+++ b/erpnext/templates/generators/item/item.html
@@ -28,9 +28,7 @@
{% block base_scripts %}
-
-
-
-
-
-{% endblock %}
\ No newline at end of file
+{{ include_script("frappe-web.bundle.js") }}
+{{ include_script("controls.bundle.js") }}
+{{ include_script("dialog.bundle.js") }}
+{% endblock %}
diff --git a/erpnext/templates/pages/cart.html b/erpnext/templates/pages/cart.html
index ea343713a1..c64c6343cc 100644
--- a/erpnext/templates/pages/cart.html
+++ b/erpnext/templates/pages/cart.html
@@ -139,9 +139,7 @@
{% block base_scripts %}
-
-
-
-
-
+{{ include_script("frappe-web.bundle.js") }}
+{{ include_script("controls.bundle.js") }}
+{{ include_script("dialog.bundle.js") }}
{% endblock %}
From 0c8294c963782767829228c95191ec87e0f5afd0 Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Fri, 7 May 2021 14:53:55 +0530
Subject: [PATCH 029/262] fix: gitignore dist directory
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 652fbdc317..63c51c4976 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ latest_updates.json
.wnf-lang-status
*.egg-info
dist/
+erpnext/public/dist
erpnext/docs/current
*.swp
*.swo
From a0ac5e3b13b230c309c4069a7a5b9aa63e9c2bb9 Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Fri, 7 May 2021 14:57:32 +0530
Subject: [PATCH 030/262] chore: Add git blame ignore revs file
Ignore the commit which replaces use of Class.extend with native class in git blames
---
.git-blame-ignore-revs | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 .git-blame-ignore-revs
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000000..c820d233a5
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,12 @@
+# Since version 2.23 (released in August 2019), git-blame has a feature
+# to ignore or bypass certain commits.
+#
+# This file contains a list of commits that are not likely what you
+# are looking for in a blame, such as mass reformatting or renaming.
+# You can set this file as a default ignore file for blame by running
+# the following command.
+#
+# $ git config blame.ignoreRevsFile .git-blame-ignore-revs
+
+# Replace use of Class.extend with native JS class
+1fe891b287a1b3f225d29ee3d07e7b1824aba9e7
From f97cc0367b699cb8342bd753c7e54d8a3b1d0cf9 Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Fri, 7 May 2021 15:32:06 +0530
Subject: [PATCH 031/262] fix: initialize filters in constructor
---
erpnext/public/js/stock_analytics.js | 48 ++++++++++++++--------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/erpnext/public/js/stock_analytics.js b/erpnext/public/js/stock_analytics.js
index c74b45e6db..dfe2c88ea8 100644
--- a/erpnext/public/js/stock_analytics.js
+++ b/erpnext/public/js/stock_analytics.js
@@ -31,6 +31,30 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
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) {
+ 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) {
+ 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"},
+ ]}
+ ];
}
setup_columns() {
var std_columns = [
@@ -45,30 +69,6 @@ erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
this.columns = std_columns.concat(this.columns);
}
- 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) {
- 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) {
- 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"},
- ]}
- ]
-
setup_filters() {
var me = this;
super.setup_filters();
From 490aed2a16bce43bd3e4373628b75f3e4f46932d Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sat, 8 May 2021 00:04:34 +0530
Subject: [PATCH 032/262] chore: Debug
---
.github/workflows/patch.yml | 69 +++++++++++++++++++
.../{ci-tests.yml => server-tests.yml} | 31 +++------
2 files changed, 78 insertions(+), 22 deletions(-)
create mode 100644 .github/workflows/patch.yml
rename .github/workflows/{ci-tests.yml => server-tests.yml} (70%)
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
new file mode 100644
index 0000000000..7c9e0272c9
--- /dev/null
+++ b/.github/workflows/patch.yml
@@ -0,0 +1,69 @@
+name: Patch
+
+on: [pull_request, workflow_dispatch]
+
+jobs:
+ test:
+ runs-on: ubuntu-18.04
+
+ name: Patch Test
+
+ services:
+ mysql:
+ image: mariadb:10.3
+ env:
+ MYSQL_ALLOW_EMPTY_PASSWORD: YES
+ ports:
+ - 3306:3306
+ options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
+
+ steps:
+ - name: Clone
+ uses: actions/checkout@v2
+
+ - name: Setup Python
+ uses: actions/setup-python@v2
+ with:
+ python-version: 3.6
+
+ - name: Add to Hosts
+ run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
+
+ - name: Cache pip
+ uses: actions/cache@v2
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
+ ${{ runner.os }}-
+
+ - name: Cache node modules
+ uses: actions/cache@v2
+ env:
+ cache-name: cache-node-modules
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-build-${{ env.cache-name }}-
+ ${{ runner.os }}-build-
+ ${{ runner.os }}-
+
+ - name: Get yarn cache directory path
+ id: yarn-cache-dir-path
+ run: echo "::set-output name=dir::$(yarn cache dir)"
+
+ - uses: actions/cache@v2
+ id: yarn-cache
+ with:
+ path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
+ key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-yarn-
+
+ - name: Install
+ run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
+
+ - name: Run Patch Tests
+ run: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/server-tests.yml
similarity index 70%
rename from .github/workflows/ci-tests.yml
rename to .github/workflows/server-tests.yml
index 4d955190be..4042a407e7 100644
--- a/.github/workflows/ci-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -1,4 +1,4 @@
-name: CI
+name: Server
on: [pull_request, workflow_dispatch]
@@ -7,24 +7,12 @@ jobs:
runs-on: ubuntu-18.04
strategy:
- fail-fast: false
+ fail-fast: true
matrix:
- include:
- - TYPE: "server"
- JOB_NAME: "Server.1"
- RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- - TYPE: "server"
- JOB_NAME: "Server.2"
- RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- - TYPE: "server"
- JOB_NAME: "Server.3"
- RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --with-coverage --ci-build-id $GITHUB_RUN_ID --app erpnext
- - TYPE: "patch"
- JOB_NAME: "Patch"
- RUN_COMMAND: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
+ container: [1, 2]
- name: ${{ matrix.JOB_NAME }}
+ name: Server Tests
services:
mysql:
@@ -42,7 +30,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
- python-version: 3.6
+ python-version: 3.7
- name: Add to Hosts
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
@@ -55,6 +43,7 @@ jobs:
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
+
- name: Cache node modules
uses: actions/cache@v2
env:
@@ -66,6 +55,7 @@ jobs:
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
+
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
@@ -82,12 +72,11 @@ jobs:
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
- name: Run Tests
- run: ${{ matrix.RUN_COMMAND }}
+ run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --build-number ${{ matrix.container }} --total-builds 2 --with-coverage
env:
- TYPE: ${{ matrix.TYPE }}
+ TYPE: server
- name: Upload Coverage Data
- if: matrix.TYPE == 'server'
run: |
cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
cd ${GITHUB_WORKSPACE}
@@ -113,10 +102,8 @@ jobs:
- name: Coveralls Finished
run: |
cd ${GITHUB_WORKSPACE}
- ls -al
pip3 install coverage==5.5
pip3 install coveralls==3.0.1
coveralls --finish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
From ccf6249bfb70e5614525bfa91e46fa4030674911 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sat, 8 May 2021 00:05:48 +0530
Subject: [PATCH 033/262] chore: Debug
---
.github/workflows/server-tests.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 4042a407e7..1e9196119e 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -10,7 +10,7 @@ jobs:
fail-fast: true
matrix:
- container: [1, 2]
+ container: [1, 2, 3]
name: Server Tests
@@ -72,7 +72,7 @@ jobs:
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
- name: Run Tests
- run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --build-number ${{ matrix.container }} --total-builds 2 --with-coverage
+ run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --build-number ${{ matrix.container }} --total-builds 3 --with-coverage
env:
TYPE: server
From 622bf077e76faeba5c7006d52438b5c1508b5c86 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sat, 8 May 2021 13:51:34 +0530
Subject: [PATCH 034/262] ci: Disble failfast temporarily
---
.github/workflows/server-tests.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 1e9196119e..0d5a3ba61a 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-18.04
strategy:
- fail-fast: true
+ fail-fast: false
matrix:
container: [1, 2, 3]
From d27e70a67aa194703f81c7d5a4a81441f632dc9b Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sat, 8 May 2021 16:02:40 +0530
Subject: [PATCH 035/262] ci: Fix coveralls
---
.github/workflows/server-tests.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 0d5a3ba61a..e5fb72538d 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -82,12 +82,12 @@ jobs:
cd ${GITHUB_WORKSPACE}
pip3 install coverage==5.5
pip3 install coveralls==3.0.1
- coveralls --service=github-actions
+ coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
COVERALLS_FLAG_NAME: run-${{ matrix.container }}
- COVERALLS_SERVICE_NAME: github-actions
+ COVERALLS_SERVICE_NAME: ${{ github.event_name == 'pull_request' && 'github' || 'github-actions' }}
COVERALLS_PARALLEL: true
coveralls:
From 142ec9e99e2e077c6eb0c36b5d3c4a24b71fb5ab Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sat, 8 May 2021 19:03:53 +0530
Subject: [PATCH 036/262] test: Pass ConflictingTaxRule during tax rule test
---
erpnext/shopping_cart/test_shopping_cart.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/shopping_cart/test_shopping_cart.py b/erpnext/shopping_cart/test_shopping_cart.py
index d857bf5f5c..ac61aebc56 100644
--- a/erpnext/shopping_cart/test_shopping_cart.py
+++ b/erpnext/shopping_cart/test_shopping_cart.py
@@ -7,7 +7,7 @@ import frappe
from frappe.utils import nowdate, add_months
from erpnext.shopping_cart.cart import _get_cart_quotation, update_cart, get_party
from erpnext.tests.utils import create_test_contact_and_address
-
+from erpnext.accounts.doctype.tax_rule.tax_rule import ConflictingTaxRule
# test_dependencies = ['Payment Terms Template']
@@ -125,7 +125,7 @@ class TestShoppingCart(unittest.TestCase):
tax_rule = frappe.get_test_records("Tax Rule")[0]
try:
frappe.get_doc(tax_rule).insert()
- except frappe.DuplicateEntryError:
+ except (frappe.DuplicateEntryError, ConflictingTaxRule):
pass
def create_quotation(self):
From 7044bcfaabb54ccd6416b87404bb9a2bcc2d0cec Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sun, 9 May 2021 11:29:00 +0530
Subject: [PATCH 037/262] ci: Try parallel testing with orchestrator
---
.github/workflows/server-tests.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index e5fb72538d..0e638104c8 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -72,9 +72,10 @@ jobs:
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
- name: Run Tests
- run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --build-number ${{ matrix.container }} --total-builds 3 --with-coverage
+ run: cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --use-orchestrator --with-coverage
env:
TYPE: server
+ CI_BUILD_ID: ${{ github.run_id }}
- name: Upload Coverage Data
run: |
From 2ac27d774d69ebc562e6d0ec566b45e9fdfa5ee7 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sun, 9 May 2021 14:38:28 +0530
Subject: [PATCH 038/262] test: Fix test dependency
---
.../doctype/accounting_dimension/test_accounting_dimension.py | 2 +-
.../test_accounting_dimension_filter.py | 2 +-
.../doctype/accounting_period/test_accounting_period.py | 4 +++-
erpnext/tests/__init__.py | 2 +-
4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
index 6fb661eb54..e657a9ae34 100644
--- a/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
+++ b/erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
@@ -8,7 +8,7 @@ import unittest
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
-test_dependencies = ['Location']
+test_dependencies = ['Cost Center', 'Location', 'Warehouse', 'Department']
class TestAccountingDimension(unittest.TestCase):
def setUp(self):
diff --git a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
index 78a88eb48c..7f6254f99f 100644
--- a/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
+++ b/erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
@@ -9,7 +9,7 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import create_dimension, disable_dimension
from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError
-test_dependencies = ['Location']
+test_dependencies = ['Location', 'Cost Center', 'Department']
class TestAccountingDimensionFilter(unittest.TestCase):
def setUp(self):
diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
index 10cd939894..3b4f138495 100644
--- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
@@ -10,6 +10,8 @@ from erpnext.accounts.general_ledger import ClosedAccountingPeriod
from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
+test_dependencies = ['Item']
+
class TestAccountingPeriod(unittest.TestCase):
def test_overlap(self):
ap1 = create_accounting_period(start_date = "2018-04-01",
@@ -38,7 +40,7 @@ def create_accounting_period(**args):
accounting_period.start_date = args.start_date or nowdate()
accounting_period.end_date = args.end_date or add_months(nowdate(), 1)
accounting_period.company = args.company or "_Test Company"
- accounting_period.period_name =args.period_name or "_Test_Period_Name_1"
+ accounting_period.period_name = args.period_name or "_Test_Period_Name_1"
accounting_period.append("closed_documents", {
"document_type": 'Sales Invoice', "closed": 1
})
diff --git a/erpnext/tests/__init__.py b/erpnext/tests/__init__.py
index 593bc7c71b..a504340d40 100644
--- a/erpnext/tests/__init__.py
+++ b/erpnext/tests/__init__.py
@@ -1 +1 @@
-global_test_dependencies = ['User', 'Company', 'Cost Center', 'Account', 'Warehouse', 'Item']
+global_test_dependencies = ['User', 'Company', 'Item']
From dfb8aa017d4c9d1a8f3d24d8b05a5949c673e525 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Sun, 9 May 2021 14:38:54 +0530
Subject: [PATCH 039/262] ci: Check limits
---
.github/workflows/server-tests.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 0e638104c8..e7830c07f6 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -10,7 +10,7 @@ jobs:
fail-fast: false
matrix:
- container: [1, 2, 3]
+ container: [1, 2, 3, 4]
name: Server Tests
@@ -30,7 +30,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
- python-version: 3.7
+ python-version: 3.6
- name: Add to Hosts
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
From ec6b652cd4f572356073fd9ab5098c21af67cb3b Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 09:18:25 +0530
Subject: [PATCH 040/262] refactor: Rename assertEquals to assertEqual to avoid
deprecation warnings
---
.../accounts/doctype/dunning/test_dunning.py | 8 +-
.../doctype/gl_entry/test_gl_entry.py | 2 +-
.../payment_order/test_payment_order.py | 8 +-
.../doctype/pricing_rule/pricing_rule.py | 2 +-
.../doctype/pricing_rule/test_pricing_rule.py | 36 +++----
erpnext/assets/doctype/asset/test_asset.py | 6 +-
.../purchase_order/test_purchase_order.py | 42 ++++----
.../mpesa_settings/test_mpesa_settings.py | 30 +++---
.../test_clinical_procedure.py | 2 +-
.../doctype/lab_test/test_lab_test.py | 4 +-
.../test_patient_appointment.py | 8 +-
.../doctype/therapy_plan/test_therapy_plan.py | 14 +--
.../doctype/therapy_type/test_therapy_type.py | 2 +-
.../test_compensatory_leave_request.py | 16 ++--
.../expense_claim/test_expense_claim.py | 12 +--
.../hr/doctype/job_offer/test_job_offer.py | 4 +-
.../leave_allocation/test_leave_allocation.py | 14 +--
.../test_leave_application.py | 18 ++--
.../leave_encashment/test_leave_encashment.py | 8 +-
.../loan_management/doctype/loan/test_loan.py | 96 +++++++++----------
.../test_loan_disbursement.py | 6 +-
.../test_loan_interest_accrual.py | 6 +-
erpnext/manufacturing/doctype/bom/test_bom.py | 2 +-
.../bom_update_tool/test_bom_update_tool.py | 6 +-
.../doctype/work_order/test_work_order.py | 10 +-
.../doctype/donation/test_donation.py | 2 +-
.../portal/doctype/homepage/test_homepage.py | 2 +-
.../homepage_section/test_homepage_section.py | 4 +-
.../test_tax_exemption_80g_certificate.py | 12 +--
erpnext/regional/india/utils.py | 2 +-
.../doctype/quotation/test_quotation.py | 2 +-
.../doctype/sales_order/test_sales_order.py | 4 +-
.../delivery_note/test_delivery_note.py | 6 +-
.../purchase_receipt/test_purchase_receipt.py | 10 +-
erpnext/support/doctype/issue/test_issue.py | 28 +++---
35 files changed, 217 insertions(+), 217 deletions(-)
diff --git a/erpnext/accounts/doctype/dunning/test_dunning.py b/erpnext/accounts/doctype/dunning/test_dunning.py
index cb18309e3c..e2d4d82e41 100644
--- a/erpnext/accounts/doctype/dunning/test_dunning.py
+++ b/erpnext/accounts/doctype/dunning/test_dunning.py
@@ -29,7 +29,7 @@ class TestDunning(unittest.TestCase):
self.assertEqual(round(amounts.get('interest_amount'), 2), 0.44)
self.assertEqual(round(amounts.get('dunning_amount'), 2), 20.44)
self.assertEqual(round(amounts.get('grand_total'), 2), 120.44)
-
+
def test_gl_entries(self):
dunning = create_dunning()
dunning.submit()
@@ -42,9 +42,9 @@ class TestDunning(unittest.TestCase):
['Sales - _TC', 0.0, 20.44]
])
for gle in gl_entries:
- self.assertEquals(expected_values[gle.account][0], gle.account)
- self.assertEquals(expected_values[gle.account][1], gle.debit)
- self.assertEquals(expected_values[gle.account][2], gle.credit)
+ self.assertEqual(expected_values[gle.account][0], gle.account)
+ self.assertEqual(expected_values[gle.account][1], gle.debit)
+ self.assertEqual(expected_values[gle.account][2], gle.credit)
def test_payment_entry(self):
dunning = create_dunning()
diff --git a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py
index b4a547b21b..4167ca70df 100644
--- a/erpnext/accounts/doctype/gl_entry/test_gl_entry.py
+++ b/erpnext/accounts/doctype/gl_entry/test_gl_entry.py
@@ -54,4 +54,4 @@ class TestGLEntry(unittest.TestCase):
self.assertTrue(all(new.name != old.name for new, old in zip(gl_entries, new_gl_entries)))
new_naming_series_current_value = frappe.db.sql("SELECT current from tabSeries where name = %s", naming_series)[0][0]
- self.assertEquals(old_naming_series_current_value + 2, new_naming_series_current_value)
+ self.assertEqual(old_naming_series_current_value + 2, new_naming_series_current_value)
diff --git a/erpnext/accounts/doctype/payment_order/test_payment_order.py b/erpnext/accounts/doctype/payment_order/test_payment_order.py
index 1c23e2a0ec..5fdde07faa 100644
--- a/erpnext/accounts/doctype/payment_order/test_payment_order.py
+++ b/erpnext/accounts/doctype/payment_order/test_payment_order.py
@@ -31,10 +31,10 @@ class TestPaymentOrder(unittest.TestCase):
doc = create_payment_order_against_payment_entry(payment_entry, "Payment Entry")
reference_doc = doc.get("references")[0]
- self.assertEquals(reference_doc.reference_name, payment_entry.name)
- self.assertEquals(reference_doc.reference_doctype, "Payment Entry")
- self.assertEquals(reference_doc.supplier, "_Test Supplier")
- self.assertEquals(reference_doc.amount, 250)
+ self.assertEqual(reference_doc.reference_name, payment_entry.name)
+ self.assertEqual(reference_doc.reference_doctype, "Payment Entry")
+ self.assertEqual(reference_doc.supplier, "_Test Supplier")
+ self.assertEqual(reference_doc.amount, 250)
def create_payment_order_against_payment_entry(ref_doc, order_type):
payment_order = frappe.get_doc(dict(
diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
index aedf1c6f1a..556f49d34c 100644
--- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py
@@ -152,7 +152,7 @@ class PricingRule(Document):
frappe.throw(_("Valid from date must be less than valid upto date"))
def validate_condition(self):
- if self.condition and ("=" in self.condition) and re.match("""[\w\.:_]+\s*={1}\s*[\w\.@'"]+""", self.condition):
+ if self.condition and ("=" in self.condition) and re.match(r'[\w\.:_]+\s*={1}\s*[\w\.@\'"]+', self.condition):
frappe.throw(_("Invalid condition expression"))
#--------------------------------------------------------------------------------
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index ef9aad562d..ffe8be1162 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -99,7 +99,7 @@ class TestPricingRule(unittest.TestCase):
args.item_code = "_Test Item 2"
details = get_item_details(args)
- self.assertEquals(details.get("discount_percentage"), 15)
+ self.assertEqual(details.get("discount_percentage"), 15)
def test_pricing_rule_for_margin(self):
from erpnext.stock.get_item_details import get_item_details
@@ -145,8 +145,8 @@ class TestPricingRule(unittest.TestCase):
"name": None
})
details = get_item_details(args)
- self.assertEquals(details.get("margin_type"), "Percentage")
- self.assertEquals(details.get("margin_rate_or_amount"), 10)
+ self.assertEqual(details.get("margin_type"), "Percentage")
+ self.assertEqual(details.get("margin_rate_or_amount"), 10)
def test_mixed_conditions_for_item_group(self):
for item in ["Mixed Cond Item 1", "Mixed Cond Item 2"]:
@@ -192,7 +192,7 @@ class TestPricingRule(unittest.TestCase):
"name": None
})
details = get_item_details(args)
- self.assertEquals(details.get("discount_percentage"), 10)
+ self.assertEqual(details.get("discount_percentage"), 10)
def test_pricing_rule_for_variants(self):
from erpnext.stock.get_item_details import get_item_details
@@ -322,11 +322,11 @@ class TestPricingRule(unittest.TestCase):
si.insert(ignore_permissions=True)
item = si.items[0]
- self.assertEquals(item.margin_rate_or_amount, 10)
- self.assertEquals(item.rate_with_margin, 1100)
+ self.assertEqual(item.margin_rate_or_amount, 10)
+ self.assertEqual(item.rate_with_margin, 1100)
self.assertEqual(item.discount_percentage, 10)
- self.assertEquals(item.discount_amount, 110)
- self.assertEquals(item.rate, 990)
+ self.assertEqual(item.discount_amount, 110)
+ self.assertEqual(item.rate, 990)
def test_pricing_rule_with_margin_and_discount_amount(self):
frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
@@ -338,10 +338,10 @@ class TestPricingRule(unittest.TestCase):
si.insert(ignore_permissions=True)
item = si.items[0]
- self.assertEquals(item.margin_rate_or_amount, 10)
- self.assertEquals(item.rate_with_margin, 1100)
- self.assertEquals(item.discount_amount, 110)
- self.assertEquals(item.rate, 990)
+ self.assertEqual(item.margin_rate_or_amount, 10)
+ self.assertEqual(item.rate_with_margin, 1100)
+ self.assertEqual(item.discount_amount, 110)
+ self.assertEqual(item.rate, 990)
def test_pricing_rule_for_product_discount_on_same_item(self):
frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
@@ -458,21 +458,21 @@ class TestPricingRule(unittest.TestCase):
si.items[0].price_list_rate = 1000
si.submit()
item = si.items[0]
- self.assertEquals(item.rate, 100)
+ self.assertEqual(item.rate, 100)
# Correct Customer and Incorrect is_return value
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", is_return=1, qty=-1)
si.items[0].price_list_rate = 1000
si.submit()
item = si.items[0]
- self.assertEquals(item.rate, 100)
+ self.assertEqual(item.rate, 100)
# Correct Customer and correct is_return value
si = create_sales_invoice(do_not_submit=True, customer="_Test Customer 1", is_return=0)
si.items[0].price_list_rate = 1000
si.submit()
item = si.items[0]
- self.assertEquals(item.rate, 900)
+ self.assertEqual(item.rate, 900)
def test_multiple_pricing_rules(self):
make_pricing_rule(discount_percentage=20, selling=1, priority=1, apply_multiple_pricing_rules=1,
@@ -545,11 +545,11 @@ class TestPricingRule(unittest.TestCase):
apply_on="Transaction", free_item="Water Flask 1", free_qty=1, free_item_rate=10)
si = create_sales_invoice(qty=5, do_not_submit=True)
- self.assertEquals(len(si.items), 2)
- self.assertEquals(si.items[1].rate, 10)
+ self.assertEqual(len(si.items), 2)
+ self.assertEqual(si.items[1].rate, 10)
si1 = create_sales_invoice(qty=2, do_not_submit=True)
- self.assertEquals(len(si1.items), 1)
+ self.assertEqual(len(si1.items), 1)
for doc in [si, si1]:
doc.delete()
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index a0d76031fc..f12a33dd2b 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -78,7 +78,7 @@ class TestAsset(unittest.TestCase):
})
doc.set_missing_values()
- self.assertEquals(doc.items[0].is_fixed_asset, 1)
+ self.assertEqual(doc.items[0].is_fixed_asset, 1)
def test_schedule_for_straight_line_method(self):
pr = make_purchase_receipt(item_code="Macbook Pro",
@@ -565,8 +565,8 @@ class TestAsset(unittest.TestCase):
doc = make_invoice(pr.name)
- self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
-
+ self.assertEqual('Asset Received But Not Billed - _TC', doc.items[0].expense_account)
+
def test_asset_cwip_toggling_cases(self):
cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting")
name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"])
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 42f4472f29..aaa98f2f1f 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -187,7 +187,7 @@ class TestPurchaseOrder(unittest.TestCase):
update_child_qty_rate('Purchase Order', trans_item, po.name)
po.reload()
- self.assertEquals(len(po.get('items')), 2)
+ self.assertEqual(len(po.get('items')), 2)
self.assertEqual(po.status, 'To Receive and Bill')
# ordered qty should increase on row addition
self.assertEqual(get_ordered_qty(), existing_ordered_qty + 7)
@@ -234,7 +234,7 @@ class TestPurchaseOrder(unittest.TestCase):
update_child_qty_rate('Purchase Order', trans_item, po.name)
po.reload()
- self.assertEquals(len(po.get('items')), 1)
+ self.assertEqual(len(po.get('items')), 1)
self.assertEqual(po.status, 'To Receive and Bill')
# ordered qty should decrease (back to initial) on row deletion
@@ -448,13 +448,13 @@ class TestPurchaseOrder(unittest.TestCase):
pi.load_from_db()
- self.assertEquals(pi.per_received, 100.00)
- self.assertEquals(pi.items[0].qty, pi.items[0].received_qty)
+ self.assertEqual(pi.per_received, 100.00)
+ self.assertEqual(pi.items[0].qty, pi.items[0].received_qty)
po.load_from_db()
- self.assertEquals(po.per_received, 100.00)
- self.assertEquals(po.per_billed, 100.00)
+ self.assertEqual(po.per_received, 100.00)
+ self.assertEqual(po.per_billed, 100.00)
pr.cancel()
@@ -674,8 +674,8 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname=["reserved_qty_for_sub_contract", "projected_qty"], as_dict=1)
- self.assertEquals(bin2.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
- self.assertEquals(bin2.projected_qty, bin1.projected_qty - 10)
+ self.assertEqual(bin2.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
+ self.assertEqual(bin2.projected_qty, bin1.projected_qty - 10)
# Create stock transfer
rm_item = [{"item_code":"_Test FG Item","rm_item_code":"_Test Item","item_name":"_Test Item",
@@ -690,7 +690,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin3.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
+ self.assertEqual(bin3.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
# close PO
po.update_status("Closed")
@@ -698,7 +698,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin4.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
+ self.assertEqual(bin4.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
# Re-open PO
po.update_status("Submitted")
@@ -706,7 +706,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
+ self.assertEqual(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item",
qty=40, basic_rate=100)
@@ -723,7 +723,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin6.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
+ self.assertEqual(bin6.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
# Cancel PR
pr.cancel()
@@ -731,7 +731,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin7.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
+ self.assertEqual(bin7.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
# Make Purchase Invoice
pi = make_pi_from_po(po.name)
@@ -743,7 +743,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin8.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
+ self.assertEqual(bin8.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
# Cancel PR
pi.cancel()
@@ -751,7 +751,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin9.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
+ self.assertEqual(bin9.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
# Cancel Stock Entry
se.cancel()
@@ -759,7 +759,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin10.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
+ self.assertEqual(bin10.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
# Cancel PO
po.reload()
@@ -768,7 +768,7 @@ class TestPurchaseOrder(unittest.TestCase):
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
fieldname="reserved_qty_for_sub_contract", as_dict=1)
- self.assertEquals(bin11.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
+ self.assertEqual(bin11.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
def test_exploded_items_in_subcontracted(self):
item_code = "_Test Subcontracted FG Item 1"
@@ -782,7 +782,7 @@ class TestPurchaseOrder(unittest.TestCase):
exploded_items = sorted([d.item_code for d in bom.exploded_items if not d.get('sourced_by_supplier')])
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
- self.assertEquals(exploded_items, supplied_items)
+ self.assertEqual(exploded_items, supplied_items)
po1 = create_purchase_order(item_code=item_code, qty=1,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", include_exploded_items=0)
@@ -790,7 +790,7 @@ class TestPurchaseOrder(unittest.TestCase):
supplied_items1 = sorted([d.rm_item_code for d in po1.supplied_items])
bom_items = sorted([d.item_code for d in bom.items if not d.get('sourced_by_supplier')])
- self.assertEquals(supplied_items1, bom_items)
+ self.assertEqual(supplied_items1, bom_items)
def test_backflush_based_on_stock_entry(self):
item_code = "_Test Subcontracted FG Item 1"
@@ -840,8 +840,8 @@ class TestPurchaseOrder(unittest.TestCase):
transferred_items = sorted([d.item_code for d in se.get('items') if se.purchase_order == po.name])
issued_items = sorted([d.rm_item_code for d in pr.get('supplied_items')])
- self.assertEquals(transferred_items, issued_items)
- self.assertEquals(pr.get('items')[0].rm_supp_cost, 2000)
+ self.assertEqual(transferred_items, issued_items)
+ self.assertEqual(pr.get('items')[0].rm_supp_cost, 2000)
transferred_rm_map = frappe._dict()
diff --git a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
index 29487962f6..3c2e59ab82 100644
--- a/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
+++ b/erpnext/erpnext_integrations/doctype/mpesa_settings/test_mpesa_settings.py
@@ -19,7 +19,7 @@ class TestMpesaSettings(unittest.TestCase):
mode_of_payment = frappe.get_doc("Mode of Payment", "Mpesa-_Test")
self.assertTrue(frappe.db.exists("Payment Gateway Account", {'payment_gateway': "Mpesa-_Test"}))
self.assertTrue(mode_of_payment.name)
- self.assertEquals(mode_of_payment.type, "Phone")
+ self.assertEqual(mode_of_payment.type, "Phone")
def test_processing_of_account_balance(self):
mpesa_doc = create_mpesa_settings(payment_gateway_name="_Account Balance")
@@ -31,11 +31,11 @@ class TestMpesaSettings(unittest.TestCase):
# test integration request creation and successful update of the status on receiving callback response
self.assertTrue(integration_request)
- self.assertEquals(integration_request.status, "Completed")
+ self.assertEqual(integration_request.status, "Completed")
# test formatting of account balance received as string to json with appropriate currency symbol
mpesa_doc.reload()
- self.assertEquals(mpesa_doc.account_balance, dumps({
+ self.assertEqual(mpesa_doc.account_balance, dumps({
"Working Account": {
"current_balance": "Sh 481,000.00",
"available_balance": "Sh 481,000.00",
@@ -60,7 +60,7 @@ class TestMpesaSettings(unittest.TestCase):
pr = pos_invoice.create_payment_request()
# test payment request creation
- self.assertEquals(pr.payment_gateway, "Mpesa-Payment")
+ self.assertEqual(pr.payment_gateway, "Mpesa-Payment")
# submitting payment request creates integration requests with random id
integration_req_ids = frappe.get_all("Integration Request", filters={
@@ -75,13 +75,13 @@ class TestMpesaSettings(unittest.TestCase):
# test integration request creation and successful update of the status on receiving callback response
self.assertTrue(integration_request)
- self.assertEquals(integration_request.status, "Completed")
+ self.assertEqual(integration_request.status, "Completed")
pos_invoice.reload()
integration_request.reload()
- self.assertEquals(pos_invoice.mpesa_receipt_number, "LGR7OWQX0R")
- self.assertEquals(integration_request.status, "Completed")
-
+ self.assertEqual(pos_invoice.mpesa_receipt_number, "LGR7OWQX0R")
+ self.assertEqual(integration_request.status, "Completed")
+
frappe.db.set_value("Customer", "_Test Customer", "default_currency", "")
integration_request.delete()
pr.reload()
@@ -104,7 +104,7 @@ class TestMpesaSettings(unittest.TestCase):
pr = pos_invoice.create_payment_request()
# test payment request creation
- self.assertEquals(pr.payment_gateway, "Mpesa-Payment")
+ self.assertEqual(pr.payment_gateway, "Mpesa-Payment")
# submitting payment request creates integration requests with random id
integration_req_ids = frappe.get_all("Integration Request", filters={
@@ -126,12 +126,12 @@ class TestMpesaSettings(unittest.TestCase):
verify_transaction(**callback_response)
# test completion of integration request
integration_request = frappe.get_doc("Integration Request", integration_req_ids[i])
- self.assertEquals(integration_request.status, "Completed")
+ self.assertEqual(integration_request.status, "Completed")
integration_requests.append(integration_request)
# check receipt number once all the integration requests are completed
pos_invoice.reload()
- self.assertEquals(pos_invoice.mpesa_receipt_number, ', '.join(mpesa_receipt_numbers))
+ self.assertEqual(pos_invoice.mpesa_receipt_number, ', '.join(mpesa_receipt_numbers))
frappe.db.set_value("Customer", "_Test Customer", "default_currency", "")
[d.delete() for d in integration_requests]
@@ -139,7 +139,7 @@ class TestMpesaSettings(unittest.TestCase):
pr.cancel()
pr.delete()
pos_invoice.delete()
-
+
def test_processing_of_only_one_succes_callback_payload(self):
create_mpesa_settings(payment_gateway_name="Payment")
mpesa_account = frappe.db.get_value("Payment Gateway Account", {"payment_gateway": 'Mpesa-Payment'}, "payment_account")
@@ -155,7 +155,7 @@ class TestMpesaSettings(unittest.TestCase):
pr = pos_invoice.create_payment_request()
# test payment request creation
- self.assertEquals(pr.payment_gateway, "Mpesa-Payment")
+ self.assertEqual(pr.payment_gateway, "Mpesa-Payment")
# submitting payment request creates integration requests with random id
integration_req_ids = frappe.get_all("Integration Request", filters={
@@ -175,7 +175,7 @@ class TestMpesaSettings(unittest.TestCase):
verify_transaction(**callback_response)
# test completion of integration request
integration_request = frappe.get_doc("Integration Request", integration_req_ids[0])
- self.assertEquals(integration_request.status, "Completed")
+ self.assertEqual(integration_request.status, "Completed")
# now one request is completed
# second integration request fails
@@ -187,7 +187,7 @@ class TestMpesaSettings(unittest.TestCase):
'name': ['not in', integration_req_ids]
}, pluck="name")
- self.assertEquals(len(new_integration_req_ids), 1)
+ self.assertEqual(len(new_integration_req_ids), 1)
frappe.db.set_value("Customer", "_Test Customer", "default_currency", "")
frappe.db.sql("delete from `tabIntegration Request` where integration_request_service = 'Mpesa'")
diff --git a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
index fb72073a07..03e96a4b3b 100644
--- a/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
+++ b/erpnext/healthcare/doctype/clinical_procedure/test_clinical_procedure.py
@@ -17,7 +17,7 @@ class TestClinicalProcedure(unittest.TestCase):
procedure_template.disabled = 1
procedure_template.save()
- self.assertEquals(frappe.db.get_value('Item', procedure_template.item, 'disabled'), 1)
+ self.assertEqual(frappe.db.get_value('Item', procedure_template.item, 'disabled'), 1)
def test_consumables(self):
patient, medical_department, practitioner = create_healthcare_docs()
diff --git a/erpnext/healthcare/doctype/lab_test/test_lab_test.py b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
index 79ab8a4d7f..c9f0029ed8 100644
--- a/erpnext/healthcare/doctype/lab_test/test_lab_test.py
+++ b/erpnext/healthcare/doctype/lab_test/test_lab_test.py
@@ -18,7 +18,7 @@ class TestLabTest(unittest.TestCase):
lab_template.disabled = 1
lab_template.save()
- self.assertEquals(frappe.db.get_value('Item', lab_template.item, 'disabled'), 1)
+ self.assertEqual(frappe.db.get_value('Item', lab_template.item, 'disabled'), 1)
lab_template.reload()
@@ -57,7 +57,7 @@ class TestLabTest(unittest.TestCase):
# sample collection should not be created
lab_test.reload()
- self.assertEquals(lab_test.sample, None)
+ self.assertEqual(lab_test.sample, None)
def test_create_lab_tests_from_sales_invoice(self):
sales_invoice = create_sales_invoice()
diff --git a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
index 2bb8a53c45..5f2dc480a1 100644
--- a/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
+++ b/erpnext/healthcare/doctype/patient_appointment/test_patient_appointment.py
@@ -20,13 +20,13 @@ class TestPatientAppointment(unittest.TestCase):
patient, medical_department, practitioner = create_healthcare_docs()
frappe.db.set_value('Healthcare Settings', None, 'automate_appointment_invoicing', 0)
appointment = create_appointment(patient, practitioner, nowdate())
- self.assertEquals(appointment.status, 'Open')
+ self.assertEqual(appointment.status, 'Open')
appointment = create_appointment(patient, practitioner, add_days(nowdate(), 2))
- self.assertEquals(appointment.status, 'Scheduled')
+ self.assertEqual(appointment.status, 'Scheduled')
encounter = create_encounter(appointment)
- self.assertEquals(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
encounter.cancel()
- self.assertEquals(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Open')
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Open')
def test_start_encounter(self):
patient, medical_department, practitioner = create_healthcare_docs()
diff --git a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
index 7fb159d6b5..113fa513f9 100644
--- a/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
+++ b/erpnext/healthcare/doctype/therapy_plan/test_therapy_plan.py
@@ -18,24 +18,24 @@ class TestTherapyPlan(unittest.TestCase):
def test_status(self):
plan = create_therapy_plan()
- self.assertEquals(plan.status, 'Not Started')
+ self.assertEqual(plan.status, 'Not Started')
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
frappe.get_doc(session).submit()
- self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'In Progress')
+ self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'In Progress')
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company')
frappe.get_doc(session).submit()
- self.assertEquals(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
+ self.assertEqual(frappe.db.get_value('Therapy Plan', plan.name, 'status'), 'Completed')
patient, medical_department, practitioner = create_healthcare_docs()
- appointment = create_appointment(patient, practitioner, nowdate())
+ appointment = create_appointment(patient, practitioner, nowdate())
session = make_therapy_session(plan.name, plan.patient, 'Basic Rehab', '_Test Company', appointment.name)
session = frappe.get_doc(session)
session.submit()
- self.assertEquals(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Closed')
session.cancel()
- self.assertEquals(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Open')
+ self.assertEqual(frappe.db.get_value('Patient Appointment', appointment.name, 'status'), 'Open')
def test_therapy_plan_from_template(self):
patient = create_patient()
@@ -49,7 +49,7 @@ class TestTherapyPlan(unittest.TestCase):
si.save()
therapy_plan_template_amt = frappe.db.get_value('Therapy Plan Template', template, 'total_amount')
- self.assertEquals(si.items[0].amount, therapy_plan_template_amt)
+ self.assertEqual(si.items[0].amount, therapy_plan_template_amt)
def create_therapy_plan(template=None):
diff --git a/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py
index 03a1be8a4e..21f6369975 100644
--- a/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py
+++ b/erpnext/healthcare/doctype/therapy_type/test_therapy_type.py
@@ -13,7 +13,7 @@ class TestTherapyType(unittest.TestCase):
therapy_type.disabled = 1
therapy_type.save()
- self.assertEquals(frappe.db.get_value('Item', therapy_type.item, 'disabled'), 1)
+ self.assertEqual(frappe.db.get_value('Item', therapy_type.item, 'disabled'), 1)
def create_therapy_type():
exercise = create_exercise_type()
diff --git a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py b/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py
index 74ce30108f..3b99c57051 100644
--- a/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py
+++ b/erpnext/hr/doctype/compensatory_leave_request/test_compensatory_leave_request.py
@@ -68,19 +68,19 @@ class TestCompensatoryLeaveRequest(unittest.TestCase):
filters = dict(transaction_name=compensatory_leave_request.leave_allocation)
leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=filters)
- self.assertEquals(len(leave_ledger_entry), 1)
- self.assertEquals(leave_ledger_entry[0].employee, compensatory_leave_request.employee)
- self.assertEquals(leave_ledger_entry[0].leave_type, compensatory_leave_request.leave_type)
- self.assertEquals(leave_ledger_entry[0].leaves, 1)
+ self.assertEqual(len(leave_ledger_entry), 1)
+ self.assertEqual(leave_ledger_entry[0].employee, compensatory_leave_request.employee)
+ self.assertEqual(leave_ledger_entry[0].leave_type, compensatory_leave_request.leave_type)
+ self.assertEqual(leave_ledger_entry[0].leaves, 1)
# check reverse leave ledger entry on cancellation
compensatory_leave_request.cancel()
leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=filters, order_by = 'creation desc')
- self.assertEquals(len(leave_ledger_entry), 2)
- self.assertEquals(leave_ledger_entry[0].employee, compensatory_leave_request.employee)
- self.assertEquals(leave_ledger_entry[0].leave_type, compensatory_leave_request.leave_type)
- self.assertEquals(leave_ledger_entry[0].leaves, -1)
+ self.assertEqual(len(leave_ledger_entry), 2)
+ self.assertEqual(leave_ledger_entry[0].employee, compensatory_leave_request.employee)
+ self.assertEqual(leave_ledger_entry[0].leave_type, compensatory_leave_request.leave_type)
+ self.assertEqual(leave_ledger_entry[0].leaves, -1)
def get_compensatory_leave_request(employee, leave_date=today()):
prev_comp_leave_req = frappe.db.get_value('Compensatory Leave Request',
diff --git a/erpnext/hr/doctype/expense_claim/test_expense_claim.py b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
index 3f22ca2141..578eccf787 100644
--- a/erpnext/hr/doctype/expense_claim/test_expense_claim.py
+++ b/erpnext/hr/doctype/expense_claim/test_expense_claim.py
@@ -88,9 +88,9 @@ class TestExpenseClaim(unittest.TestCase):
])
for gle in gl_entries:
- self.assertEquals(expected_values[gle.account][0], gle.account)
- self.assertEquals(expected_values[gle.account][1], gle.debit)
- self.assertEquals(expected_values[gle.account][2], gle.credit)
+ self.assertEqual(expected_values[gle.account][0], gle.account)
+ self.assertEqual(expected_values[gle.account][1], gle.debit)
+ self.assertEqual(expected_values[gle.account][2], gle.credit)
def test_rejected_expense_claim(self):
payable_account = get_payable_account(company_name)
@@ -104,11 +104,11 @@ class TestExpenseClaim(unittest.TestCase):
})
expense_claim.submit()
- self.assertEquals(expense_claim.status, 'Rejected')
- self.assertEquals(expense_claim.total_sanctioned_amount, 0.0)
+ self.assertEqual(expense_claim.status, 'Rejected')
+ self.assertEqual(expense_claim.total_sanctioned_amount, 0.0)
gl_entry = frappe.get_all('GL Entry', {'voucher_type': 'Expense Claim', 'voucher_no': expense_claim.name})
- self.assertEquals(len(gl_entry), 0)
+ self.assertEqual(len(gl_entry), 0)
def test_expense_approver_perms(self):
user = "test_approver_perm_emp@example.com"
diff --git a/erpnext/hr/doctype/job_offer/test_job_offer.py b/erpnext/hr/doctype/job_offer/test_job_offer.py
index 690a692ddc..b3e1dc8d87 100644
--- a/erpnext/hr/doctype/job_offer/test_job_offer.py
+++ b/erpnext/hr/doctype/job_offer/test_job_offer.py
@@ -35,13 +35,13 @@ class TestJobOffer(unittest.TestCase):
job_offer = create_job_offer(job_applicant=job_applicant.name)
job_offer.submit()
job_applicant.reload()
- self.assertEquals(job_applicant.status, "Accepted")
+ self.assertEqual(job_applicant.status, "Accepted")
# status update after rejection
job_offer.status = "Rejected"
job_offer.submit()
job_applicant.reload()
- self.assertEquals(job_applicant.status, "Rejected")
+ self.assertEqual(job_applicant.status, "Rejected")
def create_job_offer(**args):
args = frappe._dict(args)
diff --git a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
index 0b71036c86..6e7ae87d08 100644
--- a/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/test_leave_allocation.py
@@ -96,7 +96,7 @@ class TestLeaveAllocation(unittest.TestCase):
carry_forward=1)
leave_allocation_1.submit()
- self.assertEquals(leave_allocation_1.unused_leaves, 10)
+ self.assertEqual(leave_allocation_1.unused_leaves, 10)
leave_allocation_1.cancel()
@@ -108,7 +108,7 @@ class TestLeaveAllocation(unittest.TestCase):
new_leaves_allocated=25)
leave_allocation_2.submit()
- self.assertEquals(leave_allocation_2.unused_leaves, 5)
+ self.assertEqual(leave_allocation_2.unused_leaves, 5)
def test_carry_forward_leaves_expiry(self):
frappe.db.sql("delete from `tabLeave Allocation`")
@@ -145,7 +145,7 @@ class TestLeaveAllocation(unittest.TestCase):
to_date=add_months(nowdate(), 12))
leave_allocation_1.submit()
- self.assertEquals(leave_allocation_1.unused_leaves, leave_allocation.new_leaves_allocated)
+ self.assertEqual(leave_allocation_1.unused_leaves, leave_allocation.new_leaves_allocated)
def test_creation_of_leave_ledger_entry_on_submit(self):
frappe.db.sql("delete from `tabLeave Allocation`")
@@ -155,10 +155,10 @@ class TestLeaveAllocation(unittest.TestCase):
leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_allocation.name))
- self.assertEquals(len(leave_ledger_entry), 1)
- self.assertEquals(leave_ledger_entry[0].employee, leave_allocation.employee)
- self.assertEquals(leave_ledger_entry[0].leave_type, leave_allocation.leave_type)
- self.assertEquals(leave_ledger_entry[0].leaves, leave_allocation.new_leaves_allocated)
+ self.assertEqual(len(leave_ledger_entry), 1)
+ self.assertEqual(leave_ledger_entry[0].employee, leave_allocation.employee)
+ self.assertEqual(leave_ledger_entry[0].leave_type, leave_allocation.leave_type)
+ self.assertEqual(leave_ledger_entry[0].leaves, leave_allocation.new_leaves_allocated)
# check if leave ledger entry is deleted on cancellation
leave_allocation.cancel()
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index b54c9712c8..a9379e230b 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -516,9 +516,9 @@ class TestLeaveApplication(unittest.TestCase):
leave_application.submit()
leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_application.name))
- self.assertEquals(leave_ledger_entry[0].employee, leave_application.employee)
- self.assertEquals(leave_ledger_entry[0].leave_type, leave_application.leave_type)
- self.assertEquals(leave_ledger_entry[0].leaves, leave_application.total_leave_days * -1)
+ self.assertEqual(leave_ledger_entry[0].employee, leave_application.employee)
+ self.assertEqual(leave_ledger_entry[0].leave_type, leave_application.leave_type)
+ self.assertEqual(leave_ledger_entry[0].leaves, leave_application.total_leave_days * -1)
# check if leave ledger entry is deleted on cancellation
leave_application.cancel()
@@ -549,11 +549,11 @@ class TestLeaveApplication(unittest.TestCase):
leave_ledger_entry = frappe.get_all('Leave Ledger Entry', '*', filters=dict(transaction_name=leave_application.name))
- self.assertEquals(len(leave_ledger_entry), 2)
- self.assertEquals(leave_ledger_entry[0].employee, leave_application.employee)
- self.assertEquals(leave_ledger_entry[0].leave_type, leave_application.leave_type)
- self.assertEquals(leave_ledger_entry[0].leaves, -9)
- self.assertEquals(leave_ledger_entry[1].leaves, -2)
+ self.assertEqual(len(leave_ledger_entry), 2)
+ self.assertEqual(leave_ledger_entry[0].employee, leave_application.employee)
+ self.assertEqual(leave_ledger_entry[0].leave_type, leave_application.leave_type)
+ self.assertEqual(leave_ledger_entry[0].leaves, -9)
+ self.assertEqual(leave_ledger_entry[1].leaves, -2)
def test_leave_application_creation_after_expiry(self):
# test leave balance for carry forwarded allocation
@@ -566,7 +566,7 @@ class TestLeaveApplication(unittest.TestCase):
create_carry_forwarded_allocation(employee, leave_type)
- self.assertEquals(get_leave_balance_on(employee.name, leave_type.name, add_days(nowdate(), -85), add_days(nowdate(), -84)), 0)
+ self.assertEqual(get_leave_balance_on(employee.name, leave_type.name, add_days(nowdate(), -85), add_days(nowdate(), -84)), 0)
def test_leave_approver_perms(self):
employee = get_employee()
diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
index aafc9642d4..1f7fb6e68a 100644
--- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
@@ -88,10 +88,10 @@ class TestLeaveEncashment(unittest.TestCase):
leave_ledger_entry = frappe.get_all('Leave Ledger Entry', fields='*', filters=dict(transaction_name=leave_encashment.name))
- self.assertEquals(len(leave_ledger_entry), 1)
- self.assertEquals(leave_ledger_entry[0].employee, leave_encashment.employee)
- self.assertEquals(leave_ledger_entry[0].leave_type, leave_encashment.leave_type)
- self.assertEquals(leave_ledger_entry[0].leaves, leave_encashment.encashable_days * -1)
+ self.assertEqual(len(leave_ledger_entry), 1)
+ self.assertEqual(leave_ledger_entry[0].employee, leave_encashment.employee)
+ self.assertEqual(leave_ledger_entry[0].leave_type, leave_encashment.leave_type)
+ self.assertEqual(leave_ledger_entry[0].leaves, leave_encashment.encashable_days * -1)
# check if leave ledger entry is deleted on cancellation
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index fae6f860b6..fa4707ce2b 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -55,9 +55,9 @@ class TestLoan(unittest.TestCase):
def test_loan(self):
loan = frappe.get_doc("Loan", {"applicant":self.applicant1})
- self.assertEquals(loan.monthly_repayment_amount, 15052)
- self.assertEquals(flt(loan.total_interest_payable, 0), 21034)
- self.assertEquals(flt(loan.total_payment, 0), 301034)
+ self.assertEqual(loan.monthly_repayment_amount, 15052)
+ self.assertEqual(flt(loan.total_interest_payable, 0), 21034)
+ self.assertEqual(flt(loan.total_payment, 0), 301034)
schedule = loan.repayment_schedule
@@ -72,9 +72,9 @@ class TestLoan(unittest.TestCase):
loan.monthly_repayment_amount = 14000
loan.save()
- self.assertEquals(len(loan.repayment_schedule), 22)
- self.assertEquals(flt(loan.total_interest_payable, 0), 22712)
- self.assertEquals(flt(loan.total_payment, 0), 302712)
+ self.assertEqual(len(loan.repayment_schedule), 22)
+ self.assertEqual(flt(loan.total_interest_payable, 0), 22712)
+ self.assertEqual(flt(loan.total_payment, 0), 302712)
def test_loan_with_security(self):
@@ -89,7 +89,7 @@ class TestLoan(unittest.TestCase):
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods",
12, loan_application)
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
def test_loan_disbursement(self):
pledge = [{
@@ -102,7 +102,7 @@ class TestLoan(unittest.TestCase):
create_pledge(loan_application)
loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
loan.submit()
@@ -120,8 +120,8 @@ class TestLoan(unittest.TestCase):
filters = {'voucher_type': 'Loan Disbursement', 'voucher_no': loan_disbursement_entry2.name}
)
- self.assertEquals(loan.status, "Disbursed")
- self.assertEquals(loan.disbursed_amount, 1000000)
+ self.assertEqual(loan.status, "Disbursed")
+ self.assertEqual(loan.disbursed_amount, 1000000)
self.assertTrue(gl_entries1)
self.assertTrue(gl_entries2)
@@ -137,7 +137,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -156,15 +156,15 @@ class TestLoan(unittest.TestCase):
repayment_entry.submit()
penalty_amount = (accrued_interest_amount * 5 * 25) / 100
- self.assertEquals(flt(repayment_entry.penalty_amount,0), flt(penalty_amount, 0))
+ self.assertEqual(flt(repayment_entry.penalty_amount,0), flt(penalty_amount, 0))
amounts = frappe.db.get_all('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount'])
loan.load_from_db()
total_interest_paid = amounts[0]['paid_interest_amount'] + amounts[1]['paid_interest_amount']
- self.assertEquals(amounts[1]['paid_interest_amount'], repayment_entry.interest_payable)
- self.assertEquals(flt(loan.total_principal_paid, 0), flt(repayment_entry.amount_paid -
+ self.assertEqual(amounts[1]['paid_interest_amount'], repayment_entry.interest_payable)
+ self.assertEqual(flt(loan.total_principal_paid, 0), flt(repayment_entry.amount_paid -
penalty_amount - total_interest_paid, 0))
def test_loan_closure(self):
@@ -179,7 +179,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -204,12 +204,12 @@ class TestLoan(unittest.TestCase):
amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
- self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
- self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
+ self.assertEqual(flt(amount, 0),flt(accrued_interest_amount, 0))
+ self.assertEqual(flt(repayment_entry.penalty_amount, 5), 0)
request_loan_closure(loan.name)
loan.load_from_db()
- self.assertEquals(loan.status, "Loan Closure Requested")
+ self.assertEqual(loan.status, "Loan Closure Requested")
def test_loan_repayment_for_term_loan(self):
pledges = [{
@@ -241,8 +241,8 @@ class TestLoan(unittest.TestCase):
amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
'paid_principal_amount'])
- self.assertEquals(amounts[0], 11250.00)
- self.assertEquals(amounts[1], 78303.00)
+ self.assertEqual(amounts[0], 11250.00)
+ self.assertEqual(amounts[1], 78303.00)
def test_security_shortfall(self):
pledges = [{
@@ -268,17 +268,17 @@ class TestLoan(unittest.TestCase):
loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
self.assertTrue(loan_security_shortfall)
- self.assertEquals(loan_security_shortfall.loan_amount, 1000000.00)
- self.assertEquals(loan_security_shortfall.security_value, 800000.00)
- self.assertEquals(loan_security_shortfall.shortfall_amount, 600000.00)
+ self.assertEqual(loan_security_shortfall.loan_amount, 1000000.00)
+ self.assertEqual(loan_security_shortfall.security_value, 800000.00)
+ self.assertEqual(loan_security_shortfall.shortfall_amount, 600000.00)
frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
where loan_security='Test Security 2'""")
create_process_loan_security_shortfall()
loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
- self.assertEquals(loan_security_shortfall.status, "Completed")
- self.assertEquals(loan_security_shortfall.shortfall_amount, 0)
+ self.assertEqual(loan_security_shortfall.status, "Completed")
+ self.assertEqual(loan_security_shortfall.shortfall_amount, 0)
def test_loan_security_unpledge(self):
pledge = [{
@@ -292,7 +292,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -312,7 +312,7 @@ class TestLoan(unittest.TestCase):
request_loan_closure(loan.name)
loan.load_from_db()
- self.assertEquals(loan.status, "Loan Closure Requested")
+ self.assertEqual(loan.status, "Loan Closure Requested")
unpledge_request = unpledge_security(loan=loan.name, save=1)
unpledge_request.submit()
@@ -323,11 +323,11 @@ class TestLoan(unittest.TestCase):
pledged_qty = get_pledged_security_qty(loan.name)
self.assertEqual(loan.status, 'Closed')
- self.assertEquals(sum(pledged_qty.values()), 0)
+ self.assertEqual(sum(pledged_qty.values()), 0)
amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 5))
self.assertEqual(amounts['pending_principal_amount'], 0)
- self.assertEquals(amounts['payable_principal_amount'], 0.0)
+ self.assertEqual(amounts['payable_principal_amount'], 0.0)
self.assertEqual(amounts['interest_amount'], 0)
def test_partial_loan_security_unpledge(self):
@@ -346,7 +346,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -379,7 +379,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
unpledge_map = {'Test Security 1': 4000}
unpledge_request = unpledge_security(loan=loan.name, security_map = unpledge_map, save=1)
@@ -450,7 +450,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -475,7 +475,7 @@ class TestLoan(unittest.TestCase):
request_loan_closure(loan.name)
loan.load_from_db()
- self.assertEquals(loan.status, "Loan Closure Requested")
+ self.assertEqual(loan.status, "Loan Closure Requested")
amounts = calculate_amounts(loan.name, add_days(last_date, 5))
self.assertEqual(amounts['pending_principal_amount'], 0.0)
@@ -492,7 +492,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -533,8 +533,8 @@ class TestLoan(unittest.TestCase):
calculated_penalty_amount = frappe.db.get_value('Loan Interest Accrual',
{'process_loan_interest_accrual': process, 'loan': loan.name}, 'penalty_amount')
- self.assertEquals(loan.loan_amount, 1000000)
- self.assertEquals(calculated_penalty_amount, penalty_amount)
+ self.assertEqual(loan.loan_amount, 1000000)
+ self.assertEqual(calculated_penalty_amount, penalty_amount)
def test_penalty_repayment(self):
loan, dummy = create_loan_scenario_for_penalty(self)
@@ -547,13 +547,13 @@ class TestLoan(unittest.TestCase):
repayment_entry.submit()
amounts = calculate_amounts(loan.name, '2019-11-30 00:00:01')
- self.assertEquals(amounts['penalty_amount'], second_penalty)
+ self.assertEqual(amounts['penalty_amount'], second_penalty)
repayment_entry = create_repayment_entry(loan.name, self.applicant2, '2019-11-30 00:00:01', second_penalty)
repayment_entry.submit()
amounts = calculate_amounts(loan.name, '2019-11-30 00:00:02')
- self.assertEquals(amounts['penalty_amount'], 0)
+ self.assertEqual(amounts['penalty_amount'], 0)
def test_loan_write_off_limit(self):
pledge = [{
@@ -567,7 +567,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -589,15 +589,15 @@ class TestLoan(unittest.TestCase):
amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
- self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
- self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
+ self.assertEqual(flt(amount, 0),flt(accrued_interest_amount, 0))
+ self.assertEqual(flt(repayment_entry.penalty_amount, 5), 0)
amounts = calculate_amounts(loan.name, add_days(last_date, 5))
- self.assertEquals(flt(amounts['pending_principal_amount'], 0), 50)
+ self.assertEqual(flt(amounts['pending_principal_amount'], 0), 50)
request_loan_closure(loan.name)
loan.load_from_db()
- self.assertEquals(loan.status, "Loan Closure Requested")
+ self.assertEqual(loan.status, "Loan Closure Requested")
def test_loan_amount_write_off(self):
pledge = [{
@@ -611,7 +611,7 @@ class TestLoan(unittest.TestCase):
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -633,17 +633,17 @@ class TestLoan(unittest.TestCase):
amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
- self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
- self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
+ self.assertEqual(flt(amount, 0),flt(accrued_interest_amount, 0))
+ self.assertEqual(flt(repayment_entry.penalty_amount, 5), 0)
amounts = calculate_amounts(loan.name, add_days(last_date, 5))
- self.assertEquals(flt(amounts['pending_principal_amount'], 0), 100)
+ self.assertEqual(flt(amounts['pending_principal_amount'], 0), 100)
we = make_loan_write_off(loan.name, amount=amounts['pending_principal_amount'])
we.submit()
amounts = calculate_amounts(loan.name, add_days(last_date, 5))
- self.assertEquals(flt(amounts['pending_principal_amount'], 0), 0)
+ self.assertEqual(flt(amounts['pending_principal_amount'], 0), 0)
def create_loan_scenario_for_penalty(doc):
pledge = [{
diff --git a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
index a8753877a6..da56710c67 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
@@ -87,7 +87,7 @@ class TestLoanDisbursement(unittest.TestCase):
loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date='2019-10-01')
loan.submit()
- self.assertEquals(loan.loan_amount, 1000000)
+ self.assertEqual(loan.loan_amount, 1000000)
first_date = '2019-10-01'
last_date = '2019-10-30'
@@ -114,5 +114,5 @@ class TestLoanDisbursement(unittest.TestCase):
per_day_interest = get_per_day_interest(1500000, 13.5, '2019-10-30')
interest = per_day_interest * 15
- self.assertEquals(amounts['pending_principal_amount'], 1500000)
- self.assertEquals(amounts['interest_amount'], flt(interest + previous_interest, 2))
+ self.assertEqual(amounts['pending_principal_amount'], 1500000)
+ self.assertEqual(amounts['interest_amount'], flt(interest + previous_interest, 2))
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
index 85e008ac29..eb626f3eee 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
@@ -52,7 +52,7 @@ class TestLoanInterestAccrual(unittest.TestCase):
process_loan_interest_accrual_for_demand_loans(posting_date=last_date)
loan_interest_accural = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name})
- self.assertEquals(flt(loan_interest_accural.interest_amount, 0), flt(accrued_interest_amount, 0))
+ self.assertEqual(flt(loan_interest_accural.interest_amount, 0), flt(accrued_interest_amount, 0))
def test_accumulated_amounts(self):
pledge = [{
@@ -76,7 +76,7 @@ class TestLoanInterestAccrual(unittest.TestCase):
process_loan_interest_accrual_for_demand_loans(posting_date=last_date)
loan_interest_accrual = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name})
- self.assertEquals(flt(loan_interest_accrual.interest_amount, 0), flt(accrued_interest_amount, 0))
+ self.assertEqual(flt(loan_interest_accrual.interest_amount, 0), flt(accrued_interest_amount, 0))
next_start_date = '2019-10-31'
next_end_date = '2019-11-29'
@@ -90,4 +90,4 @@ class TestLoanInterestAccrual(unittest.TestCase):
loan_interest_accrual = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name,
'process_loan_interest_accrual': process})
- self.assertEquals(flt(loan_interest_accrual.total_pending_interest_amount, 0), total_pending_interest_amount)
+ self.assertEqual(flt(loan_interest_accrual.total_pending_interest_amount, 0), total_pending_interest_amount)
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index 7108338dab..e1cca9e3ef 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -223,7 +223,7 @@ class TestBOM(unittest.TestCase):
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
bom_items = sorted([d.item_code for d in bom.items if d.sourced_by_supplier != 1])
supplied_items = sorted([d.rm_item_code for d in po.supplied_items])
- self.assertEquals(bom_items, supplied_items)
+ self.assertEqual(bom_items, supplied_items)
def get_default_bom(item_code="_Test FG Item 2"):
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
index ac9a409bcb..80d1cdfc8f 100644
--- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
+++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
@@ -45,16 +45,16 @@ class TestBOMUpdateTool(unittest.TestCase):
else:
doc = frappe.get_doc("BOM", bom_no)
- self.assertEquals(doc.total_cost, 200)
+ self.assertEqual(doc.total_cost, 200)
frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 200)
update_cost()
doc.load_from_db()
- self.assertEquals(doc.total_cost, 300)
+ self.assertEqual(doc.total_cost, 300)
frappe.db.set_value("Item", "BOM Cost Test Item 2", "valuation_rate", 100)
update_cost()
doc.load_from_db()
- self.assertEquals(doc.total_cost, 200)
+ self.assertEqual(doc.total_cost, 200)
diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py
index 6b1fafe5f4..cb1ee92196 100644
--- a/erpnext/manufacturing/doctype/work_order/test_work_order.py
+++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py
@@ -473,7 +473,7 @@ class TestWorkOrder(unittest.TestCase):
def test_cost_center_for_manufacture(self):
wo_order = make_wo_order_test_record()
ste = make_stock_entry(wo_order.name, "Material Transfer for Manufacture", wo_order.qty)
- self.assertEquals(ste.get("items")[0].get("cost_center"), "_Test Cost Center - _TC")
+ self.assertEqual(ste.get("items")[0].get("cost_center"), "_Test Cost Center - _TC")
def test_operation_time_with_batch_size(self):
fg_item = "Test Batch Size Item For BOM"
@@ -539,11 +539,11 @@ class TestWorkOrder(unittest.TestCase):
ste_cancel_list.append(ste1)
ste3 = frappe.get_doc(make_stock_entry(wo_order.name, "Material Consumption for Manufacture", 2))
- self.assertEquals(ste3.fg_completed_qty, 2)
+ self.assertEqual(ste3.fg_completed_qty, 2)
expected_qty = {"_Test Item": 2, "_Test Item Home Desktop 100": 4}
for row in ste3.items:
- self.assertEquals(row.qty, expected_qty.get(row.item_code))
+ self.assertEqual(row.qty, expected_qty.get(row.item_code))
ste_cancel_list.reverse()
for ste_doc in ste_cancel_list:
ste_doc.cancel()
@@ -577,7 +577,7 @@ class TestWorkOrder(unittest.TestCase):
ste3 = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2))
for ste_row in ste3.items:
if itemwise_qty.get(ste_row.item_code) and ste_row.s_warehouse:
- self.assertEquals(ste_row.qty, itemwise_qty.get(ste_row.item_code) / 2)
+ self.assertEqual(ste_row.qty, itemwise_qty.get(ste_row.item_code) / 2)
ste3.submit()
ste_cancel_list.append(ste3)
@@ -585,7 +585,7 @@ class TestWorkOrder(unittest.TestCase):
ste2 = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2))
for ste_row in ste2.items:
if itemwise_qty.get(ste_row.item_code) and ste_row.s_warehouse:
- self.assertEquals(ste_row.qty, itemwise_qty.get(ste_row.item_code) / 2)
+ self.assertEqual(ste_row.qty, itemwise_qty.get(ste_row.item_code) / 2)
ste_cancel_list.reverse()
for ste_doc in ste_cancel_list:
ste_doc.cancel()
diff --git a/erpnext/non_profit/doctype/donation/test_donation.py b/erpnext/non_profit/doctype/donation/test_donation.py
index c6a534dac3..bbe9bf5228 100644
--- a/erpnext/non_profit/doctype/donation/test_donation.py
+++ b/erpnext/non_profit/doctype/donation/test_donation.py
@@ -39,7 +39,7 @@ class TestDonation(unittest.TestCase):
donation.on_payment_authorized()
donation.reload()
- self.assertEquals(donation.paid, 1)
+ self.assertEqual(donation.paid, 1)
self.assertTrue(frappe.db.exists('Payment Entry', {'reference_no': donation.name}))
diff --git a/erpnext/portal/doctype/homepage/test_homepage.py b/erpnext/portal/doctype/homepage/test_homepage.py
index bf5c4025a0..b717491a82 100644
--- a/erpnext/portal/doctype/homepage/test_homepage.py
+++ b/erpnext/portal/doctype/homepage/test_homepage.py
@@ -13,7 +13,7 @@ class TestHomepage(unittest.TestCase):
set_request(method='GET', path='home')
response = render()
- self.assertEquals(response.status_code, 200)
+ self.assertEqual(response.status_code, 200)
html = frappe.safe_decode(response.get_data())
self.assertTrue('
Date: Mon, 10 May 2021 11:19:19 +0530
Subject: [PATCH 041/262] chore(deps): [security] bump lodash from 4.17.19 to
4.17.21 (#25619)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21. **This update includes a security fix.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21)
Signed-off-by: dependabot-preview[bot]
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Ankush Menat
---
yarn.lock | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/yarn.lock b/yarn.lock
index 0a2ac1affc..635bb066ec 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2000,9 +2000,9 @@ lodash.values@^4.3.0:
integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=
lodash@^4.17.15:
- version "4.17.19"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
- integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^4.0.0:
version "4.1.0"
From 5ce2da8bed06978d2e1a25656136997b8f2ccbde Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 16:13:43 +0530
Subject: [PATCH 042/262] fix: Pass ORCHESTRATOR_URL via secrets
---
.github/workflows/server-tests.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index e7830c07f6..0acafcab43 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -76,6 +76,7 @@ jobs:
env:
TYPE: server
CI_BUILD_ID: ${{ github.run_id }}
+ ORCHESTRATOR_URL: ${{ secrets.ORCHESTRATOR_URL }}
- name: Upload Coverage Data
run: |
From a132de42ca37865175b722903871c3c367b68e48 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 17:25:21 +0530
Subject: [PATCH 043/262] fix: allow_zero_valuation_rate for rejected qty
---
.../doctype/purchase_invoice/test_purchase_invoice.py | 7 ++++---
.../doctype/stock_ledger_entry/test_stock_ledger_entry.py | 2 ++
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 66be11ff23..53db689c84 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -636,8 +636,8 @@ class TestPurchaseInvoice(unittest.TestCase):
def test_rejected_serial_no(self):
pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1,
- rejected_qty=1, rate=500, update_stock=1,
- rejected_warehouse = "_Test Rejected Warehouse - _TC")
+ rejected_qty=1, rate=500, update_stock=1, rejected_warehouse = "_Test Rejected Warehouse - _TC",
+ allow_zero_valuation_rate=1)
self.assertEqual(frappe.db.get_value("Serial No", pi.get("items")[0].serial_no, "warehouse"),
pi.get("items")[0].warehouse)
@@ -994,7 +994,8 @@ def make_purchase_invoice(**args):
"project": args.project,
"rejected_warehouse": args.rejected_warehouse or "",
"rejected_serial_no": args.rejected_serial_no or "",
- "asset_location": args.location or ""
+ "asset_location": args.location or "",
+ "allow_zero_valuation_rate": args.get("allow_zero_valuation_rate") or 0
})
if args.get_taxes_and_charges:
diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
index 3296f5ba4a..a1f1897041 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
@@ -15,10 +15,12 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu
from erpnext.stock.doctype.landed_cost_voucher.test_landed_cost_voucher import create_landed_cost_voucher
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import BackDatedStockTransaction
+from frappe.core.page.permission_manager.permission_manager import reset
class TestStockLedgerEntry(unittest.TestCase):
def setUp(self):
items = create_items()
+ reset('Stock Entry')
# delete SLE and BINs for all items
frappe.db.sql("delete from `tabStock Ledger Entry` where item_code in (%s)" % (', '.join(['%s']*len(items))), items)
From 4d6d5f4d893c8dd10c3e4cf9f7b01fbe648320f8 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 17:37:44 +0530
Subject: [PATCH 044/262] test: Fix valuation rate for raw materials
---
.../stock/doctype/purchase_receipt/test_purchase_receipt.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 78f77733a2..868e553dfc 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -240,6 +240,8 @@ class TestPurchaseReceipt(unittest.TestCase):
item_code = "Test Extra Item 1", qty=10, basic_rate=100)
se2 = make_stock_entry(target="_Test Warehouse - _TC",
item_code = "_Test FG Item", qty=1, basic_rate=100)
+ se3 = make_stock_entry(target="_Test Warehouse - _TC",
+ item_code = "Test Extra Item 2", qty=1, basic_rate=100)
rm_items = [
{
"item_code": item_code,
@@ -274,6 +276,7 @@ class TestPurchaseReceipt(unittest.TestCase):
se.cancel()
se1.cancel()
se2.cancel()
+ se3.cancel()
po.reload()
po.cancel()
From 018ccc2b6d1eb4d0844966f67fc166f26cbfcf19 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 18:01:53 +0530
Subject: [PATCH 045/262] test: Fix test name
- Rename TestSubcontractedItemToBeReceived > TestSubcontractedItemToBeTransferred
---
...t_subcontracted_raw_materials_to_be_transferred.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
index 6900938236..c1fc6fb82f 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
@@ -9,12 +9,12 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.buying.report.subcontracted_raw_materials_to_be_transferred.subcontracted_raw_materials_to_be_transferred import execute
import json, frappe, unittest
-class TestSubcontractedItemToBeReceived(unittest.TestCase):
+class TestSubcontractedItemToBeTransferred(unittest.TestCase):
- def test_pending_and_received_qty(self):
+ def test_pending_and_transferred_qty(self):
po = create_purchase_order(item_code='_Test FG Item', is_subcontracted='Yes')
- make_stock_entry(item_code='_Test Item', target='_Test Warehouse 1 - _TC', qty=100, basic_rate=100)
- make_stock_entry(item_code='_Test Item Home Desktop 100', target='_Test Warehouse 1 - _TC', qty=100, basic_rate=100)
+ make_stock_entry(item_code='_Test Item', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
+ make_stock_entry(item_code='_Test Item Home Desktop 100', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
transfer_subcontracted_raw_materials(po.name)
col, data = execute(filters=frappe._dict({'supplier': po.supplier,
'from_date': frappe.utils.get_datetime(frappe.utils.add_to_date(po.transaction_date, days=-10)),
@@ -38,7 +38,8 @@ def transfer_subcontracted_raw_materials(po):
'warehouse': '_Test Warehouse - _TC', 'rate': 100, 'amount': 200, 'stock_uom': 'Nos'}]
rm_item_string = json.dumps(rm_item)
se = frappe.get_doc(make_rm_stock_entry(po, rm_item_string))
+ se.from_warehouse = '_Test Warehouse 1 - _TC'
se.to_warehouse = '_Test Warehouse 1 - _TC'
se.stock_entry_type = 'Send to Subcontractor'
se.save()
- se.submit()
\ No newline at end of file
+ se.submit()
From 404e7d07c57da2de4ec65cf9aa44763787c64008 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 18:39:09 +0530
Subject: [PATCH 046/262] test: Fix permission error
---
.../doctype/stock_ledger_entry/test_stock_ledger_entry.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
index a1f1897041..ba31ad7b06 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
@@ -316,10 +316,11 @@ class TestStockLedgerEntry(unittest.TestCase):
# Set User with Stock User role but not Stock Manager
try:
user = frappe.get_doc("User", "test@example.com")
- frappe.set_user(user.name)
user.add_roles("Stock User")
user.remove_roles("Stock Manager")
+ frappe.set_user(user.name)
+
stock_entry_on_today = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
back_dated_se_1 = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100,
posting_date=add_days(today(), -1), do_not_submit=True)
From a13c453c695f971c42cab5944dacfab17ab8d181 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 20:33:47 +0530
Subject: [PATCH 047/262] test: Fix a case where test used to fail due to
holiday list
- fixes: "Please set a default Holiday List for Employee EMP-00009 or Company Wind Power LLC" error
---
.../hr/doctype/upload_attendance/test_upload_attendance.py | 7 +++++++
.../payroll/doctype/payroll_entry/test_payroll_entry.py | 6 ++++++
2 files changed, 13 insertions(+)
diff --git a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
index 6e151d0e3c..03b0cf3da2 100644
--- a/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
+++ b/erpnext/hr/doctype/upload_attendance/test_upload_attendance.py
@@ -5,11 +5,18 @@ from __future__ import unicode_literals
import frappe
import unittest
+import erpnext
from frappe.utils import getdate
from erpnext.hr.doctype.upload_attendance.upload_attendance import get_data
from erpnext.hr.doctype.employee.test_employee import make_employee
+test_dependencies = ['Holiday List']
+
class TestUploadAttendance(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", '_Test Holiday List')
+
def test_date_range(self):
employee = make_employee("test_employee@company.com")
employee_doc = frappe.get_doc("Employee", employee)
diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
index 7528bf7a7f..b80b32061f 100644
--- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
@@ -15,7 +15,13 @@ from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_
from erpnext.loan_management.doctype.loan.test_loan import create_loan, make_loan_disbursement_entry, create_loan_type, create_loan_accounts
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
+test_dependencies = ['Holiday List']
+
class TestPayrollEntry(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ frappe.db.set_value("Company", erpnext.get_default_company(), "default_holiday_list", '_Test Holiday List')
+
def setUp(self):
for dt in ["Salary Slip", "Salary Component", "Salary Component Account",
"Payroll Entry", "Salary Structure", "Salary Structure Assignment", "Payroll Employee Detail", "Additional Salary"]:
From b3fadebb419ecc17fe2799a9ac0fdbd063e9b374 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 20:49:07 +0530
Subject: [PATCH 048/262] style: Fix sider issues
---
.../test_accounting_period.py | 2 +-
.../test_leave_application.py | 60 +++++++++----------
.../leave_encashment/test_leave_encashment.py | 2 +-
3 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
index 3b4f138495..dc472c7695 100644
--- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py
@@ -40,7 +40,7 @@ def create_accounting_period(**args):
accounting_period.start_date = args.start_date or nowdate()
accounting_period.end_date = args.end_date or add_months(nowdate(), 1)
accounting_period.company = args.company or "_Test Company"
- accounting_period.period_name = args.period_name or "_Test_Period_Name_1"
+ accounting_period.period_name = args.period_name or "_Test_Period_Name_1"
accounting_period.append("closed_documents", {
"document_type": 'Sales Invoice', "closed": 1
})
diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py
index a9379e230b..a4a96b813e 100644
--- a/erpnext/hr/doctype/leave_application/test_leave_application.py
+++ b/erpnext/hr/doctype/leave_application/test_leave_application.py
@@ -16,36 +16,36 @@ from erpnext.hr.doctype.employee.test_employee import make_employee
test_dependencies = ["Leave Allocation", "Leave Block List", "Employee"]
_test_records = [
- {
- "company": "_Test Company",
- "doctype": "Leave Application",
- "employee": "_T-Employee-00001",
- "from_date": "2013-05-01",
- "description": "_Test Reason",
- "leave_type": "_Test Leave Type",
- "posting_date": "2013-01-02",
- "to_date": "2013-05-05"
- },
- {
- "company": "_Test Company",
- "doctype": "Leave Application",
- "employee": "_T-Employee-00002",
- "from_date": "2013-05-01",
- "description": "_Test Reason",
- "leave_type": "_Test Leave Type",
- "posting_date": "2013-01-02",
- "to_date": "2013-05-05"
- },
- {
- "company": "_Test Company",
- "doctype": "Leave Application",
- "employee": "_T-Employee-00001",
- "from_date": "2013-01-15",
- "description": "_Test Reason",
- "leave_type": "_Test Leave Type LWP",
- "posting_date": "2013-01-02",
- "to_date": "2013-01-15"
- }
+ {
+ "company": "_Test Company",
+ "doctype": "Leave Application",
+ "employee": "_T-Employee-00001",
+ "from_date": "2013-05-01",
+ "description": "_Test Reason",
+ "leave_type": "_Test Leave Type",
+ "posting_date": "2013-01-02",
+ "to_date": "2013-05-05"
+ },
+ {
+ "company": "_Test Company",
+ "doctype": "Leave Application",
+ "employee": "_T-Employee-00002",
+ "from_date": "2013-05-01",
+ "description": "_Test Reason",
+ "leave_type": "_Test Leave Type",
+ "posting_date": "2013-01-02",
+ "to_date": "2013-05-05"
+ },
+ {
+ "company": "_Test Company",
+ "doctype": "Leave Application",
+ "employee": "_T-Employee-00001",
+ "from_date": "2013-01-15",
+ "description": "_Test Reason",
+ "leave_type": "_Test Leave Type LWP",
+ "posting_date": "2013-01-02",
+ "to_date": "2013-01-15"
+ }
]
diff --git a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
index 1f7fb6e68a..e0ffa5dd41 100644
--- a/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
+++ b/erpnext/hr/doctype/leave_encashment/test_leave_encashment.py
@@ -91,7 +91,7 @@ class TestLeaveEncashment(unittest.TestCase):
self.assertEqual(len(leave_ledger_entry), 1)
self.assertEqual(leave_ledger_entry[0].employee, leave_encashment.employee)
self.assertEqual(leave_ledger_entry[0].leave_type, leave_encashment.leave_type)
- self.assertEqual(leave_ledger_entry[0].leaves, leave_encashment.encashable_days * -1)
+ self.assertEqual(leave_ledger_entry[0].leaves, leave_encashment.encashable_days * -1)
# check if leave ledger entry is deleted on cancellation
From 6408367285f2912e7ecff57401d747e1bdd3a647 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Mon, 10 May 2021 23:48:37 +0530
Subject: [PATCH 049/262] ci: Add test orchestrator URL
---
.github/workflows/server-tests.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 0acafcab43..bd60081064 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -76,7 +76,7 @@ jobs:
env:
TYPE: server
CI_BUILD_ID: ${{ github.run_id }}
- ORCHESTRATOR_URL: ${{ secrets.ORCHESTRATOR_URL }}
+ ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
- name: Upload Coverage Data
run: |
@@ -87,7 +87,6 @@ jobs:
coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
COVERALLS_FLAG_NAME: run-${{ matrix.container }}
COVERALLS_SERVICE_NAME: ${{ github.event_name == 'pull_request' && 'github' || 'github-actions' }}
COVERALLS_PARALLEL: true
From 042118aafdd7e018d0ddedefb90ce66c30753634 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Tue, 11 May 2021 10:09:06 +0530
Subject: [PATCH 050/262] ci: Use only 3 containers for now
---
.github/workflows/server-tests.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index bd60081064..6597048bc7 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -10,7 +10,7 @@ jobs:
fail-fast: false
matrix:
- container: [1, 2, 3, 4]
+ container: [1, 2, 3]
name: Server Tests
From b76ebb3f4b0b4f4a975aff0fccfbc0d5c4c81e1e Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Tue, 11 May 2021 10:59:16 +0530
Subject: [PATCH 051/262] fix: Use frappe.safe_eval instead of eval
---
erpnext/setup/doctype/email_digest/email_digest.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py
index 5db54eeee1..340d89bdf8 100644
--- a/erpnext/setup/doctype/email_digest/email_digest.py
+++ b/erpnext/setup/doctype/email_digest/email_digest.py
@@ -249,7 +249,7 @@ class EmailDigest(Document):
card = cache.get(cache_key)
if card:
- card = eval(card)
+ card = frappe.safe_eval(card)
else:
card = frappe._dict(getattr(self, "get_" + key)())
From af8436d0dce52fc1e9c302c2110cce88f4e7f289 Mon Sep 17 00:00:00 2001
From: Mohammad Hasnain Mohsin Rajan
Date: Wed, 12 May 2021 13:01:03 +0530
Subject: [PATCH 052/262] fix: change links in workspace (#25670)
---
.../workspace/accounting/accounting.json | 29 ++++---------------
1 file changed, 5 insertions(+), 24 deletions(-)
diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json
index 9ffa481c1c..df68318052 100644
--- a/erpnext/accounts/workspace/accounting/accounting.json
+++ b/erpnext/accounts/workspace/accounting/accounting.json
@@ -15,6 +15,7 @@
"hide_custom": 0,
"icon": "accounting",
"idx": 0,
+ "is_default": 0,
"is_standard": 1,
"label": "Accounting",
"links": [
@@ -625,9 +626,9 @@
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
- "label": "Bank Reconciliation",
- "link_to": "bank-reconciliation",
- "link_type": "Page",
+ "label": "Bank Reconciliation Tool",
+ "link_to": "Bank Reconciliation Tool",
+ "link_type": "DocType",
"onboard": 0,
"type": "Link"
},
@@ -641,26 +642,6 @@
"onboard": 0,
"type": "Link"
},
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Bank Statement Transaction Entry",
- "link_to": "Bank Statement Transaction Entry",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Bank Statement Settings",
- "link_to": "Bank Statement Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
{
"hidden": 0,
"is_query_report": 0,
@@ -1071,7 +1052,7 @@
"type": "Link"
}
],
- "modified": "2021-03-04 00:38:35.349024",
+ "modified": "2021-05-12 11:48:01.905144",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",
From dd1822ef58dc24f32d5bf62d634c886a50d7a386 Mon Sep 17 00:00:00 2001
From: Mohammad Hasnain Mohsin Rajan
Date: Wed, 12 May 2021 13:01:53 +0530
Subject: [PATCH 053/262] fix: change links in workspace (#25673)
---
.../workspace/accounting/accounting.json | 29 ++++---------------
1 file changed, 5 insertions(+), 24 deletions(-)
diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json
index 9ffa481c1c..df68318052 100644
--- a/erpnext/accounts/workspace/accounting/accounting.json
+++ b/erpnext/accounts/workspace/accounting/accounting.json
@@ -15,6 +15,7 @@
"hide_custom": 0,
"icon": "accounting",
"idx": 0,
+ "is_default": 0,
"is_standard": 1,
"label": "Accounting",
"links": [
@@ -625,9 +626,9 @@
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
- "label": "Bank Reconciliation",
- "link_to": "bank-reconciliation",
- "link_type": "Page",
+ "label": "Bank Reconciliation Tool",
+ "link_to": "Bank Reconciliation Tool",
+ "link_type": "DocType",
"onboard": 0,
"type": "Link"
},
@@ -641,26 +642,6 @@
"onboard": 0,
"type": "Link"
},
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Bank Statement Transaction Entry",
- "link_to": "Bank Statement Transaction Entry",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Bank Statement Settings",
- "link_to": "Bank Statement Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
{
"hidden": 0,
"is_query_report": 0,
@@ -1071,7 +1052,7 @@
"type": "Link"
}
],
- "modified": "2021-03-04 00:38:35.349024",
+ "modified": "2021-05-12 11:48:01.905144",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",
From aaca8335f080dca5078d90212bd810ced5f56d84 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Wed, 12 May 2021 16:36:25 +0530
Subject: [PATCH 054/262] fix: updated modified time to pull new fields
---
erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 24e67febca..d3d3ffa17f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -1380,7 +1380,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2021-03-30 22:45:58.334107",
+ "modified": "2021-04-30 22:45:58.334107",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
From 6578c045ca3d7cb40481caf0b4239420d5ab5cbb Mon Sep 17 00:00:00 2001
From: Afshan <33727827+AfshanKhan@users.noreply.github.com>
Date: Wed, 12 May 2021 17:41:50 +0530
Subject: [PATCH 055/262] fix: Dialog variable assignment after definition in
POS (#25680)
---
erpnext/selling/page/point_of_sale/pos_controller.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/erpnext/selling/page/point_of_sale/pos_controller.js b/erpnext/selling/page/point_of_sale/pos_controller.js
index 8e0a1e1c18..4f4f1b2240 100644
--- a/erpnext/selling/page/point_of_sale/pos_controller.js
+++ b/erpnext/selling/page/point_of_sale/pos_controller.js
@@ -56,10 +56,6 @@ erpnext.PointOfSale.Controller = class {
dialog.fields_dict.balance_details.grid.refresh();
});
}
- const pos_profile_query = {
- query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
- filters: { company: dialog.fields_dict.company.get_value() }
- }
const dialog = new frappe.ui.Dialog({
title: __('Create POS Opening Entry'),
static: true,
@@ -105,6 +101,10 @@ erpnext.PointOfSale.Controller = class {
primary_action_label: __('Submit')
});
dialog.show();
+ const pos_profile_query = {
+ query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query',
+ filters: { company: dialog.fields_dict.company.get_value() }
+ };
}
async prepare_app_defaults(data) {
From 1f025a84f54669ff6301bca60aa04001f18a5c59 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Wed, 12 May 2021 18:14:22 +0530
Subject: [PATCH 056/262] ci: Update frappe branch
---
.github/helper/install.sh | 2 +-
.github/workflows/server-tests.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index 44659f22fa..7b0f944c66 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -12,7 +12,7 @@ sudo apt install npm
pip install frappe-bench
-git clone https://github.com/surajshetty3416/frappe --branch "python-distributed-testing" --depth 1
+git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
mkdir ~/frappe-bench/sites/test_site
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 6597048bc7..6f831ac3d1 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -12,7 +12,7 @@ jobs:
matrix:
container: [1, 2, 3]
- name: Server Tests
+ name: Python Unit Tests
services:
mysql:
From fe68a0ff80c8d807a5886d46f2d51ad33e6949f1 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Wed, 12 May 2021 19:42:04 +0530
Subject: [PATCH 057/262] fix: Woocommerce order sync issue
---
.../connectors/woocommerce_connection.py | 30 +++++++++----------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
index 6dedaa8c53..a505ee09d2 100644
--- a/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
+++ b/erpnext/erpnext_integrations/connectors/woocommerce_connection.py
@@ -1,6 +1,7 @@
from __future__ import unicode_literals
import frappe, base64, hashlib, hmac, json
+from frappe.utils import cstr
from frappe import _
def verify_request():
@@ -146,22 +147,19 @@ def rename_address(address, customer):
def link_items(items_list, woocommerce_settings, sys_lang):
for item_data in items_list:
- item_woo_com_id = item_data.get("product_id")
+ item_woo_com_id = cstr(item_data.get("product_id"))
- if frappe.get_value("Item", {"woocommerce_id": item_woo_com_id}):
- #Edit Item
- item = frappe.get_doc("Item", {"woocommerce_id": item_woo_com_id})
- else:
+ if not frappe.db.get_value("Item", {"woocommerce_id": item_woo_com_id}, 'name'):
#Create Item
item = frappe.new_doc("Item")
+ item.item_code = _("woocommerce - {0}", sys_lang).format(item_woo_com_id)
+ item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang)
+ item.item_group = _("WooCommerce Products", sys_lang)
- item.item_name = item_data.get("name")
- item.item_code = _("woocommerce - {0}", sys_lang).format(item_data.get("product_id"))
- item.woocommerce_id = item_data.get("product_id")
- item.item_group = _("WooCommerce Products", sys_lang)
- item.stock_uom = woocommerce_settings.uom or _("Nos", sys_lang)
- item.flags.ignore_mandatory = True
- item.save()
+ item.item_name = item_data.get("name")
+ item.woocommerce_id = item_woo_com_id
+ item.flags.ignore_mandatory = True
+ item.save()
def create_sales_order(order, woocommerce_settings, customer_name, sys_lang):
new_sales_order = frappe.new_doc("Sales Order")
@@ -194,12 +192,12 @@ def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_l
for item in order.get("line_items"):
woocomm_item_id = item.get("product_id")
- found_item = frappe.get_doc("Item", {"woocommerce_id": woocomm_item_id})
+ found_item = frappe.get_doc("Item", {"woocommerce_id": cstr(woocomm_item_id)})
ordered_items_tax = item.get("total_tax")
- new_sales_order.append("items",{
- "item_code": found_item.item_code,
+ new_sales_order.append("items", {
+ "item_code": found_item.name,
"item_name": found_item.item_name,
"description": found_item.item_name,
"delivery_date": new_sales_order.delivery_date,
@@ -207,7 +205,7 @@ def set_items_in_sales_order(new_sales_order, woocommerce_settings, order, sys_l
"qty": item.get("quantity"),
"rate": item.get("price"),
"warehouse": woocommerce_settings.warehouse or default_warehouse
- })
+ })
add_tax_details(new_sales_order, ordered_items_tax, "Ordered Item tax", woocommerce_settings.tax_account)
From 28fdb2e6fae00abae6df5df5e3dbe4fba0430f31 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Wed, 12 May 2021 23:13:11 +0530
Subject: [PATCH 058/262] ci: Update Python version to 3.7
---
.github/workflows/server-tests.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 6f831ac3d1..92685e2177 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -30,7 +30,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
- python-version: 3.6
+ python-version: 3.7
- name: Add to Hosts
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
From c55aa295fcfc90dd79a72cd38db4396e8f1f4485 Mon Sep 17 00:00:00 2001
From: David Angulo
Date: Thu, 13 May 2021 01:46:04 -0500
Subject: [PATCH 059/262] fix: Translate weekday when getting weekly off dates
(#25691)
---
erpnext/hr/doctype/holiday_list/holiday_list.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/hr/doctype/holiday_list/holiday_list.py b/erpnext/hr/doctype/holiday_list/holiday_list.py
index 8af8cea605..f65e6e1207 100644
--- a/erpnext/hr/doctype/holiday_list/holiday_list.py
+++ b/erpnext/hr/doctype/holiday_list/holiday_list.py
@@ -23,7 +23,7 @@ class HolidayList(Document):
last_idx = max([cint(d.idx) for d in self.get("holidays")] or [0,])
for i, d in enumerate(date_list):
ch = self.append('holidays', {})
- ch.description = self.weekly_off
+ ch.description = _(self.weekly_off)
ch.holiday_date = d
ch.weekly_off = 1
ch.idx = last_idx + i + 1
From 0eb3a38c9d9fc0094183259b9950ae03b9c727c8 Mon Sep 17 00:00:00 2001
From: Prssanna Desai
Date: Thu, 13 May 2021 12:17:28 +0530
Subject: [PATCH 060/262] fix: quiz evalutation issue (#25671)
---
erpnext/public/js/education/lms/quiz.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/public/js/education/lms/quiz.js b/erpnext/public/js/education/lms/quiz.js
index 32fa4ab1ec..5683f73d1b 100644
--- a/erpnext/public/js/education/lms/quiz.js
+++ b/erpnext/public/js/education/lms/quiz.js
@@ -118,7 +118,7 @@ class Quiz {
quiz_response: this.get_selected(),
course: this.course,
program: this.program,
- time_taken: this.is_time_bound ? this.time_taken : ""
+ time_taken: this.is_time_bound ? this.time_taken : 0
}).then(res => {
this.submit_btn.remove()
if (!res.message) {
From ab1ae418ccac57709c6feb4b0f53375eba271997 Mon Sep 17 00:00:00 2001
From: Anuja P
Date: Thu, 13 May 2021 14:26:27 +0530
Subject: [PATCH 061/262] fix: Process SOA enhancement
---
.../process_statement_of_accounts.html | 118 +++++++++++-------
.../process_statement_of_accounts.json | 19 ++-
.../process_statement_of_accounts.py | 8 +-
3 files changed, 93 insertions(+), 52 deletions(-)
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
index b623898829..b3aca53139 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
@@ -1,24 +1,43 @@
-{{ filters.party[0] }}
-{{ _("Statement of Accounts") }}
+
+
+
-
- {{ frappe.format(filters.from_date, 'Date')}}
- {{ _("to") }}
- {{ frappe.format(filters.to_date, 'Date')}}
-
+
{{ _("STATEMENTS OF ACCOUNTS") }}
+
+
{{ _("Customer: ") }} {{filters.party[0] }}
+
+ {{ _("Date: ") }}
+ {{ frappe.format(filters.from_date, 'Date')}}
+ {{ _("to") }}
+ {{ frappe.format(filters.to_date, 'Date')}}
+
+
+
-
-
-
- {{ _("Date") }} |
- {{ _("Ref") }} |
- {{ _("Party") }} |
- {{ _("Debit") }} |
- {{ _("Credit") }} |
- {{ _("Balance (Dr - Cr)") }} |
-
-
-
+
+
+
+ {{ _("Date") }} |
+ {{ _("Reference") }} |
+ {{ _("Remarks") }} |
+ {{ _("Debit") }} |
+ {{ _("Credit") }} |
+ {{ _("Balance (Dr - Cr)") }} |
+
+
+
{% for row in data %}
{% if(row.posting_date) %}
@@ -58,32 +77,35 @@
{% endfor %}
-
-
-{% if aging %}
-{{ _("Ageing Report Based On ") }} {{ aging.ageing_based_on }}
-
- {{ _("Up to " ) }} {{ frappe.format(filters.to_date, 'Date')}}
-
-
-
-
-
-
- 30 Days |
- 60 Days |
- 90 Days |
- 120 Days |
-
-
-
-
- {{ frappe.utils.fmt_money(aging.range1, currency=filters.presentation_currency) }} |
- {{ frappe.utils.fmt_money(aging.range2, currency=filters.presentation_currency) }} |
- {{ frappe.utils.fmt_money(aging.range3, currency=filters.presentation_currency) }} |
- {{ frappe.utils.fmt_money(aging.range4, currency=filters.presentation_currency) }} |
-
-
-
-{% endif %}
-Printed On {{ frappe.format(frappe.utils.get_datetime(), 'Datetime') }}
\ No newline at end of file
+
+
+ {% if aging %}
+
{{ _("Ageing Report based on ") }} {{ aging.ageing_based_on }}
+ {{ _("up to " ) }} {{ frappe.format(filters.to_date, 'Date')}}
+
+
+
+
+ 30 Days |
+ 60 Days |
+ 90 Days |
+ 120 Days |
+
+
+
+
+ {{ frappe.utils.fmt_money(aging.range1, currency=filters.presentation_currency) }} |
+ {{ frappe.utils.fmt_money(aging.range2, currency=filters.presentation_currency) }} |
+ {{ frappe.utils.fmt_money(aging.range3, currency=filters.presentation_currency) }} |
+ {{ frappe.utils.fmt_money(aging.range4, currency=filters.presentation_currency) }} |
+
+
+
+ {% endif %}
+
+ {% if terms_and_conditions %}
+
+ {{ terms_and_conditions }}
+
+ {% endif %}
+
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
index 4be0e2ec06..922f6367df 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
@@ -1,6 +1,5 @@
{
"actions": [],
- "allow_workflow": 1,
"autoname": "Prompt",
"creation": "2020-05-22 16:46:18.712954",
"doctype": "DocType",
@@ -28,9 +27,11 @@
"customers",
"preferences",
"orientation",
- "section_break_14",
"include_ageing",
"ageing_based_on",
+ "section_break_14",
+ "letter_head",
+ "terms_and_conditions",
"section_break_1",
"enable_auto_email",
"section_break_18",
@@ -270,10 +271,22 @@
"fieldname": "body",
"fieldtype": "Text Editor",
"label": "Body"
+ },
+ {
+ "fieldname": "letter_head",
+ "fieldtype": "Link",
+ "label": "Letter Head",
+ "options": "Letter Head"
+ },
+ {
+ "fieldname": "terms_and_conditions",
+ "fieldtype": "Link",
+ "label": "Terms and Conditions",
+ "options": "Terms and Conditions"
}
],
"links": [],
- "modified": "2020-08-08 08:47:09.185728",
+ "modified": "2021-05-13 12:44:19.574844",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Statement Of Accounts",
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
index b6149e89f5..c388669592 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -62,6 +62,9 @@ def get_report_pdf(doc, consolidated=True):
tax_id = frappe.get_doc('Customer', entry.customer).tax_id
presentation_currency = get_party_account_currency('Customer', entry.customer, doc.company) \
or doc.currency or get_company_currency(doc.company)
+ if doc.letter_head:
+ from frappe.www.printview import get_letter_head
+ letter_head = get_letter_head(doc, 0)
filters= frappe._dict({
'from_date': doc.from_date,
@@ -88,7 +91,10 @@ def get_report_pdf(doc, consolidated=True):
if len(res) == 3:
continue
html = frappe.render_template(template_path, \
- {"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None})
+ {"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None,
+ "letter_head": letter_head if doc.letter_head else None,
+ "terms_and_conditions": frappe.db.get_value('Terms and Conditions', doc.terms_and_conditions, 'terms')
+ if doc.terms_and_conditions else None})
html = frappe.render_template(base_template_path, {"body": html, \
"css": get_print_style(), "title": "Statement For " + entry.customer})
statement_dict[entry.customer] = html
From e90a2a346b9de9efe1a0abd13c804568dfc27343 Mon Sep 17 00:00:00 2001
From: Anuja P
Date: Thu, 13 May 2021 15:15:47 +0530
Subject: [PATCH 062/262] fix: update new changes
---
.../process_statement_of_accounts.html | 12 ++++++------
.../process_statement_of_accounts.py | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
index f44d595332..db1fea192e 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
@@ -79,8 +79,8 @@
- {% if aging %}
- {{ _("Ageing Report based on ") }} {{ aging.ageing_based_on }}
+ {% if ageing %}
+ {{ _("Ageing Report based on ") }} {{ ageing.ageing_based_on }}
{{ _("up to " ) }} {{ frappe.format(filters.to_date, 'Date')}}
@@ -94,10 +94,10 @@
- {{ frappe.utils.fmt_money(aging.range1, currency=filters.presentation_currency) }} |
- {{ frappe.utils.fmt_money(aging.range2, currency=filters.presentation_currency) }} |
- {{ frappe.utils.fmt_money(aging.range3, currency=filters.presentation_currency) }} |
- {{ frappe.utils.fmt_money(aging.range4, currency=filters.presentation_currency) }} |
+ {{ frappe.utils.fmt_money(ageing.range1, currency=filters.presentation_currency) }} |
+ {{ frappe.utils.fmt_money(ageing.range2, currency=filters.presentation_currency) }} |
+ {{ frappe.utils.fmt_money(ageing.range3, currency=filters.presentation_currency) }} |
+ {{ frappe.utils.fmt_money(ageing.range4, currency=filters.presentation_currency) }} |
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
index 01157d6eaf..cf79c03935 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -94,7 +94,7 @@ def get_report_pdf(doc, consolidated=True):
continue
html = frappe.render_template(template_path, \
- {"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None,
+ {"filters": filters, "data": res, "ageing": ageing[0] if doc.include_ageing else None,
"letter_head": letter_head if doc.letter_head else None,
"terms_and_conditions": frappe.db.get_value('Terms and Conditions', doc.terms_and_conditions, 'terms')
if doc.terms_and_conditions else None})
From 8e748f8451db11e08cc0a920e1d0eea7c75e6a56 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 13 May 2021 14:59:28 +0530
Subject: [PATCH 063/262] fix: Parameter for
get_filtered_list_for_consolidated_report in consolidated balance sheet
---
erpnext/accounts/report/balance_sheet/balance_sheet.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py
index 287b8a7484..26bb44f4f7 100644
--- a/erpnext/accounts/report/balance_sheet/balance_sheet.py
+++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py
@@ -135,7 +135,7 @@ def get_report_summary(period_list, asset, liability, equity, provisional_profit
# from consolidated financial statement
if filters.get('accumulated_in_group_company'):
- period_list = get_filtered_list_for_consolidated_report(period_list)
+ period_list = get_filtered_list_for_consolidated_report(filters, period_list)
for period in period_list:
key = period if consolidated else period.key
From 7c6de1a8ac2ec818a796fe54268d0650d71ffb9b Mon Sep 17 00:00:00 2001
From: Mohammad Hasnain Mohsin Rajan
Date: Thu, 13 May 2021 17:28:49 +0530
Subject: [PATCH 064/262] fix: bank statement import via google sheet (#25677)
* fix: change links in workspace
* fix: google sheet bank statement import
* chore: quotes
* fix: capitalization
* fix: typo
* chore: add translation
---
.../bank_statement_import.js | 1 +
.../bank_statement_import.json | 6 +++---
.../bank_statement_import.py | 18 ++++++++++++++----
3 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
index 3dbd605344..016f29a7b5 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
@@ -239,6 +239,7 @@ frappe.ui.form.on("Bank Statement Import", {
"withdrawal",
"description",
"reference_number",
+ "bank_account"
],
},
});
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json
index 5e913cc2aa..7ffff02850 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json
@@ -146,7 +146,7 @@
},
{
"depends_on": "eval:!doc.__islocal && !doc.import_file\n",
- "description": "Must be a publicly accessible Google Sheets URL",
+ "description": "Must be a publicly accessible Google Sheets URL and adding Bank Account column is necessary for importing via Google Sheets",
"fieldname": "google_sheets_url",
"fieldtype": "Data",
"label": "Import from Google Sheets"
@@ -202,7 +202,7 @@
],
"hide_toolbar": 1,
"links": [],
- "modified": "2021-02-10 19:29:59.027325",
+ "modified": "2021-05-12 14:17:37.777246",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Statement Import",
@@ -224,4 +224,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
-}
\ No newline at end of file
+}
diff --git a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py
index 9f41b13f4b..5f110e2727 100644
--- a/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py
+++ b/erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py
@@ -47,6 +47,13 @@ class BankStatementImport(DataImport):
def start_import(self):
+ preview = frappe.get_doc("Bank Statement Import", self.name).get_preview_from_template(
+ self.import_file, self.google_sheets_url
+ )
+
+ if 'Bank Account' not in json.dumps(preview):
+ frappe.throw(_("Please add the Bank Account column"))
+
from frappe.core.page.background_jobs.background_jobs import get_info
from frappe.utils.scheduler import is_scheduler_inactive
@@ -67,6 +74,7 @@ class BankStatementImport(DataImport):
data_import=self.name,
bank_account=self.bank_account,
import_file_path=self.import_file,
+ google_sheets_url=self.google_sheets_url,
bank=self.bank,
template_options=self.template_options,
now=frappe.conf.developer_mode or frappe.flags.in_test,
@@ -90,18 +98,20 @@ def download_errored_template(data_import_name):
data_import = frappe.get_doc("Bank Statement Import", data_import_name)
data_import.export_errored_rows()
-def start_import(data_import, bank_account, import_file_path, bank, template_options):
+def start_import(data_import, bank_account, import_file_path, google_sheets_url, bank, template_options):
"""This method runs in background job"""
update_mapping_db(bank, template_options)
data_import = frappe.get_doc("Bank Statement Import", data_import)
+ file = import_file_path if import_file_path else google_sheets_url
- import_file = ImportFile("Bank Transaction", file = import_file_path, import_type="Insert New Records")
+ import_file = ImportFile("Bank Transaction", file = file, import_type="Insert New Records")
data = import_file.raw_data
- add_bank_account(data, bank_account)
- write_files(import_file, data)
+ if import_file_path:
+ add_bank_account(data, bank_account)
+ write_files(import_file, data)
try:
i = Importer(data_import.reference_doctype, data_import=data_import)
From aca8c34c4dfb8e9e8b97b5f5130f884dab266b34 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Thu, 13 May 2021 12:11:41 +0000
Subject: [PATCH 065/262] fix: filter for Indian workspace card
---
erpnext/accounts/workspace/accounting/accounting.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json
index df68318052..27c55cc176 100644
--- a/erpnext/accounts/workspace/accounting/accounting.json
+++ b/erpnext/accounts/workspace/accounting/accounting.json
@@ -684,6 +684,7 @@
"is_query_report": 0,
"label": "Goods and Services Tax (GST India)",
"onboard": 0,
+ "only_for": "India",
"type": "Card Break"
},
{
From a0a88a710ebd989eae8c2918a286961c79e4f65d Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Thu, 13 May 2021 17:42:06 +0530
Subject: [PATCH 066/262] fix: change today to now to get data for reposting
---
.../doctype/repost_item_valuation/repost_item_valuation.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 3f83780569..63c71891e4 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe.model.document import Document
-from frappe.utils import cint, get_link_to_form, add_to_date, today
+from frappe.utils import cint, get_link_to_form, add_to_date, now, today
from erpnext.stock.stock_ledger import repost_future_sle
from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced
from frappe.utils.user import get_users_with_role
@@ -127,7 +127,7 @@ def repost_entries():
check_if_stock_and_account_balance_synced(today(), d.name)
def get_repost_item_valuation_entries():
- date = add_to_date(today(), hours=-3)
+ date = add_to_date(now(), hours=-3)
return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation`
WHERE status != 'Completed' and creation <= %s and docstatus = 1
From 3503598735de13b8a87984ca66f187432770dab8 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Tue, 23 Feb 2021 18:57:52 +0000
Subject: [PATCH 067/262] Initial commit of Tax Detail report and report
builder
---
.../accounts/report/tax_detail/__init__.py | 0
.../accounts/report/tax_detail/tax_detail.js | 165 +++++++++++++++++
.../report/tax_detail/tax_detail.json | 32 ++++
.../accounts/report/tax_detail/tax_detail.py | 169 ++++++++++++++++++
4 files changed, 366 insertions(+)
create mode 100644 erpnext/accounts/report/tax_detail/__init__.py
create mode 100644 erpnext/accounts/report/tax_detail/tax_detail.js
create mode 100644 erpnext/accounts/report/tax_detail/tax_detail.json
create mode 100644 erpnext/accounts/report/tax_detail/tax_detail.py
diff --git a/erpnext/accounts/report/tax_detail/__init__.py b/erpnext/accounts/report/tax_detail/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
new file mode 100644
index 0000000000..1ac11409e3
--- /dev/null
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -0,0 +1,165 @@
+// Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+// Contributed by Case Solved and sponsored by Nulight Studios
+/* eslint-disable */
+
+frappe.query_reports["Tax Detail"] = {
+ "filters": [
+ {
+ "fieldname":"company",
+ "label": __("Company"),
+ "fieldtype": "Link",
+ "options": "Company",
+ "default": frappe.defaults.get_user_default("company"),
+ "reqd": 1
+ },
+ {
+ "fieldname":"from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start(frappe.datetime.get_today()),
+ "reqd": 1,
+ "width": "60px"
+ },
+ {
+ "fieldname":"to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_end(frappe.datetime.get_today()),
+ "reqd": 1,
+ "width": "60px"
+ },
+ ],
+ onload: function(report) {
+ report.page.add_inner_button(__("New Report"), () => new_report(), __("Custom Report"));
+ report.page.add_inner_button(__("Load Report"), () => load_report(), __("Custom Report"));
+ load_page_report();
+ }
+};
+
+class TaxReport {
+ constructor() {
+ this.report = frappe.query_reports["Tax Detail"]
+ this.qr = frappe.query_report
+ this.page = frappe.query_report.page
+ this.create_controls()
+ }
+ save_report() {
+ frappe.call({
+ method:'erpnext.accounts.report.tax_detail.tax_detail.new_custom_report',
+ args: {'name': values.report_name},
+ freeze: true
+ }).then((r) => {
+ frappe.set_route("query-report", values.report_name);
+ });
+ }
+ create_controls() {
+ this.section_name = this.page.add_field({
+ label: 'Section',
+ fieldtype: 'Select',
+ fieldname: 'section_name',
+ change() {
+ this.taxreport.set_section()
+ }
+ });
+ this.new_section = this.page.add_field({
+ label: 'New Section',
+ fieldtype: 'Button',
+ fieldname: 'new_section'
+ });
+ this.delete_section = this.page.add_field({
+ label: 'Delete Section',
+ fieldtype: 'Button',
+ fieldname: 'delete_section'
+ });
+ this.page.add_field({
+ label: 'Filter',
+ fieldtype: 'Select',
+ fieldname: 'filter_index'
+ });
+ this.page.add_field({
+ label: 'Add Filter',
+ fieldtype: 'Button',
+ fieldname: 'add_filter'
+ });
+ this.page.add_field({
+ label: 'Delete Filter',
+ fieldtype: 'Button',
+ fieldname: 'delete_filter'
+ });
+ this.page.add_field({
+ label: 'Value Column',
+ fieldtype: 'Select',
+ fieldname: 'value_field',
+ });
+ this.page.add_field({
+ label: 'Save',
+ fieldtype: 'Button',
+ fieldname: 'save'
+ });
+ }
+}
+
+function get_reports(cb) {
+ frappe.call({
+ method: 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports',
+ freeze: true
+ }).then((r) => {
+ cb(r.message);
+ })
+}
+
+function new_report() {
+ const dialog = new frappe.ui.Dialog({
+ title: __("New Report"),
+ fields: [
+ {
+ fieldname: 'report_name',
+ label: 'Report Name',
+ fieldtype: 'Data',
+ default: 'VAT Return'
+ }
+ ],
+ primary_action_label: __('Create'),
+ primary_action: function new_report_pa(values) {
+ frappe.call({
+ method:'erpnext.accounts.report.tax_detail.tax_detail.new_custom_report',
+ args: {'name': values.report_name},
+ freeze: true
+ }).then((r) => {
+ frappe.set_route("query-report", values.report_name);
+ });
+ dialog.hide();
+ }
+ });
+ dialog.show();
+}
+
+function load_page_report() {
+ if (frappe.query_report.report_name === 'Tax Detail') {
+ return;
+ }
+ this.taxreport = new TaxReport();
+}
+
+function load_report() {
+ get_reports(function load_report_cb(reports) {
+ const dialog = new frappe.ui.Dialog({
+ title: __("Load Report"),
+ fields: [
+ {
+ fieldname: 'report_name',
+ label: 'Report Name',
+ fieldtype: 'Select',
+ options: Object.keys(reports)
+ }
+ ],
+ primary_action_label: __('Load'),
+ primary_action: function load_report_pa(values) {
+ dialog.hide();
+ frappe.set_route("query-report", values.report_name);
+ }
+ });
+ dialog.show();
+ });
+}
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.json b/erpnext/accounts/report/tax_detail/tax_detail.json
new file mode 100644
index 0000000000..d52ffd05ac
--- /dev/null
+++ b/erpnext/accounts/report/tax_detail/tax_detail.json
@@ -0,0 +1,32 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2021-02-19 16:44:21.175113",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2021-02-19 16:44:21.175113",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Tax Detail",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "GL Entry",
+ "report_name": "Tax Detail",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Accounts User"
+ },
+ {
+ "role": "Accounts Manager"
+ },
+ {
+ "role": "Auditor"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
new file mode 100644
index 0000000000..46e7ae08e9
--- /dev/null
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -0,0 +1,169 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+# Contributed by Case Solved and sponsored by Nulight Studios
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+
+# field lists in multiple doctypes will be coalesced
+required_sql_fields = {
+ "GL Entry": ["posting_date", "voucher_type", "voucher_no", "account", "account_currency", "debit", "credit"],
+ "Account": ["account_type"],
+ ("Purchase Invoice", "Sales Invoice"): ["taxes_and_charges", "tax_category"],
+ ("Purchase Invoice Item", "Sales Invoice Item"): ["item_tax_template", "item_name", "base_net_amount", "item_tax_rate"],
+# "Journal Entry": ["total_amount_currency"],
+# "Journal Entry Account": ["debit_in_account_currency", "credit_in_account_currency"]
+}
+
+@frappe.whitelist()
+def get_required_fieldlist():
+ """For overriding the fieldlist from the client"""
+ return required_sql_fields
+
+def execute(filters=None, fieldlist=required_sql_fields):
+ if not filters:
+ return [], []
+
+ fieldstr = get_fieldstr(fieldlist)
+
+ gl_entries = frappe.db.sql("""
+ select {fieldstr}
+ from `tabGL Entry` ge
+ inner join `tabAccount` a on
+ ge.account=a.name and ge.company=a.company
+ left join `tabSales Invoice` si on
+ a.account_type='Tax' and ge.company=si.company and ge.voucher_type='Sales Invoice' and ge.voucher_no=si.name
+ left join `tabSales Invoice Item` sii on
+ si.name=sii.parent
+ left join `tabPurchase Invoice` pi on
+ a.account_type='Tax' and ge.company=pi.company and ge.voucher_type='Purchase Invoice' and ge.voucher_no=pi.name
+ left join `tabPurchase Invoice Item` pii on
+ pi.name=pii.parent
+/* left outer join `tabJournal Entry` je on
+ ge.voucher_no=je.name and ge.company=je.company
+ left outer join `tabJournal Entry Account` jea on
+ je.name=jea.parent and a.account_type='Tax' */
+ where (ge.voucher_type, ge.voucher_no) in (
+ select ge.voucher_type, ge.voucher_no
+ from `tabGL Entry` ge
+ join `tabAccount` a on ge.account=a.name and ge.company=a.company
+ where
+ a.account_type='Tax' and
+ ge.company=%(company)s and
+ ge.posting_date>=%(from_date)s and
+ ge.posting_date<=%(to_date)s
+ )
+ order by ge.posting_date, ge.voucher_no
+ """.format(fieldstr=fieldstr), filters, as_dict=1)
+
+ gl_entries = modify_report_data(gl_entries)
+
+ return get_columns(fieldlist), gl_entries
+
+
+abbrev = lambda dt: ''.join(l[0].lower() for l in dt.split(' ')) + '.'
+doclist = lambda dt, dfs: [abbrev(dt) + f for f in dfs]
+coalesce = lambda dts, dfs: ['coalesce(' + ', '.join(abbrev(dt) + f for dt in dts) + ') ' + f for f in dfs]
+
+def get_fieldstr(fieldlist):
+ fields = []
+ for doctypes, docfields in fieldlist.items():
+ if isinstance(doctypes, str):
+ fields += doclist(doctypes, docfields)
+ if isinstance(doctypes, tuple):
+ fields += coalesce(doctypes, docfields)
+ return ', '.join(fields)
+
+def get_columns(fieldlist):
+ columns = {}
+ for doctypes, docfields in fieldlist.items():
+ if isinstance(doctypes, str):
+ doctypes = [doctypes]
+ for doctype in doctypes:
+ meta = frappe.get_meta(doctype)
+ # get column field metadata from the db
+ fieldmeta = {}
+ for field in meta.get('fields'):
+ if field.fieldname in docfields:
+ fieldmeta[field.fieldname] = {
+ "label": _(field.label),
+ "fieldname": field.fieldname,
+ "fieldtype": field.fieldtype,
+ "options": field.options
+ }
+ # edit the columns to match the modified data
+ for field in docfields:
+ col = modify_report_columns(doctype, field, fieldmeta[field])
+ if col:
+ columns[col["fieldname"]] = col
+ # use of a dict ensures duplicate columns are removed
+ return list(columns.values())
+
+def modify_report_columns(doctype, field, column):
+ "Because data is rearranged into other columns"
+ if doctype in ["Sales Invoice Item", "Purchase Invoice Item"] and field == "item_tax_rate":
+ return None
+ if doctype == "Sales Invoice Item" and field == "base_net_amount":
+ column.update({"label": _("Credit Net Amount"), "fieldname": "credit_net_amount"})
+ if doctype == "Purchase Invoice Item" and field == "base_net_amount":
+ column.update({"label": _("Debit Net Amount"), "fieldname": "debit_net_amount"})
+ if field == "taxes_and_charges":
+ column.update({"label": _("Taxes and Charges Template")})
+ return column
+
+def modify_report_data(data):
+ import json
+ for line in data:
+ if line.account_type == "Tax" and line.item_tax_rate:
+ tax_rates = json.loads(line.item_tax_rate)
+ for account, rate in tax_rates.items():
+ if account == line.account:
+ if line.voucher_type == "Sales Invoice":
+ line.credit = line.base_net_amount * (rate / 100)
+ line.credit_net_amount = line.base_net_amount
+ if line.voucher_type == "Purchase Invoice":
+ line.debit = line.base_net_amount * (rate / 100)
+ line.debit_net_amount = line.base_net_amount
+ return data
+
+####### JS client utilities
+
+custom_report_dict = {
+ 'ref_doctype': 'GL Entry',
+ 'report_type': 'Custom Report',
+ 'reference_report': 'Tax Detail'
+}
+
+@frappe.whitelist()
+def get_custom_reports():
+ reports = frappe.get_list('Report',
+ filters = custom_report_dict,
+ fields = ['name', 'json'],
+ as_list=False
+ )
+ reports_dict = {rep.pop('name'): rep for rep in reports}
+ # Prevent custom reports with the same name
+ reports_dict['Tax Detail'] = {'json': None}
+ return reports_dict
+
+@frappe.whitelist()
+def new_custom_report(name=None):
+ if name == 'Tax Detail':
+ frappe.throw("The parent report cannot be overwritten.")
+ if not name:
+ frappe.throw("The report name must be supplied.")
+ doc = {
+ 'doctype': 'Report',
+ 'report_name': name,
+ 'is_standard': 'No',
+ 'module': 'Accounts'
+ }
+ doc.update(custom_report_dict)
+ doc = frappe.get_doc(doc)
+ doc.insert()
+ return True
+
+@frappe.whitelist()
+def save_custom_report(data):
+ return None
From a5d47f70b8864c67bddbb20e913116a01a901dfb Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Fri, 5 Mar 2021 06:46:38 +0000
Subject: [PATCH 068/262] Fleshed out report setup functionality
---
.../accounts/report/tax_detail/tax_detail.js | 320 ++++++++++++++----
1 file changed, 255 insertions(+), 65 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 1ac11409e3..0b0026028f 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -4,47 +4,79 @@
/* eslint-disable */
frappe.query_reports["Tax Detail"] = {
- "filters": [
+ 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":"from_date",
- "label": __("From Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.month_start(frappe.datetime.get_today()),
- "reqd": 1,
- "width": "60px"
+ fieldname: "from_date",
+ label: __("From Date"),
+ fieldtype: "Date",
+ default: frappe.datetime.month_start(frappe.datetime.get_today()),
+ reqd: 1,
+ width: "60px"
},
{
- "fieldname":"to_date",
- "label": __("To Date"),
- "fieldtype": "Date",
- "default": frappe.datetime.month_end(frappe.datetime.get_today()),
- "reqd": 1,
- "width": "60px"
+ fieldname: "to_date",
+ label: __("To Date"),
+ fieldtype: "Date",
+ default: frappe.datetime.month_end(frappe.datetime.get_today()),
+ reqd: 1,
+ width: "60px"
},
],
- onload: function(report) {
- report.page.add_inner_button(__("New Report"), () => new_report(), __("Custom Report"));
- report.page.add_inner_button(__("Load Report"), () => load_report(), __("Custom Report"));
- load_page_report();
+ onload: function onload(report) {
+ // Remove Add Column and Save from menu
+ report.page.add_inner_button(__("New Report"), () => new_report, __("Custom Report"));
+ report.page.add_inner_button(__("Load Report"), () => load_report, __("Custom Report"));
+ },
+ after_datatable_render: (datatable) => {
+ if (frappe.query_report.report_name == 'Tax Detail') {
+ return;
+ }
+ if (this.taxreport) {
+ this.taxreport.load_report();
+ } else {
+ this.taxreport = new TaxReport();
+ }
}
};
class TaxReport {
+ // construct after datatable is loaded
constructor() {
- this.report = frappe.query_reports["Tax Detail"]
- this.qr = frappe.query_report
- this.page = frappe.query_report.page
- this.create_controls()
+ this.report = frappe.query_reports["Tax Detail"];
+ this.qr = frappe.query_report;
+ this.page = frappe.query_report.page;
+ this.create_controls();
+ this.sections = {};
+ this.mode = 'run';
+ this.load_report();
+ }
+ load_report() {
+ // TODO
+ this.setup_menu();
+ // this.qr.refresh_report()
+ }
+ setup_menu() {
+ this.qr.menu_items.forEach((item, idx) => {
+ if (item['label'] == __('Save')) {
+ delete this.qr.menu_items[idx];
+ }
+ })
+ this.qr.menu_items.push({
+ label: __('Save'),
+ action: this.save_report
+ })
+ this.qr.set_menu_items();
}
save_report() {
+ // TODO
frappe.call({
method:'erpnext.accounts.report.tax_detail.tax_detail.new_custom_report',
args: {'name': values.report_name},
@@ -53,53 +85,218 @@ class TaxReport {
frappe.set_route("query-report", values.report_name);
});
}
- create_controls() {
- this.section_name = this.page.add_field({
- label: 'Section',
- fieldtype: 'Select',
- fieldname: 'section_name',
- change() {
- this.taxreport.set_section()
+ set_value_options() {
+ let curcols = [];
+ let options = [];
+ this.qr.columns.forEach((col, index) => {
+ if (col['fieldtype'] == "Currency") {
+ curcols.push(index);
+ options.push(col['label']);
}
});
- this.new_section = this.page.add_field({
- label: 'New Section',
- fieldtype: 'Button',
- fieldname: 'new_section'
+ this.currency_cols = curcols;
+ this.controls['value_field'].$wrapper.find("select").empty().add_options(options);
+ this.controls['value_field'].set_input(options[0]);
+ }
+ add_value_field_to_filters(filters) {
+ const curlabel = this.controls['value_field'].value;
+ this.currency_cols.forEach(index => {
+ if (this.qr.columns[index]['label'] == curlabel) {
+ filters['fieldname'] = this.qr.columns[index]['fieldname'];
+ }
});
- this.delete_section = this.page.add_field({
- label: 'Delete Section',
- fieldtype: 'Button',
- fieldname: 'delete_section'
+ return filters;
+ }
+ new_section(label) {
+ const dialog = new frappe.ui.Dialog({
+ title: label,
+ fields: [{
+ fieldname: 'data',
+ label: label,
+ fieldtype: 'Data'
+ }],
+ primary_action_label: label,
+ primary_action: (values) => {
+ dialog.hide();
+ this.set_section(values.data);
+ }
});
- this.page.add_field({
- label: 'Filter',
+ dialog.show();
+ }
+ set_section(name) {
+ this.mode = 'edit';
+ if (name && !this.sections[name]) {
+ this.sections[name] = {};
+ this.controls['section_name'].$wrapper.find("select").empty().add_options(Object.keys(this.sections));
+ }
+ if (name) {
+ this.controls['section_name'].set_input(name);
+ }
+ this.reload();
+ }
+ reload() {
+ if (this.mode == 'edit') {
+ const section_name = this.controls['section_name'].value;
+ let filters = {};
+ if (section_name) {
+ let fidx = this.controls['filter_index'].value;
+ let section = this.sections[section_name];
+ let fidxs = Object.keys(section);
+ fidxs.unshift('');
+ this.controls['filter_index'].$wrapper.find("select").empty().add_options(fidxs);
+ this.controls['filter_index'].set_input(fidx);
+ if (fidx != '') {
+ filters = section[fidx];
+ }
+ } else {
+ this.controls['filter_index'].$wrapper.find("select").empty();
+ }
+ // Set filters
+ // reload datatable
+ } else {
+ this.controls['filter_index'].$wrapper.find("select").empty();
+ // Query the result from the server & render
+ }
+ }
+ get_select(label, list, type) {
+ const dialog = new frappe.ui.Dialog({
+ title: label,
+ fields: [{
+ fieldname: 'select',
+ label: label,
+ fieldtype: 'Select',
+ options: list
+ }],
+ primary_action_label: label,
+ primary_action: (values) => {
+ dialog.hide();
+ this.exec_select(values.select, type);
+ }
+ });
+ dialog.show();
+ }
+ delete(name, type) {
+ if (type === 'section') {
+ delete this.sections[name];
+ this.controls['section_name'].$wrapper.find("select").empty().add_options(Object.keys(this.sections));
+ this.controls['section_name'].set_input(Object.keys(this.sections)[0] || '');
+ this.controls['filter_index'].set_input('');
+ }
+ if (type === 'filter') {
+ let cur_section = this.controls['section_name'].value;
+ delete this.sections[cur_section][name];
+ this.controls['filter_index'].set_input('');
+ }
+ this.reload();
+ }
+ create_controls() {
+ if (this.controls) {
+ return;
+ }
+ let controls = {};
+ // SELECT in data.js
+ controls['section_name'] = this.page.add_field({
+ label: __('Section'),
fieldtype: 'Select',
- fieldname: 'filter_index'
+ fieldname: 'section_name',
+ change: (e) => {
+ this.set_section();
+ }
});
- this.page.add_field({
- label: 'Add Filter',
+ // BUTTON in button.js
+ controls['new_section'] = this.page.add_field({
+ label: __('New Section'),
fieldtype: 'Button',
- fieldname: 'add_filter'
+ fieldname: 'new_section',
+ click: () => {
+ this.new_section(__('New Section'));
+ }
});
- this.page.add_field({
- label: 'Delete Filter',
+ controls['delete_section'] = this.page.add_field({
+ label: __('Delete Section'),
fieldtype: 'Button',
- fieldname: 'delete_filter'
+ fieldname: 'delete_section',
+ click: () => {
+ let cur_section = this.controls['section_name'].value;
+ if (cur_section) {
+ frappe.confirm(__('Are you sure you want to delete section ') + cur_section + '?',
+ () => {this.delete(cur_section, 'section')});
+ }
+ }
});
- this.page.add_field({
- label: 'Value Column',
+ controls['filter_index'] = this.page.add_field({
+ label: __('Filter'),
+ fieldtype: 'Select',
+ fieldname: 'filter_index',
+ change: (e) => {
+ // TODO
+ }
+ });
+ controls['add_filter'] = this.page.add_field({
+ label: __('Add Filter'),
+ fieldtype: 'Button',
+ fieldname: 'add_filter',
+ click: () => {
+ let section_name = this.controls['section_name'].value;
+ if (section_name) {
+ let prefix = 'Filter';
+ let filters = this.qr.datatable.columnmanager.getAppliedFilters();
+ filters = this.add_value_field_to_filters(filters);
+ const fidxs = Object.keys(this.sections[section_name]);
+ let new_idx = prefix + '0';
+ if (fidxs.length > 0) {
+ const fiidxs = fidxs.map((key) => parseInt(key.replace(prefix, '')));
+ new_idx = prefix + (Math.max(...fiidxs) + 1).toString();
+ }
+ this.sections[section_name][new_idx] = filters;
+ this.controls['filter_index'].set_input(new_idx);
+ this.reload();
+ } else {
+ frappe.throw(__('Please add or select the Section first'));
+ }
+ }
+ });
+ controls['delete_filter'] = this.page.add_field({
+ label: __('Delete Filter'),
+ fieldtype: 'Button',
+ fieldname: 'delete_filter',
+ click: () => {
+ let cur_filter = this.controls['filter_index'].value;
+ if (cur_filter) {
+ frappe.confirm(__('Are you sure you want to delete filter ') + cur_filter + '?',
+ () => {this.delete(cur_filter, 'filter')});
+ }
+ }
+ });
+ controls['value_field'] = this.page.add_field({
+ label: __('Value Column'),
fieldtype: 'Select',
fieldname: 'value_field',
+ change: (e) => {
+ // TODO
+ }
});
- this.page.add_field({
- label: 'Save',
+ controls['save'] = this.page.add_field({
+ label: __('Save & Run'),
fieldtype: 'Button',
- fieldname: 'save'
+ fieldname: 'save',
+ click: () => {
+ // TODO: Save to db
+ this.mode = 'run';
+ this.reload();
+ }
});
+ this.controls = controls;
+ this.set_value_options();
+ this.show_help();
+ }
+ show_help() {
+ const help = __('You can add multiple sections to your custom report using the New Section button above. To specify what data goes in each section, specify column filters below, then save with Add Filter. Each section can have multiple filters added. You can specify which Currency column will be summed for each filter in the final report with the Value Column select box.');
+ this.qr.show_status(help);
}
}
+
function get_reports(cb) {
frappe.call({
method: 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports',
@@ -115,7 +312,7 @@ function new_report() {
fields: [
{
fieldname: 'report_name',
- label: 'Report Name',
+ label: __('Report Name'),
fieldtype: 'Data',
default: 'VAT Return'
}
@@ -135,13 +332,6 @@ function new_report() {
dialog.show();
}
-function load_page_report() {
- if (frappe.query_report.report_name === 'Tax Detail') {
- return;
- }
- this.taxreport = new TaxReport();
-}
-
function load_report() {
get_reports(function load_report_cb(reports) {
const dialog = new frappe.ui.Dialog({
@@ -149,7 +339,7 @@ function load_report() {
fields: [
{
fieldname: 'report_name',
- label: 'Report Name',
+ label: __('Report Name'),
fieldtype: 'Select',
options: Object.keys(reports)
}
From ef8ab135c9ebafaf3f5d9a8a7c4698935ef2eef8 Mon Sep 17 00:00:00 2001
From: Richard Case
Date: Sun, 14 Mar 2021 06:05:02 +0000
Subject: [PATCH 069/262] develop: progress tax detail report
---
.../accounts/report/tax_detail/tax_detail.js | 290 ++++++++++++------
.../accounts/report/tax_detail/tax_detail.py | 54 ++--
2 files changed, 224 insertions(+), 120 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 0b0026028f..894db9e55c 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -29,11 +29,28 @@ frappe.query_reports["Tax Detail"] = {
reqd: 1,
width: "60px"
},
+ {
+ fieldname: "report_name",
+ label: __("Report Name"),
+ fieldtype: "Read Only",
+ default: frappe.query_report.report_name,
+ hidden: 1,
+ reqd: 1
+ },
+ {
+ fieldname: "mode",
+ label: __("Mode"),
+ fieldtype: "Read Only",
+ default: "run",
+ hidden: 1,
+ reqd: 1
+ }
],
onload: function onload(report) {
// Remove Add Column and Save from menu
- report.page.add_inner_button(__("New Report"), () => new_report, __("Custom Report"));
- report.page.add_inner_button(__("Load Report"), () => load_report, __("Custom Report"));
+ report.page.add_inner_button(__("New Report"), () => new_report(), __("Custom Report"));
+ report.page.add_inner_button(__("Load Report"), () => load_report(), __("Custom Report"));
+ hide_filters();
},
after_datatable_render: (datatable) => {
if (frappe.query_report.report_name == 'Tax Detail') {
@@ -47,65 +64,83 @@ frappe.query_reports["Tax Detail"] = {
}
};
+function hide_filters() {
+ frappe.query_report.page.page_form[0].querySelectorAll('.form-group.frappe-control').forEach(function setHidden(field) {
+ if (field.dataset.fieldtype == "Read Only") {
+ field.classList.add("hidden");
+ }
+ });
+}
+
class TaxReport {
// construct after datatable is loaded
constructor() {
- this.report = frappe.query_reports["Tax Detail"];
this.qr = frappe.query_report;
this.page = frappe.query_report.page;
this.create_controls();
- this.sections = {};
- this.mode = 'run';
this.load_report();
}
load_report() {
- // TODO
- this.setup_menu();
- // this.qr.refresh_report()
- }
- setup_menu() {
- this.qr.menu_items.forEach((item, idx) => {
- if (item['label'] == __('Save')) {
- delete this.qr.menu_items[idx];
- }
- })
- this.qr.menu_items.push({
- label: __('Save'),
- action: this.save_report
- })
- this.qr.set_menu_items();
- }
- save_report() {
- // TODO
+ if (this.loaded) {
+ return;
+ }
+ const report_name = this.qr.report_name;
+ this.report_name.value = report_name;
frappe.call({
- method:'erpnext.accounts.report.tax_detail.tax_detail.new_custom_report',
- args: {'name': values.report_name},
+ method: 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports',
+ args: {name: report_name},
freeze: true
}).then((r) => {
- frappe.set_route("query-report", values.report_name);
+ const data = JSON.parse(r.message[report_name]['json']);
+ if (data && data['sections']) {
+ this.sections = data['sections'];
+ } else {
+ this.sections = {};
+ }
+ this.set_section();
+ })
+ this.loaded = 1;
+ }
+ save_report() {
+ frappe.call({
+ method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report',
+ args: {
+ reference_report: 'Tax Detail',
+ report_name: this.qr.report_name,
+ columns: this.qr.get_visible_columns(),
+ sections: this.sections
+ },
+ freeze: true
+ }).then((r) => {
+ this.reload();
});
}
set_value_options() {
- let curcols = [];
- let options = [];
+ this.fieldname_lookup = {};
+ this.label_lookup = {};
this.qr.columns.forEach((col, index) => {
if (col['fieldtype'] == "Currency") {
- curcols.push(index);
- options.push(col['label']);
+ this.fieldname_lookup[col['label']] = col['fieldname'];
+ this.label_lookup[col['fieldname']] = col['label'];
}
});
- this.currency_cols = curcols;
+ const options = Object.keys(this.fieldname_lookup);
this.controls['value_field'].$wrapper.find("select").empty().add_options(options);
this.controls['value_field'].set_input(options[0]);
}
- add_value_field_to_filters(filters) {
+ set_value_label_from_filter() {
+ const section_name = this.controls['section_name'].value;
+ const fidx = this.controls['filter_index'].value;
+ if (section_name && fidx) {
+ const fieldname = this.sections[section_name][fidx]['fieldname'];
+ this.controls['value_field'].set_input(this.label_lookup[fieldname]);
+ } else {
+ this.controls['value_field'].set_input(Object.keys(this.fieldname_lookup)[0]);
+ }
+ }
+ get_value_fieldname() {
const curlabel = this.controls['value_field'].value;
- this.currency_cols.forEach(index => {
- if (this.qr.columns[index]['label'] == curlabel) {
- filters['fieldname'] = this.qr.columns[index]['fieldname'];
- }
- });
- return filters;
+ return this.fieldname_lookup[curlabel];
}
new_section(label) {
const dialog = new frappe.ui.Dialog({
@@ -123,57 +158,87 @@ class TaxReport {
});
dialog.show();
}
- set_section(name) {
- this.mode = 'edit';
- if (name && !this.sections[name]) {
- this.sections[name] = {};
- this.controls['section_name'].$wrapper.find("select").empty().add_options(Object.keys(this.sections));
- }
- if (name) {
- this.controls['section_name'].set_input(name);
- }
- this.reload();
- }
- reload() {
- if (this.mode == 'edit') {
- const section_name = this.controls['section_name'].value;
- let filters = {};
- if (section_name) {
- let fidx = this.controls['filter_index'].value;
- let section = this.sections[section_name];
- let fidxs = Object.keys(section);
- fidxs.unshift('');
- this.controls['filter_index'].$wrapper.find("select").empty().add_options(fidxs);
- this.controls['filter_index'].set_input(fidx);
- if (fidx != '') {
- filters = section[fidx];
- }
- } else {
- this.controls['filter_index'].$wrapper.find("select").empty();
+ get_filter_controls() {
+ this.qr.filters.forEach(filter => {
+ if (filter['fieldname'] == 'mode') {
+ this.mode = filter;
}
- // Set filters
- // reload datatable
- } else {
- this.controls['filter_index'].$wrapper.find("select").empty();
- // Query the result from the server & render
- }
- }
- get_select(label, list, type) {
- const dialog = new frappe.ui.Dialog({
- title: label,
- fields: [{
- fieldname: 'select',
- label: label,
- fieldtype: 'Select',
- options: list
- }],
- primary_action_label: label,
- primary_action: (values) => {
- dialog.hide();
- this.exec_select(values.select, type);
+ if (filter['fieldname'] == 'report_name') {
+ this.report_name = filter;
}
});
- dialog.show();
+ }
+ set_mode(mode) {
+ this.mode.value = mode;
+ }
+ edit_mode() {
+ return this.mode.value == 'edit';
+ }
+ set_section(name) {
+ if (name && !this.sections[name]) {
+ this.sections[name] = {};
+ }
+ let options = Object.keys(this.sections);
+ options.unshift('');
+ this.controls['section_name'].$wrapper.find("select").empty().add_options(options);
+ if (name) {
+ this.controls['section_name'].set_input(name);
+ } else {
+ this.controls['section_name'].set_input('');
+ }
+ if (this.controls['section_name'].value) {
+ this.set_mode('edit');
+ } else {
+ this.set_mode('run');
+ }
+ this.controls['filter_index'].set_input('');
+ this.reload();
+ }
+ reload_filter() {
+ const section_name = this.controls['section_name'].value;
+ if (section_name) {
+ let fidx = this.controls['filter_index'].value;
+ let section = this.sections[section_name];
+ let fidxs = Object.keys(section);
+ fidxs.unshift('');
+ this.controls['filter_index'].$wrapper.find("select").empty().add_options(fidxs);
+ this.controls['filter_index'].set_input(fidx);
+ } else {
+ this.controls['filter_index'].$wrapper.find("select").empty();
+ this.controls['filter_index'].set_input('');
+ }
+ this.set_filters();
+ }
+ set_filters() {
+ let filters = {};
+ const section_name = this.controls['section_name'].value;
+ const fidx = this.controls['filter_index'].value;
+ if (section_name && fidx) {
+ filters = this.sections[section_name][fidx]['filters'];
+ }
+ this.setAppliedFilters(filters);
+ this.qr.datatable.columnmanager.applyFilter(filters);
+ this.set_value_label_from_filter();
+ }
+ setAppliedFilters(filters) {
+ Array.from(this.qr.datatable.header.querySelectorAll('.dt-filter')).map(function setFilters(input) {
+ let idx = input.dataset.colIndex;
+ if (filters[idx]) {
+ input.value = filters[idx];
+ } else {
+ input.value = null;
+ }
+ });
+ }
+ reload() {
+ // Reloads the data. When the datatable is reloaded, load_report()
+ // will be run by the after_datatable_render event.
+ this.qr.refresh();
+ if (this.edit_mode()) {
+ this.reload_filter();
+ } else {
+ this.controls['filter_index'].$wrapper.find("select").empty();
+ }
}
delete(name, type) {
if (type === 'section') {
@@ -200,7 +265,7 @@ class TaxReport {
fieldtype: 'Select',
fieldname: 'section_name',
change: (e) => {
- this.set_section();
+ this.set_section(this.controls['section_name'].get_input_value());
}
});
// BUTTON in button.js
@@ -229,7 +294,8 @@ class TaxReport {
fieldtype: 'Select',
fieldname: 'filter_index',
change: (e) => {
- // TODO
+ this.controls['filter_index'].set_input(this.controls['filter_index'].get_input_value());
+ this.set_filters();
}
});
controls['add_filter'] = this.page.add_field({
@@ -240,17 +306,19 @@ class TaxReport {
let section_name = this.controls['section_name'].value;
if (section_name) {
let prefix = 'Filter';
- let filters = this.qr.datatable.columnmanager.getAppliedFilters();
- filters = this.add_value_field_to_filters(filters);
+ let data = {
+ filters: this.qr.datatable.columnmanager.getAppliedFilters(),
+ fieldname: this.get_value_fieldname()
+ }
const fidxs = Object.keys(this.sections[section_name]);
let new_idx = prefix + '0';
if (fidxs.length > 0) {
const fiidxs = fidxs.map((key) => parseInt(key.replace(prefix, '')));
new_idx = prefix + (Math.max(...fiidxs) + 1).toString();
}
- this.sections[section_name][new_idx] = filters;
+ this.sections[section_name][new_idx] = data;
this.controls['filter_index'].set_input(new_idx);
- this.reload();
+ this.reload_filter();
} else {
frappe.throw(__('Please add or select the Section first'));
}
@@ -273,7 +341,7 @@ class TaxReport {
fieldtype: 'Select',
fieldname: 'value_field',
change: (e) => {
- // TODO
+ this.controls['value_field'].set_input(this.controls['value_field'].get_input_value());
}
});
controls['save'] = this.page.add_field({
@@ -281,17 +349,22 @@ class TaxReport {
fieldtype: 'Button',
fieldname: 'save',
click: () => {
- // TODO: Save to db
- this.mode = 'run';
- this.reload();
+ this.controls['section_name'].set_input('');
+ this.set_mode('run');
+ this.save_report();
}
});
this.controls = controls;
this.set_value_options();
+ this.get_filter_controls();
this.show_help();
}
show_help() {
- const help = __('You can add multiple sections to your custom report using the New Section button above. To specify what data goes in each section, specify column filters below, then save with Add Filter. Each section can have multiple filters added. You can specify which Currency column will be summed for each filter in the final report with the Value Column select box.');
+ const help = __(`You can add multiple sections to your custom report using the New Section button above.
+ To specify what data goes in each section, specify column filters below, then save with Add Filter.
+ Each section can have multiple filters added.
+ You can specify which Currency column will be summed for each filter in the final report with the Value Column select box.
+ Once you're done, hit Save & Run.`);
this.qr.show_status(help);
}
}
@@ -306,6 +379,20 @@ function get_reports(cb) {
})
}
+function override_menu() {
+ //TODO: Replace save button
+ this.qr.menu_items.forEach((item, idx) => {
+ if (item['label'] == __('Save')) {
+ delete this.qr.menu_items[idx];
+ }
+ })
+ this.qr.menu_items.push({
+ label: __('Save'),
+ action: this.save_report
+ })
+ this.qr.set_menu_items();
+}
+
function new_report() {
const dialog = new frappe.ui.Dialog({
title: __("New Report"),
@@ -320,8 +407,13 @@ function new_report() {
primary_action_label: __('Create'),
primary_action: function new_report_pa(values) {
frappe.call({
- method:'erpnext.accounts.report.tax_detail.tax_detail.new_custom_report',
- args: {'name': values.report_name},
+ method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report',
+ args: {
+ reference_report: 'Tax Detail',
+ report_name: values.report_name,
+ columns: frappe.query_report.get_visible_columns(),
+ sections: {}
+ },
freeze: true
}).then((r) => {
frappe.set_route("query-report", values.report_name);
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index 46e7ae08e9..2ea782eb7a 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -3,7 +3,7 @@
# Contributed by Case Solved and sponsored by Nulight Studios
from __future__ import unicode_literals
-import frappe
+import frappe, json
from frappe import _
# field lists in multiple doctypes will be coalesced
@@ -16,15 +16,12 @@ required_sql_fields = {
# "Journal Entry Account": ["debit_in_account_currency", "credit_in_account_currency"]
}
-@frappe.whitelist()
-def get_required_fieldlist():
- """For overriding the fieldlist from the client"""
- return required_sql_fields
-def execute(filters=None, fieldlist=required_sql_fields):
+def execute(filters=None):
if not filters:
return [], []
+ fieldlist = required_sql_fields
fieldstr = get_fieldstr(fieldlist)
gl_entries = frappe.db.sql("""
@@ -136,9 +133,12 @@ custom_report_dict = {
}
@frappe.whitelist()
-def get_custom_reports():
+def get_custom_reports(name=None):
+ filters = custom_report_dict.copy()
+ if name:
+ filters['name'] = name
reports = frappe.get_list('Report',
- filters = custom_report_dict,
+ filters = filters,
fields = ['name', 'json'],
as_list=False
)
@@ -148,22 +148,34 @@ def get_custom_reports():
return reports_dict
@frappe.whitelist()
-def new_custom_report(name=None):
- if name == 'Tax Detail':
- frappe.throw("The parent report cannot be overwritten.")
- if not name:
- frappe.throw("The report name must be supplied.")
+def save_custom_report(reference_report, report_name, columns, sections):
+ import pymysql
+ if reference_report != 'Tax Detail':
+ frappe.throw(_("The wrong report is referenced."))
+ if report_name == 'Tax Detail':
+ frappe.throw(_("The parent report cannot be overwritten."))
+
+ data = {
+ 'columns': json.loads(columns),
+ 'sections': json.loads(sections)
+ }
+
doc = {
'doctype': 'Report',
- 'report_name': name,
+ 'report_name': report_name,
'is_standard': 'No',
- 'module': 'Accounts'
+ 'module': 'Accounts',
+ 'json': json.dumps(data, separators=(',', ':'))
}
doc.update(custom_report_dict)
- doc = frappe.get_doc(doc)
- doc.insert()
- return True
-@frappe.whitelist()
-def save_custom_report(data):
- return None
+ try:
+ newdoc = frappe.get_doc(doc)
+ newdoc.insert()
+ frappe.msgprint(_("Report created successfully"))
+ except (frappe.exceptions.DuplicateEntryError, pymysql.err.IntegrityError):
+ dbdoc = frappe.get_doc('Report', report_name)
+ dbdoc.update(doc)
+ dbdoc.save()
+ frappe.msgprint(_("Report updated successfully"))
+ return report_name
From dba4b3cd13e12e3db1233cbf707744773fff62e1 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Fri, 19 Mar 2021 23:05:19 +0000
Subject: [PATCH 070/262] feat: add run mode, add tests, various fixes
---
.../accounts/report/tax_detail/tax_detail.js | 22 +++--
.../accounts/report/tax_detail/tax_detail.py | 95 ++++++++++++++++---
.../report/tax_detail/test_tax_detail.py | 67 +++++++++++++
3 files changed, 166 insertions(+), 18 deletions(-)
create mode 100644 erpnext/accounts/report/tax_detail/test_tax_detail.py
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 894db9e55c..8cdce54852 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -92,11 +92,8 @@ class TaxReport {
freeze: true
}).then((r) => {
const data = JSON.parse(r.message[report_name]['json']);
- if (data && data['sections']) {
- this.sections = data['sections'];
- } else {
- this.sections = {};
- }
+ this.sections = data.sections || {};
+ this.controls['show_detail'].set_input(data.show_detail);
this.set_section();
})
this.loaded = 1;
@@ -107,8 +104,11 @@ class TaxReport {
args: {
reference_report: 'Tax Detail',
report_name: this.qr.report_name,
- columns: this.qr.get_visible_columns(),
- sections: this.sections
+ data: {
+ columns: this.qr.get_visible_columns(),
+ sections: this.sections,
+ show_detail: this.controls['show_detail'].get_input_value()
+ }
},
freeze: true
}).then((r) => {
@@ -233,7 +233,9 @@ class TaxReport {
reload() {
// Reloads the data. When the datatable is reloaded, load_report()
// will be run by the after_datatable_render event.
+ // TODO: why does this trigger multiple reloads?
this.qr.refresh();
+ this.show_help();
if (this.edit_mode()) {
this.reload_filter();
} else {
@@ -354,6 +356,12 @@ class TaxReport {
this.save_report();
}
});
+ controls['show_detail'] = this.page.add_field({
+ label: __('Show Detail'),
+ fieldtype: 'Check',
+ fieldname: 'show_detail',
+ default: 1
+ });
this.controls = controls;
this.set_value_options();
this.get_filter_controls();
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index 2ea782eb7a..6bed89841c 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -54,10 +54,89 @@ def execute(filters=None):
order by ge.posting_date, ge.voucher_no
""".format(fieldstr=fieldstr), filters, as_dict=1)
- gl_entries = modify_report_data(gl_entries)
+ report_data = modify_report_data(gl_entries)
+ summary = None
+ if filters['mode'] == 'run' and filters['report_name'] != 'Tax Detail':
+ report_data, summary = run_report(filters['report_name'], report_data)
- return get_columns(fieldlist), gl_entries
+ # return columns, data, message, chart, report_summary
+ return get_columns(fieldlist), report_data, None, None, summary
+def run_report(report_name, data):
+ "Applies the sections and filters saved in the custom report"
+ report_config = json.loads(frappe.get_doc('Report', report_name).json)
+ # Columns indexed from 1 wrt colno
+ columns = report_config.get('columns')
+ sections = report_config.get('sections', {})
+ show_detail = report_config.get('show_detail', 1)
+ new_data = []
+ summary = []
+ for section_name, section in sections.items():
+ section_total = 0.0
+ for filt_name, filt in section.items():
+ value_field = filt['fieldname']
+ rmidxs = []
+ for colno, filter_string in filt['filters'].items():
+ filter_field = columns[int(colno) - 1]['fieldname']
+ for i, row in enumerate(data):
+ if not filter_match(row[filter_field], filter_string):
+ rmidxs += [i]
+ rows = [row for i, row in enumerate(data) if i not in rmidxs]
+ section_total += subtotal(rows, value_field)
+ if show_detail: new_data += rows
+ new_data += [ {columns[1]['fieldname']: section_name, columns[2]['fieldname']: section_total} ]
+ summary += [ {'label': section_name, 'datatype': 'Currency', 'value': section_total} ]
+ if show_detail: new_data += [ {} ]
+ return new_data if new_data else data, summary
+
+def filter_match(value, string):
+ "Approximation to datatable filters"
+ import datetime
+ if string == '': return True
+ if value is None: value = -999999999999999
+ elif isinstance(value, datetime.date): return True
+
+ if isinstance(value, str):
+ value = value.lower()
+ string = string.lower()
+ if string[0] == '<': return True if string[1:].strip() else False
+ elif string[0] == '>': return False if string[1:].strip() else True
+ elif string[0] == '=': return string[1:] in value if string[1:] else False
+ elif string[0:2] == '!=': return string[2:] not in value
+ elif len(string.split(':')) == 2:
+ pre, post = string.split(':')
+ return (True if not pre.strip() and post.strip() in value else False)
+ else:
+ return string in value
+ else:
+ if string[0] in ['<', '>', '=']:
+ operator = string[0]
+ if operator == '=': operator = '=='
+ string = string[1:].strip()
+ elif string[0:2] == '!=':
+ operator = '!='
+ string = string[2:].strip()
+ elif len(string.split(':')) == 2:
+ pre, post = string.split(':')
+ try:
+ return (True if float(pre) <= value and float(post) >= value else False)
+ except ValueError:
+ return (False if pre.strip() else True)
+ else:
+ return string in str(value)
+
+ try:
+ num = float(string) if string.strip() else 0
+ return eval(f'{value} {operator} {num}')
+ except ValueError:
+ if operator == '<': return True
+ return False
+
+def subtotal(data, field):
+ subtotal = 0.0
+ for row in data:
+ subtotal += row[field]
+ return subtotal
abbrev = lambda dt: ''.join(l[0].lower() for l in dt.split(' ')) + '.'
doclist = lambda dt, dfs: [abbrev(dt) + f for f in dfs]
@@ -148,24 +227,18 @@ def get_custom_reports(name=None):
return reports_dict
@frappe.whitelist()
-def save_custom_report(reference_report, report_name, columns, sections):
- import pymysql
+def save_custom_report(reference_report, report_name, data):
if reference_report != 'Tax Detail':
frappe.throw(_("The wrong report is referenced."))
if report_name == 'Tax Detail':
frappe.throw(_("The parent report cannot be overwritten."))
- data = {
- 'columns': json.loads(columns),
- 'sections': json.loads(sections)
- }
-
doc = {
'doctype': 'Report',
'report_name': report_name,
'is_standard': 'No',
'module': 'Accounts',
- 'json': json.dumps(data, separators=(',', ':'))
+ 'json': data
}
doc.update(custom_report_dict)
@@ -173,7 +246,7 @@ def save_custom_report(reference_report, report_name, columns, sections):
newdoc = frappe.get_doc(doc)
newdoc.insert()
frappe.msgprint(_("Report created successfully"))
- except (frappe.exceptions.DuplicateEntryError, pymysql.err.IntegrityError):
+ except frappe.exceptions.DuplicateEntryError:
dbdoc = frappe.get_doc('Report', report_name)
dbdoc.update(doc)
dbdoc.save()
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
new file mode 100644
index 0000000000..dfd8d9e121
--- /dev/null
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -0,0 +1,67 @@
+from __future__ import unicode_literals
+
+import frappe, unittest, datetime
+from frappe.utils import getdate
+from .tax_detail import execute, filter_match
+
+class TestTaxDetail(unittest.TestCase):
+ def setup(self):
+ pass
+
+ def test_filter_match(self):
+ # None - treated as -inf number except range
+ self.assertTrue(filter_match(None, '!='))
+ self.assertTrue(filter_match(None, '<'))
+ self.assertTrue(filter_match(None, '3.4'))
+ self.assertFalse(filter_match(None, ' <'))
+ self.assertFalse(filter_match(None, 'ew'))
+ self.assertFalse(filter_match(None, ' '))
+ self.assertFalse(filter_match(None, ' f :'))
+
+ # Numbers
+ self.assertTrue(filter_match(3.4, '3.4'))
+ self.assertTrue(filter_match(3.4, '.4'))
+ self.assertTrue(filter_match(3.4, '3'))
+ self.assertTrue(filter_match(-3.4, '< -3'))
+ self.assertTrue(filter_match(-3.4, '> -4'))
+ self.assertTrue(filter_match(3.4, '= 3.4 '))
+ self.assertTrue(filter_match(3.4, '!=4.5'))
+ self.assertTrue(filter_match(3.4, ' 3 : 4 '))
+ self.assertTrue(filter_match(0.0, ' : '))
+ self.assertFalse(filter_match(3.4, '=4.5'))
+ self.assertFalse(filter_match(3.4, ' = 3.4 '))
+ self.assertFalse(filter_match(3.4, '!=3.4'))
+ self.assertFalse(filter_match(3.4, '>6'))
+ self.assertFalse(filter_match(3.4, '<-4.5'))
+ self.assertFalse(filter_match(3.4, '4.5'))
+ self.assertFalse(filter_match(3.4, '5:9'))
+
+ # Strings
+ self.assertTrue(filter_match('ACC-SINV-2021-00001', 'SINV'))
+ self.assertTrue(filter_match('ACC-SINV-2021-00001', 'sinv'))
+ self.assertTrue(filter_match('ACC-SINV-2021-00001', '-2021'))
+ self.assertTrue(filter_match(' ACC-SINV-2021-00001', ' acc'))
+ self.assertTrue(filter_match('ACC-SINV-2021-00001', '=2021'))
+ self.assertTrue(filter_match('ACC-SINV-2021-00001', '!=zz'))
+ self.assertTrue(filter_match('ACC-SINV-2021-00001', '< zzz '))
+ self.assertTrue(filter_match('ACC-SINV-2021-00001', ' : sinv '))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', ' sinv :'))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', ' acc'))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', '= 2021 '))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', '!=sinv'))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', ' >'))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', '>aa'))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', ' <'))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', '< '))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', ' ='))
+ self.assertFalse(filter_match('ACC-SINV-2021-00001', '='))
+
+ # Date - always match
+ self.assertTrue(filter_match(datetime.date(2021, 3, 19), ' kdsjkldfs '))
From 8e413651c2b4cfc9c7754a482f353996393cd507 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Wed, 24 Mar 2021 02:56:30 +0000
Subject: [PATCH 071/262] fix: major refactor to monkey-patch into the
QueryReport class
---
.../accounts/report/tax_detail/tax_detail.js | 300 +++++++++---------
1 file changed, 153 insertions(+), 147 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 8cdce54852..6049000404 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -3,6 +3,8 @@
// Contributed by Case Solved and sponsored by Nulight Studios
/* eslint-disable */
+frappe.provide('frappe.query_reports');
+
frappe.query_reports["Tax Detail"] = {
filters: [
{
@@ -50,83 +52,124 @@ frappe.query_reports["Tax Detail"] = {
// Remove Add Column and Save from menu
report.page.add_inner_button(__("New Report"), () => new_report(), __("Custom Report"));
report.page.add_inner_button(__("Load Report"), () => load_report(), __("Custom Report"));
- hide_filters();
- },
- after_datatable_render: (datatable) => {
- if (frappe.query_report.report_name == 'Tax Detail') {
- return;
- }
- if (this.taxreport) {
- this.taxreport.load_report();
- } else {
- this.taxreport = new TaxReport();
- }
+ hide_filters(report);
}
};
-function hide_filters() {
- frappe.query_report.page.page_form[0].querySelectorAll('.form-group.frappe-control').forEach(function setHidden(field) {
+function hide_filters(report) {
+ report.page.page_form[0].querySelectorAll('.form-group.frappe-control').forEach(function setHidden(field) {
if (field.dataset.fieldtype == "Read Only") {
field.classList.add("hidden");
}
});
}
-class TaxReport {
- // construct after datatable is loaded
+erpnext.TaxDetail = class TaxDetail {
constructor() {
- this.qr = frappe.query_report;
- this.page = frappe.query_report.page;
- this.create_controls();
+ this.patch();
this.load_report();
}
- load_report() {
- if (this.loaded) {
- return;
+ // Monkey patch the QueryReport class
+ patch() {
+ this.qr = frappe.query_report;
+ this.super = {
+ refresh_report: this.qr.refresh_report,
+ show_footer_message: this.qr.show_footer_message
}
- const report_name = this.qr.report_name;
- this.report_name.value = report_name;
- frappe.call({
- method: 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports',
- args: {name: report_name},
- freeze: true
- }).then((r) => {
- const data = JSON.parse(r.message[report_name]['json']);
- this.sections = data.sections || {};
- this.controls['show_detail'].set_input(data.show_detail);
- this.set_section();
- })
- this.loaded = 1;
+ this.qr.refresh_report = () => this.refresh_report();
+ this.qr.show_footer_message = () => this.show_footer_message();
+ }
+ show_footer_message() {
+ // The last thing to run after datatable_render in refresh()
+ console.log('show_footer_message');
+ this.super.show_footer_message.apply(this.qr);
+ if (this.qr.report_name !== 'Tax Detail') {
+ this.set_value_options();
+ this.show_help();
+ if (this.loading) {
+ this.set_section('');
+ }
+ this.reload_filter();
+ }
+ this.loading = false;
+ }
+ refresh_report() {
+ // Infrequent report build (onload), load filters & data
+ // super function runs a refresh() serially
+ // already run within frappe.run_serially
+ console.log('refresh_report');
+ this.loading = true;
+ this.super.refresh_report.apply(this.qr);
+ if (this.qr.report_name !== 'Tax Detail') {
+ frappe.call({
+ method: 'erpnext.accounts.report.tax_detail.tax_detail.get_custom_reports',
+ args: {name: this.qr.report_name}
+ }).then((r) => {
+ const data = JSON.parse(r.message[this.qr.report_name]['json']);
+ this.create_controls();
+ this.sections = data.sections || {};
+ this.controls['show_detail'].set_input(data.show_detail);
+ });
+ }
+ }
+ load_report() {
+ // One-off report build like titles, menu, etc
+ // Run when this object is created which happens in qr.load_report
+ console.log('load_report');
+ this.qr.menu_items = this.get_menu_items();
+ }
+ get_menu_items() {
+ // Replace save button
+ let new_items = [];
+ const label = __('Save');
+
+ for (let item of this.qr.menu_items) {
+ if (item.label === label) {
+ new_items.push({
+ label: label,
+ action: this.save_report,
+ standard: false
+ });
+ } else {
+ new_items.push(item);
+ }
+ }
+ return new_items;
}
save_report() {
- frappe.call({
- method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report',
- args: {
- reference_report: 'Tax Detail',
- report_name: this.qr.report_name,
- data: {
- columns: this.qr.get_visible_columns(),
- sections: this.sections,
- show_detail: this.controls['show_detail'].get_input_value()
- }
- },
- freeze: true
- }).then((r) => {
- this.reload();
- });
+ if (this.qr.report_name !== 'Tax Detail') {
+ frappe.call({
+ method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report',
+ args: {
+ reference_report: 'Tax Detail',
+ report_name: this.qr.report_name,
+ data: {
+ columns: this.qr.get_visible_columns(),
+ sections: this.sections,
+ show_detail: this.controls['show_detail'].get_input_value()
+ }
+ },
+ freeze: true
+ }).then((r) => {
+ this.set_section('');
+ });
+ }
}
set_value_options() {
- this.fieldname_lookup = {};
- this.label_lookup = {};
- this.qr.columns.forEach((col, index) => {
- if (col['fieldtype'] == "Currency") {
- this.fieldname_lookup[col['label']] = col['fieldname'];
- this.label_lookup[col['fieldname']] = col['label'];
- }
- });
- const options = Object.keys(this.fieldname_lookup);
- this.controls['value_field'].$wrapper.find("select").empty().add_options(options);
- this.controls['value_field'].set_input(options[0]);
+ // May be run with no columns or data
+ if (this.qr.columns) {
+ this.fieldname_lookup = {};
+ this.label_lookup = {};
+ this.qr.columns.forEach((col, index) => {
+ if (col['fieldtype'] == "Currency") {
+ this.fieldname_lookup[col['label']] = col['fieldname'];
+ this.label_lookup[col['fieldname']] = col['label'];
+ }
+ });
+ const options = Object.keys(this.fieldname_lookup);
+ this.controls['value_field'].$wrapper.find("select").empty().add_options(options);
+ this.controls['value_field'].set_input(options[0]);
+ }
}
set_value_label_from_filter() {
const section_name = this.controls['section_name'].value;
@@ -158,46 +201,38 @@ class TaxReport {
});
dialog.show();
}
- get_filter_controls() {
- this.qr.filters.forEach(filter => {
- if (filter['fieldname'] == 'mode') {
- this.mode = filter;
- }
- if (filter['fieldname'] == 'report_name') {
- this.report_name = filter;
- }
- });
- }
- set_mode(mode) {
- this.mode.value = mode;
- }
- edit_mode() {
- return this.mode.value == 'edit';
- }
set_section(name) {
+ // Sets the given section name and then reloads the data
if (name && !this.sections[name]) {
this.sections[name] = {};
}
let options = Object.keys(this.sections);
options.unshift('');
this.controls['section_name'].$wrapper.find("select").empty().add_options(options);
+ const org_mode = this.qr.get_filter_value('mode');
+ let refresh = false;
if (name) {
this.controls['section_name'].set_input(name);
+ this.qr.set_filter_value('mode', 'edit');
+ if (org_mode === 'run') {
+ refresh = true;
+ }
} else {
this.controls['section_name'].set_input('');
+ this.qr.set_filter_value('mode', 'run');
+ if (org_mode === 'edit') {
+ refresh = true;
+ }
}
- if (this.controls['section_name'].value) {
- this.set_mode('edit');
- } else {
- this.set_mode('run');
+ this.reload_filter();
+ if (refresh) {
+ this.qr.refresh();
}
- this.controls['filter_index'].set_input('');
- this.reload();
}
reload_filter() {
- const section_name = this.controls['section_name'].value;
+ const section_name = this.controls['section_name'].get_input_value();
if (section_name) {
- let fidx = this.controls['filter_index'].value;
+ let fidx = this.controls['filter_index'].get_input_value();
let section = this.sections[section_name];
let fidxs = Object.keys(section);
fidxs.unshift('');
@@ -207,17 +242,16 @@ class TaxReport {
this.controls['filter_index'].$wrapper.find("select").empty();
this.controls['filter_index'].set_input('');
}
- this.set_filters();
+ this.set_table_filters();
}
- set_filters() {
+ set_table_filters() {
let filters = {};
- const section_name = this.controls['section_name'].value;
- const fidx = this.controls['filter_index'].value;
+ const section_name = this.controls['section_name'].get_input_value();
+ const fidx = this.controls['filter_index'].get_input_value();
if (section_name && fidx) {
filters = this.sections[section_name][fidx]['filters'];
}
this.setAppliedFilters(filters);
- this.qr.datatable.columnmanager.applyFilter(filters);
this.set_value_label_from_filter();
}
setAppliedFilters(filters) {
@@ -229,32 +263,20 @@ class TaxReport {
input.value = null;
}
});
- }
- reload() {
- // Reloads the data. When the datatable is reloaded, load_report()
- // will be run by the after_datatable_render event.
- // TODO: why does this trigger multiple reloads?
- this.qr.refresh();
- this.show_help();
- if (this.edit_mode()) {
- this.reload_filter();
- } else {
- this.controls['filter_index'].$wrapper.find("select").empty();
- }
+ this.qr.datatable.columnmanager.applyFilter(filters);
}
delete(name, type) {
if (type === 'section') {
delete this.sections[name];
- this.controls['section_name'].$wrapper.find("select").empty().add_options(Object.keys(this.sections));
- this.controls['section_name'].set_input(Object.keys(this.sections)[0] || '');
- this.controls['filter_index'].set_input('');
+ const new_section = Object.keys(this.sections)[0] || '';
+ this.set_section(new_section);
}
if (type === 'filter') {
- let cur_section = this.controls['section_name'].value;
+ const cur_section = this.controls['section_name'].get_input_value();
delete this.sections[cur_section][name];
this.controls['filter_index'].set_input('');
+ this.reload_filter();
}
- this.reload();
}
create_controls() {
if (this.controls) {
@@ -262,7 +284,7 @@ class TaxReport {
}
let controls = {};
// SELECT in data.js
- controls['section_name'] = this.page.add_field({
+ controls['section_name'] = this.qr.page.add_field({
label: __('Section'),
fieldtype: 'Select',
fieldname: 'section_name',
@@ -271,7 +293,7 @@ class TaxReport {
}
});
// BUTTON in button.js
- controls['new_section'] = this.page.add_field({
+ controls['new_section'] = this.qr.page.add_field({
label: __('New Section'),
fieldtype: 'Button',
fieldname: 'new_section',
@@ -279,33 +301,33 @@ class TaxReport {
this.new_section(__('New Section'));
}
});
- controls['delete_section'] = this.page.add_field({
+ controls['delete_section'] = this.qr.page.add_field({
label: __('Delete Section'),
fieldtype: 'Button',
fieldname: 'delete_section',
click: () => {
- let cur_section = this.controls['section_name'].value;
+ let cur_section = this.controls['section_name'].get_input_value();
if (cur_section) {
frappe.confirm(__('Are you sure you want to delete section ') + cur_section + '?',
() => {this.delete(cur_section, 'section')});
}
}
});
- controls['filter_index'] = this.page.add_field({
+ controls['filter_index'] = this.qr.page.add_field({
label: __('Filter'),
fieldtype: 'Select',
fieldname: 'filter_index',
change: (e) => {
this.controls['filter_index'].set_input(this.controls['filter_index'].get_input_value());
- this.set_filters();
+ this.set_table_filters();
}
});
- controls['add_filter'] = this.page.add_field({
+ controls['add_filter'] = this.qr.page.add_field({
label: __('Add Filter'),
fieldtype: 'Button',
fieldname: 'add_filter',
click: () => {
- let section_name = this.controls['section_name'].value;
+ let section_name = this.controls['section_name'].get_input_value();
if (section_name) {
let prefix = 'Filter';
let data = {
@@ -326,19 +348,19 @@ class TaxReport {
}
}
});
- controls['delete_filter'] = this.page.add_field({
+ controls['delete_filter'] = this.qr.page.add_field({
label: __('Delete Filter'),
fieldtype: 'Button',
fieldname: 'delete_filter',
click: () => {
- let cur_filter = this.controls['filter_index'].value;
+ let cur_filter = this.controls['filter_index'].get_input_value();
if (cur_filter) {
frappe.confirm(__('Are you sure you want to delete filter ') + cur_filter + '?',
() => {this.delete(cur_filter, 'filter')});
}
}
});
- controls['value_field'] = this.page.add_field({
+ controls['value_field'] = this.qr.page.add_field({
label: __('Value Column'),
fieldtype: 'Select',
fieldname: 'value_field',
@@ -346,37 +368,35 @@ class TaxReport {
this.controls['value_field'].set_input(this.controls['value_field'].get_input_value());
}
});
- controls['save'] = this.page.add_field({
+ controls['save'] = this.qr.page.add_field({
label: __('Save & Run'),
fieldtype: 'Button',
fieldname: 'save',
click: () => {
- this.controls['section_name'].set_input('');
- this.set_mode('run');
this.save_report();
}
});
- controls['show_detail'] = this.page.add_field({
+ controls['show_detail'] = this.qr.page.add_field({
label: __('Show Detail'),
fieldtype: 'Check',
fieldname: 'show_detail',
default: 1
});
this.controls = controls;
- this.set_value_options();
- this.get_filter_controls();
- this.show_help();
}
show_help() {
const help = __(`You can add multiple sections to your custom report using the New Section button above.
- To specify what data goes in each section, specify column filters below, then save with Add Filter.
- Each section can have multiple filters added.
- You can specify which Currency column will be summed for each filter in the final report with the Value Column select box.
- Once you're done, hit Save & Run.`);
- this.qr.show_status(help);
+ To specify what data goes in each section, specify column filters in the data table, then save with Add Filter.
+ Each section can have multiple filters added but be careful with the duplicated data rows.
+ You can specify which Currency column will be summed for each filter in the final report with the Value Column
+ select box. Once you're done, hit Save & Run.`);
+ this.qr.$report_footer.append(`${help}
`);
}
}
+if (!window.taxdetail) {
+ window.taxdetail = new erpnext.TaxDetail();
+}
function get_reports(cb) {
frappe.call({
@@ -387,23 +407,9 @@ function get_reports(cb) {
})
}
-function override_menu() {
- //TODO: Replace save button
- this.qr.menu_items.forEach((item, idx) => {
- if (item['label'] == __('Save')) {
- delete this.qr.menu_items[idx];
- }
- })
- this.qr.menu_items.push({
- label: __('Save'),
- action: this.save_report
- })
- this.qr.set_menu_items();
-}
-
function new_report() {
const dialog = new frappe.ui.Dialog({
- title: __("New Report"),
+ title: __('New Report'),
fields: [
{
fieldname: 'report_name',
@@ -424,7 +430,7 @@ function new_report() {
},
freeze: true
}).then((r) => {
- frappe.set_route("query-report", values.report_name);
+ frappe.set_route('query-report', values.report_name);
});
dialog.hide();
}
@@ -435,7 +441,7 @@ function new_report() {
function load_report() {
get_reports(function load_report_cb(reports) {
const dialog = new frappe.ui.Dialog({
- title: __("Load Report"),
+ title: __('Load Report'),
fields: [
{
fieldname: 'report_name',
@@ -447,7 +453,7 @@ function load_report() {
primary_action_label: __('Load'),
primary_action: function load_report_pa(values) {
dialog.hide();
- frappe.set_route("query-report", values.report_name);
+ frappe.set_route('query-report', values.report_name);
}
});
dialog.show();
From 5d9217ab29d2f335b862a06f17f07151c8684051 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Wed, 24 Mar 2021 04:01:18 +0000
Subject: [PATCH 072/262] fix: minor bugs and improvements
---
.../accounts/report/tax_detail/tax_detail.js | 22 +++++++++----------
.../accounts/report/tax_detail/tax_detail.py | 4 +++-
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 6049000404..5da63dec57 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -81,7 +81,6 @@ erpnext.TaxDetail = class TaxDetail {
}
show_footer_message() {
// The last thing to run after datatable_render in refresh()
- console.log('show_footer_message');
this.super.show_footer_message.apply(this.qr);
if (this.qr.report_name !== 'Tax Detail') {
this.set_value_options();
@@ -97,7 +96,6 @@ erpnext.TaxDetail = class TaxDetail {
// Infrequent report build (onload), load filters & data
// super function runs a refresh() serially
// already run within frappe.run_serially
- console.log('refresh_report');
this.loading = true;
this.super.refresh_report.apply(this.qr);
if (this.qr.report_name !== 'Tax Detail') {
@@ -115,21 +113,23 @@ erpnext.TaxDetail = class TaxDetail {
load_report() {
// One-off report build like titles, menu, etc
// Run when this object is created which happens in qr.load_report
- console.log('load_report');
this.qr.menu_items = this.get_menu_items();
}
get_menu_items() {
- // Replace save button
+ // Replace Save, remove Add Column
let new_items = [];
- const label = __('Save');
+ const save = __('Save');
+ const addColumn = __('Add Column');
for (let item of this.qr.menu_items) {
- if (item.label === label) {
+ if (item.label === save) {
new_items.push({
- label: label,
- action: this.save_report,
+ label: save,
+ action: () => this.save_report(),
standard: false
});
+ } else if (item.label === addColumn) {
+ // Don't add
} else {
new_items.push(item);
}
@@ -279,9 +279,6 @@ erpnext.TaxDetail = class TaxDetail {
}
}
create_controls() {
- if (this.controls) {
- return;
- }
let controls = {};
// SELECT in data.js
controls['section_name'] = this.qr.page.add_field({
@@ -389,7 +386,8 @@ erpnext.TaxDetail = class TaxDetail {
To specify what data goes in each section, specify column filters in the data table, then save with Add Filter.
Each section can have multiple filters added but be careful with the duplicated data rows.
You can specify which Currency column will be summed for each filter in the final report with the Value Column
- select box. Once you're done, hit Save & Run.`);
+ select box. Use the Show Detail box to see the data rows included in each section in the final report.
+ Once you're done, hit Save & Run.`);
this.qr.$report_footer.append(`${help}
`);
}
}
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index 6bed89841c..db1bf5b678 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -6,6 +6,8 @@ from __future__ import unicode_literals
import frappe, json
from frappe import _
+# NOTE: Not compatible with the frappe custom report feature of adding arbitrary doctype columns to the report
+
# field lists in multiple doctypes will be coalesced
required_sql_fields = {
"GL Entry": ["posting_date", "voucher_type", "voucher_no", "account", "account_currency", "debit", "credit"],
@@ -87,7 +89,7 @@ def run_report(report_name, data):
new_data += [ {columns[1]['fieldname']: section_name, columns[2]['fieldname']: section_total} ]
summary += [ {'label': section_name, 'datatype': 'Currency', 'value': section_total} ]
if show_detail: new_data += [ {} ]
- return new_data if new_data else data, summary
+ return new_data or data, summary or None
def filter_match(value, string):
"Approximation to datatable filters"
From 3027cc7da61c81b8b99ea672917766e5c0530fc7 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Wed, 24 Mar 2021 04:30:28 +0000
Subject: [PATCH 073/262] fix: minor bug and tidy
---
erpnext/accounts/report/tax_detail/tax_detail.js | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 5da63dec57..391aacf391 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -172,8 +172,8 @@ erpnext.TaxDetail = class TaxDetail {
}
}
set_value_label_from_filter() {
- const section_name = this.controls['section_name'].value;
- const fidx = this.controls['filter_index'].value;
+ const section_name = this.controls['section_name'].get_input_value();
+ const fidx = this.controls['filter_index'].get_input_value();
if (section_name && fidx) {
const fieldname = this.sections[section_name][fidx]['fieldname'];
this.controls['value_field'].set_input(this.label_lookup[fieldname]);
@@ -182,7 +182,7 @@ erpnext.TaxDetail = class TaxDetail {
}
}
get_value_fieldname() {
- const curlabel = this.controls['value_field'].value;
+ const curlabel = this.controls['value_field'].get_input_value();
return this.fieldname_lookup[curlabel];
}
new_section(label) {
@@ -203,6 +203,7 @@ erpnext.TaxDetail = class TaxDetail {
}
set_section(name) {
// Sets the given section name and then reloads the data
+ this.controls['filter_index'].set_input('');
if (name && !this.sections[name]) {
this.sections[name] = {};
}
@@ -224,10 +225,10 @@ erpnext.TaxDetail = class TaxDetail {
refresh = true;
}
}
- this.reload_filter();
if (refresh) {
this.qr.refresh();
}
+ this.reload_filter();
}
reload_filter() {
const section_name = this.controls['section_name'].get_input_value();
From ece00287eadf326e68945c4221ee20429306cb9a Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sat, 27 Mar 2021 03:02:30 +0000
Subject: [PATCH 074/262] Refactor for Journal Entries (payroll)
---
.../accounts/report/tax_detail/tax_detail.py | 90 ++++++++++++++-----
1 file changed, 69 insertions(+), 21 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index db1bf5b678..b08e796807 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -7,15 +7,18 @@ import frappe, json
from frappe import _
# NOTE: Not compatible with the frappe custom report feature of adding arbitrary doctype columns to the report
+# NOTE: Payroll is implemented using Journal Entries
# field lists in multiple doctypes will be coalesced
required_sql_fields = {
- "GL Entry": ["posting_date", "voucher_type", "voucher_no", "account", "account_currency", "debit", "credit"],
- "Account": ["account_type"],
+ "GL Entry": ["posting_date", "voucher_type", "voucher_no", "account as tax_account", "account_currency", "debit", "credit"],
+# "Account": ["account_type"],
+ "Journal Entry Account": ["account_type", "account", "debit_in_account_currency", "credit_in_account_currency"],
+ ("Purchase Invoice Item", "Sales Invoice Item"): ["base_net_amount", "item_tax_rate", "item_tax_template", "item_name"],
("Purchase Invoice", "Sales Invoice"): ["taxes_and_charges", "tax_category"],
- ("Purchase Invoice Item", "Sales Invoice Item"): ["item_tax_template", "item_name", "base_net_amount", "item_tax_rate"],
# "Journal Entry": ["total_amount_currency"],
-# "Journal Entry Account": ["debit_in_account_currency", "credit_in_account_currency"]
+ "Purchase Invoice Item": ["expense_account"],
+ "Sales Invoice Item": ["income_account"]
}
@@ -40,9 +43,9 @@ def execute(filters=None):
left join `tabPurchase Invoice Item` pii on
pi.name=pii.parent
/* left outer join `tabJournal Entry` je on
- ge.voucher_no=je.name and ge.company=je.company
+ ge.voucher_no=je.name and ge.company=je.company */
left outer join `tabJournal Entry Account` jea on
- je.name=jea.parent and a.account_type='Tax' */
+ ge.voucher_type=jea.parenttype and ge.voucher_no=jea.parent
where (ge.voucher_type, ge.voucher_no) in (
select ge.voucher_type, ge.voucher_no
from `tabGL Entry` ge
@@ -142,7 +145,18 @@ def subtotal(data, field):
abbrev = lambda dt: ''.join(l[0].lower() for l in dt.split(' ')) + '.'
doclist = lambda dt, dfs: [abbrev(dt) + f for f in dfs]
-coalesce = lambda dts, dfs: ['coalesce(' + ', '.join(abbrev(dt) + f for dt in dts) + ') ' + f for f in dfs]
+
+def as_split(fields):
+ for field in fields:
+ split = field.split(' as ')
+ yield (split[0], split[1] if len(split) > 1 else split[0])
+
+def coalesce(doctypes, fields):
+ coalesce = []
+ for name, new_name in as_split(fields):
+ sharedfields = ', '.join(abbrev(dt) + name for dt in doctypes)
+ coalesce += [f'coalesce({sharedfields}) as {new_name}']
+ return coalesce
def get_fieldstr(fieldlist):
fields = []
@@ -158,20 +172,22 @@ def get_columns(fieldlist):
for doctypes, docfields in fieldlist.items():
if isinstance(doctypes, str):
doctypes = [doctypes]
+ fieldmap = {name: new_name for name, new_name in as_split(docfields)}
for doctype in doctypes:
meta = frappe.get_meta(doctype)
# get column field metadata from the db
fieldmeta = {}
for field in meta.get('fields'):
- if field.fieldname in docfields:
- fieldmeta[field.fieldname] = {
+ if field.fieldname in fieldmap.keys():
+ new_name = fieldmap[field.fieldname]
+ fieldmeta[new_name] = {
"label": _(field.label),
- "fieldname": field.fieldname,
+ "fieldname": new_name,
"fieldtype": field.fieldtype,
"options": field.options
}
# edit the columns to match the modified data
- for field in docfields:
+ for field in fieldmap.values():
col = modify_report_columns(doctype, field, fieldmeta[field])
if col:
columns[col["fieldname"]] = col
@@ -182,10 +198,28 @@ def modify_report_columns(doctype, field, column):
"Because data is rearranged into other columns"
if doctype in ["Sales Invoice Item", "Purchase Invoice Item"] and field == "item_tax_rate":
return None
+ if doctype == "GL Entry" and field == "tax_account":
+ column.update({"label": _("Tax Account")})
+ if doctype == "GL Entry" and field == "debit":
+ column.update({"label": _("Tax Debit")})
+ if doctype == "GL Entry" and field == "credit":
+ column.update({"label": _("Tax Credit")})
+
+ if doctype == "Journal Entry Account" and field == "debit_in_account_currency":
+ column.update({"label": _("Debit Net Amount"), "fieldname": "debit_net_amount"})
+ if doctype == "Journal Entry Account" and field == "credit_in_account_currency":
+ column.update({"label": _("Credit Net Amount"), "fieldname": "credit_net_amount"})
+
if doctype == "Sales Invoice Item" and field == "base_net_amount":
column.update({"label": _("Credit Net Amount"), "fieldname": "credit_net_amount"})
+ if doctype == "Sales Invoice Item" and field == "income_account":
+ column.update({"label": _("Account"), "fieldname": "account"})
+
if doctype == "Purchase Invoice Item" and field == "base_net_amount":
column.update({"label": _("Debit Net Amount"), "fieldname": "debit_net_amount"})
+ if doctype == "Purchase Invoice Item" and field == "expense_account":
+ column.update({"label": _("Account"), "fieldname": "account"})
+
if field == "taxes_and_charges":
column.update({"label": _("Taxes and Charges Template")})
return column
@@ -193,16 +227,30 @@ def modify_report_columns(doctype, field, column):
def modify_report_data(data):
import json
for line in data:
- if line.account_type == "Tax" and line.item_tax_rate:
- tax_rates = json.loads(line.item_tax_rate)
- for account, rate in tax_rates.items():
- if account == line.account:
- if line.voucher_type == "Sales Invoice":
- line.credit = line.base_net_amount * (rate / 100)
- line.credit_net_amount = line.base_net_amount
- if line.voucher_type == "Purchase Invoice":
- line.debit = line.base_net_amount * (rate / 100)
- line.debit_net_amount = line.base_net_amount
+ # Transform Invoice lines
+ if "Invoice" in line.voucher_type:
+ if line.income_account:
+ line.account = line.income_account
+ line.account_type = "Income Account"
+ if line.expense_account:
+ line.account = line.expense_account
+ line.account_type = "Expense Account"
+ if line.item_tax_rate:
+ tax_rates = json.loads(line.item_tax_rate)
+ for account, rate in tax_rates.items():
+ if account == line.account:
+ if line.voucher_type == "Sales Invoice":
+ line.credit = line.base_net_amount * (rate / 100)
+ line.credit_net_amount = line.base_net_amount
+ if line.voucher_type == "Purchase Invoice":
+ line.debit = line.base_net_amount * (rate / 100)
+ line.debit_net_amount = line.base_net_amount
+ # Transform Journal Entry lines
+ if "Journal" in line.voucher_type:
+ if line.debit_in_account_currency:
+ line.debit_net_amount = line.debit_in_account_currency
+ if line.credit_in_account_currency:
+ line.credit_net_amount = line.credit_in_account_currency
return data
####### JS client utilities
From 442a0de09496a843c33f24e98c59ffa0ec5138df Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sat, 27 Mar 2021 04:02:59 +0000
Subject: [PATCH 075/262] fix: finalise query, fix bugs, put Add Columns back
---
.../accounts/report/tax_detail/tax_detail.js | 12 +++----
.../accounts/report/tax_detail/tax_detail.py | 31 +++++++------------
2 files changed, 18 insertions(+), 25 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 391aacf391..56694fbec2 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -116,10 +116,9 @@ erpnext.TaxDetail = class TaxDetail {
this.qr.menu_items = this.get_menu_items();
}
get_menu_items() {
- // Replace Save, remove Add Column
+ // Replace Save action
let new_items = [];
const save = __('Save');
- const addColumn = __('Add Column');
for (let item of this.qr.menu_items) {
if (item.label === save) {
@@ -128,8 +127,6 @@ erpnext.TaxDetail = class TaxDetail {
action: () => this.save_report(),
standard: false
});
- } else if (item.label === addColumn) {
- // Don't add
} else {
new_items.push(item);
}
@@ -424,8 +421,11 @@ function new_report() {
args: {
reference_report: 'Tax Detail',
report_name: values.report_name,
- columns: frappe.query_report.get_visible_columns(),
- sections: {}
+ data: {
+ columns: [],
+ sections: {},
+ show_detail: 1
+ }
},
freeze: true
}).then((r) => {
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index b08e796807..c4ec1374ce 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -6,17 +6,14 @@ from __future__ import unicode_literals
import frappe, json
from frappe import _
-# NOTE: Not compatible with the frappe custom report feature of adding arbitrary doctype columns to the report
# NOTE: Payroll is implemented using Journal Entries
# field lists in multiple doctypes will be coalesced
required_sql_fields = {
"GL Entry": ["posting_date", "voucher_type", "voucher_no", "account as tax_account", "account_currency", "debit", "credit"],
-# "Account": ["account_type"],
"Journal Entry Account": ["account_type", "account", "debit_in_account_currency", "credit_in_account_currency"],
("Purchase Invoice Item", "Sales Invoice Item"): ["base_net_amount", "item_tax_rate", "item_tax_template", "item_name"],
("Purchase Invoice", "Sales Invoice"): ["taxes_and_charges", "tax_category"],
-# "Journal Entry": ["total_amount_currency"],
"Purchase Invoice Item": ["expense_account"],
"Sales Invoice Item": ["income_account"]
}
@@ -35,27 +32,20 @@ def execute(filters=None):
inner join `tabAccount` a on
ge.account=a.name and ge.company=a.company
left join `tabSales Invoice` si on
- a.account_type='Tax' and ge.company=si.company and ge.voucher_type='Sales Invoice' and ge.voucher_no=si.name
+ ge.company=si.company and ge.voucher_type='Sales Invoice' and ge.voucher_no=si.name
left join `tabSales Invoice Item` sii on
si.name=sii.parent
left join `tabPurchase Invoice` pi on
- a.account_type='Tax' and ge.company=pi.company and ge.voucher_type='Purchase Invoice' and ge.voucher_no=pi.name
+ ge.company=pi.company and ge.voucher_type='Purchase Invoice' and ge.voucher_no=pi.name
left join `tabPurchase Invoice Item` pii on
pi.name=pii.parent
-/* left outer join `tabJournal Entry` je on
- ge.voucher_no=je.name and ge.company=je.company */
- left outer join `tabJournal Entry Account` jea on
+ left join `tabJournal Entry Account` jea on
ge.voucher_type=jea.parenttype and ge.voucher_no=jea.parent
- where (ge.voucher_type, ge.voucher_no) in (
- select ge.voucher_type, ge.voucher_no
- from `tabGL Entry` ge
- join `tabAccount` a on ge.account=a.name and ge.company=a.company
- where
- a.account_type='Tax' and
- ge.company=%(company)s and
- ge.posting_date>=%(from_date)s and
- ge.posting_date<=%(to_date)s
- )
+ where
+ a.account_type='Tax' and
+ ge.company=%(company)s and
+ ge.posting_date>=%(from_date)s and
+ ge.posting_date<=%(to_date)s
order by ge.posting_date, ge.voucher_no
""".format(fieldstr=fieldstr), filters, as_dict=1)
@@ -238,7 +228,7 @@ def modify_report_data(data):
if line.item_tax_rate:
tax_rates = json.loads(line.item_tax_rate)
for account, rate in tax_rates.items():
- if account == line.account:
+ if account == line.tax_account:
if line.voucher_type == "Sales Invoice":
line.credit = line.base_net_amount * (rate / 100)
line.credit_net_amount = line.base_net_amount
@@ -247,6 +237,9 @@ def modify_report_data(data):
line.debit_net_amount = line.base_net_amount
# Transform Journal Entry lines
if "Journal" in line.voucher_type:
+ if line.account_type != 'Tax':
+ line.debit = 0.0
+ line.credit = 0.0
if line.debit_in_account_currency:
line.debit_net_amount = line.debit_in_account_currency
if line.credit_in_account_currency:
From 1c37390899724d152a2152d50e2e0c543368471e Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Tue, 30 Mar 2021 17:03:16 +0000
Subject: [PATCH 076/262] fix: Change & simplify query to cater for zero rate
tax entries
---
.../accounts/report/tax_detail/tax_detail.py | 94 ++++++-------------
1 file changed, 31 insertions(+), 63 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index c4ec1374ce..1f4d1ba8a0 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -6,16 +6,15 @@ from __future__ import unicode_literals
import frappe, json
from frappe import _
-# NOTE: Payroll is implemented using Journal Entries
+# NOTE: Payroll is implemented using Journal Entries which translate directly to GL Entries
# field lists in multiple doctypes will be coalesced
required_sql_fields = {
- "GL Entry": ["posting_date", "voucher_type", "voucher_no", "account as tax_account", "account_currency", "debit", "credit"],
- "Journal Entry Account": ["account_type", "account", "debit_in_account_currency", "credit_in_account_currency"],
- ("Purchase Invoice Item", "Sales Invoice Item"): ["base_net_amount", "item_tax_rate", "item_tax_template", "item_name"],
+ ("GL Entry", 1): ["posting_date"],
+ ("Account",): ["account_type"],
+ ("GL Entry", 2): ["account", "voucher_type", "voucher_no", "debit", "credit"],
+ ("Purchase Invoice Item", "Sales Invoice Item"): ["base_net_amount", "item_tax_rate", "item_tax_template", "item_group", "item_name"],
("Purchase Invoice", "Sales Invoice"): ["taxes_and_charges", "tax_category"],
- "Purchase Invoice Item": ["expense_account"],
- "Sales Invoice Item": ["income_account"]
}
@@ -34,15 +33,12 @@ def execute(filters=None):
left join `tabSales Invoice` si on
ge.company=si.company and ge.voucher_type='Sales Invoice' and ge.voucher_no=si.name
left join `tabSales Invoice Item` sii on
- si.name=sii.parent
+ a.root_type='Income' and si.name=sii.parent
left join `tabPurchase Invoice` pi on
ge.company=pi.company and ge.voucher_type='Purchase Invoice' and ge.voucher_no=pi.name
left join `tabPurchase Invoice Item` pii on
- pi.name=pii.parent
- left join `tabJournal Entry Account` jea on
- ge.voucher_type=jea.parenttype and ge.voucher_no=jea.parent
+ a.root_type='Expense' and pi.name=pii.parent
where
- a.account_type='Tax' and
ge.company=%(company)s and
ge.posting_date>=%(from_date)s and
ge.posting_date<=%(to_date)s
@@ -151,19 +147,18 @@ def coalesce(doctypes, fields):
def get_fieldstr(fieldlist):
fields = []
for doctypes, docfields in fieldlist.items():
- if isinstance(doctypes, str):
- fields += doclist(doctypes, docfields)
- if isinstance(doctypes, tuple):
+ if len(doctypes) == 1 or isinstance(doctypes[1], int):
+ fields += doclist(doctypes[0], docfields)
+ else:
fields += coalesce(doctypes, docfields)
return ', '.join(fields)
def get_columns(fieldlist):
columns = {}
for doctypes, docfields in fieldlist.items():
- if isinstance(doctypes, str):
- doctypes = [doctypes]
fieldmap = {name: new_name for name, new_name in as_split(docfields)}
for doctype in doctypes:
+ if isinstance(doctype, int): break
meta = frappe.get_meta(doctype)
# get column field metadata from the db
fieldmeta = {}
@@ -186,29 +181,9 @@ def get_columns(fieldlist):
def modify_report_columns(doctype, field, column):
"Because data is rearranged into other columns"
- if doctype in ["Sales Invoice Item", "Purchase Invoice Item"] and field == "item_tax_rate":
- return None
- if doctype == "GL Entry" and field == "tax_account":
- column.update({"label": _("Tax Account")})
- if doctype == "GL Entry" and field == "debit":
- column.update({"label": _("Tax Debit")})
- if doctype == "GL Entry" and field == "credit":
- column.update({"label": _("Tax Credit")})
-
- if doctype == "Journal Entry Account" and field == "debit_in_account_currency":
- column.update({"label": _("Debit Net Amount"), "fieldname": "debit_net_amount"})
- if doctype == "Journal Entry Account" and field == "credit_in_account_currency":
- column.update({"label": _("Credit Net Amount"), "fieldname": "credit_net_amount"})
-
- if doctype == "Sales Invoice Item" and field == "base_net_amount":
- column.update({"label": _("Credit Net Amount"), "fieldname": "credit_net_amount"})
- if doctype == "Sales Invoice Item" and field == "income_account":
- column.update({"label": _("Account"), "fieldname": "account"})
-
- if doctype == "Purchase Invoice Item" and field == "base_net_amount":
- column.update({"label": _("Debit Net Amount"), "fieldname": "debit_net_amount"})
- if doctype == "Purchase Invoice Item" and field == "expense_account":
- column.update({"label": _("Account"), "fieldname": "account"})
+ if doctype in ["Sales Invoice Item", "Purchase Invoice Item"]:
+ if field in ["item_tax_rate", "base_net_amount"]:
+ return None
if field == "taxes_and_charges":
column.update({"label": _("Taxes and Charges Template")})
@@ -216,35 +191,28 @@ def modify_report_columns(doctype, field, column):
def modify_report_data(data):
import json
+ new_data = []
for line in data:
- # Transform Invoice lines
+ # Remove Invoice GL Tax Entries and generate Tax entries from the invoice lines
if "Invoice" in line.voucher_type:
- if line.income_account:
- line.account = line.income_account
- line.account_type = "Income Account"
- if line.expense_account:
- line.account = line.expense_account
- line.account_type = "Expense Account"
+ if line.account_type != "Tax":
+ new_data += [line]
if line.item_tax_rate:
tax_rates = json.loads(line.item_tax_rate)
for account, rate in tax_rates.items():
- if account == line.tax_account:
- if line.voucher_type == "Sales Invoice":
- line.credit = line.base_net_amount * (rate / 100)
- line.credit_net_amount = line.base_net_amount
- if line.voucher_type == "Purchase Invoice":
- line.debit = line.base_net_amount * (rate / 100)
- line.debit_net_amount = line.base_net_amount
- # Transform Journal Entry lines
- if "Journal" in line.voucher_type:
- if line.account_type != 'Tax':
- line.debit = 0.0
- line.credit = 0.0
- if line.debit_in_account_currency:
- line.debit_net_amount = line.debit_in_account_currency
- if line.credit_in_account_currency:
- line.credit_net_amount = line.credit_in_account_currency
- return data
+ tax_line = line.copy()
+ tax_line.account_type = "Tax"
+ tax_line.account = account
+ if line.voucher_type == "Sales Invoice":
+ line.credit = line.base_net_amount
+ tax_line.credit = line.base_net_amount * (rate / 100)
+ if line.voucher_type == "Purchase Invoice":
+ line.debit = line.base_net_amount
+ tax_line.debit = line.base_net_amount * (rate / 100)
+ new_data += [tax_line]
+ else:
+ new_data += [line]
+ return new_data
####### JS client utilities
From 2cb0da8780cedb4b13d76a40766427f9f2632e8d Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Thu, 1 Apr 2021 22:31:24 +0000
Subject: [PATCH 077/262] fix: rewrite to allow referring to existing sections
and reduce to single amount column
---
.../accounts/report/tax_detail/tax_detail.js | 235 +++++++++---------
.../accounts/report/tax_detail/tax_detail.py | 60 +++--
2 files changed, 153 insertions(+), 142 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 56694fbec2..0c0397ab04 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -43,7 +43,7 @@ frappe.query_reports["Tax Detail"] = {
fieldname: "mode",
label: __("Mode"),
fieldtype: "Read Only",
- default: "run",
+ default: "edit",
hidden: 1,
reqd: 1
}
@@ -83,12 +83,12 @@ erpnext.TaxDetail = class TaxDetail {
// The last thing to run after datatable_render in refresh()
this.super.show_footer_message.apply(this.qr);
if (this.qr.report_name !== 'Tax Detail') {
- this.set_value_options();
this.show_help();
if (this.loading) {
this.set_section('');
+ } else {
+ this.reload_component('');
}
- this.reload_filter();
}
this.loading = false;
}
@@ -134,6 +134,7 @@ erpnext.TaxDetail = class TaxDetail {
return new_items;
}
save_report() {
+ this.check_datatable();
if (this.qr.report_name !== 'Tax Detail') {
frappe.call({
method:'erpnext.accounts.report.tax_detail.tax_detail.save_custom_report',
@@ -152,55 +153,13 @@ erpnext.TaxDetail = class TaxDetail {
});
}
}
- set_value_options() {
- // May be run with no columns or data
- if (this.qr.columns) {
- this.fieldname_lookup = {};
- this.label_lookup = {};
- this.qr.columns.forEach((col, index) => {
- if (col['fieldtype'] == "Currency") {
- this.fieldname_lookup[col['label']] = col['fieldname'];
- this.label_lookup[col['fieldname']] = col['label'];
- }
- });
- const options = Object.keys(this.fieldname_lookup);
- this.controls['value_field'].$wrapper.find("select").empty().add_options(options);
- this.controls['value_field'].set_input(options[0]);
+ check_datatable() {
+ if (!this.qr.datatable) {
+ frappe.throw(__('Please change the date range to load data first'));
}
}
- set_value_label_from_filter() {
- const section_name = this.controls['section_name'].get_input_value();
- const fidx = this.controls['filter_index'].get_input_value();
- if (section_name && fidx) {
- const fieldname = this.sections[section_name][fidx]['fieldname'];
- this.controls['value_field'].set_input(this.label_lookup[fieldname]);
- } else {
- this.controls['value_field'].set_input(Object.keys(this.fieldname_lookup)[0]);
- }
- }
- get_value_fieldname() {
- const curlabel = this.controls['value_field'].get_input_value();
- return this.fieldname_lookup[curlabel];
- }
- new_section(label) {
- const dialog = new frappe.ui.Dialog({
- title: label,
- fields: [{
- fieldname: 'data',
- label: label,
- fieldtype: 'Data'
- }],
- primary_action_label: label,
- primary_action: (values) => {
- dialog.hide();
- this.set_section(values.data);
- }
- });
- dialog.show();
- }
set_section(name) {
// Sets the given section name and then reloads the data
- this.controls['filter_index'].set_input('');
if (name && !this.sections[name]) {
this.sections[name] = {};
}
@@ -225,43 +184,49 @@ erpnext.TaxDetail = class TaxDetail {
if (refresh) {
this.qr.refresh();
}
- this.reload_filter();
+ this.reload_component('');
}
- reload_filter() {
+ reload_component(component_name) {
const section_name = this.controls['section_name'].get_input_value();
if (section_name) {
- let fidx = this.controls['filter_index'].get_input_value();
- let section = this.sections[section_name];
- let fidxs = Object.keys(section);
- fidxs.unshift('');
- this.controls['filter_index'].$wrapper.find("select").empty().add_options(fidxs);
- this.controls['filter_index'].set_input(fidx);
+ const section = this.sections[section_name];
+ const component_names = Object.keys(section);
+ component_names.unshift('');
+ this.controls['component'].$wrapper.find("select").empty().add_options(component_names);
+ this.controls['component'].set_input(component_name);
+ if (component_name) {
+ this.controls['component_type'].set_input(section[component_name].type);
+ }
} else {
- this.controls['filter_index'].$wrapper.find("select").empty();
- this.controls['filter_index'].set_input('');
+ this.controls['component'].$wrapper.find("select").empty();
+ this.controls['component'].set_input('');
}
this.set_table_filters();
}
set_table_filters() {
let filters = {};
const section_name = this.controls['section_name'].get_input_value();
- const fidx = this.controls['filter_index'].get_input_value();
- if (section_name && fidx) {
- filters = this.sections[section_name][fidx]['filters'];
+ const component_name = this.controls['component'].get_input_value();
+ if (section_name && component_name) {
+ const component_type = this.sections[section_name][component_name].type;
+ if (component_type === 'filter') {
+ filters = this.sections[section_name][component_name]['filters'];
+ }
}
this.setAppliedFilters(filters);
- this.set_value_label_from_filter();
}
setAppliedFilters(filters) {
- Array.from(this.qr.datatable.header.querySelectorAll('.dt-filter')).map(function setFilters(input) {
- let idx = input.dataset.colIndex;
- if (filters[idx]) {
- input.value = filters[idx];
- } else {
- input.value = null;
- }
- });
- this.qr.datatable.columnmanager.applyFilter(filters);
+ if (this.qr.datatable) {
+ Array.from(this.qr.datatable.header.querySelectorAll('.dt-filter')).map(function setFilters(input) {
+ let idx = input.dataset.colIndex;
+ if (filters[idx]) {
+ input.value = filters[idx];
+ } else {
+ input.value = null;
+ }
+ });
+ this.qr.datatable.columnmanager.applyFilter(filters);
+ }
}
delete(name, type) {
if (type === 'section') {
@@ -269,11 +234,10 @@ erpnext.TaxDetail = class TaxDetail {
const new_section = Object.keys(this.sections)[0] || '';
this.set_section(new_section);
}
- if (type === 'filter') {
+ if (type === 'component') {
const cur_section = this.controls['section_name'].get_input_value();
delete this.sections[cur_section][name];
- this.controls['filter_index'].set_input('');
- this.reload_filter();
+ this.reload_component('');
}
}
create_controls() {
@@ -293,7 +257,13 @@ erpnext.TaxDetail = class TaxDetail {
fieldtype: 'Button',
fieldname: 'new_section',
click: () => {
- this.new_section(__('New Section'));
+ frappe.prompt({
+ label: __('Section Name'),
+ fieldname: 'name',
+ fieldtype: 'Data'
+ }, (values) => {
+ this.set_section(values.name);
+ });
}
});
controls['delete_section'] = this.qr.page.add_field({
@@ -308,61 +278,87 @@ erpnext.TaxDetail = class TaxDetail {
}
}
});
- controls['filter_index'] = this.qr.page.add_field({
- label: __('Filter'),
+ controls['component'] = this.qr.page.add_field({
+ label: __('Component'),
fieldtype: 'Select',
- fieldname: 'filter_index',
+ fieldname: 'component',
change: (e) => {
- this.controls['filter_index'].set_input(this.controls['filter_index'].get_input_value());
- this.set_table_filters();
+ this.reload_component(this.controls['component'].get_input_value());
}
});
- controls['add_filter'] = this.qr.page.add_field({
- label: __('Add Filter'),
+ controls['component_type'] = this.qr.page.add_field({
+ label: __('Component Type'),
+ fieldtype: 'Select',
+ fieldname: 'component_type',
+ default: 'filter',
+ options: [
+ {label: __('Filtered Row Subtotal'), value: 'filter'},
+ {label: __('Section Subtotal'), value: 'section'}
+ ]
+ });
+ controls['add_component'] = this.qr.page.add_field({
+ label: __('Add Component'),
fieldtype: 'Button',
- fieldname: 'add_filter',
+ fieldname: 'add_component',
click: () => {
+ this.check_datatable();
let section_name = this.controls['section_name'].get_input_value();
if (section_name) {
- let prefix = 'Filter';
- let data = {
- filters: this.qr.datatable.columnmanager.getAppliedFilters(),
- fieldname: this.get_value_fieldname()
+ const component_type = this.controls['component_type'].get_input_value();
+ let idx = 0;
+ const names = Object.keys(this.sections[section_name]);
+ if (names.length > 0) {
+ const idxs = names.map((key) => parseInt(key.match(/\d+$/)) || 0);
+ idx = Math.max(...idxs) + 1;
}
- const fidxs = Object.keys(this.sections[section_name]);
- let new_idx = prefix + '0';
- if (fidxs.length > 0) {
- const fiidxs = fidxs.map((key) => parseInt(key.replace(prefix, '')));
- new_idx = prefix + (Math.max(...fiidxs) + 1).toString();
+ const filters = this.qr.datatable.columnmanager.getAppliedFilters();
+ if (component_type === 'filter') {
+ const name = 'Filter' + idx.toString();
+ let data = {
+ type: component_type,
+ filters: filters
+ }
+ this.sections[section_name][name] = data;
+ this.reload_component(name);
+ } else if (component_type === 'section') {
+ if (filters && Object.keys(filters).length !== 0) {
+ frappe.show_alert({
+ message: __('Column filters ignored'),
+ indicator: 'yellow'
+ });
+ }
+ let data = {
+ type: component_type
+ }
+ frappe.prompt({
+ label: __('Section'),
+ fieldname: 'section',
+ fieldtype: 'Select',
+ options: Object.keys(this.sections)
+ }, (values) => {
+ this.sections[section_name][values.section] = data;
+ this.reload_component(values.section);
+ });
+ } else {
+ frappe.throw(__('Please select the Component Type first'));
}
- this.sections[section_name][new_idx] = data;
- this.controls['filter_index'].set_input(new_idx);
- this.reload_filter();
} else {
- frappe.throw(__('Please add or select the Section first'));
+ frappe.throw(__('Please select the Section first'));
}
}
});
- controls['delete_filter'] = this.qr.page.add_field({
- label: __('Delete Filter'),
+ controls['delete_component'] = this.qr.page.add_field({
+ label: __('Delete Component'),
fieldtype: 'Button',
- fieldname: 'delete_filter',
+ fieldname: 'delete_component',
click: () => {
- let cur_filter = this.controls['filter_index'].get_input_value();
- if (cur_filter) {
- frappe.confirm(__('Are you sure you want to delete filter ') + cur_filter + '?',
- () => {this.delete(cur_filter, 'filter')});
+ const component = this.controls['component'].get_input_value();
+ if (component) {
+ frappe.confirm(__('Are you sure you want to delete component ') + component + '?',
+ () => {this.delete(component, 'component')});
}
}
});
- controls['value_field'] = this.qr.page.add_field({
- label: __('Value Column'),
- fieldtype: 'Select',
- fieldname: 'value_field',
- change: (e) => {
- this.controls['value_field'].set_input(this.controls['value_field'].get_input_value());
- }
- });
controls['save'] = this.qr.page.add_field({
label: __('Save & Run'),
fieldtype: 'Button',
@@ -380,13 +376,16 @@ erpnext.TaxDetail = class TaxDetail {
this.controls = controls;
}
show_help() {
- const help = __(`You can add multiple sections to your custom report using the New Section button above.
- To specify what data goes in each section, specify column filters in the data table, then save with Add Filter.
- Each section can have multiple filters added but be careful with the duplicated data rows.
- You can specify which Currency column will be summed for each filter in the final report with the Value Column
- select box. Use the Show Detail box to see the data rows included in each section in the final report.
- Once you're done, hit Save & Run.`);
- this.qr.$report_footer.append(`${help}
`);
+ const help = __(`Help: Your custom report is built from General Ledger Entries within the date range.
+ You can add multiple sections to the report using the New Section button.
+ Each component added to a section adds a subset of the data into the specified section.
+ Beware of duplicated data rows.
+ The Filtered Row component type saves the datatable column filters to specify the added data.
+ The Section component type refers to the data in a previously defined section, but it cannot refer to its parent section.
+ The Amount column is summed to give the section subtotal.
+ Use the Show Detail box to see the data rows included in each section in the final report.
+ Once finished, hit Save & Run. Report contributed by`);
+ this.qr.$report_footer.append(``);
}
}
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index 1f4d1ba8a0..426e8d4aec 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe, json
from frappe import _
-# NOTE: Payroll is implemented using Journal Entries which translate directly to GL Entries
+# NOTE: Payroll is implemented using Journal Entries which are included as GL Entries
# field lists in multiple doctypes will be coalesced
required_sql_fields = {
@@ -60,23 +60,35 @@ def run_report(report_name, data):
columns = report_config.get('columns')
sections = report_config.get('sections', {})
show_detail = report_config.get('show_detail', 1)
+ report = {}
new_data = []
summary = []
for section_name, section in sections.items():
- section_total = 0.0
- for filt_name, filt in section.items():
- value_field = filt['fieldname']
- rmidxs = []
- for colno, filter_string in filt['filters'].items():
- filter_field = columns[int(colno) - 1]['fieldname']
- for i, row in enumerate(data):
- if not filter_match(row[filter_field], filter_string):
- rmidxs += [i]
- rows = [row for i, row in enumerate(data) if i not in rmidxs]
- section_total += subtotal(rows, value_field)
- if show_detail: new_data += rows
- new_data += [ {columns[1]['fieldname']: section_name, columns[2]['fieldname']: section_total} ]
- summary += [ {'label': section_name, 'datatype': 'Currency', 'value': section_total} ]
+ report[section_name] = {'rows': [], 'subtotal': 0.0}
+ for component_name, component in section.items():
+ if component['type'] == 'filter':
+ for row in data:
+ matched = True
+ for colno, filter_string in component['filters'].items():
+ filter_field = columns[int(colno) - 1]['fieldname']
+ if not filter_match(row[filter_field], filter_string):
+ matched = False
+ break
+ if matched:
+ report[section_name]['rows'] += [row]
+ report[section_name]['subtotal'] += row['amount']
+ if component['type'] == 'section':
+ if component_name == section_name:
+ frappe.throw(_("A report component cannot refer to its parent section: ") + section_name)
+ try:
+ report[section_name]['rows'] += report[component_name]['rows']
+ report[section_name]['subtotal'] += report[component_name]['subtotal']
+ except KeyError:
+ frappe.throw(_("A report component can only refer to an earlier section: ") + section_name)
+
+ if show_detail: new_data += report[section_name]['rows']
+ new_data += [ {'voucher_no': section_name, 'amount': report[section_name]['subtotal']} ]
+ summary += [ {'label': section_name, 'datatype': 'Currency', 'value': report[section_name]['subtotal']} ]
if show_detail: new_data += [ {} ]
return new_data or data, summary or None
@@ -123,11 +135,6 @@ def filter_match(value, string):
if operator == '<': return True
return False
-def subtotal(data, field):
- subtotal = 0.0
- for row in data:
- subtotal += row[field]
- return subtotal
abbrev = lambda dt: ''.join(l[0].lower() for l in dt.split(' ')) + '.'
doclist = lambda dt, dfs: [abbrev(dt) + f for f in dfs]
@@ -185,6 +192,9 @@ def modify_report_columns(doctype, field, column):
if field in ["item_tax_rate", "base_net_amount"]:
return None
+ if doctype == "GL Entry" and field in ["debit", "credit"]:
+ column.update({"label": _("Amount"), "fieldname": "amount"})
+
if field == "taxes_and_charges":
column.update({"label": _("Taxes and Charges Template")})
return column
@@ -193,6 +203,8 @@ def modify_report_data(data):
import json
new_data = []
for line in data:
+ if line.debit: line.amount = -line.debit
+ else: line.amount = line.credit
# Remove Invoice GL Tax Entries and generate Tax entries from the invoice lines
if "Invoice" in line.voucher_type:
if line.account_type != "Tax":
@@ -204,11 +216,11 @@ def modify_report_data(data):
tax_line.account_type = "Tax"
tax_line.account = account
if line.voucher_type == "Sales Invoice":
- line.credit = line.base_net_amount
- tax_line.credit = line.base_net_amount * (rate / 100)
+ line.amount = line.base_net_amount
+ tax_line.amount = line.base_net_amount * (rate / 100)
if line.voucher_type == "Purchase Invoice":
- line.debit = line.base_net_amount
- tax_line.debit = line.base_net_amount * (rate / 100)
+ line.amount = -line.base_net_amount
+ tax_line.amount = -line.base_net_amount * (rate / 100)
new_data += [tax_line]
else:
new_data += [line]
From 77ffa6b1f67a4ee69066f749ce14b4e1ff29711a Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Thu, 8 Apr 2021 22:19:31 +0000
Subject: [PATCH 078/262] feat: add test case for report output
---
.../accounts/report/tax_detail/tax_detail.py | 2 +-
.../report/tax_detail/test_tax_detail.json | 755 ++++++++++++++++++
.../report/tax_detail/test_tax_detail.py | 96 ++-
3 files changed, 847 insertions(+), 6 deletions(-)
create mode 100644 erpnext/accounts/report/tax_detail/test_tax_detail.json
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index 426e8d4aec..fb7791f7e1 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -11,7 +11,7 @@ from frappe import _
# field lists in multiple doctypes will be coalesced
required_sql_fields = {
("GL Entry", 1): ["posting_date"],
- ("Account",): ["account_type"],
+ ("Account",): ["root_type", "account_type"],
("GL Entry", 2): ["account", "voucher_type", "voucher_no", "debit", "credit"],
("Purchase Invoice Item", "Sales Invoice Item"): ["base_net_amount", "item_tax_rate", "item_tax_template", "item_group", "item_name"],
("Purchase Invoice", "Sales Invoice"): ["taxes_and_charges", "tax_category"],
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.json b/erpnext/accounts/report/tax_detail/test_tax_detail.json
new file mode 100644
index 0000000000..17248d0320
--- /dev/null
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.json
@@ -0,0 +1,755 @@
+[
+ {
+ "abbr": "_T",
+ "company_name": "_T",
+ "country": "United Kingdom",
+ "default_currency": "GBP",
+ "doctype": "Company",
+ "name": "_T"
+ },{
+ "account_currency": "GBP",
+ "account_name": "Debtors",
+ "account_number": "",
+ "account_type": "Receivable",
+ "balance_must_be": "",
+ "company": "_T",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Account",
+ "freeze_account": "No",
+ "include_in_gross": 0,
+ "inter_company_account": 0,
+ "is_group": 0,
+ "lft": 58,
+ "modified": "2021-03-26 04:44:19.955468",
+ "name": "Debtors - _T",
+ "old_parent": null,
+ "parent": null,
+ "parent_account": "Application of Funds (Assets) - _T",
+ "parentfield": null,
+ "parenttype": null,
+ "report_type": "Balance Sheet",
+ "rgt": 59,
+ "root_type": "Asset",
+ "tax_rate": 0.0
+ },{
+ "account_currency": "GBP",
+ "account_name": "Sales",
+ "account_number": "",
+ "account_type": "Income Account",
+ "balance_must_be": "",
+ "company": "_T",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Account",
+ "freeze_account": "No",
+ "include_in_gross": 0,
+ "inter_company_account": 0,
+ "is_group": 0,
+ "lft": 291,
+ "modified": "2021-03-26 04:50:21.697703",
+ "name": "Sales - _T",
+ "old_parent": null,
+ "parent": null,
+ "parent_account": "Income - _T",
+ "parentfield": null,
+ "parenttype": null,
+ "report_type": "Profit and Loss",
+ "rgt": 292,
+ "root_type": "Income",
+ "tax_rate": 0.0
+ },{
+ "account_currency": "GBP",
+ "account_name": "VAT on Sales",
+ "account_number": "",
+ "account_type": "Tax",
+ "balance_must_be": "",
+ "company": "_T",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Account",
+ "freeze_account": "No",
+ "include_in_gross": 0,
+ "inter_company_account": 0,
+ "is_group": 0,
+ "lft": 317,
+ "modified": "2021-03-26 04:50:21.697703",
+ "name": "VAT on Sales - _T",
+ "old_parent": null,
+ "parent": null,
+ "parent_account": "Source of Funds (Liabilities) - _T",
+ "parentfield": null,
+ "parenttype": null,
+ "report_type": "Balance Sheet",
+ "rgt": 318,
+ "root_type": "Liability",
+ "tax_rate": 0.0
+ },{
+ "account_currency": "GBP",
+ "account_name": "Cost of Goods Sold",
+ "account_number": "",
+ "account_type": "Cost of Goods Sold",
+ "balance_must_be": "",
+ "company": "_T",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Account",
+ "freeze_account": "No",
+ "include_in_gross": 0,
+ "inter_company_account": 0,
+ "is_group": 0,
+ "lft": 171,
+ "modified": "2021-03-26 04:44:19.994857",
+ "name": "Cost of Goods Sold - _T",
+ "old_parent": null,
+ "parent": null,
+ "parent_account": "Expenses - _T",
+ "parentfield": null,
+ "parenttype": null,
+ "report_type": "Profit and Loss",
+ "rgt": 172,
+ "root_type": "Expense",
+ "tax_rate": 0.0
+ },{
+ "account_currency": "GBP",
+ "account_name": "VAT on Purchases",
+ "account_number": "",
+ "account_type": "Tax",
+ "balance_must_be": "",
+ "company": "_T",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Account",
+ "freeze_account": "No",
+ "include_in_gross": 0,
+ "inter_company_account": 0,
+ "is_group": 0,
+ "lft": 80,
+ "modified": "2021-03-26 04:44:19.961983",
+ "name": "VAT on Purchases - _T",
+ "old_parent": null,
+ "parent": null,
+ "parent_account": "Application of Funds (Assets) - _T",
+ "parentfield": null,
+ "parenttype": null,
+ "report_type": "Balance Sheet",
+ "rgt": 81,
+ "root_type": "Asset",
+ "tax_rate": 0.0
+ },{
+ "account_currency": "GBP",
+ "account_name": "Creditors",
+ "account_number": "",
+ "account_type": "Payable",
+ "balance_must_be": "",
+ "company": "_T",
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Account",
+ "freeze_account": "No",
+ "include_in_gross": 0,
+ "inter_company_account": 0,
+ "is_group": 0,
+ "lft": 302,
+ "modified": "2021-03-26 04:50:21.697703",
+ "name": "Creditors - _T",
+ "old_parent": null,
+ "parent": null,
+ "parent_account": "Source of Funds (Liabilities) - _T",
+ "parentfield": null,
+ "parenttype": null,
+ "report_type": "Balance Sheet",
+ "rgt": 303,
+ "root_type": "Liability",
+ "tax_rate": 0.0
+ },{
+ "additional_discount_percentage": 0.0,
+ "address_display": null,
+ "adjust_advance_taxes": 0,
+ "advances": [],
+ "against_expense_account": "Cost of Goods Sold - _T",
+ "allocate_advances_automatically": 0,
+ "amended_from": null,
+ "apply_discount_on": "Grand Total",
+ "apply_tds": 0,
+ "auto_repeat": null,
+ "base_discount_amount": 0.0,
+ "base_grand_total": 511.68,
+ "base_in_words": "GBP Five Hundred And Eleven and Sixty Eight Pence only.",
+ "base_net_total": 426.4,
+ "base_paid_amount": 0.0,
+ "base_rounded_total": 511.68,
+ "base_rounding_adjustment": 0.0,
+ "base_taxes_and_charges_added": 85.28,
+ "base_taxes_and_charges_deducted": 0.0,
+ "base_total": 426.4,
+ "base_total_taxes_and_charges": 85.28,
+ "base_write_off_amount": 0.0,
+ "bill_date": null,
+ "bill_no": null,
+ "billing_address": null,
+ "billing_address_display": null,
+ "buying_price_list": "Standard Buying",
+ "cash_bank_account": null,
+ "clearance_date": null,
+ "company": "_T",
+ "contact_display": null,
+ "contact_email": null,
+ "contact_mobile": null,
+ "contact_person": null,
+ "conversion_rate": 1.0,
+ "cost_center": null,
+ "credit_to": "Creditors - _T",
+ "currency": "GBP",
+ "disable_rounded_total": 0,
+ "discount_amount": 0.0,
+ "docstatus": 0,
+ "doctype": "Purchase Invoice",
+ "due_date": "2021-04-30",
+ "from_date": null,
+ "grand_total": 511.68,
+ "group_same_items": 0,
+ "hold_comment": null,
+ "ignore_pricing_rule": 0,
+ "in_words": "GBP Five Hundred And Eleven and Sixty Eight Pence only.",
+ "inter_company_invoice_reference": null,
+ "is_internal_supplier": 0,
+ "is_opening": "No",
+ "is_paid": 0,
+ "is_return": 0,
+ "is_subcontracted": "No",
+ "items": [
+ {
+ "allow_zero_valuation_rate": 0,
+ "amount": 426.4,
+ "asset_category": null,
+ "asset_location": null,
+ "base_amount": 426.4,
+ "base_net_amount": 426.4,
+ "base_net_rate": 5.33,
+ "base_price_list_rate": 5.33,
+ "base_rate": 5.33,
+ "base_rate_with_margin": 0.0,
+ "batch_no": null,
+ "bom": null,
+ "brand": null,
+ "conversion_factor": 0.0,
+ "cost_center": "Main - _T",
+ "deferred_expense_account": null,
+ "description": "",
+ "discount_amount": 0.0,
+ "discount_percentage": 0.0,
+ "enable_deferred_expense": 0,
+ "expense_account": "Cost of Goods Sold - _T",
+ "from_warehouse": null,
+ "image": null,
+ "include_exploded_items": 0,
+ "is_fixed_asset": 0,
+ "is_free_item": 0,
+ "item_code": null,
+ "item_group": null,
+ "item_name": "Widget Fluid 1Litre",
+ "item_tax_amount": 0.0,
+ "item_tax_rate": "{\"VAT on Purchases - _T\": 20.0}",
+ "item_tax_template": "Purchase - Standard VAT",
+ "landed_cost_voucher_amount": 0.0,
+ "manufacturer": null,
+ "manufacturer_part_no": null,
+ "margin_rate_or_amount": 0.0,
+ "margin_type": "",
+ "net_amount": 426.4,
+ "net_rate": 5.33,
+ "page_break": 0,
+ "parent": null,
+ "parentfield": "items",
+ "parenttype": "Purchase Invoice",
+ "po_detail": null,
+ "pr_detail": null,
+ "price_list_rate": 5.33,
+ "pricing_rules": null,
+ "project": null,
+ "purchase_invoice_item": null,
+ "purchase_order": null,
+ "purchase_receipt": null,
+ "qty": 80.0,
+ "quality_inspection": null,
+ "rate": 5.33,
+ "rate_with_margin": 0.0,
+ "received_qty": 0.0,
+ "rejected_qty": 0.0,
+ "rejected_serial_no": null,
+ "rejected_warehouse": null,
+ "rm_supp_cost": 0.0,
+ "sales_invoice_item": null,
+ "serial_no": null,
+ "service_end_date": null,
+ "service_start_date": null,
+ "service_stop_date": null,
+ "stock_qty": 0.0,
+ "stock_uom": "Nos",
+ "stock_uom_rate": 0.0,
+ "total_weight": 0.0,
+ "uom": "Nos",
+ "valuation_rate": 0.0,
+ "warehouse": null,
+ "weight_per_unit": 0.0,
+ "weight_uom": null
+ }
+ ],
+ "language": "en",
+ "letter_head": null,
+ "mode_of_payment": null,
+ "modified": "2021-04-03 03:33:09.180453",
+ "name": null,
+ "naming_series": "ACC-PINV-.YYYY.-",
+ "net_total": 426.4,
+ "on_hold": 0,
+ "other_charges_calculation": "\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tItem | \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tTaxable Amount | \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tVAT on Purchases | \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tWidget Fluid 1Litre | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 426.40\n\t\t\t\t\t\t\n\t\t\t\t\t | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(20.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 85.28\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t | \n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\n\t\t\n\t
\n
",
+ "outstanding_amount": 511.68,
+ "paid_amount": 0.0,
+ "parent": null,
+ "parentfield": null,
+ "parenttype": null,
+ "party_account_currency": "GBP",
+ "payment_schedule": [],
+ "payment_terms_template": null,
+ "plc_conversion_rate": 1.0,
+ "posting_date": null,
+ "posting_time": "16:59:56.789522",
+ "price_list_currency": "GBP",
+ "pricing_rules": [],
+ "project": null,
+ "rejected_warehouse": null,
+ "release_date": null,
+ "remarks": "No Remarks",
+ "represents_company": null,
+ "return_against": null,
+ "rounded_total": 511.68,
+ "rounding_adjustment": 0.0,
+ "scan_barcode": null,
+ "select_print_heading": null,
+ "set_from_warehouse": null,
+ "set_posting_time": 0,
+ "set_warehouse": null,
+ "shipping_address": null,
+ "shipping_address_display": "",
+ "shipping_rule": null,
+ "status": "Unpaid",
+ "supplied_items": [],
+ "supplier": "Raw Materials Inc",
+ "supplier_address": null,
+ "supplier_name": "Raw Materials Inc",
+ "supplier_warehouse": "Stores - _T",
+ "tax_category": "Other Supplier",
+ "tax_id": null,
+ "tax_withholding_category": null,
+ "taxes": [
+ {
+ "account_head": "VAT on Purchases - _T",
+ "add_deduct_tax": "Add",
+ "base_tax_amount": 85.28,
+ "base_tax_amount_after_discount_amount": 85.28,
+ "base_total": 511.68,
+ "category": "Total",
+ "charge_type": "On Net Total",
+ "cost_center": "Main - _T",
+ "description": "VAT on Purchases",
+ "included_in_print_rate": 0,
+ "item_wise_tax_detail": "{\"Widget Fluid 1Litre\":[20.0,85.28]}",
+ "parent": null,
+ "parentfield": "taxes",
+ "parenttype": "Purchase Invoice",
+ "rate": 0.0,
+ "row_id": null,
+ "tax_amount": 85.28,
+ "tax_amount_after_discount_amount": 85.28,
+ "total": 511.68
+ }
+ ],
+ "taxes_and_charges": null,
+ "taxes_and_charges_added": 85.28,
+ "taxes_and_charges_deducted": 0.0,
+ "tc_name": null,
+ "terms": null,
+ "title": "Raw Materials Inc",
+ "to_date": null,
+ "total": 426.4,
+ "total_advance": 0.0,
+ "total_net_weight": 0.0,
+ "total_qty": 80.0,
+ "total_taxes_and_charges": 85.28,
+ "unrealized_profit_loss_account": null,
+ "update_stock": 0,
+ "write_off_account": null,
+ "write_off_amount": 0.0,
+ "write_off_cost_center": null
+ },{
+ "account_for_change_amount": null,
+ "additional_discount_percentage": 0.0,
+ "address_display": null,
+ "advances": [],
+ "against_income_account": "Sales - _T",
+ "allocate_advances_automatically": 0,
+ "amended_from": null,
+ "apply_discount_on": "Grand Total",
+ "auto_repeat": null,
+ "base_change_amount": 0.0,
+ "base_discount_amount": 0.0,
+ "base_grand_total": 868.25,
+ "base_in_words": "GBP Eight Hundred And Sixty Eight and Twenty Five Pence only.",
+ "base_net_total": 825.0,
+ "base_paid_amount": 0.0,
+ "base_rounded_total": 868.25,
+ "base_rounding_adjustment": 0.0,
+ "base_total": 825.0,
+ "base_total_taxes_and_charges": 43.25,
+ "base_write_off_amount": 0.0,
+ "c_form_applicable": "No",
+ "c_form_no": null,
+ "campaign": null,
+ "cash_bank_account": null,
+ "change_amount": 0.0,
+ "commission_rate": 0.0,
+ "company": "_T",
+ "company_address": null,
+ "company_address_display": null,
+ "company_tax_id": null,
+ "contact_display": null,
+ "contact_email": null,
+ "contact_mobile": null,
+ "contact_person": null,
+ "conversion_rate": 1.0,
+ "cost_center": null,
+ "currency": "GBP",
+ "customer": "ABC Tyres",
+ "customer_address": null,
+ "customer_group": "All Customer Groups",
+ "customer_name": "ABC Tyres",
+ "debit_to": "Debtors - _T",
+ "discount_amount": 0.0,
+ "docstatus": 0,
+ "doctype": "Sales Invoice",
+ "due_date": "2021-03-31",
+ "from_date": null,
+ "grand_total": 868.25,
+ "group_same_items": 0,
+ "ignore_pricing_rule": 0,
+ "in_words": "GBP Eight Hundred And Sixty Eight and Twenty Five Pence only.",
+ "inter_company_invoice_reference": null,
+ "is_consolidated": 0,
+ "is_discounted": 0,
+ "is_internal_customer": 0,
+ "is_opening": "No",
+ "is_pos": 0,
+ "is_return": 0,
+ "items": [
+ {
+ "actual_batch_qty": 0.0,
+ "actual_qty": 0.0,
+ "allow_zero_valuation_rate": 0,
+ "amount": 200.0,
+ "asset": null,
+ "barcode": null,
+ "base_amount": 200.0,
+ "base_net_amount": 200.0,
+ "base_net_rate": 50.0,
+ "base_price_list_rate": 0.0,
+ "base_rate": 50.0,
+ "base_rate_with_margin": 0.0,
+ "batch_no": null,
+ "brand": null,
+ "conversion_factor": 1.0,
+ "cost_center": "Main - _T",
+ "customer_item_code": null,
+ "deferred_revenue_account": null,
+ "delivered_by_supplier": 0,
+ "delivered_qty": 0.0,
+ "delivery_note": null,
+ "description": "",
+ "discount_amount": 0.0,
+ "discount_percentage": 0.0,
+ "dn_detail": null,
+ "enable_deferred_revenue": 0,
+ "expense_account": null,
+ "finance_book": null,
+ "image": null,
+ "income_account": "Sales - _T",
+ "incoming_rate": 0.0,
+ "is_fixed_asset": 0,
+ "is_free_item": 0,
+ "item_code": null,
+ "item_group": null,
+ "item_name": "Dunlop tyres",
+ "item_tax_rate": "{\"VAT on Sales - _T\": 20.0}",
+ "item_tax_template": "Sale - Standard VAT",
+ "margin_rate_or_amount": 0.0,
+ "margin_type": "",
+ "net_amount": 200.0,
+ "net_rate": 50.0,
+ "page_break": 0,
+ "parent": null,
+ "parentfield": "items",
+ "parenttype": "Sales Invoice",
+ "price_list_rate": 0.0,
+ "pricing_rules": null,
+ "project": null,
+ "qty": 4.0,
+ "quality_inspection": null,
+ "rate": 50.0,
+ "rate_with_margin": 0.0,
+ "sales_invoice_item": null,
+ "sales_order": null,
+ "serial_no": null,
+ "service_end_date": null,
+ "service_start_date": null,
+ "service_stop_date": null,
+ "so_detail": null,
+ "stock_qty": 4.0,
+ "stock_uom": "Nos",
+ "stock_uom_rate": 50.0,
+ "target_warehouse": null,
+ "total_weight": 0.0,
+ "uom": "Nos",
+ "warehouse": null,
+ "weight_per_unit": 0.0,
+ "weight_uom": null
+ },
+ {
+ "actual_batch_qty": 0.0,
+ "actual_qty": 0.0,
+ "allow_zero_valuation_rate": 0,
+ "amount": 65.0,
+ "asset": null,
+ "barcode": null,
+ "base_amount": 65.0,
+ "base_net_amount": 65.0,
+ "base_net_rate": 65.0,
+ "base_price_list_rate": 0.0,
+ "base_rate": 65.0,
+ "base_rate_with_margin": 0.0,
+ "batch_no": null,
+ "brand": null,
+ "conversion_factor": 1.0,
+ "cost_center": "Main - _T",
+ "customer_item_code": null,
+ "deferred_revenue_account": null,
+ "delivered_by_supplier": 0,
+ "delivered_qty": 0.0,
+ "delivery_note": null,
+ "description": "",
+ "discount_amount": 0.0,
+ "discount_percentage": 0.0,
+ "dn_detail": null,
+ "enable_deferred_revenue": 0,
+ "expense_account": null,
+ "finance_book": null,
+ "image": null,
+ "income_account": "Sales - _T",
+ "incoming_rate": 0.0,
+ "is_fixed_asset": 0,
+ "is_free_item": 0,
+ "item_code": "",
+ "item_group": null,
+ "item_name": "Continental tyres",
+ "item_tax_rate": "{\"VAT on Sales - _T\": 5.0}",
+ "item_tax_template": "Sale - Reduced VAT",
+ "margin_rate_or_amount": 0.0,
+ "margin_type": "",
+ "net_amount": 65.0,
+ "net_rate": 65.0,
+ "page_break": 0,
+ "parent": null,
+ "parentfield": "items",
+ "parenttype": "Sales Invoice",
+ "price_list_rate": 0.0,
+ "pricing_rules": null,
+ "project": null,
+ "qty": 1.0,
+ "quality_inspection": null,
+ "rate": 65.0,
+ "rate_with_margin": 0.0,
+ "sales_invoice_item": null,
+ "sales_order": null,
+ "serial_no": null,
+ "service_end_date": null,
+ "service_start_date": null,
+ "service_stop_date": null,
+ "so_detail": null,
+ "stock_qty": 1.0,
+ "stock_uom": null,
+ "stock_uom_rate": 65.0,
+ "target_warehouse": null,
+ "total_weight": 0.0,
+ "uom": "Nos",
+ "warehouse": null,
+ "weight_per_unit": 0.0,
+ "weight_uom": null
+ },
+ {
+ "actual_batch_qty": 0.0,
+ "actual_qty": 0.0,
+ "allow_zero_valuation_rate": 0,
+ "amount": 560.0,
+ "asset": null,
+ "barcode": null,
+ "base_amount": 560.0,
+ "base_net_amount": 560.0,
+ "base_net_rate": 70.0,
+ "base_price_list_rate": 0.0,
+ "base_rate": 70.0,
+ "base_rate_with_margin": 0.0,
+ "batch_no": null,
+ "brand": null,
+ "conversion_factor": 1.0,
+ "cost_center": "Main - _T",
+ "customer_item_code": null,
+ "deferred_revenue_account": null,
+ "delivered_by_supplier": 0,
+ "delivered_qty": 0.0,
+ "delivery_note": null,
+ "description": "",
+ "discount_amount": 0.0,
+ "discount_percentage": 0.0,
+ "dn_detail": null,
+ "enable_deferred_revenue": 0,
+ "expense_account": null,
+ "finance_book": null,
+ "image": null,
+ "income_account": "Sales - _T",
+ "incoming_rate": 0.0,
+ "is_fixed_asset": 0,
+ "is_free_item": 0,
+ "item_code": null,
+ "item_group": null,
+ "item_name": "Toyo tyres",
+ "item_tax_rate": "{\"VAT on Sales - _T\": 0.0}",
+ "item_tax_template": "Sale - Zero VAT",
+ "margin_rate_or_amount": 0.0,
+ "margin_type": "",
+ "net_amount": 560.0,
+ "net_rate": 70.0,
+ "page_break": 0,
+ "parent": null,
+ "parentfield": "items",
+ "parenttype": "Sales Invoice",
+ "price_list_rate": 0.0,
+ "pricing_rules": null,
+ "project": null,
+ "qty": 8.0,
+ "quality_inspection": null,
+ "rate": 70.0,
+ "rate_with_margin": 0.0,
+ "sales_invoice_item": null,
+ "sales_order": null,
+ "serial_no": null,
+ "service_end_date": null,
+ "service_start_date": null,
+ "service_stop_date": null,
+ "so_detail": null,
+ "stock_qty": 8.0,
+ "stock_uom": null,
+ "stock_uom_rate": 70.0,
+ "target_warehouse": null,
+ "total_weight": 0.0,
+ "uom": "Nos",
+ "warehouse": null,
+ "weight_per_unit": 0.0,
+ "weight_uom": null
+ }
+ ],
+ "language": "en",
+ "letter_head": null,
+ "loyalty_amount": 0.0,
+ "loyalty_points": 0,
+ "loyalty_program": null,
+ "loyalty_redemption_account": null,
+ "loyalty_redemption_cost_center": null,
+ "modified": "2021-02-16 05:18:59.755144",
+ "name": null,
+ "naming_series": "ACC-SINV-.YYYY.-",
+ "net_total": 825.0,
+ "other_charges_calculation": "\n\t
\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tItem | \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tTaxable Amount | \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\tVAT on Sales | \n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tDunlop tyres | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 200.00\n\t\t\t\t\t\t\n\t\t\t\t\t | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(20.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 40.00\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t | \n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tContinental tyres | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 65.00\n\t\t\t\t\t\t\n\t\t\t\t\t | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(5.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 3.25\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t | \n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\tToyo tyres | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\u00a3 560.00\n\t\t\t\t\t\t\n\t\t\t\t\t | \n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t(0.0%)\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\u00a3 0.00\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t | \n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t
\n\t\t\t\n\t\t\n\t
\n
",
+ "outstanding_amount": 868.25,
+ "packed_items": [],
+ "paid_amount": 0.0,
+ "parent": null,
+ "parentfield": null,
+ "parenttype": null,
+ "party_account_currency": "GBP",
+ "payment_schedule": [],
+ "payment_terms_template": null,
+ "payments": [],
+ "plc_conversion_rate": 1.0,
+ "po_date": null,
+ "po_no": "",
+ "pos_profile": null,
+ "posting_date": null,
+ "posting_time": "5:19:02.994077",
+ "price_list_currency": "GBP",
+ "pricing_rules": [],
+ "project": null,
+ "redeem_loyalty_points": 0,
+ "remarks": "No Remarks",
+ "represents_company": "",
+ "return_against": null,
+ "rounded_total": 868.25,
+ "rounding_adjustment": 0.0,
+ "sales_partner": null,
+ "sales_team": [],
+ "scan_barcode": null,
+ "select_print_heading": null,
+ "selling_price_list": "Standard Selling",
+ "set_posting_time": 0,
+ "set_target_warehouse": null,
+ "set_warehouse": null,
+ "shipping_address": null,
+ "shipping_address_name": "",
+ "shipping_rule": null,
+ "source": null,
+ "status": "Overdue",
+ "tax_category": "",
+ "tax_id": null,
+ "taxes": [
+ {
+ "account_head": "VAT on Sales - _T",
+ "base_tax_amount": 43.25,
+ "base_tax_amount_after_discount_amount": 43.25,
+ "base_total": 868.25,
+ "charge_type": "On Net Total",
+ "cost_center": "Main - _T",
+ "description": "VAT on Sales",
+ "included_in_print_rate": 0,
+ "item_wise_tax_detail": "{\"Dunlop tyres\":[20.0,40.0],\"Continental tyres\":[5.0,3.25],\"Toyo tyres\":[0.0,0.0]}",
+ "parent": null,
+ "parentfield": "taxes",
+ "parenttype": "Sales Invoice",
+ "rate": 0.0,
+ "row_id": null,
+ "tax_amount": 43.25,
+ "tax_amount_after_discount_amount": 43.25,
+ "total": 868.25
+ }
+ ],
+ "taxes_and_charges": null,
+ "tc_name": null,
+ "terms": null,
+ "territory": "All Territories",
+ "timesheets": [],
+ "title": "ABC Tyres",
+ "to_date": null,
+ "total": 825.0,
+ "total_advance": 0.0,
+ "total_billing_amount": 0.0,
+ "total_commission": 0.0,
+ "total_net_weight": 0.0,
+ "total_qty": 13.0,
+ "total_taxes_and_charges": 43.25,
+ "unrealized_profit_loss_account": null,
+ "update_billed_amount_in_sales_order": 0,
+ "update_stock": 0,
+ "write_off_account": null,
+ "write_off_amount": 0.0,
+ "write_off_cost_center": null,
+ "write_off_outstanding_amount_automatically": 0
+ }
+]
\ No newline at end of file
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index dfd8d9e121..c9b8e209e4 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -1,12 +1,98 @@
from __future__ import unicode_literals
-import frappe, unittest, datetime
-from frappe.utils import getdate
-from .tax_detail import execute, filter_match
+import frappe, unittest, datetime, json, os
+from frappe.utils import getdate, add_to_date, get_first_day, get_last_day
+from .tax_detail import filter_match, save_custom_report
class TestTaxDetail(unittest.TestCase):
- def setup(self):
- pass
+ def load_testdocs(self):
+ datapath, _ = os.path.splitext(os.path.realpath(__file__))
+ with open(datapath + '.json', 'r') as fp:
+ self.docs = json.load(fp)
+
+ def load_defcols(self):
+ custom_report = frappe.get_doc('Report', 'Tax Detail')
+ self.default_columns, _ = custom_report.run_query_report(
+ filters={
+ 'from_date': '2021-03-01',
+ 'to_date': '2021-03-31',
+ 'company': '_T',
+ 'mode': 'run',
+ 'report_name': 'Tax Detail'
+ }, user=frappe.session.user)
+
+ def setUp(self):
+ "Add Transactions in 01-03-2021 - 31-03-2021"
+ self.load_testdocs()
+ now = getdate()
+ self.from_date = get_first_day(now)
+ self.to_date = get_last_day(now)
+
+ for doc in self.docs:
+ try:
+ db_doc = frappe.get_doc(doc)
+ if 'Invoice' in db_doc.doctype:
+ db_doc.due_date = add_to_date(now, days=1)
+ db_doc.insert()
+ # Create GL Entries:
+ db_doc.submit()
+ else:
+ db_doc.insert()
+ except frappe.exceptions.DuplicateEntryError as e:
+ pass
+ #print(f'Duplicate Entry: {e}')
+ except:
+ print(f'\nError importing {doc["doctype"]}: {doc["name"]}')
+ raise
+
+ self.load_defcols()
+
+ def tearDown(self):
+ "Remove the Company and all data"
+ from erpnext.setup.doctype.company.delete_company_transactions import delete_company_transactions
+ for co in filter(lambda doc: doc['doctype'] == 'Company', self.docs):
+ delete_company_transactions(co['name'])
+ db_co = frappe.get_doc('Company', co['name'])
+ db_co.delete()
+
+ def test_report(self):
+ report_name = save_custom_report(
+ 'Tax Detail',
+ '_Test Tax Detail',
+ json.dumps({
+ 'columns': self.default_columns,
+ 'sections': {
+ 'Box1':{'Filter0':{'type':'filter','filters':{'4':'VAT on Sales'}}},
+ 'Box2':{'Filter0':{'type':'filter','filters':{'4':'Acquisition'}}},
+ 'Box3':{'Box1':{'type':'section'},'Box2':{'type':'section'}},
+ 'Box4':{'Filter0':{'type':'filter','filters':{'4':'VAT on Purchases'}}},
+ 'Box5':{'Box3':{'type':'section'},'Box4':{'type':'section'}},
+ 'Box6':{'Filter0':{'type':'filter','filters':{'3':'!=Tax','4':'Sales'}}},
+ 'Box7':{'Filter0':{'type':'filter','filters':{'2':'Expense','3':'!=Tax'}}},
+ 'Box8':{'Filter0':{'type':'filter','filters':{'3':'!=Tax','4':'Sales','12':'EU'}}},
+ 'Box9':{'Filter0':{'type':'filter','filters':{'2':'Expense','3':'!=Tax','12':'EU'}}}
+ },
+ 'show_detail': 1
+ }))
+ data = frappe.desk.query_report.run(report_name,
+ filters={
+ 'from_date': self.from_date,
+ 'to_date': self.to_date,
+ 'company': '_T',
+ 'mode': 'run',
+ 'report_name': report_name
+ }, user=frappe.session.user)
+
+ self.assertListEqual(data.get('columns'), self.default_columns)
+ expected = (('Box1', 43.25), ('Box2', 0.0), ('Box3', 43.25), ('Box4', -85.28), ('Box5', -42.03),
+ ('Box6', 825.0), ('Box7', -426.40), ('Box8', 0.0), ('Box9', 0.0))
+ exrow = iter(expected)
+ for row in data.get('result'):
+ if row.get('voucher_no') and not row.get('posting_date'):
+ label, value = next(exrow)
+ self.assertDictEqual(row, {'voucher_no': label, 'amount': value})
+ self.assertListEqual(data.get('report_summary'),
+ [{'label': label, 'datatype': 'Currency', 'value': value} for label, value in expected])
def test_filter_match(self):
# None - treated as -inf number except range
From 7555f5f6130c20bfb9d608810a0215752dd7914c Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Thu, 8 Apr 2021 23:54:34 +0000
Subject: [PATCH 079/262] fix: add to workspace and fix lint
---
erpnext/accounts/report/tax_detail/tax_detail.js | 12 ++----------
.../accounts/workspace/accounting/accounting.json | 10 ++++++++++
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 0c0397ab04..098096ce0b 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -376,16 +376,8 @@ erpnext.TaxDetail = class TaxDetail {
this.controls = controls;
}
show_help() {
- const help = __(`Help: Your custom report is built from General Ledger Entries within the date range.
- You can add multiple sections to the report using the New Section button.
- Each component added to a section adds a subset of the data into the specified section.
- Beware of duplicated data rows.
- The Filtered Row component type saves the datatable column filters to specify the added data.
- The Section component type refers to the data in a previously defined section, but it cannot refer to its parent section.
- The Amount column is summed to give the section subtotal.
- Use the Show Detail box to see the data rows included in each section in the final report.
- Once finished, hit Save & Run. Report contributed by`);
- this.qr.$report_footer.append(``);
+ const help = __('Your custom report is built from General Ledger Entries within the date range. You can add multiple sections to the report using the New Section button. Each component added to a section adds a subset of the data into the specified section. Beware of duplicated data rows. The Filtered Row component type saves the datatable column filters to specify the added data. The Section component type refers to the data in a previously defined section, but it cannot refer to its parent section. The Amount column is summed to give the section subtotal. Use the Show Detail box to see the data rows included in each section in the final report. Once finished, hit Save & Run. Report contributed by');
+ this.qr.$report_footer.append('`);
}
}
diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json
index df68318052..cbfba7e31c 100644
--- a/erpnext/accounts/workspace/accounting/accounting.json
+++ b/erpnext/accounts/workspace/accounting/accounting.json
@@ -434,6 +434,16 @@
"onboard": 0,
"type": "Link"
},
+ {
+ "dependencies": "GL Entry",
+ "hidden": 0,
+ "is_query_report": 1,
+ "label": "Tax Detail",
+ "link_to": "Tax Detail",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
{
"dependencies": "GL Entry",
"hidden": 0,
From 391dc45964913d79c3baec434a6692a370d570d3 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Fri, 9 Apr 2021 00:23:08 +0000
Subject: [PATCH 080/262] chore: fix sider
---
.../accounts/report/tax_detail/tax_detail.py | 59 ++++++++++++-------
.../report/tax_detail/test_tax_detail.py | 12 ++--
2 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index fb7791f7e1..aafcf1297e 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -3,7 +3,8 @@
# Contributed by Case Solved and sponsored by Nulight Studios
from __future__ import unicode_literals
-import frappe, json
+import frappe
+import json
from frappe import _
# NOTE: Payroll is implemented using Journal Entries which are included as GL Entries
@@ -86,26 +87,35 @@ def run_report(report_name, data):
except KeyError:
frappe.throw(_("A report component can only refer to an earlier section: ") + section_name)
- if show_detail: new_data += report[section_name]['rows']
- new_data += [ {'voucher_no': section_name, 'amount': report[section_name]['subtotal']} ]
- summary += [ {'label': section_name, 'datatype': 'Currency', 'value': report[section_name]['subtotal']} ]
- if show_detail: new_data += [ {} ]
+ if show_detail:
+ new_data += report[section_name]['rows']
+ new_data += [{'voucher_no': section_name, 'amount': report[section_name]['subtotal']}]
+ summary += [{'label': section_name, 'datatype': 'Currency', 'value': report[section_name]['subtotal']}]
+ if show_detail:
+ new_data += [{}]
return new_data or data, summary or None
def filter_match(value, string):
"Approximation to datatable filters"
import datetime
- if string == '': return True
- if value is None: value = -999999999999999
- elif isinstance(value, datetime.date): return True
+ if string == '':
+ return True
+ if value is None:
+ value = -999999999999999
+ elif isinstance(value, datetime.date):
+ return True
if isinstance(value, str):
value = value.lower()
string = string.lower()
- if string[0] == '<': return True if string[1:].strip() else False
- elif string[0] == '>': return False if string[1:].strip() else True
- elif string[0] == '=': return string[1:] in value if string[1:] else False
- elif string[0:2] == '!=': return string[2:] not in value
+ if string[0] == '<':
+ return True if string[1:].strip() else False
+ elif string[0] == '>':
+ return False if string[1:].strip() else True
+ elif string[0] == '=':
+ return string[1:] in value if string[1:] else False
+ elif string[0:2] == '!=':
+ return string[2:] not in value
elif len(string.split(':')) == 2:
pre, post = string.split(':')
return (True if not pre.strip() and post.strip() in value else False)
@@ -114,7 +124,8 @@ def filter_match(value, string):
else:
if string[0] in ['<', '>', '=']:
operator = string[0]
- if operator == '=': operator = '=='
+ if operator == '=':
+ operator = '=='
string = string[1:].strip()
elif string[0:2] == '!=':
operator = '!='
@@ -132,12 +143,16 @@ def filter_match(value, string):
num = float(string) if string.strip() else 0
return eval(f'{value} {operator} {num}')
except ValueError:
- if operator == '<': return True
+ if operator == '<':
+ return True
return False
-abbrev = lambda dt: ''.join(l[0].lower() for l in dt.split(' ')) + '.'
-doclist = lambda dt, dfs: [abbrev(dt) + f for f in dfs]
+def abbrev(dt):
+ return ''.join(l[0].lower() for l in dt.split(' ')) + '.'
+
+def doclist(dt, dfs):
+ return [abbrev(dt) + f for f in dfs]
def as_split(fields):
for field in fields:
@@ -165,7 +180,8 @@ def get_columns(fieldlist):
for doctypes, docfields in fieldlist.items():
fieldmap = {name: new_name for name, new_name in as_split(docfields)}
for doctype in doctypes:
- if isinstance(doctype, int): break
+ if isinstance(doctype, int):
+ break
meta = frappe.get_meta(doctype)
# get column field metadata from the db
fieldmeta = {}
@@ -203,8 +219,10 @@ def modify_report_data(data):
import json
new_data = []
for line in data:
- if line.debit: line.amount = -line.debit
- else: line.amount = line.credit
+ if line.debit:
+ line.amount = -line.debit
+ else:
+ line.amount = line.credit
# Remove Invoice GL Tax Entries and generate Tax entries from the invoice lines
if "Invoice" in line.voucher_type:
if line.account_type != "Tax":
@@ -226,7 +244,8 @@ def modify_report_data(data):
new_data += [line]
return new_data
-####### JS client utilities
+
+# JS client utilities
custom_report_dict = {
'ref_doctype': 'GL Entry',
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index c9b8e209e4..614ef8d234 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -1,6 +1,10 @@
from __future__ import unicode_literals
-import frappe, unittest, datetime, json, os
+import frappe
+import unittest
+import datetime
+import json
+import os
from frappe.utils import getdate, add_to_date, get_first_day, get_last_day
from .tax_detail import filter_match, save_custom_report
@@ -38,12 +42,8 @@ class TestTaxDetail(unittest.TestCase):
db_doc.submit()
else:
db_doc.insert()
- except frappe.exceptions.DuplicateEntryError as e:
+ except frappe.exceptions.DuplicateEntryError:
pass
- #print(f'Duplicate Entry: {e}')
- except:
- print(f'\nError importing {doc["doctype"]}: {doc["name"]}')
- raise
self.load_defcols()
From 06e31e5d7dd4d453f65b728743a62d782b4a133b Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sat, 10 Apr 2021 00:31:16 +0000
Subject: [PATCH 081/262] fix: Test data for empty db
---
.../report/tax_detail/test_tax_detail.json | 116 ++++++++++++++++--
.../report/tax_detail/test_tax_detail.py | 50 ++++----
2 files changed, 132 insertions(+), 34 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.json b/erpnext/accounts/report/tax_detail/test_tax_detail.json
index 17248d0320..977920a231 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.json
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.json
@@ -6,6 +6,98 @@
"default_currency": "GBP",
"doctype": "Company",
"name": "_T"
+ },{
+ "account_manager": null,
+ "accounts": [],
+ "companies": [],
+ "credit_limits": [],
+ "customer_details": null,
+ "customer_group": "All Customer Groups",
+ "customer_name": "_Test Customer",
+ "customer_pos_id": null,
+ "customer_primary_address": null,
+ "customer_primary_contact": null,
+ "customer_type": "Company",
+ "default_bank_account": null,
+ "default_commission_rate": 0.0,
+ "default_currency": null,
+ "default_price_list": null,
+ "default_sales_partner": null,
+ "disabled": 0,
+ "dn_required": 0,
+ "docstatus": 0,
+ "doctype": "Customer",
+ "email_id": null,
+ "gender": null,
+ "image": null,
+ "industry": null,
+ "is_frozen": 0,
+ "is_internal_customer": 0,
+ "language": "en",
+ "lead_name": null,
+ "loyalty_program": null,
+ "loyalty_program_tier": null,
+ "market_segment": null,
+ "mobile_no": null,
+ "modified": "2021-02-15 05:18:03.624724",
+ "name": "_Test Customer",
+ "naming_series": "CUST-.YYYY.-",
+ "pan": null,
+ "parent": null,
+ "parentfield": null,
+ "parenttype": null,
+ "payment_terms": null,
+ "primary_address": null,
+ "represents_company": "",
+ "sales_team": [],
+ "salutation": null,
+ "so_required": 0,
+ "tax_category": null,
+ "tax_id": null,
+ "tax_withholding_category": null,
+ "territory": "All Territories",
+ "website": null
+ },{
+ "accounts": [],
+ "allow_purchase_invoice_creation_without_purchase_order": 0,
+ "allow_purchase_invoice_creation_without_purchase_receipt": 0,
+ "companies": [],
+ "country": "United Kingdom",
+ "default_bank_account": null,
+ "default_currency": null,
+ "default_price_list": null,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Supplier",
+ "hold_type": "",
+ "image": null,
+ "is_frozen": 0,
+ "is_internal_supplier": 0,
+ "is_transporter": 0,
+ "language": "en",
+ "modified": "2021-03-31 16:47:10.109316",
+ "name": "_Test Supplier",
+ "naming_series": "SUP-.YYYY.-",
+ "on_hold": 0,
+ "pan": null,
+ "parent": null,
+ "parentfield": null,
+ "parenttype": null,
+ "payment_terms": null,
+ "prevent_pos": 0,
+ "prevent_rfqs": 0,
+ "release_date": null,
+ "represents_company": null,
+ "supplier_details": null,
+ "supplier_group": "Raw Material",
+ "supplier_name": "_Test Supplier",
+ "supplier_type": "Company",
+ "tax_category": null,
+ "tax_id": null,
+ "tax_withholding_category": null,
+ "warn_pos": 0,
+ "warn_rfqs": 0,
+ "website": null
},{
"account_currency": "GBP",
"account_name": "Debtors",
@@ -251,7 +343,7 @@
"item_name": "Widget Fluid 1Litre",
"item_tax_amount": 0.0,
"item_tax_rate": "{\"VAT on Purchases - _T\": 20.0}",
- "item_tax_template": "Purchase - Standard VAT",
+ "item_tax_template": null,
"landed_cost_voucher_amount": 0.0,
"manufacturer": null,
"manufacturer_part_no": null,
@@ -336,11 +428,11 @@
"shipping_rule": null,
"status": "Unpaid",
"supplied_items": [],
- "supplier": "Raw Materials Inc",
+ "supplier": "_Test Supplier",
"supplier_address": null,
- "supplier_name": "Raw Materials Inc",
+ "supplier_name": "_Test Supplier",
"supplier_warehouse": "Stores - _T",
- "tax_category": "Other Supplier",
+ "tax_category": null,
"tax_id": null,
"tax_withholding_category": null,
"taxes": [
@@ -371,7 +463,7 @@
"taxes_and_charges_deducted": 0.0,
"tc_name": null,
"terms": null,
- "title": "Raw Materials Inc",
+ "title": "_Purchase Invoice",
"to_date": null,
"total": 426.4,
"total_advance": 0.0,
@@ -421,10 +513,10 @@
"conversion_rate": 1.0,
"cost_center": null,
"currency": "GBP",
- "customer": "ABC Tyres",
+ "customer": "_Test Customer",
"customer_address": null,
"customer_group": "All Customer Groups",
- "customer_name": "ABC Tyres",
+ "customer_name": "_Test Customer",
"debit_to": "Debtors - _T",
"discount_amount": 0.0,
"docstatus": 0,
@@ -481,7 +573,7 @@
"item_group": null,
"item_name": "Dunlop tyres",
"item_tax_rate": "{\"VAT on Sales - _T\": 20.0}",
- "item_tax_template": "Sale - Standard VAT",
+ "item_tax_template": null,
"margin_rate_or_amount": 0.0,
"margin_type": "",
"net_amount": 200.0,
@@ -552,7 +644,7 @@
"item_group": null,
"item_name": "Continental tyres",
"item_tax_rate": "{\"VAT on Sales - _T\": 5.0}",
- "item_tax_template": "Sale - Reduced VAT",
+ "item_tax_template": null,
"margin_rate_or_amount": 0.0,
"margin_type": "",
"net_amount": 65.0,
@@ -623,7 +715,7 @@
"item_group": null,
"item_name": "Toyo tyres",
"item_tax_rate": "{\"VAT on Sales - _T\": 0.0}",
- "item_tax_template": "Sale - Zero VAT",
+ "item_tax_template": null,
"margin_rate_or_amount": 0.0,
"margin_type": "",
"net_amount": 560.0,
@@ -735,7 +827,7 @@
"terms": null,
"territory": "All Territories",
"timesheets": [],
- "title": "ABC Tyres",
+ "title": "_Sales Invoice",
"to_date": null,
"total": 825.0,
"total_advance": 0.0,
@@ -752,4 +844,4 @@
"write_off_cost_center": null,
"write_off_outstanding_amount_automatically": 0
}
-]
\ No newline at end of file
+]
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index 614ef8d234..21732b9dfd 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -5,34 +5,27 @@ import unittest
import datetime
import json
import os
-from frappe.utils import getdate, add_to_date, get_first_day, get_last_day
+from frappe.utils import getdate, add_to_date, get_first_day, get_last_day, get_year_start, get_year_ending
from .tax_detail import filter_match, save_custom_report
class TestTaxDetail(unittest.TestCase):
def load_testdocs(self):
datapath, _ = os.path.splitext(os.path.realpath(__file__))
with open(datapath + '.json', 'r') as fp:
- self.docs = json.load(fp)
+ docs = json.load(fp)
- def load_defcols(self):
- custom_report = frappe.get_doc('Report', 'Tax Detail')
- self.default_columns, _ = custom_report.run_query_report(
- filters={
- 'from_date': '2021-03-01',
- 'to_date': '2021-03-31',
- 'company': '_T',
- 'mode': 'run',
- 'report_name': 'Tax Detail'
- }, user=frappe.session.user)
-
- def setUp(self):
- "Add Transactions in 01-03-2021 - 31-03-2021"
- self.load_testdocs()
now = getdate()
self.from_date = get_first_day(now)
self.to_date = get_last_day(now)
- for doc in self.docs:
+ docs = [{
+ "doctype": "Fiscal Year",
+ "year": "_Test Fiscal",
+ "year_end_date": get_year_ending(now),
+ "year_start_date": get_year_start(now)
+ }] + docs
+
+ for doc in docs:
try:
db_doc = frappe.get_doc(doc)
if 'Invoice' in db_doc.doctype:
@@ -45,15 +38,28 @@ class TestTaxDetail(unittest.TestCase):
except frappe.exceptions.DuplicateEntryError:
pass
+ def load_defcols(self):
+ self.company = frappe.get_doc('Company', '_T')
+ custom_report = frappe.get_doc('Report', 'Tax Detail')
+ self.default_columns, _ = custom_report.run_query_report(
+ filters={
+ 'from_date': '2021-03-01',
+ 'to_date': '2021-03-31',
+ 'company': self.company.name,
+ 'mode': 'run',
+ 'report_name': 'Tax Detail'
+ }, user=frappe.session.user)
+
+ def setUp(self):
+ self.load_testdocs()
self.load_defcols()
def tearDown(self):
"Remove the Company and all data"
from erpnext.setup.doctype.company.delete_company_transactions import delete_company_transactions
- for co in filter(lambda doc: doc['doctype'] == 'Company', self.docs):
- delete_company_transactions(co['name'])
- db_co = frappe.get_doc('Company', co['name'])
- db_co.delete()
+ delete_company_transactions(self.company.name)
+ self.company.delete()
+
def test_report(self):
report_name = save_custom_report(
@@ -78,7 +84,7 @@ class TestTaxDetail(unittest.TestCase):
filters={
'from_date': self.from_date,
'to_date': self.to_date,
- 'company': '_T',
+ 'company': self.company.name,
'mode': 'run',
'report_name': report_name
}, user=frappe.session.user)
From 89fcdf32263e2baaa704fb97f121759e34d87701 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sat, 10 Apr 2021 00:32:11 +0000
Subject: [PATCH 082/262] fix: exclude rounding GL Entries from invoice tax
lines
---
.../accounts/report/tax_detail/tax_detail.py | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index aafcf1297e..fdecd269eb 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -225,21 +225,21 @@ def modify_report_data(data):
line.amount = line.credit
# Remove Invoice GL Tax Entries and generate Tax entries from the invoice lines
if "Invoice" in line.voucher_type:
- if line.account_type != "Tax":
+ if line.account_type not in ("Tax", "Round Off"):
new_data += [line]
- if line.item_tax_rate:
- tax_rates = json.loads(line.item_tax_rate)
- for account, rate in tax_rates.items():
- tax_line = line.copy()
- tax_line.account_type = "Tax"
- tax_line.account = account
- if line.voucher_type == "Sales Invoice":
- line.amount = line.base_net_amount
- tax_line.amount = line.base_net_amount * (rate / 100)
- if line.voucher_type == "Purchase Invoice":
- line.amount = -line.base_net_amount
- tax_line.amount = -line.base_net_amount * (rate / 100)
- new_data += [tax_line]
+ if line.item_tax_rate:
+ tax_rates = json.loads(line.item_tax_rate)
+ for account, rate in tax_rates.items():
+ tax_line = line.copy()
+ tax_line.account_type = "Tax"
+ tax_line.account = account
+ if line.voucher_type == "Sales Invoice":
+ line.amount = line.base_net_amount
+ tax_line.amount = line.base_net_amount * (rate / 100)
+ if line.voucher_type == "Purchase Invoice":
+ line.amount = -line.base_net_amount
+ tax_line.amount = -line.base_net_amount * (rate / 100)
+ new_data += [tax_line]
else:
new_data += [line]
return new_data
From 75ebfbdaf392cbb98100291a52d2623a7337618d Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sat, 10 Apr 2021 02:27:00 +0000
Subject: [PATCH 083/262] fix: fiscal year test case issue
---
.../accounts/report/tax_detail/test_tax_detail.json | 11 ++---------
.../accounts/report/tax_detail/test_tax_detail.py | 13 +++++++++++++
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.json b/erpnext/accounts/report/tax_detail/test_tax_detail.json
index 977920a231..3a4b175455 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.json
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.json
@@ -1,12 +1,5 @@
[
{
- "abbr": "_T",
- "company_name": "_T",
- "country": "United Kingdom",
- "default_currency": "GBP",
- "doctype": "Company",
- "name": "_T"
- },{
"account_manager": null,
"accounts": [],
"companies": [],
@@ -297,7 +290,7 @@
"discount_amount": 0.0,
"docstatus": 0,
"doctype": "Purchase Invoice",
- "due_date": "2021-04-30",
+ "due_date": null,
"from_date": null,
"grand_total": 511.68,
"group_same_items": 0,
@@ -521,7 +514,7 @@
"discount_amount": 0.0,
"docstatus": 0,
"doctype": "Sales Invoice",
- "due_date": "2021-03-31",
+ "due_date": null,
"from_date": null,
"grand_total": 868.25,
"group_same_items": 0,
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index 21732b9dfd..dcf0e79064 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -19,6 +19,19 @@ class TestTaxDetail(unittest.TestCase):
self.to_date = get_last_day(now)
docs = [{
+ "abbr": "_T",
+ "company_name": "_T",
+ "country": "United Kingdom",
+ "default_currency": "GBP",
+ "doctype": "Company",
+ "name": "_T"
+ },{
+ "companies": [{
+ "company": "_T",
+ "parent": "_Test Fiscal",
+ "parentfield": "companies",
+ "parenttype": "Fiscal Year"
+ }],
"doctype": "Fiscal Year",
"year": "_Test Fiscal",
"year_end_date": get_year_ending(now),
From 68a31d3d0d799608fbf5593f5f7d732d2971eb03 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sat, 10 Apr 2021 18:59:57 +0000
Subject: [PATCH 084/262] fix: fiscal year error
---
.../report/tax_detail/test_tax_detail.py | 28 +++++++++++--------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index dcf0e79064..772b9a468a 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -18,6 +18,23 @@ class TestTaxDetail(unittest.TestCase):
self.from_date = get_first_day(now)
self.to_date = get_last_day(now)
+ for fy in frappe.get_list('Fiscal Year', fields=('year', 'year_start_date', 'year_end_date')):
+ if now >= fy['year_start_date'] and now <= fy['year_end_date']:
+ break
+ else:
+ docs = [{
+ "companies": [{
+ "company": "_T",
+ "parent": "_Test Fiscal",
+ "parentfield": "companies",
+ "parenttype": "Fiscal Year"
+ }],
+ "doctype": "Fiscal Year",
+ "year": "_Test Fiscal",
+ "year_end_date": get_year_ending(now),
+ "year_start_date": get_year_start(now)
+ }] + docs
+
docs = [{
"abbr": "_T",
"company_name": "_T",
@@ -25,17 +42,6 @@ class TestTaxDetail(unittest.TestCase):
"default_currency": "GBP",
"doctype": "Company",
"name": "_T"
- },{
- "companies": [{
- "company": "_T",
- "parent": "_Test Fiscal",
- "parentfield": "companies",
- "parenttype": "Fiscal Year"
- }],
- "doctype": "Fiscal Year",
- "year": "_Test Fiscal",
- "year_end_date": get_year_ending(now),
- "year_start_date": get_year_start(now)
}] + docs
for doc in docs:
From cf5b57bfacff6ffe813c7fcfef1b74d80b545337 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sat, 10 Apr 2021 20:32:22 +0000
Subject: [PATCH 085/262] fix: only load data for tests that need it
---
erpnext/accounts/report/tax_detail/test_tax_detail.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index 772b9a468a..78b15b11c5 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -69,11 +69,7 @@ class TestTaxDetail(unittest.TestCase):
'report_name': 'Tax Detail'
}, user=frappe.session.user)
- def setUp(self):
- self.load_testdocs()
- self.load_defcols()
-
- def tearDown(self):
+ def rm_testdocs(self):
"Remove the Company and all data"
from erpnext.setup.doctype.company.delete_company_transactions import delete_company_transactions
delete_company_transactions(self.company.name)
@@ -81,6 +77,8 @@ class TestTaxDetail(unittest.TestCase):
def test_report(self):
+ self.load_testdocs()
+ self.load_defcols()
report_name = save_custom_report(
'Tax Detail',
'_Test Tax Detail',
@@ -119,6 +117,8 @@ class TestTaxDetail(unittest.TestCase):
self.assertListEqual(data.get('report_summary'),
[{'label': label, 'datatype': 'Currency', 'value': value} for label, value in expected])
+ self.rm_testdocs()
+
def test_filter_match(self):
# None - treated as -inf number except range
self.assertTrue(filter_match(None, '!='))
From 699878605531f588d9f1afd836cf4b0c6621658f Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Mon, 12 Apr 2021 13:03:09 +0000
Subject: [PATCH 086/262] fix: use correct fiscal year function in testing
---
erpnext/accounts/report/tax_detail/test_tax_detail.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index 78b15b11c5..d3b8de5d19 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -10,6 +10,7 @@ from .tax_detail import filter_match, save_custom_report
class TestTaxDetail(unittest.TestCase):
def load_testdocs(self):
+ from erpnext.accounts.utils import get_fiscal_year, FiscalYearError
datapath, _ = os.path.splitext(os.path.realpath(__file__))
with open(datapath + '.json', 'r') as fp:
docs = json.load(fp)
@@ -18,10 +19,9 @@ class TestTaxDetail(unittest.TestCase):
self.from_date = get_first_day(now)
self.to_date = get_last_day(now)
- for fy in frappe.get_list('Fiscal Year', fields=('year', 'year_start_date', 'year_end_date')):
- if now >= fy['year_start_date'] and now <= fy['year_end_date']:
- break
- else:
+ try:
+ get_fiscal_year(now, company="_T")
+ except FiscalYearError:
docs = [{
"companies": [{
"company": "_T",
From d5256b60d48806e5e10442663623959fda7fb570 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Sun, 18 Apr 2021 22:13:39 +0000
Subject: [PATCH 087/262] fix: lint
---
erpnext/accounts/report/tax_detail/tax_detail.js | 4 ++--
erpnext/accounts/report/tax_detail/tax_detail.py | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.js b/erpnext/accounts/report/tax_detail/tax_detail.js
index 098096ce0b..ed6fac4e60 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.js
+++ b/erpnext/accounts/report/tax_detail/tax_detail.js
@@ -273,7 +273,7 @@ erpnext.TaxDetail = class TaxDetail {
click: () => {
let cur_section = this.controls['section_name'].get_input_value();
if (cur_section) {
- frappe.confirm(__('Are you sure you want to delete section ') + cur_section + '?',
+ frappe.confirm(__('Are you sure you want to delete section') + ' ' + cur_section + '?',
() => {this.delete(cur_section, 'section')});
}
}
@@ -354,7 +354,7 @@ erpnext.TaxDetail = class TaxDetail {
click: () => {
const component = this.controls['component'].get_input_value();
if (component) {
- frappe.confirm(__('Are you sure you want to delete component ') + component + '?',
+ frappe.confirm(__('Are you sure you want to delete component') + ' ' + component + '?',
() => {this.delete(component, 'component')});
}
}
diff --git a/erpnext/accounts/report/tax_detail/tax_detail.py b/erpnext/accounts/report/tax_detail/tax_detail.py
index fdecd269eb..18436de3d8 100644
--- a/erpnext/accounts/report/tax_detail/tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/tax_detail.py
@@ -80,12 +80,12 @@ def run_report(report_name, data):
report[section_name]['subtotal'] += row['amount']
if component['type'] == 'section':
if component_name == section_name:
- frappe.throw(_("A report component cannot refer to its parent section: ") + section_name)
+ frappe.throw(_("A report component cannot refer to its parent section") + ": " + section_name)
try:
report[section_name]['rows'] += report[component_name]['rows']
report[section_name]['subtotal'] += report[component_name]['subtotal']
except KeyError:
- frappe.throw(_("A report component can only refer to an earlier section: ") + section_name)
+ frappe.throw(_("A report component can only refer to an earlier section") + ": " + section_name)
if show_detail:
new_data += report[section_name]['rows']
@@ -141,7 +141,7 @@ def filter_match(value, string):
try:
num = float(string) if string.strip() else 0
- return eval(f'{value} {operator} {num}')
+ return frappe.safe_eval(f'{value} {operator} {num}')
except ValueError:
if operator == '<':
return True
From 6ab46e288f15e77815c0bd3a67fc0d6ba8e28e03 Mon Sep 17 00:00:00 2001
From: casesolved-co-uk
Date: Thu, 13 May 2021 12:56:02 +0000
Subject: [PATCH 088/262] fix: workspace formatting due to manual edit and
filter tweaks
---
.../workspace/accounting/accounting.json | 22 ++++++++++---------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json
index cbfba7e31c..148436edaa 100644
--- a/erpnext/accounts/workspace/accounting/accounting.json
+++ b/erpnext/accounts/workspace/accounting/accounting.json
@@ -452,18 +452,20 @@
"link_to": "DATEV",
"link_type": "Report",
"onboard": 0,
+ "only_for": "Germany",
"type": "Link"
},
{
- "dependencies": "GL Entry",
- "hidden": 0,
- "is_query_report": 1,
- "label": "UAE VAT 201",
- "link_to": "UAE VAT 201",
- "link_type": "Report",
- "onboard": 0,
- "type": "Link"
- },
+ "dependencies": "GL Entry",
+ "hidden": 0,
+ "is_query_report": 1,
+ "label": "UAE VAT 201",
+ "link_to": "UAE VAT 201",
+ "link_type": "Report",
+ "onboard": 0,
+ "only_for": "United Arab Emirates",
+ "type": "Link"
+ },
{
"hidden": 0,
"is_query_report": 0,
@@ -1062,7 +1064,7 @@
"type": "Link"
}
],
- "modified": "2021-05-12 11:48:01.905144",
+ "modified": "2021-05-13 13:44:56.249888",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",
From e9f6c8cdb19b93fb5c9a96e5f0e920032059e1ed Mon Sep 17 00:00:00 2001
From: rohitwaghchaure
Date: Fri, 14 May 2021 12:34:13 +0530
Subject: [PATCH 089/262] fix: validation message of quality inspection in
purchase receipt (#25667)
---
erpnext/controllers/stock_controller.py | 3 +--
.../doctype/quality_inspection/test_quality_inspection.py | 3 ++-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index b14c274515..41ca404d9b 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -379,8 +379,7 @@ class StockController(AccountsController):
link = frappe.utils.get_link_to_form('Quality Inspection', d.quality_inspection)
frappe.throw(_("Quality Inspection: {0} is not submitted for the item: {1} in row {2}").format(link, d.item_code, d.idx), QualityInspectionNotSubmittedError)
- qa_failed = any([r.status=="Rejected" for r in qa_doc.readings])
- if qa_failed:
+ if qa_doc.status != 'Accepted':
frappe.throw(_("Row {0}: Quality Inspection rejected for item {1}")
.format(d.idx, d.item_code), QualityInspectionRejectedError)
elif qa_required :
diff --git a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
index a7dfc9ee28..56b046a92e 100644
--- a/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
+++ b/erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
@@ -27,10 +27,11 @@ class TestQualityInspection(unittest.TestCase):
dn.reload()
self.assertRaises(QualityInspectionRejectedError, dn.submit)
- frappe.db.set_value("Quality Inspection Reading", {"parent": qa.name}, "status", "Accepted")
+ frappe.db.set_value("Quality Inspection", qa.name, "status", "Accepted")
dn.reload()
dn.submit()
+ qa.reload()
qa.cancel()
dn.reload()
dn.cancel()
From ad0b8fdd1e63c01c0819e129940fae5b83924560 Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 17 May 2021 10:49:21 +0530
Subject: [PATCH 090/262] chore: Added change log for v13.3.0
---
erpnext/change_log/v13/v13_3_0.md | 73 +++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
create mode 100644 erpnext/change_log/v13/v13_3_0.md
diff --git a/erpnext/change_log/v13/v13_3_0.md b/erpnext/change_log/v13/v13_3_0.md
new file mode 100644
index 0000000000..016dbb01f4
--- /dev/null
+++ b/erpnext/change_log/v13/v13_3_0.md
@@ -0,0 +1,73 @@
+# Version 13.3.0 Release Notes
+
+### Features & Enhancements
+
+- Purchase receipt creation from purchase invoice ([#25126](https://github.com/frappe/erpnext/pull/25126))
+- New Document Transaction Deletion ([#25354](https://github.com/frappe/erpnext/pull/25354))
+- Employee Referral ([#24997](https://github.com/frappe/erpnext/pull/24997))
+- Add Create Expense Claim button in Delivery Trip ([#25526](https://github.com/frappe/erpnext/pull/25526))
+- Reduced rate of asset depreciation as per IT Act ([#25648](https://github.com/frappe/erpnext/pull/25648))
+- Improve DATEV export ([#25238](https://github.com/frappe/erpnext/pull/25238))
+- Add pick batch button ([#25413](https://github.com/frappe/erpnext/pull/25413))
+- Enable custom field search on POS ([#25421](https://github.com/frappe/erpnext/pull/25421))
+- New check field in subscriptions for (not) submitting invoices ([#25394](https://github.com/frappe/erpnext/pull/25394))
+- Show POS reserved stock in stock projected qty report ([#25593](https://github.com/frappe/erpnext/pull/25593))
+- e-way bill validity field ([#25555](https://github.com/frappe/erpnext/pull/25555))
+- Significant reduction in time taken to save sales documents ([#25475](https://github.com/frappe/erpnext/pull/25475))
+
+### Fixes
+
+- Bank statement import via google sheet ([#25677](https://github.com/frappe/erpnext/pull/25677))
+- Invoices not getting fetched during payment reconciliation ([#25598](https://github.com/frappe/erpnext/pull/25598))
+- Error on applying TDS without party ([#25632](https://github.com/frappe/erpnext/pull/25632))
+- Allow to cancel loan with cancelled repayment entry ([#25507](https://github.com/frappe/erpnext/pull/25507))
+- Can't open general ledger from consolidated financial report ([#25542](https://github.com/frappe/erpnext/pull/25542))
+- Add 'Partially Received' to Status drop-down list in Material Request ([#24857](https://github.com/frappe/erpnext/pull/24857))
+- Updated item filters for material request ([#25531](https://github.com/frappe/erpnext/pull/25531))
+- Added validation in stock entry to check duplicate serial nos ([#25611](https://github.com/frappe/erpnext/pull/25611))
+- Update shopify api version ([#25600](https://github.com/frappe/erpnext/pull/25600))
+- Dialog variable assignment after definition in POS ([#25680](https://github.com/frappe/erpnext/pull/25680))
+- Added tax_types list ([#25587](https://github.com/frappe/erpnext/pull/25587))
+- Include search fields in Project Link field query ([#25505](https://github.com/frappe/erpnext/pull/25505))
+- Item stock levels displaying inconsistently ([#25506](https://github.com/frappe/erpnext/pull/25506))
+- Change today to now to get data for reposting ([#25703](https://github.com/frappe/erpnext/pull/25703))
+- Parameter for get_filtered_list_for_consolidated_report in consolidated balance sheet ([#25700](https://github.com/frappe/erpnext/pull/25700))
+- Minor fixes in loan ([#25546](https://github.com/frappe/erpnext/pull/25546))
+- Fieldname when updating docfield property ([#25516](https://github.com/frappe/erpnext/pull/25516))
+- Use get_serial_nos for splitting ([#25590](https://github.com/frappe/erpnext/pull/25590))
+- Show item's full name on hover over item in POS ([#25554](https://github.com/frappe/erpnext/pull/25554))
+- Stock ledger entry created against draft stock entry ([#25540](https://github.com/frappe/erpnext/pull/25540))
+- Incorrect expense account set in pos invoice ([#25543](https://github.com/frappe/erpnext/pull/25543))
+- Stock balance and batch-wise balance history report showing different closing stock ([#25575](https://github.com/frappe/erpnext/pull/25575))
+- Make strings translatable ([#25521](https://github.com/frappe/erpnext/pull/25521))
+- Serial no changed after saving stock reconciliation ([#25541](https://github.com/frappe/erpnext/pull/25541))
+- Ignore fraction difference while making round off gl entry ([#25438](https://github.com/frappe/erpnext/pull/25438))
+- Sync shopify customer addresses ([#25481](https://github.com/frappe/erpnext/pull/25481))
+- Total stock summary report not working ([#25551](https://github.com/frappe/erpnext/pull/25551))
+- Rename field has not updated value of deposit and withdrawal fields ([#25545](https://github.com/frappe/erpnext/pull/25545))
+- Unexpected keyword argument 'merge_logs' ([#25489](https://github.com/frappe/erpnext/pull/25489))
+- Validation message of quality inspection in purchase receipt ([#25667](https://github.com/frappe/erpnext/pull/25667))
+- Added is_stock_item filter ([#25530](https://github.com/frappe/erpnext/pull/25530))
+- Fetch total stock at company in PO ([#25532](https://github.com/frappe/erpnext/pull/25532))
+- Updated filters for process statement of accounts ([#25384](https://github.com/frappe/erpnext/pull/25384))
+- Incorrect expense account set in pos invoice ([#25571](https://github.com/frappe/erpnext/pull/25571))
+- Client script breaking while settings tax labels ([#25653](https://github.com/frappe/erpnext/pull/25653))
+- Empty payment term column in accounts receivable report ([#25556](https://github.com/frappe/erpnext/pull/25556))
+- Designation insufficient permission on lead doctype. ([#25331](https://github.com/frappe/erpnext/pull/25331))
+- Force https for shopify webhook registration ([#25630](https://github.com/frappe/erpnext/pull/25630))
+- Patch regional fields for old companies ([#25673](https://github.com/frappe/erpnext/pull/25673))
+- Woocommerce order sync issue ([#25692](https://github.com/frappe/erpnext/pull/25692))
+- Allow to receive same serial numbers multiple times ([#25471](https://github.com/frappe/erpnext/pull/25471))
+- Update Allocated amount after Paid Amount is changed in PE ([#25515](https://github.com/frappe/erpnext/pull/25515))
+- Updating Standard Notification's channel field ([#25564](https://github.com/frappe/erpnext/pull/25564))
+- Report summary showing inflated values when values are accumulated in Group Company ([#25577](https://github.com/frappe/erpnext/pull/25577))
+- UI fixes related to overflowing payment section ([#25652](https://github.com/frappe/erpnext/pull/25652))
+- List invoices in Payment Reconciliation Payment ([#25524](https://github.com/frappe/erpnext/pull/25524))
+- Ageing errors in PSOA ([#25490](https://github.com/frappe/erpnext/pull/25490))
+- Prevent spurious defaults for items when making prec from dnote ([#25559](https://github.com/frappe/erpnext/pull/25559))
+- Stock reconciliation getting time out error during submission ([#25557](https://github.com/frappe/erpnext/pull/25557))
+- Timesheet filter date exclusive issue ([#25626](https://github.com/frappe/erpnext/pull/25626))
+- Update cost center in the item table fetched from POS Profile ([#25609](https://github.com/frappe/erpnext/pull/25609))
+- Updated modified time in purchase invoice to pull new fields ([#25678](https://github.com/frappe/erpnext/pull/25678))
+- Stock and Accounts Settings form refactor ([#25534](https://github.com/frappe/erpnext/pull/25534))
+- Payment amount showing in foreign currency ([#25292](https://github.com/frappe/erpnext/pull/25292))
\ No newline at end of file
From 2f403f1bcd42e9a8991c604f3a05e94d13dc3b52 Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 17 May 2021 10:50:26 +0530
Subject: [PATCH 091/262] fix: renamed change log
---
erpnext/change_log/v13/v13.0.2.md | 7 -------
1 file changed, 7 deletions(-)
delete mode 100644 erpnext/change_log/v13/v13.0.2.md
diff --git a/erpnext/change_log/v13/v13.0.2.md b/erpnext/change_log/v13/v13.0.2.md
deleted file mode 100644
index 2bfbdfcc5d..0000000000
--- a/erpnext/change_log/v13/v13.0.2.md
+++ /dev/null
@@ -1,7 +0,0 @@
-## Version 13.0.2 Release Notes
-
-### Fixes
-- fix: frappe.whitelist for doc methods ([#25231](https://github.com/frappe/erpnext/pull/25231))
-- fix: incorrect incoming rate for the sales return ([#25306](https://github.com/frappe/erpnext/pull/25306))
-- fix(e-invoicing): validations & tax calculation fixes ([#25314](https://github.com/frappe/erpnext/pull/25314))
-- fix: update scheduler check time ([#25295](https://github.com/frappe/erpnext/pull/25295))
\ No newline at end of file
From 9ec0f118005732d41e84ad7e7844c72d0a01db9c Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 17 May 2021 10:50:42 +0530
Subject: [PATCH 092/262] fix: renamed change log
---
erpnext/change_log/v13/v13_0_2.md | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 erpnext/change_log/v13/v13_0_2.md
diff --git a/erpnext/change_log/v13/v13_0_2.md b/erpnext/change_log/v13/v13_0_2.md
new file mode 100644
index 0000000000..2bfbdfcc5d
--- /dev/null
+++ b/erpnext/change_log/v13/v13_0_2.md
@@ -0,0 +1,7 @@
+## Version 13.0.2 Release Notes
+
+### Fixes
+- fix: frappe.whitelist for doc methods ([#25231](https://github.com/frappe/erpnext/pull/25231))
+- fix: incorrect incoming rate for the sales return ([#25306](https://github.com/frappe/erpnext/pull/25306))
+- fix(e-invoicing): validations & tax calculation fixes ([#25314](https://github.com/frappe/erpnext/pull/25314))
+- fix: update scheduler check time ([#25295](https://github.com/frappe/erpnext/pull/25295))
\ No newline at end of file
From bc92ecb10f36724a967e4bdc17b09fa119f81ec8 Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 17 May 2021 11:56:29 +0550
Subject: [PATCH 093/262] bumped to version 13.3.0
---
erpnext/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 6775398532..ad971e2976 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '13.2.1'
+__version__ = '13.3.0'
def get_default_company(user=None):
'''Get default company for user'''
From 0517abad43592417daade7aa36b4eb40364d7c29 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Sun, 16 May 2021 16:48:44 +0530
Subject: [PATCH 094/262] fix: run scheduler for reposting if there is no
scheduler is running for the reposting
---
.../repost_item_valuation/repost_item_valuation.py | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 63c71891e4..63e96466d0 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -4,8 +4,9 @@
from __future__ import unicode_literals
import frappe, erpnext
+from rq.timeouts import JobTimeoutException
from frappe.model.document import Document
-from frappe.utils import cint, get_link_to_form, add_to_date, now, today
+from frappe.utils import cint, get_link_to_form, add_to_date, now, today, time_diff_in_hours
from erpnext.stock.stock_ledger import repost_future_sle
from erpnext.accounts.utils import update_gl_entries_after, check_if_stock_and_account_balance_synced
from frappe.utils.user import get_users_with_role
@@ -57,7 +58,8 @@ def repost(doc):
repost_gl_entries(doc)
doc.set_status('Completed')
- except Exception:
+
+ except (Exception, JobTimeoutException):
frappe.db.rollback()
traceback = frappe.get_traceback()
frappe.log_error(traceback)
@@ -113,6 +115,12 @@ def notify_error_to_stock_managers(doc, traceback):
frappe.sendmail(recipients=recipients, subject=subject, message=message)
def repost_entries():
+ job_log = frappe.get_all('Scheduled Job Log', fields = ['status', 'creation'],
+ filters = {'scheduled_job_type': 'repost_item_valuation.repost_entries'}, order_by='creation desc', limit=1)
+
+ if job_log and job_log[0]['status'] == 'Start' and time_diff_in_hours(now(), job_log[0]['creation']) < 2:
+ return
+
riv_entries = get_repost_item_valuation_entries()
for row in riv_entries:
From 60ea785dfd434f67112e785b8a4bcb4e7705ee03 Mon Sep 17 00:00:00 2001
From: prssanna
Date: Tue, 18 May 2021 15:42:13 +0530
Subject: [PATCH 095/262] fix: ensure website theme is applied correctly
---
erpnext/public/scss/shopping_cart.scss | 18 +++++++++---------
erpnext/public/scss/website.scss | 9 ++++-----
2 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss
index 159a8a47cd..92e5d32219 100644
--- a/erpnext/public/scss/shopping_cart.scss
+++ b/erpnext/public/scss/shopping_cart.scss
@@ -1,4 +1,3 @@
-@import "frappe/public/scss/desk/variables";
@import "frappe/public/scss/common/mixins";
body.product-page {
@@ -217,12 +216,12 @@ body.product-page {
border-color: var(--table-border-color) !important;
padding: 15px;
- @include media-breakpoint-between(xs, md) {
+ @media (max-width: 840px) {
height: 300px;
width: 300px;
}
- @include media-breakpoint-up(lg) {
+ @media (min-width: 1090px) {
height: 350px;
width: 350px;
}
@@ -233,11 +232,12 @@ body.product-page {
}
.item-slideshow {
- @include media-breakpoint-between(xs, md) {
+
+ @media (max-width: 840px) {
max-height: 320px;
}
- @include media-breakpoint-up(lg) {
+ @media (min-width: 1090px) {
max-height: 430px;
}
@@ -254,7 +254,7 @@ body.product-page {
cursor: pointer;
&:hover, &.active {
- border-color: $primary;
+ border-color: var(--primary);
}
}
@@ -316,12 +316,12 @@ body.product-page {
}
.item-group-slideshow {
- .item-group-description {
+ // .item-group-description {
// max-width: 900px;
- }
+ // }
.carousel-inner.rounded-carousel {
- border-radius: $card-border-radius;
+ border-radius: var(--card-border-radius);
}
}
diff --git a/erpnext/public/scss/website.scss b/erpnext/public/scss/website.scss
index 56b717c424..f4325c03f5 100644
--- a/erpnext/public/scss/website.scss
+++ b/erpnext/public/scss/website.scss
@@ -1,4 +1,3 @@
-@import "frappe/public/scss/website/variables";
.filter-options {
max-height: 300px;
@@ -14,7 +13,7 @@
}
&.active {
- border-color: $primary;
+ border-color: var(--primary);
.check {
display: inline-flex;
@@ -25,7 +24,7 @@
.check {
display: inline-flex;
padding: 0.25rem;
- background: $primary;
+ background: var(--primary);
color: white;
border-radius: 50%;
font-size: 12px;
@@ -38,12 +37,12 @@
}
.result {
- border-bottom: 1px solid $border-color;
+ border-bottom: 1px solid var(--border-color);
}
.transaction-list-item {
padding: 1rem 0;
- border-top: 1px solid $border-color;
+ border-top: 1px solid var(--border-color);
position: relative;
a.transaction-item-link {
From 9d6f343111234a533f04a20da0da0ab86d9066ff Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 18 May 2021 15:44:52 +0530
Subject: [PATCH 096/262] chore(deps): bump ini from 1.3.5 to 1.3.7 (#25733)
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
yarn.lock | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/yarn.lock b/yarn.lock
index 635bb066ec..242695c4b8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1540,16 +1540,11 @@ inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-ini@1.3.7:
+ini@1.3.7, ini@~1.3.0:
version "1.3.7"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84"
integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==
-ini@~1.3.0:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
- integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
-
is-callable@^1.1.5:
version "1.2.3"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e"
From 0fb6f9306f6cb3f6022dca0c2a0f945160a508a1 Mon Sep 17 00:00:00 2001
From: anushka19 <37659765+anushka19@users.noreply.github.com>
Date: Tue, 18 May 2021 17:00:33 +0530
Subject: [PATCH 097/262] fix: Accumulated depreciation (#25740)
* fix: Accumulated depreciation
* fix: Sider issues
---
erpnext/assets/doctype/asset_category/asset_category.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/assets/doctype/asset_category/asset_category.js b/erpnext/assets/doctype/asset_category/asset_category.js
index 74963c2aa9..51ce157a81 100644
--- a/erpnext/assets/doctype/asset_category/asset_category.js
+++ b/erpnext/assets/doctype/asset_category/asset_category.js
@@ -4,7 +4,7 @@
frappe.ui.form.on('Asset Category', {
onload: function(frm) {
frm.add_fetch('company_name', 'accumulated_depreciation_account', 'accumulated_depreciation_account');
- frm.add_fetch('company_name', 'depreciation_expense_account', 'accumulated_depreciation_account');
+ frm.add_fetch('company_name', 'depreciation_expense_account', 'depreciation_expense_account');
frm.set_query('fixed_asset_account', 'accounts', function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
From 1483a60b90e9286875d803a3182996217ced57ed Mon Sep 17 00:00:00 2001
From: Faris Ansari
Date: Wed, 19 May 2021 12:30:11 +0530
Subject: [PATCH 098/262] fix: super call syntax error
---
erpnext/selling/doctype/quotation/quotation.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 10606bf81e..7fecd4bc34 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -39,8 +39,7 @@ frappe.ui.form.on('Quotation', {
erpnext.selling.QuotationController = class QuotationController extends erpnext.selling.SellingController {
onload(doc, dt, dn) {
var me = this;
- super.(doc, dt, dn);
-
+ super.onload(doc, dt, dn);
}
party_name() {
var me = this;
From 5c6d3e043c75b9bd9b5688c34eafbe01bcf0737b Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Wed, 19 May 2021 15:33:58 +0530
Subject: [PATCH 099/262] test: Replace usage of render with get_response
---
erpnext/portal/doctype/homepage/test_homepage.py | 4 ++--
.../doctype/homepage_section/test_homepage_section.py | 6 +++---
.../product_configurator/test_product_configurator.py | 4 +---
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/erpnext/portal/doctype/homepage/test_homepage.py b/erpnext/portal/doctype/homepage/test_homepage.py
index b717491a82..e646775ab3 100644
--- a/erpnext/portal/doctype/homepage/test_homepage.py
+++ b/erpnext/portal/doctype/homepage/test_homepage.py
@@ -6,12 +6,12 @@ from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils import set_request
-from frappe.website.render import render
+from frappe.website.serve import get_response
class TestHomepage(unittest.TestCase):
def test_homepage_load(self):
set_request(method='GET', path='home')
- response = render()
+ response = get_response()
self.assertEqual(response.status_code, 200)
diff --git a/erpnext/portal/doctype/homepage_section/test_homepage_section.py b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
index f0aa554858..5bb9682bc5 100644
--- a/erpnext/portal/doctype/homepage_section/test_homepage_section.py
+++ b/erpnext/portal/doctype/homepage_section/test_homepage_section.py
@@ -7,7 +7,7 @@ import frappe
import unittest
from bs4 import BeautifulSoup
from frappe.utils import set_request
-from frappe.website.render import render
+from frappe.website.serve import get_response
class TestHomepageSection(unittest.TestCase):
def test_homepage_section_card(self):
@@ -26,7 +26,7 @@ class TestHomepageSection(unittest.TestCase):
pass
set_request(method='GET', path='home')
- response = render()
+ response = get_response()
self.assertEqual(response.status_code, 200)
@@ -59,7 +59,7 @@ class TestHomepageSection(unittest.TestCase):
}).insert()
set_request(method='GET', path='home')
- response = render()
+ response = get_response()
self.assertEqual(response.status_code, 200)
diff --git a/erpnext/portal/product_configurator/test_product_configurator.py b/erpnext/portal/product_configurator/test_product_configurator.py
index 3521e7e8bf..0a5ebef523 100644
--- a/erpnext/portal/product_configurator/test_product_configurator.py
+++ b/erpnext/portal/product_configurator/test_product_configurator.py
@@ -2,10 +2,8 @@ from __future__ import unicode_literals
from bs4 import BeautifulSoup
import frappe, unittest
-from frappe.utils import set_request, get_html_for_route
-from frappe.website.render import render
+from frappe.utils import get_html_for_route
from erpnext.portal.product_configurator.utils import get_products_for_website
-from erpnext.stock.doctype.item.test_item import make_item_variant
test_dependencies = ["Item"]
From 6a1e31c63334b7356647d24da84435b25da50bbe Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 20 May 2021 23:16:22 +0530
Subject: [PATCH 100/262] fix: Check if user can rread before querying Support
Settings
---
erpnext/support/doctype/issue/issue.js | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index ecc9fcfe82..99a4e04b7d 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -9,15 +9,17 @@ frappe.ui.form.on("Issue", {
};
});
- frappe.db.get_value("Support Settings", {name: "Support Settings"},
- ["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
- if (r && r.track_service_level_agreement == "0") {
- frm.set_df_property("service_level_section", "hidden", 1);
- }
- if (r && r.allow_resetting_service_level_agreement == "0") {
- frm.set_df_property("reset_service_level_agreement", "hidden", 1);
- }
- });
+ if (frappe.model.can_read("Support Settings")) {
+ frappe.db.get_value("Support Settings", {name: "Support Settings"},
+ ["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
+ if (r && r.track_service_level_agreement == "0") {
+ frm.set_df_property("service_level_section", "hidden", 1);
+ }
+ if (r && r.allow_resetting_service_level_agreement == "0") {
+ frm.set_df_property("reset_service_level_agreement", "hidden", 1);
+ }
+ });
+ }
if (frm.doc.service_level_agreement) {
frappe.call({
From 81d49e9c71fceba8cd2e9369a0f712c0f9c41ccc Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Fri, 21 May 2021 17:03:09 +0530
Subject: [PATCH 101/262] fix: Use extend_cscript function to properly extend
class methods to cscript
---
.eslintrc | 3 ++-
.../payment_reconciliation.js | 2 +-
.../accounts/doctype/pos_invoice/pos_invoice.js | 4 ++--
.../doctype/sales_invoice/sales_invoice.js | 5 ++++-
.../doctype/purchase_order/purchase_order.js | 2 +-
.../request_for_quotation/request_for_quotation.js | 2 +-
.../supplier_quotation/supplier_quotation.js | 2 +-
erpnext/crm/doctype/lead/lead.js | 2 +-
erpnext/crm/doctype/opportunity/opportunity.js | 4 ++--
.../maintenance_schedule/maintenance_schedule.js | 2 +-
.../doctype/maintenance_visit/maintenance_visit.js | 2 +-
erpnext/manufacturing/doctype/bom/bom.js | 4 ++--
erpnext/public/js/controllers/taxes_and_totals.js | 4 +++-
erpnext/public/js/controllers/transaction.js | 2 +-
.../doctype/installation_note/installation_note.js | 2 +-
erpnext/selling/doctype/sales_order/sales_order.js | 5 +++--
erpnext/selling/doctype/sms_center/sms_center.js | 2 +-
.../doctype/currency_exchange/currency_exchange.js | 14 +++++++-------
.../stock/doctype/delivery_note/delivery_note.js | 2 +-
.../doctype/material_request/material_request.js | 4 ++--
.../doctype/purchase_receipt/purchase_receipt.js | 2 +-
erpnext/stock/doctype/stock_entry/stock_entry.js | 2 +-
.../doctype/warranty_claim/warranty_claim.js | 4 ++--
23 files changed, 42 insertions(+), 35 deletions(-)
diff --git a/.eslintrc b/.eslintrc
index 3b6ab7498d..e40502acd6 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -151,6 +151,7 @@
"context": true,
"before": true,
"beforeEach": true,
- "onScan": true
+ "onScan": true,
+ "extend_cscript": true
}
}
diff --git a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
index 8dcd1aa8e7..c71a62dfb3 100644
--- a/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
+++ b/erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.js
@@ -262,4 +262,4 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
};
-$.extend(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.js b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
index 72d587afb5..181e9f8ec0 100644
--- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
+++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.js
@@ -135,7 +135,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
}
-$.extend(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm }))
+extend_cscript(cur_frm.cscript, new erpnext.selling.POSInvoiceController({ frm: cur_frm }))
frappe.ui.form.on('POS Invoice', {
redeem_loyalty_points: function(frm) {
@@ -235,4 +235,4 @@ frappe.ui.form.on('POS Invoice', {
});
});
}
-});
\ No newline at end of file
+});
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index b48db246ac..ea7432caa2 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -450,8 +450,11 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
}
};
+console.log('innn')
// for backward compatibility: combine new and previous states
-$.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm}));
+let controller_instance = new erpnext.accounts.SalesInvoiceController({frm: cur_frm})
+extend_cscript(cur_frm.cscript, controller_instance);
+extend_cscript(cur_frm.cscript.__proto_, controller_instance.__proto__);
cur_frm.cscript['Make Delivery Note'] = function() {
frappe.model.open_mapped_doc({
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index c0e19e9c3d..384bbc5385 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -547,7 +547,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e
};
// for backward compatibility: combine new and previous states
-$.extend(cur_frm.cscript, new erpnext.buying.PurchaseOrderController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.buying.PurchaseOrderController({frm: cur_frm}));
cur_frm.cscript.update_status= function(label, status){
frappe.call({
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index ee0e1ef576..bde00cbd94 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -414,4 +414,4 @@ erpnext.buying.RequestforQuotationController = class RequestforQuotationControll
};
// for backward compatibility: combine new and previous states
-$.extend(cur_frm.cscript, new erpnext.buying.RequestforQuotationController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.buying.RequestforQuotationController({frm: cur_frm}));
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index a3ba52e67b..dc9c590dc5 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -95,7 +95,7 @@ erpnext.buying.SupplierQuotationController = class SupplierQuotationController e
};
// for backward compatibility: combine new and previous states
-$.extend(cur_frm.cscript, new erpnext.buying.SupplierQuotationController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.buying.SupplierQuotationController({frm: cur_frm}));
cur_frm.fields_dict['items'].grid.get_field('project').get_query =
function(doc, cdt, cdn) {
diff --git a/erpnext/crm/doctype/lead/lead.js b/erpnext/crm/doctype/lead/lead.js
index 8dfee1d6c7..ebe85241d2 100644
--- a/erpnext/crm/doctype/lead/lead.js
+++ b/erpnext/crm/doctype/lead/lead.js
@@ -88,4 +88,4 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
}
};
-$.extend(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm }));
+extend_cscript(cur_frm.cscript, new erpnext.LeadController({ frm: cur_frm }));
diff --git a/erpnext/crm/doctype/opportunity/opportunity.js b/erpnext/crm/doctype/opportunity/opportunity.js
index 925c30b451..43e1b99f3a 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.js
+++ b/erpnext/crm/doctype/opportunity/opportunity.js
@@ -195,7 +195,7 @@ erpnext.crm.Opportunity = class Opportunity extends frappe.ui.form.Controller {
}
};
-$.extend(cur_frm.cscript, new erpnext.crm.Opportunity({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.crm.Opportunity({frm: cur_frm}));
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
@@ -213,4 +213,4 @@ cur_frm.cscript.item_code = function(doc, cdt, cdn) {
}
})
}
-}
\ No newline at end of file
+}
diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
index 2adfaf45ef..2371d9652c 100644
--- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
+++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.js
@@ -115,5 +115,5 @@ erpnext.maintenance.MaintenanceSchedule = class MaintenanceSchedule extends frap
}
};
-$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceSchedule({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.maintenance.MaintenanceSchedule({frm: cur_frm}));
diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
index 12dc59ccfc..503253040b 100644
--- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
+++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.js
@@ -99,4 +99,4 @@ erpnext.maintenance.MaintenanceVisit = class MaintenanceVisit extends frappe.ui.
}
};
-$.extend(cur_frm.cscript, new erpnext.maintenance.MaintenanceVisit({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.maintenance.MaintenanceVisit({frm: cur_frm}));
diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js
index b32b96af13..44f841f13b 100644
--- a/erpnext/manufacturing/doctype/bom/bom.js
+++ b/erpnext/manufacturing/doctype/bom/bom.js
@@ -405,7 +405,7 @@ erpnext.bom.BomController = class BomController extends erpnext.TransactionContr
}
};
-$.extend(cur_frm.cscript, new erpnext.bom.BomController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.bom.BomController({frm: cur_frm}));
cur_frm.cscript.hour_rate = function(doc) {
erpnext.bom.calculate_op_cost(doc);
@@ -662,4 +662,4 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) {
frm.set_value("operations", []);
}
toggle_operations(frm);
-});
\ No newline at end of file
+});
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 31410da6bf..32439b6819 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -166,7 +166,9 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
"account_list": frappe.flags.round_off_applicable_accounts
},
callback(r) {
- frappe.flags.round_off_applicable_accounts.push(...r.message);
+ if (r.message) {
+ frappe.flags.round_off_applicable_accounts.push(...r.message);
+ }
}
});
}
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index b5337464ae..0ffda07cde 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -5,7 +5,7 @@ frappe.provide('erpnext.accounts.dimensions');
erpnext.TransactionController = class TransactionController extends erpnext.taxes_and_totals {
setup() {
- this._super();
+ super.setup();
frappe.flags.hide_serial_batch_dialog = true;
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
diff --git a/erpnext/selling/doctype/installation_note/installation_note.js b/erpnext/selling/doctype/installation_note/installation_note.js
index ffa185baf6..27a3b35ccf 100644
--- a/erpnext/selling/doctype/installation_note/installation_note.js
+++ b/erpnext/selling/doctype/installation_note/installation_note.js
@@ -57,4 +57,4 @@ erpnext.selling.InstallationNote = class InstallationNote extends frappe.ui.form
}
};
-$.extend(cur_frm.cscript, new erpnext.selling.InstallationNote({frm: cur_frm}));
\ No newline at end of file
+extend_cscript(cur_frm.cscript, new erpnext.selling.InstallationNote({frm: cur_frm}));
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index d5ceca8ec8..b42c615312 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -104,7 +104,7 @@ frappe.ui.form.on("Sales Order Item", {
erpnext.selling.SalesOrderController = class SalesOrderController extends erpnext.selling.SellingController {
onload(doc, dt, dn) {
- super.onload();
+ super.onload(doc, dt, dn);
}
refresh(doc, dt, dn) {
@@ -744,4 +744,5 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex
});
}
};
-$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
+
+extend_cscript(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
diff --git a/erpnext/selling/doctype/sms_center/sms_center.js b/erpnext/selling/doctype/sms_center/sms_center.js
index dda28031df..974cfc7918 100644
--- a/erpnext/selling/doctype/sms_center/sms_center.js
+++ b/erpnext/selling/doctype/sms_center/sms_center.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-$.extend(cur_frm.cscript, {
+extend_cscript(cur_frm.cscript, {
message: function () {
var total_characters = this.frm.doc.message.length;
var total_msg = 1;
diff --git a/erpnext/setup/doctype/currency_exchange/currency_exchange.js b/erpnext/setup/doctype/currency_exchange/currency_exchange.js
index a8ea55ca0c..85036a163e 100644
--- a/erpnext/setup/doctype/currency_exchange/currency_exchange.js
+++ b/erpnext/setup/doctype/currency_exchange/currency_exchange.js
@@ -1,30 +1,30 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-$.extend(cur_frm.cscript, {
+extend_cscript(cur_frm.cscript, {
onload: function() {
if(cur_frm.doc.__islocal) {
cur_frm.set_value("to_currency", frappe.defaults.get_global_default("currency"));
}
},
-
+
refresh: function() {
cur_frm.cscript.set_exchange_rate_label();
},
-
+
from_currency: function() {
cur_frm.cscript.set_exchange_rate_label();
},
-
+
to_currency: function() {
cur_frm.cscript.set_exchange_rate_label();
},
-
+
set_exchange_rate_label: function() {
if(cur_frm.doc.from_currency && cur_frm.doc.to_currency) {
var default_label = __(frappe.meta.docfield_map[cur_frm.doctype]["exchange_rate"].label);
- cur_frm.fields_dict.exchange_rate.set_label(default_label +
+ cur_frm.fields_dict.exchange_rate.set_label(default_label +
repl(" (1 %(from_currency)s = [?] %(to_currency)s)", cur_frm.doc));
}
}
-});
\ No newline at end of file
+});
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index b736015808..c3803f19a1 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -305,7 +305,7 @@ erpnext.stock.DeliveryNoteController = class DeliveryNoteController extends erpn
}
};
-$.extend(cur_frm.cscript, new erpnext.stock.DeliveryNoteController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.stock.DeliveryNoteController({frm: cur_frm}));
frappe.ui.form.on('Delivery Note', {
setup: function(frm) {
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index f516e061c0..6585e1c78c 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -433,7 +433,7 @@ erpnext.buying.MaterialRequestController = class MaterialRequestController exten
if (doc.material_request_type == "Customer Provided") {
return{
query: "erpnext.controllers.queries.item_query",
- filters:{
+ filters:{
'customer': me.frm.doc.customer,
'is_stock_item':1
}
@@ -472,7 +472,7 @@ erpnext.buying.MaterialRequestController = class MaterialRequestController exten
};
// for backward compatibility: combine new and previous states
-$.extend(cur_frm.cscript, new erpnext.buying.MaterialRequestController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.buying.MaterialRequestController({frm: cur_frm}));
function set_schedule_date(frm) {
if(frm.doc.schedule_date){
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 688ae1d410..0182ed55a1 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -251,7 +251,7 @@ erpnext.stock.PurchaseReceiptController = class PurchaseReceiptController extend
};
// for backward compatibility: combine new and previous states
-$.extend(cur_frm.cscript, new erpnext.stock.PurchaseReceiptController({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.stock.PurchaseReceiptController({frm: cur_frm}));
cur_frm.cscript.update_status = function(status) {
frappe.ui.form.is_saving = true;
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 6afcd1f43e..700093fae3 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1064,4 +1064,4 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => {
}
-$.extend(cur_frm.cscript, new erpnext.stock.StockEntry({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.stock.StockEntry({frm: cur_frm}));
diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.js b/erpnext/support/doctype/warranty_claim/warranty_claim.js
index c9aa41fdae..358768eb46 100644
--- a/erpnext/support/doctype/warranty_claim/warranty_claim.js
+++ b/erpnext/support/doctype/warranty_claim/warranty_claim.js
@@ -55,7 +55,7 @@ erpnext.support.WarrantyClaim = class WarrantyClaim extends frappe.ui.form.Contr
}
};
-$.extend(cur_frm.cscript, new erpnext.support.WarrantyClaim({frm: cur_frm}));
+extend_cscript(cur_frm.cscript, new erpnext.support.WarrantyClaim({frm: cur_frm}));
cur_frm.fields_dict['serial_no'].get_query = function(doc, cdt, cdn) {
var cond = [];
@@ -93,4 +93,4 @@ cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) {
]
}
}
-};
\ No newline at end of file
+};
From 3e6cc5037bb2b9084dab8d6e89d70532c8323bc8 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Fri, 21 May 2021 17:37:19 +0530
Subject: [PATCH 102/262] fix: Remove unnecessary code
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index ea7432caa2..e464a783ad 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -450,11 +450,8 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
}
};
-console.log('innn')
// for backward compatibility: combine new and previous states
-let controller_instance = new erpnext.accounts.SalesInvoiceController({frm: cur_frm})
-extend_cscript(cur_frm.cscript, controller_instance);
-extend_cscript(cur_frm.cscript.__proto_, controller_instance.__proto__);
+extend_cscript(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_frm}));
cur_frm.cscript['Make Delivery Note'] = function() {
frappe.model.open_mapped_doc({
From 59961f70ee7185b346d72e0173db1030281bfc32 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Thu, 20 May 2021 23:43:19 +0530
Subject: [PATCH 103/262] refactor: timesheet
---
.../doctype/sales_invoice/sales_invoice.js | 90 +-
.../doctype/sales_invoice/sales_invoice.json | 10 +-
.../doctype/sales_invoice/sales_invoice.py | 24 +-
.../sales_invoice_timesheet.json | 234 +---
erpnext/patches.txt | 1 +
.../patches/v13_0/update_timesheet_changes.py | 25 +
.../v7_0/convert_timelog_to_timesheet.py | 2 +-
.../doctype/activity_type/activity_type.js | 4 +
.../doctype/timesheet/test_timesheet.py | 14 +-
.../projects/doctype/timesheet/timesheet.js | 169 ++-
.../projects/doctype/timesheet/timesheet.json | 58 +-
.../projects/doctype/timesheet/timesheet.py | 78 +-
.../timesheet_detail/timesheet_detail.json | 1192 ++++-------------
erpnext/projects/report/billing_summary.py | 4 +-
...ee_hours_utilization_based_on_timesheet.py | 6 +-
.../test_employee_util.py | 4 +-
.../test_project_profitability.py | 2 +-
erpnext/public/js/utils.js | 12 +
18 files changed, 697 insertions(+), 1232 deletions(-)
create mode 100644 erpnext/patches/v13_0/update_timesheet_changes.py
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index b48db246ac..9e1dbf4333 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -17,7 +17,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
var me = this;
super.onload();
- this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice'];
+ this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice', 'Timesheet'];
if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) {
// show debit_to in print format
this.frm.set_df_property("debit_to", "print_hide", 0);
@@ -685,14 +685,16 @@ frappe.ui.form.on('Sales Invoice', {
},
project: function(frm){
- frm.call({
- method: "add_timesheet_data",
- doc: frm.doc,
- callback: function(r, rt) {
- refresh_field(['timesheets'])
- }
- })
- frm.refresh();
+ if (!frm.doc.is_return) {
+ frm.call({
+ method: "add_timesheet_data",
+ doc: frm.doc,
+ callback: function(r, rt) {
+ refresh_field(['timesheets'])
+ }
+ })
+ frm.refresh();
+ }
},
onload: function(frm) {
@@ -807,14 +809,27 @@ frappe.ui.form.on('Sales Invoice', {
}
},
+ add_timesheet_row: function(frm, row, exchange_rate) {
+ frm.add_child('timesheets', {
+ 'activity_type': row.activity_type,
+ 'description': row.description,
+ 'time_sheet': row.parent,
+ 'billing_hours': row.billing_hours,
+ 'billing_amount': flt(row.billing_amount) * flt(exchange_rate),
+ 'timesheet_detail': row.name
+ });
+ frm.refresh_field('timesheets');
+ calculate_total_billing_amount(frm);
+ },
+
refresh: function(frm) {
- if (frm.doc.project) {
+ if (frm.doc.docstatus===0 && !frm.doc.is_return) {
frm.add_custom_button(__('Fetch Timesheet'), function() {
let d = new frappe.ui.Dialog({
title: __('Fetch Timesheet'),
fields: [
{
- "label" : "From",
+ "label" : __("From"),
"fieldname": "from_time",
"fieldtype": "Date",
"reqd": 1,
@@ -824,11 +839,18 @@ frappe.ui.form.on('Sales Invoice', {
fieldname: 'col_break_1',
},
{
- "label" : "To",
+ "label" : __("To"),
"fieldname": "to_time",
"fieldtype": "Date",
"reqd": 1,
- }
+ },
+ {
+ "label" : __("Project"),
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "options": "Project",
+ "default": frm.doc.project
+ },
],
primary_action: function() {
let data = d.get_values();
@@ -837,27 +859,35 @@ frappe.ui.form.on('Sales Invoice', {
args: {
from_time: data.from_time,
to_time: data.to_time,
- project: frm.doc.project
+ project: data.project
},
callback: function(r) {
- if(!r.exc) {
- if(r.message.length > 0) {
- frm.clear_table('timesheets')
- r.message.forEach((d) => {
- frm.add_child('timesheets',{
- 'time_sheet': d.parent,
- 'billing_hours': d.billing_hours,
- 'billing_amount': d.billing_amt,
- 'timesheet_detail': d.name
+ if (!r.exc && r.message.length > 0) {
+ frm.clear_table('timesheets')
+ r.message.forEach((d) => {
+ let exchange_rate = 1.0;
+ if (frm.doc.currency != d.currency) {
+ frappe.call({
+ method: 'erpnext.setup.utils.get_exchange_rate',
+ args: {
+ from_currency: d.currency,
+ to_currency: frm.doc.currency
+ },
+ callback: function(r) {
+ if (r.message) {
+ exchange_rate = r.message;
+ frm.events.add_timesheet_row(frm, d, exchange_rate);
+ }
+ }
});
- });
- frm.refresh_field('timesheets')
- }
- else {
- frappe.msgprint(__('No Timesheet Found.'))
- }
- d.hide();
+ } else {
+ frm.events.add_timesheet_row(frm, d, exchange_rate);
+ }
+ });
+ } else {
+ frappe.msgprint(__('No Timesheets found with the selected filters.'))
}
+ d.hide();
}
});
},
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index c6c67b4ddc..52bc409b6e 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -748,6 +748,7 @@
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.total_billing_amount > 0",
+ "depends_on": "eval: !doc.is_return",
"fieldname": "time_sheet_list",
"fieldtype": "Section Break",
"hide_days": 1,
@@ -770,6 +771,7 @@
"hide_days": 1,
"hide_seconds": 1,
"label": "Total Billing Amount",
+ "options": "currency",
"print_hide": 1,
"read_only": 1
},
@@ -1951,6 +1953,12 @@
"label": "Set Target Warehouse",
"options": "Warehouse"
},
+ {
+ "default": "0",
+ "fieldname": "is_debit_note",
+ "fieldtype": "Check",
+ "label": "Is Debit Note"
+ },
{
"default": "0",
"depends_on": "grand_total",
@@ -1969,7 +1977,7 @@
"link_fieldname": "consolidated_invoice"
}
],
- "modified": "2021-04-15 23:57:58.766651",
+ "modified": "2021-05-20 22:48:33.988881",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index bb74a02606..a008742390 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -125,6 +125,8 @@ class SalesInvoice(SellingController):
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
if not self.is_return:
self.validate_serial_numbers()
+ else:
+ self.timesheets = []
self.update_packing_list()
self.set_billing_hours_and_amount()
self.update_timesheet_billing_for_project()
@@ -337,7 +339,7 @@ class SalesInvoice(SellingController):
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_cancel")
-
+ self.unlink_sales_invoice_from_timesheets()
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry', 'Repost Item Valuation')
def update_status_updater_args(self):
@@ -393,6 +395,18 @@ class SalesInvoice(SellingController):
if validate_against_credit_limit:
check_credit_limit(self.customer, self.company, bypass_credit_limit_check_at_sales_order)
+ def unlink_sales_invoice_from_timesheets(self):
+ for row in self.timesheets:
+ timesheet = frappe.get_doc('Timesheet', row.time_sheet)
+ for time_log in timesheet.time_logs:
+ if time_log.sales_invoice == self.name:
+ time_log.sales_invoice = None
+ timesheet.calculate_total_amounts()
+ timesheet.calculate_percentage_billed()
+ timesheet.flags.ignore_validate_update_after_submit = True
+ timesheet.set_status()
+ timesheet.db_update_all()
+
@frappe.whitelist()
def set_missing_values(self, for_validate=False):
pos = self.set_pos_fields(for_validate)
@@ -427,7 +441,7 @@ class SalesInvoice(SellingController):
timesheet.calculate_percentage_billed()
timesheet.flags.ignore_validate_update_after_submit = True
timesheet.set_status()
- timesheet.save()
+ timesheet.db_update_all()
def update_time_sheet_detail(self, timesheet, args, sales_invoice):
for data in timesheet.time_logs:
@@ -741,8 +755,10 @@ class SalesInvoice(SellingController):
self.append('timesheets', {
'time_sheet': data.parent,
'billing_hours': data.billing_hours,
- 'billing_amount': data.billing_amt,
- 'timesheet_detail': data.name
+ 'billing_amount': data.billing_amount,
+ 'timesheet_detail': data.name,
+ 'activity_type': data.activity_type,
+ 'description': data.description
})
self.calculate_billing_amount_for_timesheet()
diff --git a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json
index f7b9aef96c..f069e8dd0b 100644
--- a/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json
+++ b/erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json
@@ -1,172 +1,78 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2016-06-14 19:21:34.321662",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
- "engine": "InnoDB",
+ "actions": [],
+ "creation": "2016-06-14 19:21:34.321662",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "activity_type",
+ "description",
+ "billing_hours",
+ "billing_amount",
+ "time_sheet",
+ "timesheet_detail"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "time_sheet",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 1,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Time Sheet",
- "length": 0,
- "no_copy": 0,
- "options": "Timesheet",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "time_sheet",
+ "fieldtype": "Link",
+ "in_global_search": 1,
+ "in_list_view": 1,
+ "label": "Time Sheet",
+ "options": "Timesheet",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "billing_hours",
- "fieldtype": "Float",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Billing Hours",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "billing_hours",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Billing Hours",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "billing_amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Billing Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "billing_amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Billing Amount",
+ "options": "currency",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 1,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "timesheet_detail",
- "fieldtype": "Data",
- "hidden": 1,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Timesheet Detail",
- "length": 0,
- "no_copy": 1,
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "allow_on_submit": 1,
+ "fieldname": "timesheet_detail",
+ "fieldtype": "Data",
+ "hidden": 1,
+ "label": "Timesheet Detail",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "activity_type",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Activity Type",
+ "options": "Activity Type",
+ "read_only": 1
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "in_list_view": 1,
+ "label": "Description",
+ "read_only": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2019-02-18 18:50:44.770361",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Sales Invoice Timesheet",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2021-05-20 22:33:57.234846",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Sales Invoice Timesheet",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 82d223cada..f94644ddff 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -778,3 +778,4 @@ erpnext.patches.v12_0.add_ewaybill_validity_field
erpnext.patches.v13_0.germany_make_custom_fields
erpnext.patches.v13_0.germany_fill_debtor_creditor_number
erpnext.patches.v13_0.set_pos_closing_as_failed
+erpnext.patches.v13_0.update_timesheet_changes
diff --git a/erpnext/patches/v13_0/update_timesheet_changes.py b/erpnext/patches/v13_0/update_timesheet_changes.py
new file mode 100644
index 0000000000..93b7f8e59a
--- /dev/null
+++ b/erpnext/patches/v13_0/update_timesheet_changes.py
@@ -0,0 +1,25 @@
+from __future__ import unicode_literals
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+def execute():
+ frappe.reload_doc("projects", "doctype", "timesheet")
+ frappe.reload_doc("projects", "doctype", "timesheet_detail")
+
+ if frappe.db.has_column("Timesheet Detail", "billable"):
+ rename_field("Timesheet Detail", "billable", "is_billable")
+
+ base_currency = frappe.defaults.get_global_default('currency')
+
+ frappe.db.sql("""UPDATE `tabTimesheet Detail`
+ SET base_billing_rate = billing_rate,
+ base_billing_amount = billing_amount,
+ base_costing_rate = costing_rate,
+ base_costing_amount = costing_amount""")
+
+ frappe.db.sql("""UPDATE `tabTimesheet`
+ SET currency = '{0}',
+ exchange_rate = 1.0,
+ base_total_billable_amount = total_billable_amount,
+ base_total_billed_amount = total_billed_amount,
+ base_total_costing_amount = total_costing_amount""".format(base_currency))
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py
index 3af6622d96..8c60b5b71e 100644
--- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py
+++ b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py
@@ -51,7 +51,7 @@ def execute():
def get_timelog_data(data):
return {
- 'billable': data.billable,
+ 'is_billable': data.billable,
'from_time': data.from_time,
'hours': data.hours,
'to_time': data.to_time,
diff --git a/erpnext/projects/doctype/activity_type/activity_type.js b/erpnext/projects/doctype/activity_type/activity_type.js
index 7eb3571af1..f1ba882812 100644
--- a/erpnext/projects/doctype/activity_type/activity_type.js
+++ b/erpnext/projects/doctype/activity_type/activity_type.js
@@ -1,4 +1,8 @@
frappe.ui.form.on("Activity Type", {
+ onload: function(frm) {
+ frm.set_currency_labels(["billing_rate", "costing_rate"], frappe.defaults.get_global_default('currency'));
+ },
+
refresh: function(frm) {
frm.add_custom_button(__("Activity Cost per Employee"), function() {
frappe.route_options = {"activity_type": frm.doc.name};
diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py
index d21ac0f2f0..2b0c3abdd7 100644
--- a/erpnext/projects/doctype/timesheet/test_timesheet.py
+++ b/erpnext/projects/doctype/timesheet/test_timesheet.py
@@ -37,7 +37,7 @@ class TestTimesheet(unittest.TestCase):
emp = make_employee("test_employee_6@salary.com")
make_salary_structure_for_timesheet(emp)
- timesheet = make_timesheet(emp, simulate=True, billable=1)
+ timesheet = make_timesheet(emp, simulate=True, is_billable=1)
self.assertEqual(timesheet.total_hours, 2)
self.assertEqual(timesheet.total_billable_hours, 2)
@@ -49,7 +49,7 @@ class TestTimesheet(unittest.TestCase):
emp = make_employee("test_employee_6@salary.com")
make_salary_structure_for_timesheet(emp)
- timesheet = make_timesheet(emp, simulate=True, billable=0)
+ timesheet = make_timesheet(emp, simulate=True, is_billable=0)
self.assertEqual(timesheet.total_hours, 2)
self.assertEqual(timesheet.total_billable_hours, 0)
@@ -61,7 +61,7 @@ class TestTimesheet(unittest.TestCase):
emp = make_employee("test_employee_6@salary.com", company="_Test Company")
salary_structure = make_salary_structure_for_timesheet(emp)
- timesheet = make_timesheet(emp, simulate = True, billable=1)
+ timesheet = make_timesheet(emp, simulate = True, is_billable=1)
salary_slip = make_salary_slip(timesheet.name)
salary_slip.submit()
@@ -82,7 +82,7 @@ class TestTimesheet(unittest.TestCase):
def test_sales_invoice_from_timesheet(self):
emp = make_employee("test_employee_6@salary.com")
- timesheet = make_timesheet(emp, simulate=True, billable=1)
+ timesheet = make_timesheet(emp, simulate=True, is_billable=1)
sales_invoice = make_sales_invoice(timesheet.name, '_Test Item', '_Test Customer')
sales_invoice.due_date = nowdate()
sales_invoice.submit()
@@ -100,7 +100,7 @@ class TestTimesheet(unittest.TestCase):
emp = make_employee("test_employee_6@salary.com")
project = frappe.get_value("Project", {"project_name": "_Test Project"})
- timesheet = make_timesheet(emp, simulate=True, billable=1, project=project, company='_Test Company')
+ timesheet = make_timesheet(emp, simulate=True, is_billable=1, project=project, company='_Test Company')
sales_invoice = create_sales_invoice(do_not_save=True)
sales_invoice.project = project
sales_invoice.submit()
@@ -171,13 +171,13 @@ def make_salary_structure_for_timesheet(employee, company=None):
return salary_structure
-def make_timesheet(employee, simulate=False, billable = 0, activity_type="_Test Activity Type", project=None, task=None, company=None):
+def make_timesheet(employee, simulate=False, is_billable = 0, activity_type="_Test Activity Type", project=None, task=None, company=None):
update_activity_type(activity_type)
timesheet = frappe.new_doc("Timesheet")
timesheet.employee = employee
timesheet.company = company or '_Test Company'
timesheet_detail = timesheet.append('time_logs', {})
- timesheet_detail.billable = billable
+ timesheet_detail.is_billable = is_billable
timesheet_detail.activity_type = activity_type
timesheet_detail.from_time = now_datetime()
timesheet_detail.hours = 2
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index 43a57e5d4a..84c7b8118b 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -90,17 +90,99 @@ frappe.ui.form.on("Timesheet", {
}
if(frm.doc.per_billed > 0) {
frm.fields_dict["time_logs"].grid.toggle_enable("billing_hours", false);
- frm.fields_dict["time_logs"].grid.toggle_enable("billable", false);
+ frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false);
}
+ frm.trigger('setup_filters');
+ frm.trigger('set_dynamic_field_label');
+ },
+
+ customer: function(frm) {
+ frm.set_query('parent_project', function(doc) {
+ return {
+ filters: {
+ "customer": doc.customer
+ }
+ };
+ });
+ frm.set_query('project', 'time_logs', function(doc) {
+ return {
+ filters: {
+ "customer": doc.customer
+ }
+ };
+ });
+ frm.refresh();
+ },
+
+ currency: function(frm) {
+ let base_currency = frappe.defaults.get_global_default('currency');
+ if (base_currency != frm.doc.currency) {
+ frappe.call({
+ method: "erpnext.setup.utils.get_exchange_rate",
+ args: {
+ from_currency: frm.doc.currency,
+ to_currency: base_currency
+ },
+ callback: function(r) {
+ if (r.message) {
+ frm.set_value('exchange_rate', flt(r.message));
+ frm.set_df_property("exchange_rate", "description", "1 " + frm.doc.currency + " = [?] " + base_currency);
+ }
+ }
+ });
+ }
+ frm.trigger('set_dynamic_field_label');
+ },
+
+ exchange_rate: function(frm) {
+ $.each(frm.doc.time_logs, function(i, d) {
+ calculate_billing_costing_amount(frm, d.doctype, d.name);
+ });
+ calculate_time_and_amount(frm);
+ },
+
+ set_dynamic_field_label: function(frm) {
+ let base_currency = frappe.defaults.get_global_default('currency');
+ frm.set_currency_labels(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"], base_currency);
+ frm.set_currency_labels(["total_costing_amount", "total_billable_amount", "total_billed_amount"], frm.doc.currency);
+
+ frm.toggle_display(["base_total_costing_amount", "base_total_billable_amount", "base_total_billed_amount"],
+ frm.doc.currency != base_currency);
+
+ if (frm.doc.time_logs.length > 0) {
+ frm.set_currency_labels(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], base_currency, "time_logs");
+ frm.set_currency_labels(["billing_rate", "billing_amount", "costing_rate", "costing_amount"], frm.doc.currency, "time_logs");
+
+ let time_logs_grid = frm.fields_dict.time_logs.grid;
+ $.each(["base_billing_rate", "base_billing_amount", "base_costing_rate", "base_costing_amount"], function(i, d) {
+ if (frappe.meta.get_docfield(time_logs_grid.doctype, d))
+ time_logs_grid.set_column_disp(d, frm.doc.currency != base_currency);
+ });
+ }
+ frm.refresh_fields();
},
make_invoice: function(frm) {
+ let fields = [{
+ "fieldtype": "Link",
+ "label": __("Item Code"),
+ "fieldname": "item_code",
+ "options": "Item"
+ }];
+
+ if (!frm.doc.customer) {
+ fields.push({
+ "fieldtype": "Link",
+ "label": __("Customer"),
+ "fieldname": "customer",
+ "options": "Customer",
+ "default": frm.doc.customer
+ });
+ }
+
let dialog = new frappe.ui.Dialog({
- title: __("Select Item (optional)"),
- fields: [
- {"fieldtype": "Link", "label": __("Item Code"), "fieldname": "item_code", "options":"Item"},
- {"fieldtype": "Link", "label": __("Customer"), "fieldname": "customer", "options":"Customer"}
- ]
+ title: __("Create Sales Invoice"),
+ fields: fields
});
dialog.set_primary_action(__('Create Sales Invoice'), () => {
@@ -113,7 +195,8 @@ frappe.ui.form.on("Timesheet", {
args: {
"source_name": frm.doc.name,
"item_code": args.item_code,
- "customer": args.customer
+ "customer": frm.doc.customer || args.customer,
+ "currency": frm.doc.currency
},
freeze: true,
callback: function(r) {
@@ -136,8 +219,7 @@ frappe.ui.form.on("Timesheet", {
parent_project: function(frm) {
set_project_in_timelog(frm);
- },
-
+ }
});
frappe.ui.form.on("Timesheet Detail", {
@@ -171,36 +253,34 @@ frappe.ui.form.on("Timesheet Detail", {
if(frm.doc.parent_project) {
frappe.model.set_value(cdt, cdn, 'project', frm.doc.parent_project);
}
-
- var $trigger_again = $('.form-grid').find('.grid-row').find('.btn-open-row');
- $trigger_again.on('click', () => {
- let $timer = $('.form-grid').find('[data-fieldname="timer"]');
- if ($timer.get(0)) {
- $timer.append(frappe.render_template("timesheet"));
- }
- frm.trigger("control_timer");
- });
},
+
hours: function(frm, cdt, cdn) {
calculate_end_time(frm, cdt, cdn);
+ calculate_billing_costing_amount(frm, cdt, cdn);
+ calculate_time_and_amount(frm);
},
billing_hours: function(frm, cdt, cdn) {
calculate_billing_costing_amount(frm, cdt, cdn);
+ calculate_time_and_amount(frm);
},
billing_rate: function(frm, cdt, cdn) {
calculate_billing_costing_amount(frm, cdt, cdn);
+ calculate_time_and_amount(frm);
},
costing_rate: function(frm, cdt, cdn) {
calculate_billing_costing_amount(frm, cdt, cdn);
+ calculate_time_and_amount(frm);
},
- billable: function(frm, cdt, cdn) {
+ is_billable: function(frm, cdt, cdn) {
update_billing_hours(frm, cdt, cdn);
update_time_rates(frm, cdt, cdn);
calculate_billing_costing_amount(frm, cdt, cdn);
+ calculate_time_and_amount(frm);
},
activity_type: function(frm, cdt, cdn) {
@@ -208,7 +288,8 @@ frappe.ui.form.on("Timesheet Detail", {
method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost",
args: {
employee: frm.doc.employee,
- activity_type: frm.selected_doc.activity_type
+ activity_type: frm.selected_doc.activity_type,
+ currency: frm.doc.currency
},
callback: function(r){
if(r.message){
@@ -240,9 +321,9 @@ var calculate_end_time = function(frm, cdt, cdn) {
}
};
-var update_billing_hours = function(frm, cdt, cdn){
- var child = locals[cdt][cdn];
- if(!child.billable) {
+var update_billing_hours = function(frm, cdt, cdn) {
+ let child = frappe.get_doc(cdt, cdn);
+ if (!child.is_billable) {
frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0);
} else {
// bill all hours by default
@@ -250,40 +331,44 @@ var update_billing_hours = function(frm, cdt, cdn){
}
};
-var update_time_rates = function(frm, cdt, cdn){
- var child = locals[cdt][cdn];
- if(!child.billable){
+var update_time_rates = function(frm, cdt, cdn) {
+ let child = frappe.get_doc(cdt, cdn);
+ if (!child.is_billable) {
frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0);
}
};
-var calculate_billing_costing_amount = function(frm, cdt, cdn){
- var child = locals[cdt][cdn];
- var billing_amount = 0.0;
- var costing_amount = 0.0;
-
- if(child.billing_hours && child.billable){
- billing_amount = (child.billing_hours * child.billing_rate);
+var calculate_billing_costing_amount = function(frm, cdt, cdn) {
+ let row = frappe.get_doc(cdt, cdn);
+ let billing_amount = 0.0;
+ let base_billing_amount = 0.0;
+ let exchange_rate = flt(frm.doc.exchange_rate);
+ frappe.model.set_value(cdt, cdn, 'base_billing_rate', flt(row.billing_rate) * exchange_rate);
+ frappe.model.set_value(cdt, cdn, 'base_costing_rate', flt(row.costing_rate) * exchange_rate);
+ if (row.billing_hours && row.is_billable) {
+ base_billing_amount = flt(row.billing_hours) * flt(row.base_billing_rate);
+ billing_amount = flt(row.billing_hours) * flt(row.billing_rate);
}
- costing_amount = flt(child.costing_rate * child.hours);
+
+ frappe.model.set_value(cdt, cdn, 'base_billing_amount', base_billing_amount);
+ frappe.model.set_value(cdt, cdn, 'base_costing_amount', flt(row.base_costing_rate) * flt(row.hours));
frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount);
- frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount);
- calculate_time_and_amount(frm);
+ frappe.model.set_value(cdt, cdn, 'costing_amount', flt(row.costing_rate) * flt(row.hours));
};
var calculate_time_and_amount = function(frm) {
- var tl = frm.doc.time_logs || [];
- var total_working_hr = 0;
- var total_billing_hr = 0;
- var total_billable_amount = 0;
- var total_costing_amount = 0;
+ let tl = frm.doc.time_logs || [];
+ let total_working_hr = 0;
+ let total_billing_hr = 0;
+ let total_billable_amount = 0;
+ let total_costing_amount = 0;
for(var i=0; i
Date: Sun, 23 May 2021 13:31:54 +0530
Subject: [PATCH 104/262] fix: Rename email.bundle to erpnext_email.bundle
to avoid override of frappe email styles
---
erpnext/hooks.py | 2 +-
.../scss/{email.bundle.scss => erpnext_email.bundle.scss} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename erpnext/public/scss/{email.bundle.scss => erpnext_email.bundle.scss} (100%)
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 3024819d76..a1d37e2812 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -19,7 +19,7 @@ app_include_js = "erpnext.bundle.js"
app_include_css = "erpnext.bundle.css"
web_include_js = "erpnext-web.bundle.js"
web_include_css = "erpnext-web.bundle.css"
-email_css = "email.bundle.css"
+email_css = "email_erpnext.bundle.css"
doctype_js = {
"Address": "public/js/address.js",
diff --git a/erpnext/public/scss/email.bundle.scss b/erpnext/public/scss/erpnext_email.bundle.scss
similarity index 100%
rename from erpnext/public/scss/email.bundle.scss
rename to erpnext/public/scss/erpnext_email.bundle.scss
From 6368c976c7f1825fb2a11b098b0d4fbc6b6a276e Mon Sep 17 00:00:00 2001
From: Saqib
Date: Tue, 18 May 2021 18:39:35 +0530
Subject: [PATCH 105/262] fix: expected amount in pos closing payments table
(#25737)
---
.../pos_closing_entry/pos_closing_entry.js | 39 ++++++++++++-------
1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
index aa0c53e228..8c5a34a0d8 100644
--- a/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
+++ b/erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.js
@@ -101,15 +101,24 @@ frappe.ui.form.on('POS Closing Entry', {
},
before_save: function(frm) {
+ frm.set_value("grand_total", 0);
+ frm.set_value("net_total", 0);
+ frm.set_value("total_quantity", 0);
+ frm.set_value("taxes", []);
+
+ for (let row of frm.doc.payment_reconciliation) {
+ row.expected_amount = 0;
+ }
+
for (let row of frm.doc.pos_transactions) {
frappe.db.get_doc("POS Invoice", row.pos_invoice).then(doc => {
- cur_frm.doc.grand_total -= flt(doc.grand_total);
- cur_frm.doc.net_total -= flt(doc.net_total);
- cur_frm.doc.total_quantity -= flt(doc.total_qty);
- refresh_payments(doc, cur_frm, 1);
- refresh_taxes(doc, cur_frm, 1);
- refresh_fields(cur_frm);
- set_html_data(cur_frm);
+ frm.doc.grand_total += flt(doc.grand_total);
+ frm.doc.net_total += flt(doc.net_total);
+ frm.doc.total_quantity += flt(doc.total_qty);
+ refresh_payments(doc, frm);
+ refresh_taxes(doc, frm);
+ refresh_fields(frm);
+ set_html_data(frm);
});
}
}
@@ -118,7 +127,7 @@ frappe.ui.form.on('POS Closing Entry', {
frappe.ui.form.on('POS Closing Entry Detail', {
closing_amount: (frm, cdt, cdn) => {
const row = locals[cdt][cdn];
- frappe.model.set_value(cdt, cdn, "difference", flt(row.expected_amount - row.closing_amount))
+ frappe.model.set_value(cdt, cdn, "difference", flt(row.expected_amount - row.closing_amount));
}
})
@@ -142,28 +151,28 @@ function add_to_pos_transaction(d, frm) {
})
}
-function refresh_payments(d, frm, remove) {
+function refresh_payments(d, frm) {
d.payments.forEach(p => {
const payment = frm.doc.payment_reconciliation.find(pay => pay.mode_of_payment === p.mode_of_payment);
if (payment) {
- if (!remove) payment.expected_amount += flt(p.amount);
- else payment.expected_amount -= flt(p.amount);
+ payment.expected_amount += flt(p.amount);
+ payment.difference = payment.closing_amount - payment.expected_amount;
} else {
frm.add_child("payment_reconciliation", {
mode_of_payment: p.mode_of_payment,
opening_amount: 0,
- expected_amount: p.amount
+ expected_amount: p.amount,
+ closing_amount: 0
})
}
})
}
-function refresh_taxes(d, frm, remove) {
+function refresh_taxes(d, frm) {
d.taxes.forEach(t => {
const tax = frm.doc.taxes.find(tx => tx.account_head === t.account_head && tx.rate === t.rate);
if (tax) {
- if (!remove) tax.amount += flt(t.tax_amount);
- else tax.amount -= flt(t.tax_amount);
+ tax.amount += flt(t.tax_amount);
} else {
frm.add_child("taxes", {
account_head: t.account_head,
From 10085580c86f9fcfb4cc96e5265665b422baa987 Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 24 May 2021 17:05:27 +0550
Subject: [PATCH 106/262] bumped to version 13.3.1
---
erpnext/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index ad971e2976..8d1767497f 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '13.3.0'
+__version__ = '13.3.1'
def get_default_company(user=None):
'''Get default company for user'''
From 2f8a742aa874d37fd24ca1f21db50492fc3a927f Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Tue, 25 May 2021 10:28:32 +0530
Subject: [PATCH 107/262] refactor: Replace render imports
---
erpnext/patches/v6_5/show_in_website_for_template_item.py | 4 ++--
erpnext/setup/doctype/item_group/item_group.py | 2 +-
erpnext/stock/doctype/item/item.py | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/erpnext/patches/v6_5/show_in_website_for_template_item.py b/erpnext/patches/v6_5/show_in_website_for_template_item.py
index af6e8304d6..3a5cac84d6 100644
--- a/erpnext/patches/v6_5/show_in_website_for_template_item.py
+++ b/erpnext/patches/v6_5/show_in_website_for_template_item.py
@@ -1,6 +1,6 @@
from __future__ import unicode_literals
import frappe
-import frappe.website.render
+from frappe.website.utils import clear_cache
def execute():
for item_code in frappe.db.sql_list("""select distinct variant_of from `tabItem`
@@ -12,4 +12,4 @@ def execute():
item.make_route()
item.db_set("route", item.route, update_modified=False)
- frappe.website.render.clear_cache()
+ clear_cache()
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index bff806d547..a3208c9584 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -8,7 +8,7 @@ from frappe import _
from frappe.utils import nowdate, cint, cstr
from frappe.utils.nestedset import NestedSet
from frappe.website.website_generator import WebsiteGenerator
-from frappe.website.render import clear_cache
+from frappe.website.utils import clear_cache
from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow
from erpnext.shopping_cart.product_info import set_product_info_for_website
from erpnext.utilities.product import get_qty_in_stock
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index dbac79465e..483635cc3b 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -18,7 +18,7 @@ from frappe.utils.html_utils import clean_html
from frappe.website.doctype.website_slideshow.website_slideshow import \
get_slideshow
-from frappe.website.render import clear_cache
+from frappe.website.utils import clear_cache
from frappe.website.website_generator import WebsiteGenerator
from six import iteritems
From d3b9edd2c4468e7319d7b143104332a6ac7a8fbc Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Tue, 25 May 2021 12:52:26 +0530
Subject: [PATCH 108/262] fix: Remove unnecessary import
---
erpnext/templates/pages/partners.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/templates/pages/partners.py b/erpnext/templates/pages/partners.py
index 6725a3e294..a7e60e2616 100644
--- a/erpnext/templates/pages/partners.py
+++ b/erpnext/templates/pages/partners.py
@@ -3,7 +3,6 @@
from __future__ import unicode_literals
import frappe
-import frappe.website.render
page_title = "Partners"
From 45bc14408e5313a339130181f00d55c414b59de4 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Tue, 25 May 2021 15:57:33 +0530
Subject: [PATCH 109/262] refactor: Remove redundant variables.scss import
---
erpnext/public/scss/erpnext.scss | 46 +++++++++----------
erpnext/public/scss/erpnext_email.bundle.scss | 14 +++---
2 files changed, 28 insertions(+), 32 deletions(-)
diff --git a/erpnext/public/scss/erpnext.scss b/erpnext/public/scss/erpnext.scss
index 0e6186138f..8ab5973deb 100644
--- a/erpnext/public/scss/erpnext.scss
+++ b/erpnext/public/scss/erpnext.scss
@@ -1,5 +1,3 @@
-@import "frappe/public/scss/desk/variables";
-
.erpnext-footer {
margin: 11px auto;
text-align: center;
@@ -141,7 +139,7 @@ body[data-route="pos"] {
}
.pos-payment-row {
- border-bottom:1px solid $border-color;
+ border-bottom:1px solid var(--border-color);
margin: 2px 0px 5px 0px;
height: 60px;
margin-top: 0px;
@@ -154,7 +152,7 @@ body[data-route="pos"] {
}
.pos-keyboard-key, .delete-btn {
- border: 1px solid $border-color;
+ border: 1px solid var(--border-color);
height:85px;
width:85px;
margin:10px 10px;
@@ -165,7 +163,7 @@ body[data-route="pos"] {
}
.numeric-keypad {
- border: 1px solid $border-color;
+ border: 1px solid var(--border-color);
height:69px;
width:69px;
font-size:20px;
@@ -192,13 +190,13 @@ body[data-route="pos"] {
background-color: #fff;
margin-left:-4px;
- @media (max-width: map-get($grid-breakpoints, "xl")) {
+ @media (max-width: var(--xl-width)) {
height: 45px;
width: 45px;
font-size: 14px;
}
- @media (max-width: map-get($grid-breakpoints, "lg")) {
+ @media (max-width: var(--lg-width)) {
height: 40px;
width: 40px;
}
@@ -209,16 +207,16 @@ body[data-route="pos"] {
& > .row > button {
border: none;
- border-right: 1px solid $border-color;
- border-bottom: 1px solid $border-color;
+ border-right: 1px solid var(--border-color);
+ border-bottom: 1px solid var(--border-color);
&:first-child {
- border-left: 1px solid $border-color;
+ border-left: 1px solid var(--border-color);
}
}
& > .row:first-child > button {
- border-top: 1px solid $border-color;
+ border-top: 1px solid var(--border-color);
}
}
@@ -236,13 +234,13 @@ body[data-route="pos"] {
}
.list-row-head.pos-invoice-list {
- border-top: 1px solid $border-color;
+ border-top: 1px solid var(--border-color);
}
.modal-dialog {
width: 750px;
- @media (max-width: map-get($grid-breakpoints, 'md')) {
+ @media (max-width: var(--md-width)) {
width: auto;
.modal-content {
@@ -251,7 +249,7 @@ body[data-route="pos"] {
}
}
- @media (max-width: map-get($grid-breakpoints, 'md')) {
+ @media (max-width: var(--md-width)) {
.amount-row h3 {
font-size: 15px;
}
@@ -291,7 +289,7 @@ body[data-route="pos"] {
padding: 9px 15px;
font-size: 12px;
margin: 0px;
- border-bottom: 1px solid $border-color;
+ border-bottom: 1px solid var(--border-color);
.cell {
display: table-cell;
@@ -313,7 +311,7 @@ body[data-route="pos"] {
.pos-bill-header {
background-color: #f5f7fa;
- border: 1px solid $border-color;
+ border: 1px solid var(--border-color);
padding: 13px 15px;
}
@@ -322,8 +320,8 @@ body[data-route="pos"] {
}
.totals-area {
- border-right: 1px solid $border-color;
- border-left: 1px solid $border-color;
+ border-right: 1px solid var(--border-color);
+ border-left: 1px solid var(--border-color);
margin-bottom: 15px;
}
@@ -334,10 +332,10 @@ body[data-route="pos"] {
.item-cart-items {
height: calc(100vh - 526px);
overflow: auto;
- border: 1px solid $border-color;
+ border: 1px solid var(--border-color);
border-top: none;
- @media (max-width: map-get($grid-breakpoints, 'md')) {
+ @media (max-width: var(--md-width)) {
height: 30vh;
}
}
@@ -359,12 +357,12 @@ body[data-route="pos"] {
}
.item-list {
- border: 1px solid $border-color;
+ border: 1px solid var(--border-color);
border-top: none;
max-height: calc(100vh - 190px);
overflow: auto;
- @media (max-width: map-get($grid-breakpoints, 'md')) {
+ @media (max-width: var(--md-width)) {
max-height: initial;
}
@@ -402,7 +400,7 @@ body[data-route="pos"] {
&> .pos-list-row {
border: none;
- @media (max-width: map-get($grid-breakpoints, 'xl')) {
+ @media (max-width: var(--xl-width)) {
padding: 5px 15px;
}
}
@@ -428,7 +426,7 @@ body[data-route="pos"] {
cursor: pointer;
}
- @media (max-width: map-get($grid-breakpoints, 'md')) {
+ @media (max-width: var(--md-width)) {
.page-actions {
max-width: 110px;
}
diff --git a/erpnext/public/scss/erpnext_email.bundle.scss b/erpnext/public/scss/erpnext_email.bundle.scss
index 3c0b918dae..d94e74a3ae 100644
--- a/erpnext/public/scss/erpnext_email.bundle.scss
+++ b/erpnext/public/scss/erpnext_email.bundle.scss
@@ -1,14 +1,12 @@
-@import "frappe/public/scss/desk/variables";
-
.panel-header {
background-color: var(--bg-color);
- border: 1px solid $border-color;
+ border: 1px solid var(--border-color);
border-radius: 3px 3px 0 0;
}
.panel-body {
- background-color: #fff;
- border: 1px solid $border-color;
+ background-color: white;
+ border: 1px solid var(--border-color);
border-top: none;
border-radius: 0 0 3px 3px;
overflow-wrap: break-word;
@@ -26,7 +24,7 @@
line-height: 24px;
text-align: center;
- color: $border-color;
- border: 1px solid $border-color;
- background-color: #fff;
+ color: var(--border-color);
+ border: 1px solid var(--border-color);
+ background-color: white;
}
From c9aa7268187748c0cbb5189768d463b71b9880f5 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 16 Sep 2020 20:30:24 +0530
Subject: [PATCH 110/262] feat: Tax deduction against advance payments
---
.../advance_taxes_and_charges/__init__.py | 0
.../advance_taxes_and_charges.json | 201 ++++++++++++++++++
.../advance_taxes_and_charges.py | 10 +
3 files changed, 211 insertions(+)
create mode 100644 erpnext/accounts/doctype/advance_taxes_and_charges/__init__.py
create mode 100644 erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
create mode 100644 erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/__init__.py b/erpnext/accounts/doctype/advance_taxes_and_charges/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
new file mode 100644
index 0000000000..79eda8c5fe
--- /dev/null
+++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
@@ -0,0 +1,201 @@
+{
+ "actions": [],
+ "creation": "2020-09-12 22:26:19.594367",
+ "doctype": "DocType",
+ "document_type": "Setup",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "add_deduct_tax",
+ "charge_type",
+ "row_id",
+ "account_head",
+ "col_break_1",
+ "description",
+ "accounting_dimensions_section",
+ "cost_center",
+ "dimension_col_break",
+ "section_break_8",
+ "rate",
+ "section_break_9",
+ "tax_amount",
+ "total",
+ "column_break_13",
+ "base_tax_amount",
+ "base_total"
+ ],
+ "fields": [
+ {
+ "columns": 2,
+ "fieldname": "charge_type",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Type",
+ "oldfieldname": "charge_type",
+ "oldfieldtype": "Select",
+ "options": "\nActual\nOn Paid Amount\nOn Previous Row Amount\nOn Previous Row Total",
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
+ "fieldname": "row_id",
+ "fieldtype": "Data",
+ "label": "Reference Row #",
+ "oldfieldname": "row_id",
+ "oldfieldtype": "Data",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "columns": 2,
+ "fieldname": "account_head",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Account Head",
+ "oldfieldname": "account_head",
+ "oldfieldtype": "Link",
+ "options": "Account",
+ "reqd": 1,
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "col_break_1",
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1,
+ "width": "50%"
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description",
+ "oldfieldname": "description",
+ "oldfieldtype": "Small Text",
+ "print_width": "300px",
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1,
+ "width": "300px"
+ },
+ {
+ "fieldname": "accounting_dimensions_section",
+ "fieldtype": "Section Break",
+ "label": "Accounting Dimensions",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "default": ":Company",
+ "fieldname": "cost_center",
+ "fieldtype": "Link",
+ "label": "Cost Center",
+ "oldfieldname": "cost_center_other_charges",
+ "oldfieldtype": "Link",
+ "options": "Cost Center",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "dimension_col_break",
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "section_break_8",
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "columns": 2,
+ "fieldname": "rate",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Rate",
+ "oldfieldname": "rate",
+ "oldfieldtype": "Currency",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "section_break_9",
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "columns": 2,
+ "fieldname": "tax_amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Amount",
+ "options": "currency",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "columns": 2,
+ "fieldname": "total",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Total",
+ "options": "currency",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "column_break_13",
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "base_tax_amount",
+ "fieldtype": "Currency",
+ "label": "Amount (Company Currency)",
+ "oldfieldname": "tax_amount",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "base_total",
+ "fieldtype": "Currency",
+ "label": "Total (Company Currency)",
+ "oldfieldname": "total",
+ "oldfieldtype": "Currency",
+ "options": "Company:company:default_currency",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "add_deduct_tax",
+ "fieldtype": "Select",
+ "label": "Add Or Deduct",
+ "options": "Add\nDeduct",
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ }
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-09-12 22:30:36.150935",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Advance Taxes and Charges",
+ "owner": "Administrator",
+ "permissions": [],
+ "sort_field": "modified",
+ "sort_order": "ASC"
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py
new file mode 100644
index 0000000000..597d2ccc62
--- /dev/null
+++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+# import frappe
+from frappe.model.document import Document
+
+class AdvanceTaxesandCharges(Document):
+ pass
From 61c5e478afada33b5d8ffe43fc174d345f581e03 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 1 Oct 2020 13:56:55 +0530
Subject: [PATCH 111/262] feat: Tax deduction against advance payments
---
.../doctype/payment_entry/payment_entry.js | 137 ++++++-
.../doctype/payment_entry/payment_entry.json | 358 ++++++++++++++----
.../doctype/payment_entry/payment_entry.py | 114 +++++-
.../payment_entry_deduction.json | 196 +++-------
erpnext/controllers/accounts_controller.py | 10 +
erpnext/public/js/controllers/accounts.js | 2 +-
6 files changed, 607 insertions(+), 210 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index b80e8ada38..29e4a31dad 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -3,6 +3,8 @@
{% include "erpnext/public/js/controllers/accounts.js" %}
frappe.provide("erpnext.accounts.dimensions");
+cur_frm.cscript.tax_table = "Advance Taxes and Charges";
+
frappe.ui.form.on('Payment Entry', {
onload: function(frm) {
if(frm.doc.__islocal) {
@@ -182,6 +184,8 @@ frappe.ui.form.on('Payment Entry', {
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency));
frm.toggle_display("base_paid_amount", frm.doc.paid_from_account_currency != company_currency);
+ frm.toggle_display("base_total_taxes_and_charges", frm.doc.total_taxes_and_charges &&
+ (frm.doc.paid_from_account_currency != company_currency));
frm.toggle_display("base_received_amount", (
frm.doc.paid_to_account_currency != company_currency
@@ -843,12 +847,12 @@ frappe.ui.form.on('Payment Entry', {
if(frm.doc.payment_type == "Receive"
&& frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions
&& frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) {
- unallocated_amount = (frm.doc.base_received_amount + total_deductions
- - frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
+ unallocated_amount = (frm.doc.base_received_amount + total_deductions + frm.doc.base_total_taxes_and_charges
+ + frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate;
} else if (frm.doc.payment_type == "Pay"
&& frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions
&& frm.doc.total_allocated_amount < frm.doc.received_amount + (total_deductions / frm.doc.target_exchange_rate)) {
- unallocated_amount = (frm.doc.base_paid_amount - (total_deductions
+ unallocated_amount = (frm.doc.base_paid_amount + frm.doc.base_total_taxes_and_charges - (total_deductions
+ frm.doc.base_total_allocated_amount)) / frm.doc.target_exchange_rate;
}
}
@@ -874,7 +878,8 @@ frappe.ui.form.on('Payment Entry', {
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
function(d) { return flt(d.amount) }));
- frm.set_value("difference_amount", difference_amount - total_deductions);
+ frm.set_value("difference_amount", difference_amount - total_deductions +
+ frm.doc.base_total_taxes_and_charges);
frm.events.hide_unhide_fields(frm);
},
@@ -1002,7 +1007,107 @@ frappe.ui.form.on('Payment Entry', {
}
});
}
- }
+ },
+
+ sales_taxes_and_charges_template: function(frm) {
+ frm.trigger('fetch_taxes_from_template');
+ },
+
+ purchase_taxes_and_charges_template: function(frm) {
+ frm.trigger('fetch_taxes_from_template');
+ },
+
+ fetch_taxes_from_template: function(frm) {
+ let master_doctype = '';
+ let taxes_and_charges = '';
+
+ if (frm.doc.party_type == 'Supplier') {
+ master_doctype = 'Purchase Taxes and Charges Template';
+ taxes_and_charges = frm.doc.purchase_taxes_and_charges_template;
+ } else if (frm.doc.party_type == 'Customer') {
+ master_doctype = 'Sales Taxes and Charges Template';
+ taxes_and_charges = frm.doc.sales_taxes_and_charges_template;
+ }
+
+ if (!taxes_and_charges) {
+ return;
+ }
+
+ frappe.call({
+ method: "erpnext.controllers.accounts_controller.get_taxes_and_charges",
+ args: {
+ "master_doctype": master_doctype,
+ "master_name": taxes_and_charges
+ },
+ callback: function(r) {
+ if(!r.exc && r.message) {
+ // set taxes table
+ if(r.message) {
+ for (let tax of r.message) {
+ if (tax.charge_type === 'On Net Total') {
+ tax.charge_type = 'On Paid Amount';
+ }
+ me.frm.add_child("taxes", tax);
+ }
+ frm.trigger('calculate_taxes');
+ frm.events.set_unallocated_amount(frm);
+ }
+ }
+ }
+ });
+ },
+
+ calculate_taxes: function(frm) {
+ frm.doc.total_taxes_and_charges = 0.0;
+ frm.doc.base_total_taxes_and_charges = 0.0;
+
+ $.each(me.frm.doc["taxes"] || [], function(i, tax) {
+ let tax_rate = tax.rate;
+ let current_tax_amount = 0.0;
+
+ // To set row_id by default as previous row.
+ if(["On Previous Row Amount", "On Previous Row Total"].includes(tax.charge_type)) {
+ if (tax.idx === 1) {
+ frappe.throw(__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"));
+ }
+ if (!tax.row_id) {
+ tax.row_id = tax.idx - 1;
+ }
+ }
+
+ if(tax.charge_type == "Actual") {
+ current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
+ } else if(tax.charge_type == "On Paid Amount") {
+ current_tax_amount = (tax_rate / 100.0) * frm.doc.paid_amount;
+ } else if(tax.charge_type == "On Previous Row Amount") {
+ current_tax_amount = (tax_rate / 100.0) *
+ frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount;
+
+ } else if(tax.charge_type == "On Previous Row Total") {
+ current_tax_amount = (tax_rate / 100.0) *
+ frm.doc["taxes"][cint(tax.row_id) - 1].total;
+ }
+
+ tax.tax_amount = current_tax_amount;
+ tax.base_tax_amount = tax.tax_amount * frm.doc.source_exchange_rate;
+
+ current_tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
+
+ if(i==0) {
+ tax.total = flt(frm.doc.paid_amount + current_tax_amount, precision("total", tax));
+ } else {
+ tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax));
+ }
+
+ tax.base_total = tax.total * frm.doc.source_exchange_rate;
+ frm.doc.total_taxes_and_charges += current_tax_amount;
+ frm.doc.base_total_taxes_and_charges += current_tax_amount * frm.doc.source_exchange_rate;
+
+ frm.refresh_field('taxes');
+ frm.refresh_field('total_taxes_and_charges');
+ frm.refresh_field('base_total_taxes_and_charges');
+ });
+ },
});
@@ -1049,6 +1154,28 @@ frappe.ui.form.on('Payment Entry Reference', {
}
})
+frappe.ui.form.on('Advance Taxes and Charges', {
+ rate: function(frm) {
+ frm.events.calculate_taxes(frm);
+ frm.events.set_unallocated_amount(frm);
+ },
+
+ tax_amount : function(frm) {
+ frm.events.calculate_taxes(frm);
+ frm.events.set_unallocated_amount(frm);
+ },
+
+ row_id: function(frm) {
+ frm.events.calculate_taxes(frm);
+ frm.events.set_unallocated_amount(frm);
+ },
+
+ taxes_remove: function(frm) {
+ frm.events.calculate_taxes(frm);
+ frm.events.set_unallocated_amount(frm);
+ }
+})
+
frappe.ui.form.on('Payment Entry Deduction', {
amount: function(frm) {
frm.events.set_unallocated_amount(frm);
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 328584a61a..11ae17093f 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -24,6 +24,10 @@
"party_bank_account",
"contact_person",
"contact_email",
+ "tds_details_section",
+ "tax_withholding_category",
+ "column_break_20",
+ "apply_tax_withholding_amount",
"payment_accounts_section",
"party_balance",
"paid_from",
@@ -52,6 +56,12 @@
"unallocated_amount",
"difference_amount",
"write_off_difference_amount",
+ "taxes_and_charges_section",
+ "purchase_taxes_and_charges_template",
+ "sales_taxes_and_charges_template",
+ "taxes",
+ "base_total_taxes_and_charges",
+ "total_taxes_and_charges",
"deductions_or_loss_section",
"deductions",
"transaction_references",
@@ -82,7 +92,9 @@
{
"fieldname": "type_of_payment",
"fieldtype": "Section Break",
- "label": "Type of Payment"
+ "label": "Type of Payment",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -92,7 +104,9 @@
"options": "ACC-PAY-.YYYY.-",
"print_hide": 1,
"reqd": 1,
- "set_only_once": 1
+ "set_only_once": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -103,11 +117,15 @@
"label": "Payment Type",
"options": "Receive\nPay\nInternal Transfer",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_5",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -116,7 +134,9 @@
"fieldtype": "Date",
"in_list_view": 1,
"label": "Posting Date",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "company",
@@ -125,26 +145,34 @@
"options": "Company",
"print_hide": 1,
"remember_last_selected_value": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
- "options": "Cost Center"
+ "options": "Cost Center",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Mode of Payment",
- "options": "Mode of Payment"
+ "options": "Mode of Payment",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type)",
"fieldname": "party_section",
"fieldtype": "Section Break",
- "label": "Payment From / To"
+ "label": "Payment From / To",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.docstatus==0",
@@ -154,7 +182,9 @@
"label": "Party Type",
"options": "DocType",
"print_hide": 1,
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -163,7 +193,9 @@
"fieldtype": "Dynamic Link",
"in_standard_filter": 1,
"label": "Party",
- "options": "party_type"
+ "options": "party_type",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -171,18 +203,24 @@
"fieldname": "party_name",
"fieldtype": "Data",
"in_global_search": 1,
- "label": "Party Name"
+ "label": "Party Name",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_11",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "party",
"fieldname": "contact_person",
"fieldtype": "Link",
"label": "Contact",
- "options": "Contact"
+ "options": "Contact",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "contact_person",
@@ -190,13 +228,17 @@
"fieldtype": "Data",
"label": "Email",
"options": "Email",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "payment_accounts_section",
"fieldtype": "Section Break",
- "label": "Accounts"
+ "label": "Accounts",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "party",
@@ -204,7 +246,9 @@
"fieldtype": "Currency",
"label": "Party Balance",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -215,7 +259,9 @@
"label": "Account Paid From",
"options": "Account",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "paid_from",
@@ -225,7 +271,9 @@
"options": "Currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "paid_from",
@@ -234,11 +282,15 @@
"label": "Account Balance",
"options": "paid_from_account_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_18",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:(in_list([\"Internal Transfer\", \"Receive\"], doc.payment_type) || doc.party)",
@@ -248,7 +300,9 @@
"label": "Account Paid To",
"options": "Account",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "paid_to",
@@ -258,7 +312,9 @@
"options": "Currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "paid_to",
@@ -267,13 +323,17 @@
"label": "Account Balance",
"options": "paid_to_account_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:(doc.paid_to && doc.paid_from)",
"fieldname": "payment_amounts_section",
"fieldtype": "Section Break",
- "label": "Amount"
+ "label": "Amount",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -281,14 +341,18 @@
"fieldtype": "Currency",
"label": "Paid Amount",
"options": "paid_from_account_currency",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "source_exchange_rate",
"fieldtype": "Float",
"label": "Exchange Rate",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_paid_amount",
@@ -297,11 +361,15 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_21",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -310,14 +378,18 @@
"label": "Received Amount",
"options": "paid_to_account_currency",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "target_exchange_rate",
"fieldtype": "Float",
"label": "Exchange Rate",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_received_amount",
@@ -326,30 +398,40 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:(doc.party && doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)",
"fieldname": "section_break_14",
"fieldtype": "Section Break",
- "label": "Reference"
+ "label": "Reference",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.docstatus==0",
"fieldname": "get_outstanding_invoice",
"fieldtype": "Button",
- "label": "Get Outstanding Invoice"
+ "label": "Get Outstanding Invoice",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "references",
"fieldtype": "Table",
"label": "Payment References",
- "options": "Payment Entry Reference"
+ "options": "Payment Entry Reference",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "section_break_34",
"fieldtype": "Section Break",
- "label": "Writeoff"
+ "label": "Writeoff",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -358,7 +440,9 @@
"fieldtype": "Currency",
"label": "Total Allocated Amount",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_total_allocated_amount",
@@ -366,23 +450,31 @@
"label": "Total Allocated Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "set_exchange_gain_loss",
"fieldtype": "Button",
- "label": "Set Exchange Gain / Loss"
+ "label": "Set Exchange Gain / Loss",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_36",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)",
"fieldname": "unallocated_amount",
"fieldtype": "Currency",
"label": "Unallocated Amount",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -392,13 +484,17 @@
"label": "Difference Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "difference_amount",
"fieldname": "write_off_difference_amount",
"fieldtype": "Button",
- "label": "Write Off Difference Amount"
+ "label": "Write Off Difference Amount",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -406,29 +502,39 @@
"depends_on": "eval:(doc.paid_amount && doc.received_amount)",
"fieldname": "deductions_or_loss_section",
"fieldtype": "Section Break",
- "label": "Deductions or Loss"
+ "label": "Deductions or Loss",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "deductions",
"fieldtype": "Table",
"label": "Payment Deductions or Loss",
- "options": "Payment Entry Deduction"
+ "options": "Payment Entry Deduction",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "transaction_references",
"fieldtype": "Section Break",
- "label": "Transaction ID"
+ "label": "Transaction ID",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
"depends_on": "eval:(doc.paid_from && doc.paid_to)",
"fieldname": "reference_no",
"fieldtype": "Data",
- "label": "Cheque/Reference No"
+ "label": "Cheque/Reference No",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_23",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -436,7 +542,9 @@
"fieldname": "reference_date",
"fieldtype": "Date",
"label": "Cheque/Reference Date",
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.docstatus==1",
@@ -445,21 +553,27 @@
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"depends_on": "eval:(doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)",
"fieldname": "section_break_12",
"fieldtype": "Section Break",
- "label": "More Information"
+ "label": "More Information",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "remarks",
@@ -470,33 +584,43 @@
},
{
"fieldname": "column_break_16",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "letter_head",
"fieldtype": "Link",
"label": "Letter Head",
"options": "Letter Head",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "print_heading",
"fieldtype": "Link",
"label": "Print Heading",
"options": "Print Heading",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fetch_from": "bank_account.bank",
"fieldname": "bank",
"fieldtype": "Read Only",
- "label": "Bank"
+ "label": "Bank",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fetch_from": "bank_account.bank_account_no",
"fieldname": "bank_account_no",
"fieldtype": "Read Only",
- "label": "Bank Account No"
+ "label": "Bank Account No",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "payment_order",
@@ -505,12 +629,16 @@
"no_copy": 1,
"options": "Payment Order",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "subscription_section",
"fieldtype": "Section Break",
- "label": "Subscription Section"
+ "label": "Subscription Section",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -520,7 +648,9 @@
"no_copy": 1,
"options": "Auto Repeat",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "amended_from",
@@ -529,7 +659,9 @@
"no_copy": 1,
"options": "Payment Entry",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "title",
@@ -544,14 +676,18 @@
"fieldname": "bank_account",
"fieldtype": "Link",
"label": "Company Bank Account",
- "options": "Bank Account"
+ "options": "Bank Account",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "party",
"fieldname": "party_bank_account",
"fieldtype": "Link",
"label": "Party Bank Account",
- "options": "Bank Account"
+ "options": "Bank Account",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "payment_order_status",
@@ -559,17 +695,23 @@
"hidden": 1,
"label": "Payment Order Status",
"options": "Initiated\nPayment Ordered",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions"
+ "label": "Accounting Dimensions",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "Draft",
@@ -584,12 +726,94 @@
"fieldname": "custom_remarks",
"fieldtype": "Check",
"label": "Custom Remarks"
+ },
+ {
+ "depends_on": "eval: doc.payment_type == 'Pay' && doc.party_type == 'Supplier'",
+ "fieldname": "tds_details_section",
+ "fieldtype": "Section Break",
+ "label": "TDS Details",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "tax_withholding_category",
+ "fieldtype": "Link",
+ "label": "Tax Withholding Category",
+ "options": "Tax Withholding Category",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "apply_tax_withholding_amount",
+ "fieldtype": "Check",
+ "label": "Apply Tax Withholding Amount",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "column_break_20",
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "collapsible": 1,
+ "fieldname": "taxes_and_charges_section",
+ "fieldtype": "Section Break",
+ "label": "Taxes and Charges",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "depends_on": "eval:doc.party_type == 'Supplier'",
+ "fieldname": "purchase_taxes_and_charges_template",
+ "fieldtype": "Link",
+ "label": "Taxes and Charges Template",
+ "options": "Purchase Taxes and Charges Template",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "depends_on": "eval: doc.party_type == 'Customer'",
+ "fieldname": "sales_taxes_and_charges_template",
+ "fieldtype": "Link",
+ "label": "Taxes and Charges Template",
+ "options": "Sales Taxes and Charges Template",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "depends_on": "eval: doc.party_type == 'Supplier' || doc.party_type == 'Customer'",
+ "fieldname": "taxes",
+ "fieldtype": "Table",
+ "label": "Advance Taxes and Charges",
+ "options": "Advance Taxes and Charges",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "base_total_taxes_and_charges",
+ "fieldtype": "Currency",
+ "label": "Total Taxes and Charges (Company Currency)",
+ "options": "Company:company:default_currency",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "total_taxes_and_charges",
+ "fieldtype": "Currency",
+ "label": "Total Taxes and Charges",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-03-08 13:05:16.958866",
+ "modified": "2020-09-13 22:33:59.860146",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 62ab76c323..a41b4512a1 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe, erpnext, json
from frappe import _, scrub, ValidationError
-from frappe.utils import flt, comma_or, nowdate, getdate
+from frappe.utils import flt, comma_or, nowdate, getdate, cint
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
from erpnext.accounts.party import get_party_account
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
@@ -15,6 +15,7 @@ from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amo
from erpnext.accounts.doctype.bank_account.bank_account import get_party_bank_account, get_bank_account_details
from erpnext.controllers.accounts_controller import AccountsController, get_supplier_block_status
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
+from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
from six import string_types, iteritems
@@ -52,6 +53,8 @@ class PaymentEntry(AccountsController):
self.set_exchange_rate()
self.validate_mandatory()
self.validate_reference_documents()
+ self.set_tax_withholding()
+ self.calculate_taxes()
self.set_amounts()
self.clear_unallocated_reference_document_rows()
self.validate_payment_against_negative_invoice()
@@ -386,6 +389,43 @@ class PaymentEntry(AccountsController):
else:
self.status = 'Draft'
+ def set_tax_withholding(self):
+ if not self.party_type == 'Supplier':
+ return
+
+ if not self.apply_tax_withholding_amount:
+ return
+
+ if self.references:
+ return
+
+ args = frappe._dict({
+ 'company': self.company,
+ 'supplier': self.party,
+ 'posting_date': self.posting_date,
+ 'net_total': self.paid_amount
+ })
+
+ tax_withholding_details = get_party_tax_withholding_details(args, self.tax_withholding_category)
+
+ if not tax_withholding_details:
+ return
+
+ accounts = []
+ for d in self.taxes:
+ if d.account_head == tax_withholding_details.get("account_head"):
+ d.update(tax_withholding_details)
+ accounts.append(d.account_head)
+
+ if not accounts or tax_withholding_details.get("account_head") not in accounts:
+ self.append("taxes", tax_withholding_details)
+
+ to_remove = [d for d in self.taxes
+ if not d.tax_amount and d.account_head == tax_withholding_details.get("account_head")]
+
+ for d in to_remove:
+ self.remove(d)
+
def set_amounts(self):
self.set_amounts_in_company_currency()
self.set_total_allocated_amount()
@@ -423,12 +463,12 @@ class PaymentEntry(AccountsController):
if self.payment_type == "Receive" \
and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
- self.unallocated_amount = (self.base_received_amount + total_deductions -
+ self.unallocated_amount = (self.base_received_amount + self.base_total_taxes_and_charges + total_deductions -
self.base_total_allocated_amount) / self.source_exchange_rate
elif self.payment_type == "Pay" \
and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
- self.unallocated_amount = (self.base_paid_amount - (total_deductions +
+ self.unallocated_amount = (self.base_paid_amount + self.base_total_taxes_and_charges - (total_deductions +
self.base_total_allocated_amount)) / self.target_exchange_rate
def set_difference_amount(self):
@@ -446,7 +486,7 @@ class PaymentEntry(AccountsController):
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
- self.difference_amount = flt(self.difference_amount - total_deductions,
+ self.difference_amount = flt(self.difference_amount - total_deductions + self.base_total_taxes_and_charges,
self.precision("difference_amount"))
# Paid amount is auto allocated in the reference document by default.
@@ -532,6 +572,7 @@ class PaymentEntry(AccountsController):
self.add_party_gl_entries(gl_entries)
self.add_bank_gl_entries(gl_entries)
self.add_deductions_gl_entries(gl_entries)
+ self.add_tax_gl_entries(gl_entries)
make_gl_entries(gl_entries, cancel=cancel, adv_adj=adv_adj)
@@ -607,6 +648,26 @@ class PaymentEntry(AccountsController):
}, item=self)
)
+ def add_tax_gl_entries(self, gl_entries):
+ for d in self.get('taxes'):
+ account_currency = get_account_currency(d.account_head)
+ if account_currency != self.company_currency:
+ frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency))
+
+ dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": d.account_head,
+ "against": self.party if self.payment_type=="Receive" else self.paid_from,
+ dr_or_cr: d.base_tax_amount,
+ dr_or_cr + "_in_account_currency": d.base_tax_amount \
+ if account_currency==self.company_currency \
+ else d.tax_amount,
+ "cost_center": d.cost_center
+ }, account_currency, item=d)
+ )
+
def add_deductions_gl_entries(self, gl_entries):
for d in self.get("deductions"):
if d.amount:
@@ -671,6 +732,51 @@ class PaymentEntry(AccountsController):
self.append('deductions', row)
self.set_unallocated_amount()
+ def calculate_taxes(self):
+ self.total_taxes_and_charges = 0.0
+ self.base_total_taxes_and_charges = 0.0
+
+ for i, tax in enumerate(self.taxes):
+ tax_rate = tax.rate
+ current_tax_rate = 0.0
+
+ # To set row_id by default as previous row.
+ if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"]:
+ if tax.idx == 1:
+ frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"))
+
+ if not tax.row_id:
+ tax.row_id = tax.idx - 1
+
+ if tax.charge_type == "Actual":
+ current_tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
+ elif tax.charge_type == "On Paid Amount":
+ current_tax_amount = (tax_rate / 100.0) * self.paid_amount
+ elif tax.charge_type == "On Previous Row Amount":
+ current_tax_amount = (tax_rate / 100.0) * \
+ self.taxes[cint(tax.row_id) - 1].tax_amount
+
+ elif tax.charge_type == "On Previous Row Total":
+ current_tax_amount = (tax_rate / 100.0) * \
+ self.taxes[cint(tax.row_id) - 1].total
+
+ tax.tax_amount = current_tax_amount
+ tax.base_tax_amount = tax.tax_amount * self.source_exchange_rate
+
+ if tax.add_deduct_tax == "Deduct":
+ current_tax_amount *= -1.0
+ else:
+ current_tax_amount *= 1.0
+
+ if i == 0:
+ tax.total = flt(self.paid_amount + current_tax_amount, self.precision("total", tax))
+ else:
+ tax.total = flt(self.taxes[i-1].total + current_tax_amount, self.precision("total", tax))
+
+ tax.base_total = tax.total * self.source_exchange_rate
+ self.total_taxes_and_charges += current_tax_amount
+ self.base_total_taxes_and_charges += current_tax_amount * self.source_exchange_rate
+
@frappe.whitelist()
def get_outstanding_reference_documents(args):
diff --git a/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json b/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json
index 7060d11691..61a1462dd7 100644
--- a/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json
+++ b/erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json
@@ -1,140 +1,70 @@
{
- "allow_copy": 0,
- "allow_events_in_timeline": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "beta": 0,
- "creation": "2016-06-15 15:56:30.815503",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "document_type": "",
- "editable_grid": 1,
+ "actions": [],
+ "creation": "2016-06-15 15:56:30.815503",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "field_order": [
+ "account",
+ "cost_center",
+ "amount",
+ "column_break_2",
+ "description"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "account",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Account",
- "length": 0,
- "no_copy": 0,
- "options": "Account",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "account",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Account",
+ "options": "Account",
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "cost_center",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Cost Center",
- "length": 0,
- "no_copy": 0,
- "options": "Cost Center",
- "permlevel": 0,
- "precision": "",
- "print_hide": 1,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "cost_center",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "Cost Center",
+ "options": "Cost Center",
+ "print_hide": 1,
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amount",
- "fieldtype": "Currency",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 0,
- "label": "Amount",
- "length": 0,
- "no_copy": 0,
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "amount",
+ "fieldtype": "Currency",
+ "in_list_view": 1,
+ "label": "Amount",
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "column_break_2",
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "description",
+ "fieldtype": "Small Text",
+ "label": "Description",
+ "show_days": 1,
+ "show_seconds": 1
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "idx": 0,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 0,
- "issingle": 0,
- "istable": 1,
- "max_attachments": 0,
- "modified": "2019-01-07 16:52:07.040146",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Payment Entry Deduction",
- "name_case": "",
- "owner": "Administrator",
- "permissions": [],
- "quick_entry": 1,
- "read_only": 0,
- "read_only_onload": 0,
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "index_web_pages_for_search": 1,
+ "istable": 1,
+ "links": [],
+ "modified": "2020-09-12 20:38:08.110674",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Payment Entry Deduction",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC"
}
\ No newline at end of file
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 544e624725..65e5823b91 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -617,6 +617,10 @@ class AccountsController(TransactionBase):
payment_entries = get_advance_payment_entries(party_type, party, party_account,
order_doctype, order_list, include_unallocated)
+ payment_entry_list = [d.reference_name for d in payment_entries]
+
+ payment_entry_taxes = get_payment_entry_taxes(payment_entry_list)
+
res = journal_entries + payment_entries
return res
@@ -1241,6 +1245,12 @@ def get_advance_payment_entries(party_type, party, party_account, order_doctype,
return list(payment_entries_against_order) + list(unallocated_payment_entries)
+def get_payment_entry_taxes(payment_entry_list):
+ taxes = frappe.db.sql("""
+ SELECT t.parent, t.add_deduct_tax, t.charge_type, t.account_head, t.cost_center,
+ t.tax_amount FROM `tabAdvance Taxes and Charges` where t.parent in %s"""
+ ,(payment_entry_list, ), as_dict=1)
+
def update_invoice_status():
# Daily update the status of the invoices
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index ceeecb28a2..23d636061c 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -165,7 +165,7 @@ cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) {
msg = __("Please select Charge Type first");
d.row_id = "";
d.rate = d.tax_amount = 0.0;
- } else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total') && d.row_id) {
+ } else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total' || d.charge_type == 'On Paid Amount') && d.row_id) {
msg = __("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'");
d.row_id = "";
} else if((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) {
From c26de286138426f74f4752c6139ce243c5bf854e Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 2 Nov 2020 19:57:27 +0530
Subject: [PATCH 112/262] fix: TDS against Purhase Orders
---
.../advance_taxes_and_charges.json | 4 +-
.../doctype/payment_entry/payment_entry.js | 12 +-
.../doctype/payment_entry/payment_entry.json | 31 +-
.../doctype/payment_entry/payment_entry.py | 25 +-
.../purchase_invoice/purchase_invoice.json | 597 +++++++++++++-----
.../purchase_invoice/purchase_invoice.py | 5 +-
.../purchase_taxes_and_charges.json | 101 ++-
erpnext/controllers/accounts_controller.py | 11 -
erpnext/controllers/taxes_and_totals.py | 40 ++
erpnext/public/js/payment/payments.js | 18 +-
10 files changed, 635 insertions(+), 209 deletions(-)
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
index 79eda8c5fe..5b3299e656 100644
--- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
@@ -33,7 +33,7 @@
"label": "Type",
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
- "options": "\nActual\nOn Paid Amount\nOn Previous Row Amount\nOn Previous Row Total",
+ "options": "\nActual\nOn Paid Amount\nIncluded In Paid Amount\nOn Previous Row Amount\nOn Previous Row Total",
"reqd": 1,
"show_days": 1,
"show_seconds": 1
@@ -190,7 +190,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2020-09-12 22:30:36.150935",
+ "modified": "2020-10-27 20:02:34.734260",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 29e4a31dad..3e11bc0e59 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -220,7 +220,7 @@ frappe.ui.form.on('Payment Entry', {
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
frm.set_currency_labels(["base_paid_amount", "base_received_amount", "base_total_allocated_amount",
- "difference_amount"], company_currency);
+ "difference_amount", "base_paid_amount_after_tax"], company_currency);
frm.set_currency_labels(["paid_amount"], frm.doc.paid_from_account_currency);
frm.set_currency_labels(["received_amount"], frm.doc.paid_to_account_currency);
@@ -368,6 +368,16 @@ frappe.ui.form.on('Payment Entry', {
}
},
+ apply_tax_withholding_amount: function(frm) {
+ if (!frm.doc.apply_tax_withholding_amount) {
+ frm.set_value("tax_withholding_category", '');
+ } else {
+ frappe.db.get_value('Supplier', frm.doc.party, 'tax_withholding_category', (values) => {
+ frm.set_value("tax_withholding_category", values.tax_withholding_category);
+ });
+ }
+ },
+
paid_from: function(frm) {
if(frm.set_party_account_based_on_party) return;
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 11ae17093f..f158345af6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -25,9 +25,9 @@
"contact_person",
"contact_email",
"tds_details_section",
- "tax_withholding_category",
- "column_break_20",
"apply_tax_withholding_amount",
+ "column_break_20",
+ "tax_withholding_category",
"payment_accounts_section",
"party_balance",
"paid_from",
@@ -39,8 +39,10 @@
"paid_to_account_balance",
"payment_amounts_section",
"paid_amount",
+ "paid_amount_after_tax",
"source_exchange_rate",
"base_paid_amount",
+ "base_paid_amount_after_tax",
"column_break_21",
"received_amount",
"target_exchange_rate",
@@ -580,7 +582,9 @@
"fieldtype": "Small Text",
"label": "Remarks",
"no_copy": 1,
- "read_only_depends_on": "eval:doc.custom_remarks == 0"
+ "read_only_depends_on": "eval:doc.custom_remarks == 0",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_16",
@@ -736,6 +740,7 @@
"show_seconds": 1
},
{
+ "depends_on": "eval:doc.apply_tax_withholding_amount",
"fieldname": "tax_withholding_category",
"fieldtype": "Link",
"label": "Tax Withholding Category",
@@ -808,12 +813,30 @@
"read_only": 1,
"show_days": 1,
"show_seconds": 1
+ },
+ {
+ "fieldname": "paid_amount_after_tax",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "label": "Paid Amount After Tax",
+ "options": "paid_from_account_currency",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "base_paid_amount_after_tax",
+ "fieldtype": "Currency",
+ "label": "Paid Amount After Tax (Company Currency)",
+ "options": "Company:company:default_currency",
+ "show_days": 1,
+ "show_seconds": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2020-09-13 22:33:59.860146",
+ "modified": "2020-10-25 20:50:14.896628",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index a41b4512a1..a21deb5431 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -396,9 +396,6 @@ class PaymentEntry(AccountsController):
if not self.apply_tax_withholding_amount:
return
- if self.references:
- return
-
args = frappe._dict({
'company': self.company,
'supplier': self.party,
@@ -427,11 +424,18 @@ class PaymentEntry(AccountsController):
self.remove(d)
def set_amounts(self):
+ self.set_amounts_after_tax()
self.set_amounts_in_company_currency()
self.set_total_allocated_amount()
self.set_unallocated_amount()
self.set_difference_amount()
+ def set_amounts_after_tax(self):
+ self.paid_amount_after_tax = flt(flt(self.paid_amount) + flt(self.total_taxes_and_charges),
+ self.precision("paid_amount_after_tax"))
+ self.base_paid_amount_after_tax = flt(flt(self.paid_amount_after_tax) * flt(self.source_exchange_rate),
+ self.precision("base_paid_amount_after_tax"))
+
def set_amounts_in_company_currency(self):
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
if self.paid_amount:
@@ -463,12 +467,12 @@ class PaymentEntry(AccountsController):
if self.payment_type == "Receive" \
and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
- self.unallocated_amount = (self.base_received_amount + self.base_total_taxes_and_charges + total_deductions -
+ self.unallocated_amount = (self.base_received_amount + total_deductions -
self.base_total_allocated_amount) / self.source_exchange_rate
elif self.payment_type == "Pay" \
and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
- self.unallocated_amount = (self.base_paid_amount + self.base_total_taxes_and_charges - (total_deductions +
+ self.unallocated_amount = (self.base_paid_amount - (total_deductions +
self.base_total_allocated_amount)) / self.target_exchange_rate
def set_difference_amount(self):
@@ -486,7 +490,7 @@ class PaymentEntry(AccountsController):
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
- self.difference_amount = flt(self.difference_amount - total_deductions + self.base_total_taxes_and_charges,
+ self.difference_amount = flt(self.difference_amount - total_deductions,
self.precision("difference_amount"))
# Paid amount is auto allocated in the reference document by default.
@@ -631,8 +635,8 @@ class PaymentEntry(AccountsController):
"account": self.paid_from,
"account_currency": self.paid_from_account_currency,
"against": self.party if self.payment_type=="Pay" else self.paid_to,
- "credit_in_account_currency": self.paid_amount,
- "credit": self.base_paid_amount,
+ "credit_in_account_currency": self.paid_amount_after_tax,
+ "credit": self.base_paid_amount_after_tax,
"cost_center": self.cost_center
}, item=self)
)
@@ -654,7 +658,10 @@ class PaymentEntry(AccountsController):
if account_currency != self.company_currency:
frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency))
- dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
+ if self.payment_type == 'Pay':
+ dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
+ elif self.payment_type == 'Receive':
+ dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
gl_entries.append(
self.get_gl_dict({
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index d3d3ffa17f..36450a9255 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -127,6 +127,7 @@
"write_off_cost_center",
"advances_section",
"allocate_advances_automatically",
+ "adjust_advance_taxes",
"get_advances",
"advances",
"payment_schedule_section",
@@ -175,7 +176,9 @@
"hidden": 1,
"label": "Title",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "naming_series",
@@ -187,7 +190,9 @@
"options": "ACC-PINV-.YYYY.-\nACC-PINV-RET-.YYYY.-",
"print_hide": 1,
"reqd": 1,
- "set_only_once": 1
+ "set_only_once": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "supplier",
@@ -199,7 +204,9 @@
"options": "Supplier",
"print_hide": 1,
"reqd": 1,
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -211,7 +218,9 @@
"label": "Supplier Name",
"oldfieldname": "supplier_name",
"oldfieldtype": "Data",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fetch_from": "supplier.tax_id",
@@ -219,21 +228,27 @@
"fieldtype": "Read Only",
"label": "Tax Id",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "due_date",
"fieldtype": "Date",
"label": "Due Date",
"oldfieldname": "due_date",
- "oldfieldtype": "Date"
+ "oldfieldtype": "Date",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
"fieldname": "is_paid",
"fieldtype": "Check",
"label": "Is Paid",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
@@ -241,19 +256,25 @@
"fieldtype": "Check",
"label": "Is Return (Debit Note)",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
"fieldname": "apply_tds",
"fieldtype": "Check",
"label": "Apply Tax Withholding Amount",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1,
"width": "50%"
},
{
@@ -263,13 +284,17 @@
"label": "Company",
"options": "Company",
"print_hide": 1,
- "remember_last_selected_value": 1
+ "remember_last_selected_value": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
- "options": "Cost Center"
+ "options": "Cost Center",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "Today",
@@ -281,7 +306,9 @@
"oldfieldtype": "Date",
"print_hide": 1,
"reqd": 1,
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "posting_time",
@@ -290,6 +317,8 @@
"no_copy": 1,
"print_hide": 1,
"print_width": "100px",
+ "show_days": 1,
+ "show_seconds": 1,
"width": "100px"
},
{
@@ -298,7 +327,9 @@
"fieldname": "set_posting_time",
"fieldtype": "Check",
"label": "Edit Posting Date and Time",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "amended_from",
@@ -310,44 +341,58 @@
"oldfieldtype": "Link",
"options": "Purchase Invoice",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.on_hold",
"fieldname": "sb_14",
"fieldtype": "Section Break",
- "label": "Hold Invoice"
+ "label": "Hold Invoice",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
"fieldname": "on_hold",
"fieldtype": "Check",
- "label": "Hold Invoice"
+ "label": "Hold Invoice",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.on_hold",
"description": "Once set, this invoice will be on hold till the set date",
"fieldname": "release_date",
"fieldtype": "Date",
- "label": "Release Date"
+ "label": "Release Date",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "cb_17",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.on_hold",
"fieldname": "hold_comment",
"fieldtype": "Small Text",
- "label": "Reason For Putting On Hold"
+ "label": "Reason For Putting On Hold",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "bill_no",
"fieldname": "supplier_invoice_details",
"fieldtype": "Section Break",
- "label": "Supplier Invoice Details"
+ "label": "Supplier Invoice Details",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "bill_no",
@@ -355,11 +400,15 @@
"label": "Supplier Invoice No",
"oldfieldname": "bill_no",
"oldfieldtype": "Data",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_15",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "bill_date",
@@ -368,13 +417,17 @@
"no_copy": 1,
"oldfieldname": "bill_date",
"oldfieldtype": "Date",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "return_against",
"fieldname": "returns",
"fieldtype": "Section Break",
- "label": "Returns"
+ "label": "Returns",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "return_against",
@@ -384,26 +437,34 @@
"no_copy": 1,
"options": "Purchase Invoice",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "section_addresses",
"fieldtype": "Section Break",
- "label": "Address and Contact"
+ "label": "Address and Contact",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "supplier_address",
"fieldtype": "Link",
"label": "Select Supplier Address",
"options": "Address",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "address_display",
"fieldtype": "Small Text",
"label": "Address",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "contact_person",
@@ -411,51 +472,67 @@
"in_global_search": 1,
"label": "Contact Person",
"options": "Contact",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "contact_display",
"fieldtype": "Small Text",
"label": "Contact",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"label": "Mobile No",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "contact_email",
"fieldtype": "Small Text",
"label": "Contact Email",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "col_break_address",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "shipping_address",
"fieldtype": "Link",
"label": "Select Shipping Address",
"options": "Address",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "shipping_address_display",
"fieldtype": "Small Text",
"label": "Shipping Address",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "currency_and_price_list",
"fieldtype": "Section Break",
"label": "Currency and Price List",
- "options": "fa fa-tag"
+ "options": "fa fa-tag",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "currency",
@@ -464,7 +541,9 @@
"oldfieldname": "currency",
"oldfieldtype": "Select",
"options": "Currency",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "conversion_rate",
@@ -473,18 +552,24 @@
"oldfieldname": "conversion_rate",
"oldfieldtype": "Currency",
"precision": "9",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break2",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "price_list_currency",
@@ -492,14 +577,18 @@
"label": "Price List Currency",
"options": "Currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",
"label": "Price List Exchange Rate",
"precision": "9",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
@@ -508,11 +597,15 @@
"label": "Ignore Pricing Rule",
"no_copy": 1,
"permlevel": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "sec_warehouse",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "update_stock",
@@ -521,7 +614,9 @@
"fieldtype": "Link",
"label": "Set Accepted Warehouse",
"options": "Warehouse",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "update_stock",
@@ -531,11 +626,15 @@
"label": "Rejected Warehouse",
"no_copy": 1,
"options": "Warehouse",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "col_break_warehouse",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "No",
@@ -543,25 +642,33 @@
"fieldtype": "Select",
"label": "Raw Materials Supplied",
"options": "No\nYes",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "items_section",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-shopping-cart"
+ "options": "fa fa-shopping-cart",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
"fieldname": "update_stock",
"fieldtype": "Check",
"label": "Update Stock",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "scan_barcode",
"fieldtype": "Data",
- "label": "Scan Barcode"
+ "label": "Scan Barcode",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_bulk_edit": 1,
@@ -571,42 +678,56 @@
"oldfieldname": "entries",
"oldfieldtype": "Table",
"options": "Purchase Invoice Item",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "pricing_rule_details",
"fieldtype": "Section Break",
- "label": "Pricing Rules"
+ "label": "Pricing Rules",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "pricing_rules",
"fieldtype": "Table",
"label": "Pricing Rule Detail",
"options": "Pricing Rule Detail",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible_depends_on": "supplied_items",
"fieldname": "raw_materials_supplied",
"fieldtype": "Section Break",
- "label": "Raw Materials Supplied"
+ "label": "Raw Materials Supplied",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "supplied_items",
"fieldtype": "Table",
"label": "Supplied Items",
"options": "Purchase Receipt Item Supplied",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "section_break_26",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total_qty",
"fieldtype": "Float",
"label": "Total Quantity",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_total",
@@ -614,7 +735,9 @@
"label": "Total (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_net_total",
@@ -624,18 +747,24 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_28",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total",
"fieldtype": "Currency",
"label": "Total",
"options": "currency",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "net_total",
@@ -645,42 +774,56 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total_net_weight",
"fieldtype": "Float",
"label": "Total Net Weight",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "taxes_section",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-money"
+ "options": "fa fa-money",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "tax_category",
"fieldtype": "Link",
"label": "Tax Category",
"options": "Tax Category",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_49",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "shipping_rule",
"fieldtype": "Link",
"label": "Shipping Rule",
"options": "Shipping Rule",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "section_break_51",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "taxes_and_charges",
@@ -689,7 +832,9 @@
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "taxes",
@@ -697,13 +842,17 @@
"label": "Purchase Taxes and Charges",
"oldfieldname": "purchase_tax_details",
"oldfieldtype": "Table",
- "options": "Purchase Taxes and Charges"
+ "options": "Purchase Taxes and Charges",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "sec_tax_breakup",
"fieldtype": "Section Break",
- "label": "Tax Breakup"
+ "label": "Tax Breakup",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "other_charges_calculation",
@@ -712,13 +861,17 @@
"no_copy": 1,
"oldfieldtype": "HTML",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "totals",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-money"
+ "options": "fa fa-money",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_taxes_and_charges_added",
@@ -728,7 +881,9 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_taxes_and_charges_deducted",
@@ -738,7 +893,9 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_total_taxes_and_charges",
@@ -748,11 +905,15 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_40",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "taxes_and_charges_added",
@@ -762,7 +923,9 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "taxes_and_charges_deducted",
@@ -772,7 +935,9 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total_taxes_and_charges",
@@ -780,14 +945,18 @@
"label": "Total Taxes and Charges",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "discount_amount",
"fieldname": "section_break_44",
"fieldtype": "Section Break",
- "label": "Additional Discount"
+ "label": "Additional Discount",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "Grand Total",
@@ -795,7 +964,9 @@
"fieldtype": "Select",
"label": "Apply Additional Discount On",
"options": "\nGrand Total\nNet Total",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_discount_amount",
@@ -803,28 +974,38 @@
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_46",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "additional_discount_percentage",
"fieldtype": "Float",
"label": "Additional Discount Percentage",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Additional Discount Amount",
"options": "currency",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "section_break_49",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_grand_total",
@@ -834,7 +1015,9 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_rounding_adjustment",
@@ -843,7 +1026,9 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -853,7 +1038,9 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_in_words",
@@ -863,13 +1050,17 @@
"oldfieldname": "in_words",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break8",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1,
"width": "50%"
},
{
@@ -880,7 +1071,9 @@
"oldfieldname": "grand_total_import",
"oldfieldtype": "Currency",
"options": "currency",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "rounding_adjustment",
@@ -889,7 +1082,9 @@
"no_copy": 1,
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -899,7 +1094,9 @@
"no_copy": 1,
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "in_words",
@@ -909,7 +1106,9 @@
"oldfieldname": "in_words_import",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total_advance",
@@ -920,7 +1119,9 @@
"oldfieldtype": "Currency",
"options": "party_account_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "outstanding_amount",
@@ -931,14 +1132,18 @@
"oldfieldtype": "Currency",
"options": "party_account_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
"depends_on": "grand_total",
"fieldname": "disable_rounded_total",
"fieldtype": "Check",
- "label": "Disable Rounded Total"
+ "label": "Disable Rounded Total",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -946,20 +1151,26 @@
"depends_on": "eval:doc.is_paid===1||(doc.advances && doc.advances.length>0)",
"fieldname": "payments_section",
"fieldtype": "Section Break",
- "label": "Payments"
+ "label": "Payments",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"label": "Mode of Payment",
"options": "Mode of Payment",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "cash_bank_account",
"fieldtype": "Link",
"label": "Cash/Bank Account",
- "options": "Account"
+ "options": "Account",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "clearance_date",
@@ -967,11 +1178,15 @@
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "col_br_payments",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "is_paid",
@@ -980,7 +1195,9 @@
"label": "Paid Amount",
"no_copy": 1,
"options": "currency",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_paid_amount",
@@ -989,7 +1206,9 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -997,7 +1216,9 @@
"depends_on": "grand_total",
"fieldname": "write_off",
"fieldtype": "Section Break",
- "label": "Write Off"
+ "label": "Write Off",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "write_off_amount",
@@ -1005,7 +1226,9 @@
"label": "Write Off Amount",
"no_copy": 1,
"options": "currency",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_write_off_amount",
@@ -1014,11 +1237,15 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_61",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1026,7 +1253,9 @@
"fieldtype": "Link",
"label": "Write Off Account",
"options": "Account",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1034,7 +1263,9 @@
"fieldtype": "Link",
"label": "Write Off Cost Center",
"options": "Cost Center",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -1044,13 +1275,17 @@
"label": "Advance Payments",
"oldfieldtype": "Section Break",
"options": "fa fa-money",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
"fieldname": "allocate_advances_automatically",
"fieldtype": "Check",
- "label": "Set Advances and Allocate (FIFO)"
+ "label": "Set Advances and Allocate (FIFO)",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:!doc.allocate_advances_automatically",
@@ -1058,7 +1293,9 @@
"fieldtype": "Button",
"label": "Get Advances Paid",
"oldfieldtype": "Button",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "advances",
@@ -1068,20 +1305,26 @@
"oldfieldname": "advance_allocation_details",
"oldfieldtype": "Table",
"options": "Purchase Invoice Advance",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:(!doc.is_return)",
"fieldname": "payment_schedule_section",
"fieldtype": "Section Break",
- "label": "Payment Terms"
+ "label": "Payment Terms",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"label": "Payment Terms Template",
- "options": "Payment Terms Template"
+ "options": "Payment Terms Template",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "payment_schedule",
@@ -1089,7 +1332,9 @@
"label": "Payment Schedule",
"no_copy": 1,
"options": "Payment Schedule",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -1097,25 +1342,33 @@
"fieldname": "terms_section_break",
"fieldtype": "Section Break",
"label": "Terms and Conditions",
- "options": "fa fa-legal"
+ "options": "fa fa-legal",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "tc_name",
"fieldtype": "Link",
"label": "Terms",
"options": "Terms and Conditions",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "terms",
"fieldtype": "Text Editor",
- "label": "Terms and Conditions1"
+ "label": "Terms and Conditions1",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "printing_settings",
"fieldtype": "Section Break",
- "label": "Printing Settings"
+ "label": "Printing Settings",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1123,7 +1376,9 @@
"fieldtype": "Link",
"label": "Letter Head",
"options": "Letter Head",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1131,11 +1386,15 @@
"fieldname": "group_same_items",
"fieldtype": "Check",
"label": "Group same items",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_112",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1147,14 +1406,18 @@
"oldfieldtype": "Link",
"options": "Print Heading",
"print_hide": 1,
- "report_hide": 1
+ "report_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "language",
"fieldtype": "Data",
"label": "Print Language",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -1163,7 +1426,9 @@
"label": "More Information",
"oldfieldtype": "Section Break",
"options": "fa fa-file-text",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "credit_to",
@@ -1174,7 +1439,9 @@
"options": "Account",
"print_hide": 1,
"reqd": 1,
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "party_account_currency",
@@ -1184,7 +1451,9 @@
"no_copy": 1,
"options": "Currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "No",
@@ -1194,7 +1463,9 @@
"oldfieldname": "is_opening",
"oldfieldtype": "Select",
"options": "No\nYes",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "against_expense_account",
@@ -1204,11 +1475,15 @@
"no_copy": 1,
"oldfieldname": "against_expense_account",
"oldfieldtype": "Small Text",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_63",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "Draft",
@@ -1235,14 +1510,18 @@
"no_copy": 1,
"oldfieldname": "remarks",
"oldfieldtype": "Text",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"label": "Subscription Section",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1251,7 +1530,9 @@
"fieldtype": "Date",
"label": "From Date",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1260,11 +1541,15 @@
"fieldtype": "Date",
"label": "To Date",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_114",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "auto_repeat",
@@ -1273,24 +1558,32 @@
"no_copy": 1,
"options": "Auto Repeat",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
"depends_on": "eval: doc.auto_repeat",
"fieldname": "update_auto_repeat_reference",
"fieldtype": "Button",
- "label": "Update Auto Repeat Reference"
+ "label": "Update Auto Repeat Reference",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions "
+ "label": "Accounting Dimensions ",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
@@ -1298,7 +1591,9 @@
"fieldname": "is_internal_supplier",
"fieldtype": "Check",
"label": "Is Internal Supplier",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "tax_withholding_category",
@@ -1306,19 +1601,25 @@
"hidden": 1,
"label": "Tax Withholding Category",
"options": "Tax Withholding Category",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "billing_address",
"fieldtype": "Link",
"label": "Select Billing Address",
- "options": "Address"
+ "options": "Address",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "billing_address_display",
"fieldtype": "Small Text",
"label": "Billing Address",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "project",
@@ -1380,7 +1681,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-30 22:45:58.334107",
+ "modified": "2020-10-27 21:21:22.647349",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 83e9f7583e..84dd491a56 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -1088,9 +1088,10 @@ class PurchaseInvoice(BuyingController):
accounts = []
for d in self.taxes:
- if d.account_head == tax_withholding_details.get("account_head"):
+ if d.account_head == tax_withholding_details.get("account_head") and not d.is_advance_tax:
d.update(tax_withholding_details)
- accounts.append(d.account_head)
+ if not d.is_advance_tax:
+ accounts.append(d.account_head)
if not accounts or tax_withholding_details.get("account_head") not in accounts:
self.append("taxes", tax_withholding_details)
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index f9fdc4b605..de7ef2ac96 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -28,7 +28,8 @@
"base_tax_amount",
"base_total",
"base_tax_amount_after_discount_amount",
- "item_wise_tax_detail"
+ "item_wise_tax_detail",
+ "is_advance_tax"
],
"fields": [
{
@@ -39,7 +40,9 @@
"oldfieldname": "category",
"oldfieldtype": "Select",
"options": "Valuation and Total\nValuation\nTotal",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "Add",
@@ -49,7 +52,9 @@
"oldfieldname": "add_deduct_tax",
"oldfieldtype": "Select",
"options": "Add\nDeduct",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"columns": 2,
@@ -61,7 +66,9 @@
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
@@ -69,7 +76,9 @@
"fieldtype": "Data",
"label": "Reference Row #",
"oldfieldname": "row_id",
- "oldfieldtype": "Data"
+ "oldfieldtype": "Data",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
@@ -77,11 +86,15 @@
"fieldname": "included_in_print_rate",
"fieldtype": "Check",
"label": "Is this Tax included in Basic Rate?",
- "report_hide": 1
+ "report_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "col_break1",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"columns": 2,
@@ -92,7 +105,9 @@
"oldfieldname": "account_head",
"oldfieldtype": "Link",
"options": "Account",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": ":Company",
@@ -101,7 +116,9 @@
"label": "Cost Center",
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
- "options": "Cost Center"
+ "options": "Cost Center",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "description",
@@ -111,11 +128,15 @@
"oldfieldtype": "Small Text",
"print_width": "300px",
"reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1,
"width": "300px"
},
{
"fieldname": "section_break_10",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"columns": 2,
@@ -124,11 +145,15 @@
"in_list_view": 1,
"label": "Rate",
"oldfieldname": "rate",
- "oldfieldtype": "Currency"
+ "oldfieldtype": "Currency",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "section_break_9",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"columns": 2,
@@ -138,7 +163,9 @@
"label": "Amount",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
- "options": "currency"
+ "options": "currency",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "tax_amount_after_discount_amount",
@@ -146,7 +173,9 @@
"label": "Tax Amount After Discount Amount",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"columns": 2,
@@ -157,11 +186,15 @@
"oldfieldname": "total",
"oldfieldtype": "Currency",
"options": "currency",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_14",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_tax_amount",
@@ -169,7 +202,9 @@
"label": "Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_total",
@@ -177,7 +212,9 @@
"hidden": 1,
"label": "Total (Company Currency)",
"options": "Company:company:default_currency",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_tax_amount_after_discount_amount",
@@ -185,7 +222,9 @@
"label": "Tax Amount After Discount Amount",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "item_wise_tax_detail",
@@ -195,22 +234,38 @@
"oldfieldname": "item_wise_tax_detail",
"oldfieldtype": "Small Text",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions"
+ "label": "Accounting Dimensions",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "is_advance_tax",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Is Advance Tax",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-09-18 17:26:09.703215",
+ "modified": "2020-10-25 18:24:43.487567",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 65e5823b91..a805dc4e91 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -617,10 +617,6 @@ class AccountsController(TransactionBase):
payment_entries = get_advance_payment_entries(party_type, party, party_account,
order_doctype, order_list, include_unallocated)
- payment_entry_list = [d.reference_name for d in payment_entries]
-
- payment_entry_taxes = get_payment_entry_taxes(payment_entry_list)
-
res = journal_entries + payment_entries
return res
@@ -1245,13 +1241,6 @@ def get_advance_payment_entries(party_type, party, party_account, order_doctype,
return list(payment_entries_against_order) + list(unallocated_payment_entries)
-def get_payment_entry_taxes(payment_entry_list):
- taxes = frappe.db.sql("""
- SELECT t.parent, t.add_deduct_tax, t.charge_type, t.account_head, t.cost_center,
- t.tax_amount FROM `tabAdvance Taxes and Charges` where t.parent in %s"""
- ,(payment_entry_list, ), as_dict=1)
-
-
def update_invoice_status():
# Daily update the status of the invoices
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 9fae49482d..f3d7b2635e 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -40,6 +40,7 @@ class calculate_taxes_and_totals(object):
self.validate_conversion_rate()
self.calculate_item_values()
self.validate_item_tax_template()
+ self.apply_advance_taxes()
self.initialize_taxes()
self.determine_exclusive_rate()
self.calculate_net_total()
@@ -683,6 +684,32 @@ class calculate_taxes_and_totals(object):
self.calculate_paid_amount()
+ def apply_advance_taxes(self):
+ if cint(self.doc.get('adjust_advance_taxes')):
+ if self.doc.get('advances'):
+ payment_entry_list = [d.reference_name for d in self.doc.get('advances')]
+ advance_taxes = get_advance_taxes(payment_entry_list)
+ accounts = []
+
+ # Remove already added advance taxes if any
+ for tax in self.doc.get('taxes'):
+ if tax.is_advance_tax:
+ self.doc.remove(tax)
+ else:
+ accounts.append(tax.account_head)
+
+ for tax in advance_taxes:
+ # Reverse add deduct from payment entry in invoice
+ if tax.account_head in accounts:
+ add_deduct_tax = 'Deduct' if tax.add_deduct_tax == 'Add' else 'Add'
+ tax.update({
+ 'add_deduct_tax': add_deduct_tax,
+ 'category': tax.get('category') or 'Total',
+ 'is_advance_tax': 1,
+ 'charge_type': 'On Net Total' if tax.charge_type == 'On Paid Amount' else tax.charge_type
+ })
+
+ self.doc.append('taxes', tax)
def get_itemised_tax_breakup_html(doc):
if not doc.taxes:
@@ -820,3 +847,16 @@ class init_landed_taxes_and_totals(object):
for d in self.doc.get(self.tax_field):
d.amount = flt(d.amount, d.precision("amount"))
d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount"))
+
+def get_advance_taxes(payment_entry_list):
+ taxes = []
+ if payment_entry_list:
+ taxes = frappe.db.sql(
+ """
+ SELECT t.parent, t.add_deduct_tax, t.charge_type, t.rate,
+ t.account_head, t.cost_center, t.tax_amount, t.description
+ FROM `tabAdvance Taxes and Charges` t, `tabPayment Entry` p
+ WHERE t.parent = p.name AND t.parent in %s
+ """, (payment_entry_list, ), as_dict=1)
+
+ return taxes
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index 0d656bc1fb..b168952e40 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -8,7 +8,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.dialog = new frappe.ui.Dialog({
title: 'Payment'
});
-
+
this.dialog.show();
this.$body = this.dialog.body;
this.set_payment_primary_action();
@@ -25,7 +25,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
set_payment_primary_action: function(){
var me = this;
-
+
this.dialog.set_primary_action(__("Submit"), function() {
// Allow no ZERO payment
$.each(me.frm.doc.payments, function (index, data) {
@@ -100,7 +100,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.selected_mode.select()
this.bind_amount_change_event();
},
-
+
bind_keyboard_event: function(){
var me = this;
this.payment_val = '';
@@ -114,17 +114,17 @@ erpnext.payments = erpnext.stock.StockController.extend({
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('.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"));
})
@@ -138,7 +138,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
$(this.$body).find('.amount').attr('disabled', true);
this.selected_mode.attr('disabled', false);
},
-
+
bind_numeric_keys_event: function(){
var me = this;
$(this.$body).find('.pos-keyboard-key').click(function(){
@@ -147,7 +147,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
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));
@@ -156,7 +156,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
})
},
-
+
bind_amount_change_event: function(){
var me = this;
this.selected_mode.change(function(){
From d18dde77577cb041ce06e4cf7971087157ceb933 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 29 Nov 2020 21:40:04 +0530
Subject: [PATCH 113/262] fix: Add tds in PO and code cleanup
---
.../advance_taxes_and_charges.json | 31 +-
.../doctype/payment_entry/payment_entry.json | 66 ++-
.../doctype/payment_entry/payment_entry.py | 89 +++-
.../purchase_invoice/purchase_invoice.py | 48 +-
.../purchase_taxes_and_charges.json | 15 +-
.../doctype/sales_invoice/sales_invoice.py | 42 ++
.../doctype/purchase_order/purchase_order.js | 8 +
.../purchase_order/purchase_order.json | 481 +++++++++++++-----
.../doctype/purchase_order/purchase_order.py | 35 ++
erpnext/controllers/accounts_controller.py | 30 ++
erpnext/controllers/taxes_and_totals.py | 28 -
11 files changed, 676 insertions(+), 197 deletions(-)
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
index 5b3299e656..aac7eb6bcb 100644
--- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
@@ -12,6 +12,7 @@
"account_head",
"col_break_1",
"description",
+ "included_in_paid_amount",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -20,9 +21,11 @@
"section_break_9",
"tax_amount",
"total",
+ "allocated_amount",
"column_break_13",
"base_tax_amount",
- "base_total"
+ "base_total",
+ "base_allocated_amount"
],
"fields": [
{
@@ -185,12 +188,36 @@
"reqd": 1,
"show_days": 1,
"show_seconds": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "included_in_paid_amount",
+ "fieldtype": "Check",
+ "label": "Included In Paid Amount",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "allocated_amount",
+ "fieldtype": "Currency",
+ "label": "Allocated Amount",
+ "options": "currency",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "base_allocated_amount",
+ "fieldtype": "Currency",
+ "label": "Allocated Amount (Company Currency)",
+ "options": "Company:company:default_currency",
+ "show_days": 1,
+ "show_seconds": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2020-10-27 20:02:34.734260",
+ "modified": "2020-11-29 19:06:14.666460",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index f158345af6..ec92db0708 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -24,15 +24,12 @@
"party_bank_account",
"contact_person",
"contact_email",
- "tds_details_section",
- "apply_tax_withholding_amount",
- "column_break_20",
- "tax_withholding_category",
"payment_accounts_section",
"party_balance",
"paid_from",
"paid_from_account_currency",
"paid_from_account_balance",
+ "advance_tax_account",
"column_break_18",
"paid_to",
"paid_to_account_currency",
@@ -45,8 +42,10 @@
"base_paid_amount_after_tax",
"column_break_21",
"received_amount",
+ "received_amount_after_tax",
"target_exchange_rate",
"base_received_amount",
+ "base_received_amount_after_tax",
"section_break_14",
"get_outstanding_invoice",
"references",
@@ -61,6 +60,10 @@
"taxes_and_charges_section",
"purchase_taxes_and_charges_template",
"sales_taxes_and_charges_template",
+ "column_break_55",
+ "apply_tax_withholding_amount",
+ "tax_withholding_category",
+ "section_break_56",
"taxes",
"base_total_taxes_and_charges",
"total_taxes_and_charges",
@@ -731,14 +734,6 @@
"fieldtype": "Check",
"label": "Custom Remarks"
},
- {
- "depends_on": "eval: doc.payment_type == 'Pay' && doc.party_type == 'Supplier'",
- "fieldname": "tds_details_section",
- "fieldtype": "Section Break",
- "label": "TDS Details",
- "show_days": 1,
- "show_seconds": 1
- },
{
"depends_on": "eval:doc.apply_tax_withholding_amount",
"fieldname": "tax_withholding_category",
@@ -750,18 +745,13 @@
},
{
"default": "0",
+ "depends_on": "eval:doc.party_type == 'Supplier'",
"fieldname": "apply_tax_withholding_amount",
"fieldtype": "Check",
"label": "Apply Tax Withholding Amount",
"show_days": 1,
"show_seconds": 1
},
- {
- "fieldname": "column_break_20",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
- },
{
"collapsible": 1,
"fieldname": "taxes_and_charges_section",
@@ -829,6 +819,44 @@
"fieldtype": "Currency",
"label": "Paid Amount After Tax (Company Currency)",
"options": "Company:company:default_currency",
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "column_break_55",
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "section_break_56",
+ "fieldtype": "Section Break",
+ "hide_border": 1,
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "advance_tax_account",
+ "fieldtype": "Link",
+ "label": "Advance Tax Account",
+ "options": "Account",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "received_amount_after_tax",
+ "fieldtype": "Currency",
+ "label": "Received Amount After Tax",
+ "options": "paid_to_account_currency",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "fieldname": "base_received_amount_after_tax",
+ "fieldtype": "Currency",
+ "label": "Received Amount After Tax (Company Currency)",
+ "options": "Company:company:default_currency",
"show_days": 1,
"show_seconds": 1
}
@@ -836,7 +864,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2020-10-25 20:50:14.896628",
+ "modified": "2020-11-29 20:03:57.772062",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index a21deb5431..251b581723 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -65,6 +65,7 @@ class PaymentEntry(AccountsController):
self.validate_allocated_amount()
self.validate_paid_invoices()
self.ensure_supplier_is_not_blocked()
+ self.validate_advance_tax_account()
self.set_status()
def on_submit(self):
@@ -310,6 +311,9 @@ class PaymentEntry(AccountsController):
+ "
" + _("If this is undesirable please cancel the corresponding Payment Entry."),
title=_("Warning"), indicator="orange")
+ def validate_advance_tax_account(self):
+ if self.get('taxes') and not self.advance_tax_account:
+ frappe.throw(_('Please select advance tax account'))
def validate_journal_entry(self):
for d in self.get("references"):
@@ -396,11 +400,29 @@ class PaymentEntry(AccountsController):
if not self.apply_tax_withholding_amount:
return
+ reference_doclist = []
+ net_total = self.paid_amount
+ included_in_paid_amount = 0
+
+ if self.get('references'):
+ for doc in self.get('references'):
+ if doc.reference_doctype == 'Purchase Order':
+ reference_doclist.append(doc.reference_name)
+
+ if reference_doclist:
+ order_amount = frappe.db.get_all('Purchase Order', fields=['sum(net_total)'],
+ filters = {'name': ('in', reference_doclist), 'docstatus': 1,
+ 'apply_tds': 1}, as_list=1)
+
+ if order_amount:
+ net_total = order_amount[0][0]
+ included_in_paid_amount = 1
+
args = frappe._dict({
'company': self.company,
'supplier': self.party,
'posting_date': self.posting_date,
- 'net_total': self.paid_amount
+ 'net_total': net_total
})
tax_withholding_details = get_party_tax_withholding_details(args, self.tax_withholding_category)
@@ -408,6 +430,8 @@ class PaymentEntry(AccountsController):
if not tax_withholding_details:
return
+ tax_withholding_details.update({'included_in_paid_amount': included_in_paid_amount})
+
accounts = []
for d in self.taxes:
if d.account_head == tax_withholding_details.get("account_head"):
@@ -424,18 +448,37 @@ class PaymentEntry(AccountsController):
self.remove(d)
def set_amounts(self):
- self.set_amounts_after_tax()
+ self.set_received_amount()
self.set_amounts_in_company_currency()
+ self.set_amounts_after_tax()
self.set_total_allocated_amount()
self.set_unallocated_amount()
self.set_difference_amount()
+ def set_received_amount(self):
+ self.base_received_amount = self.base_paid_amount
+
def set_amounts_after_tax(self):
- self.paid_amount_after_tax = flt(flt(self.paid_amount) + flt(self.total_taxes_and_charges),
+ applicable_tax = 0
+ base_applicable_tax = 0
+ for tax in self.get('taxes'):
+ if not tax.included_in_paid_amount:
+ amount = -1 * tax.tax_amount if tax.add_deduct_tax == 'Deduct' else tax.tax_amount
+ base_amount = -1 * tax.base_tax_amount if tax.add_deduct_tax == 'Deduct' else tax.base_tax_amount
+
+ applicable_tax += amount
+ base_applicable_tax += base_amount
+
+ self.paid_amount_after_tax = flt(flt(self.paid_amount) + flt(applicable_tax),
self.precision("paid_amount_after_tax"))
self.base_paid_amount_after_tax = flt(flt(self.paid_amount_after_tax) * flt(self.source_exchange_rate),
self.precision("base_paid_amount_after_tax"))
+ self.received_amount_after_tax = flt(flt(self.received_amount) + flt(applicable_tax),
+ self.precision("paid_amount_after_tax"))
+ self.base_received_amount_after_tax = flt(flt(self.received_amount_after_tax) * flt(self.source_exchange_rate),
+ self.precision("base_paid_amount_after_tax"))
+
def set_amounts_in_company_currency(self):
self.base_paid_amount, self.base_received_amount, self.difference_amount = 0, 0, 0
if self.paid_amount:
@@ -465,14 +508,14 @@ class PaymentEntry(AccountsController):
if self.party:
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
if self.payment_type == "Receive" \
- and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
- and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
- self.unallocated_amount = (self.base_received_amount + total_deductions -
+ and self.base_total_allocated_amount < self.base_received_amount_after_tax + total_deductions \
+ and self.total_allocated_amount < self.paid_amount_after_tax + (total_deductions / self.source_exchange_rate):
+ self.unallocated_amount = (self.received_amount_after_tax + total_deductions -
self.base_total_allocated_amount) / self.source_exchange_rate
elif self.payment_type == "Pay" \
- and self.base_total_allocated_amount < (self.base_paid_amount - total_deductions) \
- and self.total_allocated_amount < self.received_amount + (total_deductions / self.target_exchange_rate):
- self.unallocated_amount = (self.base_paid_amount - (total_deductions +
+ and self.base_total_allocated_amount < (self.base_paid_amount_after_tax - total_deductions) \
+ and self.total_allocated_amount < self.received_amount_after_tax + (total_deductions / self.target_exchange_rate):
+ self.unallocated_amount = (self.base_paid_amount_after_tax - (total_deductions +
self.base_total_allocated_amount)) / self.target_exchange_rate
def set_difference_amount(self):
@@ -482,11 +525,11 @@ class PaymentEntry(AccountsController):
base_party_amount = flt(self.base_total_allocated_amount) + flt(base_unallocated_amount)
if self.payment_type == "Receive":
- self.difference_amount = base_party_amount - self.base_received_amount
+ self.difference_amount = base_party_amount - self.base_received_amount_after_tax
elif self.payment_type == "Pay":
- self.difference_amount = self.base_paid_amount - base_party_amount
+ self.difference_amount = self.base_paid_amount_after_tax - base_party_amount
else:
- self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
+ self.difference_amount = self.base_paid_amount_after_tax - flt(self.base_received_amount_after_tax)
total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
@@ -616,7 +659,7 @@ class PaymentEntry(AccountsController):
gl_entries.append(gle)
if self.unallocated_amount:
- base_unallocated_amount = base_unallocated_amount = self.unallocated_amount * \
+ base_unallocated_amount = self.unallocated_amount * \
(self.source_exchange_rate if self.payment_type=="Receive" else self.target_exchange_rate)
gle = party_gl_dict.copy()
@@ -646,8 +689,8 @@ class PaymentEntry(AccountsController):
"account": self.paid_to,
"account_currency": self.paid_to_account_currency,
"against": self.party if self.payment_type=="Receive" else self.paid_from,
- "debit_in_account_currency": self.received_amount,
- "debit": self.base_received_amount,
+ "debit_in_account_currency": self.received_amount_after_tax,
+ "debit": self.base_received_amount_after_tax,
"cost_center": self.cost_center
}, item=self)
)
@@ -660,8 +703,10 @@ class PaymentEntry(AccountsController):
if self.payment_type == 'Pay':
dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
+ rev_dr_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
elif self.payment_type == 'Receive':
dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
+ rev_dr_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
gl_entries.append(
self.get_gl_dict({
@@ -672,8 +717,18 @@ class PaymentEntry(AccountsController):
if account_currency==self.company_currency \
else d.tax_amount,
"cost_center": d.cost_center
- }, account_currency, item=d)
- )
+ }, account_currency, item=d))
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": self.advance_tax_account,
+ "against": self.party if self.payment_type=="Receive" else self.paid_from,
+ rev_dr_cr: d.base_tax_amount,
+ rev_dr_cr + "_in_account_currency": d.base_tax_amount \
+ if account_currency==self.company_currency \
+ else d.tax_amount,
+ "cost_center": d.cost_center
+ }, account_currency, item=d))
def add_deductions_gl_entries(self, gl_entries):
for d in self.get("deductions"):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 84dd491a56..8f7248f1e6 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -456,6 +456,8 @@ class PurchaseInvoice(BuyingController):
self.make_tax_gl_entries(gl_entries)
self.make_internal_transfer_gl_entries(gl_entries)
+ self.allocate_advance_taxes(gl_entries)
+
gl_entries = make_regional_gl_entries(gl_entries, self)
gl_entries = merge_similar_entries(gl_entries)
@@ -899,6 +901,46 @@ class PurchaseInvoice(BuyingController):
"cost_center": self.cost_center
}, account_currency, item=self))
+ def allocate_advance_taxes(self, gl_entries):
+ tax_map = self.get_tax_map()
+ for pe in self.get('advances'):
+ pe = frappe.get_doc('Payment Entry', pe.reference_name)
+ for tax in pe.get('taxes'):
+ account_currency = get_account_currency(tax.account_head)
+ dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+ rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
+
+ unallocated_amount = tax.tax_amount - tax.allocated_amount
+ if tax_map.get(tax.account_head):
+ amount = tax_map.get(tax.account_head)
+ if amount < unallocated_amount:
+ unallocated_amount = amount
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": tax.account_head,
+ "against": self.supplier,
+ dr_or_cr: unallocated_amount,
+ dr_or_cr + "_in_account_currency": unallocated_amount \
+ if account_currency==self.company_currency \
+ else unallocated_amount,
+ 'cost_center': tax.cost_center
+ }, account_currency, item=tax))
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": pe.advance_tax_account,
+ "against": self.supplier,
+ rev_dr_cr: unallocated_amount,
+ rev_dr_cr + "_in_account_currency": unallocated_amount \
+ if account_currency==self.company_currency \
+ else unallocated_amount,
+ 'cost_center': tax.cost_center
+ }, account_currency, item=tax))
+
+ frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
+ tax_map[tax.account_head] -= unallocated_amount
+
def make_payment_gl_entries(self, gl_entries):
# Make Cash GL Entries
if cint(self.is_paid) and self.cash_bank_account and self.paid_amount:
@@ -1088,10 +1130,10 @@ class PurchaseInvoice(BuyingController):
accounts = []
for d in self.taxes:
- if d.account_head == tax_withholding_details.get("account_head") and not d.is_advance_tax:
+ if d.account_head == tax_withholding_details.get("account_head"):
d.update(tax_withholding_details)
- if not d.is_advance_tax:
- accounts.append(d.account_head)
+
+ accounts.append(d.account_head)
if not accounts or tax_withholding_details.get("account_head") not in accounts:
self.append("taxes", tax_withholding_details)
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index de7ef2ac96..0db0b6823d 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -28,8 +28,7 @@
"base_tax_amount",
"base_total",
"base_tax_amount_after_discount_amount",
- "item_wise_tax_detail",
- "is_advance_tax"
+ "item_wise_tax_detail"
],
"fields": [
{
@@ -250,22 +249,12 @@
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1
- },
- {
- "default": "0",
- "fieldname": "is_advance_tax",
- "fieldtype": "Check",
- "hidden": 1,
- "label": "Is Advance Tax",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-10-25 18:24:43.487567",
+ "modified": "2020-11-29 19:11:58.826078",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index a008742390..9af94fd780 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -842,6 +842,8 @@ class SalesInvoice(SellingController):
self.make_tax_gl_entries(gl_entries)
self.make_internal_transfer_gl_entries(gl_entries)
+ self.allocate_advance_taxes(gl_entries)
+
self.make_item_gl_entries(gl_entries)
# merge gl entries before adding pos entries
@@ -911,6 +913,46 @@ class SalesInvoice(SellingController):
"cost_center": self.cost_center
}, account_currency, item=self))
+ def allocate_advance_taxes(self, gl_entries):
+ tax_map = self.get_tax_map()
+ for pe in self.get('advances'):
+ pe = frappe.get_doc('Payment Entry', pe.reference_name)
+ for tax in pe.get('taxes'):
+ account_currency = get_account_currency(tax.account_head)
+ dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
+ rev_dr_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+
+ unallocated_amount = tax.tax_amount - tax.allocated_amount
+ if tax_map.get(tax.account_head):
+ amount = tax_map.get(tax.account_head)
+ if amount < unallocated_amount:
+ unallocated_amount = amount
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": tax.account_head,
+ "against": self.customer,
+ dr_or_cr: unallocated_amount,
+ dr_or_cr + "_in_account_currency": unallocated_amount \
+ if account_currency==self.company_currency \
+ else unallocated_amount,
+ 'cost_center': tax.cost_center
+ }, account_currency, item=tax))
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": pe.advance_tax_account,
+ "against": self.customer,
+ rev_dr_cr: unallocated_amount,
+ rev_dr_cr + "_in_account_currency": unallocated_amount \
+ if account_currency==self.company_currency \
+ else unallocated_amount,
+ 'cost_center': tax.cost_center
+ }, account_currency, item=tax))
+
+ frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
+ tax_map[tax.account_head] -= unallocated_amount
+
def make_item_gl_entries(self, gl_entries):
# income account gl entries
for item in self.get("items"):
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index dd0f065848..139aa72c08 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -45,6 +45,14 @@ frappe.ui.form.on("Purchase Order", {
});
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
+ },
+
+ apply_tds: function(frm) {
+ if (!frm.doc.apply_tds) {
+ frm.set_value("tax_withholding_category", '');
+ } else {
+ frm.set_value("tax_withholding_category", frm.supplier_tds);
+ }
}
});
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index ee2beea67f..64eda5f280 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -14,6 +14,8 @@
"supplier",
"get_items_from_open_material_requests",
"supplier_name",
+ "apply_tds",
+ "tax_withholding_category",
"column_break1",
"company",
"transaction_date",
@@ -142,7 +144,9 @@
{
"fieldname": "supplier_section",
"fieldtype": "Section Break",
- "options": "fa fa-user"
+ "options": "fa fa-user",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -152,7 +156,9 @@
"hidden": 1,
"label": "Title",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "naming_series",
@@ -164,7 +170,9 @@
"options": "PUR-ORD-.YYYY.-",
"print_hide": 1,
"reqd": 1,
- "set_only_once": 1
+ "set_only_once": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -178,14 +186,18 @@
"options": "Supplier",
"print_hide": 1,
"reqd": 1,
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))",
"description": "Fetch items based on Default Supplier.",
"fieldname": "get_items_from_open_material_requests",
"fieldtype": "Button",
- "label": "Get Items from Open Material Requests"
+ "label": "Get Items from Open Material Requests",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -194,7 +206,9 @@
"fieldtype": "Data",
"in_global_search": 1,
"label": "Supplier Name",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "company",
@@ -206,13 +220,17 @@
"options": "Company",
"print_hide": 1,
"remember_last_selected_value": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"print_width": "50%",
+ "show_days": 1,
+ "show_seconds": 1,
"width": "50%"
},
{
@@ -224,27 +242,35 @@
"oldfieldname": "transaction_date",
"oldfieldtype": "Date",
"reqd": 1,
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
"fieldname": "schedule_date",
"fieldtype": "Date",
- "label": "Required By"
+ "label": "Required By",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
"depends_on": "eval:doc.docstatus===1",
"fieldname": "order_confirmation_no",
"fieldtype": "Data",
- "label": "Order Confirmation No"
+ "label": "Order Confirmation No",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
"depends_on": "eval:doc.order_confirmation_no",
"fieldname": "order_confirmation_date",
"fieldtype": "Date",
- "label": "Order Confirmation Date"
+ "label": "Order Confirmation Date",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "amended_from",
@@ -256,19 +282,25 @@
"oldfieldtype": "Data",
"options": "Purchase Order",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "drop_ship",
"fieldtype": "Section Break",
- "label": "Drop Ship"
+ "label": "Drop Ship",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "customer",
"fieldtype": "Link",
"label": "Customer",
"options": "Customer",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"bold": 1,
@@ -276,31 +308,41 @@
"fieldtype": "Data",
"label": "Customer Name",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_19",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "customer_contact_person",
"fieldtype": "Link",
"label": "Customer Contact",
- "options": "Contact"
+ "options": "Contact",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "customer_contact_display",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Customer Contact",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "customer_contact_mobile",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Customer Mobile No",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "customer_contact_email",
@@ -308,27 +350,35 @@
"hidden": 1,
"label": "Customer Contact Email",
"options": "Email",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "section_addresses",
"fieldtype": "Section Break",
- "label": "Address and Contact"
+ "label": "Address and Contact",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "supplier_address",
"fieldtype": "Link",
"label": "Supplier Address",
"options": "Address",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "contact_person",
"fieldtype": "Link",
"label": "Supplier Contact",
"options": "Contact",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "address_display",
@@ -355,32 +405,42 @@
"label": "Contact Email",
"options": "Email",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "col_break_address",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "shipping_address",
"fieldtype": "Link",
"label": "Company Shipping Address",
"options": "Address",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "shipping_address_display",
"fieldtype": "Small Text",
"label": "Shipping Address Details",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "currency_and_price_list",
"fieldtype": "Section Break",
"label": "Currency and Price List",
- "options": "fa fa-tag"
+ "options": "fa fa-tag",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "currency",
@@ -390,7 +450,9 @@
"oldfieldtype": "Select",
"options": "Currency",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "conversion_rate",
@@ -400,18 +462,24 @@
"oldfieldtype": "Currency",
"precision": "9",
"print_hide": 1,
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "cb_price_list",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "price_list_currency",
@@ -419,14 +487,18 @@
"label": "Price List Currency",
"options": "Currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",
"label": "Price List Exchange Rate",
"precision": "9",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
@@ -435,7 +507,9 @@
"label": "Ignore Pricing Rule",
"no_copy": 1,
"permlevel": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "sec_warehouse",
@@ -448,11 +522,15 @@
"fieldtype": "Link",
"label": "Set Target Warehouse",
"options": "Warehouse",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "col_break_warehouse",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "No",
@@ -461,26 +539,34 @@
"in_standard_filter": 1,
"label": "Supply Raw Materials",
"options": "No\nYes",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.is_subcontracted==\"Yes\"",
"fieldname": "supplier_warehouse",
"fieldtype": "Link",
"label": "Supplier Warehouse",
- "options": "Warehouse"
+ "options": "Warehouse",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "items_section",
"fieldtype": "Section Break",
"hide_border": 1,
"oldfieldtype": "Section Break",
- "options": "fa fa-shopping-cart"
+ "options": "fa fa-shopping-cart",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "scan_barcode",
"fieldtype": "Data",
- "label": "Scan Barcode"
+ "label": "Scan Barcode",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_bulk_edit": 1,
@@ -490,26 +576,34 @@
"oldfieldname": "po_details",
"oldfieldtype": "Table",
"options": "Purchase Order Item",
- "reqd": 1
+ "reqd": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "section_break_48",
"fieldtype": "Section Break",
- "label": "Pricing Rules"
+ "label": "Pricing Rules",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "pricing_rules",
"fieldtype": "Table",
"label": "Purchase Order Pricing Rule",
"options": "Pricing Rule Detail",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible_depends_on": "supplied_items",
"fieldname": "raw_material_details",
"fieldtype": "Section Break",
- "label": "Raw Materials Supplied"
+ "label": "Raw Materials Supplied",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "supplied_items",
@@ -519,17 +613,23 @@
"oldfieldtype": "Table",
"options": "Purchase Order Item Supplied",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "sb_last_purchase",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total_qty",
"fieldtype": "Float",
"label": "Total Quantity",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_total",
@@ -537,7 +637,9 @@
"label": "Total (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_net_total",
@@ -548,18 +650,24 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_26",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total",
"fieldtype": "Currency",
"label": "Total",
"options": "currency",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "net_total",
@@ -569,20 +677,26 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "total_net_weight",
"fieldtype": "Float",
"label": "Total Net Weight",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "taxes_section",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-money"
+ "options": "fa fa-money",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "taxes_and_charges",
@@ -591,18 +705,24 @@
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_50",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "shipping_rule",
"fieldtype": "Link",
"label": "Shipping Rule",
"options": "Shipping Rule",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "section_break_52",
@@ -615,13 +735,17 @@
"label": "Purchase Taxes and Charges",
"oldfieldname": "purchase_tax_details",
"oldfieldtype": "Table",
- "options": "Purchase Taxes and Charges"
+ "options": "Purchase Taxes and Charges",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "sec_tax_breakup",
"fieldtype": "Section Break",
- "label": "Tax Breakup"
+ "label": "Tax Breakup",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "other_charges_calculation",
@@ -630,14 +754,18 @@
"no_copy": 1,
"oldfieldtype": "HTML",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "totals",
"fieldtype": "Section Break",
"label": "Taxes and Charges",
"oldfieldtype": "Section Break",
- "options": "fa fa-money"
+ "options": "fa fa-money",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "base_taxes_and_charges_added",
@@ -648,7 +776,9 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "base_taxes_and_charges_deducted",
@@ -659,7 +789,9 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "base_total_taxes_and_charges",
@@ -671,11 +803,15 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_39",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "taxes_and_charges_added",
@@ -686,7 +822,9 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "taxes_and_charges_deducted",
@@ -697,7 +835,9 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "total_taxes_and_charges",
@@ -706,14 +846,18 @@
"label": "Total Taxes and Charges",
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "apply_discount_on",
"fieldname": "discount_section",
"fieldtype": "Section Break",
- "label": "Additional Discount"
+ "label": "Additional Discount",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "Grand Total",
@@ -721,7 +865,9 @@
"fieldtype": "Select",
"label": "Apply Additional Discount On",
"options": "\nGrand Total\nNet Total",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_discount_amount",
@@ -729,24 +875,32 @@
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_45",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "additional_discount_percentage",
"fieldtype": "Float",
"label": "Additional Discount Percentage",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Additional Discount Amount",
"options": "currency",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "totals_section",
@@ -762,7 +916,9 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_rounding_adjustment",
@@ -771,7 +927,9 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"description": "In Words will be visible once you save the Purchase Order.",
@@ -782,7 +940,9 @@
"oldfieldname": "in_words",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "base_rounded_total",
@@ -792,12 +952,16 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break4",
"fieldtype": "Column Break",
- "oldfieldtype": "Column Break"
+ "oldfieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "grand_total",
@@ -807,7 +971,9 @@
"oldfieldname": "grand_total_import",
"oldfieldtype": "Currency",
"options": "currency",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "rounding_adjustment",
@@ -816,20 +982,26 @@
"no_copy": 1,
"options": "currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "rounded_total",
"fieldtype": "Currency",
"label": "Rounded Total",
"options": "currency",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "0",
"fieldname": "disable_rounded_total",
"fieldtype": "Check",
- "label": "Disable Rounded Total"
+ "label": "Disable Rounded Total",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "in_words",
@@ -839,7 +1011,9 @@
"oldfieldname": "in_words_import",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "advance_paid",
@@ -848,19 +1022,25 @@
"no_copy": 1,
"options": "party_account_currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "payment_schedule_section",
"fieldtype": "Section Break",
- "label": "Payment Terms"
+ "label": "Payment Terms",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"label": "Payment Terms Template",
- "options": "Payment Terms Template"
+ "options": "Payment Terms Template",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "payment_schedule",
@@ -868,7 +1048,9 @@
"label": "Payment Schedule",
"no_copy": 1,
"options": "Payment Schedule",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -877,7 +1059,9 @@
"fieldtype": "Section Break",
"label": "Terms and Conditions",
"oldfieldtype": "Section Break",
- "options": "fa fa-legal"
+ "options": "fa fa-legal",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "tc_name",
@@ -886,21 +1070,27 @@
"oldfieldname": "tc_name",
"oldfieldtype": "Link",
"options": "Terms and Conditions",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "terms",
"fieldtype": "Text Editor",
"label": "Terms and Conditions",
"oldfieldname": "terms",
- "oldfieldtype": "Text Editor"
+ "oldfieldtype": "Text Editor",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "More Information",
- "oldfieldtype": "Section Break"
+ "oldfieldtype": "Section Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"default": "Draft",
@@ -915,7 +1105,9 @@
"print_hide": 1,
"read_only": 1,
"reqd": 1,
- "search_index": 1
+ "search_index": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "ref_sq",
@@ -926,7 +1118,9 @@
"oldfieldtype": "Data",
"options": "Supplier Quotation",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "party_account_currency",
@@ -936,18 +1130,24 @@
"no_copy": 1,
"options": "Currency",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "inter_company_order_reference",
"fieldtype": "Link",
"label": "Inter Company Order Reference",
"options": "Sales Order",
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_74",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:!doc.__islocal",
@@ -957,7 +1157,9 @@
"label": "% Received",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:!doc.__islocal",
@@ -967,7 +1169,9 @@
"label": "% Billed",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -977,6 +1181,8 @@
"oldfieldtype": "Column Break",
"print_hide": 1,
"print_width": "50%",
+ "show_days": 1,
+ "show_seconds": 1,
"width": "50%"
},
{
@@ -987,7 +1193,9 @@
"oldfieldname": "letter_head",
"oldfieldtype": "Select",
"options": "Letter Head",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -999,11 +1207,15 @@
"oldfieldtype": "Link",
"options": "Print Heading",
"print_hide": 1,
- "report_hide": 1
+ "report_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_86",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1011,19 +1223,25 @@
"fieldname": "group_same_items",
"fieldtype": "Check",
"label": "Group same items",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "language",
"fieldtype": "Data",
"label": "Print Language",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
- "label": "Subscription Section"
+ "label": "Subscription Section",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1031,7 +1249,9 @@
"fieldtype": "Date",
"label": "From Date",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
@@ -1039,11 +1259,15 @@
"fieldtype": "Date",
"label": "To Date",
"no_copy": 1,
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "column_break_97",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "auto_repeat",
@@ -1052,27 +1276,35 @@
"no_copy": 1,
"options": "Auto Repeat",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"allow_on_submit": 1,
"depends_on": "eval: doc.auto_repeat",
"fieldname": "update_auto_repeat_reference",
"fieldtype": "Button",
- "label": "Update Auto Repeat Reference"
+ "label": "Update Auto Repeat Reference",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "tax_category",
"fieldtype": "Link",
"label": "Tax Category",
- "options": "Tax Category"
+ "options": "Tax Category",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "supplied_items",
"fieldname": "set_reserve_warehouse",
"fieldtype": "Link",
"label": "Set Reserve Warehouse",
- "options": "Warehouse"
+ "options": "Warehouse",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"collapsible": 1,
@@ -1082,7 +1314,9 @@
},
{
"fieldname": "column_break_75",
- "fieldtype": "Column Break"
+ "fieldtype": "Column Break",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "billing_address",
@@ -1118,13 +1352,30 @@
"label": "Represents Company",
"options": "Company",
"read_only": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "apply_tds",
+ "fieldtype": "Check",
+ "label": "Apply Tax Withholding Amount",
+ "show_days": 1,
+ "show_seconds": 1
+ },
+ {
+ "depends_on": "eval: doc.apply_tds",
+ "fieldname": "tax_withholding_category",
+ "fieldtype": "Link",
+ "label": "Tax Withholding Category",
+ "options": "Tax Withholding Category",
+ "show_days": 1,
+ "show_seconds": 1
}
],
"icon": "fa fa-file-text",
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2021-01-20 22:07:23.487138",
+ "modified": "2020-11-28 17:42:25.177827",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index ef9372eeb6..782593a5c5 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -17,6 +17,7 @@ from erpnext.accounts.party import get_party_account_currency
from six import string_types
from erpnext.stock.doctype.item.item import get_item_defaults
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
+from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\
unlink_inter_company_doc
@@ -39,11 +40,18 @@ class PurchaseOrder(BuyingController):
'percent_join_field': 'material_request'
}]
+ def onload(self):
+ supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category")
+ self.set_onload("supplier_tds", supplier_tds)
+
def validate(self):
super(PurchaseOrder, self).validate()
self.set_status()
+ # apply tax withholding only if checked and applicable
+ self.set_tax_withholding()
+
self.validate_supplier()
self.validate_schedule_date()
validate_for_items(self)
@@ -87,6 +95,33 @@ class PurchaseOrder(BuyingController):
if cint(frappe.db.get_single_value('Buying Settings', 'maintain_same_rate')):
self.validate_rate_with_reference_doc([["Supplier Quotation", "supplier_quotation", "supplier_quotation_item"]])
+ def set_tax_withholding(self):
+ if not self.apply_tds:
+ return
+
+ tax_withholding_details = get_party_tax_withholding_details(self, self.tax_withholding_category)
+
+ if not tax_withholding_details:
+ return
+
+ accounts = []
+ for d in self.taxes:
+ if d.account_head == tax_withholding_details.get("account_head"):
+ d.update(tax_withholding_details)
+ accounts.append(d.account_head)
+
+ if not accounts or tax_withholding_details.get("account_head") not in accounts:
+ self.append("taxes", tax_withholding_details)
+
+ to_remove = [d for d in self.taxes
+ if not d.tax_amount and d.account_head == tax_withholding_details.get("account_head")]
+
+ for d in to_remove:
+ self.remove(d)
+
+ # calculate totals again after applying TDS
+ self.calculate_taxes_and_totals()
+
def validate_supplier(self):
prevent_po = frappe.db.get_value("Supplier", self.supplier, 'prevent_pos')
if prevent_po:
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index a805dc4e91..da88853a96 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -700,6 +700,7 @@ class AccountsController(TransactionBase):
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
+ self.update_allocated_advance_taxes()
if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'):
unlink_ref_doc_from_payment_entries(self)
@@ -707,6 +708,35 @@ class AccountsController(TransactionBase):
if frappe.db.get_single_value('Accounts Settings', 'unlink_advance_payment_on_cancelation_of_order'):
unlink_ref_doc_from_payment_entries(self)
+ def get_tax_map(self):
+ tax_map = {}
+ for tax in self.get('taxes'):
+ tax_map.setdefault(tax.account_head, 0.0)
+ tax_map[tax.account_head] += tax.tax_amount
+
+ return tax_map
+
+ def update_allocated_advance_taxes(self):
+ if self.get('advances'):
+ tax_accounts = [d.account_head for d in self.get('taxes')]
+ allocated_tax_map = frappe._dict(frappe.get_all('GL Entry', fields=['account', 'sum(credit - debit)'],
+ filters={'voucher_no': self.name, 'account': ('in', tax_accounts)},
+ group_by='account', as_list=1))
+
+ tax_map = self.get_tax_map()
+
+ for pe in self.get('advances'):
+ pe = frappe.get_doc('Payment Entry', pe.reference_name)
+ for tax in pe.get('taxes'):
+ allocated_amount = tax_map.get(tax.account_head) - allocated_tax_map.get(tax.account_head)
+ if allocated_amount > tax.tax_amount:
+ allocated_amount = tax.tax_amount
+
+ if allocated_amount:
+ frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount - allocated_amount)
+ tax_map[tax.account_head] -= allocated_amount
+ allocated_tax_map[tax.account_head] -= allocated_amount
+
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
from erpnext.controllers.status_updater import get_allowance_for
item_allowance = {}
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index f3d7b2635e..a6b54eb590 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -40,7 +40,6 @@ class calculate_taxes_and_totals(object):
self.validate_conversion_rate()
self.calculate_item_values()
self.validate_item_tax_template()
- self.apply_advance_taxes()
self.initialize_taxes()
self.determine_exclusive_rate()
self.calculate_net_total()
@@ -684,33 +683,6 @@ class calculate_taxes_and_totals(object):
self.calculate_paid_amount()
- def apply_advance_taxes(self):
- if cint(self.doc.get('adjust_advance_taxes')):
- if self.doc.get('advances'):
- payment_entry_list = [d.reference_name for d in self.doc.get('advances')]
- advance_taxes = get_advance_taxes(payment_entry_list)
- accounts = []
-
- # Remove already added advance taxes if any
- for tax in self.doc.get('taxes'):
- if tax.is_advance_tax:
- self.doc.remove(tax)
- else:
- accounts.append(tax.account_head)
-
- for tax in advance_taxes:
- # Reverse add deduct from payment entry in invoice
- if tax.account_head in accounts:
- add_deduct_tax = 'Deduct' if tax.add_deduct_tax == 'Add' else 'Add'
- tax.update({
- 'add_deduct_tax': add_deduct_tax,
- 'category': tax.get('category') or 'Total',
- 'is_advance_tax': 1,
- 'charge_type': 'On Net Total' if tax.charge_type == 'On Paid Amount' else tax.charge_type
- })
-
- self.doc.append('taxes', tax)
-
def get_itemised_tax_breakup_html(doc):
if not doc.taxes:
return
From 79b422c0a96f425b4098516b331b5a96d17c5aec Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 28 Feb 2021 18:07:21 +0530
Subject: [PATCH 114/262] fix: Advance TDS in TDS payable monthly report
---
.../doctype/payment_entry/payment_entry.js | 19 ++-
.../doctype/payment_entry/payment_entry.json | 2 +-
.../doctype/payment_entry/payment_entry.py | 26 ++--
.../purchase_invoice/purchase_invoice.py | 2 +-
.../tax_withholding_category.py | 6 +-
.../tds_payable_monthly.js | 41 +++++-
.../tds_payable_monthly.py | 127 ++++++++++++++----
.../purchase_order/purchase_order.json | 2 +-
erpnext/setup/doctype/company/company.js | 2 +-
9 files changed, 175 insertions(+), 52 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 3e11bc0e59..19d73b1ad4 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -93,6 +93,15 @@ frappe.ui.form.on('Payment Entry', {
}
});
+ frm.set_query("advance_tax_account", function() {
+ return {
+ filters: {
+ "company": frm.doc.company,
+ "root_type": ["in", ["Asset", "Liability"]]
+ }
+ }
+ });
+
frm.set_query("reference_doctype", "references", function() {
if (frm.doc.party_type == "Customer") {
var doctypes = ["Sales Order", "Sales Invoice", "Journal Entry", "Dunning"];
@@ -1103,10 +1112,12 @@ frappe.ui.form.on('Payment Entry', {
current_tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
- if(i==0) {
- tax.total = flt(frm.doc.paid_amount + current_tax_amount, precision("total", tax));
- } else {
- tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax));
+ if (!tax.included_in_paid_amount) {
+ if(i==0) {
+ tax.total = flt(frm.doc.paid_amount + current_tax_amount, precision("total", tax));
+ } else {
+ tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax));
+ }
}
tax.base_total = tax.total * frm.doc.source_exchange_rate;
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index ec92db0708..d239c41fd8 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -864,7 +864,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2020-11-29 20:03:57.772062",
+ "modified": "2021-02-27 13:56:20.007336",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 251b581723..33eb6f2f26 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -65,7 +65,7 @@ class PaymentEntry(AccountsController):
self.validate_allocated_amount()
self.validate_paid_invoices()
self.ensure_supplier_is_not_blocked()
- self.validate_advance_tax_account()
+ self.set_advance_tax_account()
self.set_status()
def on_submit(self):
@@ -311,9 +311,13 @@ class PaymentEntry(AccountsController):
+ "
" + _("If this is undesirable please cancel the corresponding Payment Entry."),
title=_("Warning"), indicator="orange")
- def validate_advance_tax_account(self):
+ def set_advance_tax_account(self):
if self.get('taxes') and not self.advance_tax_account:
- frappe.throw(_('Please select advance tax account'))
+ unrealized_profit_loss_account = frappe.db.get_value('Company', self.company, 'unrealized_profit_loss_account')
+ if not unrealized_profit_loss_account:
+ frappe.throw(_("Please select advance tax account or add Unrealized Profit / Loss Account in company master"))
+
+ self.advance_tax_account = unrealized_profit_loss_account
def validate_journal_entry(self):
for d in self.get("references"):
@@ -418,8 +422,10 @@ class PaymentEntry(AccountsController):
net_total = order_amount[0][0]
included_in_paid_amount = 1
+ # Adding args as purchase invoice to get TDS amount
args = frappe._dict({
'company': self.company,
+ 'doctype': 'Purchase Invoice',
'supplier': self.party,
'posting_date': self.posting_date,
'net_total': net_total
@@ -727,7 +733,7 @@ class PaymentEntry(AccountsController):
rev_dr_cr + "_in_account_currency": d.base_tax_amount \
if account_currency==self.company_currency \
else d.tax_amount,
- "cost_center": d.cost_center
+ "cost_center": d.cost_center or self.cost_center
}, account_currency, item=d))
def add_deductions_gl_entries(self, gl_entries):
@@ -830,12 +836,14 @@ class PaymentEntry(AccountsController):
else:
current_tax_amount *= 1.0
- if i == 0:
- tax.total = flt(self.paid_amount + current_tax_amount, self.precision("total", tax))
- else:
- tax.total = flt(self.taxes[i-1].total + current_tax_amount, self.precision("total", tax))
+ if not tax.included_in_paid_amount:
+ if i == 0:
+ tax.total = flt(self.paid_amount + current_tax_amount, self.precision("total", tax))
+ else:
+ tax.total = flt(self.taxes[i-1].total + current_tax_amount, self.precision("total", tax))
+
+ tax.base_total = tax.total * self.source_exchange_rate
- tax.base_total = tax.total * self.source_exchange_rate
self.total_taxes_and_charges += current_tax_amount
self.base_total_taxes_and_charges += current_tax_amount * self.source_exchange_rate
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 8f7248f1e6..5d4796c916 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -935,7 +935,7 @@ class PurchaseInvoice(BuyingController):
rev_dr_cr + "_in_account_currency": unallocated_amount \
if account_currency==self.company_currency \
else unallocated_amount,
- 'cost_center': tax.cost_center
+ 'cost_center': tax.cost_center or self.cost_center
}, account_currency, item=tax))
frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 5c1cbaa4aa..b9ee4a0963 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -49,7 +49,7 @@ def get_party_tax_withholding_details(inv, tax_withholding_category=None):
if not parties:
parties.append(party)
- fiscal_year = get_fiscal_year(inv.posting_date, company=inv.company)
+ fiscal_year = get_fiscal_year(inv.get('posting_date') or inv.get('transaction_date'), company=inv.company)
tax_details = get_tax_withholding_details(tax_withholding_category, fiscal_year[0], inv.company)
if not tax_details:
@@ -154,7 +154,7 @@ def get_tax_amount(party_type, parties, inv, tax_details, fiscal_year_details, p
tax_deducted = get_deducted_tax(taxable_vouchers, fiscal_year, tax_details)
tax_amount = 0
- posting_date = inv.posting_date
+ posting_date = inv.get('posting_date') or inv.get('transaction_date')
if party_type == 'Supplier':
ldc = get_lower_deduction_certificate(fiscal_year, pan_no)
if tax_deducted:
@@ -257,7 +257,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, fiscal_year_details, tax_dedu
if ((threshold and inv.net_total >= threshold) or (cumulative_threshold and supp_credit_amt >= cumulative_threshold)):
if ldc and is_valid_certificate(
ldc.valid_from, ldc.valid_upto,
- inv.posting_date, tax_deducted,
+ inv.get('posting_date') or inv.get('transaction_date'), tax_deducted,
inv.net_total, ldc.certificate_limit
):
tds_amount = get_ltds_amount(supp_credit_amt, 0, ldc.certificate_limit, ldc.rate, tax_details)
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
index 344539eef6..011c29621a 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
@@ -54,6 +54,32 @@ frappe.query_reports["TDS Payable Monthly"] = {
frappe.query_report.refresh();
}
},
+ {
+ "fieldname":"purchase_order",
+ "label": __("Purchase Order"),
+ "fieldtype": "Link",
+ "options": "Purchase Order",
+ "get_query": function() {
+ return {
+ "filters": {
+ "name": ["in", frappe.query_report.invoices]
+ }
+ }
+ },
+ on_change: function() {
+ let supplier = frappe.query_report.get_filter_value('supplier');
+ if(!supplier) return; // return if no supplier selected
+
+ // filter order based on selected supplier
+ let orders = [];
+ frappe.query_report.order_data.map(d => {
+ if(d.supplier==supplier)
+ orders.push(d.name)
+ });
+ frappe.query_report.orders = orders;
+ frappe.query_report.refresh();
+ }
+ },
{
"fieldname":"from_date",
"label": __("From Date"),
@@ -75,15 +101,24 @@ frappe.query_reports["TDS Payable Monthly"] = {
onload: function(report) {
// fetch all tds applied invoices
frappe.call({
- "method": "erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly.get_tds_invoices",
+ "method": "erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly.get_tds_invoices_and_orders",
callback: function(r) {
let invoices = [];
- r.message.map(d => {
+ let orders = [];
+
+ r.message.invoices.map(d => {
invoices.push(d.name);
});
- report["invoice_data"] = r.message;
+ r.message.orders.map(d => {
+ orders.push(d.name);
+ });
+
+ report["invoice_data"] = r.message.invoices;
report["invoices"] = invoices;
+
+ report["order_data"] = r.message.orders;
+ report["invoices"] = orders;
}
});
}
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
index a9fb237a04..7ce61f4a28 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -8,14 +8,18 @@ from frappe.utils import getdate
def execute(filters=None):
filters["invoices"] = frappe.cache().hget("invoices", frappe.session.user)
+ filters["orders"] = frappe.cache().hget("orders", frappe.session.user)
validate_filters(filters)
set_filters(filters)
+ # TDS payment entries
+ payment_entries = get_payment_entires(filters)
+
columns = get_columns(filters)
- if not filters["invoices"]:
+ if not (filters.get("invoices") and filters.get('orders')):
return columns, []
- res = get_result(filters)
+ res = get_result(filters, payment_entries)
return columns, res
@@ -26,9 +30,14 @@ def validate_filters(filters):
def set_filters(filters):
invoices = []
+ orders = []
+
+ if not filters.get("invoices"):
+ filters["invoices"] = get_tds_invoices_and_orders()['invoices']
+
+ if not filters.get("orders"):
+ filters["orders"] = get_tds_invoices_and_orders()['orders']
- if not filters["invoices"]:
- filters["invoices"] = get_tds_invoices()
if filters.supplier and filters.purchase_invoice:
for d in filters["invoices"]:
if d.name == filters.purchase_invoice and d.supplier == filters.supplier:
@@ -42,12 +51,28 @@ def set_filters(filters):
if d.name == filters.purchase_invoice:
invoices.append(d)
+ if filters.supplier and filters.purchase_order:
+ for d in filters.get("orders"):
+ if d.name == filters.purchase_order and d.supplier == filters.supplier:
+ orders.append(d)
+ elif filters.supplier and not filters.purchase_order:
+ for d in filters.get("orders"):
+ if d.supplier == filters.supplier:
+ orders.append(d)
+ elif filters.purchase_order and not filters.supplier:
+ for d in filters.get("invoices"):
+ if d.name == filters.purchase_order:
+ orders.append(d)
+
filters["invoices"] = invoices if invoices else filters["invoices"]
+ filters["orders"] = orders if orders else filters["orders"]
filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name')
-def get_result(filters):
- supplier_map, tds_docs = get_supplier_map(filters)
- gle_map = get_gle_map(filters)
+def get_result(filters, payment_entries):
+ supplier_map, tds_docs = get_supplier_map(filters, payment_entries)
+ documents = [d.get('name') for d in filters.get('invoices')] + [d.get('name') for d in payment_entries]
+
+ gle_map = get_gle_map(filters, documents)
out = []
for d in gle_map:
@@ -62,10 +87,11 @@ def get_result(filters):
for k in gle_map[d]:
if k.party == supplier_map[d] and k.credit > 0:
- total_amount_credited += k.credit
- elif account_list and k.account == account and k.credit > 0:
- tds_deducted = k.credit
- total_amount_credited += k.credit
+ total_amount_credited += (k.credit - k.debit)
+ elif account_list and k.account == account and (k.credit - k.debit) > 0:
+ tds_deducted = (k.credit - k.debit)
+ total_amount_credited += (k.credit - k.debit)
+ voucher_type = k.voucher_type
rate = [i.tax_withholding_rate for i in tds_doc.rates
if i.fiscal_year == gle_map[d][0].fiscal_year]
@@ -73,32 +99,40 @@ def get_result(filters):
if rate and len(rate) > 0 and tds_deducted:
rate = rate[0]
- if getdate(filters.from_date) <= gle_map[d][0].posting_date \
- and getdate(filters.to_date) >= gle_map[d][0].posting_date:
- row = [supplier.pan, supplier.name]
+ row = [supplier.pan, supplier.name]
- if filters.naming_series == 'Naming Series':
- row.append(supplier.supplier_name)
+ if filters.naming_series == 'Naming Series':
+ row.append(supplier.supplier_name)
- row.extend([tds_doc.name, supplier.supplier_type, rate, total_amount_credited,
- tds_deducted, gle_map[d][0].posting_date, "Purchase Invoice", d])
- out.append(row)
+ row.extend([tds_doc.name, supplier.supplier_type, rate, total_amount_credited,
+ tds_deducted, gle_map[d][0].posting_date, voucher_type, d])
+ out.append(row)
return out
-def get_supplier_map(filters):
+def get_supplier_map(filters, payment_entries):
# create a supplier_map of the form {"purchase_invoice": {supplier_name, pan, tds_name}}
# pre-fetch all distinct applicable tds docs
supplier_map, tds_docs = {}, {}
pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id"
+ supplier_list = [d.supplier for d in filters["invoices"]] + [d.supplier for d in filters["orders"]]
+
supplier_detail = frappe.db.get_all('Supplier',
- {"name": ["in", [d.supplier for d in filters["invoices"]]]},
+ {"name": ["in", supplier_list]},
["tax_withholding_category", "name", pan+" as pan", "supplier_type", "supplier_name"])
for d in filters["invoices"]:
supplier_map[d.get("name")] = [k for k in supplier_detail
if k.name == d.get("supplier")][0]
+ for d in filters["orders"]:
+ supplier_map[d.get("name")] = [k for k in supplier_detail
+ if k.name == d.get("supplier")][0]
+
+ for d in payment_entries:
+ supplier_map[d.get("name")] = [k for k in supplier_detail
+ if k.name == d.get("supplier")][0]
+
for d in supplier_detail:
if d.get("tax_withholding_category") not in tds_docs:
tds_docs[d.get("tax_withholding_category")] = \
@@ -106,13 +140,19 @@ def get_supplier_map(filters):
return supplier_map, tds_docs
-def get_gle_map(filters):
+def get_gle_map(filters, documents):
# create gle_map of the form
# {"purchase_invoice": list of dict of all gle created for this invoice}
gle_map = {}
- gle = frappe.db.get_all('GL Entry',\
- {"voucher_no": ["in", [d.get("name") for d in filters["invoices"]]], 'is_cancelled': 0},
- ["fiscal_year", "credit", "debit", "account", "voucher_no", "posting_date"])
+ filter_obj = {}
+ gle = frappe.db.get_all('GL Entry',
+ {
+ "voucher_no": ["in", documents],
+ 'is_cancelled': 0,
+ 'posting_date': ("between", [filters.get('from_date'), filters.get('to_date')]),
+ },
+ ["fiscal_year", "credit", "debit", "account", "voucher_no", "posting_date", "voucher_type"],
+ )
for d in gle:
if not d.voucher_no in gle_map:
@@ -201,8 +241,28 @@ def get_columns(filters):
return columns
+def get_payment_entires(filters):
+ filter_dict = {
+ 'posting_date': ("between", [filters.get('from_date'), filters.get('to_date')]),
+ 'party_type': 'Supplier',
+ 'apply_tax_withholding_amount': 1
+ }
+
+ if filters.get('purchase_order') or filters.get('purchase_invoice'):
+ parent = frappe.db.get_all('Payment Entry Reference',
+ {
+ 'reference_name': ('in', [d.get('name') for d in filters.get('orders')] +
+ [d.get('name') for d in filters.get('invoices')])
+ }, ['parent'])
+ filter_dict.update({'name': ('in', [d.get('parent') for d in parent])})
+
+ payment_entries = frappe.get_all('Payment Entry', fields=['name', 'party_name as supplier'],
+ filters=filter_dict)
+
+ return payment_entries
+
@frappe.whitelist()
-def get_tds_invoices():
+def get_tds_invoices_and_orders():
# fetch tds applicable supplier and fetch invoices for these suppliers
suppliers = [d.name for d in frappe.db.get_list("Supplier",
{"tax_withholding_category": ["!=", ""]}, ["name"])]
@@ -210,7 +270,16 @@ def get_tds_invoices():
invoices = frappe.db.get_list("Purchase Invoice",
{"supplier": ["in", suppliers]}, ["name", "supplier"])
- invoices = [d for d in invoices if d.supplier]
- frappe.cache().hset("invoices", frappe.session.user, invoices)
+ orders = frappe.db.get_list("Purchase Order",
+ {"supplier": ["in", suppliers]}, ["name", "supplier"])
- return invoices
+ invoices = [d for d in invoices if d.supplier]
+ orders = [d for d in orders if d.supplier]
+
+ frappe.cache().hset("invoices", frappe.session.user, invoices)
+ frappe.cache().hset("orders", frappe.session.user, invoices)
+
+ return {
+ 'invoices': invoices,
+ 'orders': orders
+ }
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 64eda5f280..47ec212b12 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1375,7 +1375,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2020-11-28 17:42:25.177827",
+ "modified": "2021-02-27 22:07:23.487138",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js
index 9957aad019..9dc7fc42ef 100644
--- a/erpnext/setup/doctype/company/company.js
+++ b/erpnext/setup/doctype/company/company.js
@@ -276,7 +276,7 @@ erpnext.company.setup_queries = function(frm) {
["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}],
- ["unrealized_profit_loss_account", {"root_type": "Liability"},]
+ ["unrealized_profit_loss_account", {"root_type": ["in", ["Liability", "Asset"]]}]
], function(i, v) {
erpnext.company.set_custom_query(frm, v);
});
From a87e3fcb7c5ddd476fa492b5c22f18f2ba79556e Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 28 Feb 2021 23:28:25 +0530
Subject: [PATCH 115/262] fix: TDS report cleanup
---
.../doctype/payment_entry/payment_entry.py | 5 +-
.../purchase_invoice/purchase_invoice.json | 21 +++++---
.../tds_payable_monthly.js | 19 +++-----
.../tds_payable_monthly.py | 48 +++++++------------
4 files changed, 42 insertions(+), 51 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 33eb6f2f26..c0feb44a7f 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -967,7 +967,7 @@ def split_invoices_based_on_payment_terms(outstanding_invoices):
outstanding_invoices.pop(idx - 1)
outstanding_invoices += invoice_ref_based_on_payment_terms[idx]
-
+
return outstanding_invoices
def get_orders_to_be_billed(posting_date, party_type, party,
@@ -1411,6 +1411,9 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
})
pe.set_difference_amount()
+ if doc.doctype == 'Purchase Order' and doc.apply_tds:
+ pe.apply_tax_withholding_amount = 1
+
return pe
def get_bank_cash_account(doc, bank_account):
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 36450a9255..7fef60cde1 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -127,7 +127,6 @@
"write_off_cost_center",
"advances_section",
"allocate_advances_automatically",
- "adjust_advance_taxes",
"get_advances",
"advances",
"payment_schedule_section",
@@ -1492,7 +1491,9 @@
"in_standard_filter": 1,
"label": "Status",
"options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled\nInternal Transfer",
- "print_hide": 1
+ "print_hide": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "inter_company_invoice_reference",
@@ -1501,7 +1502,9 @@
"no_copy": 1,
"options": "Sales Invoice",
"print_hide": 1,
- "read_only": 1
+ "read_only": 1,
+ "show_days": 1,
+ "show_seconds": 1
},
{
"fieldname": "remarks",
@@ -1633,7 +1636,9 @@
"fieldname": "unrealized_profit_loss_account",
"fieldtype": "Link",
"label": "Unrealized Profit / Loss Account",
- "options": "Account"
+ "options": "Account",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.is_internal_supplier",
@@ -1642,7 +1647,9 @@
"fieldname": "represents_company",
"fieldtype": "Link",
"label": "Represents Company",
- "options": "Company"
+ "options": "Company",
+ "show_days": 1,
+ "show_seconds": 1
},
{
"depends_on": "eval:doc.update_stock && doc.is_internal_supplier",
@@ -1654,6 +1661,8 @@
"options": "Warehouse",
"print_hide": 1,
"print_width": "50px",
+ "show_days": 1,
+ "show_seconds": 1,
"width": "50px"
},
{
@@ -1681,7 +1690,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2020-10-27 21:21:22.647349",
+ "modified": "2021-02-28 22:33:15.728392",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
index 011c29621a..72de318a48 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js
@@ -70,13 +70,13 @@ frappe.query_reports["TDS Payable Monthly"] = {
let supplier = frappe.query_report.get_filter_value('supplier');
if(!supplier) return; // return if no supplier selected
- // filter order based on selected supplier
- let orders = [];
- frappe.query_report.order_data.map(d => {
+ // filter invoices based on selected supplier
+ let invoices = [];
+ frappe.query_report.invoice_data.map(d => {
if(d.supplier==supplier)
- orders.push(d.name)
+ invoices.push(d.name)
});
- frappe.query_report.orders = orders;
+ frappe.query_report.invoices = invoices;
frappe.query_report.refresh();
}
},
@@ -104,21 +104,14 @@ frappe.query_reports["TDS Payable Monthly"] = {
"method": "erpnext.accounts.report.tds_payable_monthly.tds_payable_monthly.get_tds_invoices_and_orders",
callback: function(r) {
let invoices = [];
- let orders = [];
- r.message.invoices.map(d => {
+ r.message.map(d => {
invoices.push(d.name);
});
- r.message.orders.map(d => {
- orders.push(d.name);
- });
-
report["invoice_data"] = r.message.invoices;
report["invoices"] = invoices;
- report["order_data"] = r.message.orders;
- report["invoices"] = orders;
}
});
}
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
index 7ce61f4a28..5101e3d752 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -8,7 +8,6 @@ from frappe.utils import getdate
def execute(filters=None):
filters["invoices"] = frappe.cache().hget("invoices", frappe.session.user)
- filters["orders"] = frappe.cache().hget("orders", frappe.session.user)
validate_filters(filters)
set_filters(filters)
@@ -16,7 +15,7 @@ def execute(filters=None):
payment_entries = get_payment_entires(filters)
columns = get_columns(filters)
- if not (filters.get("invoices") and filters.get('orders')):
+ if not filters.get("invoices"):
return columns, []
res = get_result(filters, payment_entries)
@@ -30,13 +29,9 @@ def validate_filters(filters):
def set_filters(filters):
invoices = []
- orders = []
if not filters.get("invoices"):
- filters["invoices"] = get_tds_invoices_and_orders()['invoices']
-
- if not filters.get("orders"):
- filters["orders"] = get_tds_invoices_and_orders()['orders']
+ filters["invoices"] = get_tds_invoices_and_orders()
if filters.supplier and filters.purchase_invoice:
for d in filters["invoices"]:
@@ -50,24 +45,25 @@ def set_filters(filters):
for d in filters["invoices"]:
if d.name == filters.purchase_invoice:
invoices.append(d)
-
- if filters.supplier and filters.purchase_order:
- for d in filters.get("orders"):
+ elif filters.supplier and filters.purchase_order:
+ for d in filters.get("invoices"):
if d.name == filters.purchase_order and d.supplier == filters.supplier:
- orders.append(d)
+ invoices.append(d)
elif filters.supplier and not filters.purchase_order:
- for d in filters.get("orders"):
+ for d in filters.get("invoices"):
if d.supplier == filters.supplier:
- orders.append(d)
+ invoices.append(d)
elif filters.purchase_order and not filters.supplier:
for d in filters.get("invoices"):
if d.name == filters.purchase_order:
- orders.append(d)
+ print("$#$#$$#")
+ invoices.append(d)
filters["invoices"] = invoices if invoices else filters["invoices"]
- filters["orders"] = orders if orders else filters["orders"]
filters.naming_series = frappe.db.get_single_value('Buying Settings', 'supp_master_name')
+ #print(filters.get('invoices'))
+
def get_result(filters, payment_entries):
supplier_map, tds_docs = get_supplier_map(filters, payment_entries)
documents = [d.get('name') for d in filters.get('invoices')] + [d.get('name') for d in payment_entries]
@@ -115,7 +111,7 @@ def get_supplier_map(filters, payment_entries):
# pre-fetch all distinct applicable tds docs
supplier_map, tds_docs = {}, {}
pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id"
- supplier_list = [d.supplier for d in filters["invoices"]] + [d.supplier for d in filters["orders"]]
+ supplier_list = [d.supplier for d in filters["invoices"]]
supplier_detail = frappe.db.get_all('Supplier',
{"name": ["in", supplier_list]},
@@ -125,10 +121,6 @@ def get_supplier_map(filters, payment_entries):
supplier_map[d.get("name")] = [k for k in supplier_detail
if k.name == d.get("supplier")][0]
- for d in filters["orders"]:
- supplier_map[d.get("name")] = [k for k in supplier_detail
- if k.name == d.get("supplier")][0]
-
for d in payment_entries:
supplier_map[d.get("name")] = [k for k in supplier_detail
if k.name == d.get("supplier")][0]
@@ -248,12 +240,10 @@ def get_payment_entires(filters):
'apply_tax_withholding_amount': 1
}
- if filters.get('purchase_order') or filters.get('purchase_invoice'):
+ if filters.get('purchase_invoice') or filters.get('purchase_order'):
parent = frappe.db.get_all('Payment Entry Reference',
- {
- 'reference_name': ('in', [d.get('name') for d in filters.get('orders')] +
- [d.get('name') for d in filters.get('invoices')])
- }, ['parent'])
+ { 'reference_name': ('in', [d.get('name') for d in filters.get('invoices')])}, ['parent'])
+
filter_dict.update({'name': ('in', [d.get('parent') for d in parent])})
payment_entries = frappe.get_all('Payment Entry', fields=['name', 'party_name as supplier'],
@@ -273,13 +263,9 @@ def get_tds_invoices_and_orders():
orders = frappe.db.get_list("Purchase Order",
{"supplier": ["in", suppliers]}, ["name", "supplier"])
+ invoices = invoices + orders
invoices = [d for d in invoices if d.supplier]
- orders = [d for d in orders if d.supplier]
frappe.cache().hset("invoices", frappe.session.user, invoices)
- frappe.cache().hset("orders", frappe.session.user, invoices)
- return {
- 'invoices': invoices,
- 'orders': orders
- }
+ return invoices
From fd380d34f99b70616cfa06fb6ce30cdccce931fe Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 13 May 2021 14:04:51 +0530
Subject: [PATCH 116/262] fix: Linting errors
---
.../doctype/payment_entry/payment_entry.py | 17 +++---
.../purchase_invoice/purchase_invoice.py | 8 +--
.../doctype/sales_invoice/sales_invoice.py | 8 +--
.../tds_payable_monthly.py | 4 +-
erpnext/public/js/controllers/accounts.js | 12 ++--
erpnext/public/js/payment/payments.js | 56 +++++++++----------
6 files changed, 52 insertions(+), 53 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index c0feb44a7f..736048fe3e 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -516,13 +516,13 @@ class PaymentEntry(AccountsController):
if self.payment_type == "Receive" \
and self.base_total_allocated_amount < self.base_received_amount_after_tax + total_deductions \
and self.total_allocated_amount < self.paid_amount_after_tax + (total_deductions / self.source_exchange_rate):
- self.unallocated_amount = (self.received_amount_after_tax + total_deductions -
- self.base_total_allocated_amount) / self.source_exchange_rate
+ self.unallocated_amount = (self.received_amount_after_tax + total_deductions -
+ self.base_total_allocated_amount) / self.source_exchange_rate
elif self.payment_type == "Pay" \
and self.base_total_allocated_amount < (self.base_paid_amount_after_tax - total_deductions) \
and self.total_allocated_amount < self.received_amount_after_tax + (total_deductions / self.target_exchange_rate):
- self.unallocated_amount = (self.base_paid_amount_after_tax - (total_deductions +
- self.base_total_allocated_amount)) / self.target_exchange_rate
+ self.unallocated_amount = (self.base_paid_amount_after_tax - (total_deductions +
+ self.base_total_allocated_amount)) / self.target_exchange_rate
def set_difference_amount(self):
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
@@ -719,8 +719,8 @@ class PaymentEntry(AccountsController):
"account": d.account_head,
"against": self.party if self.payment_type=="Receive" else self.paid_from,
dr_or_cr: d.base_tax_amount,
- dr_or_cr + "_in_account_currency": d.base_tax_amount \
- if account_currency==self.company_currency \
+ dr_or_cr + "_in_account_currency": d.base_tax_amount
+ if account_currency==self.company_currency
else d.tax_amount,
"cost_center": d.cost_center
}, account_currency, item=d))
@@ -730,8 +730,8 @@ class PaymentEntry(AccountsController):
"account": self.advance_tax_account,
"against": self.party if self.payment_type=="Receive" else self.paid_from,
rev_dr_cr: d.base_tax_amount,
- rev_dr_cr + "_in_account_currency": d.base_tax_amount \
- if account_currency==self.company_currency \
+ rev_dr_cr + "_in_account_currency": d.base_tax_amount
+ if account_currency==self.company_currency
else d.tax_amount,
"cost_center": d.cost_center or self.cost_center
}, account_currency, item=d))
@@ -806,7 +806,6 @@ class PaymentEntry(AccountsController):
for i, tax in enumerate(self.taxes):
tax_rate = tax.rate
- current_tax_rate = 0.0
# To set row_id by default as previous row.
if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"]:
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 5d4796c916..83c55cc653 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -921,8 +921,8 @@ class PurchaseInvoice(BuyingController):
"account": tax.account_head,
"against": self.supplier,
dr_or_cr: unallocated_amount,
- dr_or_cr + "_in_account_currency": unallocated_amount \
- if account_currency==self.company_currency \
+ dr_or_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
else unallocated_amount,
'cost_center': tax.cost_center
}, account_currency, item=tax))
@@ -932,8 +932,8 @@ class PurchaseInvoice(BuyingController):
"account": pe.advance_tax_account,
"against": self.supplier,
rev_dr_cr: unallocated_amount,
- rev_dr_cr + "_in_account_currency": unallocated_amount \
- if account_currency==self.company_currency \
+ rev_dr_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
else unallocated_amount,
'cost_center': tax.cost_center or self.cost_center
}, account_currency, item=tax))
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 9af94fd780..44b8325c62 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -933,8 +933,8 @@ class SalesInvoice(SellingController):
"account": tax.account_head,
"against": self.customer,
dr_or_cr: unallocated_amount,
- dr_or_cr + "_in_account_currency": unallocated_amount \
- if account_currency==self.company_currency \
+ dr_or_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
else unallocated_amount,
'cost_center': tax.cost_center
}, account_currency, item=tax))
@@ -944,8 +944,8 @@ class SalesInvoice(SellingController):
"account": pe.advance_tax_account,
"against": self.customer,
rev_dr_cr: unallocated_amount,
- rev_dr_cr + "_in_account_currency": unallocated_amount \
- if account_currency==self.company_currency \
+ rev_dr_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
else unallocated_amount,
'cost_center': tax.cost_center
}, account_currency, item=tax))
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
index 5101e3d752..619d799d06 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -136,7 +136,7 @@ def get_gle_map(filters, documents):
# create gle_map of the form
# {"purchase_invoice": list of dict of all gle created for this invoice}
gle_map = {}
- filter_obj = {}
+
gle = frappe.db.get_all('GL Entry',
{
"voucher_no": ["in", documents],
@@ -242,7 +242,7 @@ def get_payment_entires(filters):
if filters.get('purchase_invoice') or filters.get('purchase_order'):
parent = frappe.db.get_all('Payment Entry Reference',
- { 'reference_name': ('in', [d.get('name') for d in filters.get('invoices')])}, ['parent'])
+ {'reference_name': ('in', [d.get('name') for d in filters.get('invoices')])}, ['parent'])
filter_dict.update({'name': ('in', [d.get('parent') for d in parent])})
diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js
index 23d636061c..7b997a1153 100644
--- a/erpnext/public/js/controllers/accounts.js
+++ b/erpnext/public/js/controllers/accounts.js
@@ -156,31 +156,31 @@ cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) {
var d = locals[cdt][cdn];
var msg = "";
- if(d.account_head && !d.description) {
+ if (d.account_head && !d.description) {
// set description from account head
d.description = d.account_head.split(' - ').slice(0, -1).join(' - ');
}
- if(!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
+ if (!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
msg = __("Please select Charge Type first");
d.row_id = "";
d.rate = d.tax_amount = 0.0;
- } else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total' || d.charge_type == 'On Paid Amount') && d.row_id) {
+ } else if ((d.charge_type == 'Actual' || d.charge_type == 'On Net Total' || d.charge_type == 'On Paid Amount') && d.row_id) {
msg = __("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'");
d.row_id = "";
- } else if((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) {
+ } else if ((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) {
if (d.idx == 1) {
msg = __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row");
d.charge_type = '';
} else if (!d.row_id) {
msg = __("Please specify a valid Row ID for row {0} in table {1}", [d.idx, __(d.doctype)]);
d.row_id = "";
- } else if(d.row_id && d.row_id >= d.idx) {
+ } else if (d.row_id && d.row_id >= d.idx) {
msg = __("Cannot refer row number greater than or equal to current row number for this Charge type");
d.row_id = "";
}
}
- if(msg) {
+ if (msg) {
frappe.validated = false;
refresh_field("taxes");
frappe.throw(msg);
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index b168952e40..e2bd602ba7 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -16,14 +16,14 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.select_text()
},
- select_text: function(){
+ select_text: function() {
var me = this;
- $(this.$body).find('.form-control').click(function(){
+ $(this.$body).find('.form-control').click(function() {
$(this).select();
})
},
- set_payment_primary_action: function(){
+ set_payment_primary_action: function() {
var me = this;
this.dialog.set_primary_action(__("Submit"), function() {
@@ -38,7 +38,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
})
},
- make_keyboard: function(){
+ make_keyboard: function() {
var me = this;
$(this.$body).empty();
$(this.$body).html(frappe.render_template('pos_payment', this.frm.doc))
@@ -47,10 +47,10 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.clear_amount()
},
- make_multimode_payment: function(){
+ make_multimode_payment: function() {
var me = this;
- if(this.frm.doc.change_amount > 0){
+ if(this.frm.doc.change_amount > 0) {
me.payment_val = me.doc.outstanding_amount
}
@@ -59,7 +59,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.payments.amount = flt(this.payment_val);
},
- show_payment_details: function(){
+ show_payment_details: function() {
var me = this;
var multimode_payments = $(this.$body).find('.multimode-payments').empty();
if(this.frm.doc.payments.length){
@@ -84,7 +84,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
}
},
- set_outstanding_amount: function(){
+ set_outstanding_amount: function() {
this.selected_mode = $(this.$body).find(repl("input[idx='%(idx)s']",{'idx': this.idx}));
this.highlight_selected_row()
this.payment_val = 0.0
@@ -101,45 +101,45 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.bind_amount_change_event();
},
- bind_keyboard_event: function(){
+ bind_keyboard_event: function() {
var me = this;
this.payment_val = '';
this.bind_form_control_event();
this.bind_numeric_keys_event();
},
- bind_form_control_event: function(){
+ bind_form_control_event: function() {
var me = this;
- $(this.$body).find('.pos-payment-row').click(function(){
+ $(this.$body).find('.pos-payment-row').click(function() {
me.idx = $(this).attr("idx");
me.set_outstanding_amount()
- })
+ });
- $(this.$body).find('.form-control').click(function(){
+ $(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(){
+ $(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(){
+ $(this.$body).find('.change_amount').change(function() {
me.change_amount(flt($(this).val()), precision("change_amount"));
- })
+ });
},
- highlight_selected_row: function(){
+ highlight_selected_row: function() {
var me = this;
- var selected_row = $(this.$body).find(repl(".pos-payment-row[idx='%(idx)s']",{'idx': this.idx}));
+ 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: function(){
+ bind_numeric_keys_event: function() {
var me = this;
$(this.$body).find('.pos-keyboard-key').click(function(){
me.payment_val += $(this).text();
@@ -148,7 +148,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
me.update_paid_amount()
})
- $(this.$body).find('.delete-btn').click(function(){
+ $(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")
@@ -157,9 +157,9 @@ erpnext.payments = erpnext.stock.StockController.extend({
},
- bind_amount_change_event: function(){
+ bind_amount_change_event: function() {
var me = this;
- this.selected_mode.change(function(){
+ 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")
@@ -169,7 +169,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
clear_amount: function() {
var me = this;
- $(this.$body).find('.clr').click(function(e){
+ $(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}));
@@ -215,10 +215,10 @@ erpnext.payments = erpnext.stock.StockController.extend({
}
},
- update_payment_amount: function(){
+ update_payment_amount: function() {
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)
}
@@ -228,7 +228,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.show_amounts();
},
- show_amounts: function(){
+ show_amounts: function() {
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));
From 77dcee9d677c3f1833c213c50a9369c373991589 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 16 May 2021 17:45:45 +0530
Subject: [PATCH 117/262] fix: Test Cases
---
.../doctype/payment_entry/payment_entry.py | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 736048fe3e..ac8e7070f5 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -482,7 +482,7 @@ class PaymentEntry(AccountsController):
self.received_amount_after_tax = flt(flt(self.received_amount) + flt(applicable_tax),
self.precision("paid_amount_after_tax"))
- self.base_received_amount_after_tax = flt(flt(self.received_amount_after_tax) * flt(self.source_exchange_rate),
+ self.base_received_amount_after_tax = flt(flt(self.received_amount_after_tax) * flt(self.target_exchange_rate),
self.precision("base_paid_amount_after_tax"))
def set_amounts_in_company_currency(self):
@@ -720,8 +720,8 @@ class PaymentEntry(AccountsController):
"against": self.party if self.payment_type=="Receive" else self.paid_from,
dr_or_cr: d.base_tax_amount,
dr_or_cr + "_in_account_currency": d.base_tax_amount
- if account_currency==self.company_currency
- else d.tax_amount,
+ if account_currency==self.company_currency
+ else d.tax_amount,
"cost_center": d.cost_center
}, account_currency, item=d))
@@ -731,8 +731,8 @@ class PaymentEntry(AccountsController):
"against": self.party if self.payment_type=="Receive" else self.paid_from,
rev_dr_cr: d.base_tax_amount,
rev_dr_cr + "_in_account_currency": d.base_tax_amount
- if account_currency==self.company_currency
- else d.tax_amount,
+ if account_currency==self.company_currency
+ else d.tax_amount,
"cost_center": d.cost_center or self.cost_center
}, account_currency, item=d))
@@ -804,7 +804,7 @@ class PaymentEntry(AccountsController):
self.total_taxes_and_charges = 0.0
self.base_total_taxes_and_charges = 0.0
- for i, tax in enumerate(self.taxes):
+ for i, tax in enumerate(self.get('taxes')):
tax_rate = tax.rate
# To set row_id by default as previous row.
@@ -821,11 +821,11 @@ class PaymentEntry(AccountsController):
current_tax_amount = (tax_rate / 100.0) * self.paid_amount
elif tax.charge_type == "On Previous Row Amount":
current_tax_amount = (tax_rate / 100.0) * \
- self.taxes[cint(tax.row_id) - 1].tax_amount
+ self.get('taxes')[cint(tax.row_id) - 1].tax_amount
elif tax.charge_type == "On Previous Row Total":
current_tax_amount = (tax_rate / 100.0) * \
- self.taxes[cint(tax.row_id) - 1].total
+ self.get('taxes')[cint(tax.row_id) - 1].total
tax.tax_amount = current_tax_amount
tax.base_tax_amount = tax.tax_amount * self.source_exchange_rate
@@ -839,7 +839,7 @@ class PaymentEntry(AccountsController):
if i == 0:
tax.total = flt(self.paid_amount + current_tax_amount, self.precision("total", tax))
else:
- tax.total = flt(self.taxes[i-1].total + current_tax_amount, self.precision("total", tax))
+ tax.total = flt(self.get('taxes')[i-1].total + current_tax_amount, self.precision("total", tax))
tax.base_total = tax.total * self.source_exchange_rate
From e2f83ffaa4c5770210fedb8ec22d433fb21378b3 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 16 May 2021 17:46:07 +0530
Subject: [PATCH 118/262] fix: Linting fixes and other checks
---
.../doctype/payment_entry/payment_entry.json | 2 +-
.../purchase_invoice/purchase_invoice.py | 31 +++++-----
.../doctype/sales_invoice/sales_invoice.py | 8 +--
.../doctype/purchase_order/purchase_order.js | 4 +-
erpnext/public/js/payment/payments.js | 62 +++++++++----------
5 files changed, 53 insertions(+), 54 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index d239c41fd8..afc72045e6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -864,7 +864,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-02-27 13:56:20.007336",
+ "modified": "2021-05-15 13:05:16.958866",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 83c55cc653..a4bac3550d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -251,11 +251,9 @@ class PurchaseInvoice(BuyingController):
if self.update_stock and (not item.from_warehouse):
if for_validate and item.expense_account and item.expense_account != warehouse_account[item.warehouse]["account"]:
- msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(warehouse_account[item.warehouse]["account"]))
- msg += _("because account {} is not linked to warehouse {} ").format(frappe.bold(item.expense_account), frappe.bold(item.warehouse))
- msg += _("or it is not the default inventory account")
+ msg = _("Row {0}: Expense Head changed to {1} because account {2} is not linked to warehouse {3} or it is not the default inventory account").format(
+ item.idx, frappe.bold(warehouse_account[item.warehouse]["account"]), frappe.bold(item.expense_account), frappe.bold(item.warehouse))
frappe.msgprint(msg, title=_("Expense Head Changed"))
-
item.expense_account = warehouse_account[item.warehouse]["account"]
else:
# check if 'Stock Received But Not Billed' account is credited in Purchase receipt or not
@@ -266,8 +264,8 @@ class PurchaseInvoice(BuyingController):
if negative_expense_booked_in_pr:
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
- msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(stock_not_billed_account))
- msg += _("because expense is booked against this account in Purchase Receipt {}").format(frappe.bold(item.purchase_receipt))
+ msg = _("Row {0}: Expense Head changed to {1} because expense is booked against this account in Purchase Receipt {2}").format(
+ item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.purchase_receipt))
frappe.msgprint(msg, title=_("Expense Head Changed"))
item.expense_account = stock_not_billed_account
@@ -275,8 +273,9 @@ class PurchaseInvoice(BuyingController):
# If no purchase receipt present then book expense in 'Stock Received But Not Billed'
# This is done in cases when Purchase Invoice is created before Purchase Receipt
if for_validate and item.expense_account and item.expense_account != stock_not_billed_account:
- msg = _("Row {}: Expense Head changed to {} ").format(item.idx, frappe.bold(stock_not_billed_account))
- msg += _("as no Purchase Receipt is created against Item {}. ").format(frappe.bold(item.item_code))
+ msg = _("Row {0}: Expense Head changed to {1} as no Purchase Receipt is created against Item {2}.").format(
+ item.idx, frappe.bold(stock_not_billed_account), frappe.bold(item.item_code))
+ msg += "
"
msg += _("This is done to handle accounting for cases when Purchase Receipt is created after Purchase Invoice")
frappe.msgprint(msg, title=_("Expense Head Changed"))
@@ -308,8 +307,8 @@ class PurchaseInvoice(BuyingController):
if not d.purchase_order:
msg = _("Purchase Order Required for item {}").format(frappe.bold(d.item_code))
msg += "
"
- msg += _("To submit the invoice without purchase order please set {} ").format(frappe.bold(_('Purchase Order Required')))
- msg += _("as {} in {}").format(frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
+ msg += _("To submit the invoice without purchase order please set {0} as {1} in {2}").format(
+ frappe.bold(_('Purchase Order Required')), frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
throw(msg, title=_("Mandatory Purchase Order"))
def pr_required(self):
@@ -323,8 +322,8 @@ class PurchaseInvoice(BuyingController):
if not d.purchase_receipt and d.item_code in stock_items:
msg = _("Purchase Receipt Required for item {}").format(frappe.bold(d.item_code))
msg += "
"
- msg += _("To submit the invoice without purchase receipt please set {} ").format(frappe.bold(_('Purchase Receipt Required')))
- msg += _("as {} in {}").format(frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
+ msg += _("To submit the invoice without purchase receipt please set {0} as {1} in {2}").format(
+ frappe.bold(_('Purchase Receipt Required')), frappe.bold('No'), get_link_to_form('Buying Settings', 'Buying Settings', 'Buying Settings'))
throw(msg, title=_("Mandatory Purchase Receipt"))
def validate_write_off_account(self):
@@ -922,8 +921,8 @@ class PurchaseInvoice(BuyingController):
"against": self.supplier,
dr_or_cr: unallocated_amount,
dr_or_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
+ if account_currency==self.company_currency
+ else unallocated_amount,
'cost_center': tax.cost_center
}, account_currency, item=tax))
@@ -933,8 +932,8 @@ class PurchaseInvoice(BuyingController):
"against": self.supplier,
rev_dr_cr: unallocated_amount,
rev_dr_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
+ if account_currency==self.company_currency
+ else unallocated_amount,
'cost_center': tax.cost_center or self.cost_center
}, account_currency, item=tax))
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 44b8325c62..9a596f2b32 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -934,8 +934,8 @@ class SalesInvoice(SellingController):
"against": self.customer,
dr_or_cr: unallocated_amount,
dr_or_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
+ if account_currency==self.company_currency
+ else unallocated_amount,
'cost_center': tax.cost_center
}, account_currency, item=tax))
@@ -945,8 +945,8 @@ class SalesInvoice(SellingController):
"against": self.customer,
rev_dr_cr: unallocated_amount,
rev_dr_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
+ if account_currency==self.company_currency
+ else unallocated_amount,
'cost_center': tax.cost_center
}, account_currency, item=tax))
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 139aa72c08..ccb3ce33ec 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -321,7 +321,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if(me.values) {
me.values.sub_con_rm_items.map((row,i) => {
if (!row.item_code || !row.rm_item_code || !row.warehouse || !row.qty || row.qty === 0) {
- frappe.throw(__("Item Code, warehouse, quantity are required on row {0}", [i+1]));
+ frappe.throw(__("Item Code and warehouse and quantity are required on row {0}", [i+1]));
}
})
me._make_rm_stock_entry(me.dialog.fields_dict.sub_con_rm_items.grid.get_selected_children())
@@ -517,7 +517,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
args: {
reference_doctype: me.frm.doctype,
reference_name: me.frm.docname,
- content: __('Reason for hold: ')+data.reason_for_hold,
+ content: __('Reason for hold:') + " " +data.reason_for_hold,
comment_email: frappe.session.user,
comment_by: frappe.session.user_fullname
},
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index e2bd602ba7..9fb2f3ee7f 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -13,7 +13,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.$body = this.dialog.body;
this.set_payment_primary_action();
this.make_keyboard();
- this.select_text()
+ this.select_text();
},
select_text: function() {
@@ -43,15 +43,15 @@ erpnext.payments = erpnext.stock.StockController.extend({
$(this.$body).empty();
$(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: function() {
var me = this;
- if(this.frm.doc.change_amount > 0) {
- me.payment_val = me.doc.outstanding_amount
+ 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");
@@ -112,7 +112,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
var me = this;
$(this.$body).find('.pos-payment-row').click(function() {
me.idx = $(this).attr("idx");
- me.set_outstanding_amount()
+ me.set_outstanding_amount();
});
$(this.$body).find('.form-control').click(function() {
@@ -133,8 +133,8 @@ erpnext.payments = erpnext.stock.StockController.extend({
highlight_selected_row: function() {
var me = this;
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('.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);
},
@@ -143,15 +143,15 @@ erpnext.payments = erpnext.stock.StockController.extend({
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()
- })
+ 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.idx = me.selected_mode.attr("idx");
me.update_paid_amount();
})
@@ -161,10 +161,10 @@ erpnext.payments = erpnext.stock.StockController.extend({
var me = this;
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()
- })
+ me.selected_mode.val(format_currency(me.payment_val, me.frm.doc.currency));
+ me.idx = me.selected_mode.attr("idx");
+ me.update_payment_amount();
+ });
},
clear_amount: function() {
@@ -177,7 +177,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
me.selected_mode.val(0.0);
me.highlight_selected_row();
me.update_payment_amount();
- })
+ });
},
write_off_amount: function(write_off_amount) {
@@ -186,32 +186,32 @@ erpnext.payments = erpnext.stock.StockController.extend({
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.calculate_outstanding_amount(false)
- this.show_amounts()
+ this.calculate_outstanding_amount(false);
+ this.show_amounts();
},
change_amount: function(change_amount) {
var me = this;
this.frm.doc.change_amount = flt(change_amount, precision("change_amount"));
- this.calculate_write_off_amount()
- this.show_amounts()
+ this.calculate_write_off_amount();
+ this.show_amounts();
},
update_paid_amount: function(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'){
- me.change_amount(value)
+ 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));
}
- me.write_off_amount(value)
+ me.write_off_amount(value);
}
- }else{
- this.update_payment_amount()
+ } else {
+ this.update_payment_amount();
}
},
@@ -220,7 +220,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
$.each(this.frm.doc.payments, function(index, data) {
if(cint(me.idx) == cint(data.idx)){
- data.amount = flt(me.selected_mode.val(), 2)
+ data.amount = flt(me.selected_mode.val(), 2);
}
})
@@ -232,8 +232,8 @@ erpnext.payments = erpnext.stock.StockController.extend({
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('.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();
}
})
\ No newline at end of file
From a23aaf43f47d515a8ec2a848a9341b560aa92706 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 17 May 2021 20:58:50 +0530
Subject: [PATCH 119/262] fix: Allocate advance taxes only for payment entry
---
.../purchase_invoice/purchase_invoice.py | 65 ++++++++++---------
.../doctype/sales_invoice/sales_invoice.py | 65 ++++++++++---------
erpnext/controllers/accounts_controller.py | 19 +++---
3 files changed, 76 insertions(+), 73 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index a4bac3550d..f925bcf5ba 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -903,42 +903,43 @@ class PurchaseInvoice(BuyingController):
def allocate_advance_taxes(self, gl_entries):
tax_map = self.get_tax_map()
for pe in self.get('advances'):
- pe = frappe.get_doc('Payment Entry', pe.reference_name)
- for tax in pe.get('taxes'):
- account_currency = get_account_currency(tax.account_head)
- dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
- rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
+ if pe.reference_type == 'Payment Entry':
+ pe = frappe.get_doc('Payment Entry', pe.reference_name)
+ for tax in pe.get('taxes'):
+ account_currency = get_account_currency(tax.account_head)
+ dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+ rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
- unallocated_amount = tax.tax_amount - tax.allocated_amount
- if tax_map.get(tax.account_head):
- amount = tax_map.get(tax.account_head)
- if amount < unallocated_amount:
- unallocated_amount = amount
+ unallocated_amount = tax.tax_amount - tax.allocated_amount
+ if tax_map.get(tax.account_head):
+ amount = tax_map.get(tax.account_head)
+ if amount < unallocated_amount:
+ unallocated_amount = amount
- gl_entries.append(
- self.get_gl_dict({
- "account": tax.account_head,
- "against": self.supplier,
- dr_or_cr: unallocated_amount,
- dr_or_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center
- }, account_currency, item=tax))
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": tax.account_head,
+ "against": self.supplier,
+ dr_or_cr: unallocated_amount,
+ dr_or_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
+ else unallocated_amount,
+ 'cost_center': tax.cost_center
+ }, account_currency, item=tax))
- gl_entries.append(
- self.get_gl_dict({
- "account": pe.advance_tax_account,
- "against": self.supplier,
- rev_dr_cr: unallocated_amount,
- rev_dr_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center or self.cost_center
- }, account_currency, item=tax))
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": pe.advance_tax_account,
+ "against": self.supplier,
+ rev_dr_cr: unallocated_amount,
+ rev_dr_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
+ else unallocated_amount,
+ 'cost_center': tax.cost_center or self.cost_center
+ }, account_currency, item=tax))
- frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
- tax_map[tax.account_head] -= unallocated_amount
+ frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
+ tax_map[tax.account_head] -= unallocated_amount
def make_payment_gl_entries(self, gl_entries):
# Make Cash GL Entries
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 9a596f2b32..664b3ab0f2 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -916,42 +916,43 @@ class SalesInvoice(SellingController):
def allocate_advance_taxes(self, gl_entries):
tax_map = self.get_tax_map()
for pe in self.get('advances'):
- pe = frappe.get_doc('Payment Entry', pe.reference_name)
- for tax in pe.get('taxes'):
- account_currency = get_account_currency(tax.account_head)
- dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
- rev_dr_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+ if pe.reference_type == 'Payment Entry':
+ pe = frappe.get_doc('Payment Entry', pe.reference_name)
+ for tax in pe.get('taxes'):
+ account_currency = get_account_currency(tax.account_head)
+ dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
+ rev_dr_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
- unallocated_amount = tax.tax_amount - tax.allocated_amount
- if tax_map.get(tax.account_head):
- amount = tax_map.get(tax.account_head)
- if amount < unallocated_amount:
- unallocated_amount = amount
+ unallocated_amount = tax.tax_amount - tax.allocated_amount
+ if tax_map.get(tax.account_head):
+ amount = tax_map.get(tax.account_head)
+ if amount < unallocated_amount:
+ unallocated_amount = amount
- gl_entries.append(
- self.get_gl_dict({
- "account": tax.account_head,
- "against": self.customer,
- dr_or_cr: unallocated_amount,
- dr_or_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center
- }, account_currency, item=tax))
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": tax.account_head,
+ "against": self.customer,
+ dr_or_cr: unallocated_amount,
+ dr_or_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
+ else unallocated_amount,
+ 'cost_center': tax.cost_center
+ }, account_currency, item=tax))
- gl_entries.append(
- self.get_gl_dict({
- "account": pe.advance_tax_account,
- "against": self.customer,
- rev_dr_cr: unallocated_amount,
- rev_dr_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center
- }, account_currency, item=tax))
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": pe.advance_tax_account,
+ "against": self.customer,
+ rev_dr_cr: unallocated_amount,
+ rev_dr_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
+ else unallocated_amount,
+ 'cost_center': tax.cost_center
+ }, account_currency, item=tax))
- frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
- tax_map[tax.account_head] -= unallocated_amount
+ frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
+ tax_map[tax.account_head] -= unallocated_amount
def make_item_gl_entries(self, gl_entries):
# income account gl entries
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index da88853a96..11a9d90a1f 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -726,16 +726,17 @@ class AccountsController(TransactionBase):
tax_map = self.get_tax_map()
for pe in self.get('advances'):
- pe = frappe.get_doc('Payment Entry', pe.reference_name)
- for tax in pe.get('taxes'):
- allocated_amount = tax_map.get(tax.account_head) - allocated_tax_map.get(tax.account_head)
- if allocated_amount > tax.tax_amount:
- allocated_amount = tax.tax_amount
+ if pe.reference_type == 'Payment Entry':
+ pe = frappe.get_doc('Payment Entry', pe.reference_name)
+ for tax in pe.get('taxes'):
+ allocated_amount = tax_map.get(tax.account_head) - allocated_tax_map.get(tax.account_head)
+ if allocated_amount > tax.tax_amount:
+ allocated_amount = tax.tax_amount
- if allocated_amount:
- frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount - allocated_amount)
- tax_map[tax.account_head] -= allocated_amount
- allocated_tax_map[tax.account_head] -= allocated_amount
+ if allocated_amount:
+ frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount - allocated_amount)
+ tax_map[tax.account_head] -= allocated_amount
+ allocated_tax_map[tax.account_head] -= allocated_amount
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
from erpnext.controllers.status_updater import get_allowance_for
From c9da1fc568db4d6a163b3ba755ec69e776bcea69 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 19 May 2021 18:38:35 +0530
Subject: [PATCH 120/262] chore: Test case for adance TDS allocation
---
.../doctype/payment_entry/payment_entry.json | 333 +++++-------------
.../doctype/payment_entry/payment_entry.py | 6 +-
.../purchase_invoice/purchase_invoice.py | 41 ---
.../purchase_invoice/test_purchase_invoice.py | 90 +++++
.../doctype/sales_invoice/sales_invoice.py | 41 ---
erpnext/controllers/accounts_controller.py | 56 ++-
6 files changed, 233 insertions(+), 334 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index afc72045e6..b4b92f926e 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -97,9 +97,7 @@
{
"fieldname": "type_of_payment",
"fieldtype": "Section Break",
- "label": "Type of Payment",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Type of Payment"
},
{
"bold": 1,
@@ -109,9 +107,7 @@
"options": "ACC-PAY-.YYYY.-",
"print_hide": 1,
"reqd": 1,
- "set_only_once": 1,
- "show_days": 1,
- "show_seconds": 1
+ "set_only_once": 1
},
{
"bold": 1,
@@ -122,15 +118,11 @@
"label": "Payment Type",
"options": "Receive\nPay\nInternal Transfer",
"print_hide": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "column_break_5",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"bold": 1,
@@ -139,9 +131,7 @@
"fieldtype": "Date",
"in_list_view": 1,
"label": "Posting Date",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "company",
@@ -150,34 +140,26 @@
"options": "Company",
"print_hide": 1,
"remember_last_selected_value": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
- "options": "Cost Center",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Cost Center"
},
{
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Mode of Payment",
- "options": "Mode of Payment",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Mode of Payment"
},
{
"depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type)",
"fieldname": "party_section",
"fieldtype": "Section Break",
- "label": "Payment From / To",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Payment From / To"
},
{
"depends_on": "eval:in_list([\"Receive\", \"Pay\"], doc.payment_type) && doc.docstatus==0",
@@ -187,9 +169,7 @@
"label": "Party Type",
"options": "DocType",
"print_hide": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"bold": 1,
@@ -198,9 +178,7 @@
"fieldtype": "Dynamic Link",
"in_standard_filter": 1,
"label": "Party",
- "options": "party_type",
- "show_days": 1,
- "show_seconds": 1
+ "options": "party_type"
},
{
"allow_on_submit": 1,
@@ -208,24 +186,18 @@
"fieldname": "party_name",
"fieldtype": "Data",
"in_global_search": 1,
- "label": "Party Name",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Party Name"
},
{
"fieldname": "column_break_11",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "party",
"fieldname": "contact_person",
"fieldtype": "Link",
"label": "Contact",
- "options": "Contact",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Contact"
},
{
"depends_on": "contact_person",
@@ -233,17 +205,13 @@
"fieldtype": "Data",
"label": "Email",
"options": "Email",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"fieldname": "payment_accounts_section",
"fieldtype": "Section Break",
- "label": "Accounts",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Accounts"
},
{
"depends_on": "party",
@@ -251,9 +219,7 @@
"fieldtype": "Currency",
"label": "Party Balance",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"bold": 1,
@@ -264,9 +230,7 @@
"label": "Account Paid From",
"options": "Account",
"print_hide": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"depends_on": "paid_from",
@@ -276,9 +240,7 @@
"options": "Currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"depends_on": "paid_from",
@@ -287,15 +249,11 @@
"label": "Account Balance",
"options": "paid_from_account_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_18",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "eval:(in_list([\"Internal Transfer\", \"Receive\"], doc.payment_type) || doc.party)",
@@ -305,9 +263,7 @@
"label": "Account Paid To",
"options": "Account",
"print_hide": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"depends_on": "paid_to",
@@ -317,9 +273,7 @@
"options": "Currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"depends_on": "paid_to",
@@ -328,17 +282,13 @@
"label": "Account Balance",
"options": "paid_to_account_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:(doc.paid_to && doc.paid_from)",
"fieldname": "payment_amounts_section",
"fieldtype": "Section Break",
- "label": "Amount",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Amount"
},
{
"bold": 1,
@@ -346,18 +296,14 @@
"fieldtype": "Currency",
"label": "Paid Amount",
"options": "paid_from_account_currency",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "source_exchange_rate",
"fieldtype": "Float",
"label": "Exchange Rate",
"print_hide": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "base_paid_amount",
@@ -366,15 +312,11 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "column_break_21",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"bold": 1,
@@ -383,18 +325,14 @@
"label": "Received Amount",
"options": "paid_to_account_currency",
"print_hide": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "target_exchange_rate",
"fieldtype": "Float",
"label": "Exchange Rate",
"print_hide": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "base_received_amount",
@@ -403,40 +341,30 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1,
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"depends_on": "eval:(doc.party && doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)",
"fieldname": "section_break_14",
"fieldtype": "Section Break",
- "label": "Reference",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Reference"
},
{
"depends_on": "eval:doc.docstatus==0",
"fieldname": "get_outstanding_invoice",
"fieldtype": "Button",
- "label": "Get Outstanding Invoice",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Get Outstanding Invoice"
},
{
"fieldname": "references",
"fieldtype": "Table",
"label": "Payment References",
- "options": "Payment Entry Reference",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Payment Entry Reference"
},
{
"fieldname": "section_break_34",
"fieldtype": "Section Break",
- "label": "Writeoff",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Writeoff"
},
{
"bold": 1,
@@ -445,9 +373,7 @@
"fieldtype": "Currency",
"label": "Total Allocated Amount",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_total_allocated_amount",
@@ -455,31 +381,23 @@
"label": "Total Allocated Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "set_exchange_gain_loss",
"fieldtype": "Button",
- "label": "Set Exchange Gain / Loss",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Set Exchange Gain / Loss"
},
{
"fieldname": "column_break_36",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "eval:(doc.paid_amount && doc.received_amount && doc.references)",
"fieldname": "unallocated_amount",
"fieldtype": "Currency",
"label": "Unallocated Amount",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"bold": 1,
@@ -489,17 +407,13 @@
"label": "Difference Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "difference_amount",
"fieldname": "write_off_difference_amount",
"fieldtype": "Button",
- "label": "Write Off Difference Amount",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Write Off Difference Amount"
},
{
"collapsible": 1,
@@ -507,39 +421,29 @@
"depends_on": "eval:(doc.paid_amount && doc.received_amount)",
"fieldname": "deductions_or_loss_section",
"fieldtype": "Section Break",
- "label": "Deductions or Loss",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Deductions or Loss"
},
{
"fieldname": "deductions",
"fieldtype": "Table",
"label": "Payment Deductions or Loss",
- "options": "Payment Entry Deduction",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Payment Entry Deduction"
},
{
"fieldname": "transaction_references",
"fieldtype": "Section Break",
- "label": "Transaction ID",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Transaction ID"
},
{
"bold": 1,
"depends_on": "eval:(doc.paid_from && doc.paid_to)",
"fieldname": "reference_no",
"fieldtype": "Data",
- "label": "Cheque/Reference No",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Cheque/Reference No"
},
{
"fieldname": "column_break_23",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"bold": 1,
@@ -547,9 +451,7 @@
"fieldname": "reference_date",
"fieldtype": "Date",
"label": "Cheque/Reference Date",
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"depends_on": "eval:doc.docstatus==1",
@@ -558,76 +460,58 @@
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"depends_on": "eval:(doc.paid_from && doc.paid_to && doc.paid_amount && doc.received_amount)",
"fieldname": "section_break_12",
"fieldtype": "Section Break",
- "label": "More Information",
- "show_days": 1,
- "show_seconds": 1
+ "label": "More Information"
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "remarks",
"fieldtype": "Small Text",
"label": "Remarks",
"no_copy": 1,
- "read_only_depends_on": "eval:doc.custom_remarks == 0",
- "show_days": 1,
- "show_seconds": 1
+ "read_only_depends_on": "eval:doc.custom_remarks == 0"
},
{
"fieldname": "column_break_16",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "letter_head",
"fieldtype": "Link",
"label": "Letter Head",
"options": "Letter Head",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "print_heading",
"fieldtype": "Link",
"label": "Print Heading",
"options": "Print Heading",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fetch_from": "bank_account.bank",
"fieldname": "bank",
"fieldtype": "Read Only",
- "label": "Bank",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Bank"
},
{
"fetch_from": "bank_account.bank_account_no",
"fieldname": "bank_account_no",
"fieldtype": "Read Only",
- "label": "Bank Account No",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Bank Account No"
},
{
"fieldname": "payment_order",
@@ -636,16 +520,12 @@
"no_copy": 1,
"options": "Payment Order",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "subscription_section",
"fieldtype": "Section Break",
- "label": "Subscription Section",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Subscription Section"
},
{
"allow_on_submit": 1,
@@ -655,9 +535,7 @@
"no_copy": 1,
"options": "Auto Repeat",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "amended_from",
@@ -666,9 +544,7 @@
"no_copy": 1,
"options": "Payment Entry",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "title",
@@ -683,18 +559,14 @@
"fieldname": "bank_account",
"fieldtype": "Link",
"label": "Company Bank Account",
- "options": "Bank Account",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Bank Account"
},
{
"depends_on": "party",
"fieldname": "party_bank_account",
"fieldtype": "Link",
"label": "Party Bank Account",
- "options": "Bank Account",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Bank Account"
},
{
"fieldname": "payment_order_status",
@@ -702,23 +574,17 @@
"hidden": 1,
"label": "Payment Order Status",
"options": "Initiated\nPayment Ordered",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Accounting Dimensions"
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"default": "Draft",
@@ -739,70 +605,55 @@
"fieldname": "tax_withholding_category",
"fieldtype": "Link",
"label": "Tax Withholding Category",
- "options": "Tax Withholding Category",
- "show_days": 1,
- "show_seconds": 1
+ "mandatory_depends_on": "eval:doc.apply_tax_withholding_amount",
+ "options": "Tax Withholding Category"
},
{
"default": "0",
"depends_on": "eval:doc.party_type == 'Supplier'",
"fieldname": "apply_tax_withholding_amount",
"fieldtype": "Check",
- "label": "Apply Tax Withholding Amount",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Apply Tax Withholding Amount"
},
{
"collapsible": 1,
"fieldname": "taxes_and_charges_section",
"fieldtype": "Section Break",
- "label": "Taxes and Charges",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Taxes and Charges"
},
{
"depends_on": "eval:doc.party_type == 'Supplier'",
"fieldname": "purchase_taxes_and_charges_template",
"fieldtype": "Link",
"label": "Taxes and Charges Template",
- "options": "Purchase Taxes and Charges Template",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Purchase Taxes and Charges Template"
},
{
"depends_on": "eval: doc.party_type == 'Customer'",
"fieldname": "sales_taxes_and_charges_template",
"fieldtype": "Link",
"label": "Taxes and Charges Template",
- "options": "Sales Taxes and Charges Template",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Sales Taxes and Charges Template"
},
{
"depends_on": "eval: doc.party_type == 'Supplier' || doc.party_type == 'Customer'",
"fieldname": "taxes",
"fieldtype": "Table",
"label": "Advance Taxes and Charges",
- "options": "Advance Taxes and Charges",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Advance Taxes and Charges"
},
{
"fieldname": "base_total_taxes_and_charges",
"fieldtype": "Currency",
"label": "Total Taxes and Charges (Company Currency)",
"options": "Company:company:default_currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "total_taxes_and_charges",
"fieldtype": "Currency",
"label": "Total Taxes and Charges",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "paid_amount_after_tax",
@@ -810,61 +661,47 @@
"hidden": 1,
"label": "Paid Amount After Tax",
"options": "paid_from_account_currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_paid_amount_after_tax",
"fieldtype": "Currency",
"label": "Paid Amount After Tax (Company Currency)",
"options": "Company:company:default_currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_55",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "section_break_56",
"fieldtype": "Section Break",
- "hide_border": 1,
- "show_days": 1,
- "show_seconds": 1
+ "hide_border": 1
},
{
"fieldname": "advance_tax_account",
"fieldtype": "Link",
"label": "Advance Tax Account",
- "options": "Account",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Account"
},
{
"fieldname": "received_amount_after_tax",
"fieldtype": "Currency",
"label": "Received Amount After Tax",
- "options": "paid_to_account_currency",
- "show_days": 1,
- "show_seconds": 1
+ "options": "paid_to_account_currency"
},
{
"fieldname": "base_received_amount_after_tax",
"fieldtype": "Currency",
"label": "Received Amount After Tax (Company Currency)",
- "options": "Company:company:default_currency",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Company:company:default_currency"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-05-15 13:05:16.958866",
+ "modified": "2021-05-19 02:33:08.192932",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
@@ -908,4 +745,4 @@
"sort_order": "DESC",
"title_field": "title",
"track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index ac8e7070f5..cbe8045fd1 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -436,7 +436,10 @@ class PaymentEntry(AccountsController):
if not tax_withholding_details:
return
- tax_withholding_details.update({'included_in_paid_amount': included_in_paid_amount})
+ tax_withholding_details.update({
+ 'included_in_paid_amount': included_in_paid_amount,
+ 'cost_center': self.cost_center or erpnext.get_default_cost_center(self.company)
+ })
accounts = []
for d in self.taxes:
@@ -1412,6 +1415,7 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
if doc.doctype == 'Purchase Order' and doc.apply_tds:
pe.apply_tax_withholding_amount = 1
+ pe.tax_withholding_category = doc.tax_withholding_category
return pe
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index f925bcf5ba..934c731cf1 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -900,47 +900,6 @@ class PurchaseInvoice(BuyingController):
"cost_center": self.cost_center
}, account_currency, item=self))
- def allocate_advance_taxes(self, gl_entries):
- tax_map = self.get_tax_map()
- for pe in self.get('advances'):
- if pe.reference_type == 'Payment Entry':
- pe = frappe.get_doc('Payment Entry', pe.reference_name)
- for tax in pe.get('taxes'):
- account_currency = get_account_currency(tax.account_head)
- dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
- rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
-
- unallocated_amount = tax.tax_amount - tax.allocated_amount
- if tax_map.get(tax.account_head):
- amount = tax_map.get(tax.account_head)
- if amount < unallocated_amount:
- unallocated_amount = amount
-
- gl_entries.append(
- self.get_gl_dict({
- "account": tax.account_head,
- "against": self.supplier,
- dr_or_cr: unallocated_amount,
- dr_or_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center
- }, account_currency, item=tax))
-
- gl_entries.append(
- self.get_gl_dict({
- "account": pe.advance_tax_account,
- "against": self.supplier,
- rev_dr_cr: unallocated_amount,
- rev_dr_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center or self.cost_center
- }, account_currency, item=tax))
-
- frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
- tax_map[tax.account_head] -= unallocated_amount
-
def make_payment_gl_entries(self, gl_entries):
# Make Cash GL Entries
if cint(self.is_paid) and self.cash_bank_account and self.paid_amount:
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 66be11ff23..0da46e9886 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -950,6 +950,96 @@ class TestPurchaseInvoice(unittest.TestCase):
acc_settings.submit_journal_entriessubmit_journal_entries = 0
acc_settings.save()
+ def test_purchase_invoice_advance_taxes(self):
+ from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
+ from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
+ from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_purchase_invoice
+
+ # Update tax withholding category with current fiscal year and rate details
+ update_tax_witholding_category('_Test Company', 'TDS Payable - _TC', nowdate())
+
+ # Create Purchase Order with TDS applied
+ po = create_purchase_order(do_not_save=1, rate=3000)
+ po.apply_tds = 1
+ po.tax_withholding_category = 'TDS - 194 - Dividends - Individual'
+ po.save()
+ po.submit()
+
+ # Update Unrealized Profit / Loss Account which is used as default advance tax account
+ frappe.db.set_value('Company', '_Test Company', 'unrealized_profit_loss_account', '_Test Account Excise Duty - _TC')
+
+ # Create Payment Entry Against the order
+ payment_entry = get_payment_entry(dt='Purchase Order', dn=po.name)
+ payment_entry.save()
+ payment_entry.submit()
+
+ # Check GLE for Payment Entry
+ expected_gle = [
+ ['_Test Account Excise Duty - _TC', 6000, 0],
+ ['Cash - _TC', 0, 24000],
+ ['Creditors - _TC', 24000, 0],
+ ['TDS Payable - _TC', 0, 6000],
+ ]
+
+ gl_entries = frappe.db.sql("""select account, debit, credit
+ from `tabGL Entry`
+ where voucher_type='Payment Entry' and voucher_no=%s
+ order by account asc""", (payment_entry.name), as_dict=1)
+
+ for i, gle in enumerate(gl_entries):
+ self.assertEqual(expected_gle[i][0], gle.account)
+ self.assertEqual(expected_gle[i][1], gle.debit)
+ self.assertEqual(expected_gle[i][2], gle.credit)
+
+ # Create Purchase Invoice against Purchase Order
+ purchase_invoice = get_mapped_purchase_invoice(po.name)
+ purchase_invoice.allocate_advances_automatically = 1
+ purchase_invoice.save()
+ purchase_invoice.submit()
+
+ # Check GLE for Purchase Invoice
+ # Zero net effect on final TDS Payable on invoice
+ expected_gle = [
+ ['_Test Account Excise Duty - _TC', 0, 6000],
+ ['Cost of Goods Sold - _TC', 30000, 0],
+ ['Creditors - _TC', 0, 24000],
+ ['TDS Payable - _TC', 6000, 6000],
+ ]
+
+ gl_entries = frappe.db.sql("""select account, debit, credit
+ from `tabGL Entry`
+ where voucher_type='Purchase Invoice' and voucher_no=%s
+ order by account asc""", (purchase_invoice.name), as_dict=1)
+
+ for i, gle in enumerate(gl_entries):
+ self.assertEqual(expected_gle[i][0], gle.account)
+ self.assertEqual(expected_gle[i][1], gle.debit)
+ self.assertEqual(expected_gle[i][2], gle.credit)
+
+def update_tax_witholding_category(company, account, date):
+ from erpnext.accounts.utils import get_fiscal_year
+
+ fiscal_year = get_fiscal_year(date=date, company=company)
+
+ if not frappe.db.get_value('Tax Withholding Rate',
+ {'parent': 'TDS - 194 - Dividends - Individual', 'fiscal_year': fiscal_year[0]}):
+ tds_category = frappe.get_doc('Tax Withholding Category', 'TDS - 194 - Dividends - Individual')
+ tds_category.append('rates', {
+ 'fiscal_year': fiscal_year[0],
+ 'tax_withholding_rate': 20,
+ 'single_threshold': 2500,
+ 'cumulative_threshold': 0
+ })
+ tds_category.save()
+
+ if not frappe.db.get_value('Tax Withholding Account',
+ {'parent': 'TDS - 194 - Dividends - Individual', 'account': account}):
+ tds_category = frappe.get_doc('Tax Withholding Category', 'TDS - 194 - Dividends - Individual')
+ tds_category.append('accounts', {
+ 'company': company,
+ 'account': account
+ })
+ tds_category.save()
def unlink_payment_on_cancel_of_invoice(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 664b3ab0f2..485ae18bf0 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -913,47 +913,6 @@ class SalesInvoice(SellingController):
"cost_center": self.cost_center
}, account_currency, item=self))
- def allocate_advance_taxes(self, gl_entries):
- tax_map = self.get_tax_map()
- for pe in self.get('advances'):
- if pe.reference_type == 'Payment Entry':
- pe = frappe.get_doc('Payment Entry', pe.reference_name)
- for tax in pe.get('taxes'):
- account_currency = get_account_currency(tax.account_head)
- dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
- rev_dr_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
-
- unallocated_amount = tax.tax_amount - tax.allocated_amount
- if tax_map.get(tax.account_head):
- amount = tax_map.get(tax.account_head)
- if amount < unallocated_amount:
- unallocated_amount = amount
-
- gl_entries.append(
- self.get_gl_dict({
- "account": tax.account_head,
- "against": self.customer,
- dr_or_cr: unallocated_amount,
- dr_or_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center
- }, account_currency, item=tax))
-
- gl_entries.append(
- self.get_gl_dict({
- "account": pe.advance_tax_account,
- "against": self.customer,
- rev_dr_cr: unallocated_amount,
- rev_dr_cr + "_in_account_currency": unallocated_amount
- if account_currency==self.company_currency
- else unallocated_amount,
- 'cost_center': tax.cost_center
- }, account_currency, item=tax))
-
- frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount + unallocated_amount)
- tax_map[tax.account_head] -= unallocated_amount
-
def make_item_gl_entries(self, gl_entries):
# income account gl entries
for item in self.get("items"):
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 11a9d90a1f..1e85433a60 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -700,7 +700,7 @@ class AccountsController(TransactionBase):
from erpnext.accounts.utils import unlink_ref_doc_from_payment_entries
if self.doctype in ["Sales Invoice", "Purchase Invoice"]:
- self.update_allocated_advance_taxes()
+ self.update_allocated_advance_taxes_on_cancel()
if frappe.db.get_single_value('Accounts Settings', 'unlink_payment_on_cancellation_of_invoice'):
unlink_ref_doc_from_payment_entries(self)
@@ -716,7 +716,7 @@ class AccountsController(TransactionBase):
return tax_map
- def update_allocated_advance_taxes(self):
+ def update_allocated_advance_taxes_on_cancel(self):
if self.get('advances'):
tax_accounts = [d.account_head for d in self.get('taxes')]
allocated_tax_map = frappe._dict(frappe.get_all('GL Entry', fields=['account', 'sum(credit - debit)'],
@@ -734,10 +734,60 @@ class AccountsController(TransactionBase):
allocated_amount = tax.tax_amount
if allocated_amount:
- frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount', tax.allocated_amount - allocated_amount)
+ frappe.db.set_value('Advance Taxes and Charges', tax.name, 'allocated_amount',
+ tax.allocated_amount - allocated_amount)
tax_map[tax.account_head] -= allocated_amount
allocated_tax_map[tax.account_head] -= allocated_amount
+ def allocate_advance_taxes(self, gl_entries):
+ tax_map = self.get_tax_map()
+ for pe in self.get("advances"):
+ if pe.reference_type == "Payment Entry":
+ pe = frappe.get_doc("Payment Entry", pe.reference_name)
+ for tax in pe.get("taxes"):
+ account_currency = get_account_currency(tax.account_head)
+
+ if self.doctype == "Purchase Invoice":
+ dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+ rev_dr_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
+ else:
+ dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
+ rev_dr_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
+
+ party = self.supplier if self.doctype == "Purchase Invoice" else self.customer
+ unallocated_amount = tax.tax_amount - tax.allocated_amount
+ if tax_map.get(tax.account_head):
+ amount = tax_map.get(tax.account_head)
+ if amount < unallocated_amount:
+ unallocated_amount = amount
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": tax.account_head,
+ "against": party,
+ dr_or_cr: unallocated_amount,
+ dr_or_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
+ else unallocated_amount,
+ "cost_center": tax.cost_center
+ }, account_currency, item=tax))
+
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": pe.advance_tax_account,
+ "against": party,
+ rev_dr_cr: unallocated_amount,
+ rev_dr_cr + "_in_account_currency": unallocated_amount
+ if account_currency==self.company_currency
+ else unallocated_amount,
+ "cost_center": tax.cost_center
+ }, account_currency, item=tax))
+
+ frappe.db.set_value("Advance Taxes and Charges", tax.name, "allocated_amount",
+ tax.allocated_amount + unallocated_amount)
+
+ tax_map[tax.account_head] -= unallocated_amount
+
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
from erpnext.controllers.status_updater import get_allowance_for
item_allowance = {}
From b07f7d1b70352a6a85549541fc4a635df6ff393a Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 20 May 2021 17:08:57 +0530
Subject: [PATCH 121/262] fix: Linting and other fixes
---
.../doctype/payment_entry/payment_entry.js | 19 ++++++---
.../doctype/payment_entry/payment_entry.json | 4 +-
.../doctype/payment_entry/payment_entry.py | 19 ++++++---
.../purchase_invoice/test_purchase_invoice.py | 40 +++++++++----------
.../doctype/purchase_order/purchase_order.js | 3 +-
erpnext/public/js/payment/payments.js | 33 +++++++--------
6 files changed, 66 insertions(+), 52 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 19d73b1ad4..a7fcbd7e3b 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -1112,12 +1112,16 @@ frappe.ui.form.on('Payment Entry', {
current_tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
+ let applicable_tax_amount = 0
+
if (!tax.included_in_paid_amount) {
- if(i==0) {
- tax.total = flt(frm.doc.paid_amount + current_tax_amount, precision("total", tax));
- } else {
- tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax));
- }
+ applicable_tax_amount = current_tax_amount
+ }
+
+ if(i==0) {
+ tax.total = flt(frm.doc.paid_amount + applicable_tax_amount, precision("total", tax));
+ } else {
+ tax.total = flt(frm.doc["taxes"][i-1].total + applicable_tax_amount, precision("total", tax));
}
tax.base_total = tax.total * frm.doc.source_exchange_rate;
@@ -1194,6 +1198,11 @@ frappe.ui.form.on('Advance Taxes and Charges', {
taxes_remove: function(frm) {
frm.events.calculate_taxes(frm);
frm.events.set_unallocated_amount(frm);
+ },
+
+ included_in_paid_amount: function(frm) {
+ frm.events.calculate_taxes(frm);
+ frm.events.set_unallocated_amount(frm);
}
})
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index b4b92f926e..1e2bd8194a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -29,7 +29,6 @@
"paid_from",
"paid_from_account_currency",
"paid_from_account_balance",
- "advance_tax_account",
"column_break_18",
"paid_to",
"paid_to_account_currency",
@@ -60,6 +59,7 @@
"taxes_and_charges_section",
"purchase_taxes_and_charges_template",
"sales_taxes_and_charges_template",
+ "advance_tax_account",
"column_break_55",
"apply_tax_withholding_amount",
"tax_withholding_category",
@@ -701,7 +701,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-05-19 02:33:08.192932",
+ "modified": "2021-05-20 02:04:56.766124",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index cbe8045fd1..d960156670 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -444,6 +444,11 @@ class PaymentEntry(AccountsController):
accounts = []
for d in self.taxes:
if d.account_head == tax_withholding_details.get("account_head"):
+
+ # Preserve user updated included in paid amount
+ if d.included_in_paid_amount:
+ tax_withholding_details.update({'included_in_paid_amount': d.included_in_paid_amount})
+
d.update(tax_withholding_details)
accounts.append(d.account_head)
@@ -839,12 +844,16 @@ class PaymentEntry(AccountsController):
current_tax_amount *= 1.0
if not tax.included_in_paid_amount:
- if i == 0:
- tax.total = flt(self.paid_amount + current_tax_amount, self.precision("total", tax))
- else:
- tax.total = flt(self.get('taxes')[i-1].total + current_tax_amount, self.precision("total", tax))
+ applicable_tax = current_tax_amount
+ else:
+ applicable_tax = 0
- tax.base_total = tax.total * self.source_exchange_rate
+ if i == 0:
+ tax.total = flt(self.paid_amount + applicable_tax, self.precision("total", tax))
+ else:
+ tax.total = flt(self.get('taxes')[i-1].total + applicable_tax, self.precision("total", tax))
+
+ tax.base_total = tax.total * self.source_exchange_rate
self.total_taxes_and_charges += current_tax_amount
self.base_total_taxes_and_charges += current_tax_amount * self.source_exchange_rate
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 0da46e9886..aa56ddfdf3 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -992,29 +992,29 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(expected_gle[i][2], gle.credit)
# Create Purchase Invoice against Purchase Order
- purchase_invoice = get_mapped_purchase_invoice(po.name)
- purchase_invoice.allocate_advances_automatically = 1
- purchase_invoice.save()
- purchase_invoice.submit()
+ # purchase_invoice = get_mapped_purchase_invoice(po.name)
+ # purchase_invoice.allocate_advances_automatically = 1
+ # purchase_invoice.save()
+ # purchase_invoice.submit()
- # Check GLE for Purchase Invoice
- # Zero net effect on final TDS Payable on invoice
- expected_gle = [
- ['_Test Account Excise Duty - _TC', 0, 6000],
- ['Cost of Goods Sold - _TC', 30000, 0],
- ['Creditors - _TC', 0, 24000],
- ['TDS Payable - _TC', 6000, 6000],
- ]
+ # # Check GLE for Purchase Invoice
+ # # Zero net effect on final TDS Payable on invoice
+ # expected_gle = [
+ # ['_Test Account Excise Duty - _TC', 0, 6000],
+ # ['Cost of Goods Sold - _TC', 30000, 0],
+ # ['Creditors - _TC', 0, 24000],
+ # ['TDS Payable - _TC', 6000, 6000],
+ # ]
- gl_entries = frappe.db.sql("""select account, debit, credit
- from `tabGL Entry`
- where voucher_type='Purchase Invoice' and voucher_no=%s
- order by account asc""", (purchase_invoice.name), as_dict=1)
+ # gl_entries = frappe.db.sql("""select account, debit, credit
+ # from `tabGL Entry`
+ # where voucher_type='Purchase Invoice' and voucher_no=%s
+ # order by account asc""", (purchase_invoice.name), as_dict=1)
- for i, gle in enumerate(gl_entries):
- self.assertEqual(expected_gle[i][0], gle.account)
- self.assertEqual(expected_gle[i][1], gle.debit)
- self.assertEqual(expected_gle[i][2], gle.credit)
+ # for i, gle in enumerate(gl_entries):
+ # self.assertEqual(expected_gle[i][0], gle.account)
+ # self.assertEqual(expected_gle[i][1], gle.debit)
+ # self.assertEqual(expected_gle[i][2], gle.credit)
def update_tax_witholding_category(company, account, date):
from erpnext.accounts.utils import get_fiscal_year
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index ccb3ce33ec..0f6d927b36 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -321,7 +321,8 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if(me.values) {
me.values.sub_con_rm_items.map((row,i) => {
if (!row.item_code || !row.rm_item_code || !row.warehouse || !row.qty || row.qty === 0) {
- frappe.throw(__("Item Code and warehouse and quantity are required on row {0}", [i+1]));
+ let row_id = i+1;
+ frappe.throw(__("Item Code, warehouse and quantity are required on row {0}", [row_id]));
}
})
me._make_rm_stock_entry(me.dialog.fields_dict.sub_con_rm_items.grid.get_selected_children())
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index 9fb2f3ee7f..b9e933a38e 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -16,12 +16,11 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.select_text();
},
- select_text: function() {
- var me = this;
+ select_text() {
$(this.$body).find('.form-control').click(function() {
$(this).select();
- })
- },
+ });
+ }
set_payment_primary_action: function() {
var me = this;
@@ -62,8 +61,8 @@ erpnext.payments = erpnext.stock.StockController.extend({
show_payment_details: function() {
var me = this;
var multimode_payments = $(this.$body).find('.multimode-payments').empty();
- if(this.frm.doc.payments.length){
- $.each(this.frm.doc.payments, function(index, data){
+ 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,
@@ -88,12 +87,12 @@ erpnext.payments = erpnext.stock.StockController.extend({
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){
+ 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.selected_mode.val(format_currency(this.payment_val, this.frm.doc.currency));
- this.update_payment_amount()
- }else if(flt(this.selected_mode.val()) > 0){
+ 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());
}
@@ -101,8 +100,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
this.bind_amount_change_event();
},
- bind_keyboard_event: function() {
- var me = this;
+ bind_keyboard_event() {
this.payment_val = '';
this.bind_form_control_event();
this.bind_numeric_keys_event();
@@ -130,8 +128,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
});
},
- highlight_selected_row: function() {
- var me = this;
+ 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');
@@ -157,7 +154,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
},
- bind_amount_change_event: function() {
+ bind_amount_change_event() {
var me = this;
this.selected_mode.change(function() {
me.payment_val = flt($(this).val()) || 0.0;
@@ -180,9 +177,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
});
},
- write_off_amount: function(write_off_amount) {
- var me = this;
-
+ 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"));
@@ -204,7 +199,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
var value = me.selected_mode.val();
if (me.idx == 'change_amount') {
me.change_amount(value);
- } else{
+ } 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));
}
@@ -219,7 +214,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
var me = this;
$.each(this.frm.doc.payments, function(index, data) {
- if(cint(me.idx) == cint(data.idx)){
+ if (cint(me.idx) == cint(data.idx)) {
data.amount = flt(me.selected_mode.val(), 2);
}
})
From 6f84cee6feb1f2160bd1b48a6e4f45f8ee9cf952 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 21 May 2021 11:15:18 +0530
Subject: [PATCH 122/262] fix: Uncommentt test
---
.../purchase_invoice/test_purchase_invoice.py | 42 +++++++++----------
1 file changed, 21 insertions(+), 21 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index aa56ddfdf3..e71a416f3d 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -991,30 +991,30 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(expected_gle[i][1], gle.debit)
self.assertEqual(expected_gle[i][2], gle.credit)
- # Create Purchase Invoice against Purchase Order
- # purchase_invoice = get_mapped_purchase_invoice(po.name)
- # purchase_invoice.allocate_advances_automatically = 1
- # purchase_invoice.save()
- # purchase_invoice.submit()
+ Create Purchase Invoice against Purchase Order
+ purchase_invoice = get_mapped_purchase_invoice(po.name)
+ purchase_invoice.allocate_advances_automatically = 1
+ purchase_invoice.save()
+ purchase_invoice.submit()
- # # Check GLE for Purchase Invoice
- # # Zero net effect on final TDS Payable on invoice
- # expected_gle = [
- # ['_Test Account Excise Duty - _TC', 0, 6000],
- # ['Cost of Goods Sold - _TC', 30000, 0],
- # ['Creditors - _TC', 0, 24000],
- # ['TDS Payable - _TC', 6000, 6000],
- # ]
+ # Check GLE for Purchase Invoice
+ # Zero net effect on final TDS Payable on invoice
+ expected_gle = [
+ ['_Test Account Excise Duty - _TC', 0, 6000],
+ ['Cost of Goods Sold - _TC', 30000, 0],
+ ['Creditors - _TC', 0, 24000],
+ ['TDS Payable - _TC', 6000, 6000],
+ ]
- # gl_entries = frappe.db.sql("""select account, debit, credit
- # from `tabGL Entry`
- # where voucher_type='Purchase Invoice' and voucher_no=%s
- # order by account asc""", (purchase_invoice.name), as_dict=1)
+ gl_entries = frappe.db.sql("""select account, debit, credit
+ from `tabGL Entry`
+ where voucher_type='Purchase Invoice' and voucher_no=%s
+ order by account asc""", (purchase_invoice.name), as_dict=1)
- # for i, gle in enumerate(gl_entries):
- # self.assertEqual(expected_gle[i][0], gle.account)
- # self.assertEqual(expected_gle[i][1], gle.debit)
- # self.assertEqual(expected_gle[i][2], gle.credit)
+ for i, gle in enumerate(gl_entries):
+ self.assertEqual(expected_gle[i][0], gle.account)
+ self.assertEqual(expected_gle[i][1], gle.debit)
+ self.assertEqual(expected_gle[i][2], gle.credit)
def update_tax_witholding_category(company, account, date):
from erpnext.accounts.utils import get_fiscal_year
From 36d47f97f400630ffaa259e7dc50fe7b120e0c35 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 21 May 2021 11:16:26 +0530
Subject: [PATCH 123/262] fix: Linting issues
---
erpnext/public/js/payment/payments.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index b9e933a38e..ddf8706809 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -20,7 +20,7 @@ erpnext.payments = erpnext.stock.StockController.extend({
$(this.$body).find('.form-control').click(function() {
$(this).select();
});
- }
+ },
set_payment_primary_action: function() {
var me = this;
@@ -85,8 +85,8 @@ erpnext.payments = erpnext.stock.StockController.extend({
set_outstanding_amount: function() {
this.selected_mode = $(this.$body).find(repl("input[idx='%(idx)s']",{'idx': this.idx}));
- this.highlight_selected_row()
- this.payment_val = 0.0
+ 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"))
From 55a3fb57dd213993907114615bb3c406a191d9e7 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sat, 22 May 2021 20:30:18 +0530
Subject: [PATCH 124/262] fix: Linting Issues
---
.../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 2 +-
.../accounts/report/tds_payable_monthly/tds_payable_monthly.py | 1 -
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index e71a416f3d..0da46e9886 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -991,7 +991,7 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(expected_gle[i][1], gle.debit)
self.assertEqual(expected_gle[i][2], gle.credit)
- Create Purchase Invoice against Purchase Order
+ # Create Purchase Invoice against Purchase Order
purchase_invoice = get_mapped_purchase_invoice(po.name)
purchase_invoice.allocate_advances_automatically = 1
purchase_invoice.save()
diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
index 619d799d06..ceefa31cfa 100644
--- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
+++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py
@@ -56,7 +56,6 @@ def set_filters(filters):
elif filters.purchase_order and not filters.supplier:
for d in filters.get("invoices"):
if d.name == filters.purchase_order:
- print("$#$#$$#")
invoices.append(d)
filters["invoices"] = invoices if invoices else filters["invoices"]
From 84f270e73223313dc789bb5617911ded5efbc0a7 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 25 May 2021 18:03:42 +0530
Subject: [PATCH 125/262] fix: Remove unwanted commits
---
erpnext/controllers/taxes_and_totals.py | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index a6b54eb590..0b89750766 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -819,16 +819,3 @@ class init_landed_taxes_and_totals(object):
for d in self.doc.get(self.tax_field):
d.amount = flt(d.amount, d.precision("amount"))
d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount"))
-
-def get_advance_taxes(payment_entry_list):
- taxes = []
- if payment_entry_list:
- taxes = frappe.db.sql(
- """
- SELECT t.parent, t.add_deduct_tax, t.charge_type, t.rate,
- t.account_head, t.cost_center, t.tax_amount, t.description
- FROM `tabAdvance Taxes and Charges` t, `tabPayment Entry` p
- WHERE t.parent = p.name AND t.parent in %s
- """, (payment_entry_list, ), as_dict=1)
-
- return taxes
From 8fddd0f0c1a4b4f51af8e7834e37d7f48a08576a Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 25 May 2021 22:03:50 +0530
Subject: [PATCH 126/262] fix: Update TDS rate for test
---
.../doctype/purchase_invoice/test_purchase_invoice.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 0da46e9886..319808ac95 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -975,10 +975,10 @@ class TestPurchaseInvoice(unittest.TestCase):
# Check GLE for Payment Entry
expected_gle = [
- ['_Test Account Excise Duty - _TC', 6000, 0],
+ ['_Test Account Excise Duty - _TC', 3000, 0],
['Cash - _TC', 0, 24000],
['Creditors - _TC', 24000, 0],
- ['TDS Payable - _TC', 0, 6000],
+ ['TDS Payable - _TC', 0, 3000],
]
gl_entries = frappe.db.sql("""select account, debit, credit
@@ -1000,10 +1000,10 @@ class TestPurchaseInvoice(unittest.TestCase):
# Check GLE for Purchase Invoice
# Zero net effect on final TDS Payable on invoice
expected_gle = [
- ['_Test Account Excise Duty - _TC', 0, 6000],
+ ['_Test Account Excise Duty - _TC', 0, 3000],
['Cost of Goods Sold - _TC', 30000, 0],
['Creditors - _TC', 0, 24000],
- ['TDS Payable - _TC', 6000, 6000],
+ ['TDS Payable - _TC', 6000, 3000],
]
gl_entries = frappe.db.sql("""select account, debit, credit
@@ -1026,7 +1026,7 @@ def update_tax_witholding_category(company, account, date):
tds_category = frappe.get_doc('Tax Withholding Category', 'TDS - 194 - Dividends - Individual')
tds_category.append('rates', {
'fiscal_year': fiscal_year[0],
- 'tax_withholding_rate': 20,
+ 'tax_withholding_rate': 10,
'single_threshold': 2500,
'cumulative_threshold': 0
})
From 5e27c7dae21c317bde812547cc6ae1f6c69ba61d Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 25 May 2021 22:34:58 +0530
Subject: [PATCH 127/262] fix: Add non group filter for account
---
erpnext/accounts/doctype/payment_entry/payment_entry.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index a7fcbd7e3b..a4022ef40a 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -97,7 +97,8 @@ frappe.ui.form.on('Payment Entry', {
return {
filters: {
"company": frm.doc.company,
- "root_type": ["in", ["Asset", "Liability"]]
+ "root_type": ["in", ["Asset", "Liability"]],
+ "is_group": 0
}
}
});
From 59769c7a8685fb22ba18cccd9283e2e912784b59 Mon Sep 17 00:00:00 2001
From: Anupam Kumar
Date: Wed, 26 May 2021 12:16:04 +0530
Subject: [PATCH 128/262] fix: student invalid password reset link (#25825)
---
erpnext/education/doctype/student/student.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/education/doctype/student/student.py b/erpnext/education/doctype/student/student.py
index 2dc0f634f0..6be9e7104b 100644
--- a/erpnext/education/doctype/student/student.py
+++ b/erpnext/education/doctype/student/student.py
@@ -74,7 +74,6 @@ class Student(Document):
student_user.flags.ignore_permissions = True
student_user.add_roles("Student")
student_user.save()
- update_password_link = student_user.reset_password()
def update_applicant_status(self):
"""Updates Student Applicant status to Admitted"""
From be3671fe7b3965be2f34fb902e68d25c3f5c174b Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 27 May 2021 13:27:17 +0530
Subject: [PATCH 129/262] fix: Create new supplier for test case
---
.../purchase_invoice/test_purchase_invoice.py | 15 ++++++++++-----
.../doctype/purchase_order/test_purchase_order.py | 2 +-
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 319808ac95..2610a69471 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -16,6 +16,7 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_tra
from erpnext.projects.doctype.project.test_project import make_project
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.buying.doctype.supplier.test_supplier import create_supplier
test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"]
test_ignore = ["Serial No"]
@@ -955,11 +956,15 @@ class TestPurchaseInvoice(unittest.TestCase):
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_purchase_invoice
+ # create a new supplier to test
+ supplier = create_supplier(supplier_name = '_Test TDS Advance Supplier',
+ tax_withholding_category = 'TDS - 194 - Dividends - Individual')
+
# Update tax withholding category with current fiscal year and rate details
update_tax_witholding_category('_Test Company', 'TDS Payable - _TC', nowdate())
# Create Purchase Order with TDS applied
- po = create_purchase_order(do_not_save=1, rate=3000)
+ po = create_purchase_order(do_not_save=1, supplier=supplier.name, rate=3000)
po.apply_tds = 1
po.tax_withholding_category = 'TDS - 194 - Dividends - Individual'
po.save()
@@ -976,8 +981,8 @@ class TestPurchaseInvoice(unittest.TestCase):
# Check GLE for Payment Entry
expected_gle = [
['_Test Account Excise Duty - _TC', 3000, 0],
- ['Cash - _TC', 0, 24000],
- ['Creditors - _TC', 24000, 0],
+ ['Cash - _TC', 0, 27000],
+ ['Creditors - _TC', 27000, 0],
['TDS Payable - _TC', 0, 3000],
]
@@ -1002,8 +1007,8 @@ class TestPurchaseInvoice(unittest.TestCase):
expected_gle = [
['_Test Account Excise Duty - _TC', 0, 3000],
['Cost of Goods Sold - _TC', 30000, 0],
- ['Creditors - _TC', 0, 24000],
- ['TDS Payable - _TC', 6000, 3000],
+ ['Creditors - _TC', 0, 27000],
+ ['TDS Payable - _TC', 3000, 3000],
]
gl_entries = frappe.db.sql("""select account, debit, credit
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index aaa98f2f1f..39171960d8 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -1111,7 +1111,7 @@ def create_purchase_order(**args):
po.schedule_date = add_days(nowdate(), 1)
po.company = args.company or "_Test Company"
- po.supplier = args.customer or "_Test Supplier"
+ po.supplier = args.supplier or "_Test Supplier"
po.is_subcontracted = args.is_subcontracted or "No"
po.currency = args.currency or frappe.get_cached_value('Company', po.company, "default_currency")
po.conversion_factor = args.conversion_factor or 1
From ea18230274725f2cf0a3fa62b8b6f756af4dea79 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 27 May 2021 16:40:37 +0530
Subject: [PATCH 130/262] fix: Update GL Entry ordering
---
.../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 2610a69471..07f9b42fbf 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1005,8 +1005,8 @@ class TestPurchaseInvoice(unittest.TestCase):
# Check GLE for Purchase Invoice
# Zero net effect on final TDS Payable on invoice
expected_gle = [
+ ['_Test Account Cost for Goods Sold - _TC', 30000, 0],
['_Test Account Excise Duty - _TC', 0, 3000],
- ['Cost of Goods Sold - _TC', 30000, 0],
['Creditors - _TC', 0, 27000],
['TDS Payable - _TC', 3000, 3000],
]
From 753e5894de1be99c4e1b9a9fbc3c567b4ae2a5a1 Mon Sep 17 00:00:00 2001
From: Anuja P
Date: Thu, 27 May 2021 17:33:22 +0530
Subject: [PATCH 131/262] fix: ageing error in PSOA
---
.../process_statement_of_accounts.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
index 2ad455c48f..0b0ee904ff 100644
--- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
+++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py
@@ -94,7 +94,7 @@ def get_report_pdf(doc, consolidated=True):
continue
html = frappe.render_template(template_path, \
- {"filters": filters, "data": res, "ageing": ageing[0] if doc.include_ageing else None,
+ {"filters": filters, "data": res, "ageing": ageing[0] if (doc.include_ageing and ageing) else None,
"letter_head": letter_head if doc.letter_head else None,
"terms_and_conditions": frappe.db.get_value('Terms and Conditions', doc.terms_and_conditions, 'terms')
if doc.terms_and_conditions else None})
From 740c68d075c4583045052df5e3192039d2cd4576 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 27 May 2021 17:43:53 +0530
Subject: [PATCH 132/262] fix: Debug Test
---
.../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 07f9b42fbf..8bb9d7dacf 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1016,6 +1016,9 @@ class TestPurchaseInvoice(unittest.TestCase):
where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", (purchase_invoice.name), as_dict=1)
+ for gle in gl_entries:
+ print(gle.account, gle.debit, gle.credit)
+
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_gle[i][0], gle.account)
self.assertEqual(expected_gle[i][1], gle.debit)
From 46d39d27aaea10eda484cf41dda0b3bb6392f67f Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 27 May 2021 14:16:01 +0200
Subject: [PATCH 133/262] fix: validate company in taxes setup
---
erpnext/setup/setup_wizard/operations/taxes_setup.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py
index 429a558c58..dd0ebd1517 100644
--- a/erpnext/setup/setup_wizard/operations/taxes_setup.py
+++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py
@@ -11,6 +11,9 @@ from frappe import _
def setup_taxes_and_charges(company_name: str, country: str):
+ if not frappe.db.exists('Company', company_name):
+ frappe.throw(_('Company {} does not exist yet. Taxes setup aborted.').format(company_name))
+
file_path = os.path.join(os.path.dirname(__file__), '..', 'data', 'country_wise_tax.json')
with open(file_path, 'r') as json_file:
tax_data = json.load(json_file)
From 86ee3ebb09ea11e971a48e1718822a2e998fba10 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 27 May 2021 14:16:26 +0200
Subject: [PATCH 134/262] feat: create tax category during taxes setup
---
erpnext/setup/setup_wizard/operations/taxes_setup.py | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py
index dd0ebd1517..672caf2606 100644
--- a/erpnext/setup/setup_wizard/operations/taxes_setup.py
+++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py
@@ -102,6 +102,9 @@ def make_taxes_and_charges_template(company_name, doctype, template):
if frappe.db.exists(doctype, {'title': template.get('title'), 'company': company_name}):
return
+ if template.get('tax_category'):
+ ensure_tax_category_exists(template.get('tax_category'))
+
for tax_row in template.get('taxes'):
account_data = tax_row.get('account_head')
tax_row_defaults = {
@@ -233,3 +236,10 @@ def get_or_create_tax_group(company_name, root_type):
tax_group_name = tax_group_account.name
return tax_group_name
+
+
+def ensure_tax_category_exists(name):
+ if not frappe.db.exists('Tax Category', name):
+ doc = frappe.new_doc('Tax Category')
+ doc.title = name
+ doc.save()
From 50794407b49469682a53b6f91dd3257ca7b25f9d Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Thu, 27 May 2021 14:17:53 +0200
Subject: [PATCH 135/262] feat: Item Tax Templates for Germany
---
.../setup_wizard/data/country_wise_tax.json | 307 +++++++++++++-----
1 file changed, 232 insertions(+), 75 deletions(-)
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 5876488033..2e2a0ca726 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -485,33 +485,32 @@
"SKR04 mit Kontonummern": {
"sales_tax_templates": [
{
- "title": "Umsatzsteuer 19%",
+ "title": "Umsatzsteuer",
+ "tax_category": "Umsatzsteuer",
"taxes": [
{
"account_head": {
"account_name": "Umsatzsteuer 19%",
"account_number": "3806",
"tax_rate": 19.00
- }
- }
- ]
- },
- {
- "title": "Umsatzsteuer 7%",
- "taxes": [
+ },
+ "rate": 0.00
+ },
{
"account_head": {
"account_name": "Umsatzsteuer 7%",
"account_number": "3801",
"tax_rate": 7.00
- }
+ },
+ "rate": 0.00
}
]
}
],
"purchase_tax_templates": [
{
- "title": "Abziehbare Vorsteuer 19%",
+ "title": "Vorsteuer",
+ "tax_category": "Vorsteuer",
"taxes": [
{
"account_head": {
@@ -519,25 +518,23 @@
"account_number": "1406",
"root_type": "Asset",
"tax_rate": 19.00
- }
- }
- ]
- },
- {
- "title": "Abziehbare Vorsteuer 7%",
- "taxes": [
+ },
+ "rate": 0.00
+ },
{
"account_head": {
"account_name": "Abziehbare Vorsteuer 7%",
"account_number": "1401",
"root_type": "Asset",
"tax_rate": 7.00
- }
+ },
+ "rate": 0.00
}
]
},
{
"title": "Innergemeinschaftlicher Erwerb 19% Umsatzsteuer und 19% Vorsteuer",
+ "tax_category": "Innergemeinschaftlicher Erwerb 19%",
"taxes": [
{
"account_head": {
@@ -564,33 +561,32 @@
"SKR03 mit Kontonummern": {
"sales_tax_templates": [
{
- "title": "Umsatzsteuer 19%",
+ "title": "Umsatzsteuer",
+ "tax_category": "Umsatzsteuer",
"taxes": [
{
"account_head": {
"account_name": "Umsatzsteuer 19%",
"account_number": "1776",
"tax_rate": 19.00
- }
- }
- ]
- },
- {
- "title": "Umsatzsteuer 7%",
- "taxes": [
+ },
+ "rate": 0.00
+ },
{
"account_head": {
"account_name": "Umsatzsteuer 7%",
"account_number": "1771",
"tax_rate": 7.00
- }
+ },
+ "rate": 0.00
}
]
}
],
"purchase_tax_templates": [
{
- "title": "Abziehbare Vorsteuer 19%",
+ "title": "Vorsteuer",
+ "tax_category": "Vorsteuer",
"taxes": [
{
"account_head": {
@@ -598,20 +594,17 @@
"account_number": "1576",
"root_type": "Asset",
"tax_rate": 19.00
- }
- }
- ]
- },
- {
- "title": "Abziehbare Vorsteuer 7%",
- "taxes": [
+ },
+ "rate": 0.00
+ },
{
"account_head": {
"account_name": "Abziehbare Vorsteuer 7%",
"account_number": "1571",
"root_type": "Asset",
"tax_rate": 7.00
- }
+ },
+ "rate": 0.00
}
]
}
@@ -620,33 +613,32 @@
"Standard with Numbers": {
"sales_tax_templates": [
{
- "title": "Umsatzsteuer 19%",
+ "title": "Umsatzsteuer",
+ "tax_category": "Umsatzsteuer",
"taxes": [
{
"account_head": {
"account_name": "Umsatzsteuer 19%",
"account_number": "2301",
"tax_rate": 19.00
- }
- }
- ]
- },
- {
- "title": "Umsatzsteuer 7%",
- "taxes": [
+ },
+ "rate": 0.00
+ },
{
"account_head": {
"account_name": "Umsatzsteuer 7%",
"account_number": "2302",
"tax_rate": 7.00
- }
+ },
+ "rate": 0.00
}
]
}
],
"purchase_tax_templates": [
{
- "title": "Abziehbare Vorsteuer 19%",
+ "title": "Vorsteuer",
+ "tax_category": "Vorsteuer",
"taxes": [
{
"account_head": {
@@ -654,20 +646,107 @@
"account_number": "1501",
"root_type": "Asset",
"tax_rate": 19.00
- }
- }
- ]
- },
- {
- "title": "Abziehbare Vorsteuer 7%",
- "taxes": [
+ },
+ "rate": 0.00
+ },
{
"account_head": {
"account_name": "Abziehbare Vorsteuer 7%",
"account_number": "1502",
"root_type": "Asset",
"tax_rate": 7.00
- }
+ },
+ "rate": 0.00
+ }
+ ]
+ }
+ ],
+ "item_tax_templates": [
+ {
+ "title": "Umsatzsteuer 19%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "account_number": "2301",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 7%",
+ "account_number": "2302",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 0.00
+ }
+ ]
+ },
+ {
+ "title": "Umsatzsteuer 7%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "account_number": "2301",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 7%",
+ "account_number": "2302",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 7.00
+ }
+ ]
+ },
+ {
+ "title": "Vorsteuer 19%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "account_number": "1501",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "account_number": "1502",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 0.00
+ }
+ ]
+ },
+ {
+ "title": "Vorsteuer 7%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "account_number": "1501",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "account_number": "1502",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 7.00
}
]
}
@@ -676,13 +755,67 @@
"*": {
"sales_tax_templates": [
{
- "title": "Umsatzsteuer 19%",
+ "title": "Umsatzsteuer",
+ "tax_category": "Umsatzsteuer",
"taxes": [
{
"account_head": {
"account_name": "Umsatzsteuer 19%",
"tax_rate": 19.00
- }
+ },
+ "rate": 0.00
+ },
+ {
+ "account_head": {
+ "account_name": "Umsatzsteuer 7%",
+ "tax_rate": 7.00
+ },
+ "rate": 0.00
+ }
+ ]
+ }
+ ],
+ "purchase_tax_templates": [
+ {
+ "title": "Vorsteuer 19%",
+ "tax_category": "Vorsteuer",
+ "taxes": [
+ {
+ "account_head": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "tax_rate": 19.00,
+ "root_type": "Asset"
+ },
+ "rate": 0.00
+ },
+ {
+ "account_head": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "rate": 0.00
+ }
+ ]
+ }
+ ],
+ "item_tax_templates": [
+ {
+ "title": "Umsatzsteuer 19%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 7%",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 0.00
}
]
},
@@ -690,36 +823,60 @@
"title": "Umsatzsteuer 7%",
"taxes": [
{
- "account_head": {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
"account_name": "Umsatzsteuer 7%",
"tax_rate": 7.00
- }
- }
- ]
- }
- ],
- "purchase_tax_templates": [
- {
- "title": "Abziehbare Vorsteuer 19%",
- "taxes": [
- {
- "account_head": {
- "account_name": "Abziehbare Vorsteuer 19%",
- "tax_rate": 19.00,
- "root_type": "Asset"
- }
+ },
+ "tax_rate": 7.00
}
]
},
{
- "title": "Abziehbare Vorsteuer 7%",
+ "title": "Vorsteuer 19%",
"taxes": [
{
- "account_head": {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
"account_name": "Abziehbare Vorsteuer 7%",
"root_type": "Asset",
"tax_rate": 7.00
- }
+ },
+ "tax_rate": 0.00
+ }
+ ]
+ },
+ {
+ "title": "Vorsteuer 7%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 7.00
}
]
}
From 2e83cb77ca0147b8ab6fd5b0b999cfb5e6f213ea Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 27 May 2021 20:09:45 +0530
Subject: [PATCH 136/262] fix: Split GL Entry
---
.../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 8bb9d7dacf..1ec49d178f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1008,7 +1008,8 @@ class TestPurchaseInvoice(unittest.TestCase):
['_Test Account Cost for Goods Sold - _TC', 30000, 0],
['_Test Account Excise Duty - _TC', 0, 3000],
['Creditors - _TC', 0, 27000],
- ['TDS Payable - _TC', 3000, 3000],
+ ['TDS Payable - _TC', 0, 3000],
+ ['TDS Payable - _TC', 3000, 0]
]
gl_entries = frappe.db.sql("""select account, debit, credit
From a150645b5712f4d7b595a1966c4f0b8600b917f2 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 27 May 2021 20:10:50 +0530
Subject: [PATCH 137/262] fix: Remove GL Entry from print
---
.../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 1ec49d178f..1c4350f8dc 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1017,9 +1017,6 @@ class TestPurchaseInvoice(unittest.TestCase):
where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", (purchase_invoice.name), as_dict=1)
- for gle in gl_entries:
- print(gle.account, gle.debit, gle.credit)
-
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_gle[i][0], gle.account)
self.assertEqual(expected_gle[i][1], gle.debit)
From 5f4527a6a19c504d1d0d637e8038ba5464b2dab4 Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Fri, 28 May 2021 08:55:38 +0530
Subject: [PATCH 138/262] refactor: Use css variables for breakpoint value
---
erpnext/public/scss/shopping_cart.scss | 20 ++++----------------
1 file changed, 4 insertions(+), 16 deletions(-)
diff --git a/erpnext/public/scss/shopping_cart.scss b/erpnext/public/scss/shopping_cart.scss
index 92e5d32219..9402cf9ea4 100644
--- a/erpnext/public/scss/shopping_cart.scss
+++ b/erpnext/public/scss/shopping_cart.scss
@@ -73,15 +73,6 @@ body.product-page {
}
}
- // .card-body {
- // text-align: center;
- // }
-
- // .featured-item {
- // .card-body {
- // text-align: left;
- // }
- // }
.card-img-container {
height: 210px;
width: 100%;
@@ -216,12 +207,12 @@ body.product-page {
border-color: var(--table-border-color) !important;
padding: 15px;
- @media (max-width: 840px) {
+ @media (max-width: var(--md-width)) {
height: 300px;
width: 300px;
}
- @media (min-width: 1090px) {
+ @media (min-width: var(--lg-width)) {
height: 350px;
width: 350px;
}
@@ -233,11 +224,11 @@ body.product-page {
.item-slideshow {
- @media (max-width: 840px) {
+ @media (max-width: var(--md-width)) {
max-height: 320px;
}
- @media (min-width: 1090px) {
+ @media (min-width: var(--lg-width)) {
max-height: 430px;
}
@@ -316,9 +307,6 @@ body.product-page {
}
.item-group-slideshow {
- // .item-group-description {
- // max-width: 900px;
- // }
.carousel-inner.rounded-carousel {
border-radius: var(--card-border-radius);
From 07ba05630e7e5e96a873a75f38160e108faf6fd8 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Thu, 27 May 2021 15:29:41 +0530
Subject: [PATCH 139/262] fix: Add future in requirements.txt
Since future is removed from frappe, adding it as a dependency here
---
requirements.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/requirements.txt b/requirements.txt
index f1ffeb8f48..65688f41e0 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+future==0.18.2
# frappe # https://github.com/frappe/frappe is installed during bench-init
gocardless-pro~=1.22.0
googlemaps # used in ERPNext, but dependency is defined in Frappe
From f93a7a72c1142068e69cfb01367d16b218e945d0 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Thu, 27 May 2021 15:36:26 +0530
Subject: [PATCH 140/262] ci(test): Temporary change to test PY2 compatability
removal in Frappe
---
.github/helper/install.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index 7b0f944c66..8020408904 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -12,7 +12,7 @@ sudo apt install npm
pip install frappe-bench
-git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1
+git clone https://github.com/gavindsouza/frappe --branch drop-py2-code --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
mkdir ~/frappe-bench/sites/test_site
From b084f1d3203b247041695fd50fbc27770eff97d2 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 28 May 2021 11:57:38 +0530
Subject: [PATCH 141/262] fix(India): Show only company addresses for ITC
reversal entry
---
.../doctype/journal_entry/regional/india.js | 17 +++++++++++++++++
.../doctype/gstr_3b_report/gstr_3b_report.py | 2 +-
2 files changed, 18 insertions(+), 1 deletion(-)
create mode 100644 erpnext/accounts/doctype/journal_entry/regional/india.js
diff --git a/erpnext/accounts/doctype/journal_entry/regional/india.js b/erpnext/accounts/doctype/journal_entry/regional/india.js
new file mode 100644
index 0000000000..75a69ac0cf
--- /dev/null
+++ b/erpnext/accounts/doctype/journal_entry/regional/india.js
@@ -0,0 +1,17 @@
+frappe.ui.form.on("Journal Entry", {
+ refresh: function(frm) {
+ frm.set_query('company_address', function(doc) {
+ if(!doc.company) {
+ frappe.throw(__('Please set Company'));
+ }
+
+ return {
+ query: 'frappe.contacts.doctype.address.address.address_query',
+ filters: {
+ link_doctype: 'Company',
+ link_name: doc.company
+ }
+ };
+ });
+ }
+});
\ No newline at end of file
diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
index 3ddcc58867..641520437f 100644
--- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
+++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py
@@ -310,7 +310,7 @@ class GSTR3BReport(Document):
self.report_dict['sup_details']['osup_det']['txval'] += taxable_value
gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category')
- place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply', '00-Other Territory')
+ place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory'
if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \
self.gst_details.get("gst_state") != place_of_supply.split("-")[1]:
From 97687839b0a26251c40994b97eb724e5219163be Mon Sep 17 00:00:00 2001
From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com>
Date: Fri, 28 May 2021 13:39:53 +0530
Subject: [PATCH 142/262] ci: Run mariadb tests after PR merge for coverage
badge
---
.github/workflows/server-tests.yml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 92685e2177..672d96595a 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -1,6 +1,10 @@
name: Server
-on: [pull_request, workflow_dispatch]
+on:
+ pull_request:
+ workflow_dispatch:
+ push:
+ branches: [ develop ]
jobs:
test:
From 49c20f4f8d1913e0eced8e2eb8f9eab9d5bf35c8 Mon Sep 17 00:00:00 2001
From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com>
Date: Fri, 28 May 2021 13:41:14 +0530
Subject: [PATCH 143/262] chore: Update server-site test badge URL
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0a556f57b4..c6fc251244 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
ERP made simple
-[](https://github.com/frappe/erpnext/actions/workflows/ci-tests.yml)
+[](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
[](https://www.codetriage.com/frappe/erpnext)
[](https://coveralls.io/github/frappe/erpnext?branch=develop)
From 6038663bf82cbfa9e019a6a9020f8ccd92631607 Mon Sep 17 00:00:00 2001
From: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
Date: Fri, 28 May 2021 12:59:28 +0200
Subject: [PATCH 144/262] fix: add_deduct_tax in Purchase Taxes setup (#25757)
---
erpnext/setup/setup_wizard/operations/taxes_setup.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py
index 429a558c58..5019837441 100644
--- a/erpnext/setup/setup_wizard/operations/taxes_setup.py
+++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py
@@ -106,6 +106,9 @@ def make_taxes_and_charges_template(company_name, doctype, template):
'charge_type': 'On Net Total'
}
+ if doctype == 'Purchase Taxes and Charges Template':
+ tax_row_defaults['add_deduct_tax'] = 'Add'
+
# if account_head is a dict, search or create the account and get it's name
if isinstance(account_data, dict):
tax_row_defaults['description'] = '{0} @ {1}'.format(account_data.get('account_name'), account_data.get('tax_rate'))
From 2df7f474fabab9440336f48de184c6a27d0119c1 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Fri, 28 May 2021 21:12:10 +0530
Subject: [PATCH 145/262] fix: use dictionary filter instead of list (#25875)
Item query doesn't support list filter anymore.
---
erpnext/manufacturing/doctype/work_order/work_order.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/manufacturing/doctype/work_order/work_order.js b/erpnext/manufacturing/doctype/work_order/work_order.js
index a6086fb88d..3e5a72db9a 100644
--- a/erpnext/manufacturing/doctype/work_order/work_order.js
+++ b/erpnext/manufacturing/doctype/work_order/work_order.js
@@ -76,9 +76,9 @@ frappe.ui.form.on("Work Order", {
frm.set_query("production_item", function() {
return {
query: "erpnext.controllers.queries.item_query",
- filters:[
- ['is_stock_item', '=',1]
- ]
+ filters: {
+ "is_stock_item": 1,
+ }
};
});
From 62996ec980fa23e0b4c58a8f8286904109e44bdc Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 28 May 2021 23:06:15 +0530
Subject: [PATCH 146/262] Revert "ci(test): Temporary change to test PY2
compatability removal in Frappe"
This reverts commit f93a7a72c1142068e69cfb01367d16b218e945d0.
---
.github/helper/install.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index 8020408904..7b0f944c66 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -12,7 +12,7 @@ sudo apt install npm
pip install frappe-bench
-git clone https://github.com/gavindsouza/frappe --branch drop-py2-code --depth 1
+git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
mkdir ~/frappe-bench/sites/test_site
From 05d5fb24f7bdb3c4f7dd069590447b8d5752de70 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Sat, 29 May 2021 23:18:36 +0530
Subject: [PATCH 147/262] fix(test): tax detail report (#25884)
---
erpnext/accounts/report/tax_detail/test_tax_detail.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/report/tax_detail/test_tax_detail.py b/erpnext/accounts/report/tax_detail/test_tax_detail.py
index d3b8de5d19..743ddba024 100644
--- a/erpnext/accounts/report/tax_detail/test_tax_detail.py
+++ b/erpnext/accounts/report/tax_detail/test_tax_detail.py
@@ -71,10 +71,8 @@ class TestTaxDetail(unittest.TestCase):
def rm_testdocs(self):
"Remove the Company and all data"
- from erpnext.setup.doctype.company.delete_company_transactions import delete_company_transactions
- delete_company_transactions(self.company.name)
- self.company.delete()
-
+ from erpnext.setup.doctype.company.company import create_transaction_deletion_request
+ create_transaction_deletion_request(self.company.name)
def test_report(self):
self.load_testdocs()
From 4c94ccc8d8f01715a9a2109c4c9142000fe34c5a Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 31 May 2021 10:51:57 +0530
Subject: [PATCH 148/262] chore: Added change log
---
erpnext/change_log/v13/v13_4_0.md | 54 +++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 erpnext/change_log/v13/v13_4_0.md
diff --git a/erpnext/change_log/v13/v13_4_0.md b/erpnext/change_log/v13/v13_4_0.md
new file mode 100644
index 0000000000..eaf4f762d4
--- /dev/null
+++ b/erpnext/change_log/v13/v13_4_0.md
@@ -0,0 +1,54 @@
+# Version 13.4.0 Release Notes
+
+### Features & Enhancements
+
+- Multiple GST enhancement and fixes ([#25249](https://github.com/frappe/erpnext/pull/25249))
+- Linking supplier with an item group for filtering items ([#25683](https://github.com/frappe/erpnext/pull/25683))
+- Leave Policy Assignment Refactor ([#24327](https://github.com/frappe/erpnext/pull/24327))
+- Dimension-wise Accounts Balance Report ([#25260](https://github.com/frappe/erpnext/pull/25260))
+- Show net values in Party Accounts ([#25714](https://github.com/frappe/erpnext/pull/25714))
+- Add pending qty section to batch/serial selector dialog ([#25519](https://github.com/frappe/erpnext/pull/25519))
+- enhancements in Training Event ([#25782](https://github.com/frappe/erpnext/pull/25782))
+- Refactored timesheet ([#25701](https://github.com/frappe/erpnext/pull/25701))
+
+### Fixes
+
+- Process Statement of Accounts formatting ([#25777](https://github.com/frappe/erpnext/pull/25777))
+- Removed serial no validation for sales invoice ([#25817](https://github.com/frappe/erpnext/pull/25817))
+- Fetch email id from dialog box in pos past order summary ([#25808](https://github.com/frappe/erpnext/pull/25808))
+- Don't map set warehouse from delivery note to purchase receipt ([#25672](https://github.com/frappe/erpnext/pull/25672))
+- Apply permission while selecting projects ([#25765](https://github.com/frappe/erpnext/pull/25765))
+- Error on adding bank account to plaid ([#25658](https://github.com/frappe/erpnext/pull/25658))
+- Set disable rounded total if it is globally enabled ([#25789](https://github.com/frappe/erpnext/pull/25789))
+- Wrong amount on CR side in general ledger report for customer when different account currencies are involved ([#25654](https://github.com/frappe/erpnext/pull/25654))
+- Stock move dialog duplicate submit actions (V13) ([#25486](https://github.com/frappe/erpnext/pull/25486))
+- Cashflow mapper not showing data ([#25815](https://github.com/frappe/erpnext/pull/25815))
+- Ignore rounding diff while importing JV using data import ([#25816](https://github.com/frappe/erpnext/pull/25816))
+- Woocommerce order sync issue ([#25688](https://github.com/frappe/erpnext/pull/25688))
+- Expected amount in pos closing payments table ([#25737](https://github.com/frappe/erpnext/pull/25737))
+- Show only company addresses for ITC reversal entry ([#25867](https://github.com/frappe/erpnext/pull/25867))
+- Timeout error while loading warehouse tree ([#25694](https://github.com/frappe/erpnext/pull/25694))
+- Plaid Withdrawals and Deposits are recorded incorrectly ([#25784](https://github.com/frappe/erpnext/pull/25784))
+- Return case for item with available qty equal to one ([#25760](https://github.com/frappe/erpnext/pull/25760))
+- The status of repost item valuation showing In Progress since long time ([#25754](https://github.com/frappe/erpnext/pull/25754))
+- Updated applicable charges form in landed cost voucher ([#25732](https://github.com/frappe/erpnext/pull/25732))
+- Rearrange buttons for Company DocType ([#25617](https://github.com/frappe/erpnext/pull/25617))
+- Show uom for item in selector dialog ([#25697](https://github.com/frappe/erpnext/pull/25697))
+- Warehouse not found in stock entry ([#25776](https://github.com/frappe/erpnext/pull/25776))
+- Use dictionary filter instead of list (bp #25874 pre-release) ([#25875](https://github.com/frappe/erpnext/pull/25875))
+- Send emails on rfq submit ([#25695](https://github.com/frappe/erpnext/pull/25695))
+- Cannot bypass e-invoicing for non gst item invoices ([#25759](https://github.com/frappe/erpnext/pull/25759))
+- Validation message of quality inspection in purchase receipt ([#25666](https://github.com/frappe/erpnext/pull/25666))
+- Dialog variable assignment after definition in POS ([#25681](https://github.com/frappe/erpnext/pull/25681))
+- Wrong quantity after transaction for parallel stock transactions ([#25779](https://github.com/frappe/erpnext/pull/25779))
+- Item Variant Details Report ([#25797](https://github.com/frappe/erpnext/pull/25797))
+- Duplicate stock entry on multiple click ([#25742](https://github.com/frappe/erpnext/pull/25742))
+- Bank statement import via google sheet ([#25676](https://github.com/frappe/erpnext/pull/25676))
+- Change today to now to get data for reposting ([#25702](https://github.com/frappe/erpnext/pull/25702))
+- Parameter for get_filtered_list_for_consolidated_report in consolidated balance sheet ([#25698](https://github.com/frappe/erpnext/pull/25698))
+- Ageing error in PSOA ([#25857](https://github.com/frappe/erpnext/pull/25857))
+- Breaking cost center validation ([#25660](https://github.com/frappe/erpnext/pull/25660))
+- Project filter for Kanban Board ([#25744](https://github.com/frappe/erpnext/pull/25744))
+- Show allow zero valuation only when auto checked ([#25778](https://github.com/frappe/erpnext/pull/25778))
+- Missing cost center message on creating gl entries ([#25755](https://github.com/frappe/erpnext/pull/25755))
+- Address template with upper filter throws jinja error ([#25756](https://github.com/frappe/erpnext/pull/25756))
From c63e233bc7d60ae71f211ec79747ab39eaa827aa Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 31 May 2021 11:34:33 +0550
Subject: [PATCH 149/262] bumped to version 13.4.0
---
erpnext/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 8d1767497f..20097ef066 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '13.3.1'
+__version__ = '13.4.0'
def get_default_company(user=None):
'''Get default company for user'''
From 7f2ae23dbfed3fe418ea44a072cd898381718db8 Mon Sep 17 00:00:00 2001
From: Eben van Deventer
Date: Mon, 31 May 2021 12:24:29 +0200
Subject: [PATCH 150/262] Correct South Africa VAT Rate
On 1 April 2018 South Africa increased the VAT rate from 14% to 15%, this proposed change seeks to update the default parameters for a fresh ERPNext installation.
This was already done with a commit to version-13 branch under #25894, this proposed change is to ensure that the update is pulled through to future versions.
---
erpnext/setup/setup_wizard/data/country_wise_tax.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 5876488033..512f8ace4a 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -1519,7 +1519,7 @@
"South Africa": {
"South Africa Tax": {
"account_name": "VAT",
- "tax_rate": 14.00
+ "tax_rate": 15.00
}
},
From 5b17f335d1da606f131bf6605f81af0a83bfb864 Mon Sep 17 00:00:00 2001
From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com>
Date: Tue, 1 Jun 2021 08:18:56 +0530
Subject: [PATCH 151/262] ci: Add coveralls_repo_token env variable
---
.github/workflows/server-tests.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/server-tests.yml b/.github/workflows/server-tests.yml
index 672d96595a..69afa15187 100644
--- a/.github/workflows/server-tests.yml
+++ b/.github/workflows/server-tests.yml
@@ -91,6 +91,7 @@ jobs:
coveralls
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
COVERALLS_FLAG_NAME: run-${{ matrix.container }}
COVERALLS_SERVICE_NAME: ${{ github.event_name == 'pull_request' && 'github' || 'github-actions' }}
COVERALLS_PARALLEL: true
From 2f5885627db3f33d3e3f5138bf29ad57f6f46f09 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 1 Jun 2021 11:07:18 +0530
Subject: [PATCH 152/262] fix: Labeling and other fixes
---
.../advance_taxes_and_charges.json | 80 ++++---------
.../doctype/payment_entry/payment_entry.js | 6 +-
.../doctype/payment_entry/payment_entry.json | 5 +-
.../purchase_taxes_and_charges.json | 105 +++++++-----------
.../sales_taxes_and_charges.json | 38 ++++---
.../public/js/controllers/taxes_and_totals.js | 2 +-
6 files changed, 92 insertions(+), 144 deletions(-)
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
index aac7eb6bcb..c127601259 100644
--- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
@@ -36,10 +36,8 @@
"label": "Type",
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
- "options": "\nActual\nOn Paid Amount\nIncluded In Paid Amount\nOn Previous Row Amount\nOn Previous Row Total",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "options": "\nActual\nOn Paid Amount\nOn Previous Row Amount\nOn Previous Row Total",
+ "reqd": 1
},
{
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
@@ -47,9 +45,7 @@
"fieldtype": "Data",
"label": "Reference Row #",
"oldfieldname": "row_id",
- "oldfieldtype": "Data",
- "show_days": 1,
- "show_seconds": 1
+ "oldfieldtype": "Data"
},
{
"columns": 2,
@@ -61,15 +57,11 @@
"oldfieldtype": "Link",
"options": "Account",
"reqd": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"fieldname": "col_break_1",
"fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1,
"width": "50%"
},
{
@@ -80,16 +72,12 @@
"oldfieldtype": "Small Text",
"print_width": "300px",
"reqd": 1,
- "show_days": 1,
- "show_seconds": 1,
"width": "300px"
},
{
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Accounting Dimensions"
},
{
"default": ":Company",
@@ -98,21 +86,15 @@
"label": "Cost Center",
"oldfieldname": "cost_center_other_charges",
"oldfieldtype": "Link",
- "options": "Cost Center",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Cost Center"
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "section_break_8",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"columns": 2,
@@ -121,15 +103,11 @@
"in_list_view": 1,
"label": "Rate",
"oldfieldname": "rate",
- "oldfieldtype": "Currency",
- "show_days": 1,
- "show_seconds": 1
+ "oldfieldtype": "Currency"
},
{
"fieldname": "section_break_9",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"columns": 2,
@@ -137,9 +115,7 @@
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
- "options": "currency",
- "show_days": 1,
- "show_seconds": 1
+ "options": "currency"
},
{
"columns": 2,
@@ -148,15 +124,11 @@
"in_list_view": 1,
"label": "Total",
"options": "currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_13",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "base_tax_amount",
@@ -165,9 +137,7 @@
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_total",
@@ -176,48 +146,38 @@
"oldfieldname": "total",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "add_deduct_tax",
"fieldtype": "Select",
"label": "Add Or Deduct",
"options": "Add\nDeduct",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"default": "0",
"fieldname": "included_in_paid_amount",
"fieldtype": "Check",
- "label": "Included In Paid Amount",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Included In Paid Amount"
},
{
"fieldname": "allocated_amount",
"fieldtype": "Currency",
"label": "Allocated Amount",
- "options": "currency",
- "show_days": 1,
- "show_seconds": 1
+ "options": "currency"
},
{
"fieldname": "base_allocated_amount",
"fieldtype": "Currency",
"label": "Allocated Amount (Company Currency)",
- "options": "Company:company:default_currency",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Company:company:default_currency"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2020-11-29 19:06:14.666460",
+ "modified": "2021-05-31 02:03:57.444647",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index a4022ef40a..b1cf9e02e6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -230,7 +230,7 @@ frappe.ui.form.on('Payment Entry', {
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
frm.set_currency_labels(["base_paid_amount", "base_received_amount", "base_total_allocated_amount",
- "difference_amount", "base_paid_amount_after_tax"], company_currency);
+ "difference_amount", "base_paid_amount_after_tax", "base_received_amount_after_tax"], company_currency);
frm.set_currency_labels(["paid_amount"], frm.doc.paid_from_account_currency);
frm.set_currency_labels(["received_amount"], frm.doc.paid_to_account_currency);
@@ -238,11 +238,13 @@ frappe.ui.form.on('Payment Entry', {
var party_account_currency = frm.doc.payment_type=="Receive" ?
frm.doc.paid_from_account_currency : frm.doc.paid_to_account_currency;
- frm.set_currency_labels(["total_allocated_amount", "unallocated_amount"], party_account_currency);
+ frm.set_currency_labels(["total_allocated_amount", "unallocated_amount",
+ "total_taxes_and_charges"], party_account_currency);
var currency_field = (frm.doc.payment_type=="Receive") ? "paid_from_account_currency" : "paid_to_account_currency"
frm.set_df_property("total_allocated_amount", "options", currency_field);
frm.set_df_property("unallocated_amount", "options", currency_field);
+ frm.set_df_property("total_taxes_and_charges", "options", currency_field);
frm.set_df_property("party_balance", "options", currency_field);
frm.set_currency_labels(["total_amount", "outstanding_amount", "allocated_amount"],
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 1e2bd8194a..0b4178a547 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -335,6 +335,7 @@
"reqd": 1
},
{
+ "depends_on": "doc.received_amount",
"fieldname": "base_received_amount",
"fieldtype": "Currency",
"label": "Received Amount (Company Currency)",
@@ -683,6 +684,7 @@
"fieldname": "advance_tax_account",
"fieldtype": "Link",
"label": "Advance Tax Account",
+ "mandatory_depends_on": "doc.base_total_taxes_and_charges",
"options": "Account"
},
{
@@ -692,6 +694,7 @@
"options": "paid_to_account_currency"
},
{
+ "depends_on": "doc.received_amount",
"fieldname": "base_received_amount_after_tax",
"fieldtype": "Currency",
"label": "Received Amount After Tax (Company Currency)",
@@ -701,7 +704,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-05-20 02:04:56.766124",
+ "modified": "2021-05-31 01:54:18.378910",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index 0db0b6823d..f6703315fa 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -12,6 +12,7 @@
"charge_type",
"row_id",
"included_in_print_rate",
+ "included_in_paid_amount",
"col_break1",
"account_head",
"description",
@@ -21,6 +22,7 @@
"cost_center",
"dimension_col_break",
"section_break_9",
+ "currency",
"tax_amount",
"tax_amount_after_discount_amount",
"total",
@@ -39,9 +41,7 @@
"oldfieldname": "category",
"oldfieldtype": "Select",
"options": "Valuation and Total\nValuation\nTotal",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"default": "Add",
@@ -51,9 +51,7 @@
"oldfieldname": "add_deduct_tax",
"oldfieldtype": "Select",
"options": "Add\nDeduct",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"columns": 2,
@@ -65,9 +63,7 @@
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total\nOn Item Quantity",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
@@ -75,9 +71,7 @@
"fieldtype": "Data",
"label": "Reference Row #",
"oldfieldname": "row_id",
- "oldfieldtype": "Data",
- "show_days": 1,
- "show_seconds": 1
+ "oldfieldtype": "Data"
},
{
"default": "0",
@@ -85,15 +79,11 @@
"fieldname": "included_in_print_rate",
"fieldtype": "Check",
"label": "Is this Tax included in Basic Rate?",
- "report_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "report_hide": 1
},
{
"fieldname": "col_break1",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"columns": 2,
@@ -104,9 +94,7 @@
"oldfieldname": "account_head",
"oldfieldtype": "Link",
"options": "Account",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"default": ":Company",
@@ -115,9 +103,7 @@
"label": "Cost Center",
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
- "options": "Cost Center",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Cost Center"
},
{
"fieldname": "description",
@@ -127,15 +113,11 @@
"oldfieldtype": "Small Text",
"print_width": "300px",
"reqd": 1,
- "show_days": 1,
- "show_seconds": 1,
"width": "300px"
},
{
"fieldname": "section_break_10",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"columns": 2,
@@ -144,15 +126,11 @@
"in_list_view": 1,
"label": "Rate",
"oldfieldname": "rate",
- "oldfieldtype": "Currency",
- "show_days": 1,
- "show_seconds": 1
+ "oldfieldtype": "Currency"
},
{
"fieldname": "section_break_9",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"columns": 2,
@@ -162,9 +140,7 @@
"label": "Amount",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
- "options": "currency",
- "show_days": 1,
- "show_seconds": 1
+ "options": "currency"
},
{
"fieldname": "tax_amount_after_discount_amount",
@@ -172,9 +148,7 @@
"label": "Tax Amount After Discount Amount",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"columns": 2,
@@ -185,15 +159,11 @@
"oldfieldname": "total",
"oldfieldtype": "Currency",
"options": "currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_14",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "base_tax_amount",
@@ -201,9 +171,7 @@
"label": "Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_total",
@@ -211,9 +179,7 @@
"hidden": 1,
"label": "Total (Company Currency)",
"options": "Company:company:default_currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "base_tax_amount_after_discount_amount",
@@ -221,9 +187,7 @@
"label": "Tax Amount After Discount Amount",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "item_wise_tax_detail",
@@ -233,28 +197,37 @@
"oldfieldname": "item_wise_tax_detail",
"oldfieldtype": "Small Text",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Accounting Dimensions"
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "account_head.account_currency",
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Account Currency",
+ "options": "Currency",
+ "read_only": 1
+ },
+ {
+ "default": "0",
+ "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
+ "fieldname": "included_in_paid_amount",
+ "fieldtype": "Check",
+ "label": "Included In Paid Amount"
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-11-29 19:11:58.826078",
+ "modified": "2021-05-31 03:41:38.298937",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
index 3c8cb6b851..36fd634b50 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
@@ -1,8 +1,10 @@
{
+ "actions": [],
"creation": "2013-04-24 11:39:32",
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
+ "engine": "InnoDB",
"field_order": [
"charge_type",
"row_id",
@@ -10,12 +12,14 @@
"col_break_1",
"description",
"included_in_print_rate",
+ "included_in_paid_amount",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
"section_break_8",
"rate",
"section_break_9",
+ "currency",
"tax_amount",
"total",
"tax_amount_after_discount_amount",
@@ -23,8 +27,7 @@
"base_tax_amount",
"base_total",
"base_tax_amount_after_discount_amount",
- "item_wise_tax_detail",
- "parenttype"
+ "item_wise_tax_detail"
],
"fields": [
{
@@ -173,17 +176,6 @@
"oldfieldtype": "Small Text",
"read_only": 1
},
- {
- "fieldname": "parenttype",
- "fieldtype": "Data",
- "hidden": 1,
- "in_filter": 1,
- "label": "Parenttype",
- "oldfieldname": "parenttype",
- "oldfieldtype": "Data",
- "print_hide": 1,
- "search_index": 1
- },
{
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
@@ -192,15 +184,33 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "account_head.account_currency",
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Account Currency",
+ "options": "Currency",
+ "read_only": 1
+ },
+ {
+ "default": "0",
+ "description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
+ "fieldname": "included_in_paid_amount",
+ "fieldtype": "Check",
+ "label": "Included In Paid Amount"
}
],
"idx": 1,
+ "index_web_pages_for_search": 1,
"istable": 1,
- "modified": "2019-05-25 22:59:38.740883",
+ "links": [],
+ "modified": "2021-05-31 05:40:32.856780",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
"owner": "Administrator",
"permissions": [],
+ "sort_field": "modified",
"sort_order": "ASC"
}
\ No newline at end of file
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 2e133bed2e..3097f72201 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -464,7 +464,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
},
calculate_totals: function() {
- // Changing sequence can cause rounding_adjustmentng issue and on-screen discrepency
+ // Changing sequence can because of rounding adjustment issue and on-screen discrepancy
var me = this;
var tax_count = this.frm.doc["taxes"] ? this.frm.doc["taxes"].length : 0;
this.frm.doc.grand_total = flt(tax_count
From eff8f6fe34d5571795b1e5f037529c10c1744d04 Mon Sep 17 00:00:00 2001
From: Sagar Vora
Date: Tue, 1 Jun 2021 19:57:17 +0530
Subject: [PATCH 153/262] fix(Payroll): no need to set `abbr` specially in
Salary Slip (#25877)
---
erpnext/payroll/doctype/salary_slip/salary_slip.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index afdf081ac8..3c2533131b 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -621,16 +621,13 @@ class SalarySlip(TransactionBase):
component_row = self.append(component_type)
for attr in (
- 'depends_on_payment_days', 'salary_component',
+ 'depends_on_payment_days', 'salary_component', 'abbr',
'do_not_include_in_total', 'is_tax_applicable',
'is_flexible_benefit', 'variable_based_on_taxable_salary',
'exempted_from_income_tax'
):
component_row.set(attr, component_data.get(attr))
- abbr = component_data.get('abbr') or component_data.get('salary_component_abbr')
- component_row.set('abbr', abbr)
-
if additional_salary:
component_row.default_amount = 0
component_row.additional_amount = amount
From 5dd92934aef8dfe89555560ff5b9680596d33bff Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Wed, 2 Jun 2021 14:13:09 +0530
Subject: [PATCH 154/262] fix: not able to select the item code in work order
---
erpnext/controllers/queries.py | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 46301b7587..638503edfa 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -204,7 +204,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
if "description" in searchfields:
searchfields.remove("description")
-
+
columns = ''
extra_searchfields = [field for field in searchfields
if not field in ["name", "item_group", "description"]]
@@ -216,9 +216,10 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
if not field in searchfields]
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
- if filters.get('supplier'):
- item_group_list = frappe.get_all('Supplier Item Group', filters = {'supplier': filters.get('supplier')}, fields = ['item_group'])
-
+ if filters and isinstance(filters, dict) and filters.get('supplier'):
+ item_group_list = frappe.get_all('Supplier Item Group',
+ filters = {'supplier': filters.get('supplier')}, fields = ['item_group'])
+
item_groups = []
for i in item_group_list:
item_groups.append(i.item_group)
@@ -227,7 +228,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
if item_groups:
filters['item_group'] = ['in', item_groups]
-
+
description_cond = ''
if frappe.db.count('Item', cache=True) < 50000:
# scan description only if items are less than 50000
From f259bf48aaa40630b0a7b08b6d323a14ffc8aa03 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 2 Jun 2021 13:20:03 +0200
Subject: [PATCH 155/262] refactor: make tax category
---
.../setup_wizard/data/country_wise_tax.json | 4 +++
.../setup_wizard/operations/taxes_setup.py | 33 +++++++++++--------
2 files changed, 24 insertions(+), 13 deletions(-)
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 2e2a0ca726..5ed8ab92bf 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -481,6 +481,10 @@
},
"Germany": {
+ "tax_categories": [
+ "Umsatzsteuer",
+ "Vorsteuer"
+ ],
"chart_of_accounts": {
"SKR04 mit Kontonummern": {
"sales_tax_templates": [
diff --git a/erpnext/setup/setup_wizard/operations/taxes_setup.py b/erpnext/setup/setup_wizard/operations/taxes_setup.py
index 4a3de957b9..f4fe18e116 100644
--- a/erpnext/setup/setup_wizard/operations/taxes_setup.py
+++ b/erpnext/setup/setup_wizard/operations/taxes_setup.py
@@ -26,7 +26,7 @@ def setup_taxes_and_charges(company_name: str, country: str):
if 'chart_of_accounts' not in country_wise_tax:
country_wise_tax = simple_to_detailed(country_wise_tax)
- from_detailed_data(company_name, country_wise_tax.get('chart_of_accounts'))
+ from_detailed_data(company_name, country_wise_tax)
def simple_to_detailed(templates):
@@ -77,10 +77,16 @@ def simple_to_detailed(templates):
def from_detailed_data(company_name, data):
"""Create Taxes and Charges Templates from detailed data."""
coa_name = frappe.db.get_value('Company', company_name, 'chart_of_accounts')
- tax_templates = data.get(coa_name) or data.get('*')
- sales_tax_templates = tax_templates.get('sales_tax_templates') or tax_templates.get('*')
- purchase_tax_templates = tax_templates.get('purchase_tax_templates') or tax_templates.get('*')
- item_tax_templates = tax_templates.get('item_tax_templates') or tax_templates.get('*')
+ coa_data = data.get('chart_of_accounts', {})
+ tax_templates = coa_data.get(coa_name) or coa_data.get('*', {})
+ tax_categories = data.get('tax_categories')
+ sales_tax_templates = tax_templates.get('sales_tax_templates') or tax_templates.get('*', {})
+ purchase_tax_templates = tax_templates.get('purchase_tax_templates') or tax_templates.get('*', {})
+ item_tax_templates = tax_templates.get('item_tax_templates') or tax_templates.get('*', {})
+
+ if tax_categories:
+ for tax_category in tax_categories:
+ make_tax_catgory(tax_category)
if sales_tax_templates:
for template in sales_tax_templates:
@@ -102,9 +108,6 @@ def make_taxes_and_charges_template(company_name, doctype, template):
if frappe.db.exists(doctype, {'title': template.get('title'), 'company': company_name}):
return
- if template.get('tax_category'):
- ensure_tax_category_exists(template.get('tax_category'))
-
for tax_row in template.get('taxes'):
account_data = tax_row.get('account_head')
tax_row_defaults = {
@@ -241,8 +244,12 @@ def get_or_create_tax_group(company_name, root_type):
return tax_group_name
-def ensure_tax_category_exists(name):
- if not frappe.db.exists('Tax Category', name):
- doc = frappe.new_doc('Tax Category')
- doc.title = name
- doc.save()
+def make_tax_catgory(tax_category):
+ doctype = 'Tax Category'
+ if isinstance(tax_category, str):
+ tax_category = {'title': tax_category}
+
+ tax_category['doctype'] = doctype
+ if not frappe.db.exists(doctype, tax_category['title']):
+ doc = frappe.get_doc(tax_category)
+ doc.insert(ignore_permissions=True)
From b6f27a4caef1fd479762579fd6f612fdc78fa69d Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 2 Jun 2021 13:20:33 +0200
Subject: [PATCH 156/262] feat: set is_default for german tax templates
---
erpnext/setup/setup_wizard/data/country_wise_tax.json | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 5ed8ab92bf..f4728ef398 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -491,6 +491,7 @@
{
"title": "Umsatzsteuer",
"tax_category": "Umsatzsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
@@ -515,6 +516,7 @@
{
"title": "Vorsteuer",
"tax_category": "Vorsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
@@ -567,6 +569,7 @@
{
"title": "Umsatzsteuer",
"tax_category": "Umsatzsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
@@ -591,6 +594,7 @@
{
"title": "Vorsteuer",
"tax_category": "Vorsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
@@ -619,6 +623,7 @@
{
"title": "Umsatzsteuer",
"tax_category": "Umsatzsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
@@ -643,6 +648,7 @@
{
"title": "Vorsteuer",
"tax_category": "Vorsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
@@ -761,6 +767,7 @@
{
"title": "Umsatzsteuer",
"tax_category": "Umsatzsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
@@ -783,6 +790,7 @@
{
"title": "Vorsteuer 19%",
"tax_category": "Vorsteuer",
+ "is_default": 1,
"taxes": [
{
"account_head": {
From 3c748efae3cfc78a88447ac9edeccfea860f1358 Mon Sep 17 00:00:00 2001
From: barredterra <14891507+barredterra@users.noreply.github.com>
Date: Wed, 2 Jun 2021 13:27:15 +0200
Subject: [PATCH 157/262] feat: add Item Tax Templates for german COAs "SKR03"
and "SKR04"
---
.../setup_wizard/data/country_wise_tax.json | 180 ++++++++++++++++++
1 file changed, 180 insertions(+)
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index f4728ef398..8305cae73e 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -562,6 +562,96 @@
}
]
}
+ ],
+ "item_tax_templates": [
+ {
+ "title": "Umsatzsteuer 19%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "account_number": "3806",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 7%",
+ "account_number": "3801",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 0.00
+ }
+ ]
+ },
+ {
+ "title": "Umsatzsteuer 7%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "account_number": "3806",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 7%",
+ "account_number": "3801",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 7.00
+ }
+ ]
+ },
+ {
+ "title": "Vorsteuer 19%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "account_number": "1406",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "account_number": "1401",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 0.00
+ }
+ ]
+ },
+ {
+ "title": "Vorsteuer 7%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "account_number": "1406",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "account_number": "1401",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 7.00
+ }
+ ]
+ }
]
},
"SKR03 mit Kontonummern": {
@@ -616,6 +706,96 @@
}
]
}
+ ],
+ "item_tax_templates": [
+ {
+ "title": "Umsatzsteuer 19%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "account_number": "1776",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 7%",
+ "account_number": "1771",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 0.00
+ }
+ ]
+ },
+ {
+ "title": "Umsatzsteuer 7%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 19%",
+ "account_number": "1776",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Umsatzsteuer 7%",
+ "account_number": "1771",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 7.00
+ }
+ ]
+ },
+ {
+ "title": "Vorsteuer 19%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "account_number": "1576",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 19.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "account_number": "1571",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 0.00
+ }
+ ]
+ },
+ {
+ "title": "Vorsteuer 7%",
+ "taxes": [
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 19%",
+ "account_number": "1576",
+ "root_type": "Asset",
+ "tax_rate": 19.00
+ },
+ "tax_rate": 0.00
+ },
+ {
+ "tax_type": {
+ "account_name": "Abziehbare Vorsteuer 7%",
+ "account_number": "1571",
+ "root_type": "Asset",
+ "tax_rate": 7.00
+ },
+ "tax_rate": 7.00
+ }
+ ]
+ }
]
},
"Standard with Numbers": {
From f6627550d11ea95170ce5f208a257bb31218585f Mon Sep 17 00:00:00 2001
From: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
Date: Wed, 2 Jun 2021 15:17:00 +0200
Subject: [PATCH 158/262] fix: remove wrong tax_category
---
erpnext/setup/setup_wizard/data/country_wise_tax.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/erpnext/setup/setup_wizard/data/country_wise_tax.json b/erpnext/setup/setup_wizard/data/country_wise_tax.json
index 8305cae73e..ec9a6d6b70 100644
--- a/erpnext/setup/setup_wizard/data/country_wise_tax.json
+++ b/erpnext/setup/setup_wizard/data/country_wise_tax.json
@@ -540,7 +540,6 @@
},
{
"title": "Innergemeinschaftlicher Erwerb 19% Umsatzsteuer und 19% Vorsteuer",
- "tax_category": "Innergemeinschaftlicher Erwerb 19%",
"taxes": [
{
"account_head": {
From 8821d71094729ba0ce576414486d0fcf91035f0e Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Wed, 2 Jun 2021 22:34:19 +0550
Subject: [PATCH 159/262] bumped to version 13.4.1
---
erpnext/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 20097ef066..5808090db3 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '13.4.0'
+__version__ = '13.4.1'
def get_default_company(user=None):
'''Get default company for user'''
From f899b3a633f7d43e3b44c17ad69e300298e7ba95 Mon Sep 17 00:00:00 2001
From: Anoop <3326959+akurungadam@users.noreply.github.com>
Date: Thu, 3 Jun 2021 09:24:31 +0530
Subject: [PATCH 160/262] fix: update linked Customer on Patient update only if
Link Customer to Patient is enabled (#25921)
---
erpnext/healthcare/doctype/patient/patient.py | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/erpnext/healthcare/doctype/patient/patient.py b/erpnext/healthcare/doctype/patient/patient.py
index 789d452c07..56a34007ff 100644
--- a/erpnext/healthcare/doctype/patient/patient.py
+++ b/erpnext/healthcare/doctype/patient/patient.py
@@ -33,21 +33,20 @@ class Patient(Document):
self.reload() # self.notify_update()
def on_update(self):
- if self.customer:
- customer = frappe.get_doc('Customer', self.customer)
- if self.customer_group:
- customer.customer_group = self.customer_group
- if self.territory:
- customer.territory = self.territory
-
- customer.customer_name = self.patient_name
- customer.default_price_list = self.default_price_list
- customer.default_currency = self.default_currency
- customer.language = self.language
- customer.ignore_mandatory = True
- customer.save(ignore_permissions=True)
- else:
- if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient'):
+ if frappe.db.get_single_value('Healthcare Settings', 'link_customer_to_patient'):
+ if self.customer:
+ customer = frappe.get_doc('Customer', self.customer)
+ if self.customer_group:
+ customer.customer_group = self.customer_group
+ if self.territory:
+ customer.territory = self.territory
+ customer.customer_name = self.patient_name
+ customer.default_price_list = self.default_price_list
+ customer.default_currency = self.default_currency
+ customer.language = self.language
+ customer.ignore_mandatory = True
+ customer.save(ignore_permissions=True)
+ else:
create_customer(self)
def set_full_name(self):
From 4e10ce163263b750f02091f2ad236681e34deffe Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Thu, 27 May 2021 17:05:36 +0530
Subject: [PATCH 161/262] fix: timeout error in the repost item valuation
---
erpnext/hooks.py | 4 +++-
.../repost_item_valuation/repost_item_valuation.py | 13 ++++---------
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 55169dffba..8ad77a1524 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -332,7 +332,9 @@ scheduler_events = {
"erpnext.projects.doctype.project.project.collect_project_status",
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
- "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
+ "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders"
+ ],
+ "hourly_long": [
"erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries"
],
"daily": [
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 5b626ea345..55f2ebb224 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -37,6 +37,9 @@ class RepostItemValuation(Document):
self.db_set('status', status)
def on_submit(self):
+ if not frappe.flags.in_test:
+ return
+
frappe.enqueue(repost, timeout=1800, queue='long',
job_name='repost_sle', now=frappe.flags.in_test, doc=self)
@@ -115,12 +118,6 @@ def notify_error_to_stock_managers(doc, traceback):
frappe.sendmail(recipients=recipients, subject=subject, message=message)
def repost_entries():
- job_log = frappe.get_all('Scheduled Job Log', fields = ['status', 'creation'],
- filters = {'scheduled_job_type': 'repost_item_valuation.repost_entries'}, order_by='creation desc', limit=1)
-
- if job_log and job_log[0]['status'] == 'Start' and time_diff_in_hours(now(), job_log[0]['creation']) < 2:
- return
-
riv_entries = get_repost_item_valuation_entries()
for row in riv_entries:
@@ -135,9 +132,7 @@ def repost_entries():
check_if_stock_and_account_balance_synced(today(), d.name)
def get_repost_item_valuation_entries():
- date = add_to_date(now(), hours=-3)
-
return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation`
WHERE status != 'Completed' and creation <= %s and docstatus = 1
ORDER BY timestamp(posting_date, posting_time) asc, creation asc
- """, date, as_dict=1)
+ """, now(), as_dict=1)
From 8449a4704897d090f4277d895533630ea3bb0c2d Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Thu, 3 Jun 2021 17:57:01 +0530
Subject: [PATCH 162/262] fix: filter type for item query
---
erpnext/controllers/queries.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 638503edfa..81ac234e70 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
import erpnext
+import json
from frappe.desk.reportview import get_match_cond, get_filters_cond
from frappe.utils import nowdate, getdate
from collections import defaultdict
@@ -198,6 +199,9 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
conditions = []
+ if isinstance(filters, str):
+ filters = json.loads(filters)
+
#Get searchfields from meta and use in Item Link field query
meta = frappe.get_meta("Item", cached=True)
searchfields = meta.get_search_fields()
From 3e920892001856ce8157d44778cae618a2a4babf Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Fri, 4 Jun 2021 11:15:38 +0530
Subject: [PATCH 163/262] fix: invalid 'depends_on' expression in opportunity
(#25953)
---
erpnext/crm/doctype/opportunity/opportunity.json | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json
index 2e09a76c0f..4ba4140244 100644
--- a/erpnext/crm/doctype/opportunity/opportunity.json
+++ b/erpnext/crm/doctype/opportunity/opportunity.json
@@ -280,7 +280,6 @@
"read_only": 1
},
{
- "depends_on": "eval:",
"fieldname": "territory",
"fieldtype": "Link",
"label": "Territory",
@@ -431,7 +430,7 @@
"icon": "fa fa-info-sign",
"idx": 195,
"links": [],
- "modified": "2021-01-06 19:42:46.190051",
+ "modified": "2021-06-04 10:11:22.831139",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",
From 5bf5775b4373c84d3834f56cdc568f952798024b Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 11:44:40 +0530
Subject: [PATCH 164/262] chore: Drop old patches
v7 backup was restored and upgraded to latest v10.x.x branch. The
patches run uptil the upgrade are removed in this change. This means
only existing v10 sites are allowed direct upgrade to v13 and newer
---
erpnext/patches/repair_tools/__init__.py | 0
.../set_stock_balance_as_per_serial_no.py | 13 -
erpnext/patches/v10_0/__init__.py | 0
.../patches/v10_0/add_agriculture_domain.py | 13 -
.../add_guardian_role_for_parent_portal.py | 23 --
.../patches/v10_0/add_non_profit_domain.py | 20 --
.../allow_operators_in_supplier_scorecard.py | 23 --
.../v10_0/copy_projects_renamed_fields.py | 13 -
..._regional_print_format_based_on_country.py | 22 --
.../fix_reserved_qty_for_sub_contract.py | 31 ---
.../recalculate_gross_margin_for_project.py | 14 -
.../v10_0/rename_schools_to_education.py | 32 ---
...r_purchase_receipts_with_rejected_items.py | 32 ---
...t_requested_qty_for_non_stock_uom_items.py | 21 --
...t_auto_created_serial_no_in_stock_entry.py | 56 ----
erpnext/patches/v10_0/set_b2c_limit.py | 12 -
..._default_payment_terms_based_on_company.py | 37 ---
erpnext/patches/v10_0/set_discount_amount.py | 35 ---
...set_numeric_ranges_in_template_if_blank.py | 35 ---
.../v10_0/set_primary_contact_for_customer.py | 21 --
...n_transactions_based_on_serial_no_input.py | 21 --
.../patches/v10_0/set_student_party_type.py | 8 -
.../setup_vat_for_uae_and_saudi_arabia.py | 13 -
...s_of_all_department_members_in_calendar.py | 6 -
erpnext/patches/v10_0/taxes_issue_with_pos.py | 26 --
.../update_address_template_for_india.py | 12 -
.../patches/v10_0/update_assessment_plan.py | 17 --
.../patches/v10_0/update_assessment_result.py | 20 --
.../update_asset_calculate_depreciation.py | 12 -
.../v10_0/update_hub_connector_domain.py | 10 -
.../v10_0/update_lft_rgt_for_employee.py | 9 -
.../patches/v10_0/update_project_in_sle.py | 15 --
.../update_reserved_qty_for_purchase_order.py | 53 ----
...date_sales_order_link_to_purchase_order.py | 18 --
...update_status_for_multiple_source_in_po.py | 40 ---
.../update_status_in_purchase_receipt.py | 8 -
.../update_territory_and_customer_group.py | 29 ---
.../v10_0/update_user_image_in_employee.py | 19 --
.../v10_0/update_warehouse_address_details.py | 37 ---
erpnext/patches/v10_1/__init__.py | 0
erpnext/patches/v11_0/__init__.py | 1 -
.../v11_0/remove_subscriber_doctype.py | 16 --
erpnext/patches/v11_1/__init__.py | 0
erpnext/patches/v12_0/__init__.py | 0
erpnext/patches/v13_0/__init__.py | 1 -
erpnext/patches/v4_0/__init__.py | 0
.../patches/v4_0/apply_user_permissions.py | 50 ----
erpnext/patches/v4_0/countrywise_coa.py | 29 ---
...custom_fields_for_india_specific_fields.py | 63 -----
.../v4_0/create_price_list_if_missing.py | 35 ---
.../v4_0/customer_discount_to_pricing_rule.py | 33 ---
erpnext/patches/v4_0/fields_to_be_renamed.py | 109 --------
erpnext/patches/v4_0/fix_address_template.py | 12 -
.../patches/v4_0/fix_case_of_hr_module_def.py | 13 -
erpnext/patches/v4_0/fix_contact_address.py | 13 -
erpnext/patches/v4_0/fix_employee_user_id.py | 23 --
.../global_defaults_to_system_settings.py | 39 ---
erpnext/patches/v4_0/import_country_codes.py | 15 --
.../v4_0/map_charge_to_taxes_and_charges.py | 16 --
.../move_warehouse_user_to_restrictions.py | 13 -
erpnext/patches/v4_0/new_address_template.py | 14 -
.../patches/v4_0/reload_sales_print_format.py | 8 -
.../remove_employee_role_if_no_employee.py | 18 --
.../patches/v4_0/remove_module_home_pages.py | 10 -
.../patches/v4_0/rename_sitemap_to_route.py | 17 --
.../v4_0/reset_permissions_for_masters.py | 20 --
.../patches/v4_0/save_default_letterhead.py | 13 -
.../set_pricing_rule_for_buying_or_selling.py | 13 -
erpnext/patches/v4_0/split_email_settings.py | 67 -----
.../patches/v4_0/update_account_root_type.py | 34 ---
...custom_print_formats_for_renamed_fields.py | 36 ---
...to_sales_person_in_maintenance_schedule.py | 12 -
...harges_in_custom_purchase_print_formats.py | 12 -
.../v4_0/update_tax_amount_after_discount.py | 20 --
.../patches/v4_0/update_user_properties.py | 51 ----
.../v4_0/update_users_report_view_settings.py | 12 -
erpnext/patches/v4_0/validate_v3_patch.py | 11 -
erpnext/patches/v4_1/__init__.py | 0
.../v4_1/fix_delivery_and_billing_status.py | 12 -
erpnext/patches/v4_1/fix_jv_remarks.py | 21 --
.../v4_1/fix_sales_order_delivered_status.py | 15 --
.../patches/v4_1/set_outgoing_email_footer.py | 12 -
erpnext/patches/v4_2/__init__.py | 0
.../patches/v4_2/add_currency_turkish_lira.py | 10 -
erpnext/patches/v4_2/default_website_style.py | 11 -
...elete_gl_entries_for_cancelled_invoices.py | 14 -
.../patches/v4_2/delete_old_print_formats.py | 23 --
erpnext/patches/v4_2/discount_amount.py | 12 -
.../patches/v4_2/fix_account_master_type.py | 12 -
.../fix_gl_entries_for_stock_transactions.py | 54 ----
erpnext/patches/v4_2/fix_recurring_orders.py | 41 ---
erpnext/patches/v4_2/party_model.py | 117 ---------
erpnext/patches/v4_2/recalculate_bom_cost.py | 16 --
.../repost_sle_for_si_with_no_warehouse.py | 34 ---
.../v4_2/repost_stock_reconciliation.py | 31 ---
erpnext/patches/v4_2/reset_bom_costs.py | 17 --
.../v4_2/seprate_manufacture_and_repack.py | 9 -
erpnext/patches/v4_2/set_company_country.py | 15 --
erpnext/patches/v4_2/set_item_has_batch.py | 65 -----
erpnext/patches/v4_2/toggle_rounded_total.py | 9 -
.../v4_2/update_landed_cost_voucher.py | 10 -
.../patches/v4_2/update_project_milestones.py | 9 -
.../update_sales_order_invoice_field_name.py | 7 -
.../v4_2/update_stock_uom_for_dn_in_sle.py | 11 -
erpnext/patches/v4_4/__init__.py | 0
erpnext/patches/v4_4/make_email_accounts.py | 96 -------
erpnext/patches/v5_0/__init__.py | 0
.../v5_0/convert_stock_reconciliation.py | 31 ---
.../patches/v5_0/execute_on_doctype_update.py | 9 -
.../fix_taxes_and_totals_in_party_currency.py | 66 -----
.../v5_0/index_on_account_and_gl_entry.py | 30 ---
erpnext/patches/v5_0/is_group.py | 9 -
erpnext/patches/v5_0/item_patches.py | 6 -
.../v5_0/link_warehouse_with_account.py | 10 -
erpnext/patches/v5_0/new_crm_module.py | 24 --
erpnext/patches/v5_0/newsletter.py | 38 ---
.../v5_0/opportunity_not_submittable.py | 10 -
erpnext/patches/v5_0/party_model_patch_fix.py | 18 --
erpnext/patches/v5_0/portal_fixes.py | 7 -
erpnext/patches/v5_0/project_costing.py | 8 -
.../v5_0/recalculate_total_amount_in_jv.py | 26 --
...nned_operating_cost_in_production_order.py | 13 -
.../patches/v5_0/remove_birthday_events.py | 7 -
erpnext/patches/v5_0/rename_customer_issue.py | 6 -
erpnext/patches/v5_0/rename_pos_setting.py | 6 -
.../patches/v5_0/rename_table_fieldnames.py | 243 ------------------
.../v5_0/rename_taxes_and_charges_master.py | 14 -
erpnext/patches/v5_0/rename_total_fields.py | 55 ----
...lds_in_custom_scripts_and_print_formats.py | 65 -----
.../repost_gle_for_jv_with_multiple_party.py | 26 --
erpnext/patches/v5_0/repost_requested_qty.py | 21 --
erpnext/patches/v5_0/reset_values_in_tools.py | 12 -
erpnext/patches/v5_0/set_appraisal_remarks.py | 9 -
.../v5_0/set_default_company_in_bom.py | 10 -
erpnext/patches/v5_0/set_footer_address.py | 9 -
.../patches/v5_0/stock_entry_update_value.py | 8 -
.../taxes_and_totals_in_party_currency.py | 80 ------
erpnext/patches/v5_0/update_account_types.py | 20 --
erpnext/patches/v5_0/update_advance_paid.py | 13 -
.../update_companywise_payment_account.py | 21 --
.../v5_0/update_dn_against_doc_fields.py | 14 -
erpnext/patches/v5_0/update_from_bom.py | 9 -
.../update_frozen_accounts_permission_role.py | 13 -
.../v5_0/update_item_and_description_again.py | 50 ----
.../v5_0/update_item_desc_in_invoice.py | 52 ----
.../v5_0/update_item_description_and_image.py | 54 ----
.../patches/v5_0/update_item_name_in_bom.py | 18 --
.../v5_0/update_journal_entry_title.py | 12 -
...pdate_material_transfer_for_manufacture.py | 6 -
..._material_transferred_for_manufacturing.py | 10 -
...ial_transferred_for_manufacturing_again.py | 19 --
.../v5_0/update_operation_description.py | 11 -
erpnext/patches/v5_0/update_opportunity.py | 14 -
erpnext/patches/v5_0/update_projects.py | 34 ---
erpnext/patches/v5_0/update_sms_sender.py | 9 -
...amount_after_discount_in_purchase_cycle.py | 17 --
.../patches/v5_0/update_temporary_account.py | 9 -
erpnext/patches/v5_0/update_time_log_title.py | 12 -
erpnext/patches/v5_1/__init__.py | 0
erpnext/patches/v5_1/default_bom.py | 7 -
erpnext/patches/v5_1/fix_against_account.py | 37 ---
erpnext/patches/v5_1/rename_roles.py | 10 -
erpnext/patches/v5_1/sales_bom_rename.py | 12 -
erpnext/patches/v5_2/__init__.py | 1 -
.../v5_2/change_item_selects_to_checks.py | 19 --
erpnext/patches/v5_4/__init__.py | 0
erpnext/patches/v5_4/cleanup_journal_entry.py | 21 --
.../patches/v5_4/fix_invoice_outstanding.py | 13 -
.../patches/v5_4/fix_missing_item_images.py | 126 ---------
...x_reserved_qty_and_sle_for_packed_items.py | 22 --
...anagers_regarding_wrong_tax_calculation.py | 41 ---
.../patches/v5_4/set_root_and_report_type.py | 12 -
.../v5_4/stock_entry_additional_costs.py | 53 ----
.../update_purchase_cost_against_project.py | 13 -
erpnext/patches/v5_7/__init__.py | 1 -
.../patches/v5_7/item_template_attributes.py | 124 ---------
erpnext/patches/v5_8/__init__.py | 1 -
.../v5_8/add_credit_note_print_heading.py | 14 -
erpnext/patches/v5_8/tax_rule.py | 31 ---
...pdate_order_reference_in_return_entries.py | 92 -------
erpnext/patches/v6_0/__init__.py | 0
erpnext/patches/v6_0/default_activity_rate.py | 14 -
.../patches/v6_0/fix_outstanding_amount.py | 16 --
erpnext/patches/v6_0/fix_planned_qty.py | 14 -
erpnext/patches/v6_0/multi_currency.py | 65 -----
erpnext/patches/v6_0/set_default_title.py | 36 ---
erpnext/patches/v6_10/__init__.py | 1 -
.../v6_10/email_digest_default_quote.py | 6 -
.../fix_billed_amount_in_drop_ship_po.py | 18 --
.../fix_delivery_status_of_drop_ship_item.py | 10 -
erpnext/patches/v6_10/fix_jv_total_amount.py | 14 -
.../v6_10/fix_ordered_received_billed.py | 17 --
erpnext/patches/v6_12/__init__.py | 0
.../repost_entries_with_target_warehouse.py | 175 -------------
erpnext/patches/v6_12/set_overdue_tasks.py | 8 -
erpnext/patches/v6_16/__init__.py | 1 -
.../v6_16/create_manufacturer_records.py | 19 --
.../update_billing_status_in_dn_and_pr.py | 42 ---
erpnext/patches/v6_19/__init__.py | 1 -
.../v6_19/comment_feed_communication.py | 7 -
erpnext/patches/v6_2/__init__.py | 1 -
.../fix_missing_default_taxes_and_lead.py | 25 --
.../v6_2/remove_newsletter_duplicates.py | 13 -
erpnext/patches/v6_20/__init__.py | 0
.../set_party_account_currency_in_orders.py | 24 --
erpnext/patches/v6_20x/__init__.py | 1 -
.../v6_20x/remove_customer_supplier_roles.py | 23 --
.../remove_fiscal_year_from_holiday_list.py | 19 --
.../v6_20x/rename_project_name_to_project.py | 17 --
...t_valuation_rate_for_negative_inventory.py | 11 -
erpnext/patches/v6_20x/set_compact_print.py | 8 -
.../update_product_bundle_description.py | 11 -
erpnext/patches/v6_21/__init__.py | 1 -
erpnext/patches/v6_21/fix_reorder_level.py | 24 --
.../v6_21/rename_material_request_fields.py | 14 -
erpnext/patches/v6_23/__init__.py | 0
.../v6_23/update_stopped_status_to_closed.py | 9 -
erpnext/patches/v6_24/__init__.py | 0
...tomer_address_to_shipping_address_on_po.py | 19 --
erpnext/patches/v6_24/set_recurring_id.py | 13 -
erpnext/patches/v6_27/__init__.py | 1 -
.../v6_27/fix_recurring_order_status.py | 54 ----
erpnext/patches/v6_3/__init__.py | 0
.../v6_3/convert_applicable_territory.py | 24 --
erpnext/patches/v6_4/__init__.py | 1 -
erpnext/patches/v6_4/email_digest_update.py | 10 -
erpnext/patches/v6_4/fix_duplicate_bins.py | 20 --
.../v6_4/fix_expense_included_in_valuation.py | 74 ------
...x_journal_entries_due_to_reconciliation.py | 53 ----
...ified_in_sales_order_and_purchase_order.py | 10 -
.../fix_sales_order_maintenance_status.py | 8 -
.../fix_status_in_sales_and_purchase_order.py | 8 -
erpnext/patches/v6_4/make_image_thumbnail.py | 15 --
...al_entries_where_reference_name_missing.py | 23 --
.../v6_4/round_status_updater_percentages.py | 14 -
erpnext/patches/v6_4/set_user_in_contact.py | 7 -
erpnext/patches/v6_5/__init__.py | 1 -
.../v6_5/show_in_website_for_template_item.py | 15 --
erpnext/patches/v6_6/__init__.py | 1 -
erpnext/patches/v6_6/fix_website_image.py | 32 ---
...emove_fiscal_year_from_leave_allocation.py | 17 --
erpnext/patches/v6_8/__init__.py | 0
erpnext/patches/v6_8/make_webform_standard.py | 14 -
.../v6_8/move_drop_ship_to_po_items.py | 43 ----
erpnext/patches/v7_0/__init__.py | 0
.../v7_0/calculate_total_costing_amount.py | 18 --
.../v7_0/convert_timelog_to_timesheet.py | 69 -----
.../v7_0/convert_timelogbatch_to_timesheet.py | 32 ---
erpnext/patches/v7_0/create_budget_record.py | 57 ----
.../v7_0/create_warehouse_nestedset.py | 128 ---------
erpnext/patches/v7_0/fix_duplicate_icons.py | 27 --
...ouse_ledger_gl_entries_for_transactions.py | 51 ----
erpnext/patches/v7_0/make_guardian.py | 37 ---
.../v7_0/make_is_group_fieldtype_as_check.py | 18 --
...count_type_stock_and_warehouse_to_stock.py | 10 -
.../v7_0/migrate_mode_of_payments_v6_to_v7.py | 38 ---
.../v7_0/migrate_schools_to_erpnext.py | 30 ---
...lesinvoiceitem_to_salesinvoicetimesheet.py | 17 --
.../v7_0/po_status_issue_for_pr_return.py | 40 ---
erpnext/patches/v7_0/re_route.py | 5 -
.../remove_administrator_role_in_doctypes.py | 9 -
.../v7_0/remove_doctypes_and_reports.py | 27 --
erpnext/patches/v7_0/remove_features_setup.py | 29 ---
.../remove_old_earning_deduction_doctypes.py | 16 --
.../v7_0/rename_advance_table_fields.py | 18 --
.../v7_0/rename_examination_to_assessment.py | 24 --
.../rename_fee_amount_to_fee_component.py | 16 --
erpnext/patches/v7_0/rename_prevdoc_fields.py | 76 ------
.../patches/v7_0/rename_salary_components.py | 149 -----------
.../patches/v7_0/rename_time_sheet_doctype.py | 14 -
.../repost_bin_qty_and_item_projected_qty.py | 15 --
.../repost_gle_for_pi_with_update_stock.py | 20 --
.../v7_0/repost_gle_for_pos_sales_return.py | 25 --
...et_base_amount_in_invoice_payment_table.py | 24 --
.../v7_0/set_is_group_for_warehouse.py | 7 -
.../v7_0/set_material_request_type_in_item.py | 16 --
.../v7_0/set_naming_series_for_timesheet.py | 15 --
.../v7_0/set_party_name_in_payment_entry.py | 20 --
erpnext/patches/v7_0/set_portal_settings.py | 28 --
..._table_for_expense_claim_type_if_exists.py | 20 --
.../v7_0/system_settings_setup_complete.py | 16 --
erpnext/patches/v7_0/update_autoname_field.py | 14 -
.../v7_0/update_change_amount_account.py | 19 --
...rsion_factor_in_supplier_quotation_item.py | 19 --
erpnext/patches/v7_0/update_home_page.py | 27 --
.../update_maintenance_module_in_doctype.py | 11 -
.../v7_0/update_mins_to_first_response.py | 24 --
.../update_missing_employee_in_timesheet.py | 20 --
.../v7_0/update_mode_of_payment_type.py | 29 ---
erpnext/patches/v7_0/update_party_status.py | 21 --
...vdoc_values_for_supplier_quotation_item.py | 9 -
.../v7_0/update_project_in_gl_entry.py | 21 --
.../update_refdoc_in_landed_cost_voucher.py | 15 --
.../v7_0/update_status_for_timesheet.py | 11 -
.../patches/v7_0/update_status_of_po_so.py | 68 -----
...pdate_status_of_zero_amount_sales_order.py | 7 -
.../v7_0/update_timesheet_communications.py | 27 --
erpnext/patches/v7_1/__init__.py | 1 -
.../add_account_user_role_for_timesheet.py | 31 ---
.../v7_1/add_field_for_task_dependent.py | 10 -
.../v7_1/fix_link_for_customer_from_lead.py | 7 -
..._invoice_from_parent_to_child_timesheet.py | 20 --
.../patches/v7_1/rename_field_timesheet.py | 11 -
.../v7_1/rename_quality_inspection_field.py | 38 ---
...tock_for_deleted_bins_for_merging_items.py | 44 ----
erpnext/patches/v7_1/save_stock_settings.py | 15 --
.../v7_1/set_budget_against_as_cost_center.py | 11 -
.../v7_1/set_currency_exchange_date.py | 10 -
.../v7_1/set_prefered_contact_email.py | 17 --
.../patches/v7_1/set_sales_person_status.py | 8 -
erpnext/patches/v7_1/set_student_guardian.py | 23 --
.../v7_1/set_total_amount_currency_in_je.py | 24 --
.../patches/v7_1/update_bom_base_currency.py | 20 --
erpnext/patches/v7_1/update_component_type.py | 15 --
erpnext/patches/v7_1/update_invoice_status.py | 34 ---
erpnext/patches/v7_1/update_lead_source.py | 29 ---
.../update_missing_salary_component_type.py | 50 ----
erpnext/patches/v7_1/update_portal_roles.py | 21 --
.../v7_1/update_total_billing_hours.py | 14 -
erpnext/patches/v7_2/__init__.py | 1 -
...ar_leave_encashment_as_salary_component.py | 36 ---
erpnext/patches/v7_2/contact_address_links.py | 32 ---
.../delete_fleet_management_module_def.py | 10 -
...ty_supplied_items_for_non_subcontracted.py | 14 -
.../patches/v7_2/make_all_assessment_group.py | 14 -
erpnext/patches/v7_2/mark_students_active.py | 9 -
.../v7_2/rename_att_date_attendance.py | 15 --
.../v7_2/rename_evaluation_criteria.py | 39 ---
.../patches/v7_2/set_null_value_to_fields.py | 11 -
.../patches/v7_2/setup_auto_close_settings.py | 18 --
erpnext/patches/v7_2/stock_uom_in_selling.py | 15 --
.../v7_2/update_abbr_in_salary_slips.py | 14 -
.../patches/v7_2/update_assessment_modules.py | 51 ----
.../v7_2/update_attendance_docstatus.py | 10 -
erpnext/patches/v7_2/update_doctype_status.py | 11 -
.../update_guardian_name_in_student_master.py | 14 -
erpnext/patches/v7_2/update_party_type.py | 16 --
erpnext/patches/v7_2/update_salary_slips.py | 22 --
.../v7_2/update_website_for_variant.py | 13 -
erpnext/patches/v8_0/__init__.py | 1 -
.../patches/v8_0/addresses_linked_to_lead.py | 5 -
.../v8_0/change_in_words_varchar_length.py | 16 --
...dress_doc_from_address_field_in_company.py | 33 ---
erpnext/patches/v8_0/create_domain_docs.py | 53 ----
erpnext/patches/v8_0/delete_bin_indexes.py | 16 --
.../delete_schools_depricated_doctypes.py | 14 -
.../patches/v8_0/disable_instructor_role.py | 18 --
...ooking_asset_depreciation_automatically.py | 9 -
..._for_invoices_with_negative_outstanding.py | 23 --
...ayments_table_blank_for_non_pos_invoice.py | 15 --
.../merge_student_batch_and_student_group.py | 73 ------
...from_account_to_warehouse_for_inventory.py | 15 --
.../v8_0/move_perpetual_inventory_setting.py | 13 -
...ample_item_to_allow_zero_valuation_rate.py | 13 -
...ems_in_status_field_of_material_request.py | 25 --
...rename_total_margin_to_rate_with_margin.py | 24 --
...ost_reserved_qty_for_multiple_sales_uom.py | 19 --
.../revert_manufacturers_table_from_item.py | 22 --
erpnext/patches/v8_0/save_system_settings.py | 20 --
..._serial_nos_for_disabled_sales_invoices.py | 14 -
.../patches/v8_0/set_project_copied_from.py | 11 -
...nvoice_serial_number_from_delivery_note.py | 42 ---
.../patches/v8_0/update_customer_pos_id.py | 9 -
.../patches/v8_0/update_production_orders.py | 49 ----
.../v8_0/update_sales_cost_in_project.py | 11 -
...tus_as_paid_for_completed_expense_claim.py | 19 --
.../update_stock_qty_value_in_bom_item.py | 14 -
...ate_stock_qty_value_in_purchase_invoice.py | 9 -
...ate_student_groups_from_student_batches.py | 38 ---
.../update_supplier_address_in_stock_entry.py | 22 --
erpnext/patches/v8_1/__init__.py | 0
erpnext/patches/v8_1/add_hsn_sac_codes.py | 11 -
.../add_indexes_in_transaction_doctypes.py | 10 -
...allow_invoice_copy_to_edit_after_submit.py | 13 -
.../patches/v8_1/delete_deprecated_reports.py | 33 ---
erpnext/patches/v8_1/gst_fixes.py | 62 -----
...e_sales_invoice_from_returned_serial_no.py | 18 --
.../v8_1/removed_report_support_hours.py | 14 -
.../v8_1/set_delivery_date_in_so_item.py | 22 --
.../v8_1/update_expense_claim_status.py | 23 --
erpnext/patches/v8_1/update_gst_state.py | 15 --
erpnext/patches/v8_10/__init__.py | 0
.../change_default_customer_credit_days.py | 89 -------
erpnext/patches/v8_3/__init__.py | 0
.../set_restrict_to_domain_for_module_def.py | 9 -
.../v8_3/update_company_total_sales.py | 15 --
erpnext/patches/v8_4/__init__.py | 1 -
.../patches/v8_4/make_scorecard_records.py | 11 -
erpnext/patches/v8_5/__init__.py | 0
.../fix_tax_breakup_for_non_invoice_docs.py | 48 ----
.../remove_project_type_property_setter.py | 18 --
.../remove_quotations_route_in_sidebar.py | 16 --
.../v8_5/set_default_mode_of_payment.py | 17 --
.../update_customer_group_in_POS_profile.py | 9 -
.../update_existing_data_in_project_type.py | 19 --
erpnext/patches/v8_6/__init__.py | 0
...point_sms_doctype_module_to_frappe_core.py | 9 -
.../patches/v8_6/rename_bom_update_tool.py | 9 -
...mission_for_quotation_for_sales_manager.py | 11 -
.../v8_6/update_timesheet_company_from_PO.py | 15 --
erpnext/patches/v8_7/__init__.py | 0
.../v8_7/fix_purchase_receipt_status.py | 13 -
.../make_subscription_from_recurring_data.py | 58 -----
erpnext/patches/v8_8/__init__.py | 0
.../add_new_fields_in_accounts_settings.py | 9 -
.../patches/v8_8/set_bom_rate_as_per_uom.py | 13 -
erpnext/patches/v8_9/__init__.py | 1 -
.../v8_9/add_setup_progress_actions.py | 47 ----
...gst_doctypes_for_outside_india_accounts.py | 14 -
...e_employee_from_salary_structure_parent.py | 6 -
.../v8_9/rename_company_sales_target_field.py | 8 -
.../v8_9/set_default_customer_group.py | 8 -
.../set_default_fields_in_variant_settings.py | 13 -
erpnext/patches/v8_9/set_member_party_type.py | 9 -
.../v8_9/set_print_zero_amount_taxes.py | 9 -
...update_billing_gstin_for_indian_account.py | 15 --
erpnext/patches/v9_0/__init__.py | 1 -
erpnext/patches/v9_0/add_healthcare_domain.py | 13 -
.../add_user_to_child_table_in_pos_profile.py | 38 ---
.../patches/v9_0/copy_old_fees_field_data.py | 15 --
..._existing_warehouse_from_stock_settings.py | 8 -
.../v9_0/remove_subscription_module.py | 9 -
.../v9_0/revert_manufacturing_user_role.py | 22 --
erpnext/patches/v9_0/set_pos_profile_name.py | 24 --
...for_material_request_and_purchase_order.py | 24 --
...ipping_type_for_existing_shipping_rules.py | 18 --
.../patches/v9_0/set_uoms_in_variant_field.py | 14 -
.../v9_0/set_variant_item_description.py | 46 ----
.../student_admission_childtable_migrate.py | 31 ---
.../v9_0/update_employee_loan_details.py | 24 --
...te_multi_uom_fields_in_material_request.py | 12 -
erpnext/patches/v9_1/__init__.py | 0
.../v9_1/create_issue_opportunity_type.py | 34 ---
erpnext/patches/v9_2/__init__.py | 0
.../delete_healthcare_domain_default_items.py | 17 --
.../patches/v9_2/delete_process_payroll.py | 5 -
.../v9_2/remove_company_from_patient.py | 7 -
.../v9_2/rename_net_weight_in_item_master.py | 8 -
.../v9_2/rename_translated_domains_in_en.py | 39 ---
.../repost_reserved_qty_for_production.py | 9 -
.../v9_2/set_item_name_in_production_order.py | 12 -
441 files changed, 9599 deletions(-)
delete mode 100644 erpnext/patches/repair_tools/__init__.py
delete mode 100644 erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py
delete mode 100644 erpnext/patches/v10_0/__init__.py
delete mode 100644 erpnext/patches/v10_0/add_agriculture_domain.py
delete mode 100644 erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py
delete mode 100644 erpnext/patches/v10_0/add_non_profit_domain.py
delete mode 100644 erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py
delete mode 100644 erpnext/patches/v10_0/copy_projects_renamed_fields.py
delete mode 100644 erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py
delete mode 100644 erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
delete mode 100644 erpnext/patches/v10_0/recalculate_gross_margin_for_project.py
delete mode 100644 erpnext/patches/v10_0/rename_schools_to_education.py
delete mode 100644 erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
delete mode 100644 erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py
delete mode 100644 erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py
delete mode 100644 erpnext/patches/v10_0/set_b2c_limit.py
delete mode 100644 erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py
delete mode 100644 erpnext/patches/v10_0/set_discount_amount.py
delete mode 100644 erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py
delete mode 100644 erpnext/patches/v10_0/set_primary_contact_for_customer.py
delete mode 100644 erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py
delete mode 100644 erpnext/patches/v10_0/set_student_party_type.py
delete mode 100644 erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py
delete mode 100644 erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py
delete mode 100644 erpnext/patches/v10_0/taxes_issue_with_pos.py
delete mode 100644 erpnext/patches/v10_0/update_address_template_for_india.py
delete mode 100644 erpnext/patches/v10_0/update_assessment_plan.py
delete mode 100644 erpnext/patches/v10_0/update_assessment_result.py
delete mode 100644 erpnext/patches/v10_0/update_asset_calculate_depreciation.py
delete mode 100644 erpnext/patches/v10_0/update_hub_connector_domain.py
delete mode 100644 erpnext/patches/v10_0/update_lft_rgt_for_employee.py
delete mode 100644 erpnext/patches/v10_0/update_project_in_sle.py
delete mode 100644 erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py
delete mode 100644 erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py
delete mode 100644 erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py
delete mode 100644 erpnext/patches/v10_0/update_status_in_purchase_receipt.py
delete mode 100644 erpnext/patches/v10_0/update_territory_and_customer_group.py
delete mode 100644 erpnext/patches/v10_0/update_user_image_in_employee.py
delete mode 100644 erpnext/patches/v10_0/update_warehouse_address_details.py
delete mode 100644 erpnext/patches/v10_1/__init__.py
delete mode 100644 erpnext/patches/v11_0/__init__.py
delete mode 100644 erpnext/patches/v11_0/remove_subscriber_doctype.py
delete mode 100644 erpnext/patches/v11_1/__init__.py
delete mode 100644 erpnext/patches/v12_0/__init__.py
delete mode 100644 erpnext/patches/v13_0/__init__.py
delete mode 100644 erpnext/patches/v4_0/__init__.py
delete mode 100644 erpnext/patches/v4_0/apply_user_permissions.py
delete mode 100644 erpnext/patches/v4_0/countrywise_coa.py
delete mode 100644 erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py
delete mode 100644 erpnext/patches/v4_0/create_price_list_if_missing.py
delete mode 100644 erpnext/patches/v4_0/customer_discount_to_pricing_rule.py
delete mode 100644 erpnext/patches/v4_0/fields_to_be_renamed.py
delete mode 100644 erpnext/patches/v4_0/fix_address_template.py
delete mode 100644 erpnext/patches/v4_0/fix_case_of_hr_module_def.py
delete mode 100644 erpnext/patches/v4_0/fix_contact_address.py
delete mode 100644 erpnext/patches/v4_0/fix_employee_user_id.py
delete mode 100644 erpnext/patches/v4_0/global_defaults_to_system_settings.py
delete mode 100644 erpnext/patches/v4_0/import_country_codes.py
delete mode 100644 erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py
delete mode 100644 erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
delete mode 100644 erpnext/patches/v4_0/new_address_template.py
delete mode 100644 erpnext/patches/v4_0/reload_sales_print_format.py
delete mode 100644 erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
delete mode 100644 erpnext/patches/v4_0/remove_module_home_pages.py
delete mode 100644 erpnext/patches/v4_0/rename_sitemap_to_route.py
delete mode 100644 erpnext/patches/v4_0/reset_permissions_for_masters.py
delete mode 100644 erpnext/patches/v4_0/save_default_letterhead.py
delete mode 100644 erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
delete mode 100644 erpnext/patches/v4_0/split_email_settings.py
delete mode 100644 erpnext/patches/v4_0/update_account_root_type.py
delete mode 100644 erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py
delete mode 100644 erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py
delete mode 100644 erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py
delete mode 100644 erpnext/patches/v4_0/update_tax_amount_after_discount.py
delete mode 100644 erpnext/patches/v4_0/update_user_properties.py
delete mode 100644 erpnext/patches/v4_0/update_users_report_view_settings.py
delete mode 100644 erpnext/patches/v4_0/validate_v3_patch.py
delete mode 100644 erpnext/patches/v4_1/__init__.py
delete mode 100644 erpnext/patches/v4_1/fix_delivery_and_billing_status.py
delete mode 100644 erpnext/patches/v4_1/fix_jv_remarks.py
delete mode 100644 erpnext/patches/v4_1/fix_sales_order_delivered_status.py
delete mode 100644 erpnext/patches/v4_1/set_outgoing_email_footer.py
delete mode 100644 erpnext/patches/v4_2/__init__.py
delete mode 100644 erpnext/patches/v4_2/add_currency_turkish_lira.py
delete mode 100644 erpnext/patches/v4_2/default_website_style.py
delete mode 100644 erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
delete mode 100644 erpnext/patches/v4_2/delete_old_print_formats.py
delete mode 100644 erpnext/patches/v4_2/discount_amount.py
delete mode 100644 erpnext/patches/v4_2/fix_account_master_type.py
delete mode 100644 erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
delete mode 100644 erpnext/patches/v4_2/fix_recurring_orders.py
delete mode 100644 erpnext/patches/v4_2/party_model.py
delete mode 100644 erpnext/patches/v4_2/recalculate_bom_cost.py
delete mode 100644 erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
delete mode 100644 erpnext/patches/v4_2/repost_stock_reconciliation.py
delete mode 100644 erpnext/patches/v4_2/reset_bom_costs.py
delete mode 100644 erpnext/patches/v4_2/seprate_manufacture_and_repack.py
delete mode 100644 erpnext/patches/v4_2/set_company_country.py
delete mode 100644 erpnext/patches/v4_2/set_item_has_batch.py
delete mode 100644 erpnext/patches/v4_2/toggle_rounded_total.py
delete mode 100644 erpnext/patches/v4_2/update_landed_cost_voucher.py
delete mode 100644 erpnext/patches/v4_2/update_project_milestones.py
delete mode 100644 erpnext/patches/v4_2/update_sales_order_invoice_field_name.py
delete mode 100644 erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py
delete mode 100644 erpnext/patches/v4_4/__init__.py
delete mode 100644 erpnext/patches/v4_4/make_email_accounts.py
delete mode 100644 erpnext/patches/v5_0/__init__.py
delete mode 100644 erpnext/patches/v5_0/convert_stock_reconciliation.py
delete mode 100644 erpnext/patches/v5_0/execute_on_doctype_update.py
delete mode 100644 erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py
delete mode 100644 erpnext/patches/v5_0/index_on_account_and_gl_entry.py
delete mode 100644 erpnext/patches/v5_0/is_group.py
delete mode 100644 erpnext/patches/v5_0/item_patches.py
delete mode 100644 erpnext/patches/v5_0/link_warehouse_with_account.py
delete mode 100644 erpnext/patches/v5_0/new_crm_module.py
delete mode 100644 erpnext/patches/v5_0/newsletter.py
delete mode 100644 erpnext/patches/v5_0/opportunity_not_submittable.py
delete mode 100644 erpnext/patches/v5_0/party_model_patch_fix.py
delete mode 100644 erpnext/patches/v5_0/portal_fixes.py
delete mode 100644 erpnext/patches/v5_0/project_costing.py
delete mode 100644 erpnext/patches/v5_0/recalculate_total_amount_in_jv.py
delete mode 100644 erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py
delete mode 100644 erpnext/patches/v5_0/remove_birthday_events.py
delete mode 100644 erpnext/patches/v5_0/rename_customer_issue.py
delete mode 100644 erpnext/patches/v5_0/rename_pos_setting.py
delete mode 100644 erpnext/patches/v5_0/rename_table_fieldnames.py
delete mode 100644 erpnext/patches/v5_0/rename_taxes_and_charges_master.py
delete mode 100644 erpnext/patches/v5_0/rename_total_fields.py
delete mode 100644 erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py
delete mode 100644 erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
delete mode 100644 erpnext/patches/v5_0/repost_requested_qty.py
delete mode 100644 erpnext/patches/v5_0/reset_values_in_tools.py
delete mode 100644 erpnext/patches/v5_0/set_appraisal_remarks.py
delete mode 100644 erpnext/patches/v5_0/set_default_company_in_bom.py
delete mode 100644 erpnext/patches/v5_0/set_footer_address.py
delete mode 100644 erpnext/patches/v5_0/stock_entry_update_value.py
delete mode 100644 erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py
delete mode 100644 erpnext/patches/v5_0/update_account_types.py
delete mode 100644 erpnext/patches/v5_0/update_advance_paid.py
delete mode 100644 erpnext/patches/v5_0/update_companywise_payment_account.py
delete mode 100644 erpnext/patches/v5_0/update_dn_against_doc_fields.py
delete mode 100644 erpnext/patches/v5_0/update_from_bom.py
delete mode 100644 erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
delete mode 100644 erpnext/patches/v5_0/update_item_and_description_again.py
delete mode 100644 erpnext/patches/v5_0/update_item_desc_in_invoice.py
delete mode 100644 erpnext/patches/v5_0/update_item_description_and_image.py
delete mode 100644 erpnext/patches/v5_0/update_item_name_in_bom.py
delete mode 100644 erpnext/patches/v5_0/update_journal_entry_title.py
delete mode 100644 erpnext/patches/v5_0/update_material_transfer_for_manufacture.py
delete mode 100644 erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py
delete mode 100644 erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py
delete mode 100644 erpnext/patches/v5_0/update_operation_description.py
delete mode 100644 erpnext/patches/v5_0/update_opportunity.py
delete mode 100644 erpnext/patches/v5_0/update_projects.py
delete mode 100644 erpnext/patches/v5_0/update_sms_sender.py
delete mode 100644 erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py
delete mode 100644 erpnext/patches/v5_0/update_temporary_account.py
delete mode 100644 erpnext/patches/v5_0/update_time_log_title.py
delete mode 100644 erpnext/patches/v5_1/__init__.py
delete mode 100644 erpnext/patches/v5_1/default_bom.py
delete mode 100644 erpnext/patches/v5_1/fix_against_account.py
delete mode 100644 erpnext/patches/v5_1/rename_roles.py
delete mode 100644 erpnext/patches/v5_1/sales_bom_rename.py
delete mode 100644 erpnext/patches/v5_2/__init__.py
delete mode 100644 erpnext/patches/v5_2/change_item_selects_to_checks.py
delete mode 100644 erpnext/patches/v5_4/__init__.py
delete mode 100644 erpnext/patches/v5_4/cleanup_journal_entry.py
delete mode 100644 erpnext/patches/v5_4/fix_invoice_outstanding.py
delete mode 100644 erpnext/patches/v5_4/fix_missing_item_images.py
delete mode 100644 erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py
delete mode 100644 erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
delete mode 100644 erpnext/patches/v5_4/set_root_and_report_type.py
delete mode 100644 erpnext/patches/v5_4/stock_entry_additional_costs.py
delete mode 100644 erpnext/patches/v5_4/update_purchase_cost_against_project.py
delete mode 100644 erpnext/patches/v5_7/__init__.py
delete mode 100644 erpnext/patches/v5_7/item_template_attributes.py
delete mode 100644 erpnext/patches/v5_8/__init__.py
delete mode 100644 erpnext/patches/v5_8/add_credit_note_print_heading.py
delete mode 100644 erpnext/patches/v5_8/tax_rule.py
delete mode 100644 erpnext/patches/v5_8/update_order_reference_in_return_entries.py
delete mode 100644 erpnext/patches/v6_0/__init__.py
delete mode 100644 erpnext/patches/v6_0/default_activity_rate.py
delete mode 100644 erpnext/patches/v6_0/fix_outstanding_amount.py
delete mode 100644 erpnext/patches/v6_0/fix_planned_qty.py
delete mode 100644 erpnext/patches/v6_0/multi_currency.py
delete mode 100644 erpnext/patches/v6_0/set_default_title.py
delete mode 100644 erpnext/patches/v6_10/__init__.py
delete mode 100644 erpnext/patches/v6_10/email_digest_default_quote.py
delete mode 100644 erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py
delete mode 100644 erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py
delete mode 100644 erpnext/patches/v6_10/fix_jv_total_amount.py
delete mode 100644 erpnext/patches/v6_10/fix_ordered_received_billed.py
delete mode 100644 erpnext/patches/v6_12/__init__.py
delete mode 100644 erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
delete mode 100644 erpnext/patches/v6_12/set_overdue_tasks.py
delete mode 100644 erpnext/patches/v6_16/__init__.py
delete mode 100644 erpnext/patches/v6_16/create_manufacturer_records.py
delete mode 100644 erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py
delete mode 100644 erpnext/patches/v6_19/__init__.py
delete mode 100644 erpnext/patches/v6_19/comment_feed_communication.py
delete mode 100644 erpnext/patches/v6_2/__init__.py
delete mode 100644 erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py
delete mode 100644 erpnext/patches/v6_2/remove_newsletter_duplicates.py
delete mode 100644 erpnext/patches/v6_20/__init__.py
delete mode 100644 erpnext/patches/v6_20/set_party_account_currency_in_orders.py
delete mode 100644 erpnext/patches/v6_20x/__init__.py
delete mode 100644 erpnext/patches/v6_20x/remove_customer_supplier_roles.py
delete mode 100644 erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py
delete mode 100644 erpnext/patches/v6_20x/rename_project_name_to_project.py
delete mode 100644 erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py
delete mode 100644 erpnext/patches/v6_20x/set_compact_print.py
delete mode 100644 erpnext/patches/v6_20x/update_product_bundle_description.py
delete mode 100644 erpnext/patches/v6_21/__init__.py
delete mode 100644 erpnext/patches/v6_21/fix_reorder_level.py
delete mode 100644 erpnext/patches/v6_21/rename_material_request_fields.py
delete mode 100644 erpnext/patches/v6_23/__init__.py
delete mode 100644 erpnext/patches/v6_23/update_stopped_status_to_closed.py
delete mode 100644 erpnext/patches/v6_24/__init__.py
delete mode 100644 erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py
delete mode 100644 erpnext/patches/v6_24/set_recurring_id.py
delete mode 100644 erpnext/patches/v6_27/__init__.py
delete mode 100644 erpnext/patches/v6_27/fix_recurring_order_status.py
delete mode 100644 erpnext/patches/v6_3/__init__.py
delete mode 100644 erpnext/patches/v6_3/convert_applicable_territory.py
delete mode 100644 erpnext/patches/v6_4/__init__.py
delete mode 100644 erpnext/patches/v6_4/email_digest_update.py
delete mode 100644 erpnext/patches/v6_4/fix_duplicate_bins.py
delete mode 100644 erpnext/patches/v6_4/fix_expense_included_in_valuation.py
delete mode 100644 erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
delete mode 100644 erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py
delete mode 100644 erpnext/patches/v6_4/fix_sales_order_maintenance_status.py
delete mode 100644 erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py
delete mode 100644 erpnext/patches/v6_4/make_image_thumbnail.py
delete mode 100644 erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
delete mode 100644 erpnext/patches/v6_4/round_status_updater_percentages.py
delete mode 100644 erpnext/patches/v6_4/set_user_in_contact.py
delete mode 100644 erpnext/patches/v6_5/__init__.py
delete mode 100644 erpnext/patches/v6_5/show_in_website_for_template_item.py
delete mode 100644 erpnext/patches/v6_6/__init__.py
delete mode 100644 erpnext/patches/v6_6/fix_website_image.py
delete mode 100644 erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py
delete mode 100644 erpnext/patches/v6_8/__init__.py
delete mode 100644 erpnext/patches/v6_8/make_webform_standard.py
delete mode 100644 erpnext/patches/v6_8/move_drop_ship_to_po_items.py
delete mode 100644 erpnext/patches/v7_0/__init__.py
delete mode 100644 erpnext/patches/v7_0/calculate_total_costing_amount.py
delete mode 100644 erpnext/patches/v7_0/convert_timelog_to_timesheet.py
delete mode 100644 erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py
delete mode 100644 erpnext/patches/v7_0/create_budget_record.py
delete mode 100644 erpnext/patches/v7_0/create_warehouse_nestedset.py
delete mode 100644 erpnext/patches/v7_0/fix_duplicate_icons.py
delete mode 100644 erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
delete mode 100644 erpnext/patches/v7_0/make_guardian.py
delete mode 100644 erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py
delete mode 100644 erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py
delete mode 100644 erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py
delete mode 100644 erpnext/patches/v7_0/migrate_schools_to_erpnext.py
delete mode 100644 erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py
delete mode 100644 erpnext/patches/v7_0/po_status_issue_for_pr_return.py
delete mode 100644 erpnext/patches/v7_0/re_route.py
delete mode 100644 erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py
delete mode 100644 erpnext/patches/v7_0/remove_doctypes_and_reports.py
delete mode 100644 erpnext/patches/v7_0/remove_features_setup.py
delete mode 100644 erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py
delete mode 100644 erpnext/patches/v7_0/rename_advance_table_fields.py
delete mode 100644 erpnext/patches/v7_0/rename_examination_to_assessment.py
delete mode 100644 erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py
delete mode 100644 erpnext/patches/v7_0/rename_prevdoc_fields.py
delete mode 100644 erpnext/patches/v7_0/rename_salary_components.py
delete mode 100644 erpnext/patches/v7_0/rename_time_sheet_doctype.py
delete mode 100644 erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
delete mode 100644 erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
delete mode 100644 erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py
delete mode 100644 erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py
delete mode 100644 erpnext/patches/v7_0/set_is_group_for_warehouse.py
delete mode 100644 erpnext/patches/v7_0/set_material_request_type_in_item.py
delete mode 100644 erpnext/patches/v7_0/set_naming_series_for_timesheet.py
delete mode 100644 erpnext/patches/v7_0/set_party_name_in_payment_entry.py
delete mode 100644 erpnext/patches/v7_0/set_portal_settings.py
delete mode 100644 erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py
delete mode 100644 erpnext/patches/v7_0/system_settings_setup_complete.py
delete mode 100644 erpnext/patches/v7_0/update_autoname_field.py
delete mode 100644 erpnext/patches/v7_0/update_change_amount_account.py
delete mode 100644 erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py
delete mode 100644 erpnext/patches/v7_0/update_home_page.py
delete mode 100644 erpnext/patches/v7_0/update_maintenance_module_in_doctype.py
delete mode 100644 erpnext/patches/v7_0/update_mins_to_first_response.py
delete mode 100644 erpnext/patches/v7_0/update_missing_employee_in_timesheet.py
delete mode 100644 erpnext/patches/v7_0/update_mode_of_payment_type.py
delete mode 100644 erpnext/patches/v7_0/update_party_status.py
delete mode 100644 erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py
delete mode 100644 erpnext/patches/v7_0/update_project_in_gl_entry.py
delete mode 100644 erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py
delete mode 100644 erpnext/patches/v7_0/update_status_for_timesheet.py
delete mode 100644 erpnext/patches/v7_0/update_status_of_po_so.py
delete mode 100644 erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py
delete mode 100644 erpnext/patches/v7_0/update_timesheet_communications.py
delete mode 100644 erpnext/patches/v7_1/__init__.py
delete mode 100644 erpnext/patches/v7_1/add_account_user_role_for_timesheet.py
delete mode 100644 erpnext/patches/v7_1/add_field_for_task_dependent.py
delete mode 100644 erpnext/patches/v7_1/fix_link_for_customer_from_lead.py
delete mode 100644 erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py
delete mode 100644 erpnext/patches/v7_1/rename_field_timesheet.py
delete mode 100644 erpnext/patches/v7_1/rename_quality_inspection_field.py
delete mode 100644 erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py
delete mode 100644 erpnext/patches/v7_1/save_stock_settings.py
delete mode 100644 erpnext/patches/v7_1/set_budget_against_as_cost_center.py
delete mode 100644 erpnext/patches/v7_1/set_currency_exchange_date.py
delete mode 100644 erpnext/patches/v7_1/set_prefered_contact_email.py
delete mode 100644 erpnext/patches/v7_1/set_sales_person_status.py
delete mode 100644 erpnext/patches/v7_1/set_student_guardian.py
delete mode 100644 erpnext/patches/v7_1/set_total_amount_currency_in_je.py
delete mode 100644 erpnext/patches/v7_1/update_bom_base_currency.py
delete mode 100644 erpnext/patches/v7_1/update_component_type.py
delete mode 100644 erpnext/patches/v7_1/update_invoice_status.py
delete mode 100644 erpnext/patches/v7_1/update_lead_source.py
delete mode 100644 erpnext/patches/v7_1/update_missing_salary_component_type.py
delete mode 100644 erpnext/patches/v7_1/update_portal_roles.py
delete mode 100644 erpnext/patches/v7_1/update_total_billing_hours.py
delete mode 100644 erpnext/patches/v7_2/__init__.py
delete mode 100644 erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py
delete mode 100644 erpnext/patches/v7_2/contact_address_links.py
delete mode 100644 erpnext/patches/v7_2/delete_fleet_management_module_def.py
delete mode 100644 erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py
delete mode 100644 erpnext/patches/v7_2/make_all_assessment_group.py
delete mode 100644 erpnext/patches/v7_2/mark_students_active.py
delete mode 100644 erpnext/patches/v7_2/rename_att_date_attendance.py
delete mode 100644 erpnext/patches/v7_2/rename_evaluation_criteria.py
delete mode 100644 erpnext/patches/v7_2/set_null_value_to_fields.py
delete mode 100644 erpnext/patches/v7_2/setup_auto_close_settings.py
delete mode 100644 erpnext/patches/v7_2/stock_uom_in_selling.py
delete mode 100644 erpnext/patches/v7_2/update_abbr_in_salary_slips.py
delete mode 100644 erpnext/patches/v7_2/update_assessment_modules.py
delete mode 100644 erpnext/patches/v7_2/update_attendance_docstatus.py
delete mode 100644 erpnext/patches/v7_2/update_doctype_status.py
delete mode 100644 erpnext/patches/v7_2/update_guardian_name_in_student_master.py
delete mode 100644 erpnext/patches/v7_2/update_party_type.py
delete mode 100644 erpnext/patches/v7_2/update_salary_slips.py
delete mode 100644 erpnext/patches/v7_2/update_website_for_variant.py
delete mode 100644 erpnext/patches/v8_0/__init__.py
delete mode 100644 erpnext/patches/v8_0/addresses_linked_to_lead.py
delete mode 100644 erpnext/patches/v8_0/change_in_words_varchar_length.py
delete mode 100644 erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py
delete mode 100644 erpnext/patches/v8_0/create_domain_docs.py
delete mode 100644 erpnext/patches/v8_0/delete_bin_indexes.py
delete mode 100644 erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
delete mode 100644 erpnext/patches/v8_0/disable_instructor_role.py
delete mode 100644 erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py
delete mode 100644 erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py
delete mode 100644 erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py
delete mode 100644 erpnext/patches/v8_0/merge_student_batch_and_student_group.py
delete mode 100644 erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py
delete mode 100644 erpnext/patches/v8_0/move_perpetual_inventory_setting.py
delete mode 100644 erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py
delete mode 100644 erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py
delete mode 100644 erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py
delete mode 100644 erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py
delete mode 100644 erpnext/patches/v8_0/revert_manufacturers_table_from_item.py
delete mode 100644 erpnext/patches/v8_0/save_system_settings.py
delete mode 100644 erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py
delete mode 100644 erpnext/patches/v8_0/set_project_copied_from.py
delete mode 100644 erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
delete mode 100644 erpnext/patches/v8_0/update_customer_pos_id.py
delete mode 100644 erpnext/patches/v8_0/update_production_orders.py
delete mode 100644 erpnext/patches/v8_0/update_sales_cost_in_project.py
delete mode 100644 erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py
delete mode 100644 erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py
delete mode 100644 erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py
delete mode 100644 erpnext/patches/v8_0/update_student_groups_from_student_batches.py
delete mode 100644 erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py
delete mode 100644 erpnext/patches/v8_1/__init__.py
delete mode 100644 erpnext/patches/v8_1/add_hsn_sac_codes.py
delete mode 100644 erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py
delete mode 100644 erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py
delete mode 100644 erpnext/patches/v8_1/delete_deprecated_reports.py
delete mode 100644 erpnext/patches/v8_1/gst_fixes.py
delete mode 100644 erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py
delete mode 100644 erpnext/patches/v8_1/removed_report_support_hours.py
delete mode 100644 erpnext/patches/v8_1/set_delivery_date_in_so_item.py
delete mode 100644 erpnext/patches/v8_1/update_expense_claim_status.py
delete mode 100644 erpnext/patches/v8_1/update_gst_state.py
delete mode 100644 erpnext/patches/v8_10/__init__.py
delete mode 100644 erpnext/patches/v8_10/change_default_customer_credit_days.py
delete mode 100644 erpnext/patches/v8_3/__init__.py
delete mode 100644 erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py
delete mode 100644 erpnext/patches/v8_3/update_company_total_sales.py
delete mode 100644 erpnext/patches/v8_4/__init__.py
delete mode 100644 erpnext/patches/v8_4/make_scorecard_records.py
delete mode 100644 erpnext/patches/v8_5/__init__.py
delete mode 100644 erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py
delete mode 100644 erpnext/patches/v8_5/remove_project_type_property_setter.py
delete mode 100644 erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py
delete mode 100644 erpnext/patches/v8_5/set_default_mode_of_payment.py
delete mode 100644 erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
delete mode 100644 erpnext/patches/v8_5/update_existing_data_in_project_type.py
delete mode 100644 erpnext/patches/v8_6/__init__.py
delete mode 100644 erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py
delete mode 100644 erpnext/patches/v8_6/rename_bom_update_tool.py
delete mode 100644 erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
delete mode 100644 erpnext/patches/v8_6/update_timesheet_company_from_PO.py
delete mode 100644 erpnext/patches/v8_7/__init__.py
delete mode 100644 erpnext/patches/v8_7/fix_purchase_receipt_status.py
delete mode 100644 erpnext/patches/v8_7/make_subscription_from_recurring_data.py
delete mode 100644 erpnext/patches/v8_8/__init__.py
delete mode 100644 erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py
delete mode 100644 erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
delete mode 100644 erpnext/patches/v8_9/__init__.py
delete mode 100644 erpnext/patches/v8_9/add_setup_progress_actions.py
delete mode 100644 erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py
delete mode 100644 erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py
delete mode 100644 erpnext/patches/v8_9/rename_company_sales_target_field.py
delete mode 100644 erpnext/patches/v8_9/set_default_customer_group.py
delete mode 100644 erpnext/patches/v8_9/set_default_fields_in_variant_settings.py
delete mode 100644 erpnext/patches/v8_9/set_member_party_type.py
delete mode 100644 erpnext/patches/v8_9/set_print_zero_amount_taxes.py
delete mode 100644 erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py
delete mode 100644 erpnext/patches/v9_0/__init__.py
delete mode 100644 erpnext/patches/v9_0/add_healthcare_domain.py
delete mode 100644 erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py
delete mode 100644 erpnext/patches/v9_0/copy_old_fees_field_data.py
delete mode 100644 erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py
delete mode 100644 erpnext/patches/v9_0/remove_subscription_module.py
delete mode 100644 erpnext/patches/v9_0/revert_manufacturing_user_role.py
delete mode 100644 erpnext/patches/v9_0/set_pos_profile_name.py
delete mode 100644 erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
delete mode 100644 erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py
delete mode 100644 erpnext/patches/v9_0/set_uoms_in_variant_field.py
delete mode 100644 erpnext/patches/v9_0/set_variant_item_description.py
delete mode 100644 erpnext/patches/v9_0/student_admission_childtable_migrate.py
delete mode 100644 erpnext/patches/v9_0/update_employee_loan_details.py
delete mode 100644 erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py
delete mode 100644 erpnext/patches/v9_1/__init__.py
delete mode 100644 erpnext/patches/v9_1/create_issue_opportunity_type.py
delete mode 100644 erpnext/patches/v9_2/__init__.py
delete mode 100644 erpnext/patches/v9_2/delete_healthcare_domain_default_items.py
delete mode 100644 erpnext/patches/v9_2/delete_process_payroll.py
delete mode 100644 erpnext/patches/v9_2/remove_company_from_patient.py
delete mode 100644 erpnext/patches/v9_2/rename_net_weight_in_item_master.py
delete mode 100644 erpnext/patches/v9_2/rename_translated_domains_in_en.py
delete mode 100644 erpnext/patches/v9_2/repost_reserved_qty_for_production.py
delete mode 100644 erpnext/patches/v9_2/set_item_name_in_production_order.py
diff --git a/erpnext/patches/repair_tools/__init__.py b/erpnext/patches/repair_tools/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py b/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py
deleted file mode 100644
index 5a421d146f..0000000000
--- a/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from erpnext.stock.stock_balance import set_stock_balance_as_per_serial_no
- frappe.db.auto_commit_on_many_writes = 1
-
- set_stock_balance_as_per_serial_no()
-
- frappe.db.auto_commit_on_many_writes = 0
diff --git a/erpnext/patches/v10_0/__init__.py b/erpnext/patches/v10_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v10_0/add_agriculture_domain.py b/erpnext/patches/v10_0/add_agriculture_domain.py
deleted file mode 100644
index c18e69f3e6..0000000000
--- a/erpnext/patches/v10_0/add_agriculture_domain.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- domain = 'Agriculture'
- if not frappe.db.exists('Domain', domain):
- frappe.get_doc({
- 'doctype': 'Domain',
- 'domain': domain
- }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py b/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py
deleted file mode 100644
index 0b891f21f4..0000000000
--- a/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # create guardian role
- if not frappe.get_value('Role', dict(role_name='Guardian')):
- frappe.get_doc({
- 'doctype': 'Role',
- 'role_name': 'Guardian',
- 'desk_access': 0,
- 'restrict_to_domain': 'Education'
- }).insert(ignore_permissions=True)
-
- # set guardian roles in already created users
- if frappe.db.exists("Doctype", "Guardian"):
- for user in frappe.db.sql_list("""select u.name from `tabUser` u , `tabGuardian` g where g.email_address = u.name"""):
- user = frappe.get_doc('User', user)
- user.flags.ignore_validate = True
- user.flags.ignore_mandatory = True
- user.save()
diff --git a/erpnext/patches/v10_0/add_non_profit_domain.py b/erpnext/patches/v10_0/add_non_profit_domain.py
deleted file mode 100644
index b03d669515..0000000000
--- a/erpnext/patches/v10_0/add_non_profit_domain.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- domain = 'Non Profit'
- if not frappe.db.exists('Domain', domain):
- frappe.get_doc({
- 'doctype': 'Domain',
- 'domain': domain
- }).insert(ignore_permissions=True)
-
- frappe.get_doc({
- 'doctype': 'Role',
- 'role_name': 'Non Profit Portal User',
- 'desk_access': 0,
- 'restrict_to_domain': domain
- }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py b/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py
deleted file mode 100644
index 827f9bc94f..0000000000
--- a/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2019, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_criteria')
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_scoring_criteria')
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard')
-
- for criteria in frappe.get_all('Supplier Scorecard Criteria', fields=['name', 'formula'], limit_page_length=None):
- frappe.db.set_value('Supplier Scorecard Criteria', criteria.name,
- 'formula', criteria.formula.replace('<','<').replace('>','>'))
-
- for criteria in frappe.get_all('Supplier Scorecard Scoring Criteria', fields=['name', 'formula'], limit_page_length=None):
- if criteria.formula: # not mandatory
- frappe.db.set_value('Supplier Scorecard Scoring Criteria', criteria.name,
- 'formula', criteria.formula.replace('<','<').replace('>','>'))
-
- for sc in frappe.get_all('Supplier Scorecard', fields=['name', 'weighting_function'], limit_page_length=None):
- frappe.db.set_value('Supplier Scorecard', sc.name, 'weighting_function',
- sc.weighting_function.replace('<','<').replace('>','>'))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/copy_projects_renamed_fields.py b/erpnext/patches/v10_0/copy_projects_renamed_fields.py
deleted file mode 100644
index 80db3bdd1e..0000000000
--- a/erpnext/patches/v10_0/copy_projects_renamed_fields.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- """ copy data from old fields to new """
- frappe.reload_doc("projects", "doctype", "project")
-
- if frappe.db.has_column('Project', 'total_sales_cost'):
- rename_field('Project', "total_sales_cost", "total_sales_amount")
-
- if frappe.db.has_column('Project', 'total_billing_amount'):
- rename_field('Project', "total_billing_amount", "total_billable_amount")
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py b/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py
deleted file mode 100644
index 38b04cebc2..0000000000
--- a/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- print_format_mapper = {
- 'India': ['GST POS Invoice', 'GST Tax Invoice'],
- 'Saudi Arabia': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice'],
- 'United Arab Emirates': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice']
- }
-
- frappe.db.sql(""" update `tabPrint Format` set disabled = 1 where name
- in ('GST POS Invoice', 'GST Tax Invoice', 'Simplified Tax Invoice', 'Detailed Tax Invoice')""")
-
- for d in frappe.get_all('Company', fields = ["country"],
- filters={'country': ('in', ['India', 'Saudi Arabia', 'United Arab Emirates'])}):
- if print_format_mapper.get(d.country):
- print_formats = print_format_mapper.get(d.country)
- frappe.db.sql(""" update `tabPrint Format` set disabled = 0
- where name in (%s)""" % ", ".join(["%s"]*len(print_formats)), tuple(print_formats))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py b/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
deleted file mode 100644
index c0a9e5eb5b..0000000000
--- a/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.utils import get_bin
-
-def execute():
- frappe.reload_doc("stock", "doctype", "bin")
- frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied")
- for d in frappe.db.sql("""
- select distinct rm_item_code, reserve_warehouse
- from `tabPurchase Order Item Supplied`
- where docstatus=1 and reserve_warehouse is not null and reserve_warehouse != ''"""):
-
- try:
- bin_doc = get_bin(d[0], d[1])
- bin_doc.update_reserved_qty_for_sub_contracting()
- except:
- pass
-
- for d in frappe.db.sql("""select distinct item_code, source_warehouse
- from `tabWork Order Item`
- where docstatus=1 and transferred_qty > required_qty
- and source_warehouse is not null and source_warehouse != ''""", as_list=1):
-
- try:
- bin_doc = get_bin(d[0], d[1])
- bin_doc.update_reserved_qty_for_production()
- except:
- pass
diff --git a/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py b/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py
deleted file mode 100644
index 6d461f3bc9..0000000000
--- a/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'project')
- for d in frappe.db.sql(""" select name from `tabProject` where
- ifnull(total_consumed_material_cost, 0 ) > 0 and ifnull(total_billed_amount, 0) > 0""", as_dict=1):
- doc = frappe.get_doc("Project", d.name)
- doc.calculate_gross_margin()
- doc.db_set('gross_margin', doc.gross_margin)
- doc.db_set('per_gross_margin', doc.per_gross_margin)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/rename_schools_to_education.py b/erpnext/patches/v10_0/rename_schools_to_education.py
deleted file mode 100644
index 85c25a8943..0000000000
--- a/erpnext/patches/v10_0/rename_schools_to_education.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # rename the School module as Education
-
- # rename the school module
- if frappe.db.exists('Module Def', 'Schools') and not frappe.db.exists('Module Def', 'Education'):
- frappe.rename_doc("Module Def", "Schools", "Education")
-
- # delete the school module
- if frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Education'):
- frappe.db.sql("""delete from `tabModule Def` where module_name = 'Schools'""")
-
-
- # rename "School Settings" to the "Education Settings
- if frappe.db.exists('DocType', 'School Settings'):
- frappe.rename_doc("DocType", "School Settings", "Education Settings", force=True)
- frappe.reload_doc("education", "doctype", "education_settings")
-
- # delete the discussion web form if exists
- if frappe.db.exists('Web Form', 'Discussion'):
- frappe.db.sql("""delete from `tabWeb Form` where name = 'discussion'""")
-
- # rename the select option field from "School Bus" to "Institute's Bus"
- frappe.reload_doc("education", "doctype", "Program Enrollment")
- if "mode_of_transportation" in frappe.db.get_table_columns("Program Enrollment"):
- frappe.db.sql("""update `tabProgram Enrollment` set mode_of_transportation = "Institute's Bus"
- where mode_of_transportation = "School Bus" """)
diff --git a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
deleted file mode 100644
index e6546e386b..0000000000
--- a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe, erpnext
-
-def execute():
- for company in frappe.get_all("Company"):
- if not erpnext.is_perpetual_inventory_enabled(company.name):
- continue
-
- acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
- pr_with_rejected_warehouse = frappe.db.sql("""
- select pr.name
- from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
- where pr.name = pr_item.parent
- and pr.posting_date > %s
- and pr.docstatus=1
- and pr.company = %s
- and pr_item.rejected_qty > 0
- """, (acc_frozen_upto, company.name), as_dict=1)
-
- for d in pr_with_rejected_warehouse:
- doc = frappe.get_doc("Purchase Receipt", d.name)
-
- doc.docstatus = 2
- doc.make_gl_entries_on_cancel()
-
-
- # update gl entries for submit state of PR
- doc.docstatus = 1
- doc.make_gl_entries()
diff --git a/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py b/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py
deleted file mode 100644
index 4fe4e97cf5..0000000000
--- a/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2019, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
-
- count=0
- for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse
- from `tabMaterial Request Item` where docstatus = 1 and stock_uom<>uom"""):
- try:
- count += 1
- update_bin_qty(item_code, warehouse, {
- "indented_qty": get_indented_qty(item_code, warehouse),
- })
- if count % 200 == 0:
- frappe.db.commit()
- except:
- frappe.db.rollback()
diff --git a/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py b/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py
deleted file mode 100644
index c6470f21d7..0000000000
--- a/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- serialised_items = [d.name for d in frappe.get_all("Item", filters={"has_serial_no": 1})]
-
- if not serialised_items:
- return
-
- for dt in ["Stock Entry Detail", "Purchase Receipt Item", "Purchase Invoice Item"]:
- cond = ""
- if dt=="Purchase Invoice Item":
- cond = """ and parent in (select name from `tabPurchase Invoice`
- where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.parent and update_stock=1)"""
-
- item_rows = frappe.db.sql("""
- select name
- from `tab{0}`
- where conversion_factor != 1
- and docstatus = 1
- and ifnull(serial_no, '') = ''
- and item_code in ({1})
- {2}
- """.format(dt, ', '.join(['%s']*len(serialised_items)), cond), tuple(serialised_items))
-
- if item_rows:
- sle_serial_nos = dict(frappe.db.sql("""
- select voucher_detail_no, serial_no
- from `tabStock Ledger Entry`
- where ifnull(serial_no, '') != ''
- and voucher_detail_no in (%s)
- """.format(', '.join(['%s']*len(item_rows))),
- tuple([d[0] for d in item_rows])))
-
- batch_size = 100
- for i in range(0, len(item_rows), batch_size):
- batch_item_rows = item_rows[i:i + batch_size]
- when_then = []
- for item_row in batch_item_rows:
-
- when_then.append('WHEN `name` = "{row_name}" THEN "{value}"'.format(
- row_name=item_row[0],
- value=sle_serial_nos.get(item_row[0])))
-
- frappe.db.sql("""
- update
- `tab{doctype}`
- set
- serial_no = CASE {when_then_cond} ELSE `serial_no` END
- """.format(
- doctype = dt,
- when_then_cond=" ".join(when_then)
- ))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_b2c_limit.py b/erpnext/patches/v10_0/set_b2c_limit.py
deleted file mode 100644
index 5d964e681a..0000000000
--- a/erpnext/patches/v10_0/set_b2c_limit.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("regional", "doctype", "gst_settings")
- frappe.reload_doc("accounts", "doctype", "gst_account")
- gst_settings = frappe.get_doc("GST Settings")
- gst_settings.b2c_limit = 250000
- gst_settings.save()
diff --git a/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py b/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py
deleted file mode 100644
index a90e096390..0000000000
--- a/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.patches.v8_10.change_default_customer_credit_days import make_payment_term, make_template
-
-def execute():
- for dt in ("Company", "Customer Group"):
- frappe.reload_doc("setup", "doctype", frappe.scrub(dt))
-
- credit_records = frappe.db.sql("""
- SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name`
- from `tab{0}`
- where
- ((credit_days_based_on='Fixed Days' or credit_days_based_on is null) and credit_days is not null)
- or credit_days_based_on='Last Day of the Next Month'
- """.format(dt), as_dict=1)
-
- for d in credit_records:
- template = create_payment_terms_template(d)
-
- frappe.db.sql("""
- update `tab{0}`
- set `payment_terms` = %s
- where name = %s
- """.format(dt), (template.name, d.name))
-
-def create_payment_terms_template(data):
- if data.credit_days_based_on == "Fixed Days":
- pyt_template_name = 'Default Payment Term - N{0}'.format(data.credit_days)
- else:
- pyt_template_name = 'Default Payment Term - EO2M'
-
- if not frappe.db.exists("Payment Terms Template", pyt_template_name):
- payment_term = make_payment_term(data.credit_days, data.credit_days_based_on)
- template = make_template(payment_term)
- else:
- template = frappe.get_doc("Payment Terms Template", pyt_template_name)
- return template
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_discount_amount.py b/erpnext/patches/v10_0/set_discount_amount.py
deleted file mode 100644
index d5e2c5a84b..0000000000
--- a/erpnext/patches/v10_0/set_discount_amount.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "sales_invoice_item")
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_item')
- frappe.reload_doc('buying', 'doctype', 'purchase_order_item')
- frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item')
- frappe.reload_doc('selling', 'doctype', 'sales_order_item')
- frappe.reload_doc('selling', 'doctype', 'quotation_item')
- frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
-
- selling_doctypes = ["Sales Order Item", "Sales Invoice Item", "Delivery Note Item", "Quotation Item"]
- buying_doctypes = ["Purchase Order Item", "Purchase Invoice Item", "Purchase Receipt Item", "Supplier Quotation Item"]
-
- for doctype in selling_doctypes:
- frappe.db.sql('''
- UPDATE
- `tab%s`
- SET
- discount_amount = if(rate_with_margin > 0, rate_with_margin, price_list_rate) * discount_percentage / 100
- WHERE
- discount_percentage > 0
- ''' % (doctype))
- for doctype in buying_doctypes:
- frappe.db.sql('''
- UPDATE
- `tab%s`
- SET
- discount_amount = price_list_rate * discount_percentage / 100
- WHERE
- discount_percentage > 0
- ''' % (doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py b/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py
deleted file mode 100644
index 6825f19d74..0000000000
--- a/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- item_numeric_attributes = frappe.db.sql("""
- select name, numeric_values, from_range, to_range, increment
- from `tabItem Attribute`
- where numeric_values = 1
- """, as_dict=1)
-
- for d in item_numeric_attributes:
- frappe.db.sql("""
- update `tabItem Variant Attribute`
- set
- from_range = CASE
- WHEN from_range = 0 THEN %(from_range)s
- ELSE from_range
- END,
- to_range = CASE
- WHEN to_range = 0 THEN %(to_range)s
- ELSE to_range
- END,
- increment = CASE
- WHEN increment = 0 THEN %(increment)s
- ELSE increment
- END,
- numeric_values = %(numeric_values)s
- where
- attribute = %(name)s
- and exists(select name from tabItem
- where name=`tabItem Variant Attribute`.parent and has_variants=1)
- """, d)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_primary_contact_for_customer.py b/erpnext/patches/v10_0/set_primary_contact_for_customer.py
deleted file mode 100644
index ae0b31c21f..0000000000
--- a/erpnext/patches/v10_0/set_primary_contact_for_customer.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Customer')
-
- frappe.db.sql("""
- update
- `tabCustomer`, (
- select `tabContact`.name, `tabContact`.mobile_no, `tabContact`.email_id,
- `tabDynamic Link`.link_name from `tabContact`, `tabDynamic Link`
- where `tabContact`.name = `tabDynamic Link`.parent and
- `tabDynamic Link`.link_doctype = 'Customer' and `tabContact`.is_primary_contact = 1
- ) as contact
- set
- `tabCustomer`.customer_primary_contact = contact.name,
- `tabCustomer`.mobile_no = contact.mobile_no, `tabCustomer`.email_id = contact.email_id
- where `tabCustomer`.name = contact.link_name""")
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py b/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py
deleted file mode 100644
index 083b7f4b20..0000000000
--- a/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "stock_settings")
-
- ss = frappe.get_doc("Stock Settings")
- ss.set_qty_in_transactions_based_on_serial_no_input = 1
-
- if ss.default_warehouse \
- and not frappe.db.exists("Warehouse", ss.default_warehouse):
- ss.default_warehouse = None
-
- if ss.stock_uom and not frappe.db.exists("UOM", ss.stock_uom):
- ss.stock_uom = None
-
- ss.flags.ignore_mandatory = True
- ss.save()
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_student_party_type.py b/erpnext/patches/v10_0/set_student_party_type.py
deleted file mode 100644
index 08376ae894..0000000000
--- a/erpnext/patches/v10_0/set_student_party_type.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists("Party Type", "Student"):
- party = frappe.new_doc("Party Type")
- party.party_type = "Student"
- party.save()
diff --git a/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py b/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py
deleted file mode 100644
index a8d90499d8..0000000000
--- a/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.setup.doctype.company.company import install_country_fixtures
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
- frappe.reload_doc("accounts", "doctype", "payment_schedule")
- for d in frappe.get_all('Company',
- filters={'country': ('in', ['Saudi Arabia', 'United Arab Emirates'])}):
- install_country_fixtures(d.name)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py b/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py
deleted file mode 100644
index 7e2ff7a8a7..0000000000
--- a/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("hr", "doctype", "hr_settings")
- frappe.db.set_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar", 1)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/taxes_issue_with_pos.py b/erpnext/patches/v10_0/taxes_issue_with_pos.py
deleted file mode 100644
index 2a3275ac2c..0000000000
--- a/erpnext/patches/v10_0/taxes_issue_with_pos.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.get_all('Sales Invoice', fields=["name"],
- filters = {'is_pos':1, 'docstatus': 1, 'creation': ('>', '2018-04-23')}):
- doc = frappe.get_doc('Sales Invoice', d.name)
- if (not doc.taxes and doc.taxes_and_charges and doc.pos_profile and doc.outstanding_amount != 0 and
- frappe.db.get_value('POS Profile', doc.pos_profile, 'taxes_and_charges', cache=True) == doc.taxes_and_charges):
-
- doc.append_taxes_from_master()
- doc.calculate_taxes_and_totals()
- for d in doc.taxes:
- d.db_update()
-
- doc.db_update()
-
- delete_gle_for_voucher(doc.name)
- doc.make_gl_entries()
-
-def delete_gle_for_voucher(voucher_no):
- frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
- {'voucher_no': voucher_no})
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_address_template_for_india.py b/erpnext/patches/v10_0/update_address_template_for_india.py
deleted file mode 100644
index 1ddca93760..0000000000
--- a/erpnext/patches/v10_0/update_address_template_for_india.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.address_template.setup import set_up_address_templates
-
-def execute():
- if frappe.db.get_value('Company', {'country': 'India'}, 'name'):
- address_template = frappe.db.get_value('Address Template', 'India', 'template')
- if not address_template or "gstin" not in address_template:
- set_up_address_templates(default_country='India')
diff --git a/erpnext/patches/v10_0/update_assessment_plan.py b/erpnext/patches/v10_0/update_assessment_plan.py
deleted file mode 100644
index 174623c1a4..0000000000
--- a/erpnext/patches/v10_0/update_assessment_plan.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('education', 'doctype', 'assessment_plan')
-
- frappe.db.sql("""
- UPDATE `tabAssessment Plan` as ap
- INNER JOIN `tabStudent Group` as sg ON sg.name = ap.student_group
- SET ap.academic_term = sg.academic_term,
- ap.academic_year = sg.academic_year,
- ap.program = sg.program
- WHERE ap.docstatus = 1
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_assessment_result.py b/erpnext/patches/v10_0/update_assessment_result.py
deleted file mode 100644
index 96218db972..0000000000
--- a/erpnext/patches/v10_0/update_assessment_result.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('education', 'doctype', 'assessment_result')
-
- frappe.db.sql("""
- UPDATE `tabAssessment Result` AS ar
- INNER JOIN `tabAssessment Plan` AS ap ON ap.name = ar.assessment_plan
- SET ar.academic_term = ap.academic_term,
- ar.academic_year = ap.academic_year,
- ar.program = ap.program,
- ar.course = ap.course,
- ar.assessment_group = ap.assessment_group,
- ar.student_group = ap.student_group
- WHERE ap.docstatus = 1
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_asset_calculate_depreciation.py b/erpnext/patches/v10_0/update_asset_calculate_depreciation.py
deleted file mode 100644
index b947a40b4a..0000000000
--- a/erpnext/patches/v10_0/update_asset_calculate_depreciation.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('assets', 'doctype', 'asset')
- frappe.reload_doc('assets', 'doctype', 'depreciation_schedule')
-
- frappe.db.sql("""
- update tabAsset a
- set calculate_depreciation = 1
- where exists(select ds.name from `tabDepreciation Schedule` ds where ds.parent=a.name)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_hub_connector_domain.py b/erpnext/patches/v10_0/update_hub_connector_domain.py
deleted file mode 100644
index baf580a369..0000000000
--- a/erpnext/patches/v10_0/update_hub_connector_domain.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Data Migration Connector"):
- frappe.db.sql("""
- UPDATE `tabData Migration Connector`
- SET hostname = 'https://hubmarket.org'
- WHERE connector_name = 'Hub Connector'
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_lft_rgt_for_employee.py b/erpnext/patches/v10_0/update_lft_rgt_for_employee.py
deleted file mode 100644
index 46ca786e0d..0000000000
--- a/erpnext/patches/v10_0/update_lft_rgt_for_employee.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils.nestedset import rebuild_tree
-
-def execute():
- """ assign lft and rgt appropriately """
- frappe.reload_doc("hr", "doctype", "employee")
-
- rebuild_tree("Employee", "reports_to")
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_project_in_sle.py b/erpnext/patches/v10_0/update_project_in_sle.py
deleted file mode 100644
index 08c64f18d8..0000000000
--- a/erpnext/patches/v10_0/update_project_in_sle.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ['Sales Invoice', 'Delivery Note', 'Stock Entry']:
- frappe.db.sql(""" update
- `tabStock Ledger Entry` sle, `tab{0}` parent_doc
- set
- sle.project = parent_doc.project
- where
- sle.voucher_no = parent_doc.name and sle.voucher_type = %s and sle.project is null
- and parent_doc.project is not null and parent_doc.project != ''""".format(doctype), doctype)
diff --git a/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py b/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py
deleted file mode 100644
index 7b2c36698a..0000000000
--- a/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.utils import get_bin
-
-def execute():
- po_item = list(frappe.db.sql(("""
- select distinct po.name as poname, poitem.rm_item_code as rm_item_code, po.company
- from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitem
- where po.name = poitem.parent
- and po.is_subcontracted = "Yes"
- and po.docstatus = 1"""), as_dict=1))
- if not po_item:
- return
-
- frappe.reload_doc("stock", "doctype", "bin")
- frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied")
- company_warehouse = frappe._dict(frappe.db.sql("""select company, min(name) from `tabWarehouse`
- where is_group = 0 group by company"""))
-
- items = list(set([d.rm_item_code for d in po_item]))
- item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse
- from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items))
-
- # Update reserved warehouse
- for item in po_item:
- reserve_warehouse = get_warehouse(item.rm_item_code, item.company, company_warehouse, item_wh)
- frappe.db.sql("""update `tabPurchase Order Item Supplied`
- set reserve_warehouse = %s
- where parent = %s and rm_item_code = %s
- """, (reserve_warehouse, item["poname"], item["rm_item_code"]))
-
- # Update bin
- item_wh_bin = frappe.db.sql(("""
- select distinct poitemsup.rm_item_code as rm_item_code,
- poitemsup.reserve_warehouse as reserve_warehouse
- from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
- where po.name = poitemsup.parent
- and po.is_subcontracted = "Yes"
- and po.docstatus = 1"""), as_dict=1)
- for d in item_wh_bin:
- try:
- stock_bin = get_bin(d["rm_item_code"], d["reserve_warehouse"])
- stock_bin.update_reserved_qty_for_sub_contracting()
- except:
- pass
-
-def get_warehouse(item_code, company, company_warehouse, item_wh):
- reserve_warehouse = item_wh.get(item_code)
- if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != company:
- reserve_warehouse = None
- if not reserve_warehouse:
- reserve_warehouse = company_warehouse.get(company)
- return reserve_warehouse
diff --git a/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py b/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py
deleted file mode 100644
index b4f58384bf..0000000000
--- a/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("buying", "doctype", "supplier_quotation_item")
-
- for doctype in ['Purchase Order','Supplier Quotation']:
- frappe.db.sql("""
- Update
- `tab{doctype} Item`, `tabMaterial Request Item`
- set
- `tab{doctype} Item`.sales_order = `tabMaterial Request Item`.sales_order
- where
- `tab{doctype} Item`.material_request= `tabMaterial Request Item`.parent
- and `tab{doctype} Item`.material_request_item = `tabMaterial Request Item`.name
- and `tabMaterial Request Item`.sales_order is not null""".format(doctype=doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py b/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py
deleted file mode 100644
index fd3be08b89..0000000000
--- a/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
-
-
- # update the sales order item in the material request
- frappe.reload_doc('stock', 'doctype', 'material_request_item')
- frappe.db.sql('''update `tabMaterial Request Item` mri, `tabSales Order Item` soi
- set mri.sales_order_item = soi.name
- where ifnull(mri.sales_order, "")!="" and soi.parent=mri.sales_order
- and soi.item_code=mri.item_code and mri.docstatus=1
- ''')
-
- # update the sales order item in the purchase order
- frappe.db.sql('''update `tabPurchase Order Item` poi, `tabSales Order Item` soi
- set poi.sales_order_item = soi.name
- where ifnull(poi.sales_order, "")!="" and soi.parent=poi.sales_order
- and soi.item_code=poi.item_code and poi.docstatus = 1
- ''')
-
- # Update the status in material request and sales order
- po_list = frappe.db.sql('''
- select parent from `tabPurchase Order Item` where ifnull(material_request, "")!="" and
- ifnull(sales_order, "")!="" and docstatus=1
- ''',as_dict=1)
-
- for po in list(set([d.get("parent") for d in po_list if d.get("parent")])):
- try:
- po_doc = frappe.get_doc("Purchase Order", po)
-
- # update the so in the status updater
- po_doc.update_status_updater()
- po_doc.update_qty(update_modified=False)
-
- except Exception:
- pass
diff --git a/erpnext/patches/v10_0/update_status_in_purchase_receipt.py b/erpnext/patches/v10_0/update_status_in_purchase_receipt.py
deleted file mode 100644
index a0bdd9e2cc..0000000000
--- a/erpnext/patches/v10_0/update_status_in_purchase_receipt.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "purchase_receipt")
- frappe.db.sql('''
- UPDATE `tabPurchase Receipt` SET status = "Completed" WHERE per_billed = 100 AND docstatus = 1
- ''')
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_territory_and_customer_group.py b/erpnext/patches/v10_0/update_territory_and_customer_group.py
deleted file mode 100644
index 7f3dae991d..0000000000
--- a/erpnext/patches/v10_0/update_territory_and_customer_group.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.rename_doc import get_fetch_fields
-
-def execute():
- ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"]
- customers = frappe.get_all('Customer', fields=["name", "customer_group"])
- customer_group_fetch = get_fetch_fields('Customer', 'Customer Group', ignore_doctypes)
-
- batch_size = 1000
- for i in range(0, len(customers), batch_size):
- batch_customers = customers[i:i + batch_size]
- for d in customer_group_fetch:
- when_then = []
- for customer in batch_customers:
- value = frappe.db.escape(frappe.as_unicode(customer.get("customer_group")))
-
- when_then.append('''
- WHEN `%s` = %s and %s != %s
- THEN %s
- '''%(d["master_fieldname"], frappe.db.escape(frappe.as_unicode(customer.name)),
- d["linked_to_fieldname"], value, value))
-
- frappe.db.sql("""
- update
- `tab%s`
- set
- %s = CASE %s ELSE `%s` END
- """%(d['doctype'], d.linked_to_fieldname, " ".join(when_then), d.linked_to_fieldname))
diff --git a/erpnext/patches/v10_0/update_user_image_in_employee.py b/erpnext/patches/v10_0/update_user_image_in_employee.py
deleted file mode 100644
index 72d5d2a857..0000000000
--- a/erpnext/patches/v10_0/update_user_image_in_employee.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('hr', 'doctype', 'employee')
-
- frappe.db.sql("""
- UPDATE
- `tabEmployee`, `tabUser`
- SET
- `tabEmployee`.image = `tabUser`.user_image
- WHERE
- `tabEmployee`.user_id = `tabUser`.name and
- `tabEmployee`.user_id is not null and
- `tabEmployee`.user_id != '' and `tabEmployee`.image is null
- """)
diff --git a/erpnext/patches/v10_0/update_warehouse_address_details.py b/erpnext/patches/v10_0/update_warehouse_address_details.py
deleted file mode 100644
index b982b9a662..0000000000
--- a/erpnext/patches/v10_0/update_warehouse_address_details.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- warehouse = frappe.db.sql("""select name, email_id, phone_no, mobile_no, address_line_1,
- address_line_2, city, state, pin from `tabWarehouse` where ifnull(address_line_1, '') != ''
- or ifnull(mobile_no, '') != ''
- or ifnull(email_id, '') != '' """, as_dict=1)
-
- for d in warehouse:
- try:
- address = frappe.new_doc('Address')
- address.name = d.name
- address.address_title = d.name
- address.address_line1 = d.address_line_1
- address.city = d.city
- address.state = d.state
- address.pincode = d.pin
- address.db_insert()
- address.append('links',{'link_doctype':'Warehouse','link_name':d.name})
- address.links[0].db_insert()
- if d.name and (d.email_id or d.mobile_no or d.phone_no):
- contact = frappe.new_doc('Contact')
- contact.name = d.name
- contact.first_name = d.name
- contact.mobile_no = d.mobile_no
- contact.email_id = d.email_id
- contact.phone = d.phone_no
- contact.db_insert()
- contact.append('links',{'link_doctype':'Warehouse','link_name':d.name})
- contact.links[0].db_insert()
- except frappe.DuplicateEntryError:
- pass
-
\ No newline at end of file
diff --git a/erpnext/patches/v10_1/__init__.py b/erpnext/patches/v10_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v11_0/__init__.py b/erpnext/patches/v11_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v11_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v11_0/remove_subscriber_doctype.py b/erpnext/patches/v11_0/remove_subscriber_doctype.py
deleted file mode 100644
index 4839a20f91..0000000000
--- a/erpnext/patches/v11_0/remove_subscriber_doctype.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- """ copy subscribe field to customer """
- frappe.reload_doc("accounts","doctype","subscription")
-
- if frappe.db.exists("DocType", "Subscriber"):
- if frappe.db.has_column('Subscription','subscriber'):
- frappe.db.sql("""
- update `tabSubscription` s1
- set customer=(select customer from tabSubscriber where name=s1.subscriber)
- """)
-
- frappe.delete_doc("DocType", "Subscriber")
\ No newline at end of file
diff --git a/erpnext/patches/v11_1/__init__.py b/erpnext/patches/v11_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v12_0/__init__.py b/erpnext/patches/v12_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v13_0/__init__.py b/erpnext/patches/v13_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v13_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v4_0/__init__.py b/erpnext/patches/v4_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_0/apply_user_permissions.py b/erpnext/patches/v4_0/apply_user_permissions.py
deleted file mode 100644
index 3c5d612c18..0000000000
--- a/erpnext/patches/v4_0/apply_user_permissions.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.hr.doctype.employee.employee import EmployeeUserDisabledError
-
-def execute():
- update_hr_permissions()
- update_permissions()
- remove_duplicate_user_permissions()
- frappe.clear_cache()
-
-def update_hr_permissions():
- # add set user permissions rights to HR Manager
- frappe.db.sql("""update `tabDocPerm` set `set_user_permissions`=1 where parent in ('Employee', 'Leave Application')
- and role='HR Manager' and permlevel=0 and `read`=1""")
- docperm_meta = frappe.get_meta('DocPerm')
- if docperm_meta.get_field('apply_user_permissions'):
- # apply user permissions on Employee and Leave Application
- frappe.db.sql("""update `tabDocPerm` set `apply_user_permissions`=1 where parent in ('Employee', 'Leave Application')
- and role in ('Employee', 'Leave Approver') and permlevel=0 and `read`=1""")
-
- frappe.clear_cache()
-
- # save employees to run on_update events
- for employee in frappe.db.sql_list("""select name from `tabEmployee` where docstatus < 2"""):
- try:
- emp = frappe.get_doc("Employee", employee)
- emp.flags.ignore_mandatory = True
- emp.save()
- except EmployeeUserDisabledError:
- pass
-
-def update_permissions():
- # clear match conditions other than owner
- frappe.db.sql("""update tabDocPerm set `match`=''
- where ifnull(`match`,'') not in ('', 'owner')""")
-
-def remove_duplicate_user_permissions():
- # remove duplicate user_permissions (if they exist)
- for d in frappe.db.sql("""select parent, defkey, defvalue,
- count(*) as cnt from tabDefaultValue
- where parent not in ('__global', '__default')
- group by parent, defkey, defvalue""", as_dict=1):
- if d.cnt > 1:
- # order by parenttype so that user permission does not get removed!
- frappe.db.sql("""delete from tabDefaultValue where `parent`=%s and `defkey`=%s and
- `defvalue`=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))
-
diff --git a/erpnext/patches/v4_0/countrywise_coa.py b/erpnext/patches/v4_0/countrywise_coa.py
deleted file mode 100644
index f45e6028c8..0000000000
--- a/erpnext/patches/v4_0/countrywise_coa.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("setup", 'doctype', "company")
- frappe.reload_doc("accounts", 'doctype', "account")
-
- frappe.db.sql("""update tabAccount set account_type='Cash'
- where account_type='Bank or Cash' and account_name in ('Cash', 'Cash In Hand')""")
-
- frappe.db.sql("""update tabAccount set account_type='Stock'
- where account_name = 'Stock Assets'""")
-
- ac_types = {"Fixed Asset Account": "Fixed Asset", "Bank or Cash": "Bank"}
- for old, new in ac_types.items():
- frappe.db.sql("""update tabAccount set account_type=%s
- where account_type=%s""", (new, old))
-
- try:
- frappe.db.sql("""update `tabAccount` set report_type =
- if(is_pl_account='Yes', 'Profit and Loss', 'Balance Sheet')""")
-
- frappe.db.sql("""update `tabAccount` set balance_must_be=debit_or_credit
- where ifnull(allow_negative_balance, 0) = 0""")
- except:
- pass
diff --git a/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py b/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py
deleted file mode 100644
index fe50e444b5..0000000000
--- a/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.custom.doctype.custom_field.custom_field import create_custom_field_if_values_exist
-
-def execute():
- frappe.reload_doc("stock", "doctype", "purchase_receipt")
- frappe.reload_doc("hr", "doctype", "employee")
- frappe.reload_doc("Payroll", "doctype", "salary_slip")
-
- india_specific_fields = {
- "Purchase Receipt": [{
- "label": "Supplier Shipment No",
- "fieldname": "challan_no",
- "fieldtype": "Data",
- "insert_after": "is_subcontracted"
- }, {
- "label": "Supplier Shipment Date",
- "fieldname": "challan_date",
- "fieldtype": "Date",
- "insert_after": "is_subcontracted"
- }],
- "Employee": [{
- "label": "PAN Number",
- "fieldname": "pan_number",
- "fieldtype": "Data",
- "insert_after": "company_email"
- }, {
- "label": "Gratuity LIC Id",
- "fieldname": "gratuity_lic_id",
- "fieldtype": "Data",
- "insert_after": "company_email"
- }, {
- "label": "Esic Card No",
- "fieldname": "esic_card_no",
- "fieldtype": "Data",
- "insert_after": "bank_ac_no"
- }, {
- "label": "PF Number",
- "fieldname": "pf_number",
- "fieldtype": "Data",
- "insert_after": "bank_ac_no"
- }],
- "Salary Slip": [{
- "label": "Esic No",
- "fieldname": "esic_no",
- "fieldtype": "Data",
- "insert_after": "letter_head",
- "permlevel": 1
- }, {
- "label": "PF Number",
- "fieldname": "pf_no",
- "fieldtype": "Data",
- "insert_after": "letter_head",
- "permlevel": 1
- }]
- }
-
- for dt, docfields in india_specific_fields.items():
- for df in docfields:
- create_custom_field_if_values_exist(dt, df)
diff --git a/erpnext/patches/v4_0/create_price_list_if_missing.py b/erpnext/patches/v4_0/create_price_list_if_missing.py
deleted file mode 100644
index 039e52111c..0000000000
--- a/erpnext/patches/v4_0/create_price_list_if_missing.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-from frappe.utils.nestedset import get_root_of
-
-def execute():
- # setup not complete
- if not frappe.db.sql("""select name from tabCompany limit 1"""):
- return
-
- if "shopping_cart" in frappe.get_installed_apps():
- frappe.reload_doc("shopping_cart", "doctype", "shopping_cart_settings")
-
- if not frappe.db.sql("select name from `tabPrice List` where buying=1"):
- create_price_list(_("Standard Buying"), buying=1)
-
- if not frappe.db.sql("select name from `tabPrice List` where selling=1"):
- create_price_list(_("Standard Selling"), selling=1)
-
-def create_price_list(pl_name, buying=0, selling=0):
- price_list = frappe.get_doc({
- "doctype": "Price List",
- "price_list_name": pl_name,
- "enabled": 1,
- "buying": buying,
- "selling": selling,
- "currency": frappe.db.get_default("currency"),
- "territories": [{
- "territory": get_root_of("Territory")
- }]
- })
- price_list.insert()
diff --git a/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py b/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py
deleted file mode 100644
index 1b260c48cc..0000000000
--- a/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils.nestedset import get_root_of
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "pricing_rule")
-
- frappe.db.auto_commit_on_many_writes = True
-
- default_item_group = get_root_of("Item Group")
-
- for d in frappe.db.sql("""select * from `tabCustomer Discount`
- where ifnull(parent, '') != ''""", as_dict=1):
- if not d.discount:
- continue
-
- frappe.get_doc({
- "doctype": "Pricing Rule",
- "apply_on": "Item Group",
- "item_group": d.item_group or default_item_group,
- "applicable_for": "Customer",
- "customer": d.parent,
- "price_or_discount": "Discount Percentage",
- "discount_percentage": d.discount,
- "selling": 1
- }).insert()
-
- frappe.db.auto_commit_on_many_writes = False
-
- frappe.delete_doc("DocType", "Customer Discount")
diff --git a/erpnext/patches/v4_0/fields_to_be_renamed.py b/erpnext/patches/v4_0/fields_to_be_renamed.py
deleted file mode 100644
index cc17697132..0000000000
--- a/erpnext/patches/v4_0/fields_to_be_renamed.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-from frappe.modules import scrub, get_doctype_module
-
-rename_map = {
- "Quotation Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"]
- ],
-
- "Sales Order Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"],
- ["reserved_warehouse", "warehouse"]
- ],
-
- "Delivery Note Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"]
- ],
-
- "Sales Invoice Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"]
- ],
-
- "Supplier Quotation Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["purchase_rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"]
- ],
-
- "Purchase Order Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["purchase_rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"]
- ],
-
- "Purchase Receipt Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["purchase_rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"]
- ],
-
- "Purchase Invoice Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"],
- ["expense_head", "expense_account"]
- ],
-
- "Item": [
- ["purchase_account", "expense_account"],
- ["default_sales_cost_center", "selling_cost_center"],
- ["cost_center", "buying_cost_center"],
- ["default_income_account", "income_account"],
- ],
- "Item Price": [
- ["ref_rate", "price_list_rate"]
- ]
-}
-
-def execute():
- for dn in rename_map:
- frappe.reload_doc(get_doctype_module(dn), "doctype", scrub(dn))
-
- for dt, field_list in rename_map.items():
- for field in field_list:
- rename_field(dt, field[0], field[1])
diff --git a/erpnext/patches/v4_0/fix_address_template.py b/erpnext/patches/v4_0/fix_address_template.py
deleted file mode 100644
index 905e3db3e8..0000000000
--- a/erpnext/patches/v4_0/fix_address_template.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- missing_line = """{{ address_line1 }}
"""
- for name, template in frappe.db.sql("select name, template from `tabAddress Template`"):
- if missing_line not in template:
- d = frappe.get_doc("Address Template", name)
- d.template = missing_line + d.template
- d.save()
diff --git a/erpnext/patches/v4_0/fix_case_of_hr_module_def.py b/erpnext/patches/v4_0/fix_case_of_hr_module_def.py
deleted file mode 100644
index e77b427b77..0000000000
--- a/erpnext/patches/v4_0/fix_case_of_hr_module_def.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- hr = frappe.db.get_value("Module Def", "HR")
- if hr == "Hr":
- frappe.rename_doc("Module Def", "Hr", "HR")
- frappe.db.set_value("Module Def", "HR", "module_name", "HR")
-
- frappe.clear_cache()
- frappe.setup_module_map()
diff --git a/erpnext/patches/v4_0/fix_contact_address.py b/erpnext/patches/v4_0/fix_contact_address.py
deleted file mode 100644
index 6a3e106b8c..0000000000
--- a/erpnext/patches/v4_0/fix_contact_address.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("website", "doctype", "contact_us_settings")
- address = frappe.db.get_value("Contact Us Settings", None, "address")
- if address:
- address = frappe.get_doc("Address", address)
- contact = frappe.get_doc("Contact Us Settings", "Contact Us Settings")
- for f in ("address_title", "address_line1", "address_line2", "city", "state", "country", "pincode"):
- contact.set(f, address.get(f))
-
- contact.save()
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/fix_employee_user_id.py b/erpnext/patches/v4_0/fix_employee_user_id.py
deleted file mode 100644
index 6f449f97bb..0000000000
--- a/erpnext/patches/v4_0/fix_employee_user_id.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-from frappe.utils import get_fullname
-
-def execute():
- for user_id in frappe.db.sql_list("""select distinct user_id from `tabEmployee`
- where ifnull(user_id, '')!=''
- group by user_id having count(name) > 1"""):
-
- fullname = get_fullname(user_id)
- employee = frappe.db.get_value("Employee", {"employee_name": fullname, "user_id": user_id})
-
- if employee:
- frappe.db.sql("""update `tabEmployee` set user_id=null
- where user_id=%s and name!=%s""", (user_id, employee))
- else:
- count = frappe.db.sql("""select count(*) from `tabEmployee` where user_id=%s""", user_id)[0][0]
- frappe.db.sql("""update `tabEmployee` set user_id=null
- where user_id=%s limit %s""", (user_id, count - 1))
diff --git a/erpnext/patches/v4_0/global_defaults_to_system_settings.py b/erpnext/patches/v4_0/global_defaults_to_system_settings.py
deleted file mode 100644
index 2905fe1e6a..0000000000
--- a/erpnext/patches/v4_0/global_defaults_to_system_settings.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# MIT License. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-from collections import Counter
-from frappe.core.doctype.user.user import STANDARD_USERS
-
-def execute():
- frappe.reload_doc("core", "doctype", "system_settings")
- system_settings = frappe.get_doc("System Settings")
-
- # set values from global_defauls
- global_defaults = frappe.db.get_value("Global Defaults", None,
- ["time_zone", "date_format", "number_format", "float_precision", "session_expiry"], as_dict=True)
-
- if global_defaults:
- for key, val in global_defaults.items():
- if not system_settings.get(key):
- system_settings.set(key, val)
-
- # language
- if not system_settings.get("language"):
- # find most common language
- lang = frappe.db.sql_list("""select language from `tabUser`
- where ifnull(language, '')!='' and language not like "Loading%%" and name not in ({standard_users})""".format(
- standard_users=", ".join(["%s"]*len(STANDARD_USERS))), tuple(STANDARD_USERS))
- lang = Counter(lang).most_common(1)
- lang = (len(lang) > 0) and lang[0][0] or "english"
-
- system_settings.language = lang
-
- system_settings.flags.ignore_mandatory = True
- system_settings.save()
-
- global_defaults = frappe.get_doc("Global Defaults")
- global_defaults.flags.ignore_mandatory = True
- global_defaults.save()
diff --git a/erpnext/patches/v4_0/import_country_codes.py b/erpnext/patches/v4_0/import_country_codes.py
deleted file mode 100644
index 43e23d5b63..0000000000
--- a/erpnext/patches/v4_0/import_country_codes.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# MIT License. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.geo.country_info import get_all
-from frappe.utils.install import import_country_and_currency
-
-from six import iteritems
-
-def execute():
- frappe.reload_doc("setup", "doctype", "country")
- import_country_and_currency()
- for name, country in iteritems(get_all()):
- frappe.set_value("Country", name, "code", country.get("code"))
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py b/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py
deleted file mode 100644
index 97e217aa05..0000000000
--- a/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # update sales cycle
- for d in ['Sales Invoice', 'Sales Order', 'Quotation', 'Delivery Note']:
- frappe.db.sql("""update `tab%s` set taxes_and_charges=charge""" % d)
-
- # update purchase cycle
- for d in ['Purchase Invoice', 'Purchase Order', 'Supplier Quotation', 'Purchase Receipt']:
- frappe.db.sql("""update `tab%s` set taxes_and_charges=purchase_other_charges""" % d)
-
- frappe.db.sql("""update `tabPurchase Taxes and Charges` set parentfield='other_charges'""")
diff --git a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py b/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
deleted file mode 100644
index 8b81936d8d..0000000000
--- a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- for warehouse, user in frappe.db.sql("""select parent, user from `tabWarehouse User`"""):
- frappe.permissions.add_user_permission("Warehouse", warehouse, user)
-
- frappe.delete_doc_if_exists("DocType", "Warehouse User")
- frappe.reload_doc("stock", "doctype", "warehouse")
diff --git a/erpnext/patches/v4_0/new_address_template.py b/erpnext/patches/v4_0/new_address_template.py
deleted file mode 100644
index fa6602706e..0000000000
--- a/erpnext/patches/v4_0/new_address_template.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("utilities", "doctype", "address_template")
- if not frappe.db.sql("select name from `tabAddress Template`"):
- try:
- d = frappe.new_doc("Address Template")
- d.update({"country":frappe.db.get_default("country") or
- frappe.db.get_value("Global Defaults", "Global Defaults", "country")})
- d.insert()
- except:
- print(frappe.get_traceback())
-
diff --git a/erpnext/patches/v4_0/reload_sales_print_format.py b/erpnext/patches/v4_0/reload_sales_print_format.py
deleted file mode 100644
index b8f090f9f3..0000000000
--- a/erpnext/patches/v4_0/reload_sales_print_format.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'Print Format', 'POS Invoice')
diff --git a/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py b/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
deleted file mode 100644
index 8766ace54f..0000000000
--- a/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- for user in frappe.db.sql_list("select distinct parent from `tabHas Role` where role='Employee'"):
- # if employee record does not exists, remove employee role!
- if not frappe.db.get_value("Employee", {"user_id": user}):
- try:
- user = frappe.get_doc("User", user)
- for role in user.get("roles", {"role": "Employee"}):
- user.get("roles").remove(role)
- user.save()
- except frappe.DoesNotExistError:
- pass
diff --git a/erpnext/patches/v4_0/remove_module_home_pages.py b/erpnext/patches/v4_0/remove_module_home_pages.py
deleted file mode 100644
index a2720e0ebf..0000000000
--- a/erpnext/patches/v4_0/remove_module_home_pages.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for page in ("accounts-home", "website-home", "support-home", "stock-home", "selling-home", "projects-home",
- "manufacturing-home", "hr-home", "buying-home"):
- frappe.delete_doc("Page", page)
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/rename_sitemap_to_route.py b/erpnext/patches/v4_0/rename_sitemap_to_route.py
deleted file mode 100644
index ffb1fda144..0000000000
--- a/erpnext/patches/v4_0/rename_sitemap_to_route.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import frappe.model
-
-def execute():
- frappe.reload_doc("setup", "doctype", "item_group")
- frappe.reload_doc("stock", "doctype", "item")
- frappe.reload_doc("setup", "doctype", "sales_partner")
-
- try:
- frappe.model.rename_field("Item Group", "parent_website_sitemap", "parent_website_route")
- frappe.model.rename_field("Item", "parent_website_sitemap", "parent_website_route")
- frappe.model.rename_field("Sales Partner", "parent_website_sitemap",
- "parent_website_route")
- except Exception as e:
- if e.args[0]!=1054:
- raise
diff --git a/erpnext/patches/v4_0/reset_permissions_for_masters.py b/erpnext/patches/v4_0/reset_permissions_for_masters.py
deleted file mode 100644
index bc1b438e2b..0000000000
--- a/erpnext/patches/v4_0/reset_permissions_for_masters.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-from frappe.permissions import reset_perms
-
-def execute():
- for doctype in ("About Us Settings", "Accounts Settings", "Activity Type",
- "Blog Category", "Blog Settings", "Blogger", "Branch", "Brand", "Buying Settings",
- "Communication", "Company", "Contact Us Settings",
- "Country", "Currency", "Currency Exchange", "Deduction Type", "Department",
- "Designation", "Earning Type", "Event", "Feed", "File", "Fiscal Year",
- "HR Settings", "Industry Type", "Leave Type", "Letter Head",
- "Mode of Payment", "Module Def", "Naming Series", "POS Setting", "Print Heading",
- "Report", "Role", "Selling Settings", "Stock Settings", "Supplier Type", "UOM"):
- try:
- reset_perms(doctype)
- except:
- print("Error resetting perms for", doctype)
- raise
diff --git a/erpnext/patches/v4_0/save_default_letterhead.py b/erpnext/patches/v4_0/save_default_letterhead.py
deleted file mode 100644
index 5d75f096b3..0000000000
--- a/erpnext/patches/v4_0/save_default_letterhead.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """save default letterhead to set default_letter_head_content"""
- try:
- letter_head = frappe.get_doc("Letter Head", {"is_default": 1})
- letter_head.save()
- except frappe.DoesNotExistError:
- pass
diff --git a/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py b/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
deleted file mode 100644
index 7e472e2195..0000000000
--- a/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "pricing_rule")
- frappe.db.sql("""update `tabPricing Rule` set selling=1 where ifnull(applicable_for, '') in
- ('', 'Customer', 'Customer Group', 'Territory', 'Sales Partner', 'Campaign')""")
-
- frappe.db.sql("""update `tabPricing Rule` set buying=1 where ifnull(applicable_for, '') in
- ('', 'Supplier', 'Supplier Type')""")
diff --git a/erpnext/patches/v4_0/split_email_settings.py b/erpnext/patches/v4_0/split_email_settings.py
deleted file mode 100644
index 5d1dea60ee..0000000000
--- a/erpnext/patches/v4_0/split_email_settings.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- print("WARNING!!!! Email Settings not migrated. Please setup your email again.")
-
- # this will happen if you are migrating very old accounts
- # comment out this line below and remember to create new Email Accounts
- # for incoming and outgoing mails
- raise Exception
-
- return
-
-
- frappe.reload_doc("core", "doctype", "outgoing_email_settings")
- frappe.reload_doc("support", "doctype", "support_email_settings")
-
- email_settings = get_email_settings()
- map_outgoing_email_settings(email_settings)
- map_support_email_settings(email_settings)
-
-
-def map_outgoing_email_settings(email_settings):
- outgoing_email_settings = frappe.get_doc("Outgoing Email Settings")
- for fieldname in (("outgoing_mail_server", "mail_server"),
- "use_ssl", "mail_port", "mail_login", "mail_password",
- "always_use_login_id_as_sender", "auto_email_id"):
-
- if isinstance(fieldname, tuple):
- from_fieldname, to_fieldname = fieldname
- else:
- from_fieldname = to_fieldname = fieldname
-
- outgoing_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
-
- outgoing_email_settings._fix_numeric_types()
- outgoing_email_settings.save()
-
-def map_support_email_settings(email_settings):
- support_email_settings = frappe.get_doc("Support Email Settings")
-
- for fieldname in ("sync_support_mails", "support_email",
- ("support_host", "mail_server"),
- ("support_use_ssl", "use_ssl"),
- ("support_username", "mail_login"),
- ("support_password", "mail_password"),
- "support_signature", "send_autoreply", "support_autoreply"):
-
- if isinstance(fieldname, tuple):
- from_fieldname, to_fieldname = fieldname
- else:
- from_fieldname = to_fieldname = fieldname
-
- support_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
-
- support_email_settings._fix_numeric_types()
- support_email_settings.save()
-
-def get_email_settings():
- ret = {}
- for field, value in frappe.db.sql("select field, value from tabSingles where doctype='Email Settings'"):
- ret[field] = value
- return ret
-
diff --git a/erpnext/patches/v4_0/update_account_root_type.py b/erpnext/patches/v4_0/update_account_root_type.py
deleted file mode 100644
index 15ddf032a4..0000000000
--- a/erpnext/patches/v4_0/update_account_root_type.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
-
- account_table_columns = frappe.db.get_table_columns("Account")
- if "debit_or_credit" in account_table_columns and "is_pl_account" in account_table_columns:
- frappe.db.sql("""UPDATE tabAccount
- SET root_type = CASE
- WHEN (debit_or_credit='Debit' and is_pl_account = 'No') THEN 'Asset'
- WHEN (debit_or_credit='Credit' and is_pl_account = 'No') THEN 'Liability'
- WHEN (debit_or_credit='Debit' and is_pl_account = 'Yes') THEN 'Expense'
- WHEN (debit_or_credit='Credit' and is_pl_account = 'Yes') THEN 'Income'
- END
- WHERE ifnull(parent_account, '') = ''
- """)
-
- else:
- for key, root_type in (("asset", "Asset"), ("liabilities", "Liability"), ("expense", "Expense"),
- ("income", "Income")):
- frappe.db.sql("""update tabAccount set root_type=%s where name like %s
- and ifnull(parent_account, '')=''""", (root_type, "%" + key + "%"))
-
- for root in frappe.db.sql("""SELECT name, lft, rgt, root_type FROM `tabAccount`
- WHERE ifnull(parent_account, '')=''""", as_dict=True):
- if root.root_type:
- frappe.db.sql("""UPDATE tabAccount SET root_type=%s WHERE lft>%s and rgt<%s""",
- (root.root_type, root.lft, root.rgt))
- else:
- print(b"Root type not found for {0}".format(root.name.encode("utf-8")))
diff --git a/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py b/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py
deleted file mode 100644
index d784a1b182..0000000000
--- a/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import re
-
-def execute():
- # NOTE: sequence is important
- fields_list = (
- ("amount", "base_amount"),
- ("ref_rate", "price_list_rate"),
- ("base_ref_rate", "base_price_list_rate"),
- ("adj_rate", "discount_percentage"),
- ("export_rate", "rate"),
- ("basic_rate", "base_rate"),
- ("export_amount", "amount"),
- ("reserved_warehouse", "warehouse"),
- ("import_ref_rate", "price_list_rate"),
- ("purchase_ref_rate", "base_price_list_rate"),
- ("discount_rate", "discount_percentage"),
- ("import_rate", "rate"),
- ("purchase_rate", "base_rate"),
- ("import_amount", "amount")
- )
-
- condition = " or ".join("""html like "%%{}%%" """.format(d[0].replace("_", "\\_")) for d in fields_list
- if d[0] != "amount")
-
- for name, html in frappe.db.sql("""select name, html from `tabPrint Format`
- where standard = 'No' and ({}) and html not like '%%frappe.%%'""".format(condition)):
- html = html.replace("wn.", "frappe.")
- for from_field, to_field in fields_list:
- html = re.sub(r"\b{}\b".format(from_field), to_field, html)
-
- frappe.db.set_value("Print Format", name, "html", html)
diff --git a/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py b/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py
deleted file mode 100644
index fe66a5e3ef..0000000000
--- a/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("support", "doctype", "schedules")
- frappe.reload_doc("support", "doctype", "maintenance_schedule_item")
-
- frappe.db.sql("""update `tabMaintenance Schedule Detail` set sales_person=incharge_name""")
- frappe.db.sql("""update `tabMaintenance Schedule Item` set sales_person=incharge_name""")
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py b/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py
deleted file mode 100644
index 2e2e77a9fc..0000000000
--- a/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import re
-
-def execute():
- for name, html in frappe.db.sql("""select name, html from `tabPrint Format`
- where standard = 'No' and html like '%%purchase\\_tax\\_details%%'"""):
- html = re.sub(r"\bpurchase_tax_details\b", "taxes", html)
- frappe.db.set_value("Print Format", name, "html", html)
diff --git a/erpnext/patches/v4_0/update_tax_amount_after_discount.py b/erpnext/patches/v4_0/update_tax_amount_after_discount.py
deleted file mode 100644
index d10329ef37..0000000000
--- a/erpnext/patches/v4_0/update_tax_amount_after_discount.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "sales_taxes_and_charges")
- docs_with_discount_amount = frappe._dict()
- for dt in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
- records = frappe.db.sql_list("""select name from `tab%s`
- where ifnull(discount_amount, 0) > 0 and docstatus=1""" % dt)
- docs_with_discount_amount[dt] = records
-
- for dt, discounted_records in docs_with_discount_amount.items():
- frappe.db.sql("""update `tabSales Taxes and Charges`
- set tax_amount_after_discount_amount = tax_amount
- where parenttype = %s and parent not in (%s)""" %
- ('%s', ', '.join(['%s']*(len(discounted_records)+1))),
- tuple([dt, ''] + discounted_records))
diff --git a/erpnext/patches/v4_0/update_user_properties.py b/erpnext/patches/v4_0/update_user_properties.py
deleted file mode 100644
index f2085ce4df..0000000000
--- a/erpnext/patches/v4_0/update_user_properties.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-import frappe.defaults
-
-def execute():
- frappe.reload_doc("core", "doctype", "docfield")
- frappe.reload_doc("hr", "doctype", "employee")
-
- set_print_email_permissions()
- migrate_user_properties_to_user_permissions()
-
- frappe.clear_cache()
-
-def migrate_user_properties_to_user_permissions():
- for d in frappe.db.sql("""select parent, defkey, defvalue from tabDefaultValue
- where parent not in ('__global', '__default')""", as_dict=True):
- df = frappe.db.sql("""select options from tabDocField
- where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True)
-
- if df:
- frappe.db.sql("""update tabDefaultValue
- set defkey=%s, parenttype='User Permission'
- where defkey=%s and
- parent not in ('__global', '__default')""", (df[0].options, d.defkey))
-
-def set_print_email_permissions():
- # reset Page perms
- from frappe.core.page.permission_manager.permission_manager import reset
- reset("Page")
- reset("Report")
-
- if "allow_print" not in frappe.db.get_table_columns("DocType"):
- return
-
- # patch to move print, email into DocPerm
- # NOTE: allow_print and allow_email are misnamed. They were used to hide print / hide email
- for doctype, hide_print, hide_email in frappe.db.sql("""select name, ifnull(allow_print, 0), ifnull(allow_email, 0)
- from `tabDocType` where ifnull(issingle, 0)=0 and ifnull(istable, 0)=0 and
- (ifnull(allow_print, 0)=0 or ifnull(allow_email, 0)=0)"""):
-
- if not hide_print:
- frappe.db.sql("""update `tabDocPerm` set `print`=1
- where permlevel=0 and `read`=1 and parent=%s""", doctype)
-
- if not hide_email:
- frappe.db.sql("""update `tabDocPerm` set `email`=1
- where permlevel=0 and `read`=1 and parent=%s""", doctype)
diff --git a/erpnext/patches/v4_0/update_users_report_view_settings.py b/erpnext/patches/v4_0/update_users_report_view_settings.py
deleted file mode 100644
index 6f216f5b38..0000000000
--- a/erpnext/patches/v4_0/update_users_report_view_settings.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-from frappe.model.utils.rename_field import update_users_report_view_settings
-from erpnext.patches.v4_0.fields_to_be_renamed import rename_map
-
-def execute():
- for dt, field_list in rename_map.items():
- for field in field_list:
- update_users_report_view_settings(dt, field[0], field[1])
diff --git a/erpnext/patches/v4_0/validate_v3_patch.py b/erpnext/patches/v4_0/validate_v3_patch.py
deleted file mode 100644
index 3df39edea6..0000000000
--- a/erpnext/patches/v4_0/validate_v3_patch.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from frappe.modules.patch_handler import executed
- last_v3_patch = 'patches.1401.fix_pos_outstanding'
- if not executed(last_v3_patch):
- raise Exception("site not ready to migrate to version 4")
diff --git a/erpnext/patches/v4_1/__init__.py b/erpnext/patches/v4_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_1/fix_delivery_and_billing_status.py b/erpnext/patches/v4_1/fix_delivery_and_billing_status.py
deleted file mode 100644
index 8cc6a4b0be..0000000000
--- a/erpnext/patches/v4_1/fix_delivery_and_billing_status.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabSales Order` set delivery_status = 'Not Delivered'
- where delivery_status = 'Delivered' and ifnull(per_delivered, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""")
-
- frappe.db.sql("""update `tabSales Order` set billing_status = 'Not Billed'
- where billing_status = 'Billed' and ifnull(per_billed, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""")
diff --git a/erpnext/patches/v4_1/fix_jv_remarks.py b/erpnext/patches/v4_1/fix_jv_remarks.py
deleted file mode 100644
index e07bf05f1a..0000000000
--- a/erpnext/patches/v4_1/fix_jv_remarks.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- reference_date = guess_reference_date()
- for name in frappe.db.sql_list("""select name from `tabJournal Entry`
- where date(creation)>=%s""", reference_date):
- jv = frappe.get_doc("Journal Entry", name)
- try:
- jv.create_remarks()
- except frappe.MandatoryError:
- pass
- else:
- frappe.db.set_value("Journal Entry", jv.name, "remark", jv.remark)
-
-def guess_reference_date():
- return (frappe.db.get_value("Patch Log", {"patch": "erpnext.patches.v4_0.validate_v3_patch"}, "creation")
- or "2014-05-06")
diff --git a/erpnext/patches/v4_1/fix_sales_order_delivered_status.py b/erpnext/patches/v4_1/fix_sales_order_delivered_status.py
deleted file mode 100644
index 66037b8958..0000000000
--- a/erpnext/patches/v4_1/fix_sales_order_delivered_status.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for si in frappe.db.sql_list("""select name
- from `tabSales Invoice`
- where ifnull(update_stock,0) = 1 and docstatus = 1 and exists(
- select name from `tabSales Invoice Item` where parent=`tabSales Invoice`.name and
- ifnull(so_detail, "") != "")"""):
-
- invoice = frappe.get_doc("Sales Invoice", si)
- invoice.update_qty()
diff --git a/erpnext/patches/v4_1/set_outgoing_email_footer.py b/erpnext/patches/v4_1/set_outgoing_email_footer.py
deleted file mode 100644
index 54d016bf5f..0000000000
--- a/erpnext/patches/v4_1/set_outgoing_email_footer.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.setup.install import default_mail_footer
-
-def execute():
- return
- mail_footer = frappe.db.get_default('mail_footer') or ''
- mail_footer += default_mail_footer
- frappe.db.set_value("Outgoing Email Settings", "Outgoing Email Settings", "footer", mail_footer)
diff --git a/erpnext/patches/v4_2/__init__.py b/erpnext/patches/v4_2/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_2/add_currency_turkish_lira.py b/erpnext/patches/v4_2/add_currency_turkish_lira.py
deleted file mode 100644
index 1a46089f94..0000000000
--- a/erpnext/patches/v4_2/add_currency_turkish_lira.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- return
- # country = get_country_info(country="Turkey")
- # add_country_and_currency("Turkey", country)
diff --git a/erpnext/patches/v4_2/default_website_style.py b/erpnext/patches/v4_2/default_website_style.py
deleted file mode 100644
index e8f9502ea6..0000000000
--- a/erpnext/patches/v4_2/default_website_style.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- return
- # frappe.reload_doc('website', 'doctype', 'style_settings')
- # style_settings = frappe.get_doc("Style Settings", "Style Settings")
- # if not style_settings.apply_style:
- # style_settings.update(default_properties)
- # style_settings.apply_style = 1
- # style_settings.save()
diff --git a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py b/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
deleted file mode 100644
index 169b1e2927..0000000000
--- a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice`
- where docstatus = 2 and ifnull(update_stock, 0) = 1""")
-
- if cancelled_invoices:
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
- % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/delete_old_print_formats.py b/erpnext/patches/v4_2/delete_old_print_formats.py
deleted file mode 100644
index cacdb85ce0..0000000000
--- a/erpnext/patches/v4_2/delete_old_print_formats.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- old_formats = ("Sales Invoice", "Sales Invoice Spartan", "Sales Invoice Modern",
- "Sales Invoice Classic",
- "Sales Order Spartan", "Sales Order Modern", "Sales Order Classic",
- "Purchase Order Spartan", "Purchase Order Modern", "Purchase Order Classic",
- "Quotation Spartan", "Quotation Modern", "Quotation Classic",
- "Delivery Note Spartan", "Delivery Note Modern", "Delivery Note Classic")
-
- for fmt in old_formats:
- # update property setter
- for ps in frappe.db.sql_list("""select name from `tabProperty Setter`
- where property='default_print_format' and value=%s""", fmt):
- ps = frappe.get_doc("Property Setter", ps)
- ps.value = "Standard"
- ps.save(ignore_permissions = True)
-
- frappe.delete_doc_if_exists("Print Format", fmt)
diff --git a/erpnext/patches/v4_2/discount_amount.py b/erpnext/patches/v4_2/discount_amount.py
deleted file mode 100644
index 7ab61bdbea..0000000000
--- a/erpnext/patches/v4_2/discount_amount.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.modules import scrub, get_doctype_module
-
-def execute():
- for dt in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
- frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt))
- frappe.db.sql("""update `tab{0}` set base_discount_amount=discount_amount,
- discount_amount=discount_amount/conversion_rate""".format(dt))
diff --git a/erpnext/patches/v4_2/fix_account_master_type.py b/erpnext/patches/v4_2/fix_account_master_type.py
deleted file mode 100644
index 99444ce83b..0000000000
--- a/erpnext/patches/v4_2/fix_account_master_type.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.db.sql("""select name from `tabAccount`
- where ifnull(master_type, '') not in ('Customer', 'Supplier', 'Employee', '') and docstatus=0"""):
- ac = frappe.get_doc("Account", d[0])
- ac.master_type = None
- ac.save()
diff --git a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py b/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
deleted file mode 100644
index c6c94d4179..0000000000
--- a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- from erpnext.stock.stock_balance import repost
- repost(allow_zero_rate=True, only_actual=True)
-
- frappe.reload_doctype("Account")
-
- warehouse_account = frappe.db.sql("""select name, master_name from tabAccount
- where ifnull(account_type, '') = 'Warehouse'""")
- if warehouse_account:
- warehouses = [d[1] for d in warehouse_account]
- accounts = [d[0] for d in warehouse_account]
-
- stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
- from `tabStock Ledger Entry` sle
- where sle.warehouse in (%s)
- order by sle.posting_date""" %
- ', '.join(['%s']*len(warehouses)), tuple(warehouses))
-
- rejected = []
- for voucher_type, voucher_no in stock_vouchers:
- stock_bal = frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry`
- where voucher_type=%s and voucher_no =%s and warehouse in (%s)""" %
- ('%s', '%s', ', '.join(['%s']*len(warehouses))), tuple([voucher_type, voucher_no] + warehouses))
-
- account_bal = frappe.db.sql("""select ifnull(sum(ifnull(debit, 0) - ifnull(credit, 0)), 0)
- from `tabGL Entry`
- where voucher_type=%s and voucher_no =%s and account in (%s)
- group by voucher_type, voucher_no""" %
- ('%s', '%s', ', '.join(['%s']*len(accounts))), tuple([voucher_type, voucher_no] + accounts))
-
- if stock_bal and account_bal and abs(flt(stock_bal[0][0]) - flt(account_bal[0][0])) > 0.1:
- try:
- print(voucher_type, voucher_no, stock_bal[0][0], account_bal[0][0])
-
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
-
- voucher = frappe.get_doc(voucher_type, voucher_no)
- voucher.make_gl_entries()
- frappe.db.commit()
- except Exception as e:
- print(frappe.get_traceback())
- rejected.append([voucher_type, voucher_no])
- frappe.db.rollback()
-
- print("Failed to repost: ")
- print(rejected)
diff --git a/erpnext/patches/v4_2/fix_recurring_orders.py b/erpnext/patches/v4_2/fix_recurring_orders.py
deleted file mode 100644
index ea1724a040..0000000000
--- a/erpnext/patches/v4_2/fix_recurring_orders.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- sales_orders = frappe.db.sql("""select name from `tabSales Order`
- where docstatus = 1 and ifnull(is_recurring, 0) = 1
- and (per_delivered > 0 or per_billed > 0)""", as_dict=1)
-
- for so in sales_orders:
- if not frappe.db.exists("Delivery Note Item", {"against_sales_order": so.name, "docstatus": 1}):
- frappe.db.sql("""update `tabSales Order` set per_delivered = 0,
- delivery_status = 'Not Delivered' where name = %s""", so.name)
- frappe.db.sql("""update `tabSales Order Item` set delivered_qty = 0
- where parent = %s""", so.name)
-
- if not frappe.db.exists("Sales Invoice Item", {"sales_order": so.name, "docstatus": 1}):
- frappe.db.sql("""update `tabSales Order` set per_billed = 0,
- billing_status = 'Not Billed' where name = %s""", so.name)
- frappe.db.sql("""update `tabSales Order Item` set billed_amt = 0
- where parent = %s""", so.name)
-
- purchase_orders = frappe.db.sql("""select name from `tabPurchase Order`
- where docstatus = 1 and ifnull(is_recurring, 0) = 1
- and (per_received > 0 or per_billed > 0)""", as_dict=1)
-
- for po in purchase_orders:
- if not frappe.db.exists("Purchase Receipt Item", {"prevdoc_doctype": "Purchase Order",
- "prevdoc_docname": po.name, "docstatus": 1}):
- frappe.db.sql("""update `tabPurchase Order` set per_received = 0
- where name = %s""", po.name)
- frappe.db.sql("""update `tabPurchase Order Item` set received_qty = 0
- where parent = %s""", po.name)
-
- if not frappe.db.exists("Purchase Invoice Item", {"purchase_order": po.name, "docstatus": 1}):
- frappe.db.sql("""update `tabPurchase Order` set per_billed = 0
- where name = %s""", po.name)
- frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0
- where parent = %s""", po.name)
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/party_model.py b/erpnext/patches/v4_2/party_model.py
deleted file mode 100644
index 46d7fffee1..0000000000
--- a/erpnext/patches/v4_2/party_model.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
- frappe.reload_doc("setup", "doctype", "company")
- frappe.reload_doc("accounts", "doctype", "gl_entry")
- frappe.reload_doc("accounts", "doctype", "journal_entry_account")
- receivable_payable_accounts = create_receivable_payable_account()
- if receivable_payable_accounts:
- set_party_in_jv_and_gl_entry(receivable_payable_accounts)
- delete_individual_party_account()
- remove_customer_supplier_account_report()
-
-def create_receivable_payable_account():
- receivable_payable_accounts = frappe._dict()
-
- def _create_account(args):
- if args["parent_account"] and frappe.db.exists("Account", args["parent_account"]):
- account_id = frappe.db.get_value("Account",
- {"account_name": args["account_name"], "company": args["company"]})
- if not account_id:
- account = frappe.new_doc("Account")
- account.is_group = 0
- account.update(args)
- account.insert()
-
- account_id = account.name
-
- frappe.db.set_value("Company", args["company"], ("default_receivable_account"
- if args["account_type"]=="Receivable" else "default_payable_account"), account_id)
-
- receivable_payable_accounts.setdefault(args["company"], {}).setdefault(args["account_type"], account_id)
-
- for company in frappe.db.sql_list("select name from tabCompany"):
- _create_account({
- "account_name": "Debtors",
- "account_type": "Receivable",
- "company": company,
- "parent_account": get_parent_account(company, "Customer")
- })
-
- _create_account({
- "account_name": "Creditors",
- "account_type": "Payable",
- "company": company,
- "parent_account": get_parent_account(company, "Supplier")
- })
-
- return receivable_payable_accounts
-
-def get_parent_account(company, master_type):
- parent_account = None
-
- if "receivables_group" in frappe.db.get_table_columns("Company"):
- parent_account = frappe.get_cached_value('Company', company,
- "receivables_group" if master_type=="Customer" else "payables_group")
- if not parent_account:
- parent_account = frappe.db.get_value("Account", {"company": company,
- "account_name": "Accounts Receivable" if master_type=="Customer" else "Accounts Payable"})
-
- if not parent_account:
- parent_account = frappe.db.sql_list("""select parent_account from tabAccount
- where company=%s and ifnull(master_type, '')=%s and ifnull(master_name, '')!='' limit 1""",
- (company, master_type))
- parent_account = parent_account[0][0] if parent_account else None
-
- return parent_account
-
-def set_party_in_jv_and_gl_entry(receivable_payable_accounts):
- accounts = frappe.db.sql("""select name, master_type, master_name, company from `tabAccount`
- where ifnull(master_type, '') in ('Customer', 'Supplier') and ifnull(master_name, '') != ''""", as_dict=1)
-
- account_map = frappe._dict()
- for d in accounts:
- account_map.setdefault(d.name, d)
-
- if not account_map:
- return
-
- for dt in ["Journal Entry Account", "GL Entry"]:
- records = frappe.db.sql("""select name, account from `tab%s`
- where account in (%s) and ifnull(party, '') = '' and docstatus < 2""" %
- (dt, ", ".join(['%s']*len(account_map))), tuple(account_map.keys()), as_dict=1)
- for i, d in enumerate(records):
- account_details = account_map.get(d.account, {})
- account_type = "Receivable" if account_details.get("master_type")=="Customer" else "Payable"
- new_account = receivable_payable_accounts[account_details.get("company")][account_type]
-
- frappe.db.sql("update `tab{0}` set account=%s, party_type=%s, party=%s where name=%s".format(dt),
- (new_account, account_details.get("master_type"), account_details.get("master_name"), d.name))
-
- if i%500 == 0:
- frappe.db.commit()
-
-def delete_individual_party_account():
- frappe.db.sql("""delete from `tabAccount`
- where ifnull(master_type, '') in ('Customer', 'Supplier')
- and ifnull(master_name, '') != ''
- and not exists(select gle.name from `tabGL Entry` gle
- where gle.account = tabAccount.name)""")
-
- accounts_not_deleted = frappe.db.sql_list("""select tabAccount.name from `tabAccount`
- where ifnull(master_type, '') in ('Customer', 'Supplier')
- and ifnull(master_name, '') != ''
- and exists(select gle.name from `tabGL Entry` gle where gle.account = tabAccount.name)""")
-
- if accounts_not_deleted:
- print("Accounts not deleted: " + "\n".join(accounts_not_deleted))
-
-
-def remove_customer_supplier_account_report():
- for d in ["Customer Account Head", "Supplier Account Head"]:
- frappe.delete_doc("Report", d)
diff --git a/erpnext/patches/v4_2/recalculate_bom_cost.py b/erpnext/patches/v4_2/recalculate_bom_cost.py
deleted file mode 100644
index eee89fce96..0000000000
--- a/erpnext/patches/v4_2/recalculate_bom_cost.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.db.sql("select name from `tabBOM` where docstatus < 2"):
- try:
- document = frappe.get_doc('BOM', d[0])
- if document.docstatus == 1:
- document.flags.ignore_validate_update_after_submit = True
- document.calculate_cost()
- document.save()
- except:
- pass
diff --git a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py b/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
deleted file mode 100644
index 1356129dc0..0000000000
--- a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from erpnext.stock.stock_ledger import NegativeStockError
-
-def execute():
- si_list = frappe.db.sql("""select distinct si.name
- from `tabSales Invoice Item` si_item, `tabSales Invoice` si
- where si.name = si_item.parent and si.modified > '2015-02-16' and si.docstatus=1
- and ifnull(si_item.warehouse, '') = '' and ifnull(si.update_stock, 0) = 1
- order by posting_date, posting_time""", as_dict=1)
-
- failed_list = []
- for si in si_list:
- try:
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- si_doc.docstatus = 2
- si_doc.on_cancel()
-
- si_doc.docstatus = 1
- si_doc.set_missing_item_details()
- si_doc.on_submit()
- frappe.db.commit()
- except:
- failed_list.append(si.name)
- frappe.local.stockledger_exceptions = None
- frappe.db.rollback()
-
- print("Failed to repost: ", failed_list)
-
-
-
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/repost_stock_reconciliation.py b/erpnext/patches/v4_2/repost_stock_reconciliation.py
deleted file mode 100644
index ad20ebbae4..0000000000
--- a/erpnext/patches/v4_2/repost_stock_reconciliation.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import json
-
-def execute():
- existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
- frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
-
- head_row = ["Item Code", "Warehouse", "Quantity", "Valuation Rate"]
- stock_reco_to_be_reposted = []
- for d in frappe.db.sql("""select name, reconciliation_json from `tabStock Reconciliation`
- where docstatus=1 and creation > '2014-03-01'""", as_dict=1):
- data = json.loads(d.reconciliation_json)
- for row in data[data.index(head_row)+1:]:
- if row[3] in ["", None]:
- stock_reco_to_be_reposted.append(d.name)
- break
-
- for dn in stock_reco_to_be_reposted:
- reco = frappe.get_doc("Stock Reconciliation", dn)
- reco.docstatus = 2
- reco.on_cancel()
-
- reco.docstatus = 1
- reco.validate()
- reco.on_submit()
-
- frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
diff --git a/erpnext/patches/v4_2/reset_bom_costs.py b/erpnext/patches/v4_2/reset_bom_costs.py
deleted file mode 100644
index 42ca759467..0000000000
--- a/erpnext/patches/v4_2/reset_bom_costs.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('manufacturing', 'doctype', 'bom_operation')
- for d in frappe.db.sql("""select name from `tabBOM` where docstatus < 2""", as_dict=1):
- try:
- bom = frappe.get_doc('BOM', d.name)
- bom.flags.ignore_validate_update_after_submit = True
- bom.calculate_cost()
- bom.save()
- frappe.db.commit()
- except:
- frappe.db.rollback()
diff --git a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py b/erpnext/patches/v4_2/seprate_manufacture_and_repack.py
deleted file mode 100644
index 2c935436a2..0000000000
--- a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabStock Entry` set purpose='Manufacture' where purpose='Manufacture/Repack' and ifnull(work_order,"")!="" """)
- frappe.db.sql("""update `tabStock Entry` set purpose='Repack' where purpose='Manufacture/Repack' and ifnull(work_order,"")="" """)
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/set_company_country.py b/erpnext/patches/v4_2/set_company_country.py
deleted file mode 100644
index 89f07f2873..0000000000
--- a/erpnext/patches/v4_2/set_company_country.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- country = frappe.db.get_single_value("Global Defaults", "country")
- if not country:
- print("Country not specified in Global Defaults")
- return
-
- for company in frappe.db.sql_list("""select name from `tabCompany`
- where ifnull(country, '')=''"""):
- frappe.db.set_value("Company", company, "country", country)
diff --git a/erpnext/patches/v4_2/set_item_has_batch.py b/erpnext/patches/v4_2/set_item_has_batch.py
deleted file mode 100644
index 7e52d2def0..0000000000
--- a/erpnext/patches/v4_2/set_item_has_batch.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("update tabItem set has_batch_no = 0 where ifnull(has_batch_no, '') = ''")
- frappe.db.sql("update tabItem set has_serial_no = 0 where ifnull(has_serial_no, '') = ''")
-
- item_list = frappe.db.sql("""select name, has_batch_no, has_serial_no from tabItem
- where is_stock_item = 1""", as_dict=1)
-
- sle_count = get_sle_count()
- sle_with_batch = get_sle_with_batch()
- sle_with_serial = get_sle_with_serial()
-
- batch_items = get_items_with_batch()
- serialized_items = get_items_with_serial()
-
- for d in item_list:
- if d.has_batch_no == 1:
- if d.name not in batch_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_batch.get(d.name):
- frappe.db.set_value("Item", d.name, "has_batch_no", 0)
- else:
- if d.name in batch_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_batch.get(d.name)):
- frappe.db.set_value("Item", d.name, "has_batch_no", 1)
-
- if d.has_serial_no == 1:
- if d.name not in serialized_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_serial.get(d.name):
- frappe.db.set_value("Item", d.name, "has_serial_no", 0)
- else:
- if d.name in serialized_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_serial.get(d.name)):
- frappe.db.set_value("Item", d.name, "has_serial_no", 1)
-
-
-def get_sle_count():
- sle_count = {}
- for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` group by item_code""", as_dict=1):
- sle_count.setdefault(d.item_code, d.cnt)
-
- return sle_count
-
-def get_sle_with_batch():
- sle_with_batch = {}
- for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
- where ifnull(batch_no, '') != '' group by item_code""", as_dict=1):
- sle_with_batch.setdefault(d.item_code, d.cnt)
-
- return sle_with_batch
-
-
-def get_sle_with_serial():
- sle_with_serial = {}
- for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
- where ifnull(serial_no, '') != '' group by item_code""", as_dict=1):
- sle_with_serial.setdefault(d.item_code, d.cnt)
-
- return sle_with_serial
-
-def get_items_with_batch():
- return frappe.db.sql_list("select item from tabBatch")
-
-def get_items_with_serial():
- return frappe.db.sql_list("select item_code from `tabSerial No`")
diff --git a/erpnext/patches/v4_2/toggle_rounded_total.py b/erpnext/patches/v4_2/toggle_rounded_total.py
deleted file mode 100644
index e571208eb6..0000000000
--- a/erpnext/patches/v4_2/toggle_rounded_total.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
- global_defaults.toggle_rounded_total()
diff --git a/erpnext/patches/v4_2/update_landed_cost_voucher.py b/erpnext/patches/v4_2/update_landed_cost_voucher.py
deleted file mode 100644
index ec0029671e..0000000000
--- a/erpnext/patches/v4_2/update_landed_cost_voucher.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "landed_cost_voucher")
- frappe.db.sql("""update `tabLanded Cost Voucher` set distribute_charges_based_on = 'Amount'
- where docstatus=1""")
diff --git a/erpnext/patches/v4_2/update_project_milestones.py b/erpnext/patches/v4_2/update_project_milestones.py
deleted file mode 100644
index e704116d05..0000000000
--- a/erpnext/patches/v4_2/update_project_milestones.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for project in frappe.db.sql_list("select name from tabProject"):
- frappe.reload_doc("projects", "doctype", "project")
- p = frappe.get_doc("Project", project)
- p.update_milestones_completed()
- p.db_set("percent_milestones_completed", p.percent_milestones_completed)
diff --git a/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py b/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py
deleted file mode 100644
index 28dd5c0d4e..0000000000
--- a/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.db.sql("""update `tabSales Invoice` set from_date = invoice_period_from_date,
- to_date = invoice_period_to_date, is_recurring = convert_into_recurring_invoice""")
diff --git a/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py b/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py
deleted file mode 100644
index 89bf795534..0000000000
--- a/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabStock Ledger Entry` sle, tabItem item
- set sle.stock_uom = item.stock_uom
- where sle.voucher_type="Delivery Note" and item.name = sle.item_code
- and sle.stock_uom != item.stock_uom""")
diff --git a/erpnext/patches/v4_4/__init__.py b/erpnext/patches/v4_4/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_4/make_email_accounts.py b/erpnext/patches/v4_4/make_email_accounts.py
deleted file mode 100644
index 57df1ae491..0000000000
--- a/erpnext/patches/v4_4/make_email_accounts.py
+++ /dev/null
@@ -1,96 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model import default_fields
-
-from six import iteritems
-
-def execute():
- frappe.reload_doc("email", "doctype", "email_account")
-
- # outgoing
- outgoing = dict(frappe.db.sql("select field, value from tabSingles where doctype='Outgoing Email Settings'"))
- if outgoing and outgoing['mail_server'] and outgoing['mail_login']:
- account = frappe.new_doc("Email Account")
- mapping = {
- "login_id_is_different": 1,
- "email_id": "auto_email_id",
- "login_id": "mail_login",
- "password": "mail_password",
- "footer": "footer",
- "smtp_server": "mail_server",
- "smtp_port": "mail_port",
- "use_tls": "use_ssl"
- }
-
- for target_fieldname, source_fieldname in iteritems(mapping):
- account.set(target_fieldname, outgoing.get(source_fieldname))
-
- account.enable_outgoing = 1
- account.enable_incoming = 0
-
- account.insert()
-
- # support
- support = dict(frappe.db.sql("select field, value from tabSingles where doctype='Support Email Settings'"))
- if support and support['mail_server'] and support['mail_login']:
- account = frappe.new_doc("Email Account")
- mapping = {
- "enable_incoming": "sync_support_mails",
- "email_id": "mail_login",
- "password": "mail_password",
- "email_server": "mail_server",
- "use_ssl": "use_ssl",
- "signature": "support_signature",
- "enable_auto_reply": "send_autoreply",
- "auto_reply_message": "support_autoreply"
- }
-
- for target_fieldname, source_fieldname in iteritems(mapping):
- account.set(target_fieldname, support.get(source_fieldname))
-
- account.enable_outgoing = 0
- account.append_to = "Issue"
-
- insert_or_update(account)
-
- # sales, jobs
- for doctype in ("Sales Email Settings", "Jobs Email Settings"):
- source = dict(frappe.db.sql("select field, value from tabSingles where doctype=%s", doctype))
- if source and source.get('host') and source.get('username'):
- account = frappe.new_doc("Email Account")
- mapping = {
- "enable_incoming": "extract_emails",
- "email_id": "username",
- "password": "password",
- "email_server": "host",
- "use_ssl": "use_ssl",
- }
-
- for target_fieldname, source_fieldname in iteritems(mapping):
- account.set(target_fieldname, source.get(source_fieldname))
-
- account.enable_outgoing = 0
- account.append_to = "Lead" if doctype=="Sales Email Settings" else "Job Applicant"
-
- insert_or_update(account)
-
- for doctype in ("Outgoing Email Settings", "Support Email Settings",
- "Sales Email Settings", "Jobs Email Settings"):
- frappe.delete_doc("DocType", doctype)
-
-def insert_or_update(account):
- try:
- account.insert()
- except frappe.NameError as e:
- if e.args[0]=="Email Account":
- existing_account = frappe.get_doc("Email Account", e.args[1])
- for key, value in account.as_dict().items():
- if not existing_account.get(key) and value \
- and key not in default_fields \
- and key != "__islocal":
- existing_account.set(key, value)
-
- existing_account.save()
- else:
- raise
-
diff --git a/erpnext/patches/v5_0/__init__.py b/erpnext/patches/v5_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v5_0/convert_stock_reconciliation.py b/erpnext/patches/v5_0/convert_stock_reconciliation.py
deleted file mode 100644
index 75d1da752f..0000000000
--- a/erpnext/patches/v5_0/convert_stock_reconciliation.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from __future__ import unicode_literals
-import frappe, json
-
-def execute():
- # stock reco now amendable
- frappe.db.sql("""update tabDocPerm set `amend` = 1 where parent='Stock Reconciliation' and submit = 1""")
-
- frappe.reload_doc("stock", "doctype", "stock_reconciliation_item")
- frappe.reload_doctype("Stock Reconciliation")
-
- if frappe.db.has_column("Stock Reconciliation", "reconciliation_json"):
- for sr in frappe.db.get_all("Stock Reconciliation", ["name"],
- {"reconciliation_json": ["!=", ""]}):
- start = False
- sr = frappe.get_doc("Stock Reconciliation", sr.name)
- for row in json.loads(sr.reconciliation_json):
- if start:
- sr.append("items", {
- "item_code": row[0],
- "warehouse": row[1],
- "qty": row[2] if len(row) > 2 else None,
- "valuation_rate": row[3] if len(row) > 3 else None
- })
-
- elif row[0]=="Item Code":
- start = True
-
-
- for item in sr.items:
- item.db_update()
-
diff --git a/erpnext/patches/v5_0/execute_on_doctype_update.py b/erpnext/patches/v5_0/execute_on_doctype_update.py
deleted file mode 100644
index 70b1d8ded6..0000000000
--- a/erpnext/patches/v5_0/execute_on_doctype_update.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Stock Ledger Entry", "Communication", "DefaultValue", "DocShare", "File", "ToDo"):
- frappe.get_doc("DocType", dt).run_module_method("on_doctype_update")
diff --git a/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py b/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py
deleted file mode 100644
index 30dc0f8db4..0000000000
--- a/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.meta import get_field_precision
-
-def execute():
- if not frappe.db.sql("""select name from `tabPatch Log`
- where patch = 'erpnext.patches.v5_0.taxes_and_totals_in_party_currency'"""):
- return
- selling_doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]
- buying_doctypes = ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
-
- for dt in selling_doctypes:
- update_values(dt, "Sales Taxes and Charges")
-
- for dt in buying_doctypes:
- update_values(dt, "Purchase Taxes and Charges")
-
-def update_values(dt, tax_table):
- rate_field_precision = get_field_precision(frappe.get_meta(dt + " Item").get_field("rate"))
- tax_amount_precision = get_field_precision(frappe.get_meta(tax_table).get_field("tax_amount"))
-
- # update net_total, discount_on
- frappe.db.sql("""
- UPDATE
- `tab{0}`
- SET
- total_taxes_and_charges = round(base_total_taxes_and_charges / conversion_rate, {1})
- WHERE
- docstatus < 2
- and ifnull(base_total_taxes_and_charges, 0) != 0
- and ifnull(total_taxes_and_charges, 0) = 0
- """.format(dt, tax_amount_precision))
-
- # update net_amount
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` item
- SET
- item.net_amount = round(item.base_net_amount / par.conversion_rate, {2}),
- item.net_rate = round(item.base_net_rate / par.conversion_rate, {2})
- WHERE
- par.name = item.parent
- and par.docstatus < 2
- and ((ifnull(item.base_net_amount, 0) != 0 and ifnull(item.net_amount, 0) = 0)
- or (ifnull(item.base_net_rate, 0) != 0 and ifnull(item.net_rate, 0) = 0))
- """.format(dt, dt + " Item", rate_field_precision))
-
- # update tax in party currency
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` tax
- SET
- tax.tax_amount = round(tax.base_tax_amount / par.conversion_rate, {2}),
- tax.total = round(tax.base_total / conversion_rate, {2}),
- tax.tax_amount_after_discount_amount = round(tax.base_tax_amount_after_discount_amount / conversion_rate, {2})
- WHERE
- par.name = tax.parent
- and par.docstatus < 2
- and ((ifnull(tax.base_tax_amount, 0) != 0 and ifnull(tax.tax_amount, 0) = 0)
- or (ifnull(tax.base_total, 0) != 0 and ifnull(tax.total, 0) = 0)
- or (ifnull(tax.base_tax_amount_after_discount_amount, 0) != 0 and
- ifnull(tax.tax_amount_after_discount_amount, 0) = 0))
- """.format(dt, tax_table, tax_amount_precision))
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/index_on_account_and_gl_entry.py b/erpnext/patches/v5_0/index_on_account_and_gl_entry.py
deleted file mode 100644
index 2920e9293d..0000000000
--- a/erpnext/patches/v5_0/index_on_account_and_gl_entry.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- index_map = {
- "Account": ["parent_account", "lft", "rgt"],
- "GL Entry": ["posting_date", "account", 'party', "voucher_no"],
- "Sales Invoice": ["posting_date", "debit_to", "customer"],
- "Purchase Invoice": ["posting_date", "credit_to", "supplier"]
- }
-
- for dt, indexes in index_map.items():
- existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
- where Column_name != 'name'""".format(dt), as_dict=1)]
-
- for old, column in existing_indexes:
- if column in ("parent", "group_or_ledger", "is_group", "is_pl_account", "debit_or_credit",
- "account_name", "company", "project", "voucher_date", "due_date", "bill_no",
- "bill_date", "is_opening", "fiscal_year", "outstanding_amount"):
- frappe.db.sql("alter table `tab{0}` drop index {1}".format(dt, old))
-
- existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
- where Column_name != 'name'""".format(dt), as_dict=1)]
-
- existing_indexed_columns = list(set([x[1] for x in existing_indexes]))
-
- for new in indexes:
- if new not in existing_indexed_columns:
- frappe.db.sql("alter table `tab{0}` add index ({1})".format(dt, new))
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/is_group.py b/erpnext/patches/v5_0/is_group.py
deleted file mode 100644
index 4e3f760bed..0000000000
--- a/erpnext/patches/v5_0/is_group.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.reload_doctype("Account")
- frappe.reload_doctype("Cost Center")
- frappe.db.sql("update tabAccount set is_group = if(group_or_ledger='Group', 1, 0)")
- frappe.db.sql("update `tabCost Center` set is_group = if(group_or_ledger='Group', 1, 0)")
diff --git a/erpnext/patches/v5_0/item_patches.py b/erpnext/patches/v5_0/item_patches.py
deleted file mode 100644
index e223e09f5b..0000000000
--- a/erpnext/patches/v5_0/item_patches.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("update `tabItem` set end_of_life='2099-12-31' where ifnull(end_of_life, '0000-00-00')='0000-00-00'")
- frappe.db.sql("update `tabItem` set website_image = image where ifnull(website_image, '') = 'attach_files:'")
diff --git a/erpnext/patches/v5_0/link_warehouse_with_account.py b/erpnext/patches/v5_0/link_warehouse_with_account.py
deleted file mode 100644
index 338fd7ad7f..0000000000
--- a/erpnext/patches/v5_0/link_warehouse_with_account.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if "master_name" in frappe.db.get_table_columns("Account"):
- frappe.db.sql("""update tabAccount set warehouse=master_name
- where ifnull(account_type, '') = 'Warehouse' and ifnull(master_name, '') != ''""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/new_crm_module.py b/erpnext/patches/v5_0/new_crm_module.py
deleted file mode 100644
index f5dda1f273..0000000000
--- a/erpnext/patches/v5_0/new_crm_module.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import json
-import frappe
-
-def execute():
- frappe.reload_doc('crm', 'doctype', 'lead')
- frappe.reload_doc('crm', 'doctype', 'opportunity')
-
- add_crm_to_user_desktop_items()
-
-def add_crm_to_user_desktop_items():
- key = "_user_desktop_items"
- for user in frappe.get_all("User", filters={"enabled": 1, "user_type": "System User"}):
- user = user.name
- user_desktop_items = frappe.db.get_defaults(key, parent=user)
- if user_desktop_items:
- user_desktop_items = json.loads(user_desktop_items)
- if "CRM" not in user_desktop_items:
- user_desktop_items.append("CRM")
- frappe.db.set_default(key, json.dumps(user_desktop_items), parent=user)
-
diff --git a/erpnext/patches/v5_0/newsletter.py b/erpnext/patches/v5_0/newsletter.py
deleted file mode 100644
index 63e3312413..0000000000
--- a/erpnext/patches/v5_0/newsletter.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- frappe.reload_doc("core", "doctype", "block_module")
- frappe.reload_doctype("User")
- frappe.reload_doctype("Lead")
- frappe.reload_doctype("Contact")
-
- frappe.reload_doc('email', 'doctype', 'email_group')
- frappe.reload_doc('email', 'doctype', 'email_group_member')
- frappe.reload_doc('email', 'doctype', 'newsletter')
-
- frappe.permissions.reset_perms("Newsletter")
-
- if not frappe.db.exists("Role", "Newsletter Manager"):
- frappe.get_doc({"doctype": "Role", "role": "Newsletter Manager"}).insert()
-
- for userrole in frappe.get_all("Has Role", "parent", {"role": "Sales Manager", "parenttype": "User"}):
- if frappe.db.exists("User", userrole.parent):
- user = frappe.get_doc("User", userrole.parent)
- user.append("roles", {
- "doctype": "Has Role",
- "role": "Newsletter Manager"
- })
- user.flags.ignore_mandatory = True
- user.save()
-
- # create default lists
- general = frappe.new_doc("Email Group")
- general.title = "General"
- general.insert()
- general.import_from("Lead")
- general.import_from("Contact")
diff --git a/erpnext/patches/v5_0/opportunity_not_submittable.py b/erpnext/patches/v5_0/opportunity_not_submittable.py
deleted file mode 100644
index e29d66f284..0000000000
--- a/erpnext/patches/v5_0/opportunity_not_submittable.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Opportunity")
- frappe.db.sql("update tabDocPerm set submit=0, cancel=0, amend=0 where parent='Opportunity'")
- frappe.db.sql("update tabOpportunity set docstatus=0 where docstatus=1")
diff --git a/erpnext/patches/v5_0/party_model_patch_fix.py b/erpnext/patches/v5_0/party_model_patch_fix.py
deleted file mode 100644
index d9b6709792..0000000000
--- a/erpnext/patches/v5_0/party_model_patch_fix.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for company in frappe.get_all("Company",
- ["name", "default_receivable_account", "default_payable_account"]):
-
- if company.default_receivable_account:
- frappe.db.sql("""update `tabSales Invoice` invoice set `debit_to`=%(account)s
- where company=%(company)s
- and not exists (select name from `tabAccount` account where account.name=invoice.debit_to)""",
- {"company": company.name, "account": company.default_receivable_account})
-
- if company.default_payable_account:
- frappe.db.sql("""update `tabPurchase Invoice` invoice set `credit_to`=%(account)s
- where company=%(company)s
- and not exists (select name from `tabAccount` account where account.name=invoice.credit_to)""",
- {"company": company.name, "account": company.default_payable_account})
diff --git a/erpnext/patches/v5_0/portal_fixes.py b/erpnext/patches/v5_0/portal_fixes.py
deleted file mode 100644
index 1fefd99167..0000000000
--- a/erpnext/patches/v5_0/portal_fixes.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import erpnext.setup.install
-
-def execute():
- frappe.reload_doc("website", "doctype", "web_form_field", force=True, reset_permissions=True)
- #erpnext.setup.install.add_web_forms()
diff --git a/erpnext/patches/v5_0/project_costing.py b/erpnext/patches/v5_0/project_costing.py
deleted file mode 100644
index e2d65d0594..0000000000
--- a/erpnext/patches/v5_0/project_costing.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Project")
- frappe.db.sql("update `tabProject` set expected_start_date = project_start_date, \
- expected_end_date = completion_date, actual_end_date = act_completion_date, \
- estimated_costing = project_value, gross_margin = gross_margin_value")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py b/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py
deleted file mode 100644
index d5af43c541..0000000000
--- a/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import money_in_words
-
-def execute():
- company_currency = dict(frappe.db.sql("select name, default_currency from `tabCompany`"))
- bank_or_cash_accounts = frappe.db.sql_list("""select name from `tabAccount`
- where account_type in ('Bank', 'Cash') and docstatus < 2""")
-
- for je in frappe.db.sql_list("""select name from `tabJournal Entry` where docstatus < 2"""):
- total_amount = 0
- total_amount_in_words = ""
-
- je_doc = frappe.get_doc('Journal Entry', je)
- for d in je_doc.get("accounts"):
- if (d.party_type and d.party) or d.account in bank_or_cash_accounts:
- total_amount = d.debit or d.credit
- if total_amount:
- total_amount_in_words = money_in_words(total_amount, company_currency.get(je_doc.company))
-
- if total_amount:
- frappe.db.sql("""update `tabJournal Entry` set total_amount=%s, total_amount_in_words=%s
- where name = %s""", (total_amount, total_amount_in_words, je))
diff --git a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py b/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py
deleted file mode 100644
index 6d392831b4..0000000000
--- a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for wo in frappe.db.sql("""select name from `tabWork Order` where docstatus < 2""", as_dict=1):
- work_order = frappe.get_doc("Work Order", wo.name)
- if work_order.operations:
- work_order.flags.ignore_validate_update_after_submit = True
- work_order.calculate_time()
- work_order.save()
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/remove_birthday_events.py b/erpnext/patches/v5_0/remove_birthday_events.py
deleted file mode 100644
index 3ead8669b8..0000000000
--- a/erpnext/patches/v5_0/remove_birthday_events.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for e in frappe.db.sql_list("""select name from tabEvent where
- repeat_on='Every Year' and ref_type='Employee'"""):
- frappe.delete_doc("Event", e, force=True)
diff --git a/erpnext/patches/v5_0/rename_customer_issue.py b/erpnext/patches/v5_0/rename_customer_issue.py
deleted file mode 100644
index 1bd69ceec1..0000000000
--- a/erpnext/patches/v5_0/rename_customer_issue.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Customer Issue"):
- frappe.rename_doc("DocType", "Customer Issue", "Warranty Claim")
diff --git a/erpnext/patches/v5_0/rename_pos_setting.py b/erpnext/patches/v5_0/rename_pos_setting.py
deleted file mode 100644
index bf10333564..0000000000
--- a/erpnext/patches/v5_0/rename_pos_setting.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("POS Setting"):
- frappe.rename_doc("DocType", "POS Setting", "POS Profile")
diff --git a/erpnext/patches/v5_0/rename_table_fieldnames.py b/erpnext/patches/v5_0/rename_table_fieldnames.py
deleted file mode 100644
index aefb0a2037..0000000000
--- a/erpnext/patches/v5_0/rename_table_fieldnames.py
+++ /dev/null
@@ -1,243 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-from frappe.modules import scrub, get_doctype_module
-
-rename_map = {
- "Opportunity": [
- ["enquiry_details", "items"]
- ],
- "Quotation": [
- ["quotation_details", "items"],
- ["other_charges", "taxes"]
- ],
- "Sales Order": [
- ["sales_order_details", "items"],
- ["other_charges", "taxes"],
- ["packing_details", "packed_items"]
- ],
- "Delivery Note": [
- ["delivery_note_details", "items"],
- ["other_charges", "taxes"],
- ["packing_details", "packed_items"]
- ],
- "Sales Invoice": [
- ["entries", "items"],
- ["other_charges", "taxes"],
- ["packing_details", "packed_items"],
- ["advance_adjustment_details", "advances"]
- ],
- "Material Request": [
- ["indent_details", "items"]
- ],
- "Supplier Quotation": [
- ["quotation_items", "items"],
- ["other_charges", "taxes"]
- ],
- "Purchase Order": [
- ["po_details", "items"],
- ["other_charges", "taxes"],
- ["po_raw_material_details", "supplied_items"]
- ],
- "Purchase Receipt": [
- ["purchase_receipt_details", "items"],
- ["other_charges", "taxes"],
- ["pr_raw_material_details", "supplied_items"]
- ],
- "Purchase Invoice": [
- ["entries", "items"],
- ["other_charges", "taxes"],
- ["advance_allocation_details", "advances"]
- ],
- "Work Order": [
- ["production_order_operations", "operations"]
- ],
- "BOM": [
- ["bom_operations", "operations"],
- ["bom_materials", "items"],
- ["flat_bom_details", "exploded_items"]
- ],
- "Payment Reconciliation": [
- ["payment_reconciliation_payments", "payments"],
- ["payment_reconciliation_invoices", "invoices"]
- ],
- "Sales Taxes and Charges Template": [
- ["other_charges", "taxes"],
- ["valid_for_territories", "territories"]
- ],
- "Purchase Taxes and Charges Template": [
- ["other_charges", "taxes"]
- ],
- "Shipping Rule": [
- ["shipping_rule_conditions", "conditions"],
- ["valid_for_territories", "territories"]
- ],
- "Price List": [
- ["valid_for_territories", "territories"]
- ],
- "Appraisal": [
- ["appraisal_details", "goals"]
- ],
- "Appraisal Template": [
- ["kra_sheet", "goals"]
- ],
- "Bank Reconciliation": [
- ["entries", "journal_entries"]
- ],
- "C-Form": [
- ["invoice_details", "invoices"]
- ],
- "Employee": [
- ["employee_leave_approvers", "leave_approvers"],
- ["educational_qualification_details", "education"],
- ["previous_experience_details", "external_work_history"],
- ["experience_in_company_details", "internal_work_history"]
- ],
- "Expense Claim": [
- ["expense_voucher_details", "expenses"]
- ],
- "Fiscal Year": [
- ["fiscal_year_companies", "companies"]
- ],
- "Holiday List": [
- ["holiday_list_details", "holidays"]
- ],
- "Installation Note": [
- ["installed_item_details", "items"]
- ],
- "Item": [
- ["item_reorder", "reorder_levels"],
- ["uom_conversion_details", "uoms"],
- ["item_supplier_details", "supplier_items"],
- ["item_customer_details", "customer_items"],
- ["item_tax", "taxes"],
- ["item_specification_details", "quality_parameters"],
- ["item_website_specifications", "website_specifications"]
- ],
- "Item Group": [
- ["item_website_specifications", "website_specifications"]
- ],
- "Landed Cost Voucher": [
- ["landed_cost_purchase_receipts", "purchase_receipts"],
- ["landed_cost_items", "items"],
- ["landed_cost_taxes_and_charges", "taxes"]
- ],
- "Maintenance Schedule": [
- ["item_maintenance_detail", "items"],
- ["maintenance_schedule_detail", "schedules"]
- ],
- "Maintenance Visit": [
- ["maintenance_visit_details", "purposes"]
- ],
- "Packing Slip": [
- ["item_details", "items"]
- ],
- "Customer": [
- ["party_accounts", "accounts"]
- ],
- "Customer Group": [
- ["party_accounts", "accounts"]
- ],
- "Supplier": [
- ["party_accounts", "accounts"]
- ],
- "Supplier Type": [
- ["party_accounts", "accounts"]
- ],
- "Payment Tool": [
- ["payment_tool_details", "vouchers"]
- ],
- "Production Planning Tool": [
- ["pp_so_details", "sales_orders"],
- ["pp_details", "items"]
- ],
- "Quality Inspection": [
- ["qa_specification_details", "readings"]
- ],
- "Salary Slip": [
- ["earning_details", "earnings"],
- ["deduction_details", "deductions"]
- ],
- "Salary Structure": [
- ["earning_details", "earnings"],
- ["deduction_details", "deductions"]
- ],
- "Product Bundle": [
- ["sales_bom_items", "items"]
- ],
- "SMS Settings": [
- ["static_parameter_details", "parameters"]
- ],
- "Stock Entry": [
- ["mtn_details", "items"]
- ],
- "Sales Partner": [
- ["partner_target_details", "targets"]
- ],
- "Sales Person": [
- ["target_details", "targets"]
- ],
- "Territory": [
- ["target_details", "targets"]
- ],
- "Time Sheet": [
- ["time_sheet_details", "time_logs"]
- ],
- "Workstation": [
- ["workstation_operation_hours", "working_hours"]
- ],
- "Payment Reconciliation Payment": [
- ["journal_voucher", "journal_entry"],
- ],
- "Purchase Invoice Advance": [
- ["journal_voucher", "journal_entry"],
- ],
- "Sales Invoice Advance": [
- ["journal_voucher", "journal_entry"],
- ],
- "Journal Entry": [
- ["entries", "accounts"]
- ],
- "Monthly Distribution": [
- ["budget_distribution_details", "percentages"]
- ]
-}
-
-def execute():
- # rename doctypes
- tables = frappe.db.sql_list("show tables")
- for old_dt, new_dt in [["Journal Voucher Detail", "Journal Entry Account"],
- ["Journal Voucher", "Journal Entry"],
- ["Budget Distribution Detail", "Monthly Distribution Percentage"],
- ["Budget Distribution", "Monthly Distribution"]]:
- if "tab"+new_dt not in tables:
- frappe.rename_doc("DocType", old_dt, new_dt, force=True)
-
- # reload new child doctypes
- frappe.reload_doc("manufacturing", "doctype", "work_order_operation")
- frappe.reload_doc("manufacturing", "doctype", "workstation_working_hour")
- frappe.reload_doc("stock", "doctype", "item_variant")
- frappe.reload_doc("Payroll", "doctype", "salary_detail")
- frappe.reload_doc("accounts", "doctype", "party_account")
- frappe.reload_doc("accounts", "doctype", "fiscal_year_company")
-
- #rename table fieldnames
- for dn in rename_map:
- if not frappe.db.exists("DocType", dn):
- continue
- frappe.reload_doc(get_doctype_module(dn), "doctype", scrub(dn))
-
- for dt, field_list in rename_map.items():
- if not frappe.db.exists("DocType", dt):
- continue
- for field in field_list:
- rename_field(dt, field[0], field[1])
-
- # update voucher type
- for old, new in [["Bank Voucher", "Bank Entry"], ["Cash Voucher", "Cash Entry"],
- ["Credit Card Voucher", "Credit Card Entry"], ["Contra Voucher", "Contra Entry"],
- ["Write Off Voucher", "Write Off Entry"], ["Excise Voucher", "Excise Entry"]]:
- frappe.db.sql("update `tabJournal Entry` set voucher_type=%s where voucher_type=%s", (new, old))
diff --git a/erpnext/patches/v5_0/rename_taxes_and_charges_master.py b/erpnext/patches/v5_0/rename_taxes_and_charges_master.py
deleted file mode 100644
index e26f48cda1..0000000000
--- a/erpnext/patches/v5_0/rename_taxes_and_charges_master.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- if frappe.db.table_exists("Sales Taxes and Charges Master"):
- frappe.rename_doc("DocType", "Sales Taxes and Charges Master",
- "Sales Taxes and Charges Template")
- frappe.delete_doc("DocType", "Sales Taxes and Charges Master")
-
- if frappe.db.table_exists("Purchase Taxes and Charges Master"):
- frappe.rename_doc("DocType", "Purchase Taxes and Charges Master",
- "Purchase Taxes and Charges Template")
- frappe.delete_doc("DocType", "Purchase Taxes and Charges Master")
diff --git a/erpnext/patches/v5_0/rename_total_fields.py b/erpnext/patches/v5_0/rename_total_fields.py
deleted file mode 100644
index 6657dd843e..0000000000
--- a/erpnext/patches/v5_0/rename_total_fields.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-from frappe.modules import scrub, get_doctype_module
-
-selling_doctypes = ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice")
-
-buying_doctypes = ("Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice")
-
-selling_renamed_fields = (
- ("net_total", "base_net_total"),
- ("net_total_export", "net_total"),
- ("other_charges_total", "base_total_taxes_and_charges"),
- ("other_charges_total_export", "total_taxes_and_charges"),
- ("grand_total", "base_grand_total"),
- ("grand_total_export", "grand_total"),
- ("rounded_total", "base_rounded_total"),
- ("rounded_total_export", "rounded_total"),
- ("in_words", "base_in_words"),
- ("in_words_export", "in_words")
-)
-
-buying_renamed_fields = (
- ("net_total", "base_net_total"),
- ("net_total_import", "net_total"),
- ("grand_total", "base_grand_total"),
- ("grand_total_import", "grand_total"),
- ("rounded_total", "base_rounded_total"),
- ("in_words", "base_in_words"),
- ("in_words_import", "in_words"),
- ("other_charges_added", "base_taxes_and_charges_added"),
- ("other_charges_added_import", "taxes_and_charges_added"),
- ("other_charges_deducted", "base_taxes_and_charges_deducted"),
- ("other_charges_deducted_import", "taxes_and_charges_deducted"),
- ("total_tax", "base_total_taxes_and_charges")
-)
-
-def execute():
- for doctypes, fields in [[selling_doctypes, selling_renamed_fields], [buying_doctypes, buying_renamed_fields]]:
- for dt in doctypes:
- frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt))
- table_columns = frappe.db.get_table_columns(dt)
- base_net_total = frappe.db.sql("select sum(ifnull({0}, 0)) from `tab{1}`".format(fields[0][1], dt))[0][0]
- if not base_net_total:
- for f in fields:
- if f[0] in table_columns:
- rename_field(dt, f[0], f[1])
-
- # Added new field "total_taxes_and_charges" in buying cycle, updating value
- if dt in ("Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"):
- frappe.db.sql("""update `tab{0}` set total_taxes_and_charges =
- round(base_total_taxes_and_charges/conversion_rate, 2)""".format(dt))
diff --git a/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py b/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py
deleted file mode 100644
index c564f8b02a..0000000000
--- a/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import re
-
-def execute():
- # NOTE: sequence is important
- renamed_fields = get_all_renamed_fields()
-
- for dt, script_field, ref_dt_field in (("Client Script", "script", "dt"), ("Print Format", "html", "doc_type")):
-
- cond1 = " or ".join("""{0} like "%%{1}%%" """.format(script_field, d[0].replace("_", "\\_")) for d in renamed_fields)
- cond2 = " and standard = 'No'" if dt == "Print Format" else ""
-
- for name, script, ref_dt in frappe.db.sql("select name, {0} as script, {1} as ref_dt from `tab{2}` where ({3}) {4}".format(script_field, ref_dt_field, dt, cond1, cond2)):
- update_script(dt, name, ref_dt, script_field, script, renamed_fields)
-
-def get_all_renamed_fields():
- from erpnext.patches.v5_0.rename_table_fieldnames import rename_map
-
- renamed_fields = (
- ("base_amount", "base_net_amount"),
- ("net_total", "base_net_total"),
- ("net_total_export", "total"),
- ("net_total_import", "total"),
- ("other_charges_total", "base_total_taxes_and_charges"),
- ("other_charges_total_export", "total_taxes_and_charges"),
- ("other_charges_added", "base_taxes_and_charges_added"),
- ("other_charges_added_import", "taxes_and_charges_added"),
- ("other_charges_deducted", "base_taxes_and_charges_deducted"),
- ("other_charges_deducted_import", "taxes_and_charges_deducted"),
- ("total_tax", "base_total_taxes_and_charges"),
- ("grand_total", "base_grand_total"),
- ("grand_total_export", "grand_total"),
- ("grand_total_import", "grand_total"),
- ("rounded_total", "base_rounded_total"),
- ("rounded_total_export", "rounded_total"),
- ("rounded_total_import", "rounded_total"),
- ("in_words", "base_in_words"),
- ("in_words_export", "in_words"),
- ("in_words_import", "in_words"),
- ("tax_amount", "base_tax_amount"),
- ("tax_amount_after_discount_amount", "base_tax_amount_after_discount_amount"),
- )
-
- for fields in rename_map.values():
- renamed_fields += tuple(fields)
-
- return renamed_fields
-
-def update_script(dt, name, ref_dt, script_field, script, renamed_fields):
- for from_field, to_field in renamed_fields:
- if from_field != "entries":
- script = re.sub(r"\b{}\b".format(from_field), to_field, script)
-
- if ref_dt == "Journal Entry":
- script = re.sub(r"\bentries\b", "accounts", script)
- elif ref_dt == "Bank Reconciliation":
- script = re.sub(r"\bentries\b", "journal_entries", script)
- elif ref_dt in ("Sales Invoice", "Purchase Invoice"):
- script = re.sub(r"\bentries\b", "items", script)
-
- frappe.db.set_value(dt, name, script_field, script)
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py b/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
deleted file mode 100644
index 76efdcc7c6..0000000000
--- a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- je_list = frappe.db.sql_list("""
- select par.name from `tabJournal Entry` par
- where par.docstatus=1 and par.creation > '2015-03-01'
- and (select count(distinct child.party) from `tabJournal Entry Account` child
- where par.name=child.parent and ifnull(child.party, '') != '') > 1
- """)
-
- for d in je_list:
- # delete existing gle
- frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
-
- # repost gl entries
- je = frappe.get_doc("Journal Entry", d)
- je.make_gl_entries()
-
- if je_list:
- print(je_list)
-
-
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/repost_requested_qty.py b/erpnext/patches/v5_0/repost_requested_qty.py
deleted file mode 100644
index 6af71f3fc4..0000000000
--- a/erpnext/patches/v5_0/repost_requested_qty.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
-
- count=0
- for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse
- from `tabMaterial Request Item` where docstatus = 1"""):
- try:
- count += 1
- update_bin_qty(item_code, warehouse, {
- "indented_qty": get_indented_qty(item_code, warehouse),
- })
- if count % 200 == 0:
- frappe.db.commit()
- except:
- frappe.db.rollback()
diff --git a/erpnext/patches/v5_0/reset_values_in_tools.py b/erpnext/patches/v5_0/reset_values_in_tools.py
deleted file mode 100644
index fd970ba1b0..0000000000
--- a/erpnext/patches/v5_0/reset_values_in_tools.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ["Payment Tool", "Bank Reconciliation", "Payment Reconciliation", "Leave Control Panel",
- "Salary Manager", "Upload Attenadance", "Production Planning Tool", "BOM Update Tool", "Customize Form",
- "Employee Attendance Tool", "Rename Tool", "BOM Update Tool", "Process Payroll", "Naming Series"]:
- frappe.db.sql("delete from `tabSingles` where doctype=%s", dt)
-
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/set_appraisal_remarks.py b/erpnext/patches/v5_0/set_appraisal_remarks.py
deleted file mode 100644
index 8652c32cf0..0000000000
--- a/erpnext/patches/v5_0/set_appraisal_remarks.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Appraisal")
- frappe.db.sql("update `tabAppraisal` set remarks = comments")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/set_default_company_in_bom.py b/erpnext/patches/v5_0/set_default_company_in_bom.py
deleted file mode 100644
index a5cd761119..0000000000
--- a/erpnext/patches/v5_0/set_default_company_in_bom.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("manufacturing", "doctype", "bom")
- company = frappe.db.get_value("Global Defaults", None, "default_company")
- frappe.db.sql("""update `tabBOM` set company = %s""",company)
diff --git a/erpnext/patches/v5_0/set_footer_address.py b/erpnext/patches/v5_0/set_footer_address.py
deleted file mode 100644
index 8120d834e1..0000000000
--- a/erpnext/patches/v5_0/set_footer_address.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("System Settings")
- ss = frappe.get_doc("System Settings", "System Settings")
- ss.email_footer_address = frappe.db.get_default("company")
- ss.flags.ignore_mandatory = True
- ss.save()
diff --git a/erpnext/patches/v5_0/stock_entry_update_value.py b/erpnext/patches/v5_0/stock_entry_update_value.py
deleted file mode 100644
index ba1af310f5..0000000000
--- a/erpnext/patches/v5_0/stock_entry_update_value.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.db.get_all("Stock Entry"):
- se = frappe.get_doc("Stock Entry", d.name)
- se.set_total_incoming_outgoing_value()
- se.db_update()
diff --git a/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py b/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py
deleted file mode 100644
index 76d10820b5..0000000000
--- a/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.meta import get_field_precision
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
-
-def execute():
- selling_doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]
- buying_doctypes = ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
-
- for dt in selling_doctypes:
- update_values(dt, "Sales Taxes and Charges")
-
- for dt in buying_doctypes:
- update_values(dt, "Purchase Taxes and Charges")
-
-def update_values(dt, tax_table):
- frappe.reload_doctype(dt)
- frappe.reload_doctype(dt + " Item")
- frappe.reload_doctype(tax_table)
-
- net_total_precision = get_field_precision(frappe.get_meta(dt).get_field("net_total"))
- for field in ("total", "base_total", "base_net_total"):
- make_property_setter(dt, field, "precision", net_total_precision, "Select")
-
- rate_field_precision = get_field_precision(frappe.get_meta(dt + " Item").get_field("rate"))
- for field in ("net_rate", "base_net_rate", "net_amount", "base_net_amount", "base_rate", "base_amount"):
- make_property_setter(dt + " Item", field, "precision", rate_field_precision, "Select")
-
- tax_amount_precision = get_field_precision(frappe.get_meta(tax_table).get_field("tax_amount"))
- for field in ("base_tax_amount", "total", "base_total", "tax_amount_after_discount_amount",
- "base_tax_amount_after_discount_amount"):
- make_property_setter(tax_table, field, "precision", tax_amount_precision, "Select")
-
- # update net_total, discount_on
- frappe.db.sql("""
- UPDATE
- `tab{0}`
- SET
- total = round(net_total, {1}),
- base_total = round(net_total*conversion_rate, {1}),
- net_total = round(base_net_total / conversion_rate, {1}),
- apply_discount_on = "Grand Total"
- WHERE
- docstatus < 2
- """.format(dt, net_total_precision))
-
- # update net_amount
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` item
- SET
- item.base_net_amount = round(item.base_amount, {2}),
- item.base_net_rate = round(item.base_rate, {2}),
- item.net_amount = round(item.base_amount / par.conversion_rate, {2}),
- item.net_rate = round(item.base_rate / par.conversion_rate, {2}),
- item.base_amount = round(item.amount * par.conversion_rate, {2}),
- item.base_rate = round(item.rate * par.conversion_rate, {2})
- WHERE
- par.name = item.parent
- and par.docstatus < 2
- """.format(dt, dt + " Item", rate_field_precision))
-
- # update tax in party currency
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` tax
- SET
- tax.base_tax_amount = round(tax.tax_amount, {2}),
- tax.tax_amount = round(tax.tax_amount / par.conversion_rate, {2}),
- tax.base_total = round(tax.total, {2}),
- tax.total = round(tax.total / conversion_rate, {2}),
- tax.base_tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount, {2}),
- tax.tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount / conversion_rate, {2})
- WHERE
- par.name = tax.parent
- and par.docstatus < 2
- """.format(dt, tax_table, tax_amount_precision))
diff --git a/erpnext/patches/v5_0/update_account_types.py b/erpnext/patches/v5_0/update_account_types.py
deleted file mode 100644
index 424743efaa..0000000000
--- a/erpnext/patches/v5_0/update_account_types.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for company in frappe.db.get_all("Company"):
- company = frappe.get_doc("Company", company.name)
-
- match_types = ("Stock Received But Not Billed", "Stock Adjustment", "Expenses Included In Valuation",
- "Cost of Goods Sold")
-
- for account_type in match_types:
- account_name = "{0} - {1}".format(account_type, company.abbr)
- current_account_type = frappe.db.get_value("Account", account_name, "account_type")
- if current_account_type != account_type:
- frappe.db.set_value("Account", account_name, "account_type", account_type)
-
- company.set_default_accounts()
diff --git a/erpnext/patches/v5_0/update_advance_paid.py b/erpnext/patches/v5_0/update_advance_paid.py
deleted file mode 100644
index 74e71e84c8..0000000000
--- a/erpnext/patches/v5_0/update_advance_paid.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Sales Order", "Purchase Order"):
- orders_with_advance = frappe.db.sql("""select name from `tab{0}`
- where docstatus < 2 and ifnull(advance_paid, 0) != 0""".format(dt), as_dict=1)
-
- for order in orders_with_advance:
- frappe.get_doc(dt, order.name).set_total_advance_paid()
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_companywise_payment_account.py b/erpnext/patches/v5_0/update_companywise_payment_account.py
deleted file mode 100644
index fb4b919c85..0000000000
--- a/erpnext/patches/v5_0/update_companywise_payment_account.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment')
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment_account')
-
- mode_of_payment_list = frappe.db.sql("""select name, default_account
- from `tabMode of Payment`""", as_dict=1)
-
- for d in mode_of_payment_list:
- if d.get("default_account"):
- parent_doc = frappe.get_doc("Mode of Payment", d.get("name"))
-
- parent_doc.set("accounts",
- [{"company": frappe.db.get_value("Account", d.get("default_account"), "company"),
- "default_account": d.get("default_account")}])
- parent_doc.save()
diff --git a/erpnext/patches/v5_0/update_dn_against_doc_fields.py b/erpnext/patches/v5_0/update_dn_against_doc_fields.py
deleted file mode 100644
index 56f4f484b1..0000000000
--- a/erpnext/patches/v5_0/update_dn_against_doc_fields.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
-
- frappe.db.sql("""update `tabDelivery Note Item` set so_detail = prevdoc_detail_docname
- where ifnull(against_sales_order, '') != ''""")
-
- frappe.db.sql("""update `tabDelivery Note Item` set si_detail = prevdoc_detail_docname
- where ifnull(against_sales_invoice, '') != ''""")
diff --git a/erpnext/patches/v5_0/update_from_bom.py b/erpnext/patches/v5_0/update_from_bom.py
deleted file mode 100644
index 4b3e62d7a5..0000000000
--- a/erpnext/patches/v5_0/update_from_bom.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Stock Entry")
- frappe.db.sql("update `tabStock Entry` set from_bom = if(ifnull(bom_no, '')='', 0, 1)")
diff --git a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py b/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
deleted file mode 100644
index b52785ae60..0000000000
--- a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- account_settings = frappe.get_doc("Accounts Settings")
-
- if not account_settings.frozen_accounts_modifier and account_settings.bde_auth_role:
- frappe.db.set_value("Accounts Settings", None,
- "frozen_accounts_modifier", account_settings.bde_auth_role)
-
diff --git a/erpnext/patches/v5_0/update_item_and_description_again.py b/erpnext/patches/v5_0/update_item_and_description_again.py
deleted file mode 100644
index 35dedcc072..0000000000
--- a/erpnext/patches/v5_0/update_item_and_description_again.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cstr
-import re
-
-def execute():
- item_details = frappe._dict()
- for d in frappe.db.sql("select name, description from `tabItem`", as_dict=1):
- description = cstr(d.description).strip()
- new_desc = extract_description(description)
-
- item_details.setdefault(d.name, frappe._dict({
- "old_description": description,
- "new_description": new_desc
- }))
-
-
- dt_list= ["Purchase Order Item","Supplier Quotation Item", "BOM", "BOM Explosion Item" , \
- "BOM Item", "Opportunity Item" , "Quotation Item" , "Sales Order Item" , "Delivery Note Item" , \
- "Material Request Item" , "Purchase Receipt Item" , "Stock Entry Detail"]
- for dt in dt_list:
- frappe.reload_doctype(dt)
- records = frappe.db.sql("""select name, `{0}` as item_code, description from `tab{1}`
- where description is not null and description like '%%]*\>".format(tag), "", desc)
-
- return desc
diff --git a/erpnext/patches/v5_0/update_item_desc_in_invoice.py b/erpnext/patches/v5_0/update_item_desc_in_invoice.py
deleted file mode 100644
index dba35d5693..0000000000
--- a/erpnext/patches/v5_0/update_item_desc_in_invoice.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.website.utils import find_first_image
-from frappe.utils import cstr
-import re
-
-def execute():
- item_details = frappe._dict()
- for d in frappe.db.sql("select name, description, image from `tabItem`", as_dict=1):
- description = cstr(d.description).strip()
- item_details.setdefault(d.name, frappe._dict({
- "description": description,
- "image": d.image
- }))
-
-
- dt_list= ["Sales Invoice Item","Purchase Invoice Item"]
- for dt in dt_list:
- frappe.reload_doctype(dt)
- records = frappe.db.sql("""select name, item_code, description from `tab{0}`
- where ifnull(item_code, '') != '' and description is not null """.format(dt), as_dict=1)
-
- count = 1
- for d in records:
- if item_details.get(d.item_code) and cstr(d.description) == item_details.get(d.item_code).description:
- desc = item_details.get(d.item_code).description
- image = item_details.get(d.item_code).image
- else:
- desc, image = extract_image_and_description(cstr(d.description))
-
- if not image:
- item_detail = item_details.get(d.item_code)
- if item_detail:
- image = item_detail.image
-
- frappe.db.sql("""update `tab{0}` set description = %s, image = %s
- where name = %s """.format(dt), (desc, image, d.name))
-
- count += 1
- if count % 500 == 0:
- frappe.db.commit()
-
-
-def extract_image_and_description(data):
- image_url = find_first_image(data)
- desc = data
- for tag in ("img", "table", "tr", "td"):
- desc = re.sub("\*{0}[^>]*\>".format(tag), "", desc)
- return desc, image_url
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_item_description_and_image.py b/erpnext/patches/v5_0/update_item_description_and_image.py
deleted file mode 100644
index 75df39ee39..0000000000
--- a/erpnext/patches/v5_0/update_item_description_and_image.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.website.utils import find_first_image
-from frappe.utils import cstr
-import re
-
-def execute():
- item_details = frappe._dict()
- for d in frappe.db.sql("select name, description_html, description from `tabItem`", as_dict=1):
- description = cstr(d.description_html).strip() or cstr(d.description).strip()
- image_url, new_desc = extract_image_and_description(description)
-
- item_details.setdefault(d.name, frappe._dict({
- "old_description": description,
- "new_description": new_desc,
- "image_url": image_url
- }))
-
-
- dt_list= ["Purchase Order Item","Supplier Quotation Item", "BOM", "BOM Explosion Item" , \
- "BOM Item", "Opportunity Item" , "Quotation Item" , "Sales Order Item" , "Delivery Note Item" , \
- "Material Request Item" , "Purchase Receipt Item" , "Stock Entry Detail"]
- for dt in dt_list:
- frappe.reload_doctype(dt)
- records = frappe.db.sql("""select name, `{0}` as item_code, description from `tab{1}`
- where description is not null and image is null and description like '%%
]+\>", "", data)
-
- return image_url, desc
diff --git a/erpnext/patches/v5_0/update_item_name_in_bom.py b/erpnext/patches/v5_0/update_item_name_in_bom.py
deleted file mode 100644
index 5781542a2a..0000000000
--- a/erpnext/patches/v5_0/update_item_name_in_bom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("manufacturing", "doctype", "bom")
- frappe.reload_doc("manufacturing", "doctype", "bom_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_explosion_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_operation")
-
- frappe.db.sql("""update `tabBOM` as bom set bom.item_name = \
- ( select item.item_name from `tabItem` as item where item.name = bom.item)""")
- frappe.db.sql("""update `tabBOM Item` as bomItem set bomItem.item_name = ( select item.item_name \
- from `tabItem` as item where item.name = bomItem.item_code)""")
- frappe.db.sql("""update `tabBOM Explosion Item` as explosionItem set explosionItem.item_name = \
- ( select item.item_name from `tabItem` as item where item.name = explosionItem.item_code)""")
diff --git a/erpnext/patches/v5_0/update_journal_entry_title.py b/erpnext/patches/v5_0/update_journal_entry_title.py
deleted file mode 100644
index eaa2be054f..0000000000
--- a/erpnext/patches/v5_0/update_journal_entry_title.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Journal Entry")
- frappe.db.sql("""update `tabJournal Entry` set title =
- if(ifnull(pay_to_recd_from, "")!="", pay_to_recd_from,
- (select account from `tabJournal Entry Account`
- where parent=`tabJournal Entry`.name and idx=1 limit 1))""")
diff --git a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py b/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py
deleted file mode 100644
index f31c9fed4d..0000000000
--- a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabStock Entry` set purpose='Material Transfer for Manufacture'
- where ifnull(work_order, '')!='' and purpose='Material Transfer'""")
diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py
deleted file mode 100644
index 2a09aa29af..0000000000
--- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Work Order")
- frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing=
- (select sum(fg_completed_qty) from `tabStock Entry`
- where docstatus=1
- and work_order=`tabWork Order`.name
- and purpose = "Material Transfer for Manufacture")""")
diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py
deleted file mode 100644
index 5847c83d38..0000000000
--- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- wo_order_qty_transferred = frappe._dict()
- for se in frappe.db.sql("""select work_order, sum(fg_completed_qty) as transferred_qty
- from `tabStock Entry`
- where docstatus=1 and ifnull(work_order, '') != ''
- and purpose = 'Material Transfer for Manufacture'
- group by work_order""", as_dict=1):
- wo_order_qty_transferred.setdefault(se.work_order, se.transferred_qty)
-
- for d in frappe.get_all("Work Order", filters={"docstatus": 1}, fields=["name", "qty"]):
- if d.name in wo_order_qty_transferred:
- material_transferred_for_manufacturing = wo_order_qty_transferred.get(d.name) \
- if wo_order_qty_transferred.get(d.name) <= d.qty else d.qty
-
- frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing=%s
- where name=%s""", (material_transferred_for_manufacturing, d.name))
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_operation_description.py b/erpnext/patches/v5_0/update_operation_description.py
deleted file mode 100644
index 4ce32f35f1..0000000000
--- a/erpnext/patches/v5_0/update_operation_description.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- if "opn_description" in frappe.db.get_table_columns("BOM Operation"):
- frappe.db.sql("""update `tabBOM Operation` set description = opn_description
- where ifnull(description, '') = ''""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_opportunity.py b/erpnext/patches/v5_0/update_opportunity.py
deleted file mode 100644
index 8eb45c48e7..0000000000
--- a/erpnext/patches/v5_0/update_opportunity.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('crm', 'doctype', 'opportunity')
- frappe.reload_doc('crm', 'doctype', 'opportunity_item')
-
- # all existing opportunities were with items
- frappe.db.sql("update `tabDocType` set module = 'CRM' where name='Opportunity Item'")
- frappe.db.sql("update tabOpportunity set with_items=1, title=customer_name")
- frappe.db.sql("update `tabEmail Account` set append_to='Opportunity' where append_to='Lead'")
diff --git a/erpnext/patches/v5_0/update_projects.py b/erpnext/patches/v5_0/update_projects.py
deleted file mode 100644
index 68e03c9bdb..0000000000
--- a/erpnext/patches/v5_0/update_projects.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # convert milestones to tasks
- frappe.reload_doctype("Project")
- frappe.reload_doc("projects", "doctype", "project_task")
- frappe.reload_doctype("Task")
- frappe.reload_doc("projects", "doctype", "task_depends_on")
- frappe.reload_doc("projects", "doctype", "time_log")
-
- for m in frappe.get_all("Project Milestone", "*"):
- if (m.milestone and m.milestone_date
- and frappe.db.exists("Project", m.parent)):
- subject = (m.milestone[:139] + "…") if (len(m.milestone) > 140) else m.milestone
- description = m.milestone
- task = frappe.get_doc({
- "doctype": "Task",
- "subject": subject,
- "description": description if description!=subject else None,
- "expected_start_date": m.milestone_date,
- "status": "Open" if m.status=="Pending" else "Closed",
- "project": m.parent,
- })
- task.flags.ignore_mandatory = True
- task.insert(ignore_permissions=True)
-
- # remove project milestone
- frappe.delete_doc("DocType", "Project Milestone")
-
- # remove calendar events for milestone
- for e in frappe.get_all("Event", ["name"], {"ref_type": "Project"}):
- frappe.delete_doc("Event", e.name)
diff --git a/erpnext/patches/v5_0/update_sms_sender.py b/erpnext/patches/v5_0/update_sms_sender.py
deleted file mode 100644
index 7ffc703c43..0000000000
--- a/erpnext/patches/v5_0/update_sms_sender.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.set_value("SMS Settings", "SMS Settings", "sms_sender_name",
- frappe.db.get_single_value("Global Defaults", "sms_sender_name"))
diff --git a/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py b/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py
deleted file mode 100644
index 53df9422b3..0000000000
--- a/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""
- update
- `tabPurchase Taxes and Charges`
- set
- tax_amount_after_discount_amount = tax_amount,
- base_tax_amount_after_discount_amount = base_tax_amount
- where
- ifnull(tax_amount_after_discount_amount, 0) = 0
- and ifnull(base_tax_amount_after_discount_amount, 0) = 0
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_temporary_account.py b/erpnext/patches/v5_0/update_temporary_account.py
deleted file mode 100644
index 078c8714ff..0000000000
--- a/erpnext/patches/v5_0/update_temporary_account.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""Update `tabAccount` set account_type = 'Temporary'
- where account_name in ('Temporary Assets', 'Temporary Liabilities', 'Temporary Opening')""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_time_log_title.py b/erpnext/patches/v5_0/update_time_log_title.py
deleted file mode 100644
index 8263be0007..0000000000
--- a/erpnext/patches/v5_0/update_time_log_title.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Time Log")
- for d in frappe.get_all("Time Log"):
- time_log = frappe.get_doc("Time Log", d.name)
- time_log.set_title()
- frappe.db.set_value("Time Log", time_log.name, "title", time_log.title)
diff --git a/erpnext/patches/v5_1/__init__.py b/erpnext/patches/v5_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v5_1/default_bom.py b/erpnext/patches/v5_1/default_bom.py
deleted file mode 100644
index 6484edd603..0000000000
--- a/erpnext/patches/v5_1/default_bom.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.db.sql("""Update `tabItem` as item set default_bom = NULL where
- not exists(select name from `tabBOM` as bom where item.default_bom = bom.name and bom.docstatus =1 )""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_1/fix_against_account.py b/erpnext/patches/v5_1/fix_against_account.py
deleted file mode 100644
index a62c15b7d1..0000000000
--- a/erpnext/patches/v5_1/fix_against_account.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-from erpnext.accounts.doctype.gl_entry.gl_entry import update_against_account
-
-def execute():
- from_date = "2015-05-01"
-
- for doc in frappe.get_all("Journal Entry",
- filters={"creation": (">", from_date), "docstatus": "1"}):
-
- # update in gl_entry
- update_against_account("Journal Entry", doc.name)
-
- # update in jv
- doc = frappe.get_doc("Journal Entry", doc.name)
- doc.set_against_account()
- doc.db_update()
-
- for doc in frappe.get_all("Sales Invoice",
- filters={"creation": (">", from_date), "docstatus": "1"},
- fields=["name", "customer"]):
-
- frappe.db.sql("""update `tabGL Entry` set against=%s
- where voucher_type='Sales Invoice' and voucher_no=%s
- and credit > 0 and ifnull(party, '')=''""",
- (doc.customer, doc.name))
-
- for doc in frappe.get_all("Purchase Invoice",
- filters={"creation": (">", from_date), "docstatus": "1"},
- fields=["name", "supplier"]):
-
- frappe.db.sql("""update `tabGL Entry` set against=%s
- where voucher_type='Purchase Invoice' and voucher_no=%s
- and debit > 0 and ifnull(party, '')=''""",
- (doc.supplier, doc.name))
diff --git a/erpnext/patches/v5_1/rename_roles.py b/erpnext/patches/v5_1/rename_roles.py
deleted file mode 100644
index e19c22a614..0000000000
--- a/erpnext/patches/v5_1/rename_roles.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists("Role", "Stock User"):
- frappe.rename_doc("Role", "Material User", "Stock User")
- if not frappe.db.exists("Role", "Stock Manager"):
- frappe.rename_doc("Role", "Material Manager", "Stock Manager")
- if not frappe.db.exists("Role", "Item Manager"):
- frappe.rename_doc("Role", "Material Master Manager", "Item Manager")
diff --git a/erpnext/patches/v5_1/sales_bom_rename.py b/erpnext/patches/v5_1/sales_bom_rename.py
deleted file mode 100644
index e06012f3e4..0000000000
--- a/erpnext/patches/v5_1/sales_bom_rename.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- tables = frappe.db.sql_list("show tables")
- for old_dt, new_dt in [["Sales BOM Item", "Product Bundle Item"],
- ["Sales BOM", "Product Bundle"]]:
- if "tab"+new_dt not in tables:
- frappe.rename_doc("DocType", old_dt, new_dt, force=True)
diff --git a/erpnext/patches/v5_2/__init__.py b/erpnext/patches/v5_2/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v5_2/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v5_2/change_item_selects_to_checks.py b/erpnext/patches/v5_2/change_item_selects_to_checks.py
deleted file mode 100644
index 1ee8f6caa5..0000000000
--- a/erpnext/patches/v5_2/change_item_selects_to_checks.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- fields = ("is_stock_item", "is_asset_item", "has_batch_no", "has_serial_no",
- "is_sales_item", "is_purchase_item", "inspection_required", "is_sub_contracted_item")
-
- # convert to 1 or 0
- update_str = ", ".join(["`{0}`=if(`{0}`='Yes',1,0)".format(f) for f in fields])
- frappe.db.sql("update tabItem set {0}".format(update_str))
-
- frappe.db.commit()
-
- # alter fields to int
- for f in fields:
- frappe.db.sql("alter table tabItem change {0} {0} int(1) default '0'".format(f, f))
-
- frappe.reload_doctype("Item")
diff --git a/erpnext/patches/v5_4/__init__.py b/erpnext/patches/v5_4/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v5_4/cleanup_journal_entry.py b/erpnext/patches/v5_4/cleanup_journal_entry.py
deleted file mode 100644
index 6860e6ad09..0000000000
--- a/erpnext/patches/v5_4/cleanup_journal_entry.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from pymysql import InternalError
-
-def execute():
- frappe.reload_doctype("Journal Entry Account")
- for doctype, fieldname in (
- ("Sales Order", "against_sales_order"),
- ("Purchase Order", "against_purchase_order"),
- ("Sales Invoice", "against_invoice"),
- ("Purchase Invoice", "against_voucher"),
- ("Journal Entry", "against_jv"),
- ("Expense Claim", "against_expense_claim"),
- ):
- try:
- frappe.db.sql("""update `tabJournal Entry Account`
- set reference_type=%s, reference_name={0} where ifnull({0}, '') != ''
- """.format(fieldname), doctype)
- except InternalError:
- # column not found
- pass
diff --git a/erpnext/patches/v5_4/fix_invoice_outstanding.py b/erpnext/patches/v5_4/fix_invoice_outstanding.py
deleted file mode 100644
index 54a1da69ef..0000000000
--- a/erpnext/patches/v5_4/fix_invoice_outstanding.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
-
-def execute():
- frappe.reload_doctype("Sales Invoice")
- return_entries = frappe.get_list("Sales Invoice", filters={"is_return": 1, "docstatus": 1},
- fields=["debit_to", "customer", "return_against"])
- for d in return_entries:
- update_outstanding_amt(d.debit_to, "Customer", d.customer, "Sales Invoice", d.return_against)
diff --git a/erpnext/patches/v5_4/fix_missing_item_images.py b/erpnext/patches/v5_4/fix_missing_item_images.py
deleted file mode 100644
index c6fe57896f..0000000000
--- a/erpnext/patches/v5_4/fix_missing_item_images.py
+++ /dev/null
@@ -1,126 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-import os
-from frappe.utils import get_files_path
-from frappe.core.doctype.file.file import get_content_hash
-
-def execute():
- files_path = get_files_path()
-
- # get files that don't have attached_to_name but exist
- unlinked_files = get_unlinked_files(files_path)
- if not unlinked_files:
- return
-
- fixed_files = fix_files_for_item(files_path, unlinked_files)
-
- # fix remaining files
- for key, file_data in unlinked_files.items():
- if key not in fixed_files:
- rename_and_set_content_hash(files_path, unlinked_files, key)
- frappe.db.commit()
-
-def fix_files_for_item(files_path, unlinked_files):
- fixed_files = []
-
- # make a list of files/something and /files/something to check in child table's image column
- file_urls = [key for key in unlinked_files.keys()] + ["/" + key for key in unlinked_files.keys()]
- file_item_code = get_file_item_code(file_urls)
-
- for (file_url, item_code), children in file_item_code.items():
- new_file_url = "/files/{0}".format(unlinked_files[file_url]["file_name"])
-
- for row in children:
- # print file_url, new_file_url, item_code, row.doctype, row.name
-
- # replace image in these rows with the new file url
- frappe.db.set_value(row.doctype, row.name, "image", new_file_url, update_modified=False)
-
- # set it as attachment of this item code
- file_data = frappe.get_doc("File", unlinked_files[file_url]["file"])
- file_data.attached_to_doctype = "Item"
- file_data.attached_to_name = item_code
- file_data.flags.ignore_folder_validate = True
-
- try:
- file_data.save()
- except IOError:
- print("File {0} does not exist".format(new_file_url))
-
- # marking fix to prevent further errors
- fixed_files.append(file_url)
-
- continue
-
- # set it as image in Item
- if not frappe.db.get_value("Item", item_code, "image"):
- frappe.db.set_value("Item", item_code, "image", new_file_url, update_modified=False)
-
- rename_and_set_content_hash(files_path, unlinked_files, file_url)
-
- fixed_files.append(file_url)
-
- # commit
- frappe.db.commit()
-
- return fixed_files
-
-def rename_and_set_content_hash(files_path, unlinked_files, file_url):
- # rename this file
- old_filename = os.path.join(files_path, unlinked_files[file_url]["file"])
- new_filename = os.path.join(files_path, unlinked_files[file_url]["file_name"])
-
- if not os.path.exists(new_filename):
- os.rename(old_filename, new_filename)
-
- # set content hash if missing
- file_data_name = unlinked_files[file_url]["file"]
- if not frappe.db.get_value("File", file_data_name, "content_hash"):
- with open(new_filename, "r") as f:
- content_hash = get_content_hash(f.read())
- frappe.db.set_value("File", file_data_name, "content_hash", content_hash)
-
-def get_unlinked_files(files_path):
- # find files that have the same name as a File doc
- # and the file_name mentioned in that File doc doesn't exist
- # and it isn't already attached to a doc
- unlinked_files = {}
- files = os.listdir(files_path)
- for file in files:
- if not frappe.db.exists("File", {"file_name": file}):
- file_data = frappe.db.get_value("File", {"name": file},
- ["file_name", "attached_to_doctype", "attached_to_name"], as_dict=True)
-
- if (file_data
- and file_data.file_name
- and file_data.file_name not in files
- and not file_data.attached_to_doctype
- and not file_data.attached_to_name):
-
- file_data["file"] = file
- unlinked_files["files/{0}".format(file)] = file_data
-
- return unlinked_files
-
-def get_file_item_code(file_urls):
- # get a map of file_url, item_code and list of documents where file_url will need to be changed in image field
- file_item_code = {}
-
- doctypes = frappe.db.sql_list("""select name from `tabDocType` dt
- where istable=1
- and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='item_code')
- and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='image')""")
-
- for doctype in doctypes:
- result = frappe.db.sql("""select name, image, item_code, '{0}' as doctype from `tab{0}`
- where image in ({1})""".format(doctype, ", ".join(["%s"]*len(file_urls))),
- file_urls, as_dict=True)
-
- for r in result:
- key = (r.image, r.item_code)
- if key not in file_item_code:
- file_item_code[key] = []
-
- file_item_code[key].append(r)
-
- return file_item_code
diff --git a/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py b/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py
deleted file mode 100644
index 6eb3994c7c..0000000000
--- a/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import repost_actual_qty
-
-def execute():
- cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice`
- where docstatus = 2 and ifnull(update_stock, 0) = 1""")
-
- if cancelled_invoices:
- repost_for = frappe.db.sql("""select distinct item_code, warehouse from `tabStock Ledger Entry`
- where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
- % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
-
- frappe.db.sql("""delete from `tabStock Ledger Entry`
- where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
- % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
-
- for item_code, warehouse in repost_for:
- repost_actual_qty(item_code, warehouse)
\ No newline at end of file
diff --git a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
deleted file mode 100644
index ba311225bb..0000000000
--- a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.email import sendmail_to_system_managers
-from frappe.utils import get_link_to_form
-
-def execute():
- wrong_records = []
- for dt in ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
- "Purchase Order", "Purchase Receipt", "Purchase Invoice"):
- records = frappe.db.sql_list("""select name from `tab{0}`
- where apply_discount_on = 'Net Total' and ifnull(discount_amount, 0) != 0
- and modified >= '2015-02-17' and docstatus=1""".format(dt))
-
- if records:
- records = [get_link_to_form(dt, d) for d in records]
- wrong_records.append([dt, records])
-
- if wrong_records:
- content = """Dear System Manager,
-
-Due to an error related to Discount Amount on Net Total, tax calculation might be wrong in the following records. We did not fix the tax amount automatically because it can corrupt the entries, so we request you to check these records and amend if you found the calculation wrong.
-
-Please check following Entries:
-
-%s
-
-
-Regards,
-
-Administrator""" % "\n".join([(d[0] + ": " + ", ".join(d[1])) for d in wrong_records])
- try:
- sendmail_to_system_managers("[Important] [ERPNext] Tax calculation might be wrong, please check.", content)
- except:
- pass
-
- print("="*50)
- print(content)
- print("="*50)
\ No newline at end of file
diff --git a/erpnext/patches/v5_4/set_root_and_report_type.py b/erpnext/patches/v5_4/set_root_and_report_type.py
deleted file mode 100644
index 9147644da2..0000000000
--- a/erpnext/patches/v5_4/set_root_and_report_type.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- roots = frappe.db.sql("""select lft, rgt, report_type, root_type
- from `tabAccount` where ifnull(parent_account, '')=''""", as_dict=1)
- for d in roots:
- frappe.db.sql("update `tabAccount` set report_type=%s, root_type=%s where lft > %s and rgt < %s",
- (d.report_type, d.root_type, d.lft, d.rgt))
\ No newline at end of file
diff --git a/erpnext/patches/v5_4/stock_entry_additional_costs.py b/erpnext/patches/v5_4/stock_entry_additional_costs.py
deleted file mode 100644
index 3a98deb918..0000000000
--- a/erpnext/patches/v5_4/stock_entry_additional_costs.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doctype("Stock Entry")
- frappe.reload_doctype("Stock Entry Detail")
- frappe.reload_doctype("Landed Cost Taxes and Charges")
-
- stock_entry_db_columns = frappe.db.get_table_columns("Stock Entry")
- if "additional_operating_cost" in stock_entry_db_columns:
- operating_cost_fieldname = "additional_operating_cost"
- elif "total_fixed_cost" in stock_entry_db_columns:
- operating_cost_fieldname = "total_fixed_cost"
- else:
- return
-
-
- frappe.db.sql("""update `tabStock Entry Detail` sed, `tabStock Entry` se
- set sed.valuation_rate=sed.incoming_rate, sed.basic_rate=sed.incoming_rate, sed.basic_amount=sed.amount
- where sed.parent = se.name
- and (se.purpose not in ('Manufacture', 'Repack') or ifnull({0}, 0)=0)
- """.format(operating_cost_fieldname))
-
-
- stock_entries = frappe.db.sql_list("""select name from `tabStock Entry`
- where purpose in ('Manufacture', 'Repack') and ifnull({0}, 0)!=0
- and docstatus < 2""".format(operating_cost_fieldname))
-
- for d in stock_entries:
- stock_entry = frappe.get_doc("Stock Entry", d)
- stock_entry.append("additional_costs", {
- "description": "Additional Operating Cost",
- "amount": stock_entry.get(operating_cost_fieldname)
- })
-
- number_of_fg_items = len([t.t_warehouse for t in stock_entry.get("items") if t.t_warehouse])
-
- for d in stock_entry.get("items"):
- d.valuation_rate = d.incoming_rate
-
- if d.bom_no or (d.t_warehouse and number_of_fg_items == 1):
- d.additional_cost = stock_entry.get(operating_cost_fieldname)
-
- d.basic_rate = flt(d.valuation_rate) - flt(d.additional_cost)
- d.basic_amount = flt(flt(d.basic_rate) *flt(d.transfer_qty), d.precision("basic_amount"))
-
- stock_entry.flags.ignore_validate = True
- stock_entry.flags.ignore_validate_update_after_submit = True
- stock_entry.save()
diff --git a/erpnext/patches/v5_4/update_purchase_cost_against_project.py b/erpnext/patches/v5_4/update_purchase_cost_against_project.py
deleted file mode 100644
index 1b917c83c4..0000000000
--- a/erpnext/patches/v5_4/update_purchase_cost_against_project.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for p in frappe.get_all("Project"):
- purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
- from `tabPurchase Invoice Item` where project = %s and docstatus=1""", p.name)
- purchase_cost = purchase_cost and purchase_cost[0][0] or 0
-
- frappe.db.set_value("Project", p.name, "total_purchase_cost", purchase_cost)
\ No newline at end of file
diff --git a/erpnext/patches/v5_7/__init__.py b/erpnext/patches/v5_7/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v5_7/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v5_7/item_template_attributes.py b/erpnext/patches/v5_7/item_template_attributes.py
deleted file mode 100644
index 6aa81f79b2..0000000000
--- a/erpnext/patches/v5_7/item_template_attributes.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.exceptions import SQLError
-
-def execute():
- """
- Structure History:
- 1. Item and Item Variant
- 2. Item, Variant Attribute, Manage Variants and Manage Variant Items
- 3. Item, Item Variant Attribute, Item Attribute and Item Attribute Type (latest)
- """
- rename_and_reload_doctypes()
-
- variant_templates = frappe.get_all("Item", filters={"has_variants": 1}, limit_page_length=1)
- if not variant_templates:
- # database does not have items that have variants
- # so no point in running the patch
- return
-
- variant_attributes = frappe.get_all("Item Variant Attribute", fields=["*"], limit_page_length=1)
-
- if variant_attributes:
- # manage variant patch is already applied
- migrate_manage_variants()
-
- else:
- # old structure based on "Item Variant" table
- try:
- migrate_item_variants()
-
- except SQLError:
- print("`tabItem Variant` not found")
-
-def rename_and_reload_doctypes():
- if "tabVariant Attribute" in frappe.db.get_tables():
- frappe.rename_doc("DocType", "Variant Attribute", "Item Variant Attribute")
-
- frappe.reload_doctype("Item")
- frappe.reload_doc("Stock", "DocType", "Item Variant Attribute")
- frappe.reload_doc("Stock", "DocType", "Item Attribute Value")
- frappe.reload_doc("Stock", "DocType", "Item Attribute")
-
-def migrate_manage_variants():
- item_attribute = {}
- for d in frappe.db.sql("""select DISTINCT va.attribute, i.variant_of
- from `tabItem Variant Attribute` va, `tabItem` i
- where va.parent = i.name and ifnull(i.variant_of, '')!=''""", as_dict=1):
- item_attribute.setdefault(d.variant_of, []).append({"attribute": d.attribute})
-
- for item, attributes in item_attribute.items():
- template = frappe.get_doc("Item", item)
- template.set('attributes', attributes)
- template.save()
-
-# patch old style
-def migrate_item_variants():
- for item in frappe.get_all("Item", filters={"has_variants": 1}):
- all_variants = frappe.get_all("Item", filters={"variant_of": item.name}, fields=["name", "description"])
- item_attributes = frappe.db.sql("""select distinct item_attribute, item_attribute_value
- from `tabItem Variant` where parent=%s""", item.name)
-
- if not item_attributes and not all_variants:
- item = frappe.get_doc("Item", item.name)
- item.has_variants = 0
- item.save()
- continue
-
- attribute_value_options = {}
- for attribute, value in item_attributes:
- attribute_value_options.setdefault(attribute, []).append(value)
-
- possible_combinations = get_possible_combinations(attribute_value_options)
-
- for variant in all_variants:
- for combination in possible_combinations:
- match = True
- for attribute, value in combination.items():
- if "{0}: {1}".format(attribute, value) not in variant.description:
- match = False
- break
-
- if match:
- # found the right variant
- save_attributes_in_variant(variant, combination)
- break
-
- save_attributes_in_template(item, attribute_value_options)
-
- frappe.delete_doc("DocType", "Item Variant")
-
-def save_attributes_in_template(item, attribute_value_options):
- # store attribute in Item Variant Attribute table for template
- template = frappe.get_doc("Item", item)
- template.set("attributes", [{"attribute": attribute} for attribute in attribute_value_options.keys()])
- template.save()
-
-def get_possible_combinations(attribute_value_options):
- possible_combinations = []
-
- for attribute, values in attribute_value_options.items():
- if not possible_combinations:
- for v in values:
- possible_combinations.append({attribute: v})
-
- else:
- for v in values:
- for combination in possible_combinations:
- combination[attribute] = v
-
- return possible_combinations
-
-def save_attributes_in_variant(variant, combination):
- # add data into attributes table
- variant_item = frappe.get_doc("Item", variant.name)
- variant_item.set("attributes", [])
- for attribute, value in combination.items():
- variant_item.append("attributes", {
- "attribute": attribute,
- "attribute_value": value
- })
- variant_item.save()
diff --git a/erpnext/patches/v5_8/__init__.py b/erpnext/patches/v5_8/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v5_8/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v5_8/add_credit_note_print_heading.py b/erpnext/patches/v5_8/add_credit_note_print_heading.py
deleted file mode 100644
index 476cbc8956..0000000000
--- a/erpnext/patches/v5_8/add_credit_note_print_heading.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- for print_heading in (_("Credit Note"), _("Debit Note")):
- if not frappe.db.exists("Print Heading", print_heading):
- frappe.get_doc({
- "doctype": "Print Heading",
- "print_heading": print_heading
- }).insert()
diff --git a/erpnext/patches/v5_8/tax_rule.py b/erpnext/patches/v5_8/tax_rule.py
deleted file mode 100644
index 8da28ba4c9..0000000000
--- a/erpnext/patches/v5_8/tax_rule.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "tax_rule")
-
- customers = frappe.db.sql("""select name, default_taxes_and_charges from tabCustomer where
- ifnull(default_taxes_and_charges, '') != '' """, as_dict=1)
-
- for d in customers:
- if not frappe.db.sql("select name from `tabTax Rule` where customer=%s", d.name):
- tr = frappe.new_doc("Tax Rule")
- tr.tax_type = "Sales"
- tr.customer = d.name
- tr.sales_tax_template = d.default_taxes_and_charges
- tr.save()
-
-
- suppliers = frappe.db.sql("""select name, default_taxes_and_charges from tabSupplier where
- ifnull(default_taxes_and_charges, '') != '' """, as_dict=1)
-
- for d in suppliers:
- if not frappe.db.sql("select name from `tabTax Rule` where supplier=%s", d.name):
- tr = frappe.new_doc("Tax Rule")
- tr.tax_type = "Purchase"
- tr.supplier = d.name
- tr.purchase_tax_template = d.default_taxes_and_charges
- tr.save()
\ No newline at end of file
diff --git a/erpnext/patches/v5_8/update_order_reference_in_return_entries.py b/erpnext/patches/v5_8/update_order_reference_in_return_entries.py
deleted file mode 100644
index 503263834c..0000000000
--- a/erpnext/patches/v5_8/update_order_reference_in_return_entries.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Delivery Note")
- frappe.reload_doctype("Sales Invoice")
- frappe.reload_doctype("Purchase Receipt")
- frappe.reload_doctype("Sales Order Item")
- frappe.reload_doctype("Purchase Order Item")
- frappe.reload_doctype("Purchase Order Item Supplied")
-
- # sales return
- return_entries = list(frappe.db.sql("""
- select dn.name as name, dn_item.name as row_id, dn.return_against,
- dn_item.item_code, "Delivery Note" as doctype
- from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn
- where dn_item.parent=dn.name and dn.is_return=1 and dn.docstatus < 2
- """, as_dict=1))
-
- return_entries += list(frappe.db.sql("""
- select si.name as name, si_item.name as row_id, si.return_against,
- si_item.item_code, "Sales Invoice" as doctype, update_stock
- from `tabSales Invoice Item` si_item, `tabSales Invoice` si
- where si_item.parent=si.name and si.is_return=1 and si.docstatus < 2
- """, as_dict=1))
-
- for d in return_entries:
- ref_field = "against_sales_order" if d.doctype == "Delivery Note" else "sales_order"
- order_details = frappe.db.sql("""
- select {ref_field} as sales_order, so_detail,
- (select transaction_date from `tabSales Order` where name=item.{ref_field}) as sales_order_date
- from `tab{doctype} Item` item
- where
- parent=%s
- and item_code=%s
- and ifnull(so_detail, '') !=''
- order by sales_order_date DESC limit 1
- """.format(ref_field=ref_field, doctype=d.doctype), (d.return_against, d.item_code), as_dict=1)
-
- if order_details:
- frappe.db.sql("""
- update `tab{doctype} Item`
- set {ref_field}=%s, so_detail=%s
- where name=%s
- """.format(doctype=d.doctype, ref_field=ref_field),
- (order_details[0].sales_order, order_details[0].so_detail, d.row_id))
-
- if (d.doctype=="Sales Invoice" and d.update_stock) or d.doctype=="Delivery Note":
- doc = frappe.get_doc(d.doctype, d.name)
- doc.update_reserved_qty()
-
- if d.doctype=="Sales Invoice":
- doc.status_updater = []
- doc.update_status_updater_args()
-
- doc.update_prevdoc_status()
-
- #--------------------------
- # purchase return
- return_entries = frappe.db.sql("""
- select pr.name as name, pr_item.name as row_id, pr.return_against, pr_item.item_code
- from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr
- where pr_item.parent=pr.name and pr.is_return=1 and pr.docstatus < 2
- """, as_dict=1)
-
- for d in return_entries:
- order_details = frappe.db.sql("""
- select prevdoc_docname as purchase_order, prevdoc_detail_docname as po_detail,
- (select transaction_date from `tabPurchase Order` where name=item.prevdoc_detail_docname) as purchase_order_date
- from `tabPurchase Receipt Item` item
- where
- parent=%s
- and item_code=%s
- and ifnull(prevdoc_detail_docname, '') !=''
- and ifnull(prevdoc_doctype, '') = 'Purchase Order' and ifnull(prevdoc_detail_docname, '') != ''
- order by purchase_order_date DESC limit 1
- """, (d.return_against, d.item_code), as_dict=1)
-
- if order_details:
- frappe.db.sql("""
- update `tabPurchase Receipt Item`
- set prevdoc_doctype='Purchase Order', prevdoc_docname=%s, prevdoc_detail_docname=%s
- where name=%s
- """, (order_details[0].purchase_order, order_details[0].po_detail, d.row_id))
-
- pr = frappe.get_doc("Purchase Receipt", d.name)
- pr.update_ordered_and_reserved_qty()
- pr.update_prevdoc_status()
-
diff --git a/erpnext/patches/v6_0/__init__.py b/erpnext/patches/v6_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_0/default_activity_rate.py b/erpnext/patches/v6_0/default_activity_rate.py
deleted file mode 100644
index cfbfb723bc..0000000000
--- a/erpnext/patches/v6_0/default_activity_rate.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("projects", "doctype", "activity_cost")
-
- for cost in frappe.db.get_list("Activity Cost", filters = {"employee": ""},
- fields = ("name", "activity_type", "costing_rate", "billing_rate")):
- activity_type = frappe.get_doc("Activity Type", cost.activity_type)
- activity_type.costing_rate = cost.costing_rate
- activity_type.billing_rate = cost.billing_rate
- activity_type.save()
-
- frappe.delete_doc("Activity Cost", cost.name)
diff --git a/erpnext/patches/v6_0/fix_outstanding_amount.py b/erpnext/patches/v6_0/fix_outstanding_amount.py
deleted file mode 100644
index 0de689074f..0000000000
--- a/erpnext/patches/v6_0/fix_outstanding_amount.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
-
-def execute():
- for dt, party_field, account_field in (("Sales Invoice", "customer", "debit_to"),
- ("Purchase Invoice", "supplier", "credit_to")):
-
- wrong_invoices = frappe.db.sql("""select name, {0} as account from `tab{1}`
- where docstatus=1 and ifnull({2}, '')=''""".format(account_field, dt, party_field))
-
- for invoice, account in wrong_invoices:
- update_outstanding_amt(account, party_field.title(), None, dt, invoice)
\ No newline at end of file
diff --git a/erpnext/patches/v6_0/fix_planned_qty.py b/erpnext/patches/v6_0/fix_planned_qty.py
deleted file mode 100644
index cf7b429249..0000000000
--- a/erpnext/patches/v6_0/fix_planned_qty.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
-
-def execute():
- for item_code, warehouse in frappe.db.sql("""select distinct production_item, fg_warehouse
- from `tabWork Order`"""):
- if frappe.db.exists("Item", item_code) and frappe.db.exists("Warehouse", warehouse):
- update_bin_qty(item_code, warehouse, {
- "planned_qty": get_planned_qty(item_code, warehouse)
- })
diff --git a/erpnext/patches/v6_0/multi_currency.py b/erpnext/patches/v6_0/multi_currency.py
deleted file mode 100644
index b4c37fc253..0000000000
--- a/erpnext/patches/v6_0/multi_currency.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # Reload doctype
- for dt in ("Account", "GL Entry", "Journal Entry",
- "Journal Entry Account", "Sales Invoice", "Purchase Invoice", "Customer", "Supplier"):
- frappe.reload_doctype(dt)
-
- company_list = frappe.get_all("Company", fields=["name", "default_currency", "default_receivable_account"])
- for company in company_list:
-
- # update currency in account and gl entry as per company currency
- frappe.db.sql("""update `tabAccount` set account_currency = %s
- where ifnull(account_currency, '') = '' and company=%s""", (company.default_currency, company.name))
-
- # update newly introduced field's value in sales / purchase invoice
- frappe.db.sql("""
- update
- `tabSales Invoice`
- set
- base_paid_amount=paid_amount,
- base_write_off_amount=write_off_amount,
- party_account_currency=%s
- where company=%s
- """, (company.default_currency, company.name))
-
- frappe.db.sql("""
- update
- `tabPurchase Invoice`
- set
- base_write_off_amount=write_off_amount,
- party_account_currency=%s
- where company=%s
- """, (company.default_currency, company.name))
-
- # update exchange rate, debit/credit in account currency in Journal Entry
- frappe.db.sql("""
- update `tabJournal Entry Account` jea
- set exchange_rate=1,
- debit_in_account_currency=debit,
- credit_in_account_currency=credit,
- account_type=(select account_type from `tabAccount` where name=jea.account)
- """)
-
- frappe.db.sql("""
- update `tabJournal Entry Account` jea, `tabJournal Entry` je
- set account_currency=%s
- where jea.parent = je.name and je.company=%s
- """, (company.default_currency, company.name))
-
- # update debit/credit in account currency in GL Entry
- frappe.db.sql("""
- update
- `tabGL Entry`
- set
- debit_in_account_currency=debit,
- credit_in_account_currency=credit,
- account_currency=%s
- where
- company=%s
- """, (company.default_currency, company.name))
diff --git a/erpnext/patches/v6_0/set_default_title.py b/erpnext/patches/v6_0/set_default_title.py
deleted file mode 100644
index cceff3f480..0000000000
--- a/erpnext/patches/v6_0/set_default_title.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Quotation")
- frappe.db.sql("""update tabQuotation set title = customer_name""")
-
- frappe.reload_doctype("Sales Order")
- frappe.db.sql("""update `tabSales Order` set title = customer_name""")
-
- frappe.reload_doctype("Delivery Note")
- frappe.db.sql("""update `tabDelivery Note` set title = customer_name""")
-
- frappe.reload_doctype("Material Request")
- frappe.db.sql("""update `tabMaterial Request` set title = material_request_type""")
-
- frappe.reload_doctype("Supplier Quotation")
- frappe.db.sql("""update `tabSupplier Quotation` set title = supplier_name""")
-
- frappe.reload_doctype("Purchase Order")
- frappe.db.sql("""update `tabPurchase Order` set title = supplier_name""")
-
- frappe.reload_doctype("Purchase Receipt")
- frappe.db.sql("""update `tabPurchase Receipt` set title = supplier_name""")
-
- frappe.reload_doctype("Purchase Invoice")
- frappe.db.sql("""update `tabPurchase Invoice` set title = supplier_name""")
-
- frappe.reload_doctype("Stock Entry")
- frappe.db.sql("""update `tabStock Entry` set title = purpose""")
-
- frappe.reload_doctype("Sales Invoice")
- frappe.db.sql("""update `tabSales Invoice` set title = customer_name""")
-
- frappe.reload_doctype("Expense Claim")
- frappe.db.sql("""update `tabExpense Claim` set title = employee_name""")
diff --git a/erpnext/patches/v6_10/__init__.py b/erpnext/patches/v6_10/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_10/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_10/email_digest_default_quote.py b/erpnext/patches/v6_10/email_digest_default_quote.py
deleted file mode 100644
index 6139f1a88a..0000000000
--- a/erpnext/patches/v6_10/email_digest_default_quote.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Email Digest")
- frappe.db.sql("update `tabEmail Digest` set add_quote = 1")
diff --git a/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py b/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py
deleted file mode 100644
index d7f72b5880..0000000000
--- a/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0
- where delivered_by_supplier=1 and docstatus=1""")
-
- drop_ship_pos = frappe.db.sql("""select distinct parent from `tabPurchase Order Item`
- where delivered_by_supplier=1 and docstatus=1""")
-
- for po in drop_ship_pos:
- invoices = frappe.db.sql("""select distinct parent from `tabPurchase Invoice Item`
- where purchase_order=%s and docstatus=1""", po[0])
- if invoices:
- for inv in invoices:
- frappe.get_doc("Purchase Invoice", inv[0]).update_qty(update_modified=False)
- else:
- frappe.db.sql("""update `tabPurchase Order` set per_billed=0 where name=%s""", po[0])
\ No newline at end of file
diff --git a/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py b/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py
deleted file mode 100644
index 9a53b7f5d3..0000000000
--- a/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Sales Order Item")
- for so_name in frappe.db.sql("""select distinct parent from `tabSales Order Item`
- where delivered_by_supplier=1 and docstatus=1"""):
- so = frappe.get_doc("Sales Order", so_name[0])
- so.update_delivery_status()
- so.set_status(update=True, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v6_10/fix_jv_total_amount.py b/erpnext/patches/v6_10/fix_jv_total_amount.py
deleted file mode 100644
index 42cb9e9e15..0000000000
--- a/erpnext/patches/v6_10/fix_jv_total_amount.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-# patch all for-print field (total amount) in Journal Entry in 2015
-def execute():
- for je in frappe.get_all("Journal Entry", filters={"creation": (">", "2015-01-01")}):
- je = frappe.get_doc("Journal Entry", je.name)
- original = je.total_amount
-
- je.set_print_format_fields()
-
- if je.total_amount != original:
- je.db_set("total_amount", je.total_amount, update_modified=False)
- je.db_set("total_amount_in_words", je.total_amount_in_words, update_modified=False)
diff --git a/erpnext/patches/v6_10/fix_ordered_received_billed.py b/erpnext/patches/v6_10/fix_ordered_received_billed.py
deleted file mode 100644
index c81a20ec54..0000000000
--- a/erpnext/patches/v6_10/fix_ordered_received_billed.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- not_null_patch_date = frappe.db.sql("""select date(creation) from `tabPatch Log` where patch='frappe.patches.v6_9.int_float_not_null'""")
- if not not_null_patch_date:
- return
-
- not_null_patch_date = not_null_patch_date[0][0]
-
- for doctype in ("Purchase Invoice", "Sales Invoice", "Purchase Order", "Delivery Note", "Installation Note", "Delivery Note", "Purchase Receipt"):
- for name in frappe.db.sql_list("""select name from `tab{doctype}`
- where docstatus > 0 and (date(creation) >= %(patch_date)s or date(modified) >= %(patch_date)s)""".format(doctype=doctype),
- {"patch_date": not_null_patch_date}):
-
- doc = frappe.get_doc(doctype, name)
- doc.update_qty(update_modified=False)
diff --git a/erpnext/patches/v6_12/__init__.py b/erpnext/patches/v6_12/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py b/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
deleted file mode 100644
index fb5eab4e05..0000000000
--- a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
+++ /dev/null
@@ -1,175 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-"""
-This patch is written to fix Stock Ledger Entries and GL Entries
-against Delivery Notes and Sales Invoice where Target Warehouse has been set wrongly
-due to User Permissions on Warehouse.
-
-This cannot be run automatically because we can't take a call that
-Target Warehouse has been set purposefully or by mistake.
-Thats why we left it to the users to take the call, and manually run the patch.
-
-This patch has 2 main functions, `check()` and `repost()`.
-- Run `check` function, to list out all the Sales Orders, Delivery Notes
- and Sales Invoice with Target Warehouse.
-- Run `repost` function to remove the Target Warehouse value and repost SLE and GLE again.
-
-To execute this patch run following commands from frappe-bench directory:
-```
- bench --site [your-site-name] execute erpnext.patches.v6_12.repost_entries_with_target_warehouse.check
- bench --site [your-site-name] backup
- bench --site [your-site-name] execute erpnext.patches.v6_12.repost_entries_with_target_warehouse.repost
-```
-
-Exception Handling:
-While reposting, if you get any exception, it will printed on screen.
-Mostly it can be due to negative stock issue. If that is the case, follow these steps
- - Ensure that stock is available for those items in the mentioned warehouse on the date mentioned in the error
- - Execute `repost` funciton again
-"""
-
-def check():
- so_list = get_affected_sales_order()
- dn_list = get_affected_delivery_notes()
- si_list = get_affected_sales_invoice()
-
- if so_list or dn_list or si_list:
- print("Entries with Target Warehouse:")
-
- if so_list:
- print("Sales Order")
- print(so_list)
-
- if dn_list:
- print("Delivery Notes")
- print([d.name for d in dn_list])
-
- if si_list:
- print("Sales Invoice")
- print([d.name for d in si_list])
-
-
-def repost():
- dn_failed_list, si_failed_list = [], []
- repost_dn(dn_failed_list)
- repost_si(si_failed_list)
- repost_so()
- frappe.db.commit()
-
- if dn_failed_list:
- print("-"*40)
- print("Delivery Note Failed to Repost")
- print(dn_failed_list)
-
- if si_failed_list:
- print("-"*40)
- print("Sales Invoice Failed to Repost")
- print(si_failed_list)
- print()
-
- print("""
-If above Delivery Notes / Sales Invoice failed due to negative stock, follow these steps:
- - Ensure that stock is available for those items in the mentioned warehouse on the date mentioned in the error
- - Run this patch again
-""")
-
-def repost_dn(dn_failed_list):
- dn_list = get_affected_delivery_notes()
-
- if dn_list:
- print("-"*40)
- print("Reposting Delivery Notes")
-
- for dn in dn_list:
- if dn.docstatus == 0:
- continue
-
- print(dn.name)
-
- try:
- dn_doc = frappe.get_doc("Delivery Note", dn.name)
- dn_doc.docstatus = 2
- dn_doc.update_prevdoc_status()
- dn_doc.update_stock_ledger()
- dn_doc.cancel_packing_slips()
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type='Delivery Note' and voucher_no=%s""", dn.name)
-
- frappe.db.sql("update `tabDelivery Note Item` set target_warehouse='' where parent=%s", dn.name)
- dn_doc = frappe.get_doc("Delivery Note", dn.name)
- dn_doc.docstatus = 1
- dn_doc.on_submit()
- frappe.db.commit()
- except Exception:
- dn_failed_list.append(dn.name)
- frappe.local.stockledger_exceptions = None
- print(frappe.get_traceback())
- frappe.db.rollback()
-
- frappe.db.sql("update `tabDelivery Note Item` set target_warehouse='' where docstatus=0")
-
-def repost_si(si_failed_list):
- si_list = get_affected_sales_invoice()
-
- if si_list:
- print("-"*40)
- print("Reposting Sales Invoice")
-
- for si in si_list:
- if si.docstatus == 0:
- continue
-
- print(si.name)
-
- try:
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- si_doc.docstatus = 2
- si_doc.update_stock_ledger()
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
-
- frappe.db.sql("update `tabSales Invoice Item` set target_warehouse='' where parent=%s", si.name)
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- si_doc.docstatus = 1
- si_doc.update_stock_ledger()
- si_doc.make_gl_entries()
- frappe.db.commit()
- except Exception:
- si_failed_list.append(si.name)
- frappe.local.stockledger_exceptions = None
- print(frappe.get_traceback())
- frappe.db.rollback()
-
- frappe.db.sql("update `tabSales Invoice Item` set target_warehouse='' where docstatus=0")
-
-def repost_so():
- so_list = get_affected_sales_order()
-
- frappe.db.sql("update `tabSales Order Item` set target_warehouse=''")
-
- if so_list:
- print("-"*40)
- print("Sales Order reposted")
-
-
-def get_affected_delivery_notes():
- return frappe.db.sql("""select distinct dn.name, dn.docstatus
- from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
- where dn.name=dn_item.parent and dn.docstatus < 2
- and dn_item.target_warehouse is not null and dn_item.target_warehouse != ''
- order by dn.posting_date asc""", as_dict=1)
-
-def get_affected_sales_invoice():
- return frappe.db.sql("""select distinct si.name, si.docstatus
- from `tabSales Invoice` si, `tabSales Invoice Item` si_item
- where si.name=si_item.parent and si.docstatus < 2 and si.update_stock=1
- and si_item.target_warehouse is not null and si_item.target_warehouse != ''
- order by si.posting_date asc""", as_dict=1)
-
-def get_affected_sales_order():
- return frappe.db.sql_list("""select distinct parent from `tabSales Order Item`
- where target_warehouse is not null and target_warehouse != '' and docstatus <2""")
\ No newline at end of file
diff --git a/erpnext/patches/v6_12/set_overdue_tasks.py b/erpnext/patches/v6_12/set_overdue_tasks.py
deleted file mode 100644
index 7dbb8ba8b6..0000000000
--- a/erpnext/patches/v6_12/set_overdue_tasks.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Task")
-
- from erpnext.projects.doctype.task.task import set_tasks_as_overdue
- set_tasks_as_overdue()
diff --git a/erpnext/patches/v6_16/__init__.py b/erpnext/patches/v6_16/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_16/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_16/create_manufacturer_records.py b/erpnext/patches/v6_16/create_manufacturer_records.py
deleted file mode 100644
index 5ae65f0660..0000000000
--- a/erpnext/patches/v6_16/create_manufacturer_records.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cstr
-
-def execute():
- frappe.reload_doc("stock", "doctype", "manufacturer")
- frappe.reload_doctype("Item")
-
- for d in frappe.db.sql("""select distinct manufacturer from tabItem
- where ifnull(manufacturer, '') != '' and disabled=0"""):
- manufacturer_name = cstr(d[0]).strip()
- if manufacturer_name and not frappe.db.exists("Manufacturer", manufacturer_name):
- man = frappe.new_doc("Manufacturer")
- man.short_name = manufacturer_name
- man.full_name = manufacturer_name
- man.save()
diff --git a/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py b/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py
deleted file mode 100644
index 481f13005b..0000000000
--- a/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Delivery Note", "Purchase Receipt"):
- frappe.reload_doctype(dt)
- frappe.reload_doctype(dt + " Item")
-
- # Update billed_amt in DN and PR which are not against any order
- for d in frappe.db.sql("""select name from `tabDelivery Note Item` item
- where (so_detail is null or so_detail = '') and docstatus=1""", as_dict=1):
-
- billed_amt = frappe.db.sql("""select sum(amount) from `tabSales Invoice Item`
- where dn_detail=%s and docstatus=1""", d.name)
- billed_amt = billed_amt and billed_amt[0][0] or 0
- frappe.db.set_value("Delivery Note Item", d.name, "billed_amt", billed_amt, update_modified=False)
-
- frappe.db.commit()
-
- # Update billed_amt in DN and PR which are not against any order
- for d in frappe.db.sql("""select name from `tabPurchase Receipt Item` item
- where (purchase_order_item is null or purchase_order_item = '') and docstatus=1""", as_dict=1):
-
- billed_amt = frappe.db.sql("""select sum(amount) from `tabPurchase Invoice Item`
- where pr_detail=%s and docstatus=1""", d.name)
- billed_amt = billed_amt and billed_amt[0][0] or 0
- frappe.db.set_value("Purchase Receipt Item", d.name, "billed_amt", billed_amt, update_modified=False)
-
- frappe.db.commit()
-
- for dt in ("Delivery Note", "Purchase Receipt"):
- # Update billed amt which are against order or invoice
- # Update billing status for all
- for d in frappe.db.sql("select name from `tab{0}` where docstatus=1".format(dt), as_dict=1):
- doc = frappe.get_doc(dt, d.name)
- doc.update_billing_status(update_modified=False)
- doc.set_status(update=True, update_modified=False)
-
- frappe.db.commit()
diff --git a/erpnext/patches/v6_19/__init__.py b/erpnext/patches/v6_19/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_19/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_19/comment_feed_communication.py b/erpnext/patches/v6_19/comment_feed_communication.py
deleted file mode 100644
index bc41c2d8ff..0000000000
--- a/erpnext/patches/v6_19/comment_feed_communication.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.patches.v6_19.comment_feed_communication import update_timeline_doc_for
-
-def execute():
- for doctype in ("Customer", "Supplier", "Employee", "Project"):
- update_timeline_doc_for(doctype)
diff --git a/erpnext/patches/v6_2/__init__.py b/erpnext/patches/v6_2/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_2/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py b/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py
deleted file mode 100644
index b0cfc3d3bf..0000000000
--- a/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # remove missing lead
- for customer in frappe.db.sql_list("""select name from `tabCustomer`
- where ifnull(lead_name, '')!='' and not exists (select name from `tabLead` where name=`tabCustomer`.lead_name)"""):
- frappe.db.set_value("Customer", customer, "lead_name", None)
-
- # remove missing default taxes
- for customer in frappe.db.sql_list("""select name from `tabCustomer`
- where ifnull(default_taxes_and_charges, '')!='' and not exists (
- select name from `tabSales Taxes and Charges Template` where name=`tabCustomer`.default_taxes_and_charges
- )"""):
- c = frappe.get_doc("Customer", customer)
- c.default_taxes_and_charges = None
- c.save()
-
- for supplier in frappe.db.sql_list("""select name from `tabSupplier`
- where ifnull(default_taxes_and_charges, '')!='' and not exists (
- select name from `tabPurchase Taxes and Charges Template` where name=`tabSupplier`.default_taxes_and_charges
- )"""):
- c = frappe.get_doc("Supplier", supplier)
- c.default_taxes_and_charges = None
- c.save()
diff --git a/erpnext/patches/v6_2/remove_newsletter_duplicates.py b/erpnext/patches/v6_2/remove_newsletter_duplicates.py
deleted file mode 100644
index f9d15475d1..0000000000
--- a/erpnext/patches/v6_2/remove_newsletter_duplicates.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- duplicates = frappe.db.sql("""select email_group, email, count(name)
- from `tabEmail Group Member`
- group by email_group, email
- having count(name) > 1""")
-
- # delete all duplicates except 1
- for email_group, email, count in duplicates:
- frappe.db.sql("""delete from `tabEmail Group Member`
- where email_group=%s and email=%s limit %s""", (email_group, email, count-1))
diff --git a/erpnext/patches/v6_20/__init__.py b/erpnext/patches/v6_20/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_20/set_party_account_currency_in_orders.py b/erpnext/patches/v6_20/set_party_account_currency_in_orders.py
deleted file mode 100644
index ae7ad9592d..0000000000
--- a/erpnext/patches/v6_20/set_party_account_currency_in_orders.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Sales Order", "Purchase Order"):
- frappe.reload_doctype(doctype)
-
- for order in frappe.db.sql("""select name, {0} as party from `tab{1}`
- where advance_paid > 0 and docstatus=1"""
- .format(("customer" if doctype=="Sales Order" else "supplier"), doctype), as_dict=1):
-
- party_account_currency = frappe.db.get_value("Journal Entry Account", {
- "reference_type": doctype,
- "reference_name": order.name,
- "party": order.party,
- "docstatus": 1,
- "is_advance": "Yes"
- }, "account_currency")
-
- frappe.db.set_value(doctype, order.name, "party_account_currency", party_account_currency)
-
\ No newline at end of file
diff --git a/erpnext/patches/v6_20x/__init__.py b/erpnext/patches/v6_20x/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_20x/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_20x/remove_customer_supplier_roles.py b/erpnext/patches/v6_20x/remove_customer_supplier_roles.py
deleted file mode 100644
index a651576887..0000000000
--- a/erpnext/patches/v6_20x/remove_customer_supplier_roles.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("buying", "doctype", "request_for_quotation_supplier")
- frappe.reload_doc("buying", "doctype", "request_for_quotation_item")
- frappe.reload_doc("buying", "doctype", "request_for_quotation")
- frappe.reload_doc("projects", "doctype", "timesheet")
-
- for role in ('Customer', 'Supplier'):
- frappe.db.sql('''delete from `tabHas Role`
- where role=%s and parent in ("Administrator", "Guest")''', role)
-
- if not frappe.db.sql('select name from `tabHas Role` where role=%s', role):
-
- # delete DocPerm
- for doctype in frappe.db.sql('select parent from tabDocPerm where role=%s', role):
- d = frappe.get_doc("DocType", doctype[0])
- d.permissions = [p for p in d.permissions if p.role != role]
- d.save()
-
- # delete Role
- frappe.delete_doc_if_exists('Role', role)
diff --git a/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py b/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py
deleted file mode 100644
index d440c6859e..0000000000
--- a/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Holiday List")
-
- default_holiday_list = frappe.db.get_value("Holiday List", {"is_default": 1})
- if default_holiday_list:
- for company in frappe.get_all("Company", fields=["name", "default_holiday_list"]):
- if not company.default_holiday_list:
- frappe.db.set_value("Company", company.name, "default_holiday_list", default_holiday_list)
-
-
- fiscal_years = frappe._dict((fy.name, fy) for fy in frappe.get_all("Fiscal Year", fields=["name", "year_start_date", "year_end_date"]))
-
- for holiday_list in frappe.get_all("Holiday List", fields=["name", "fiscal_year"]):
- fy = fiscal_years[holiday_list.fiscal_year]
- frappe.db.set_value("Holiday List", holiday_list.name, "from_date", fy.year_start_date)
- frappe.db.set_value("Holiday List", holiday_list.name, "to_date", fy.year_end_date)
diff --git a/erpnext/patches/v6_20x/rename_project_name_to_project.py b/erpnext/patches/v6_20x/rename_project_name_to_project.py
deleted file mode 100644
index 49ec9d22bc..0000000000
--- a/erpnext/patches/v6_20x/rename_project_name_to_project.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
-
- doc_list = ["Work Order", "BOM", "Purchase Invoice Item", "Sales Invoice",
- "Purchase Order Item", "Stock Entry", "Delivery Note", "Sales Order",
- "Purchase Receipt Item", "Supplier Quotation Item"]
-
- for doctype in doc_list:
- frappe.reload_doctype(doctype)
- rename_field(doctype, "project_name", "project")
-
\ No newline at end of file
diff --git a/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py b/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py
deleted file mode 100644
index 8369fea317..0000000000
--- a/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-from erpnext.stock.stock_balance import repost
-
-def execute():
- if cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")):
- repost(only_actual=True)
\ No newline at end of file
diff --git a/erpnext/patches/v6_20x/set_compact_print.py b/erpnext/patches/v6_20x/set_compact_print.py
deleted file mode 100644
index 495407f0e0..0000000000
--- a/erpnext/patches/v6_20x/set_compact_print.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.setup.install import create_compact_item_print_custom_field
-
-def execute():
- create_compact_item_print_custom_field()
- frappe.db.set_value("Print Settings", None, "compact_item_print", 1)
diff --git a/erpnext/patches/v6_20x/update_product_bundle_description.py b/erpnext/patches/v6_20x/update_product_bundle_description.py
deleted file mode 100644
index 1fac44b001..0000000000
--- a/erpnext/patches/v6_20x/update_product_bundle_description.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import sanitize_html
-
-def execute():
- for product_bundle in frappe.get_all('Product Bundle'):
- doc = frappe.get_doc('Product Bundle', product_bundle.name)
- for item in doc.items:
- if item.description:
- description = sanitize_html(item.description)
- item.db_set('description', description, update_modified=False)
diff --git a/erpnext/patches/v6_21/__init__.py b/erpnext/patches/v6_21/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_21/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_21/fix_reorder_level.py b/erpnext/patches/v6_21/fix_reorder_level.py
deleted file mode 100644
index 82a35ebab1..0000000000
--- a/erpnext/patches/v6_21/fix_reorder_level.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-from erpnext.stock.doctype.item.item import DuplicateReorderRows
-
-def execute():
- if frappe.db.has_column("Item", "re_order_level"):
- for item in frappe.db.sql("""select name, default_warehouse, re_order_level, re_order_qty
- from tabItem
- where ifnull(re_order_level, 0) != 0
- and ifnull(re_order_qty, 0) != 0""", as_dict=1):
-
- item_doc = frappe.get_doc("Item", item.name)
- item_doc.append("reorder_levels", {
- "warehouse": item.default_warehouse,
- "warehouse_reorder_level": item.re_order_level,
- "warehouse_reorder_qty": item.re_order_qty,
- "material_request_type": "Purchase"
- })
-
- try:
- item_doc.save()
- except DuplicateReorderRows:
- pass
diff --git a/erpnext/patches/v6_21/rename_material_request_fields.py b/erpnext/patches/v6_21/rename_material_request_fields.py
deleted file mode 100644
index 07be27a5d6..0000000000
--- a/erpnext/patches/v6_21/rename_material_request_fields.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'material_request_item')
- rename_field("Material Request Item", "sales_order_no", "sales_order")
-
- frappe.reload_doc('support', 'doctype', 'maintenance_schedule_item')
- rename_field("Maintenance Schedule Item", "prevdoc_docname", "sales_order")
-
\ No newline at end of file
diff --git a/erpnext/patches/v6_23/__init__.py b/erpnext/patches/v6_23/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_23/update_stopped_status_to_closed.py b/erpnext/patches/v6_23/update_stopped_status_to_closed.py
deleted file mode 100644
index 79d1e0ac30..0000000000
--- a/erpnext/patches/v6_23/update_stopped_status_to_closed.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Sales Order", "Purchase Order"):
- frappe.db.sql("update `tab{0}` set status='Closed' where status='Stopped'".format(dt))
\ No newline at end of file
diff --git a/erpnext/patches/v6_24/__init__.py b/erpnext/patches/v6_24/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py b/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py
deleted file mode 100644
index 1dd8083c7c..0000000000
--- a/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Purchase Order")
-
- if not frappe.db.has_column("Purchase Order", "shipping_address"):
- return
-
- if not frappe.db.has_column("Purchase Order", "customer_address"):
- return
-
- frappe.db.sql("""update `tabPurchase Order` set shipping_address=customer_address,
- shipping_address_display=customer_address_display""")
-
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v6_24/set_recurring_id.py b/erpnext/patches/v6_24/set_recurring_id.py
deleted file mode 100644
index 527a2fd3d9..0000000000
--- a/erpnext/patches/v6_24/set_recurring_id.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ('Sales Order', 'Purchase Order', 'Sales Invoice',
- 'Purchase Invoice'):
- frappe.reload_doctype(doctype)
- frappe.db.sql('''update `tab{0}` set submit_on_creation=1, notify_by_email=1
- where is_recurring=1'''.format(doctype))
- frappe.db.sql('''update `tab{0}` set notify_by_email=1
- where is_recurring=1'''.format(doctype))
- frappe.db.sql('''update `tab{0}` set recurring_id = name
- where is_recurring=1 and ifnull(recurring_id, '') = "" '''.format(doctype))
diff --git a/erpnext/patches/v6_27/__init__.py b/erpnext/patches/v6_27/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_27/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_27/fix_recurring_order_status.py b/erpnext/patches/v6_27/fix_recurring_order_status.py
deleted file mode 100644
index 5843c9fbe5..0000000000
--- a/erpnext/patches/v6_27/fix_recurring_order_status.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doc in (
- {
- "doctype": "Sales Order",
- "stock_doctype": "Delivery Note",
- "invoice_doctype": "Sales Invoice",
- "stock_doctype_ref_field": "against_sales_order",
- "invoice_ref_field": "sales_order",
- "qty_field": "delivered_qty"
- },
- {
- "doctype": "Purchase Order",
- "stock_doctype": "Purchase Receipt",
- "invoice_doctype": "Purchase Invoice",
- "stock_doctype_ref_field": "prevdoc_docname",
- "invoice_ref_field": "purchase_order",
- "qty_field": "received_qty"
- }):
-
- order_list = frappe.db.sql("""select name from `tab{0}`
- where docstatus=1 and is_recurring=1
- and ifnull(recurring_id, '') != name and creation >= '2016-01-25'"""
- .format(doc["doctype"]), as_dict=1)
-
- for order in order_list:
- frappe.db.sql("""update `tab{0} Item`
- set {1}=0, billed_amt=0 where parent=%s""".format(doc["doctype"],
- doc["qty_field"]), order.name)
-
- # Check against Delivery Note and Purchase Receipt
- stock_doc_list = frappe.db.sql("""select distinct parent from `tab{0} Item`
- where docstatus=1 and ifnull({1}, '')=%s"""
- .format(doc["stock_doctype"], doc["stock_doctype_ref_field"]), order.name)
-
- if stock_doc_list:
- for dn in stock_doc_list:
- frappe.get_doc(doc["stock_doctype"], dn[0]).update_qty(update_modified=False)
-
- # Check against Invoice
- invoice_list = frappe.db.sql("""select distinct parent from `tab{0} Item`
- where docstatus=1 and ifnull({1}, '')=%s"""
- .format(doc["invoice_doctype"], doc["invoice_ref_field"]), order.name)
-
- if invoice_list:
- for dn in invoice_list:
- frappe.get_doc(doc["invoice_doctype"], dn[0]).update_qty(update_modified=False)
-
- frappe.get_doc(doc["doctype"], order.name).set_status(update=True, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v6_3/__init__.py b/erpnext/patches/v6_3/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_3/convert_applicable_territory.py b/erpnext/patches/v6_3/convert_applicable_territory.py
deleted file mode 100644
index 231a483ea2..0000000000
--- a/erpnext/patches/v6_3/convert_applicable_territory.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "price_list_country")
- frappe.reload_doc("accounts", "doctype", "shipping_rule_country")
- frappe.reload_doctype("Price List")
- frappe.reload_doctype("Shipping Rule")
- frappe.reload_doctype("shopping_cart", "doctype", "shopping_cart_settings")
-
- # for price list
- countries = frappe.db.sql_list("select name from tabCountry")
-
- for doctype in ("Price List", "Shipping Rule"):
- for at in frappe.db.sql("""select name, parent, territory from `tabApplicable Territory` where
- parenttype = %s """, doctype, as_dict=True):
- if at.territory in countries:
- parent = frappe.get_doc(doctype, at.parent)
- if not parent.countries:
- parent.append("countries", {"country": at.territory})
- parent.save()
-
-
- frappe.delete_doc("DocType", "Applicable Territory")
diff --git a/erpnext/patches/v6_4/__init__.py b/erpnext/patches/v6_4/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_4/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_4/email_digest_update.py b/erpnext/patches/v6_4/email_digest_update.py
deleted file mode 100644
index 8342b7fce6..0000000000
--- a/erpnext/patches/v6_4/email_digest_update.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Email Digest")
- frappe.db.sql("""update `tabEmail Digest` set expense_year_to_date =
- income_year_to_date""")
-
- if frappe.db.exists("Email Digest", "Scheduler Errors"):
- frappe.delete_doc("Email Digest", "Scheduler Errors")
diff --git a/erpnext/patches/v6_4/fix_duplicate_bins.py b/erpnext/patches/v6_4/fix_duplicate_bins.py
deleted file mode 100644
index 77d05273e8..0000000000
--- a/erpnext/patches/v6_4/fix_duplicate_bins.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import repost_stock
-
-def execute():
- bins = frappe.db.sql("""select item_code, warehouse, count(*) from `tabBin`
- group by item_code, warehouse having count(*) > 1""", as_dict=True)
-
- for d in bins:
- try:
- frappe.db.sql("delete from tabBin where item_code=%s and warehouse=%s", (d.item_code, d.warehouse))
-
- repost_stock(d.item_code, d.warehouse, allow_zero_rate=True, only_actual=False, only_bin=True)
-
- frappe.db.commit()
- except:
- frappe.db.rollback()
\ No newline at end of file
diff --git a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py b/erpnext/patches/v6_4/fix_expense_included_in_valuation.py
deleted file mode 100644
index 7ed15ab010..0000000000
--- a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.utils import cstr
-
-def execute():
- for company in frappe.db.sql("select name, expenses_included_in_valuation from tabCompany", as_dict=1):
- frozen_date = get_frozen_date(company.name, company.expenses_included_in_valuation)
-
- # Purchase Invoices after frozen date
- # which are not against Receipt, but valuation related tax is there
- pi_list = frappe.db.sql("""
- select distinct pi.name
- from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
- where
- pi.name = pi_item.parent
- and pi.company = %s
- and pi.posting_date > %s
- and pi.docstatus = 1
- and pi.is_opening = 'No'
- and (pi_item.item_tax_amount is not null and pi_item.item_tax_amount > 0)
- and (pi_item.purchase_receipt is null or pi_item.purchase_receipt = '')
- and (pi_item.item_code is not null and pi_item.item_code != '')
- and exists(select name from `tabItem` where name=pi_item.item_code and is_stock_item=1)
- """, (company.name, frozen_date), as_dict=1)
-
- for pi in pi_list:
- # Check whether gle exists for Expenses Included in Valuation account against the PI
- gle_for_expenses_included_in_valuation = frappe.db.sql("""select name from `tabGL Entry`
- where voucher_type='Purchase Invoice' and voucher_no=%s and account=%s""",
- (pi.name, company.expenses_included_in_valuation))
-
- if gle_for_expenses_included_in_valuation:
- print(pi.name)
-
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type='Purchase Invoice' and voucher_no=%s""", pi.name)
-
- purchase_invoice = frappe.get_doc("Purchase Invoice", pi.name)
-
- # some old entries have missing expense accounts
- if purchase_invoice.against_expense_account:
- expense_account = purchase_invoice.against_expense_account.split(",")
- if len(expense_account) == 1:
- expense_account = expense_account[0]
- for item in purchase_invoice.items:
- if not item.expense_account:
- item.db_set("expense_account", expense_account, update_modified=False)
-
- purchase_invoice.make_gl_entries()
-
-def get_frozen_date(company, account):
- # Accounting frozen upto
- accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
-
- # Last adjustment entry to correct Expenses Included in Valuation account balance
- last_adjustment_entry = frappe.db.sql("""select posting_date from `tabGL Entry`
- where account=%s and company=%s and voucher_type = 'Journal Entry'
- order by posting_date desc limit 1""", (account, company))
-
- last_adjustment_date = cstr(last_adjustment_entry[0][0]) if last_adjustment_entry else None
-
- # Last period closing voucher
- last_closing_entry = frappe.db.sql("""select posting_date from `tabGL Entry`
- where company=%s and voucher_type = 'Period Closing Voucher'
- order by posting_date desc limit 1""", company)
-
- last_closing_date = cstr(last_closing_entry[0][0]) if last_closing_entry else None
-
- frozen_date = max([accounts_frozen_upto, last_adjustment_date, last_closing_date])
-
- return frozen_date or '1900-01-01'
diff --git a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py b/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
deleted file mode 100644
index b53412d7eb..0000000000
--- a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Sales Invoice Advance")
- frappe.reload_doctype("Purchase Invoice Advance")
-
- je_rows = frappe.db.sql("""
- select name, parent, reference_type, reference_name, debit, credit
- from `tabJournal Entry Account`
- where docstatus=1 and date(modified) >= '2015-09-17'
- and ((ifnull(debit_in_account_currency, 0)*exchange_rate != ifnull(debit, 0))
- or (ifnull(credit_in_account_currency, 0)*exchange_rate != ifnull(credit, 0)))
- order by parent
- """, as_dict=True)
-
- journal_entries = []
-
- for d in je_rows:
- if d.parent not in journal_entries:
- journal_entries.append(d.parent)
-
- is_advance_entry=None
- if d.reference_type in ("Sales Invoice", "Purchase Invoice") and d.reference_name:
- is_advance_entry = frappe.db.sql("""select name from `tab{0}`
- where reference_name=%s and reference_row=%s
- and ifnull(allocated_amount, 0) > 0 and docstatus=1"""
- .format(d.reference_type + " Advance"), (d.parent, d.name))
-
- if is_advance_entry or not (d.debit or d.credit):
- frappe.db.sql("""
- update `tabJournal Entry Account`
- set debit=debit_in_account_currency*exchange_rate,
- credit=credit_in_account_currency*exchange_rate
- where name=%s""", d.name)
- else:
- frappe.db.sql("""
- update `tabJournal Entry Account`
- set debit_in_account_currency=debit/exchange_rate,
- credit_in_account_currency=credit/exchange_rate
- where name=%s""", d.name)
-
- for d in journal_entries:
- print(d)
- # delete existing gle
- frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
-
- # repost gl entries
- je = frappe.get_doc("Journal Entry", d)
- je.make_gl_entries()
\ No newline at end of file
diff --git a/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py b/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py
deleted file mode 100644
index f27489e7b0..0000000000
--- a/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Sales Order", "Purchase Order"):
- data = frappe.db.sql("""select parent, modified_by, modified
- from `tab{doctype} Item` where docstatus=1 group by parent""".format(doctype=doctype), as_dict=True)
- for item in data:
- frappe.db.sql("""update `tab{doctype}` set modified_by=%(modified_by)s, modified=%(modified)s
- where name=%(parent)s""".format(doctype=doctype), item)
diff --git a/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py b/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py
deleted file mode 100644
index 50aa9e542e..0000000000
--- a/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doc in frappe.get_all("Sales Order", filters={"docstatus": 1,
- "order_type": "Maintenance"}):
- doc = frappe.get_doc("Sales Order", doc.name)
- doc.set_status(update=True)
diff --git a/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py b/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py
deleted file mode 100644
index 746a99004a..0000000000
--- a/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Sales Order", "Purchase Order"):
- for doc in frappe.get_all(doctype, filters={"docstatus": 1}):
- doc = frappe.get_doc(doctype, doc.name)
- doc.set_status(update=True)
diff --git a/erpnext/patches/v6_4/make_image_thumbnail.py b/erpnext/patches/v6_4/make_image_thumbnail.py
deleted file mode 100644
index 2c86e8af86..0000000000
--- a/erpnext/patches/v6_4/make_image_thumbnail.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("File")
- frappe.reload_doctype("Item")
- for item in frappe.get_all("Item", fields=("name", "website_image", "thumbnail")):
- if item.website_image and not item.thumbnail:
- item_doc = frappe.get_doc("Item", item.name)
- try:
- item_doc.make_thumbnail()
- if item_doc.thumbnail:
- item_doc.db_set("thumbnail", item_doc.thumbnail, update_modified=False)
- except Exception:
- print("Unable to make thumbnail for {0}".format(item.website_image.encode("utf-8")))
diff --git a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py b/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
deleted file mode 100644
index 1319b53558..0000000000
--- a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- je_list = frappe.db.sql_list("""select distinct parent from `tabJournal Entry Account` je
- where docstatus=1 and ifnull(reference_name, '') !='' and creation > '2015-03-01'
- and not exists(select name from `tabGL Entry`
- where voucher_type='Journal Entry' and voucher_no=je.parent
- and against_voucher_type=je.reference_type
- and against_voucher=je.reference_name)""")
-
- for d in je_list:
- print(d)
-
- # delete existing gle
- frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
-
- # repost gl entries
- je = frappe.get_doc("Journal Entry", d)
- je.make_gl_entries()
\ No newline at end of file
diff --git a/erpnext/patches/v6_4/round_status_updater_percentages.py b/erpnext/patches/v6_4/round_status_updater_percentages.py
deleted file mode 100644
index 900e906b7b..0000000000
--- a/erpnext/patches/v6_4/round_status_updater_percentages.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype, fieldname in (
- ("Sales Order", "per_billed"),
- ("Sales Order", "per_delivered"),
- ("Delivery Note", "per_installed"),
- ("Purchase Order", "per_billed"),
- ("Purchase Order", "per_received"),
- ("Material Request", "per_ordered"),
- ):
- frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=round(`{fieldname}`, 2)""".format(
- doctype=doctype, fieldname=fieldname))
diff --git a/erpnext/patches/v6_4/set_user_in_contact.py b/erpnext/patches/v6_4/set_user_in_contact.py
deleted file mode 100644
index 7e8a6eecd5..0000000000
--- a/erpnext/patches/v6_4/set_user_in_contact.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Contact")
- frappe.db.sql("""update tabContact, tabUser set tabContact.user = tabUser.name
- where tabContact.email_id = tabUser.email""")
diff --git a/erpnext/patches/v6_5/__init__.py b/erpnext/patches/v6_5/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_5/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_5/show_in_website_for_template_item.py b/erpnext/patches/v6_5/show_in_website_for_template_item.py
deleted file mode 100644
index af6e8304d6..0000000000
--- a/erpnext/patches/v6_5/show_in_website_for_template_item.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import frappe.website.render
-
-def execute():
- for item_code in frappe.db.sql_list("""select distinct variant_of from `tabItem`
- where variant_of is not null and variant_of !='' and show_in_website=1"""):
-
- item = frappe.get_doc("Item", item_code)
- item.db_set("show_in_website", 1, update_modified=False)
-
- item.make_route()
- item.db_set("route", item.route, update_modified=False)
-
- frappe.website.render.clear_cache()
diff --git a/erpnext/patches/v6_6/__init__.py b/erpnext/patches/v6_6/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_6/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_6/fix_website_image.py b/erpnext/patches/v6_6/fix_website_image.py
deleted file mode 100644
index cc3e2d852c..0000000000
--- a/erpnext/patches/v6_6/fix_website_image.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.utils import encode
-
-def execute():
- """Fix the File records created via item.py even if the website_image file didn't exist"""
- for item in frappe.db.sql_list("""select name from `tabItem`
- where website_image is not null and website_image != ''
- and website_image like '/files/%'
- and exists (
- select name from `tabFile`
- where attached_to_doctype='Item'
- and attached_to_name=`tabItem`.name
- and file_url=`tabItem`.website_image
- and (file_name is null or file_name = '')
- )"""):
-
- item = frappe.get_doc("Item", item)
- file = frappe.get_doc("File", {
- "attached_to_doctype": "Item",
- "attached_to_name": item.name,
- "file_url": item.website_image
- })
-
- try:
- file.validate_file()
- except IOError:
- print(encode(item.website_image), "does not exist")
- file.delete()
- item.db_set("website_image", None, update_modified=False)
-
-
diff --git a/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py b/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py
deleted file mode 100644
index 11c582fc49..0000000000
--- a/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Leave Allocation")
- if frappe.db.has_column("Leave Allocation", "fiscal_year"):
- for leave_allocation in frappe.db.sql("select name, fiscal_year from `tabLeave Allocation`", as_dict=True):
- dates = frappe.db.get_value("Fiscal Year", leave_allocation["fiscal_year"],
- ["year_start_date", "year_end_date"])
-
- if dates:
- year_start_date, year_end_date = dates
-
- frappe.db.sql("""update `tabLeave Allocation`
- set from_date=%s, to_date=%s where name=%s""",
- (year_start_date, year_end_date, leave_allocation["name"]))
-
diff --git a/erpnext/patches/v6_8/__init__.py b/erpnext/patches/v6_8/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_8/make_webform_standard.py b/erpnext/patches/v6_8/make_webform_standard.py
deleted file mode 100644
index 2cc16a286f..0000000000
--- a/erpnext/patches/v6_8/make_webform_standard.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- pass
-
- # done via fixtures
-
- # frappe.reload_doctype("Web Form")
- # frappe.delete_doc("Web Form", "Issues")
- # frappe.delete_doc("Web Form", "Addresses")
-
- # from erpnext.setup.install import add_web_forms
- # add_web_forms()
diff --git a/erpnext/patches/v6_8/move_drop_ship_to_po_items.py b/erpnext/patches/v6_8/move_drop_ship_to_po_items.py
deleted file mode 100644
index 7184deeccc..0000000000
--- a/erpnext/patches/v6_8/move_drop_ship_to_po_items.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Purchase Order")
- frappe.reload_doctype("Purchase Order Item")
-
- if not frappe.db.has_column("Purchase Order", "delivered_by_supplier"):
- return
-
- for po in frappe.get_all("Purchase Order", filters={"delivered_by_supplier": 1}, fields=["name"]):
- purchase_order = frappe.get_doc("Purchase Order", po)
-
- for item in purchase_order.items:
- if item.prevdoc_doctype == "Sales Order":
- delivered_by_supplier = frappe.get_value("Sales Order Item", item.prevdoc_detail_docname,
- "delivered_by_supplier")
-
- if delivered_by_supplier:
- frappe.db.sql("""update `tabPurchase Order Item`
- set delivered_by_supplier=1, billed_amt=amount, received_qty=qty
- where name=%s """, item.name)
-
- update_per_received(purchase_order)
- update_per_billed(purchase_order)
-
-def update_per_received(po):
- frappe.db.sql(""" update `tabPurchase Order`
- set per_received = round((select sum(if(qty > ifnull(received_qty, 0),
- ifnull(received_qty, 0), qty)) / sum(qty) *100
- from `tabPurchase Order Item`
- where parent = %(name)s), 2)
- where name = %(name)s """, {"name": po.name})
-
-def update_per_billed(po):
- frappe.db.sql(""" update `tabPurchase Order`
- set per_billed = round((select sum( if(amount > ifnull(billed_amt, 0),
- ifnull(billed_amt, 0), amount)) / sum(amount) *100
- from `tabPurchase Order Item`
- where parent = %(name)s), 2)
- where name = %(name)s """, {"name": po.name})
-
-
diff --git a/erpnext/patches/v7_0/__init__.py b/erpnext/patches/v7_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v7_0/calculate_total_costing_amount.py b/erpnext/patches/v7_0/calculate_total_costing_amount.py
deleted file mode 100644
index 8ed60a2955..0000000000
--- a/erpnext/patches/v7_0/calculate_total_costing_amount.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet')
-
- for data in frappe.get_all('Timesheet', fields=["name, total_costing_amount"],
- filters = [["docstatus", "<", "2"]]):
- if flt(data.total_costing_amount) == 0.0:
- ts = frappe.get_doc('Timesheet', data.name)
- ts.update_cost()
- ts.calculate_total_amounts()
- ts.flags.ignore_validate = True
- ts.flags.ignore_mandatory = True
- ts.flags.ignore_validate_update_after_submit = True
- ts.flags.ignore_links = True
- ts.save()
diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py
deleted file mode 100644
index 8c60b5b71e..0000000000
--- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'task')
- frappe.reload_doc('projects', 'doctype', 'timesheet')
- if not frappe.db.table_exists("Time Log"):
- return
-
- from erpnext.manufacturing.doctype.work_order.work_order \
- import make_timesheet, add_timesheet_detail
-
- for data in frappe.db.sql("select * from `tabTime Log`", as_dict=1):
- if data.task:
- company = frappe.db.get_value("Task", data.task, "company")
- elif data.work_order:
- company = frappe.db.get_value("Work Order", data.work_order, "company")
- else:
- company = frappe.db.get_single_value('Global Defaults', 'default_company')
-
- time_sheet = make_timesheet(data.work_order, company)
- args = get_timelog_data(data)
- add_timesheet_detail(time_sheet, args)
- if data.docstatus == 2:
- time_sheet.docstatus = 0
- else:
- time_sheet.docstatus = data.docstatus
- time_sheet.employee = data.employee
- time_sheet.note = data.note
- time_sheet.company = company
-
- time_sheet.set_status()
- time_sheet.set_dates()
- time_sheet.update_cost()
- time_sheet.calculate_total_amounts()
- time_sheet.flags.ignore_validate = True
- time_sheet.flags.ignore_links = True
- time_sheet.save(ignore_permissions=True)
-
- # To ignore validate_mandatory_fields function
- if data.docstatus == 1:
- time_sheet.db_set("docstatus", 1)
- for d in time_sheet.get("time_logs"):
- d.db_set("docstatus", 1)
- time_sheet.update_work_order(time_sheet.name)
- time_sheet.update_task_and_project()
- if data.docstatus == 2:
- time_sheet.db_set("docstatus", 2)
- for d in time_sheet.get("time_logs"):
- d.db_set("docstatus", 2)
-
-def get_timelog_data(data):
- return {
- 'is_billable': data.billable,
- 'from_time': data.from_time,
- 'hours': data.hours,
- 'to_time': data.to_time,
- 'project': data.project,
- 'task': data.task,
- 'activity_type': data.activity_type,
- 'operation': data.operation,
- 'operation_id': data.operation_id,
- 'workstation': data.workstation,
- 'completed_qty': data.completed_qty,
- 'billing_rate': data.billing_rate,
- 'billing_amount': data.billing_amount,
- 'costing_rate': data.costing_rate,
- 'costing_amount': data.costing_amount
- }
diff --git a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py b/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py
deleted file mode 100644
index e78f163e07..0000000000
--- a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-
-def execute():
- if not frappe.db.exists("DocType", "Time Log Batch"):
- return
-
- from erpnext.manufacturing.doctype.work_order.work_order import add_timesheet_detail
-
- for tlb in frappe.get_all('Time Log Batch', fields=["*"],
- filters = [["docstatus", "<", "2"]]):
- time_sheet = frappe.new_doc('Timesheet')
- time_sheet.employee= ""
- time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company')
- time_sheet.sales_invoice = tlb.sales_invoice
-
- for data in frappe.get_all('Time Log Batch Detail', fields=["*"],
- filters = {'parent': tlb.name}):
- args = get_timesheet_data(data)
- add_timesheet_detail(time_sheet, args)
-
- time_sheet.docstatus = tlb.docstatus
- time_sheet.flags.ignore_links = True
- time_sheet.save(ignore_permissions=True)
-
-def get_timesheet_data(data):
- from erpnext.patches.v7_0.convert_timelog_to_timesheet import get_timelog_data
-
- time_log = frappe.get_all('Time Log', fields=["*"], filters = {'name': data.time_log})
- if time_log:
- return get_timelog_data(time_log[0])
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/create_budget_record.py b/erpnext/patches/v7_0/create_budget_record.py
deleted file mode 100644
index fd8bec9f32..0000000000
--- a/erpnext/patches/v7_0/create_budget_record.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.accounts.doctype.budget.budget import DuplicateBudgetError
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "budget")
- frappe.reload_doc("accounts", "doctype", "budget_account")
-
- existing_budgets = frappe.db.sql("""
- select
- cc.name, cc.company, cc.distribution_id,
- budget.account, budget.budget_allocated, budget.fiscal_year
- from
- `tabCost Center` cc, `tabBudget Detail` budget
- where
- cc.name=budget.parent
- """, as_dict=1)
-
- actions = {}
- for d in frappe.db.sql("select name, yearly_bgt_flag, monthly_bgt_flag from tabCompany", as_dict=1):
- actions.setdefault(d.name, d)
-
- budget_records = []
- for d in existing_budgets:
- budget = frappe.db.get_value("Budget",
- {"cost_center": d.name, "fiscal_year": d.fiscal_year, "company": d.company})
-
- if not budget:
- budget = frappe.new_doc("Budget")
- budget.cost_center = d.name
- budget.fiscal_year = d.fiscal_year
- budget.monthly_distribution = d.distribution_id
- budget.company = d.company
- if actions[d.company]["yearly_bgt_flag"]:
- budget.action_if_annual_budget_exceeded = actions[d.company]["yearly_bgt_flag"]
- if actions[d.company]["monthly_bgt_flag"]:
- budget.action_if_accumulated_monthly_budget_exceeded = actions[d.company]["monthly_bgt_flag"]
- else:
- budget = frappe.get_doc("Budget", budget)
-
- budget.append("accounts", {
- "account": d.account,
- "budget_amount": d.budget_allocated
- })
-
- try:
- budget.insert()
- budget_records.append(budget)
- except DuplicateBudgetError:
- pass
-
- for budget in budget_records:
- budget.submit()
-
- if frappe.db.get_value("DocType", "Budget Detail"):
- frappe.delete_doc("DocType", "Budget Detail")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/create_warehouse_nestedset.py b/erpnext/patches/v7_0/create_warehouse_nestedset.py
deleted file mode 100644
index 1c9fc32142..0000000000
--- a/erpnext/patches/v7_0/create_warehouse_nestedset.py
+++ /dev/null
@@ -1,128 +0,0 @@
-
-from __future__ import unicode_literals
-import frappe, erpnext
-from frappe import _
-from frappe.utils import cint
-from frappe.utils.nestedset import rebuild_tree
-
-def execute():
- """
- Patch Reference:
- 1. check whether warehouse is associated to company or not
- 2. if warehouse is associated with company
- a. create warehouse group for company
- b. set warehouse group as parent to other warehouses and set is_group as 0
- 3. if warehouses is not associated with company
- a. get distinct companies from stock ledger entries
- b. if sle have only company,
- i. set default company to all warehouse
- ii. repeat 2.a and 2.b
- c. if have multiple companies,
- i. create group warehouse without company
- ii. repeat 2.b
- """
-
- frappe.reload_doc("stock", "doctype", "warehouse")
-
- if check_is_warehouse_associated_with_company():
- for company in frappe.get_all("Company", fields=["name", "abbr"]):
- make_warehouse_nestedset(company)
- else:
- sle_against_companies = frappe.db.sql_list("""select distinct company from `tabStock Ledger Entry`""")
-
- if len(sle_against_companies) == 1:
- company = frappe.get_cached_value('Company', sle_against_companies[0],
- fieldname=["name", "abbr"], as_dict=1)
- set_company_to_warehouse(company.name)
- make_warehouse_nestedset(company)
-
- elif len(sle_against_companies) > 1:
- make_warehouse_nestedset()
-
-def check_is_warehouse_associated_with_company():
- warehouse_associcated_with_company = False
-
- for warehouse in frappe.get_all("Warehouse", fields=["name", "company"]):
- if warehouse.company:
- warehouse_associcated_with_company = True
-
- return warehouse_associcated_with_company
-
-def make_warehouse_nestedset(company=None):
- validate_parent_account_for_warehouse(company)
- stock_account_group = get_stock_account_group(company.name)
- enable_perpetual_inventory = cint(erpnext.is_perpetual_inventory_enabled(company.name)) or 0
- if not stock_account_group and enable_perpetual_inventory:
- return
-
- if company:
- warehouse_group = "{0} - {1}".format(_("All Warehouses"), company.abbr)
- ignore_mandatory = False
- else:
- warehouse_group = _("All Warehouses")
- ignore_mandatory = True
-
- if not frappe.db.get_value("Warehouse", warehouse_group):
- create_default_warehouse_group(company, stock_account_group, ignore_mandatory)
-
- set_parent_to_warehouse(warehouse_group, company)
- if enable_perpetual_inventory:
- set_parent_to_warehouse_account(company)
-
-def validate_parent_account_for_warehouse(company=None):
- if not company:
- return
-
- if cint(erpnext.is_perpetual_inventory_enabled(company.name)):
- parent_account = frappe.db.sql("""select name from tabAccount
- where account_type='Stock' and company=%s and is_group=1
- and (warehouse is null or warehouse = '')""", company.name)
-
- if not parent_account:
- current_parent_accounts_for_warehouse = frappe.db.sql("""select parent_account from tabAccount
- where account_type='Warehouse' and (warehouse is not null or warehouse != '') """)
-
- if current_parent_accounts_for_warehouse:
- frappe.db.set_value("Account", current_parent_accounts_for_warehouse[0][0], "account_type", "Stock")
-
-def create_default_warehouse_group(company=None, stock_account_group=None, ignore_mandatory=False):
- wh = frappe.get_doc({
- "doctype": "Warehouse",
- "warehouse_name": _("All Warehouses"),
- "is_group": 1,
- "company": company.name if company else "",
- "parent_warehouse": ""
- })
-
- if ignore_mandatory:
- wh.flags.ignore_mandatory = ignore_mandatory
-
- wh.insert(ignore_permissions=True)
-
-def set_parent_to_warehouse(warehouse_group, company=None):
- frappe.db.sql(""" update tabWarehouse set parent_warehouse = %s, is_group = 0
- where (is_group = 0 or is_group is null or is_group = '') and ifnull(company, '') = %s
- """,(warehouse_group, company.name if company else ""))
-
- rebuild_tree("Warehouse", "parent_warehouse")
-
-def set_parent_to_warehouse_account(company):
- frappe.db.sql(""" update tabAccount set parent_account = %s
- where is_group = 0 and account_type = "Warehouse"
- and (warehouse is not null or warehouse != '') and company = %s
- """,("{0} - {1}".format(_("All Warehouses"), company.abbr), company.name))
-
- rebuild_tree("Account", "parent_account")
-
-def set_company_to_warehouse(company):
- frappe.db.sql("update tabWahouse set company=%s", company)
-
-def get_stock_account_group(company):
- stock_account_group = frappe.db.get_all('Account', filters = {'company': company, 'is_group': 1,
- 'account_type': 'Stock', 'root_type': 'Asset'}, limit=1)
-
- if not stock_account_group:
- stock_account_group = frappe.db.get_all('Account', filters = {'company': company, 'is_group': 1,
- 'parent_account': '', 'root_type': 'Asset'}, limit=1)
-
- return stock_account_group[0].name if stock_account_group else None
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/fix_duplicate_icons.py b/erpnext/patches/v7_0/fix_duplicate_icons.py
deleted file mode 100644
index 9f442029b5..0000000000
--- a/erpnext/patches/v7_0/fix_duplicate_icons.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from frappe.desk.doctype.desktop_icon.desktop_icon import (sync_desktop_icons,
- get_desktop_icons, set_hidden)
-from erpnext.patches.v7_0.migrate_schools_to_erpnext import reload_doctypes_for_schools_icons
-
-def execute():
- '''hide new style icons if old ones are set'''
- frappe.reload_doc('desk', 'doctype', 'desktop_icon')
-
- reload_doctypes_for_schools_icons()
-
- sync_desktop_icons()
-
- for user in frappe.get_all('User', filters={'user_type': 'System User'}):
- desktop_icons = get_desktop_icons(user.name)
- icons_dict = {}
- for d in desktop_icons:
- if not d.hidden:
- icons_dict[d.module_name] = d
-
- for key in (('Selling', 'Customer'), ('Stock', 'Item'), ('Buying', 'Supplier'),
- ('HR', 'Employee'), ('CRM', 'Lead'), ('Support', 'Issue'), ('Projects', 'Project')):
- if key[0] in icons_dict and key[1] in icons_dict:
- set_hidden(key[1], user.name, 1)
-
diff --git a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py b/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
deleted file mode 100644
index 2bc09714d8..0000000000
--- a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe, erpnext
-
-def execute():
- frappe.reload_doctype("Account")
-
- warehouses = frappe.db.sql("""select name, company from tabAccount
- where account_type = 'Stock' and is_group = 0
- and (warehouse is null or warehouse = '')""", as_dict=1)
- warehouses = [d.name for d in warehouses if erpnext.is_perpetual_inventory_enabled(d.company)]
-
- if len(warehouses) > 0:
- warehouses = set_warehouse_for_stock_account(warehouses)
- if not warehouses:
- return
-
- stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
- from `tabStock Ledger Entry` sle
- where sle.warehouse in (%s) and creation > '2016-05-01'
- and not exists(select name from `tabGL Entry`
- where account=sle.warehouse and voucher_type=sle.voucher_type and voucher_no=sle.voucher_no)
- order by sle.posting_date""" %
- ', '.join(['%s']*len(warehouses)), tuple(warehouses))
-
- rejected = []
- for voucher_type, voucher_no in stock_vouchers:
- try:
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
-
- voucher = frappe.get_doc(voucher_type, voucher_no)
- voucher.make_gl_entries()
- frappe.db.commit()
- except Exception as e:
- print(frappe.get_traceback())
- rejected.append([voucher_type, voucher_no])
- frappe.db.rollback()
-
- print(rejected)
-
-def set_warehouse_for_stock_account(warehouse_account):
- for account in warehouse_account:
- if frappe.db.exists('Warehouse', account):
- frappe.db.set_value("Account", account, "warehouse", account)
- else:
- warehouse_account.remove(account)
-
- return warehouse_account
diff --git a/erpnext/patches/v7_0/make_guardian.py b/erpnext/patches/v7_0/make_guardian.py
deleted file mode 100644
index 519969b38d..0000000000
--- a/erpnext/patches/v7_0/make_guardian.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Student"):
- student_table_cols = frappe.db.get_table_columns("Student")
- if "father_name" in student_table_cols:
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "student")
- # frappe.reload_doc("schools", "doctype", "guardian")
- # frappe.reload_doc("schools", "doctype", "guardian_interest")
-
- frappe.reload_doc("education", "doctype", "student")
- frappe.reload_doc("education", "doctype", "guardian")
- frappe.reload_doc("education", "doctype", "guardian_interest")
- frappe.reload_doc("hr", "doctype", "interest")
-
- fields = ["name", "father_name", "mother_name"]
-
- if "father_email_id" in student_table_cols:
- fields += ["father_email_id", "mother_email_id"]
-
- students = frappe.get_all("Student", fields)
- for stud in students:
- if stud.father_name:
- make_guardian(stud.father_name, stud.name, stud.father_email_id)
- if stud.mother_name:
- make_guardian(stud.mother_name, stud.name, stud.mother_email_id)
-
-def make_guardian(name, student, email=None):
- frappe.get_doc({
- 'doctype': 'Guardian',
- 'guardian_name': name,
- 'email': email,
- 'student': student
- }).insert()
diff --git a/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py b/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py
deleted file mode 100644
index ba82e869fa..0000000000
--- a/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ["Sales Person", "Customer Group", "Item Group", "Territory"]:
-
- # convert to 1 or 0
- frappe.db.sql("update `tab{doctype}` set is_group = if(is_group='Yes',1,0) "
- .format(doctype=doctype))
-
- frappe.db.commit()
-
- # alter fields to int
-
- frappe.db.sql("alter table `tab{doctype}` change is_group is_group int(1) default '0'"
- .format(doctype=doctype))
-
- frappe.reload_doctype(doctype)
diff --git a/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py b/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py
deleted file mode 100644
index 02808a742f..0000000000
--- a/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
-
- frappe.db.sql(""" update tabAccount set account_type = "Stock"
- where account_type = "Warehouse" """)
-
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py b/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py
deleted file mode 100644
index e0e3f7075a..0000000000
--- a/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_payment')
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment')
-
- count = 0
- for data in frappe.db.sql("""select name, mode_of_payment, cash_bank_account, paid_amount, company
- from `tabSales Invoice` si
- where si.is_pos = 1 and si.docstatus < 2
- and si.cash_bank_account is not null and si.cash_bank_account != ''
- and not exists(select name from `tabSales Invoice Payment` where parent=si.name)""", as_dict=1):
-
- if not data.mode_of_payment and not frappe.db.exists("Mode of Payment", "Cash"):
- mop = frappe.new_doc("Mode of Payment")
- mop.mode_of_payment = "Cash"
- mop.type = "Cash"
- mop.save()
-
- si_doc = frappe.get_doc('Sales Invoice', data.name)
- row = si_doc.append('payments', {
- 'mode_of_payment': data.mode_of_payment or 'Cash',
- 'account': data.cash_bank_account,
- 'type': frappe.db.get_value('Mode of Payment', data.mode_of_payment, 'type') or 'Cash',
- 'amount': data.paid_amount
- })
- row.db_update()
-
- si_doc.set_paid_amount()
- si_doc.db_set("paid_amount", si_doc.paid_amount, update_modified = False)
- si_doc.db_set("base_paid_amount", si_doc.base_paid_amount, update_modified = False)
-
- count +=1
-
- if count % 200 == 0:
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py b/erpnext/patches/v7_0/migrate_schools_to_erpnext.py
deleted file mode 100644
index b72bc137b6..0000000000
--- a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import unicode_literals
-import frappe, os
-from frappe.installer import remove_from_installed_apps
-
-def execute():
- reload_doctypes_for_schools_icons()
-
- frappe.reload_doc('website', 'doctype', 'portal_settings')
- frappe.reload_doc('website', 'doctype', 'portal_menu_item')
- frappe.reload_doc('buying', 'doctype', 'request_for_quotation')
-
- if 'schools' in frappe.get_installed_apps():
- if not frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Academics'):
-
- # 'Schools' module changed to the 'Education'
- # frappe.rename_doc("Module Def", "Academics", "Schools")
-
- frappe.rename_doc("Module Def", "Academics", "Education")
-
- remove_from_installed_apps("schools")
-
-def reload_doctypes_for_schools_icons():
- # 'Schools' module changed to the 'Education'
- # base_path = frappe.get_app_path('erpnext', 'schools', 'doctype')
-
- base_path = frappe.get_app_path('erpnext', 'education', 'doctype')
- for doctype in os.listdir(base_path):
- if os.path.exists(os.path.join(base_path, doctype, doctype + '.json')) \
- and doctype not in ("fee_component", "assessment", "assessment_result"):
- frappe.reload_doc('education', 'doctype', doctype)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py b/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py
deleted file mode 100644
index 998c4b674b..0000000000
--- a/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_payment')
- for time_sheet in frappe.db.sql(""" select sales_invoice, name, total_billable_amount from `tabTimesheet`
- where sales_invoice is not null and docstatus < 2""", as_dict=True):
- if not frappe.db.exists('Sales Invoice', time_sheet.sales_invoice):
- continue
- si_doc = frappe.get_doc('Sales Invoice', time_sheet.sales_invoice)
- ts = si_doc.append('timesheets',{})
- ts.time_sheet = time_sheet.name
- ts.billing_amount = time_sheet.total_billable_amount
- ts.db_update()
- si_doc.calculate_billing_amount_from_timesheet()
- si_doc.db_set("total_billing_amount", si_doc.total_billing_amount, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py b/erpnext/patches/v7_0/po_status_issue_for_pr_return.py
deleted file mode 100644
index 910814fd22..0000000000
--- a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- parent_list = []
- count = 0
-
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
-
- for data in frappe.db.sql("""
- select
- `tabPurchase Receipt Item`.purchase_order, `tabPurchase Receipt Item`.name,
- `tabPurchase Receipt Item`.item_code, `tabPurchase Receipt Item`.idx,
- `tabPurchase Receipt Item`.parent
- from
- `tabPurchase Receipt Item`, `tabPurchase Receipt`
- where
- `tabPurchase Receipt Item`.parent = `tabPurchase Receipt`.name and
- `tabPurchase Receipt Item`.purchase_order_item is null and
- `tabPurchase Receipt Item`.purchase_order is not null and
- `tabPurchase Receipt`.is_return = 1""", as_dict=1):
- name = frappe.db.get_value('Purchase Order Item',
- {'item_code': data.item_code, 'parent': data.purchase_order, 'idx': data.idx}, 'name')
-
- if name:
- frappe.db.set_value('Purchase Receipt Item', data.name, 'purchase_order_item', name, update_modified=False)
- parent_list.append(data.parent)
-
- count +=1
- if count % 200 == 0:
- frappe.db.commit()
-
- if len(parent_list) > 0:
- for parent in set(parent_list):
- doc = frappe.get_doc('Purchase Receipt', parent)
- doc.update_qty(update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/re_route.py b/erpnext/patches/v7_0/re_route.py
deleted file mode 100644
index 3cec6f39b2..0000000000
--- a/erpnext/patches/v7_0/re_route.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-from frappe.patches.v7_0.re_route import update_routes
-
-def execute():
- update_routes(['Item', 'Item Group', 'Sales Partner', 'Job Opening'])
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py b/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py
deleted file mode 100644
index 8c87c4e3d3..0000000000
--- a/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""delete from tabDocPerm where role="Administrator" and parent in
- ("Payment Gateway", "Payment Gateway Account", "Payment Request", "Academic Term", "Academic Year", "Course",
- "Course Schedule", "Examination", "Fee Category", "Fee Structure", "Fees", "Instructor", "Program", "Program Enrollment Tool",
- "Room", "Scheduling Tool", "Student", "Student Applicant", "Student Attendance", "Student Group", "Student Group Creation Tool")
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/remove_doctypes_and_reports.py b/erpnext/patches/v7_0/remove_doctypes_and_reports.py
deleted file mode 100644
index 2356e2f6ee..0000000000
--- a/erpnext/patches/v7_0/remove_doctypes_and_reports.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Log"):
- frappe.db.sql("""delete from `tabDocType`
- where name in('Time Log Batch', 'Time Log Batch Detail', 'Time Log')""")
-
- frappe.db.sql("""delete from `tabDocField` where parent in ('Time Log', 'Time Log Batch')""")
- frappe.db.sql("""update `tabClient Script` set dt = 'Timesheet' where dt = 'Time Log'""")
-
- for data in frappe.db.sql(""" select label, fieldname from `tabCustom Field` where dt = 'Time Log'""", as_dict=1):
- custom_field = frappe.get_doc({
- 'doctype': 'Custom Field',
- 'label': data.label,
- 'dt': 'Timesheet Detail',
- 'fieldname': data.fieldname,
- 'fieldtype': data.fieldtype or "Data"
- }).insert(ignore_permissions=True)
-
- frappe.db.sql("""delete from `tabCustom Field` where dt = 'Time Log'""")
- frappe.reload_doc('projects', 'doctype', 'timesheet')
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
-
- report = "Daily Time Log Summary"
- if frappe.db.exists("Report", report):
- frappe.delete_doc('Report', report)
diff --git a/erpnext/patches/v7_0/remove_features_setup.py b/erpnext/patches/v7_0/remove_features_setup.py
deleted file mode 100644
index 49393cc248..0000000000
--- a/erpnext/patches/v7_0/remove_features_setup.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.setup.install import create_compact_item_print_custom_field
-from frappe.utils import cint
-
-def execute():
- frappe.reload_doctype('Stock Settings')
- stock_settings = frappe.get_doc('Stock Settings', 'Stock Settings')
- stock_settings.show_barcode_field = cint(frappe.db.get_value("Features Setup", None, "fs_item_barcode"))
- if not frappe.db.exists("UOM", stock_settings.stock_uom):
- stock_settings.stock_uom = None
- stock_settings.save()
-
- create_compact_item_print_custom_field()
-
- compact_item_print = frappe.db.get_value("Features Setup", None, "compact_item_print")
- frappe.db.set_value("Print Settings", None, "compact_item_print", compact_item_print)
-
- # remove defaults
- frappe.db.sql("""delete from tabDefaultValue where defkey in ('fs_item_serial_nos',
- 'fs_item_batch_nos', 'fs_brands', 'fs_item_barcode',
- 'fs_item_advanced', 'fs_packing_details', 'fs_item_group_in_details',
- 'fs_exports', 'fs_imports', 'fs_discounts', 'fs_purchase_discounts',
- 'fs_after_sales_installations', 'fs_projects', 'fs_sales_extras',
- 'fs_recurring_invoice', 'fs_pos', 'fs_manufacturing', 'fs_quality',
- 'fs_page_break', 'fs_more_info', 'fs_pos_view', 'compact_item_print')""")
-
- frappe.delete_doc('DocType', 'Features Setup')
diff --git a/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py b/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py
deleted file mode 100644
index 05a2c49461..0000000000
--- a/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Salary Component"):
- for dt in ("Salary Structure Earning", "Salary Structure Deduction", "Salary Slip Earning",
- "Salary Slip Deduction", "Earning Type", "Deduction Type"):
- frappe.delete_doc("DocType", dt)
-
-
- for d in frappe.db.sql("""select name from `tabCustom Field`
- where dt in ('Salary Detail', 'Salary Component')"""):
- frappe.get_doc("Custom Field", d[0]).save()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_advance_table_fields.py b/erpnext/patches/v7_0/rename_advance_table_fields.py
deleted file mode 100644
index 34d81343e2..0000000000
--- a/erpnext/patches/v7_0/rename_advance_table_fields.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- for dt in ("Sales Invoice Advance", "Purchase Invoice Advance"):
- frappe.reload_doctype(dt)
-
- frappe.db.sql("update `tab{0}` set reference_type = 'Journal Entry'".format(dt))
-
- if frappe.get_meta(dt).has_field('journal_entry'):
- rename_field(dt, "journal_entry", "reference_name")
-
- if frappe.get_meta(dt).has_field('jv_detail_no'):
- rename_field(dt, "jv_detail_no", "reference_row")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_examination_to_assessment.py b/erpnext/patches/v7_0/rename_examination_to_assessment.py
deleted file mode 100644
index dc248de4fa..0000000000
--- a/erpnext/patches/v7_0/rename_examination_to_assessment.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- if frappe.db.exists("DocType", "Examination"):
- frappe.rename_doc("DocType", "Examination", "Assessment")
- frappe.rename_doc("DocType", "Examination Result", "Assessment Result")
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "assessment")
- # frappe.reload_doc("schools", "doctype", "assessment_result")
-
- frappe.reload_doc("education", "doctype", "assessment")
- frappe.reload_doc("education", "doctype", "assessment_result")
-
- rename_field("Assessment", "exam_name", "assessment_name")
- rename_field("Assessment", "exam_code", "assessment_code")
-
- frappe.db.sql("delete from `tabPortal Menu Item` where route = '/examination'")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py b/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py
deleted file mode 100644
index 5cb6a3b7c4..0000000000
--- a/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- if frappe.db.exists("DocType", "Fee Amount"):
- frappe.rename_doc("DocType", "Fee Amount", "Fee Component")
- for dt in ("Fees", "Fee Structure"):
- frappe.reload_doctype(dt)
- rename_field(dt, "amount", "components")
-
-
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_prevdoc_fields.py b/erpnext/patches/v7_0/rename_prevdoc_fields.py
deleted file mode 100644
index ded4ad4aae..0000000000
--- a/erpnext/patches/v7_0/rename_prevdoc_fields.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import json
-from frappe.model.utils.rename_field import update_reports, rename_field, update_property_setters
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
-
-def execute():
- frappe.reload_doctype('Purchase Order Item')
- frappe.reload_doctype('Purchase Receipt Item')
- update_po_fields()
- update_prop_setters_reports_print_format_for_po()
- set_sales_order_field()
- rename_pr_fields()
-
-def update_po_fields():
- for data in frappe.db.sql(""" select prevdoc_docname, prevdoc_detail_docname, name, prevdoc_doctype
- from `tabPurchase Order Item` where prevdoc_doctype is not null""", as_dict=True):
- if data.prevdoc_doctype == 'Material Request':
- frappe.db.set_value("Purchase Order Item", data.name, "material_request", data.prevdoc_docname, update_modified=False)
- frappe.db.set_value("Purchase Order Item", data.name, "material_request_item", data.prevdoc_detail_docname, update_modified=False)
- elif data.prevdoc_doctype == 'Sales Order':
- frappe.db.set_value("Purchase Order Item", data.name, "sales_order", data.prevdoc_docname, update_modified=False)
- frappe.db.set_value("Purchase Order Item", data.name, "sales_order_item", data.prevdoc_detail_docname, update_modified=False)
-
-def get_columns():
- return {
- 'prevdoc_docname': 'material_request',
- 'prevdoc_detail_docname': 'material_request_item'
- }
-
-def update_prop_setters_reports_print_format_for_po():
- for key, val in get_columns().items():
- update_property_setters('Purchase Order Item', key, val)
- update_reports('Purchase Order Item', key, val)
- update_print_format_for_po(key, val, 'Purchase Order')
-
-def update_print_format_for_po(old_fieldname, new_fieldname, doc_type):
- column_mapper = get_columns()
-
- for data in frappe.db.sql(""" select name, format_data from `tabPrint Format` where
- format_data like %(old_fieldname)s and doc_type = %(doc_type)s""",
- {'old_fieldname': '%%%s%%'%(old_fieldname), 'doc_type': doc_type}, as_dict=True):
-
- update_print_format_fields(old_fieldname, new_fieldname, data)
-
-def update_print_format_fields(old_fieldname, new_fieldname, args):
- report_dict = json.loads(args.format_data)
- update = False
-
- for col in report_dict:
- if col.get('fieldname') and col.get('fieldname') == old_fieldname:
- col['fieldname'] = new_fieldname
- update = True
-
- if col.get('visible_columns'):
- for key in col.get('visible_columns'):
- if key.get('fieldname') == old_fieldname:
- key['fieldname'] = new_fieldname
- update = True
-
- if update:
- val = json.dumps(report_dict)
- frappe.db.sql("""update `tabPrint Format` set `format_data`=%s where name=%s""", (val, args.name))
-
-def set_sales_order_field():
- for data in frappe.db.sql("""select doc_type, field_name, property, value, property_type
- from `tabProperty Setter` where doc_type = 'Purchase Order Item'
- and field_name in('material_request', 'material_request_item')""", as_dict=True):
- if data.field_name == 'material_request':
- make_property_setter(data.doc_type, 'sales_order', data.property, data.value, data.property_type)
- else:
- make_property_setter(data.doc_type, 'sales_order_item', data.property, data.value, data.property_type)
-
-def rename_pr_fields():
- rename_field("Purchase Receipt Item", "prevdoc_docname", "purchase_order")
- rename_field("Purchase Receipt Item", "prevdoc_detail_docname", "purchase_order_item")
diff --git a/erpnext/patches/v7_0/rename_salary_components.py b/erpnext/patches/v7_0/rename_salary_components.py
deleted file mode 100644
index 1693f3bdf1..0000000000
--- a/erpnext/patches/v7_0/rename_salary_components.py
+++ /dev/null
@@ -1,149 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import update_property_setters
-
-def execute():
- if not frappe.db.exists("DocType", "Salary Structure Earning"):
- return
-
- frappe.reload_doc("Payroll", "doctype", "salary_detail")
- frappe.reload_doc("Payroll", "doctype", "salary_component")
-
- standard_cols = ["name", "creation", "modified", "owner", "modified_by", "parent", "parenttype", "parentfield", "idx"]
-
- dt_cols = {
- "Salary Structure Deduction": ["d_type", "d_modified_amt", "depend_on_lwp"],
- "Salary Structure Earning": ["e_type", "modified_value", "depend_on_lwp"],
- "Salary Slip Earning": ["e_type", "e_modified_amount", "e_depends_on_lwp", "e_amount"],
- "Salary Slip Deduction": ["d_type", "d_modified_amount", "d_depends_on_lwp", "d_amount"],
- }
-
- earning_type_exists = True if "earning_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
- e_type_exists = True if "e_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
-
-
- if e_type_exists and earning_type_exists:
- frappe.db.sql("""update `tabSalary Slip Earning`
- set e_type = earning_type, e_modified_amount = earning_amount
- where e_type is null and earning_type is not null""")
-
- frappe.db.sql("""update `tabSalary Structure Earning` set e_type = earning_type
- where e_type is null and earning_type is not null""")
-
- frappe.db.sql("""update `tabSalary Slip Deduction` set
- d_type = deduction_type, d_modified_amount = deduction_amount
- where d_type is null and deduction_type is not null""")
-
- frappe.db.sql("""update `tabSalary Structure Deduction` set d_type = deduction_type
- where d_type is null and deduction_type is not null""")
-
- if earning_type_exists and not e_type_exists:
- for val in dt_cols.values():
- if val[0] == "e_type":
- val[0] = "earning_type"
-
- if val[0] == "d_type":
- val[0] = "deduction_type"
-
- if val[1] == "e_modified_amount":
- val[1] ="earning_amount"
-
- if val[1] == "d_modified_amount":
- val[1] ="deduction_amount"
-
-
-
- target_cols = standard_cols + ["salary_component", "amount", "depends_on_payment_days", "default_amount"]
- target_cols = "`" + "`, `".join(target_cols) + "`"
-
- for doctype, cols in dt_cols.items():
- source_cols = "`" + "`, `".join(standard_cols + cols) + "`"
- if len(cols) == 3:
- source_cols += ", 0"
-
-
- frappe.db.sql("""INSERT INTO `tabSalary Detail` ({0}) SELECT {1} FROM `tab{2}`"""
- .format(target_cols, source_cols, doctype))
-
-
- dt_cols_de = {
- "Deduction Type": ["deduction_name", "description"],
- "Earning Type": ["earning_name", "description"],
- }
-
- standard_cols_de = standard_cols
-
-
- target_cols = standard_cols_de + ["salary_component", "description"]
- target_cols = "`" + "`, `".join(target_cols) + "`"
-
- for doctype, cols in dt_cols_de.items():
- source_cols = "`" + "`, `".join(standard_cols_de + cols) + "`"
- try:
- frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`"""
- .format(target_cols, source_cols, doctype))
- except Exception as e:
- if e.args[0]==1062:
- pass
-
- update_customizations()
-
- for doctype in ["Salary Structure Deduction", "Salary Structure Earning", "Salary Slip Earning",
- "Salary Slip Deduction", "Deduction Type", "Earning Type"] :
- frappe.delete_doc("DocType", doctype)
-
-
-def update_customizations():
- dt_cols = {
- "Salary Structure Deduction": {
- "d_type": "salary_component",
- "deduction_type": "salary_component",
- "d_modified_amt": "amount",
- "depend_on_lwp": "depends_on_payment_days"
- },
- "Salary Structure Earning": {
- "e_type": "salary_component",
- "earning_type": "salary_component",
- "modified_value": "amount",
- "depend_on_lwp": "depends_on_payment_days"
- },
- "Salary Slip Earning": {
- "e_type": "salary_component",
- "earning_type": "salary_component",
- "e_modified_amount": "amount",
- "e_amount" : "default_amount",
- "e_depends_on_lwp": "depends_on_payment_days"
- },
- "Salary Slip Deduction": {
- "d_type": "salary_component",
- "deduction_type": "salary_component",
- "d_modified_amount": "amount",
- "d_amount" : "default_amount",
- "d_depends_on_lwp": "depends_on_payment_days"
- }
- }
-
- update_property_setters_and_custom_fields("Salary Detail", dt_cols)
-
- dt_cols = {
- "Earning Type": {
- "earning_name": "salary_component"
- },
- "Deduction Type": {
- "deduction_name": "salary_component"
- }
- }
-
- update_property_setters_and_custom_fields("Salary Component", dt_cols)
-
-
-
-
-def update_property_setters_and_custom_fields(new_dt, dt_cols):
- for doctype, cols in dt_cols.items():
- frappe.db.sql("update `tabProperty Setter` set doc_type = %s where doc_type=%s", (new_dt, doctype))
- frappe.db.sql("update `tabCustom Field` set dt = %s where dt=%s", (new_dt, doctype))
-
-
- for old_fieldname, new_fieldname in cols.items():
- update_property_setters(new_dt, old_fieldname, new_fieldname)
diff --git a/erpnext/patches/v7_0/rename_time_sheet_doctype.py b/erpnext/patches/v7_0/rename_time_sheet_doctype.py
deleted file mode 100644
index f80a8301d7..0000000000
--- a/erpnext/patches/v7_0/rename_time_sheet_doctype.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Sheet") and not frappe.db.table_exists("Timesheet"):
- frappe.rename_doc("DocType", "Time Sheet", "Timesheet")
- frappe.rename_doc("DocType", "Time Sheet Detail", "Timesheet Detail")
-
- for doctype in ['Time Sheet', 'Time Sheet Detail']:
- frappe.delete_doc('DocType', doctype)
-
- report = "Daily Time Sheet Summary"
- if frappe.db.exists("Report", report):
- frappe.delete_doc('Report', report)
diff --git a/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py b/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
deleted file mode 100644
index a5cf22cf01..0000000000
--- a/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- repost_bin_qty()
-
-def repost_bin_qty():
- for bin in frappe.db.sql(""" select name from `tabBin`
- where (actual_qty + ordered_qty + indented_qty + planned_qty - reserved_qty - reserved_qty_for_production - reserved_qty_for_sub_contract) != projected_qty """, as_dict=1):
- bin_doc = frappe.get_doc('Bin', bin.name)
- bin_doc.set_projected_qty()
- bin_doc.db_set("projected_qty", bin_doc.projected_qty, update_modified = False)
diff --git a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py b/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
deleted file mode 100644
index b864e597b8..0000000000
--- a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-
-def execute():
- frappe.reload_doctype("Purchase Invoice")
-
- for pi in frappe.db.sql("""select name from `tabPurchase Invoice`
- where company in(select name from tabCompany where enable_perpetual_inventory = 1) and
- update_stock=1 and docstatus=1 order by posting_date asc""", as_dict=1):
-
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type = 'Purchase Invoice' and voucher_no = %s""", pi.name)
-
- pi_doc = frappe.get_doc("Purchase Invoice", pi.name)
- pi_doc.make_gl_entries()
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py b/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py
deleted file mode 100644
index 77ecafd6f1..0000000000
--- a/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint, flt
-
-def execute():
- frappe.reload_doctype("Sales Invoice")
- frappe.reload_doctype("Sales Invoice Item")
-
- for si in frappe.get_all("Sales Invoice", fields = ["name"],
- filters={"docstatus": 1, "is_pos": 1, "is_return": 1}):
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- if len(si_doc.payments) > 0:
- si_doc.set_paid_amount()
- si_doc.flags.ignore_validate_update_after_submit = True
- si_doc.save()
- if si_doc.grand_total <= si_doc.paid_amount and si_doc.paid_amount < 0:
- delete_gle_for_voucher(si_doc.name)
- si_doc.run_method("make_gl_entries")
-
-def delete_gle_for_voucher(voucher_no):
- frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
- {'voucher_no': voucher_no})
diff --git a/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py b/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py
deleted file mode 100644
index 5dd61a06cc..0000000000
--- a/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- si_list = frappe.db.sql("""
- select distinct parent
- from `tabSales Invoice Payment`
- where docstatus!=2 and parenttype = 'Sales Invoice'
- and amount != 0 and base_amount = 0
- """)
-
- count = 0
- for d in si_list:
- si = frappe.get_doc("Sales Invoice", d[0])
- for p in si.get("payments"):
- if p.amount and not p.base_amount:
- base_amount = flt(p.amount*si.conversion_rate, si.precision("base_paid_amount"))
- frappe.db.set_value("Sales Invoice Payment", p.name, "base_amount", base_amount, update_modified=False)
-
- count +=1
-
- if count % 200 == 0:
- frappe.db.commit()
diff --git a/erpnext/patches/v7_0/set_is_group_for_warehouse.py b/erpnext/patches/v7_0/set_is_group_for_warehouse.py
deleted file mode 100644
index 3e69616b80..0000000000
--- a/erpnext/patches/v7_0/set_is_group_for_warehouse.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "warehouse")
- frappe.db.sql("""update tabWarehouse
- set is_group = if ((ifnull(is_group, "No") = "Yes" or ifnull(is_group, 0) = 1), 1, 0)""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/set_material_request_type_in_item.py b/erpnext/patches/v7_0/set_material_request_type_in_item.py
deleted file mode 100644
index 5fb14adbc8..0000000000
--- a/erpnext/patches/v7_0/set_material_request_type_in_item.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Item")
- if "default_bom" in frappe.db.get_table_columns("Item"):
- frappe.db.sql("""update `tabItem`
- set default_material_request_type = (
- case
- when (default_bom is not null and default_bom != '')
- then 'Manufacture'
- else 'Purchase'
- end )""")
-
- else:
- frappe.db.sql("update tabItem set default_material_request_type='Purchase'")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/set_naming_series_for_timesheet.py b/erpnext/patches/v7_0/set_naming_series_for_timesheet.py
deleted file mode 100644
index d4d1a69d21..0000000000
--- a/erpnext/patches/v7_0/set_naming_series_for_timesheet.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet')
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
-
- make_property_setter('Timesheet', "naming_series", "options", 'TS-', "Text")
- make_property_setter('Timesheet', "naming_series", "default", 'TS-', "Text")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/set_party_name_in_payment_entry.py b/erpnext/patches/v7_0/set_party_name_in_payment_entry.py
deleted file mode 100644
index bbdcf5cf3c..0000000000
--- a/erpnext/patches/v7_0/set_party_name_in_payment_entry.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- customers = frappe._dict(frappe.db.sql("select name, customer_name from tabCustomer"))
- suppliers = frappe._dict(frappe.db.sql("select name, supplier_name from tabSupplier"))
-
- frappe.reload_doc('accounts', 'doctype', 'payment_entry')
-
- pe_list = frappe.db.sql("""select name, party_type, party from `tabPayment Entry`
- where party is not null and party != ''""", as_dict=1)
- for pe in pe_list:
- party_name = customers.get(pe.party) if pe.party_type=="Customer" else suppliers.get(pe.party)
-
- frappe.db.set_value("Payment Entry", pe.name, "party_name", party_name, update_modified=False)
-
diff --git a/erpnext/patches/v7_0/set_portal_settings.py b/erpnext/patches/v7_0/set_portal_settings.py
deleted file mode 100644
index 5259d4fbd4..0000000000
--- a/erpnext/patches/v7_0/set_portal_settings.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.reload_doctype('Role')
- for dt in ("assessment", "course", "fees"):
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", dt)
- frappe.reload_doc("education", "doctype", dt)
-
- for dt in ("domain", "has_domain", "domain_settings"):
- frappe.reload_doc("core", "doctype", dt)
-
- frappe.reload_doc('website', 'doctype', 'portal_menu_item')
-
- frappe.get_doc('Portal Settings').sync_menu()
-
- if 'schools' in frappe.get_installed_apps():
- domain = frappe.get_doc('Domain', 'Education')
- domain.setup_domain()
- else:
- domain = frappe.get_doc('Domain', 'Manufacturing')
- domain.setup_data()
- domain.setup_sidebar_items()
diff --git a/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py b/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py
deleted file mode 100644
index c5657079b3..0000000000
--- a/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("hr", "doctype", "expense_claim_type")
- frappe.reload_doc("hr", "doctype", "expense_claim_account")
-
- if not frappe.db.has_column('Expense Claim Type', 'default_account'):
- return
-
- for expense_claim_type in frappe.get_all("Expense Claim Type", fields=["name", "default_account"]):
- if expense_claim_type.default_account \
- and frappe.db.exists("Account", expense_claim_type.default_account):
- doc = frappe.get_doc("Expense Claim Type", expense_claim_type.name)
- doc.append("accounts", {
- "company": frappe.db.get_value("Account", expense_claim_type.default_account, "company"),
- "default_account": expense_claim_type.default_account,
- })
- doc.flags.ignore_mandatory = True
- doc.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/system_settings_setup_complete.py b/erpnext/patches/v7_0/system_settings_setup_complete.py
deleted file mode 100644
index 0feeee981e..0000000000
--- a/erpnext/patches/v7_0/system_settings_setup_complete.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('System Settings')
- companies = frappe.db.sql("""select name, country
- from tabCompany order by creation asc""", as_dict=True)
- if companies:
- frappe.db.set_value('System Settings', 'System Settings', 'setup_complete', 1)
-
- for company in companies:
- if company.country:
- frappe.db.set_value('System Settings', 'System Settings', 'country', company.country)
- break
-
-
diff --git a/erpnext/patches/v7_0/update_autoname_field.py b/erpnext/patches/v7_0/update_autoname_field.py
deleted file mode 100644
index bfa9b281df..0000000000
--- a/erpnext/patches/v7_0/update_autoname_field.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctypes = frappe.db.sql(""" select name, autoname from `tabDocType`
- where autoname like 'field:%' and allow_rename = 1""", as_dict=1)
-
- for doctype in doctypes:
- fieldname = doctype.autoname.split(":")[1]
- if fieldname:
- frappe.db.sql(""" update `tab%s` set %s = name """%(doctype.name, fieldname))
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_change_amount_account.py b/erpnext/patches/v7_0/update_change_amount_account.py
deleted file mode 100644
index 1741095ea9..0000000000
--- a/erpnext/patches/v7_0/update_change_amount_account.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
-
- for company in frappe.db.sql("""select company from `tabSales Invoice`
- where change_amount <> 0 and account_for_change_amount is null group by company""", as_list = 1):
- cash_account = get_default_bank_cash_account(company[0], 'Cash').get('account')
- if not cash_account:
- bank_account = get_default_bank_cash_account(company[0], 'Bank').get('account')
- cash_account = bank_account
-
- if cash_account:
- frappe.db.sql("""update `tabSales Invoice`
- set account_for_change_amount = %(cash_account)s where change_amount <> 0
- and company = %(company)s and account_for_change_amount is null""",
- {'cash_account': cash_account, 'company': company[0]})
diff --git a/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py b/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py
deleted file mode 100644
index 24da4b1aeb..0000000000
--- a/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item')
-
- frappe.db.sql("""update
- `tabSupplier Quotation Item` as sqi_t,
- (select sqi.item_code as item_code, sqi.uom as uom, ucd.conversion_factor as conversion_factor
- from `tabSupplier Quotation Item` sqi left join `tabUOM Conversion Detail` ucd
- on ucd.uom = sqi.uom and sqi.item_code = ucd.parent) as conversion_data,
- `tabItem` as item
- set
- sqi_t.conversion_factor= ifnull(conversion_data.conversion_factor, 1),
- sqi_t.stock_qty = (ifnull(conversion_data.conversion_factor, 1) * sqi_t.qty),
- sqi_t.stock_uom = item.stock_uom
- where
- sqi_t.item_code = conversion_data.item_code and
- sqi_t.uom = conversion_data.uom and sqi_t.item_code = item.name""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_home_page.py b/erpnext/patches/v7_0/update_home_page.py
deleted file mode 100644
index 909825c572..0000000000
--- a/erpnext/patches/v7_0/update_home_page.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import erpnext
-
-def execute():
- frappe.reload_doc('portal', 'doctype', 'homepage_featured_product')
- frappe.reload_doc('portal', 'doctype', 'homepage')
- frappe.reload_doc('portal', 'doctype', 'products_settings')
- frappe.reload_doctype('Item')
- frappe.reload_doctype('Item Group')
-
- website_settings = frappe.get_doc('Website Settings', 'Website Settings')
- if frappe.db.exists('Web Page', website_settings.home_page):
- header = frappe.db.get_value('Web Page', website_settings.home_page, 'header')
- if header and header.startswith(""):
- homepage = frappe.get_doc('Homepage', 'Homepage')
- homepage.company = erpnext.get_default_company() or frappe.get_all("Company")[0].name
- if '
' in header:
- homepage.tag_line = header.split('')[1].split('
')[0] or 'Default Website'
- else:
- homepage.tag_line = 'Default Website'
- homepage.setup_items()
- homepage.save()
-
- website_settings.home_page = 'home'
- website_settings.save()
-
diff --git a/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py b/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py
deleted file mode 100644
index 4c0c6a9313..0000000000
--- a/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.set_value("DocType", "Maintenance Schedule", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Schedule Detail", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Schedule Item", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Visit", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Visit Purpose", "module", "Maintenance")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_mins_to_first_response.py b/erpnext/patches/v7_0/update_mins_to_first_response.py
deleted file mode 100644
index 16681357e6..0000000000
--- a/erpnext/patches/v7_0/update_mins_to_first_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from frappe.core.doctype.communication.communication import update_mins_to_first_communication
-
-def execute():
- frappe.reload_doctype('Issue')
- frappe.reload_doctype('Opportunity')
-
- for doctype in ('Issue', 'Opportunity'):
- frappe.db.sql('update tab{0} set mins_to_first_response=0'.format(doctype))
- for parent in frappe.get_all(doctype, order_by='creation desc', limit=500):
- parent_doc = frappe.get_doc(doctype, parent.name)
- for communication in frappe.get_all('Communication',
- filters={'reference_doctype': doctype, 'reference_name': parent.name,
- 'communication_medium': 'Email'},
- order_by = 'creation asc', limit=2):
-
- communication_doc = frappe.get_doc('Communication', communication.name)
-
- update_mins_to_first_communication(parent_doc, communication_doc)
-
- if parent_doc.mins_to_first_response:
- continue
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py b/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py
deleted file mode 100644
index 54d492b265..0000000000
--- a/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Log") and "employee" in frappe.db.get_table_columns("Time Log"):
- timesheet = frappe.db.sql("""select tl.employee as employee, ts.name as name,
- tl.modified as modified, tl.modified_by as modified_by, tl.creation as creation, tl.owner as owner
- from
- `tabTimesheet` ts, `tabTimesheet Detail` tsd, `tabTime Log` tl
- where
- tsd.parent = ts.name and tl.from_time = tsd.from_time and tl.to_time = tsd.to_time
- and tl.hours = tsd.hours and tl.billing_rate = tsd.billing_rate and tsd.idx=1
- and tl.docstatus < 2 and (ts.employee = '' or ts.employee is null)""", as_dict=1)
-
- for data in timesheet:
- ts_doc = frappe.get_doc('Timesheet', data.name)
- if len(ts_doc.time_logs) == 1:
- frappe.db.sql(""" update `tabTimesheet` set creation = %(creation)s,
- owner = %(owner)s, modified = %(modified)s, modified_by = %(modified_by)s,
- employee = %(employee)s where name = %(name)s""", data)
diff --git a/erpnext/patches/v7_0/update_mode_of_payment_type.py b/erpnext/patches/v7_0/update_mode_of_payment_type.py
deleted file mode 100644
index 9292a1be1b..0000000000
--- a/erpnext/patches/v7_0/update_mode_of_payment_type.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment')
-
- frappe.db.sql(""" update `tabMode of Payment` set type = 'Cash' where (type is null or type = '') and name = 'Cash'""")
-
- for data in frappe.db.sql("""select name from `tabSales Invoice` where is_pos=1 and docstatus<2 and
- (ifnull(paid_amount, 0) - ifnull(change_amount, 0)) > ifnull(grand_total, 0) and modified > '2016-05-01'""", as_dict=1):
- if data.name:
- si_doc = frappe.get_doc("Sales Invoice", data.name)
- remove_payment = []
- mode_of_payment = [d.mode_of_payment for d in si_doc.payments if flt(d.amount) > 0]
- if mode_of_payment != set(mode_of_payment):
- for payment_data in si_doc.payments:
- if payment_data.idx != 1 and payment_data.amount == si_doc.grand_total:
- remove_payment.append(payment_data)
- frappe.db.sql(""" delete from `tabSales Invoice Payment`
- where name = %(name)s""", {'name': payment_data.name})
-
- if len(remove_payment) > 0:
- for d in remove_payment:
- si_doc.remove(d)
-
- si_doc.set_paid_amount()
- si_doc.db_set("paid_amount", si_doc.paid_amount, update_modified = False)
- si_doc.db_set("base_paid_amount", si_doc.base_paid_amount, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_party_status.py b/erpnext/patches/v7_0/update_party_status.py
deleted file mode 100644
index 0c6b4ea598..0000000000
--- a/erpnext/patches/v7_0/update_party_status.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- return
- # for party_type in ('Customer', 'Supplier'):
- # frappe.reload_doctype(party_type)
- #
- # # set all as default status
- # frappe.db.sql('update `tab{0}` set status=%s'.format(party_type), default_status[party_type])
- #
- # for doctype in status_depends_on[party_type]:
- # filters = get_filters_for(doctype)
- # parties = frappe.get_all(doctype, fields="{0} as party".format(party_type.lower()),
- # filters=filters, limit_page_length=1)
- #
- # parties = filter(None, [p.party for p in parties])
- #
- # if parties:
- # frappe.db.sql('update `tab{0}` set status="Open" where name in ({1})'.format(party_type,
- # ', '.join(len(parties) * ['%s'])), parties)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py b/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py
deleted file mode 100644
index e90de50c1e..0000000000
--- a/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Supplier Quotation Item')
- for data in frappe.db.sql(""" select prevdoc_docname, prevdoc_detail_docname, name
- from `tabSupplier Quotation Item` where prevdoc_docname is not null""", as_dict=True):
- frappe.db.set_value("Supplier Quotation Item", data.name, "material_request", data.prevdoc_docname)
- frappe.db.set_value("Supplier Quotation Item", data.name, "material_request_item", data.prevdoc_detail_docname)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_project_in_gl_entry.py b/erpnext/patches/v7_0/update_project_in_gl_entry.py
deleted file mode 100644
index d99e9a41e3..0000000000
--- a/erpnext/patches/v7_0/update_project_in_gl_entry.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("GL Entry")
-
- for doctype in ("Delivery Note", "Sales Invoice", "Stock Entry"):
- frappe.db.sql("""
- update `tabGL Entry` gle, `tab{0}` dt
- set gle.project = dt.project
- where gle.voucher_type=%s and gle.voucher_no = dt.name
- and ifnull(gle.cost_center, '') != '' and ifnull(dt.project, '') != ''
- """.format(doctype), doctype)
-
- for doctype in ("Purchase Receipt", "Purchase Invoice"):
- frappe.db.sql("""
- update `tabGL Entry` gle, `tab{0} Item` dt
- set gle.project = dt.project
- where gle.voucher_type=%s and gle.voucher_no = dt.parent and gle.cost_center=dt.cost_center
- and ifnull(gle.cost_center, '') != '' and ifnull(dt.project, '') != ''
- """.format(doctype), doctype)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py b/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py
deleted file mode 100644
index 2d562bb40e..0000000000
--- a/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if "purchase_receipt" not in frappe.db.get_table_columns("Landed Cost Purchase Receipt"):
- return
-
- frappe.reload_doctype("Landed Cost Purchase Receipt")
-
- frappe.db.sql("""
- update `tabLanded Cost Purchase Receipt`
- set receipt_document_type = 'Purchase Receipt', receipt_document = purchase_receipt
- where (receipt_document is null or receipt_document = '')
- and (purchase_receipt is not null and purchase_receipt != '')
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_status_for_timesheet.py b/erpnext/patches/v7_0/update_status_for_timesheet.py
deleted file mode 100644
index 117c40c59f..0000000000
--- a/erpnext/patches/v7_0/update_status_for_timesheet.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update
- `tabTimesheet` as ts,
- (
- select min(from_time)as from_time, max(to_time) as to_time, parent from `tabTimesheet Detail` group by parent
- ) as tsd
- set ts.status = 'Submitted', ts.start_date = tsd.from_time, ts.end_date = tsd.to_time
- where tsd.parent = ts.name and ts.status = 'Draft' and ts.docstatus =1""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_status_of_po_so.py b/erpnext/patches/v7_0/update_status_of_po_so.py
deleted file mode 100644
index d630e8f0f2..0000000000
--- a/erpnext/patches/v7_0/update_status_of_po_so.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint, flt
-
-def execute():
- update_po_per_received_per_billed()
- update_so_per_delivered_per_billed()
- update_status()
-
-def update_po_per_received_per_billed():
- frappe.db.sql("""
- update
- `tabPurchase Order`
- set
- `tabPurchase Order`.per_received = round((select sum(if(qty > ifnull(received_qty, 0),
- ifnull(received_qty, 0), qty)) / sum(qty) *100 from `tabPurchase Order Item`
- where parent = `tabPurchase Order`.name), 2),
- `tabPurchase Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0),
- ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabPurchase Order Item`
- where parent = `tabPurchase Order`.name), 2), 0)
- where
- net_total > 0
- """)
-
-def update_so_per_delivered_per_billed():
- frappe.db.sql("""
- update
- `tabSales Order`
- set
- `tabSales Order`.per_delivered = round((select sum( if(qty > ifnull(delivered_qty, 0),
- ifnull(delivered_qty, 0), qty)) / sum(qty) *100 from `tabSales Order Item`
- where parent = `tabSales Order`.name), 2),
- `tabSales Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0),
- ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabSales Order Item`
- where parent = `tabSales Order`.name), 2), 0)
- where
- net_total > 0
- """)
-
-def update_status():
- frappe.db.sql("""
- update
- `tabSales Order`
- set status = (Case when status = 'Closed' then 'Closed'
- When per_delivered < 100 and per_billed < 100 and docstatus = 1 then 'To Deliver and Bill'
- when per_delivered = 100 and per_billed < 100 and docstatus = 1 then 'To Bill'
- when per_delivered < 100 and per_billed = 100 and docstatus = 1 then 'To Deliver'
- when per_delivered = 100 and per_billed = 100 and docstatus = 1 then 'Completed'
- when order_type = 'Maintenance' and per_billed = 100 and docstatus = 1 then 'Completed'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
-
- frappe.db.sql("""
- update
- `tabPurchase Order`
- set status = (Case when status = 'Closed' then 'Closed'
- when status = 'Delivered' then 'Delivered'
- When per_received < 100 and per_billed < 100 and docstatus = 1 then 'To Receive and Bill'
- when per_received = 100 and per_billed < 100 and docstatus = 1 then 'To Bill'
- when per_received < 100 and per_billed = 100 and docstatus = 1 then 'To Receive'
- when per_received = 100 and per_billed = 100 and docstatus = 1 then 'Completed'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py b/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py
deleted file mode 100644
index 9b2b24785a..0000000000
--- a/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for data in frappe.get_all('Sales Order', fields = ["name"], filters = [["docstatus", "=", "1"], ["grand_total", "=", "0"]]):
- sales_order = frappe.get_doc('Sales Order', data.name)
- sales_order.set_status(update=True, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_timesheet_communications.py b/erpnext/patches/v7_0/update_timesheet_communications.py
deleted file mode 100644
index 203471ea8f..0000000000
--- a/erpnext/patches/v7_0/update_timesheet_communications.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Log"):
- timesheet = frappe.db.sql("""SELECT ts.name AS name, tl.name AS timelogname,
- tl.modified AS modified, tl.modified_by AS modified_by, tl.creation AS creation, tl.owner AS owner
- FROM
- `tabTimesheet` ts, `tabTimesheet Detail` tsd, `tabTime Log` tl
- WHERE
- tsd.parent = ts.name AND tl.from_time = tsd.from_time AND tl.to_time = tsd.to_time
- AND tl.hours = tsd.hours AND tl.billing_rate = tsd.billing_rate AND tsd.idx=1
- AND tl.docstatus < 2""", as_dict=1)
-
- for data in timesheet:
- frappe.db.sql(""" update `tabTimesheet` set creation = %(creation)s,
- owner = %(owner)s, modified = %(modified)s, modified_by = %(modified_by)s
- where name = %(name)s""", data)
-
- frappe.db.sql("""
- update
- tabCommunication
- set
- reference_doctype = "Timesheet", reference_name = %(timesheet)s
- where
- reference_doctype = "Time Log" and reference_name = %(timelog)s
- """, {'timesheet': data.name, 'timelog': data.timelogname}, auto_commit=1)
diff --git a/erpnext/patches/v7_1/__init__.py b/erpnext/patches/v7_1/__init__.py
deleted file mode 100644
index 519ff49eac..0000000000
--- a/erpnext/patches/v7_1/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py b/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py
deleted file mode 100644
index 7372b0cc5f..0000000000
--- a/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.get_value('DocPerm', {'parent': 'Timesheet', 'role': 'Accounts User', 'permlevel': 1}):
- doc = frappe.get_doc('DocType', 'Timesheet')
- doc.append('permissions', {
- 'role': "Accounts User",
- 'permlevel': 0,
- 'read': 1,
- 'write': 1,
- 'create': 1,
- 'delete': 1,
- 'submit': 1,
- 'cancel': 1,
- 'amend': 1,
- 'report': 1,
- 'email': 1
- })
-
- doc.append('permissions', {
- 'role': "Accounts User",
- 'permlevel': 1,
- 'read': 1,
- 'write': 1
- })
-
- doc.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/add_field_for_task_dependent.py b/erpnext/patches/v7_1/add_field_for_task_dependent.py
deleted file mode 100644
index 65b1c74e87..0000000000
--- a/erpnext/patches/v7_1/add_field_for_task_dependent.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Task')
- for t in frappe.get_all('Task', fields=['name']):
- task = frappe.get_doc('Task', t.name)
- task.update_depends_on()
- if task.depends_on_tasks:
- task.db_set('depends_on_tasks', task.depends_on_tasks, update_modified=False)
diff --git a/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py b/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py
deleted file mode 100644
index 33f809fe37..0000000000
--- a/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for c in frappe.db.sql('select name from tabCustomer where ifnull(lead_name,"")!=""'):
- customer = frappe.get_doc('Customer', c[0])
- customer.update_lead_status()
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py b/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py
deleted file mode 100644
index d1ec7c697e..0000000000
--- a/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
-
- frappe.db.sql(""" update
- `tabTimesheet` as ts,
- (select
- sum(billing_amount) as billing_amount, sum(billing_hours) as billing_hours, time_sheet
- from `tabSales Invoice Timesheet` where docstatus = 1 group by time_sheet
- ) as sit
- set
- ts.total_billed_amount = sit.billing_amount, ts.total_billed_hours = sit.billing_hours,
- ts.per_billed = ((sit.billing_amount * 100)/ts.total_billable_amount)
- where ts.name = sit.time_sheet and ts.docstatus = 1""")
-
- frappe.db.sql(""" update `tabTimesheet Detail` tsd, `tabTimesheet` ts set tsd.sales_invoice = ts.sales_invoice
- where tsd.parent = ts.name and ts.sales_invoice is not null""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/rename_field_timesheet.py b/erpnext/patches/v7_1/rename_field_timesheet.py
deleted file mode 100644
index 3690a2e79d..0000000000
--- a/erpnext/patches/v7_1/rename_field_timesheet.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- doctype = 'Timesheet'
- fields_dict = {'total_billing_amount': 'total_billable_amount', 'total_billing_hours': 'total_billable_hours'}
-
- for old_fieldname, new_fieldname in fields_dict.items():
- if old_fieldname in frappe.db.get_table_columns(doctype):
- rename_field(doctype, old_fieldname, new_fieldname)
diff --git a/erpnext/patches/v7_1/rename_quality_inspection_field.py b/erpnext/patches/v7_1/rename_quality_inspection_field.py
deleted file mode 100644
index 3b5a7d95eb..0000000000
--- a/erpnext/patches/v7_1/rename_quality_inspection_field.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import *
-
-def execute():
- for doctype in ("Purchase Receipt Item", "Delivery Note Item"):
- frappe.reload_doctype(doctype)
-
- table_columns = frappe.db.get_table_columns(doctype)
- if "qa_no" in table_columns:
- rename_field(doctype, "qa_no", "quality_inspection")
-
- frappe.reload_doctype("Item")
- rename_field("Item", "inspection_required", "inspection_required_before_purchase")
-
- frappe.reload_doc('stock', 'doctype', 'quality_inspection')
- frappe.db.sql("""
- update
- `tabQuality Inspection`
- set
- reference_type = 'Purchase Receipt', reference_name = purchase_receipt_no
- where
- ifnull(purchase_receipt_no, '') != '' and inspection_type = 'Incoming'
- """)
-
- frappe.db.sql("""
- update
- `tabQuality Inspection`
- set
- reference_type = 'Delivery Note', reference_name = delivery_note_no
- where
- ifnull(delivery_note_no, '') != '' and inspection_type = 'Outgoing'
- """)
-
- for old_fieldname in ["purchase_receipt_no", "delivery_note_no"]:
- update_reports("Quality Inspection", old_fieldname, "reference_name")
- update_users_report_view_settings("Quality Inspection", old_fieldname, "reference_name")
- update_property_setters("Quality Inspection", old_fieldname, "reference_name")
diff --git a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py
deleted file mode 100644
index aca21085cc..0000000000
--- a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import repost_stock
-
-def execute():
- frappe.reload_doc('manufacturing', 'doctype', 'work_order_item')
- frappe.reload_doc('manufacturing', 'doctype', 'work_order')
-
- modified_items = frappe.db.sql_list("""
- select name from `tabItem`
- where is_stock_item=1 and modified >= '2016-10-31'
- """)
-
- if not modified_items:
- return
-
- item_warehouses_with_transactions = []
- transactions = ("Sales Order Item", "Material Request Item", "Purchase Order Item",
- "Stock Ledger Entry", "Packed Item")
-
- for doctype in transactions:
- item_warehouses_with_transactions += list(frappe.db.sql("""
- select distinct item_code, warehouse
- from `tab{0}` where docstatus=1 and item_code in ({1})"""
- .format(doctype, ', '.join(['%s']*len(modified_items))), tuple(modified_items)))
-
- item_warehouses_with_transactions += list(frappe.db.sql("""
- select distinct production_item, fg_warehouse
- from `tabWork Order` where docstatus=1 and production_item in ({0})"""
- .format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
-
- item_warehouses_with_transactions += list(frappe.db.sql("""
- select distinct pr_item.item_code, pr_item.source_warehouse
- from `tabWork Order` pr, `tabWork Order Item` pr_item
- where pr_item.parent and pr.name and pr.docstatus=1 and pr_item.item_code in ({0})"""
- .format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
-
- item_warehouses_with_bin = list(frappe.db.sql("select distinct item_code, warehouse from `tabBin`"))
-
- item_warehouses_with_missing_bin = list(
- set(item_warehouses_with_transactions) - set(item_warehouses_with_bin))
-
- for item_code, warehouse in item_warehouses_with_missing_bin:
- repost_stock(item_code, warehouse)
diff --git a/erpnext/patches/v7_1/save_stock_settings.py b/erpnext/patches/v7_1/save_stock_settings.py
deleted file mode 100644
index d3f0263c10..0000000000
--- a/erpnext/patches/v7_1/save_stock_settings.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- stock_settings = frappe.get_doc('Stock Settings')
-
- if stock_settings.default_warehouse \
- and not frappe.db.exists("Warehouse", stock_settings.default_warehouse):
- stock_settings.default_warehouse = None
-
- if stock_settings.stock_uom and not frappe.db.exists("UOM", stock_settings.stock_uom):
- stock_settings.stock_uom = None
-
- stock_settings.flags.ignore_mandatory = True
- stock_settings.save()
diff --git a/erpnext/patches/v7_1/set_budget_against_as_cost_center.py b/erpnext/patches/v7_1/set_budget_against_as_cost_center.py
deleted file mode 100644
index dd9a432cf0..0000000000
--- a/erpnext/patches/v7_1/set_budget_against_as_cost_center.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "budget")
- frappe.db.sql("""
- update
- `tabBudget`
- set
- budget_against = 'Cost Center'
- """)
diff --git a/erpnext/patches/v7_1/set_currency_exchange_date.py b/erpnext/patches/v7_1/set_currency_exchange_date.py
deleted file mode 100644
index 2a2d420f21..0000000000
--- a/erpnext/patches/v7_1/set_currency_exchange_date.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Currency Exchange")
- frappe.db.sql("""
- update `tabCurrency Exchange`
- set `date` = '2010-01-01'
- where date is null or date = '0000-00-00'
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/set_prefered_contact_email.py b/erpnext/patches/v7_1/set_prefered_contact_email.py
deleted file mode 100644
index 3b68e22269..0000000000
--- a/erpnext/patches/v7_1/set_prefered_contact_email.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('User')
- for d in frappe.get_all("Employee"):
- employee = frappe.get_doc("Employee", d.name)
- if employee.company_email:
- employee.prefered_contact_email = "Company Email"
- employee.prefered_email = employee.company_email
- elif employee.personal_email:
- employee.prefered_contact_email = "Personal Email"
- employee.prefered_email = employee.personal_email
- elif employee.user_id:
- employee.prefered_contact_email = "User ID"
- employee.prefered_email = employee.user_id
- employee.db_update()
diff --git a/erpnext/patches/v7_1/set_sales_person_status.py b/erpnext/patches/v7_1/set_sales_person_status.py
deleted file mode 100644
index 929beac27f..0000000000
--- a/erpnext/patches/v7_1/set_sales_person_status.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('setup','doctype','sales_person')
- frappe.db.sql("""update `tabSales Person` set enabled=1
- where (employee is null or employee = ''
- or employee IN (select employee from tabEmployee where status != "Left"))""")
diff --git a/erpnext/patches/v7_1/set_student_guardian.py b/erpnext/patches/v7_1/set_student_guardian.py
deleted file mode 100644
index 093c0bf6d9..0000000000
--- a/erpnext/patches/v7_1/set_student_guardian.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Guardian"):
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "student")
- # frappe.reload_doc("schools", "doctype", "student_guardian")
- # frappe.reload_doc("schools", "doctype", "student_sibling")
-
- frappe.reload_doc("education", "doctype", "student")
- frappe.reload_doc("education", "doctype", "student_guardian")
- frappe.reload_doc("education", "doctype", "student_sibling")
- if "student" not in frappe.db.get_table_columns("Guardian"):
- return
- guardian = frappe.get_all("Guardian", fields=["name", "student"])
- for d in guardian:
- if d.student:
- student = frappe.get_doc("Student", d.student)
- if student:
- student.append("guardians", {"guardian": d.name})
- student.save()
diff --git a/erpnext/patches/v7_1/set_total_amount_currency_in_je.py b/erpnext/patches/v7_1/set_total_amount_currency_in_je.py
deleted file mode 100644
index 8426ddcd7d..0000000000
--- a/erpnext/patches/v7_1/set_total_amount_currency_in_je.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext import get_default_currency
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "journal_entry")
-
- frappe.db.sql(""" update `tabJournal Entry` set total_amount_currency = %s
- where ifnull(multi_currency, 0) = 0
- and (pay_to_recd_from is not null or pay_to_recd_from != "") """, get_default_currency())
-
- for je in frappe.db.sql(""" select name from `tabJournal Entry` where multi_currency = 1
- and (pay_to_recd_from is not null or pay_to_recd_from != "")""", as_dict=1):
-
- doc = frappe.get_doc("Journal Entry", je.name)
- for d in doc.get('accounts'):
- if d.party_type and d.party:
- total_amount_currency = d.account_currency
-
- elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]:
- total_amount_currency = d.account_currency
-
- frappe.db.set_value("Journal Entry", je.name, "total_amount_currency",
- total_amount_currency, update_modified=False)
diff --git a/erpnext/patches/v7_1/update_bom_base_currency.py b/erpnext/patches/v7_1/update_bom_base_currency.py
deleted file mode 100644
index 9a59209ea5..0000000000
--- a/erpnext/patches/v7_1/update_bom_base_currency.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext import get_default_currency
-
-def execute():
- frappe.reload_doc("manufacturing", "doctype", "bom")
- frappe.reload_doc("manufacturing", "doctype", "bom_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_explosion_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_operation")
- frappe.reload_doc("manufacturing", "doctype", "bom_scrap_item")
-
- frappe.db.sql(""" update `tabBOM Operation` set base_hour_rate = hour_rate,
- base_operating_cost = operating_cost """)
-
- frappe.db.sql(""" update `tabBOM Item` set base_rate = rate, base_amount = amount """)
- frappe.db.sql(""" update `tabBOM Scrap Item` set base_rate = rate, base_amount = amount """)
-
- frappe.db.sql(""" update `tabBOM` set `tabBOM`.base_operating_cost = `tabBOM`.operating_cost,
- `tabBOM`.base_raw_material_cost = `tabBOM`.raw_material_cost,
- `tabBOM`.currency = (select default_currency from `tabCompany` where name = `tabBOM`.company)""")
diff --git a/erpnext/patches/v7_1/update_component_type.py b/erpnext/patches/v7_1/update_component_type.py
deleted file mode 100644
index 24ca0570e0..0000000000
--- a/erpnext/patches/v7_1/update_component_type.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doc('Payroll', 'doctype', 'salary_component')
- sal_components = frappe.db.sql("""
- select DISTINCT salary_component, parentfield from `tabSalary Detail`""", as_dict=True)
-
- if sal_components:
- for sal_component in sal_components:
- if sal_component.parentfield == "earnings":
- frappe.db.sql("""update `tabSalary Component` set type='Earning' where salary_component=%(sal_comp)s""",{"sal_comp": sal_component.salary_component})
- else:
- frappe.db.sql("""update `tabSalary Component` set type='Deduction' where salary_component=%(sal_comp)s""",{"sal_comp": sal_component.salary_component})
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/update_invoice_status.py b/erpnext/patches/v7_1/update_invoice_status.py
deleted file mode 100644
index 851af80f7a..0000000000
--- a/erpnext/patches/v7_1/update_invoice_status.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice')
-
- frappe.db.sql("""
- update
- `tabPurchase Invoice`
- set
- status = (Case When outstanding_amount = 0 and docstatus = 1 and is_return = 0 then 'Paid'
- when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue'
- when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid'
- when outstanding_amount < 0 and docstatus =1 then 'Debit Note Issued'
- when is_return = 1 and docstatus =1 then 'Return'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
-
- frappe.db.sql("""
- update
- `tabSales Invoice`
- set status = (Case When outstanding_amount = 0 and docstatus = 1 and is_return = 0 then 'Paid'
- when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue'
- when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid'
- when outstanding_amount < 0 and docstatus =1 then 'Credit Note Issued'
- when is_return = 1 and docstatus =1 then 'Return'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/update_lead_source.py b/erpnext/patches/v7_1/update_lead_source.py
deleted file mode 100644
index a2a48a62e1..0000000000
--- a/erpnext/patches/v7_1/update_lead_source.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- from erpnext.setup.setup_wizard.operations.install_fixtures import default_lead_sources
-
- frappe.reload_doc('crm', 'doctype', 'lead_source')
-
- frappe.local.lang = frappe.db.get_default("lang") or 'en'
-
- for s in default_lead_sources:
- insert_lead_source(_(s))
-
- # get lead sources in existing forms (customized)
- # and create a document if not created
- for d in ['Lead', 'Opportunity', 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']:
- sources = frappe.db.sql_list('select distinct source from `tab{0}`'.format(d))
- for s in sources:
- if s and s not in default_lead_sources:
- insert_lead_source(s)
-
- # remove customization for source
- for p in frappe.get_all('Property Setter', {'doc_type':d, 'field_name':'source', 'property':'options'}):
- frappe.delete_doc('Property Setter', p.name)
-
-def insert_lead_source(s):
- if not frappe.db.exists('Lead Source', s):
- frappe.get_doc(dict(doctype='Lead Source', source_name=s)).insert()
diff --git a/erpnext/patches/v7_1/update_missing_salary_component_type.py b/erpnext/patches/v7_1/update_missing_salary_component_type.py
deleted file mode 100644
index 824f2b881f..0000000000
--- a/erpnext/patches/v7_1/update_missing_salary_component_type.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-from frappe.utils import cstr
-
-'''
-Some components do not have type set, try and guess whether they turn up in
-earnings or deductions in existing salary slips
-'''
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "salary_component_account")
- frappe.reload_doc("Payroll", "doctype", "salary_component")
- frappe.reload_doc("Payroll", "doctype", "taxable_salary_slab")
-
- for s in frappe.db.sql('''select name, type, salary_component_abbr from `tabSalary Component`
- where ifnull(type, "")="" or ifnull(salary_component_abbr, "") = ""''', as_dict=1):
-
- component = frappe.get_doc('Salary Component', s.name)
-
- # guess
- if not s.type:
- guess = frappe.db.sql('''select
- parentfield from `tabSalary Detail`
- where salary_component=%s limit 1''', s.name)
-
- if guess:
- component.type = 'Earning' if guess[0][0]=='earnings' else 'Deduction'
-
- else:
- component.type = 'Deduction'
-
- if not s.salary_component_abbr:
- abbr = ''.join([c[0] for c in component.salary_component.split()]).upper()
-
- abbr_count = frappe.db.sql("""
- select
- count(name)
- from
- `tabSalary Component`
- where
- salary_component_abbr = %s or salary_component_abbr like %s
- """, (abbr, abbr + "-%%"))
-
- if abbr_count and abbr_count[0][0] > 0:
- abbr = abbr + "-" + cstr(abbr_count[0][0])
-
- component.salary_component_abbr = abbr
-
- component.save()
diff --git a/erpnext/patches/v7_1/update_portal_roles.py b/erpnext/patches/v7_1/update_portal_roles.py
deleted file mode 100644
index 482586b8ef..0000000000
--- a/erpnext/patches/v7_1/update_portal_roles.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Role')
- frappe.reload_doctype('User')
- for role_name in ('Customer', 'Supplier', 'Student'):
- if frappe.db.exists('Role', role_name):
- frappe.db.set_value('Role', role_name, 'desk_access', 0)
- else:
- frappe.get_doc(dict(doctype='Role', role_name=role_name, desk_access=0)).insert()
-
-
- # set customer, supplier roles
- for c in frappe.get_all('Contact', fields=['user'], filters={'ifnull(user, "")': ('!=', '')}):
- user = frappe.get_doc('User', c.user)
- user.flags.ignore_validate = True
- user.flags.ignore_mandatory = True
- user.save()
-
-
diff --git a/erpnext/patches/v7_1/update_total_billing_hours.py b/erpnext/patches/v7_1/update_total_billing_hours.py
deleted file mode 100644
index b9c96028f5..0000000000
--- a/erpnext/patches/v7_1/update_total_billing_hours.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
-
- frappe.db.sql("""update tabTimesheet set total_billable_hours=total_hours
- where total_billable_amount>0 and docstatus = 1""")
-
- frappe.db.sql("""update `tabTimesheet Detail` set billing_hours=hours where docstatus < 2""")
-
- frappe.db.sql(""" update `tabSales Invoice Timesheet` set billing_hours = (select total_billable_hours from `tabTimesheet`
- where name = time_sheet) where time_sheet is not null""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/__init__.py b/erpnext/patches/v7_2/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v7_2/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py b/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py
deleted file mode 100644
index d2583b9422..0000000000
--- a/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # frappe.reload_doctype('Salary Slip', 'Salary Component')
- frappe.reload_doc("Payroll", "doctype", "Salary Slip")
- frappe.reload_doc("Payroll", "doctype", "Salary Component")
- salary_components = [['Arrear', "ARR"], ['Leave Encashment', 'LENC']]
- for salary_component, salary_abbr in salary_components:
- if not frappe.db.exists('Salary Component', salary_component):
- sal_comp = frappe.get_doc({
- "doctype": "Salary Component",
- "salary_component": salary_component,
- "type": "Earning",
- "salary_component_abbr": salary_abbr
- }).insert()
-
- salary_slips = frappe.db.sql("""select name, arrear_amount, leave_encashment_amount from `tabSalary Slip`
- where docstatus !=2 and (arrear_amount > 0 or leave_encashment_amount > 0)""", as_dict=True)
-
- for salary_slip in salary_slips:
- doc = frappe.get_doc('Salary Slip', salary_slip.name)
-
- if salary_slip.get("arrear_amount") > 0:
- r = doc.append('earnings', {
- 'salary_component': 'Arrear',
- 'amount': salary_slip.arrear_amount
- })
- r.db_update()
-
- if salary_slip.get("leave_encashment_amount") > 0:
- r = doc.append('earnings', {
- 'salary_component': 'Leave Encashment',
- 'amount': salary_slip.leave_encashment_amount
- })
- r.db_update()
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/contact_address_links.py b/erpnext/patches/v7_2/contact_address_links.py
deleted file mode 100644
index 200434c208..0000000000
--- a/erpnext/patches/v7_2/contact_address_links.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links
-from frappe.utils import update_progress_bar
-
-def execute():
- frappe.reload_doc('core', 'doctype', 'dynamic_link')
- frappe.reload_doc('contacts', 'doctype', 'contact')
- frappe.reload_doc('contacts', 'doctype', 'address')
- map_fields = (
- ('Customer', 'customer'),
- ('Supplier', 'supplier'),
- ('Lead', 'lead'),
- ('Sales Partner', 'sales_partner')
- )
- for doctype in ('Contact', 'Address'):
- if frappe.db.has_column(doctype, 'customer'):
- items = frappe.get_all(doctype)
- for i, doc in enumerate(items):
- doc = frappe.get_doc(doctype, doc.name)
- dirty = False
- for field in map_fields:
- if doc.get(field[1]):
- doc.append('links', dict(link_doctype=field[0], link_name=doc.get(field[1])))
- dirty = True
-
- if dirty:
- deduplicate_dynamic_links(doc)
- doc.update_children()
-
- update_progress_bar('Updating {0}'.format(doctype), i, len(items))
- print
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/delete_fleet_management_module_def.py b/erpnext/patches/v7_2/delete_fleet_management_module_def.py
deleted file mode 100644
index 542ac11e3f..0000000000
--- a/erpnext/patches/v7_2/delete_fleet_management_module_def.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists('Module Def', 'Fleet Management'):
- frappe.db.sql("""delete from `tabModule Def`
- where module_name = 'Fleet Management'""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py b/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py
deleted file mode 100644
index ec6f8afc3a..0000000000
--- a/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]:
- child_table = 'Purchase Receipt Item Supplied' if doctype != 'Purchase Order' else 'Purchase Order Item Supplied'
- for data in frappe.db.sql(""" select distinct `tab{doctype}`.name from `tab{doctype}` , `tab{child_table}`
- where `tab{doctype}`.name = `tab{child_table}`.parent and `tab{doctype}`.docstatus != 2
- and `tab{doctype}`.is_subcontracted = 'No' """.format(doctype = doctype, child_table = child_table), as_dict=1):
- frappe.db.sql(""" delete from `tab{child_table}`
- where parent = %s and parenttype = %s""".format(child_table= child_table), (data.name, doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/make_all_assessment_group.py b/erpnext/patches/v7_2/make_all_assessment_group.py
deleted file mode 100644
index f3ec628374..0000000000
--- a/erpnext/patches/v7_2/make_all_assessment_group.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists({"doctype": "Assessment Group","assessment_group_name": "All Assessment Groups"}):
- frappe.reload_doc("education", "doctype", "assessment_group")
- doc = frappe.new_doc("Assessment Group")
- doc.assessment_group_name = "All Assessment Groups"
- doc.is_group = 1
- doc.flags.ignore_mandatory = True
- doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/mark_students_active.py b/erpnext/patches/v7_2/mark_students_active.py
deleted file mode 100644
index 7289e4a915..0000000000
--- a/erpnext/patches/v7_2/mark_students_active.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc('schools', 'doctype', 'student_group_student')
-
- frappe.reload_doc('education', 'doctype', 'student_group_student')
- frappe.db.sql("update `tabStudent Group Student` set active=1")
diff --git a/erpnext/patches/v7_2/rename_att_date_attendance.py b/erpnext/patches/v7_2/rename_att_date_attendance.py
deleted file mode 100644
index 7f06d8f123..0000000000
--- a/erpnext/patches/v7_2/rename_att_date_attendance.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import update_reports, update_users_report_view_settings, update_property_setters
-
-def execute():
- if "att_date" not in frappe.db.get_table_columns("Attendance"):
- return
- frappe.reload_doc("hr", "doctype", "attendance")
- frappe.db.sql("""update `tabAttendance`
- set attendance_date = att_date
- where attendance_date is null or attendance_date = '0000-00-00'""")
-
- update_reports("Attendance", "att_date", "attendance_date")
- update_users_report_view_settings("Attendance", "att_date", "attendance_date")
- update_property_setters("Attendance", "att_date", "attendance_date")
diff --git a/erpnext/patches/v7_2/rename_evaluation_criteria.py b/erpnext/patches/v7_2/rename_evaluation_criteria.py
deleted file mode 100644
index c6520b1b72..0000000000
--- a/erpnext/patches/v7_2/rename_evaluation_criteria.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- # 'Schools' module changed to the 'Education'
-
-
- frappe.rename_doc("DocType", "Evaluation Criteria", "Assessment Criteria", force=True)
- # frappe.reload_doc("schools", "doctype", "assessment_criteria")
- frappe.reload_doc("education", "doctype", "assessment_criteria")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Criteria'):
- rename_field("Assessment Criteria", "evaluation_criteria", "assessment_criteria")
-
- frappe.rename_doc("DocType", "Assessment Evaluation Criteria", "Assessment Plan Criteria", force=True)
- # frappe.reload_doc("schools", "doctype", "assessment_plan_criteria")
- frappe.reload_doc("education", "doctype", "assessment_plan_criteria")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Plan'):
- rename_field("Assessment Plan Criteria", "evaluation_criteria", "assessment_criteria")
-
- # frappe.reload_doc("schools", "doctype", "assessment_plan")
- frappe.reload_doc("education", "doctype", "assessment_plan")
- rename_field("Assessment Plan", "evaluation_criterias", "assessment_criteria")
-
- # frappe.reload_doc("schools", "doctype", "assessment_result_detail")
- frappe.reload_doc("education", "doctype", "assessment_result_detail")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Result Detail'):
- rename_field("Assessment Result Detail", "evaluation_criteria", "assessment_criteria")
-
- frappe.rename_doc("DocType", "Course Evaluation Criteria", "Course Assessment Criteria", force=True)
- # frappe.reload_doc("schools", "doctype", "course_assessment_criteria")
- frappe.reload_doc("education", "doctype", "course_assessment_criteria")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Course Assessment Criteria'):
- rename_field("Course Assessment Criteria", "evaluation_criteria", "assessment_criteria")
-
- # frappe.reload_doc("schools", "doctype", "course")
- frappe.reload_doc("education", "doctype", "course")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Course'):
- rename_field("Course", "evaluation_criterias", "assessment_criteria")
diff --git a/erpnext/patches/v7_2/set_null_value_to_fields.py b/erpnext/patches/v7_2/set_null_value_to_fields.py
deleted file mode 100644
index 6388be438d..0000000000
--- a/erpnext/patches/v7_2/set_null_value_to_fields.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- fields = {"Cost Center": "project", "Project": "cost_center"}
- for budget_against, field in fields.items():
- frappe.db.sql(""" update `tabBudget` set {field} = null
- where budget_against = %s """.format(field = field), budget_against)
diff --git a/erpnext/patches/v7_2/setup_auto_close_settings.py b/erpnext/patches/v7_2/setup_auto_close_settings.py
deleted file mode 100644
index 4eef2b9c8a..0000000000
--- a/erpnext/patches/v7_2/setup_auto_close_settings.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # update the selling settings and set the close_opportunity_after_days
- frappe.reload_doc("selling", "doctype", "selling_settings")
- frappe.db.set_value("Selling Settings", "Selling Settings", "close_opportunity_after_days", 15)
-
- # Auto close Replied opportunity
- frappe.db.sql("""update `tabOpportunity` set status='Closed' where status='Replied'
- and date_sub(curdate(), interval 15 Day)>modified""")
-
- # create Support Settings doctype and update close_issue_after_days
- frappe.reload_doc("support", "doctype", "support_settings")
- frappe.db.set_value("Support Settings", "Support Settings", "close_issue_after_days", 7)
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/stock_uom_in_selling.py b/erpnext/patches/v7_2/stock_uom_in_selling.py
deleted file mode 100644
index d029555747..0000000000
--- a/erpnext/patches/v7_2/stock_uom_in_selling.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Sales Order')
- frappe.reload_doctype('Sales Invoice')
- frappe.reload_doctype('Quotation')
- frappe.reload_doctype('Delivery Note')
-
- doctype_list = ['Sales Order Item', 'Delivery Note Item', 'Quotation Item', 'Sales Invoice Item']
-
- for doctype in doctype_list:
- frappe.reload_doctype(doctype)
- frappe.db.sql("""update `tab{doctype}`
- set uom = stock_uom, conversion_factor = 1, stock_qty = qty""".format(doctype=doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_abbr_in_salary_slips.py b/erpnext/patches/v7_2/update_abbr_in_salary_slips.py
deleted file mode 100644
index 57432fe986..0000000000
--- a/erpnext/patches/v7_2/update_abbr_in_salary_slips.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('Payroll', 'doctype', 'Salary Slip')
- if not frappe.db.has_column('Salary Detail', 'abbr'):
- return
-
- salary_details = frappe.db.sql("""select abbr, salary_component, name from `tabSalary Detail`
- where abbr is null or abbr = ''""", as_dict=True)
-
- for salary_detail in salary_details:
- salary_component_abbr = frappe.get_value("Salary Component", salary_detail.salary_component, "salary_component_abbr")
- frappe.db.sql("""update `tabSalary Detail` set abbr = %s where name = %s""",(salary_component_abbr, salary_detail.name))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_assessment_modules.py b/erpnext/patches/v7_2/update_assessment_modules.py
deleted file mode 100644
index 2b5e774d46..0000000000
--- a/erpnext/patches/v7_2/update_assessment_modules.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- #Rename Grading Structure to Grading Scale
- if not frappe.db.exists("DocType", "Grading Scale"):
- frappe.rename_doc("DocType", "Grading Structure", "Grading Scale", force=True)
- if not frappe.db.exists("DocType", "Grading Scale Interval"):
- frappe.rename_doc("DocType", "Grade Interval", "Grading Scale Interval", force=True)
-
- # frappe.reload_doc("schools", "doctype", "grading_scale_interval")
- frappe.reload_doc("education", "doctype", "grading_scale_interval")
- if "to_score" in frappe.db.get_table_columns("Grading Scale Interval"):
- rename_field("Grading Scale Interval", "to_score", "threshold")
-
- if not frappe.db.exists("DocType", "Assessment Plan"):
- frappe.rename_doc("DocType", "Assessment", "Assessment Plan", force=True)
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "assessment_plan")
-
- #Rename Assessment Results
- frappe.reload_doc("education", "doctype", "assessment_plan")
- if "grading_structure" in frappe.db.get_table_columns("Assessment Plan"):
- rename_field("Assessment Plan", "grading_structure", "grading_scale")
-
- # frappe.reload_doc("schools", "doctype", "assessment_result")
- # frappe.reload_doc("schools", "doctype", "assessment_result_detail")
- # frappe.reload_doc("schools", "doctype", "assessment_criteria")
- frappe.reload_doc("education", "doctype", "assessment_result")
- frappe.reload_doc("education", "doctype", "assessment_result_detail")
- frappe.reload_doc("education", "doctype", "assessment_criteria")
-
-
- for assessment in frappe.get_all("Assessment Plan",
- fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]):
- for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s",
- assessment.name, as_dict=True):
- if stud_result.result:
- assessment_result = frappe.new_doc("Assessment Result")
- assessment_result.student = stud_result.student
- assessment_result.student_name = stud_result.student_name
- assessment_result.assessment_plan = assessment.name
- assessment_result.grading_scale = assessment.grading_scale
- assessment_result.total_score = stud_result.result
- assessment_result.flags.ignore_validate = True
- assessment_result.flags.ignore_mandatory = True
- assessment_result.save()
-
- frappe.db.sql("""delete from `tabAssessment Result` where parent != '' or parent is not null""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_attendance_docstatus.py b/erpnext/patches/v7_2/update_attendance_docstatus.py
deleted file mode 100644
index a69052657d..0000000000
--- a/erpnext/patches/v7_2/update_attendance_docstatus.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("education", "doctype", "student_attendance")
- frappe.db.sql('''
- update `tabStudent Attendance` set
- docstatus=0
- where
- docstatus=1''')
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_doctype_status.py b/erpnext/patches/v7_2/update_doctype_status.py
deleted file mode 100644
index c66f3f2e73..0000000000
--- a/erpnext/patches/v7_2/update_doctype_status.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctypes = ["Opportunity", "Quotation", "Sales Order", "Sales Invoice", "Purchase Invoice", "Purchase Order", "Delivery Note", "Purchase Receipt"]
- for doctype in doctypes:
- frappe.db.sql(""" update `tab{doctype}` set status = 'Draft'
- where status = 'Cancelled' and docstatus = 0 """.format(doctype = doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_guardian_name_in_student_master.py b/erpnext/patches/v7_2/update_guardian_name_in_student_master.py
deleted file mode 100644
index 9f589ef00e..0000000000
--- a/erpnext/patches/v7_2/update_guardian_name_in_student_master.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "student_guardian")
- frappe.reload_doc("education", "doctype", "student_guardian")
-
- student_guardians = frappe.get_all("Student Guardian", fields=["guardian"])
- for student_guardian in student_guardians:
- guardian_name = frappe.db.get_value("Guardian", student_guardian.guardian, "guardian_name")
- frappe.db.sql("update `tabStudent Guardian` set guardian_name = %s where guardian= %s",
- (guardian_name, student_guardian.guardian))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_party_type.py b/erpnext/patches/v7_2/update_party_type.py
deleted file mode 100644
index 147f5a3643..0000000000
--- a/erpnext/patches/v7_2/update_party_type.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('setup', 'doctype', 'party_type')
- make_party_type()
-
-def make_party_type():
- for party_type in ["Customer", "Supplier", "Employee"]:
- if not frappe.db.get_value("Party Type", party_type):
- doc = frappe.new_doc("Party Type")
- doc.party_type = party_type
- doc.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py
deleted file mode 100644
index 9fcce62d8f..0000000000
--- a/erpnext/patches/v7_2/update_salary_slips.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details
-from frappe.utils import cint
-
-def execute():
- frappe.reload_doc("Payroll", "doctype", "Salary Slip")
- if not frappe.db.has_column('Salary Slip', 'fiscal_year'):
- return
-
- salary_slips = frappe.db.sql("""select month, name, fiscal_year from `tabSalary Slip`
- where (month is not null and month != '') and
- start_date is null and end_date is null and docstatus != 2""", as_dict=True)
-
- for salary_slip in salary_slips:
- if not cint(salary_slip.month):
- continue
- get_start_end_date = get_month_details(salary_slip.fiscal_year, cint(salary_slip.month))
- start_date = get_start_end_date['month_start_date']
- end_date = get_start_end_date['month_end_date']
- frappe.db.sql("""update `tabSalary Slip` set start_date = %s, end_date = %s where name = %s""",
- (start_date, end_date, salary_slip.name))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_website_for_variant.py b/erpnext/patches/v7_2/update_website_for_variant.py
deleted file mode 100644
index e8eef6e7da..0000000000
--- a/erpnext/patches/v7_2/update_website_for_variant.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # variant must have show_in_website = 0
- frappe.reload_doctype('Item')
- frappe.db.sql('''
- update tabItem set
- show_variant_in_website = 1,
- show_in_website = 0
- where
- show_in_website=1
- and ifnull(variant_of, "")!=""''')
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/__init__.py b/erpnext/patches/v8_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v8_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v8_0/addresses_linked_to_lead.py b/erpnext/patches/v8_0/addresses_linked_to_lead.py
deleted file mode 100644
index b5f2234228..0000000000
--- a/erpnext/patches/v8_0/addresses_linked_to_lead.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""UPDATE `tabDynamic Link` SET link_doctype = 'Lead' WHERE link_doctype = 'Load'""")
diff --git a/erpnext/patches/v8_0/change_in_words_varchar_length.py b/erpnext/patches/v8_0/change_in_words_varchar_length.py
deleted file mode 100644
index 68ff95b5ed..0000000000
--- a/erpnext/patches/v8_0/change_in_words_varchar_length.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctypes = frappe.db.sql_list("""select parent from tabDocField where fieldname = 'in_words'""")
-
- for dt in doctypes:
- for fieldname in ("in_words", "base_in_words"):
- frappe.db.sql("alter table `tab{0}` change column `{1}` `{2}` varchar(255)"
- .format(dt, fieldname, fieldname))
-
- frappe.db.sql("""alter table `tabJournal Entry`
- change column `total_amount_in_words` `total_amount_in_words` varchar(255)""")
diff --git a/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py b/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py
deleted file mode 100644
index cf1bc5af05..0000000000
--- a/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # new field address_html is created in place of address field for the company's address in PR #8754 (without patch)
- # so here is the patch for moving the address details in the address doc
- company_list = []
- if 'address' in frappe.db.get_table_columns('Company'):
- company_list = frappe.db.sql('''select name, address from `tabCompany`
- where address is not null and address != ""''', as_dict=1)
-
- for company in company_list:
- add_list = company.address.split(" ")
- if ',' in company.address:
- add_list = company.address.rpartition(',')
- elif ' ' in company.address:
- add_list = company.address.rpartition(' ')
- else:
- add_list = [company.address, None, company.address]
-
- doc = frappe.get_doc({
- "doctype":"Address",
- "address_line1": add_list[0],
- "city": add_list[2],
- "links": [{
- "link_doctype": "Company",
- "link_name": company.name
- }]
- })
- doc.save()
diff --git a/erpnext/patches/v8_0/create_domain_docs.py b/erpnext/patches/v8_0/create_domain_docs.py
deleted file mode 100644
index 3ef4f3c1bb..0000000000
--- a/erpnext/patches/v8_0/create_domain_docs.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import erpnext
-
-def execute():
- """Create domain documents"""
- frappe.reload_doc("core", "doctype", "domain")
- frappe.reload_doc("core", "doctype", "domain_settings")
- frappe.reload_doc("core", "doctype", "has_domain")
- frappe.reload_doc("core", "doctype", "role")
-
- for domain in ("Distribution", "Manufacturing", "Retail", "Services", "Education"):
- if not frappe.db.exists({"doctype": "Domain", "domain": domain}):
- create_domain(domain)
-
- # set domain in domain settings based on company domain
-
- domains = []
- condition = ""
- company = erpnext.get_default_company()
- if company:
- condition = " and name={0}".format(frappe.db.escape(company))
-
- domains = frappe.db.sql_list("select distinct domain from `tabCompany` where domain != 'Other' {0}".format(condition))
-
- if not domains:
- return
-
- domain_settings = frappe.get_doc("Domain Settings", "Domain Settings")
- checked_domains = [row.domain for row in domain_settings.active_domains]
-
- for domain in domains:
- # check and ignore if the domains is already checked in domain settings
- if domain in checked_domains:
- continue
-
- if not frappe.db.get_value("Domain", domain):
- # user added custom domain in companies domain field
- create_domain(domain)
-
- row = domain_settings.append("active_domains", dict(domain=domain))
-
- domain_settings.save(ignore_permissions=True)
-
-def create_domain(domain):
- # create new domain
-
- doc = frappe.new_doc("Domain")
- doc.domain = domain
- doc.db_update()
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/delete_bin_indexes.py b/erpnext/patches/v8_0/delete_bin_indexes.py
deleted file mode 100644
index 12cacdb952..0000000000
--- a/erpnext/patches/v8_0/delete_bin_indexes.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-# -*- coding: utf-8 -*-
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # delete bin indexes
- unwanted_indexes = ["item_code", "warehouse"]
-
- for k in unwanted_indexes:
- try:
- frappe.db.sql("drop index {0} on `tabBin`".format(k))
- except:
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py b/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
deleted file mode 100644
index 09a78ed3ca..0000000000
--- a/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ delete doctypes """
-
- if frappe.db.exists("DocType", "Grading Structure"):
- frappe.delete_doc("DocType", "Grading Structure", force=1)
-
- if frappe.db.exists("DocType", "Grade Interval"):
- frappe.delete_doc("DocType", "Grade Interval", force=1)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/disable_instructor_role.py b/erpnext/patches/v8_0/disable_instructor_role.py
deleted file mode 100644
index 4ba78d172c..0000000000
--- a/erpnext/patches/v8_0/disable_instructor_role.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """
- disable the instructor role for companies with domain other than
- Education.
- """
-
- domains = frappe.db.sql_list("select domain from tabCompany")
- if "Education" not in domains:
- if frappe.db.exists("Role", "Instructor"):
- role = frappe.get_doc("Role", "Instructor")
- role.disabled = 1
- role.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py b/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py
deleted file mode 100644
index 1088d702dd..0000000000
--- a/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.set_value("Accounts Settings", None,
- "book_asset_depreciation_entry_automatically", 1)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py b/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py
deleted file mode 100644
index 2e7f360c97..0000000000
--- a/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt, status in [["Sales Invoice", "Credit Note Issued"], ["Purchase Invoice", "Debit Note Issued"]]:
- invoices = frappe.db.sql("""
- select name
- from `tab{0}`
- where
- status = %s
- and outstanding_amount < 0
- and docstatus=1
- and is_return=0
- """.format(dt), status)
-
- for inv in invoices:
- return_inv = frappe.db.sql("""select name from `tab{0}`
- where is_return=1 and return_against=%s and docstatus=1""".format(dt), inv[0])
- if not return_inv:
- frappe.db.sql("update `tab{0}` set status='Paid' where name = %s".format(dt), inv[0])
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py b/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py
deleted file mode 100644
index 9750fb7222..0000000000
--- a/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Sales Invoice')
-
- frappe.db.sql("""
- delete from
- `tabSales Invoice Payment`
- where
- parent in (select name from `tabSales Invoice` where is_pos = 0)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py b/erpnext/patches/v8_0/merge_student_batch_and_student_group.py
deleted file mode 100644
index fb9021fd68..0000000000
--- a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import *
-from frappe.model.mapper import get_mapped_doc
-
-
-def execute():
- # for converting student batch into student group
- for doctype in ["Student Group", "Student Group Student", 'Program Enrollment',
- "Student Group Instructor", "Student Attendance", "Student", "Student Batch Name"]:
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", frappe.scrub(doctype))
-
- frappe.reload_doc("education", "doctype", frappe.scrub(doctype))
-
- if frappe.db.table_exists("Student Batch"):
- student_batches = frappe.db.sql('''select name as student_group_name, student_batch_name as batch,
- program, academic_year, academic_term from `tabStudent Batch`''', as_dict=1)
-
- for student_batch in student_batches:
- # create student batch name if does not exists !!
- if student_batch.get("batch") and not frappe.db.exists("Student Batch Name", student_batch.get("batch")):
- frappe.get_doc({
- "doctype": "Student Batch Name",
- "batch_name": student_batch.get("batch")
- }).insert(ignore_permissions=True)
-
- student_batch.update({"doctype":"Student Group", "group_based_on": "Batch"})
- doc = frappe.get_doc(student_batch)
-
- if frappe.db.sql("SHOW COLUMNS FROM `tabStudent Batch Student` LIKE 'active'"):
- cond = ", active"
- else:
- cond = " "
- student_list = frappe.db.sql('''select student, student_name {cond} from `tabStudent Batch Student`
- where parent=%s'''.format(cond=cond), (doc.student_group_name), as_dict=1)
-
- if student_list:
- for i, student in enumerate(student_list):
- student.update({"group_roll_number": i+1})
- doc.extend("students", student_list)
-
- instructor_list = None
- if frappe.db.table_exists("Student Batch Instructor"):
- instructor_list = frappe.db.sql('''select instructor, instructor_name from `tabStudent Batch Instructor`
- where parent=%s''', (doc.student_group_name), as_dict=1)
- if instructor_list:
- doc.extend("instructors", instructor_list)
- doc.save()
-
- # delete the student batch and child-table
- if frappe.db.table_exists("Student Batch"):
- frappe.delete_doc("DocType", "Student Batch", force=1)
- if frappe.db.table_exists("Student Batch Student"):
- frappe.delete_doc("DocType", "Student Batch Student", force=1)
- if frappe.db.table_exists("Student Batch Instructor"):
- frappe.delete_doc("DocType", "Student Batch Instructor", force=1)
-
- # delete the student batch creation tool
- if frappe.db.table_exists("Student Batch Creation Tool"):
- frappe.delete_doc("DocType", "Student Batch Creation Tool", force=1)
-
- # delete the student batch creation tool
- if frappe.db.table_exists("Attendance Tool Student"):
- frappe.delete_doc("DocType", "Attendance Tool Student", force=1)
-
- # change the student batch to student group in the student attendance
- table_columns = frappe.db.get_table_columns("Student Attendance")
- if "student_batch" in table_columns:
- rename_field("Student Attendance", "student_batch", "student_group")
diff --git a/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py b/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py
deleted file mode 100644
index b59d81831f..0000000000
--- a/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Warehouse")
- frappe.db.sql("""
- update
- `tabWarehouse`
- set
- account = (select name from `tabAccount`
- where account_type = 'Stock' and
- warehouse = `tabWarehouse`.name and is_group = 0 limit 1)""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/move_perpetual_inventory_setting.py b/erpnext/patches/v8_0/move_perpetual_inventory_setting.py
deleted file mode 100644
index 78322d4575..0000000000
--- a/erpnext/patches/v8_0/move_perpetual_inventory_setting.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Company')
- enabled = frappe.db.get_single_value("Accounts Settings", "auto_accounting_for_stock") or 0
- for data in frappe.get_all('Company', fields = ["name"]):
- doc = frappe.get_doc('Company', data.name)
- doc.enable_perpetual_inventory = enabled
- doc.db_update()
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py b/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py
deleted file mode 100644
index e517df5fdb..0000000000
--- a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
-
- doc_list = ["Purchase Invoice Item", "Stock Entry Detail", "Delivery Note Item",
- "Purchase Receipt Item", "Sales Invoice Item"]
-
- for doctype in doc_list:
- frappe.reload_doctype(doctype)
- if "is_sample_item" in frappe.db.get_table_columns(doctype):
- rename_field(doctype, "is_sample_item", "allow_zero_valuation_rate")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py b/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py
deleted file mode 100644
index 5ad862a436..0000000000
--- a/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql(
- """
- UPDATE `tabMaterial Request`
- SET status = CASE
- WHEN docstatus = 2 THEN 'Cancelled'
- WHEN docstatus = 0 THEN 'Draft'
- ELSE CASE
- WHEN status = 'Stopped' THEN 'Stopped'
- WHEN status != 'Stopped' AND per_ordered = 0 THEN 'Pending'
- WHEN per_ordered < 100 AND per_ordered > 0 AND status != 'Stopped'
- THEN 'Partially Ordered'
- WHEN per_ordered = 100 AND material_request_type = 'Purchase'
- AND status != 'Stopped' THEN 'Ordered'
- WHEN per_ordered = 100 AND material_request_type = 'Material Transfer'
- AND status != 'Stopped' THEN 'Transferred'
- WHEN per_ordered = 100 AND material_request_type = 'Material Issue'
- AND status != 'Stopped' THEN 'Issued'
- END
- END
- """
- )
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py b/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py
deleted file mode 100644
index 4065438796..0000000000
--- a/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- """
- Rename Total Margin field to Rate With Margin in
- "Sales Order Item", "Sales Invoice Item", "Delivery Note Item",
- "Quotation Item"
- """
-
- for d in ("Sales Order Item", "Sales Invoice Item",
- "Delivery Note Item", "Quotation Item"):
- frappe.reload_doctype(d)
- rename_field_if_exists(d, "total_margin", "rate_with_margin")
-
-
-def rename_field_if_exists(doctype, old_fieldname, new_fieldname):
- try:
- rename_field(doctype, old_fieldname, new_fieldname)
- except Exception as e:
- if e.args[0] != 1054:
- raise
diff --git a/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py b/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py
deleted file mode 100644
index 3030b8e2f3..0000000000
--- a/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
-
-def execute():
- for doctype in ("Sales Order Item", "Bin"):
- frappe.reload_doctype(doctype)
-
- repost_for = frappe.db.sql("""select distinct item_code, warehouse
- from `tabSales Order Item` where docstatus=1 and uom != stock_uom and
- exists(select name from tabItem where name=`tabSales Order Item`.item_code and ifnull(is_stock_item, 0)=1)""")
-
- for item_code, warehouse in repost_for:
- update_bin_qty(item_code, warehouse, {
- "reserved_qty": get_reserved_qty(item_code, warehouse)
- })
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py b/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py
deleted file mode 100644
index 60cbb33b80..0000000000
--- a/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Item Manufacturer"):
- frappe.reload_doctype("Item")
- item_manufacturers = frappe.db.sql("""
- select parent, manufacturer, manufacturer_part_no
- from `tabItem Manufacturer`
- """, as_dict=1)
-
- for im in item_manufacturers:
- frappe.db.sql("""
- update tabItem
- set manufacturer=%s, manufacturer_part_no=%s
- where name=%s
- """, (im.manufacturer, im.manufacturer_part_no, im.parent))
-
- frappe.delete_doc("DocType", "Item Manufacturer")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/save_system_settings.py b/erpnext/patches/v8_0/save_system_settings.py
deleted file mode 100644
index d479ece8a6..0000000000
--- a/erpnext/patches/v8_0/save_system_settings.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-
-def execute():
- """
- save system settings document
- """
-
- frappe.reload_doc("core", "doctype", "system_settings")
- doc = frappe.get_doc("System Settings")
- doc.flags.ignore_mandatory = True
-
- if cint(doc.currency_precision) == 0:
- doc.currency_precision = ''
-
- doc.save(ignore_permissions=True)
diff --git a/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py b/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py
deleted file mode 100644
index 197d6ded61..0000000000
--- a/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
-
-def execute():
- frappe.db.sql("""
- update
- `tabSales Invoice Item`
- set serial_no = NULL
- where
- parent in (select name from `tabSales Invoice` where update_stock = 0 and docstatus = 1)""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/set_project_copied_from.py b/erpnext/patches/v8_0/set_project_copied_from.py
deleted file mode 100644
index d4287978cf..0000000000
--- a/erpnext/patches/v8_0/set_project_copied_from.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Project")
-
- frappe.db.sql('''
- UPDATE `tabProject`
- SET copied_from=name
- WHERE copied_from is NULL
- ''')
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
deleted file mode 100644
index 8a4ef4086b..0000000000
--- a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
-
-def execute():
- """ Set the Serial Numbers in Sales Invoice Item from Delivery Note Item """
-
- frappe.reload_doc("stock", "doctype", "serial_no")
-
- frappe.db.sql(""" update `tabSales Invoice Item` sii inner join
- `tabDelivery Note Item` dni on sii.dn_detail=dni.name and sii.qty=dni.qty
- set sii.serial_no=dni.serial_no where sii.parent IN (select si.name
- from `tabSales Invoice` si where si.update_stock=0 and si.docstatus=1)""")
-
- items = frappe.db.sql(""" select sii.parent, sii.serial_no from `tabSales Invoice Item` sii
- left join `tabSales Invoice` si on sii.parent=si.name
- where si.docstatus=1 and si.update_stock=0""", as_dict=True)
-
- for item in items:
- sales_invoice = item.get("parent", None)
- serial_nos = item.get("serial_no", "")
-
- if not sales_invoice or not serial_nos:
- continue
-
- serial_nos = ["{}".format(frappe.db.escape(no)) for no in serial_nos.split("\n")]
-
- frappe.db.sql("""
- UPDATE
- `tabSerial No`
- SET
- sales_invoice={sales_invoice}
- WHERE
- name in ({serial_nos})
- """.format(
- sales_invoice=frappe.db.escape(sales_invoice),
- serial_nos=",".join(serial_nos)
- )
- )
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_customer_pos_id.py b/erpnext/patches/v8_0/update_customer_pos_id.py
deleted file mode 100644
index a772ae90c5..0000000000
--- a/erpnext/patches/v8_0/update_customer_pos_id.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Customer")
- frappe.db.sql(""" update `tabCustomer` set customer_pos_id = name """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_production_orders.py b/erpnext/patches/v8_0/update_production_orders.py
deleted file mode 100644
index 8e993cc102..0000000000
--- a/erpnext/patches/v8_0/update_production_orders.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # reload schema
- for doctype in ("Work Order", "Work Order Item", "Work Order Operation",
- "BOM Item", "BOM Explosion Item", "BOM"):
- frappe.reload_doctype(doctype)
-
- frappe.reload_doc("stock", "doctype", "item")
- frappe.reload_doc("stock", "doctype", "item_default")
-
- # fetch all draft and submitted work orders
- fields = ["name"]
- if "source_warehouse" in frappe.db.get_table_columns("Work Order"):
- fields.append("source_warehouse")
-
- wo_orders = frappe.get_all("Work Order", filters={"docstatus": ["!=", 2]}, fields=fields)
-
- count = 0
- for p in wo_orders:
- wo_order = frappe.get_doc("Work Order", p.name)
- count += 1
-
- # set required items table
- wo_order.set_required_items()
-
- for item in wo_order.get("required_items"):
- # set source warehouse based on parent
- if not item.source_warehouse and "source_warehouse" in fields:
- item.source_warehouse = wo_order.get("source_warehouse")
- item.db_update()
-
- if wo_order.docstatus == 1:
- # update transferred qty based on Stock Entry, it also updates db
- wo_order.update_transaferred_qty_for_required_items()
-
- # Set status where it was 'Unstopped', as it is deprecated
- if wo_order.status == "Unstopped":
- status = wo_order.get_status()
- wo_order.db_set("status", status)
- elif wo_order.status == "Stopped":
- wo_order.update_reserved_qty_for_production()
-
- if count % 200 == 0:
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_sales_cost_in_project.py b/erpnext/patches/v8_0/update_sales_cost_in_project.py
deleted file mode 100644
index 1a29fc4db4..0000000000
--- a/erpnext/patches/v8_0/update_sales_cost_in_project.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("projects", "doctype", "project")
-
- frappe.db.sql("""
- update `tabProject` p
- set total_sales_amount = ifnull((select sum(base_grand_total)
- from `tabSales Order` where project=p.name and docstatus=1), 0)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py b/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py
deleted file mode 100644
index 19d27b206b..0000000000
--- a/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ set status as Paid in Expense Claim if total_sactioned_amount
- and total_amount_reimbursed is equal """
-
- frappe.reload_doctype('Expense Claim')
-
- frappe.db.sql("""
- update
- `tabExpense Claim`
- set status = 'Paid'
- where
- total_sanctioned_amount = total_amount_reimbursed
- """)
diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py
deleted file mode 100644
index 1f937bb8af..0000000000
--- a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('manufacturing', 'doctype', 'bom_item')
- frappe.reload_doc('manufacturing', 'doctype', 'bom_explosion_item')
- frappe.reload_doc('manufacturing', 'doctype', 'bom_scrap_item')
- frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom, conversion_factor = 1")
- frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty")
- if "qty" in frappe.db.get_table_columns("BOM Scrap Item"):
- frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py b/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py
deleted file mode 100644
index be5cf3aed7..0000000000
--- a/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_item')
- frappe.db.sql("update `tabPurchase Invoice Item` set stock_qty = qty, stock_uom = uom")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_student_groups_from_student_batches.py b/erpnext/patches/v8_0/update_student_groups_from_student_batches.py
deleted file mode 100644
index ae24fe4a14..0000000000
--- a/erpnext/patches/v8_0/update_student_groups_from_student_batches.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import *
-from frappe.model.mapper import get_mapped_doc
-
-
-def execute():
- if frappe.db.table_exists("Student Batch"):
- student_batches = frappe.db.sql('''select name from `tabStudent Batch`''', as_dict=1)
-
- for student_batch in student_batches:
- if frappe.db.exists("Student Group", student_batch.get("name")):
- student_group = frappe.get_doc("Student Group", student_batch.get("name"))
-
- if frappe.db.table_exists("Student Batch Student"):
- current_student_list = frappe.db.sql_list('''select student from `tabStudent Group Student`
- where parent=%s''', (student_group.name))
- batch_student_list = frappe.db.sql_list('''select student from `tabStudent Batch Student`
- where parent=%s''', (student_group.name))
-
- student_list = list(set(batch_student_list)-set(current_student_list))
- if student_list:
- student_group.extend("students", [{"student":d} for d in student_list])
-
- if frappe.db.table_exists("Student Batch Instructor"):
- current_instructor_list = frappe.db.sql_list('''select instructor from `tabStudent Group Instructor`
- where parent=%s''', (student_group.name))
- batch_instructor_list = frappe.db.sql_list('''select instructor from `tabStudent Batch Instructor`
- where parent=%s''', (student_group.name))
-
- instructor_list = list(set(batch_instructor_list)-set(current_instructor_list))
- if instructor_list:
- student_group.extend("instructors", [{"instructor":d} for d in instructor_list])
-
- student_group.save()
diff --git a/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py b/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py
deleted file mode 100644
index a2173048fd..0000000000
--- a/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # copy supplier_address to address_display, and set supplier_address to blank
-
- stock_entries = frappe.db.sql(""" select name, purchase_order, supplier_address from `tabStock Entry`
- where ifnull(supplier_address, '') <> ''""", as_dict=True)
-
- frappe.reload_doc('stock', 'doctype', 'stock_entry')
-
- for stock_entry in stock_entries:
- # move supplier address to address_display, and fetch the supplier address from purchase order
-
- se = frappe.get_doc("Stock Entry", stock_entry.get("name"))
- se.address_display = stock_entry.get("supplier_address")
- se.supplier_address = frappe.db.get_value("Purchase Order", stock_entry.get("purchase_order"),"supplier_address") or None
-
- se.db_update()
diff --git a/erpnext/patches/v8_1/__init__.py b/erpnext/patches/v8_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_1/add_hsn_sac_codes.py b/erpnext/patches/v8_1/add_hsn_sac_codes.py
deleted file mode 100644
index 0fce96a8d4..0000000000
--- a/erpnext/patches/v8_1/add_hsn_sac_codes.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.india.setup import setup
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- return
-
- # call setup for india
- setup(patch=True)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py b/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py
deleted file mode 100644
index 4631602606..0000000000
--- a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Sales Order Item", "Purchase Order Item",
- "Material Request Item", "Work Order Item", "Packed Item"):
- frappe.get_doc("DocType", dt).run_module_method("on_doctype_update")
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py b/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py
deleted file mode 100644
index 4c606af424..0000000000
--- a/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- inv_copy_options = "ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nDUPLICATE FOR SUPPLIER\nTRIPLICATE FOR SUPPLIER"
-
- frappe.db.sql("""update `tabCustom Field` set allow_on_submit=1, options=%s
- where fieldname='invoice_copy' and dt = 'Sales Invoice'
- """, inv_copy_options)
-
- frappe.db.sql("""update `tabCustom Field` set read_only=1
- where fieldname='gst_state_number' and dt = 'Address'
- """)
diff --git a/erpnext/patches/v8_1/delete_deprecated_reports.py b/erpnext/patches/v8_1/delete_deprecated_reports.py
deleted file mode 100644
index 3e0fdee719..0000000000
--- a/erpnext/patches/v8_1/delete_deprecated_reports.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ delete deprecated reports """
-
- reports = [
- "Monthly Salary Register", "Customer Addresses And Contacts",
- "Supplier Addresses And Contacts"
- ]
-
- for report in reports:
- if frappe.db.exists("Report", report):
- check_and_update_auto_email_report(report)
- frappe.db.commit()
-
- frappe.delete_doc("Report", report, ignore_permissions=True)
-
-def check_and_update_auto_email_report(report):
- """ delete or update auto email report for deprecated report """
-
- auto_email_report = frappe.db.get_value("Auto Email Report", {"report": report})
- if not auto_email_report:
- return
-
- if report == "Monthly Salary Register":
- frappe.delete_doc("Auto Email Report", auto_email_report)
-
- elif report in ["Customer Addresses And Contacts", "Supplier Addresses And Contacts"]:
- frappe.db.set_value("Auto Email Report", auto_email_report, "report", report)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/gst_fixes.py b/erpnext/patches/v8_1/gst_fixes.py
deleted file mode 100644
index 34255eb0a4..0000000000
--- a/erpnext/patches/v8_1/gst_fixes.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.custom.doctype.custom_field.custom_field import create_custom_field
-from erpnext.regional.address_template.setup import set_up_address_templates
-
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- return
-
- update_existing_custom_fields()
- add_custom_fields()
- set_up_address_templates(default_country='India')
- frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
-
-
-def update_existing_custom_fields():
- frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC'
- where fieldname='gst_hsn_code' and label='GST HSN Code'
- """)
-
- frappe.db.sql("""update `tabCustom Field` set print_hide = 1
- where fieldname in ('customer_gstin', 'supplier_gstin', 'company_gstin')
- """)
-
- frappe.db.sql("""update `tabCustom Field` set insert_after = 'address_display'
- where fieldname in ('customer_gstin', 'supplier_gstin')
- """)
-
- frappe.db.sql("""update `tabCustom Field` set insert_after = 'company_address_display'
- where fieldname = 'company_gstin'
- """)
-
- frappe.db.sql("""update `tabCustom Field` set insert_after = 'description'
- where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item')
- """)
-
-
-def add_custom_fields():
- hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
- fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
-
- custom_fields = {
- 'Address': [
- dict(fieldname='gst_state_number', label='GST State Number',
- fieldtype='Int', insert_after='gst_state'),
- ],
- 'Sales Invoice': [
- dict(fieldname='invoice_copy', label='Invoice Copy',
- fieldtype='Select', insert_after='project', print_hide=1, allow_on_submit=1,
- options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER'),
- ],
- 'Sales Order Item': [hsn_sac_field],
- 'Delivery Note Item': [hsn_sac_field],
- 'Purchase Order Item': [hsn_sac_field],
- 'Purchase Receipt Item': [hsn_sac_field]
- }
-
- for doctype, fields in custom_fields.items():
- for df in fields:
- create_custom_field(doctype, df)
diff --git a/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py b/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py
deleted file mode 100644
index 3962f8f1f2..0000000000
--- a/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Serial No")
-
- frappe.db.sql("""
- update
- `tabSerial No`
- set
- sales_invoice = NULL
- where
- sales_invoice in (select return_against from
- `tabSales Invoice` where docstatus =1 and is_return=1)
- and sales_invoice is not null and sales_invoice !='' """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/removed_report_support_hours.py b/erpnext/patches/v8_1/removed_report_support_hours.py
deleted file mode 100644
index 0936b2231b..0000000000
--- a/erpnext/patches/v8_1/removed_report_support_hours.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql(""" update `tabAuto Email Report` set report = %s
- where name = %s""", ('Support Hour Distribution', 'Support Hours'))
-
- frappe.db.sql(""" update `tabCustom Role` set report = %s
- where report = %s""", ('Support Hour Distribution', 'Support Hours'))
-
- frappe.delete_doc('Report', 'Support Hours')
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
deleted file mode 100644
index af2d28b857..0000000000
--- a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Sales Order")
- frappe.reload_doctype("Sales Order Item")
-
- if "final_delivery_date" in frappe.db.get_table_columns("Sales Order"):
- frappe.db.sql("""
- update `tabSales Order`
- set delivery_date = final_delivery_date
- where (delivery_date is null or delivery_date = '0000-00-00')
- and order_type = 'Sales'""")
-
- frappe.db.sql("""
- update `tabSales Order` so, `tabSales Order Item` so_item
- set so_item.delivery_date = so.delivery_date
- where so.name = so_item.parent
- and so.order_type = 'Sales'
- and (so_item.delivery_date is null or so_item.delivery_date = '0000-00-00')
- and (so.delivery_date is not null and so.delivery_date != '0000-00-00')
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/update_expense_claim_status.py b/erpnext/patches/v8_1/update_expense_claim_status.py
deleted file mode 100644
index 4c1b85a13f..0000000000
--- a/erpnext/patches/v8_1/update_expense_claim_status.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Expense Claim')
-
- for data in frappe.db.sql(""" select name from `tabExpense Claim`
- where (docstatus=1 and total_sanctioned_amount=0 and status = 'Paid') or
- (docstatus = 1 and approval_status = 'Rejected' and total_sanctioned_amount > 0)""", as_dict=1):
- doc = frappe.get_doc('Expense Claim', data.name)
- if doc.approval_status == 'Rejected':
- for d in doc.expenses:
- d.db_set("sanctioned_amount", 0, update_modified = False)
- doc.db_set("total_sanctioned_amount", 0, update_modified = False)
-
- frappe.db.sql(""" delete from `tabGL Entry` where voucher_type = 'Expense Claim'
- and voucher_no = %s""", (doc.name))
-
- doc.set_status()
- doc.db_set("status", doc.status, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/update_gst_state.py b/erpnext/patches/v8_1/update_gst_state.py
deleted file mode 100644
index 7aaf2d5ff3..0000000000
--- a/erpnext/patches/v8_1/update_gst_state.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.india import states
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- return
-
- if not frappe.db.get_value("Custom Field", filters={'fieldname':'gst_state'}):
- return
-
- frappe.db.sql("update `tabCustom Field` set options=%s where fieldname='gst_state'", '\n'.join(states))
- frappe.db.sql("update `tabAddress` set gst_state='Chhattisgarh' where gst_state='Chattisgarh'")
- frappe.db.sql("update `tabAddress` set gst_state_number='05' where gst_state='Uttarakhand'")
diff --git a/erpnext/patches/v8_10/__init__.py b/erpnext/patches/v8_10/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_10/change_default_customer_credit_days.py b/erpnext/patches/v8_10/change_default_customer_credit_days.py
deleted file mode 100644
index 992be17da0..0000000000
--- a/erpnext/patches/v8_10/change_default_customer_credit_days.py
+++ /dev/null
@@ -1,89 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- frappe.reload_doc("selling", "doctype", "customer")
- frappe.reload_doc("buying", "doctype", "supplier")
- frappe.reload_doc("setup", "doctype", "supplier_type")
- frappe.reload_doc("accounts", "doctype", "payment_term")
- frappe.reload_doc("accounts", "doctype", "payment_terms_template_detail")
- frappe.reload_doc("accounts", "doctype", "payment_terms_template")
-
- payment_terms = []
- records = []
- for doctype in ("Customer", "Supplier", "Supplier Type"):
- credit_days = frappe.db.sql("""
- SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name`
- from `tab{0}`
- where
- ((credit_days_based_on='Fixed Days' or credit_days_based_on is null)
- and credit_days is not null)
- or credit_days_based_on='Last Day of the Next Month'
- """.format(doctype))
-
- credit_records = ((record[0], record[1], record[2]) for record in credit_days)
- for days, based_on, party_name in credit_records:
- if based_on == "Fixed Days":
- pyt_template_name = 'Default Payment Term - N{0}'.format(days)
- else:
- pyt_template_name = 'Default Payment Term - EO2M'
-
- if not frappe.db.exists("Payment Terms Template", pyt_template_name):
- payment_term = make_payment_term(days, based_on)
- template = make_template(payment_term)
- else:
- template = frappe.get_doc("Payment Terms Template", pyt_template_name)
-
- payment_terms.append('WHEN `name`={0} THEN {1}'.format(frappe.db.escape(party_name), template.template_name))
- records.append(frappe.db.escape(party_name))
-
- begin_query_str = "UPDATE `tab{0}` SET `payment_terms` = CASE ".format(doctype)
- value_query_str = " ".join(payment_terms)
- cond_query_str = " ELSE `payment_terms` END WHERE "
-
- if records:
- frappe.db.sql(
- begin_query_str + value_query_str + cond_query_str + '`name` IN %s',
- (records,)
- )
-
-
-def make_template(payment_term):
- doc = frappe.new_doc('Payment Terms Template Detail')
- doc.payment_term = payment_term.payment_term_name
- doc.due_date_based_on = payment_term.due_date_based_on
- doc.invoice_portion = payment_term.invoice_portion
- doc.description = payment_term.description
- doc.credit_days = payment_term.credit_days
- doc.credit_months = payment_term.credit_months
-
- template = frappe.new_doc('Payment Terms Template')
- template.template_name = 'Default Payment Term - {0}'.format(payment_term.payment_term_name)
- template.append('terms', doc)
- template.save()
-
- return template
-
-
-def make_payment_term(days, based_on):
- based_on_map = {
- 'Fixed Days': 'Day(s) after invoice date',
- 'Last Day of the Next Month': 'Month(s) after the end of the invoice month'
- }
-
- doc = frappe.new_doc('Payment Term')
- doc.due_date_based_on = based_on_map.get(based_on)
- doc.invoice_portion = 100
-
- if based_on == 'Fixed Days':
- doc.credit_days = days
- doc.description = 'Net payable within {0} days'.format(days)
- doc.payment_term_name = 'N{0}'.format(days)
- else:
- doc.credit_months = 1
- doc.description = 'Net payable by the end of next month'
- doc.payment_term_name = 'EO2M'
-
- doc.save()
- return doc
diff --git a/erpnext/patches/v8_3/__init__.py b/erpnext/patches/v8_3/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py b/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py
deleted file mode 100644
index 6c4c6d5bd8..0000000000
--- a/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ set the restrict to domain in module def """
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v8_3/update_company_total_sales.py b/erpnext/patches/v8_3/update_company_total_sales.py
deleted file mode 100644
index 78efecb387..0000000000
--- a/erpnext/patches/v8_3/update_company_total_sales.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.setup.doctype.company.company import update_company_current_month_sales, update_company_monthly_sales
-
-def execute():
- '''Update company monthly sales history based on sales invoices'''
- frappe.reload_doctype("Company")
- companies = [d['name'] for d in frappe.get_list("Company")]
-
- for company in companies:
- update_company_current_month_sales(company)
- update_company_monthly_sales(company)
diff --git a/erpnext/patches/v8_4/__init__.py b/erpnext/patches/v8_4/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v8_4/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v8_4/make_scorecard_records.py b/erpnext/patches/v8_4/make_scorecard_records.py
deleted file mode 100644
index 73afa277b4..0000000000
--- a/erpnext/patches/v8_4/make_scorecard_records.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
-def execute():
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_variable')
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_standing')
- make_default_records()
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/__init__.py b/erpnext/patches/v8_5/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py b/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py
deleted file mode 100644
index 82beba3770..0000000000
--- a/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.india.setup import make_custom_fields
-from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_html
-
-def execute():
- companies = [d.name for d in frappe.get_all('Company', filters = {'country': 'India'})]
- if not companies:
- return
-
- make_custom_fields()
-
- # update invoice copy value
- values = ["Original for Recipient", "Duplicate for Transporter",
- "Duplicate for Supplier", "Triplicate for Supplier"]
- for d in values:
- frappe.db.sql("update `tabSales Invoice` set invoice_copy=%s where invoice_copy=%s", (d, d))
-
- # update tax breakup in transactions made after 1st July 2017
- doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
- "Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
-
- for doctype in doctypes:
- frappe.reload_doctype(doctype)
-
- date_field = "posting_date"
- if doctype in ["Quotation", "Sales Order", "Supplier Quotation", "Purchase Order"]:
- date_field = "transaction_date"
-
- records = [d.name for d in frappe.get_all(doctype, filters={
- "docstatus": ["!=", 2],
- date_field: [">=", "2017-07-01"],
- "company": ["in", companies],
- "total_taxes_and_charges": [">", 0],
- "other_charges_calculation": ""
- })]
- if records:
- frappe.db.sql("""
- update `tab%s Item` dt_item
- set gst_hsn_code = (select gst_hsn_code from tabItem where name=dt_item.item_code)
- where parent in (%s)
- and (gst_hsn_code is null or gst_hsn_code = '')
- """ % (doctype, ', '.join(['%s']*len(records))), tuple(records))
-
- for record in records:
- doc = frappe.get_doc(doctype, record)
- html = get_itemised_tax_breakup_html(doc)
- doc.db_set("other_charges_calculation", html, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/remove_project_type_property_setter.py b/erpnext/patches/v8_5/remove_project_type_property_setter.py
deleted file mode 100644
index 70a08f5377..0000000000
--- a/erpnext/patches/v8_5/remove_project_type_property_setter.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- ps = frappe.db.get_value('Property Setter', dict(doc_type='Project', field_name='project_type',
- property='options'))
- if ps:
- frappe.delete_doc('Property Setter', ps)
-
- project_types = frappe.db.sql_list('select distinct project_type from tabProject')
-
- for project_type in project_types:
- if project_type and not frappe.db.exists("Project Type", project_type):
- p_type = frappe.get_doc({
- "doctype": "Project Type",
- "project_type": project_type
- })
- p_type.insert()
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py b/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py
deleted file mode 100644
index 2d7df4a179..0000000000
--- a/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Portal Settings")
-
- frappe.db.sql("""
- delete from
- `tabPortal Menu Item`
- where
- (route = '/quotations' and title = 'Supplier Quotation')
- or (route = '/quotation' and title = 'Quotations')
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/set_default_mode_of_payment.py b/erpnext/patches/v8_5/set_default_mode_of_payment.py
deleted file mode 100644
index 34ecbb0a3c..0000000000
--- a/erpnext/patches/v8_5/set_default_mode_of_payment.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("POS Profile")
- frappe.reload_doctype("Sales Invoice Payment")
-
- frappe.db.sql("""
- update
- `tabSales Invoice Payment`
- set `tabSales Invoice Payment`.default = 1
- where
- `tabSales Invoice Payment`.parenttype = 'POS Profile'
- and `tabSales Invoice Payment`.idx=1""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
deleted file mode 100644
index 2661914401..0000000000
--- a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('POS Profile')
- customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
- if customer_group:
- frappe.db.sql(""" update `tabPOS Profile`
- set customer_group = %s where customer_group is null """, (customer_group))
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/update_existing_data_in_project_type.py b/erpnext/patches/v8_5/update_existing_data_in_project_type.py
deleted file mode 100644
index 497da0602e..0000000000
--- a/erpnext/patches/v8_5/update_existing_data_in_project_type.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("projects", "doctype", "project_type")
- frappe.reload_doc("projects", "doctype", "project")
-
- project_types = ["Internal", "External", "Other"]
-
- for project_type in project_types:
- if not frappe.db.exists("Project Type", project_type):
- p_type = frappe.get_doc({
- "doctype": "Project Type",
- "project_type": project_type
- })
- p_type.insert()
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/__init__.py b/erpnext/patches/v8_6/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py b/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py
deleted file mode 100644
index 014a74abe3..0000000000
--- a/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql('''UPDATE `tabDocType` SET module="Core"
- WHERE name IN ("SMS Parameter", "SMS Settings");''')
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/rename_bom_update_tool.py b/erpnext/patches/v8_6/rename_bom_update_tool.py
deleted file mode 100644
index ef5f335e45..0000000000
--- a/erpnext/patches/v8_6/rename_bom_update_tool.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.delete_doc_if_exists("DocType", "BOM Replace Tool")
-
- frappe.reload_doctype("BOM")
- frappe.db.sql("update tabBOM set conversion_rate=1 where conversion_rate is null or conversion_rate=0")
- frappe.db.sql("update tabBOM set set_rate_of_sub_assembly_item_based_on_bom=1")
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
deleted file mode 100644
index db4f94748e..0000000000
--- a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # Set write permission to permlevel 1 for sales manager role in Quotation doctype
- frappe.db.sql(""" update `tabCustom DocPerm` set `tabCustom DocPerm`.write = 1
- where `tabCustom DocPerm`.parent = 'Quotation' and `tabCustom DocPerm`.role = 'Sales Manager'
- and `tabCustom DocPerm`.permlevel = 1 """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py
deleted file mode 100644
index 2d46bee7ca..0000000000
--- a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Timesheet')
- company = frappe.get_all('Company')
-
- #Check more than one company exists
- if len(company) > 1:
- frappe.db.sql(""" update `tabTimesheet` set `tabTimesheet`.company =
- (select company from `tabWork Order` where name = `tabTimesheet`.work_order)
- where workn_order is not null and work_order !=''""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_7/__init__.py b/erpnext/patches/v8_7/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_7/fix_purchase_receipt_status.py b/erpnext/patches/v8_7/fix_purchase_receipt_status.py
deleted file mode 100644
index 99ecb44214..0000000000
--- a/erpnext/patches/v8_7/fix_purchase_receipt_status.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # there is no more status called "Submitted", there was an old issue that used
- # to set it as Submitted, fixed in this commit
- frappe.db.sql("""
- update
- `tabPurchase Receipt`
- set
- status = 'To Bill'
- where
- status = 'Submitted'""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_7/make_subscription_from_recurring_data.py b/erpnext/patches/v8_7/make_subscription_from_recurring_data.py
deleted file mode 100644
index 2932749116..0000000000
--- a/erpnext/patches/v8_7/make_subscription_from_recurring_data.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import today
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'subscription')
- frappe.reload_doc('selling', 'doctype', 'sales_order')
- frappe.reload_doc('selling', 'doctype', 'quotation')
- frappe.reload_doc('buying', 'doctype', 'purchase_order')
- frappe.reload_doc('buying', 'doctype', 'supplier_quotation')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice')
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
- frappe.reload_doc('stock', 'doctype', 'delivery_note')
- frappe.reload_doc('accounts', 'doctype', 'journal_entry')
- frappe.reload_doc('accounts', 'doctype', 'payment_entry')
-
- for doctype in ['Sales Order', 'Sales Invoice', 'Purchase Order', 'Purchase Invoice']:
- date_field = "transaction_date"
- if doctype in ("Sales Invoice", "Purchase Invoice"):
- date_field = "posting_date"
-
- for data in get_data(doctype, date_field):
- make_subscription(doctype, data, date_field)
-
-def get_data(doctype, date_field):
- return frappe.db.sql(""" select name, from_date, end_date, recurring_type, recurring_id,
- next_date, notify_by_email, notification_email_address, recurring_print_format,
- repeat_on_day_of_month, submit_on_creation, docstatus, {0}
- from `tab{1}` where is_recurring = 1 and next_date >= %s and docstatus < 2
- order by next_date desc
- """.format(date_field, doctype), today(), as_dict=1)
-
-def make_subscription(doctype, data, date_field):
- if data.name == data.recurring_id:
- start_date = data.get(date_field)
- else:
- start_date = frappe.db.get_value(doctype, data.recurring_id, date_field)
-
- doc = frappe.get_doc({
- 'doctype': 'Subscription',
- 'reference_doctype': doctype,
- 'reference_document': data.recurring_id,
- 'start_date': start_date,
- 'end_date': data.end_date,
- 'frequency': data.recurring_type,
- 'repeat_on_day': data.repeat_on_day_of_month,
- 'notify_by_email': data.notify_by_email,
- 'recipients': data.notification_email_address,
- 'next_schedule_date': data.next_date,
- 'submit_on_creation': data.submit_on_creation
- }).insert(ignore_permissions=True)
-
- if data.docstatus == 1:
- doc.submit()
\ No newline at end of file
diff --git a/erpnext/patches/v8_8/__init__.py b/erpnext/patches/v8_8/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py b/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py
deleted file mode 100644
index bd25f15d78..0000000000
--- a/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- frappe.db.sql(
- "INSERT INTO `tabSingles` (`doctype`, `field`, `value`) VALUES ('Accounts Settings', 'allow_stale', '1'), "
- "('Accounts Settings', 'stale_days', '1')"
- )
diff --git a/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py b/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
deleted file mode 100644
index 5b169cdff2..0000000000
--- a/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""
- update `tabBOM Item`
- set rate = rate * conversion_factor
- where uom != stock_uom and docstatus < 2
- and conversion_factor not in (0, 1)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/__init__.py b/erpnext/patches/v8_9/__init__.py
deleted file mode 100644
index 8b13789179..0000000000
--- a/erpnext/patches/v8_9/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/erpnext/patches/v8_9/add_setup_progress_actions.py b/erpnext/patches/v8_9/add_setup_progress_actions.py
deleted file mode 100644
index 77501073cf..0000000000
--- a/erpnext/patches/v8_9/add_setup_progress_actions.py
+++ /dev/null
@@ -1,47 +0,0 @@
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- """Add setup progress actions"""
- if not frappe.db.exists('DocType', 'Setup Progress') or not frappe.db.exists('DocType', 'Setup Progress Action'):
- return
-
- frappe.reload_doc("setup", "doctype", "setup_progress")
- frappe.reload_doc("setup", "doctype", "setup_progress_action")
-
- actions = [
- {"action_name": "Add Company", "action_doctype": "Company", "min_doc_count": 1, "is_completed": 1,
- "domains": '[]' },
- {"action_name": "Set Sales Target", "action_doctype": "Company", "min_doc_count": 99,
- "action_document": frappe.defaults.get_defaults().get("company") or '',
- "action_field": "monthly_sales_target", "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Customers", "action_doctype": "Customer", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Suppliers", "action_doctype": "Supplier", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Products", "action_doctype": "Item", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Programs", "action_doctype": "Program", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Instructors", "action_doctype": "Instructor", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Courses", "action_doctype": "Course", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Rooms", "action_doctype": "Room", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Users", "action_doctype": "User", "min_doc_count": 4, "is_completed": 0,
- "domains": '[]' },
- {"action_name": "Add Letterhead", "action_doctype": "Letter Head", "min_doc_count": 1, "is_completed": 0,
- "domains": '[]' }
- ]
-
- setup_progress = frappe.get_doc("Setup Progress", "Setup Progress")
- setup_progress.actions = []
- for action in actions:
- setup_progress.append("actions", action)
-
- setup_progress.save(ignore_permissions=True)
-
diff --git a/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py b/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py
deleted file mode 100644
index f67af90555..0000000000
--- a/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- if frappe.db.exists("DocType", "GST Settings"):
- frappe.delete_doc("DocType", "GST Settings")
- frappe.delete_doc("DocType", "GST HSN Code")
-
- for report_name in ('GST Sales Register', 'GST Purchase Register',
- 'GST Itemised Sales Register', 'GST Itemised Purchase Register'):
-
- frappe.delete_doc('Report', report_name)
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py b/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py
deleted file mode 100644
index 808ae6d527..0000000000
--- a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if 'employee' in frappe.db.get_table_columns("Salary Structure"):
- frappe.db.sql("alter table `tabSalary Structure` drop column employee")
diff --git a/erpnext/patches/v8_9/rename_company_sales_target_field.py b/erpnext/patches/v8_9/rename_company_sales_target_field.py
deleted file mode 100644
index 5433eb673e..0000000000
--- a/erpnext/patches/v8_9/rename_company_sales_target_field.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- frappe.reload_doc("setup", "doctype", "company")
- if frappe.db.has_column('Company', 'sales_target'):
- rename_field("Company", "sales_target", "monthly_sales_target")
diff --git a/erpnext/patches/v8_9/set_default_customer_group.py b/erpnext/patches/v8_9/set_default_customer_group.py
deleted file mode 100644
index cbbe09daf5..0000000000
--- a/erpnext/patches/v8_9/set_default_customer_group.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- selling_settings = frappe.get_single('Selling Settings')
- selling_settings.set_default_customer_group_and_territory()
- selling_settings.flags.ignore_mandatory = True
- selling_settings.save()
diff --git a/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py b/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py
deleted file mode 100644
index a550d093fa..0000000000
--- a/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'item_variant_settings')
- frappe.reload_doc('stock', 'doctype', 'variant_field')
-
- doc = frappe.get_doc('Item Variant Settings')
- doc.set_default_fields()
- doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/set_member_party_type.py b/erpnext/patches/v8_9/set_member_party_type.py
deleted file mode 100644
index 33bbc11a93..0000000000
--- a/erpnext/patches/v8_9/set_member_party_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists("Party Type", "Member"):
- frappe.reload_doc("non_profit", "doctype", "member")
- party = frappe.new_doc("Party Type")
- party.party_type = "Member"
- party.save()
diff --git a/erpnext/patches/v8_9/set_print_zero_amount_taxes.py b/erpnext/patches/v8_9/set_print_zero_amount_taxes.py
deleted file mode 100644
index 3c508eaa09..0000000000
--- a/erpnext/patches/v8_9/set_print_zero_amount_taxes.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.setup.install import create_print_zero_amount_taxes_custom_field
-
-def execute():
- frappe.reload_doc('printing', 'doctype', 'print_style')
- frappe.reload_doc('printing', 'doctype', 'print_settings')
- create_print_zero_amount_taxes_custom_field()
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py b/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py
deleted file mode 100644
index 24e20409c1..0000000000
--- a/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
-
- if company:
- for doctype in ['Sales Invoice', 'Delivery Note']:
- frappe.db.sql(""" update `tab{0}`
- set billing_address_gstin = (select gstin from `tabAddress`
- where name = customer_address)
- where customer_address is not null and customer_address != ''""".format(doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/__init__.py b/erpnext/patches/v9_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v9_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v9_0/add_healthcare_domain.py b/erpnext/patches/v9_0/add_healthcare_domain.py
deleted file mode 100644
index 3c0433b9d4..0000000000
--- a/erpnext/patches/v9_0/add_healthcare_domain.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- domain = 'Healthcare'
- if not frappe.db.exists('Domain', domain):
- frappe.get_doc({
- 'doctype': 'Domain',
- 'domain': domain
- }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py b/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py
deleted file mode 100644
index 8a8c8064dd..0000000000
--- a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("POS Profile User"):
- frappe.reload_doc('accounts', 'doctype', 'pos_profile_user')
-
- frappe.db.sql(""" update `tabPOS Profile User`,
- (select `tabPOS Profile User`.name from `tabPOS Profile User`, `tabPOS Profile`
- where `tabPOS Profile`.name = `tabPOS Profile User`.parent
- group by `tabPOS Profile User`.user, `tabPOS Profile`.company) as pfu
- set
- `tabPOS Profile User`.default = 1
- where `tabPOS Profile User`.name = pfu.name""")
- else:
- doctype = 'POS Profile'
- frappe.reload_doc('accounts', 'doctype', doctype)
- frappe.reload_doc('accounts', 'doctype', 'pos_profile_user')
- frappe.reload_doc('accounts', 'doctype', 'pos_item_group')
- frappe.reload_doc('accounts', 'doctype', 'pos_customer_group')
-
- for doc in frappe.get_all(doctype):
- _doc = frappe.get_doc(doctype, doc.name)
- user = frappe.db.get_value(doctype, doc.name, 'user')
-
- if not user: continue
-
- _doc.append('applicable_for_users', {
- 'user': user,
- 'default': 1
- })
-
- _doc.flags.ignore_validate = True
- _doc.flags.ignore_mandatory = True
- _doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/copy_old_fees_field_data.py b/erpnext/patches/v9_0/copy_old_fees_field_data.py
deleted file mode 100644
index 14278209c7..0000000000
--- a/erpnext/patches/v9_0/copy_old_fees_field_data.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "fees")
- frappe.reload_doc("education", "doctype", "fees")
-
- if "total_amount" not in frappe.db.get_table_columns("Fees"):
- return
-
- frappe.db.sql("""update tabFees set grand_total=total_amount where grand_total = 0.0""")
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py b/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py
deleted file mode 100644
index c685bbc681..0000000000
--- a/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- default_warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse")
- if default_warehouse:
- if not frappe.db.get_value("Warehouse", {"name": default_warehouse}):
- frappe.db.set_value("Stock Settings", None, "default_warehouse", "")
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/remove_subscription_module.py b/erpnext/patches/v9_0/remove_subscription_module.py
deleted file mode 100644
index 493873f3e8..0000000000
--- a/erpnext/patches/v9_0/remove_subscription_module.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists('Module Def', 'Subscription'):
- frappe.db.sql(""" delete from `tabModule Def` where name = 'Subscription'""")
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/revert_manufacturing_user_role.py b/erpnext/patches/v9_0/revert_manufacturing_user_role.py
deleted file mode 100644
index f38b7f29ce..0000000000
--- a/erpnext/patches/v9_0/revert_manufacturing_user_role.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if 'Manufacturing' in frappe.get_active_domains(): return
-
- role = 'Manufacturing User'
- frappe.db.set_value('Role', role, 'restrict_to_domain', '')
- frappe.db.set_value('Role', role, 'disabled', 0)
-
- users = frappe.get_all('Has Role', filters = {
- 'parenttype': 'User',
- 'role': ('in', ['System Manager', 'Manufacturing Manager'])
- }, fields=['parent'], as_list=1)
-
- for user in users:
- _user = frappe.get_doc('User', user[0])
- _user.append('roles', {
- 'role': role
- })
- _user.flags.ignore_validate = True
- _user.save()
diff --git a/erpnext/patches/v9_0/set_pos_profile_name.py b/erpnext/patches/v9_0/set_pos_profile_name.py
deleted file mode 100644
index a3a9735215..0000000000
--- a/erpnext/patches/v9_0/set_pos_profile_name.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctype = 'POS Profile'
- frappe.reload_doctype(doctype)
-
- for pos in frappe.get_all(doctype, filters={'disabled': 0}):
- doc = frappe.get_doc(doctype, pos.name)
-
- if not doc.user: continue
-
- try:
- pos_profile_name = doc.user + ' - ' + doc.company
- doc.flags.ignore_validate = True
- doc.flags.ignore_mandatory = True
- doc.save()
-
- frappe.rename_doc(doctype, doc.name, pos_profile_name, force=True)
- except frappe.LinkValidationError:
- frappe.db.set_value("POS Profile", doc.name, 'disabled', 1)
diff --git a/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py b/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
deleted file mode 100644
index 3d012978fa..0000000000
--- a/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Material Request", "Purchase Order"):
- frappe.reload_doctype(doctype)
- frappe.reload_doctype(doctype + " Item")
-
- if not frappe.db.has_column(doctype, "schedule_date"):
- continue
-
- #Update only submitted MR
- for record in frappe.get_all(doctype, filters= [["docstatus", "=", 1]], fields=["name"]):
- doc = frappe.get_doc(doctype, record)
- if doc.items:
- if not doc.schedule_date:
- schedule_dates = [d.schedule_date for d in doc.items if d.schedule_date]
- if len(schedule_dates) > 0:
- min_schedule_date = min(schedule_dates)
- frappe.db.set_value(doctype, record,
- "schedule_date", min_schedule_date, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py b/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py
deleted file mode 100644
index 5092695b7d..0000000000
--- a/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Shipping Rule")
-
- # default "calculate_based_on"
- frappe.db.sql('''update `tabShipping Rule`
- set calculate_based_on = "Net Weight"
- where ifnull(calculate_based_on, '') = '' ''')
-
- # default "shipping_rule_type"
- frappe.db.sql('''update `tabShipping Rule`
- set shipping_rule_type = "Selling"
- where ifnull(shipping_rule_type, '') = '' ''')
diff --git a/erpnext/patches/v9_0/set_uoms_in_variant_field.py b/erpnext/patches/v9_0/set_uoms_in_variant_field.py
deleted file mode 100644
index 9e783d99be..0000000000
--- a/erpnext/patches/v9_0/set_uoms_in_variant_field.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- doc = frappe.get_doc('Item Variant Settings')
- variant_field_names = [vf.field_name for vf in doc.fields]
- if 'uoms' not in variant_field_names:
- doc.append(
- 'fields', {
- 'field_name': 'uoms'
- }
- )
- doc.save()
diff --git a/erpnext/patches/v9_0/set_variant_item_description.py b/erpnext/patches/v9_0/set_variant_item_description.py
deleted file mode 100644
index 82d6148508..0000000000
--- a/erpnext/patches/v9_0/set_variant_item_description.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cstr
-
-def execute():
- '''
- Issue:
- While copying data from template item to variant item,
- the system appending description multiple times to the respective variant.
-
- Purpose:
- Check variant description,
- if variant have user defined description remove all system appended descriptions
- else replace multiple system generated descriptions with single description
-
- Steps:
- 1. Get all variant items
- 2. Create system generated variant description
- 3. If variant have user defined description, remove all system generated descriptions
- 4. If variant description only contains system generated description,
- replace multiple descriptions by new description.
- '''
- for item in frappe.db.sql(""" select name from tabItem
- where ifnull(variant_of, '') != '' """,as_dict=1):
- variant = frappe.get_doc("Item", item.name)
- temp_variant_description = '\n'
-
- if variant.attributes:
- for d in variant.attributes:
- temp_variant_description += "
" + d.attribute + ": " + cstr(d.attribute_value) + "
"
-
- variant_description = variant.description.replace(temp_variant_description, '').rstrip()
- if variant_description:
- splitted_desc = variant.description.strip().split(temp_variant_description)
-
- if len(splitted_desc) > 2:
- if splitted_desc[0] == '':
- variant_description = temp_variant_description + variant_description
- elif splitted_desc[1] == '' or splitted_desc[1] == '\n':
- variant_description += temp_variant_description
- variant.db_set('description', variant_description, update_modified=False)
- else:
- variant.db_set('description', variant_description, update_modified=False)
-
- else:
- variant.db_set('description', temp_variant_description, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/student_admission_childtable_migrate.py b/erpnext/patches/v9_0/student_admission_childtable_migrate.py
deleted file mode 100644
index a5712c76dc..0000000000
--- a/erpnext/patches/v9_0/student_admission_childtable_migrate.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc('schools', 'doctype', 'Student Admission Program')
- # frappe.reload_doc('schools', 'doctype', 'student_admission')
- frappe.reload_doc('education', 'doctype', 'Student Admission Program')
- frappe.reload_doc('education', 'doctype', 'student_admission')
-
- if "program" not in frappe.db.get_table_columns("Student Admission"):
- return
-
- student_admissions = frappe.get_all("Student Admission", fields=["name", "application_fee", \
- "naming_series_for_student_applicant", "program", "introduction", "eligibility"])
- for student_admission in student_admissions:
- doc = frappe.get_doc("Student Admission", student_admission.name)
- doc.append("program_details", {
- "program": student_admission.get("program"),
- "application_fee": student_admission.get("application_fee"),
- "applicant_naming_series": student_admission.get("naming_series_for_student_applicant"),
- })
- if student_admission.eligibility and student_admission.introduction:
- doc.introduction = student_admission.introduction + "
" + \
- student_admission.eligibility + "
"
- doc.flags.ignore_validate = True
- doc.flags.ignore_mandatory = True
- doc.save()
diff --git a/erpnext/patches/v9_0/update_employee_loan_details.py b/erpnext/patches/v9_0/update_employee_loan_details.py
deleted file mode 100644
index ef8d32855f..0000000000
--- a/erpnext/patches/v9_0/update_employee_loan_details.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('Payroll', 'doctype', 'salary_slip_loan')
- frappe.reload_doc('Payroll', 'doctype', 'salary_slip')
-
- for data in frappe.db.sql(""" select name,
- start_date, end_date, total_loan_repayment
- from
- `tabSalary Slip`
- where
- docstatus < 2 and ifnull(total_loan_repayment, 0) > 0""", as_dict=1):
- salary_slip = frappe.get_doc('Salary Slip', data.name)
- salary_slip.set_loan_repayment()
-
- if salary_slip.total_loan_repayment == data.total_loan_repayment:
- for row in salary_slip.loans:
- row.db_update()
-
- salary_slip.db_update()
diff --git a/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py b/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py
deleted file mode 100644
index 45610ed5a7..0000000000
--- a/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Material Request')
- frappe.reload_doctype('Material Request Item')
-
- frappe.db.sql(""" update `tabMaterial Request Item`
- set stock_uom = uom, stock_qty = qty, conversion_factor = 1.0""")
\ No newline at end of file
diff --git a/erpnext/patches/v9_1/__init__.py b/erpnext/patches/v9_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v9_1/create_issue_opportunity_type.py b/erpnext/patches/v9_1/create_issue_opportunity_type.py
deleted file mode 100644
index aa8bbd1e79..0000000000
--- a/erpnext/patches/v9_1/create_issue_opportunity_type.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- # delete custom field if exists
- for doctype, fieldname in (('Issue', 'issue_type'), ('Opportunity', 'opportunity_type')):
- custom_field = frappe.db.get_value("Custom Field", {"fieldname": fieldname, 'dt': doctype})
- if custom_field:
- frappe.delete_doc("Custom Field", custom_field, ignore_permissions=True)
-
- frappe.reload_doc('support', 'doctype', 'issue_type')
- frappe.reload_doc('support', 'doctype', 'issue')
- frappe.reload_doc('crm', 'doctype', 'opportunity_type')
- frappe.reload_doc('crm', 'doctype', 'opportunity')
-
- # rename enquiry_type -> opportunity_type
- from frappe.model.utils.rename_field import rename_field
- rename_field('Opportunity', 'enquiry_type', 'opportunity_type')
-
- # create values if already set
- for opts in (('Issue', 'issue_type', 'Issue Type'),
- ('Opportunity', 'opportunity_type', 'Opportunity Type')):
- for d in frappe.db.sql('select distinct {0} from `tab{1}`'.format(opts[1], opts[0])):
- if d[0] and not frappe.db.exists(opts[2], d[0]):
- frappe.get_doc(dict(doctype = opts[2], name=d[0])).insert()
-
- # fixtures
- for name in ('Hub', _('Sales'), _('Support'), _('Maintenance')):
- if not frappe.db.exists('Opportunity Type', name):
- frappe.get_doc(dict(doctype = 'Opportunity Type', name=name)).insert()
diff --git a/erpnext/patches/v9_2/__init__.py b/erpnext/patches/v9_2/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py b/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py
deleted file mode 100644
index 54ae18b8e2..0000000000
--- a/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import getdate
-
-def execute():
- domain_settings = frappe.get_doc('Domain Settings')
- active_domains = [d.domain for d in domain_settings.active_domains]
-
- if "Healthcare" not in active_domains:
- items = ["TTT", "MCH", "LDL", "GTT", "HDL", "BILT", "BILD", "BP", "BS"]
- for item_code in items:
- try:
- item = frappe.db.get_value("Item", {"item_code": item_code}, ["name", "creation"], as_dict=1)
- if item and getdate(item.creation) >= getdate("2017-11-10"):
- frappe.delete_doc("Item", item.name)
- except:
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v9_2/delete_process_payroll.py b/erpnext/patches/v9_2/delete_process_payroll.py
deleted file mode 100644
index 91c49f577f..0000000000
--- a/erpnext/patches/v9_2/delete_process_payroll.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.delete_doc("DocType", "Process Payroll")
diff --git a/erpnext/patches/v9_2/remove_company_from_patient.py b/erpnext/patches/v9_2/remove_company_from_patient.py
deleted file mode 100644
index 1a50088f23..0000000000
--- a/erpnext/patches/v9_2/remove_company_from_patient.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Patient"):
- if 'company' in frappe.db.get_table_columns("Patient"):
- frappe.db.sql("alter table `tabPatient` drop column company")
diff --git a/erpnext/patches/v9_2/rename_net_weight_in_item_master.py b/erpnext/patches/v9_2/rename_net_weight_in_item_master.py
deleted file mode 100644
index cad979deab..0000000000
--- a/erpnext/patches/v9_2/rename_net_weight_in_item_master.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- frappe.reload_doc("stock", "doctype", "item")
- if frappe.db.has_column('Item', 'net_weight'):
- rename_field("Item", "net_weight", "weight_per_unit")
diff --git a/erpnext/patches/v9_2/rename_translated_domains_in_en.py b/erpnext/patches/v9_2/rename_translated_domains_in_en.py
deleted file mode 100644
index e5a9e2461f..0000000000
--- a/erpnext/patches/v9_2/rename_translated_domains_in_en.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-from frappe.model.rename_doc import rename_doc
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'item')
- language = frappe.get_single("System Settings").language
-
- if language and language.startswith('en'): return
-
- frappe.local.lang = language
-
- all_domains = frappe.get_hooks("domains")
-
- for domain in all_domains:
- translated_domain = _(domain, lang=language)
- if frappe.db.exists("Domain", translated_domain):
- #if domain already exists merged translated_domain and domain
- merge = False
- if frappe.db.exists("Domain", domain):
- merge=True
-
- rename_doc("Domain", translated_domain, domain, ignore_permissions=True, merge=merge)
-
- domain_settings = frappe.get_single("Domain Settings")
- active_domains = [d.domain for d in domain_settings.active_domains]
-
- try:
- for domain in active_domains:
- domain = frappe.get_doc("Domain", domain)
- domain.setup_domain()
-
- if int(frappe.db.get_single_value('System Settings', 'setup_complete')):
- domain.setup_sidebar_items()
- domain.setup_desktop_icons()
- domain.set_default_portal_role()
- except frappe.LinkValidationError:
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v9_2/repost_reserved_qty_for_production.py b/erpnext/patches/v9_2/repost_reserved_qty_for_production.py
deleted file mode 100644
index 040e655bd8..0000000000
--- a/erpnext/patches/v9_2/repost_reserved_qty_for_production.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "bin")
- bins = frappe.db.sql("select name from `tabBin` where reserved_qty_for_production > 0")
- for d in bins:
- bin_doc = frappe.get_doc("Bin", d[0])
- bin_doc.update_reserved_qty_for_production()
diff --git a/erpnext/patches/v9_2/set_item_name_in_production_order.py b/erpnext/patches/v9_2/set_item_name_in_production_order.py
deleted file mode 100644
index 1f490e62c8..0000000000
--- a/erpnext/patches/v9_2/set_item_name_in_production_order.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
-
- frappe.db.sql("""
- update `tabBOM Item` bom, `tabWork Order Item` po_item
- set po_item.item_name = bom.item_name,
- po_item.description = bom.description
- where po_item.item_code = bom.item_code
- and (po_item.item_name is null or po_item.description is null)
- """)
From 8697e894419181e90868732db023d39e7561a58a Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 11:47:09 +0530
Subject: [PATCH 165/262] chore: Drop < v10 patches from list
v7 backup was restored and upgraded to latest v10.x.x branch. The patches run uptil the upgrade are removed in this change. This means only existing v10 sites are allowed direct upgrade to v13 and newer
There are older version patches still left since they're being used in later ERPNext versions too.
---
erpnext/patches.txt | 495 --------------------------------------------
1 file changed, 495 deletions(-)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 1e8ce3c658..770bef353f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -1,494 +1,19 @@
-execute:import unidecode # new requirement
-erpnext.patches.v8_0.move_perpetual_inventory_setting
-erpnext.patches.v8_9.set_print_zero_amount_taxes
erpnext.patches.v12_0.update_is_cancelled_field
erpnext.patches.v11_0.rename_production_order_to_work_order
erpnext.patches.v11_0.refactor_naming_series
erpnext.patches.v11_0.refactor_autoname_naming
-erpnext.patches.v10_0.rename_schools_to_education
-erpnext.patches.v4_0.validate_v3_patch
-erpnext.patches.v4_0.fix_employee_user_id
-erpnext.patches.v4_0.remove_employee_role_if_no_employee
-erpnext.patches.v4_0.update_user_properties
-erpnext.patches.v4_0.apply_user_permissions
-erpnext.patches.v4_0.move_warehouse_user_to_restrictions
-erpnext.patches.v4_0.global_defaults_to_system_settings
-erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28
execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16 #2020-07-24
-execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24
-execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31
-execute:frappe.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-29
-execute:frappe.reload_doc('selling', 'doctype', 'quotation') # 2014-01-29
-execute:frappe.reload_doc('stock', 'doctype', 'delivery_note') # 2014-01-29
-erpnext.patches.v4_0.reload_sales_print_format
-execute:frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') # 2014-01-29
-execute:frappe.reload_doc('buying', 'doctype', 'purchase_order') # 2014-01-29
-execute:frappe.reload_doc('buying', 'doctype', 'supplier_quotation') # 2014-01-29
-execute:frappe.reload_doc('stock', 'doctype', 'purchase_receipt') # 2014-01-29
-execute:frappe.reload_doc('accounts', 'doctype', 'pos_setting') # 2014-01-29
-execute:frappe.reload_doc('selling', 'doctype', 'customer') # 2014-01-29
-execute:frappe.reload_doc('buying', 'doctype', 'supplier') # 2014-01-29
-execute:frappe.reload_doc('accounts', 'doctype', 'asset_category')
-execute:frappe.reload_doc('accounts', 'doctype', 'pricing_rule')
-erpnext.patches.v4_0.map_charge_to_taxes_and_charges
-execute:frappe.reload_doc('support', 'doctype', 'newsletter') # 2014-01-31
-execute:frappe.reload_doc('hr', 'doctype', 'employee') # 2014-02-03
-execute:frappe.db.sql("update tabPage set module='Core' where name='Setup'")
-erpnext.patches.v5_2.change_item_selects_to_checks
-execute:frappe.reload_doctype('Item')
-erpnext.patches.v4_0.fields_to_be_renamed
-erpnext.patches.v4_0.rename_sitemap_to_route
-erpnext.patches.v7_0.re_route #2016-06-27
-erpnext.patches.v4_0.fix_contact_address
-erpnext.patches.v4_0.customer_discount_to_pricing_rule
-execute:frappe.db.sql("""delete from `tabWebsite Item Group` where ifnull(item_group, '')=''""")
-erpnext.patches.v4_0.remove_module_home_pages
-erpnext.patches.v4_0.split_email_settings
-erpnext.patches.v4_0.import_country_codes
-erpnext.patches.v4_0.countrywise_coa
-execute:frappe.delete_doc("DocType", "MIS Control")
-execute:frappe.delete_doc("Page", "Financial Statements")
-execute:frappe.delete_doc("DocType", "Stock Ledger")
-execute:frappe.delete_doc("DocType", "Grade")
-execute:frappe.db.sql("delete from `tabWebsite Item Group` where ifnull(item_group, '')=''")
-execute:frappe.delete_doc("Print Format", "SalesInvoice")
-execute:import frappe.defaults;frappe.defaults.clear_default("price_list_currency")
-erpnext.patches.v4_0.update_account_root_type
-execute:frappe.delete_doc("Report", "Purchase In Transit")
-erpnext.patches.v4_0.new_address_template
-execute:frappe.delete_doc("DocType", "SMS Control")
-execute:frappe.delete_doc_if_exists("DocType", "Bulk SMS") #2015-08-18
-erpnext.patches.v4_0.fix_case_of_hr_module_def
-erpnext.patches.v4_0.fix_address_template
-
-# WATCHOUT: This patch reload's documents
-erpnext.patches.v4_0.reset_permissions_for_masters
-erpnext.patches.v6_20x.rename_project_name_to_project #2016-03-14
-
-erpnext.patches.v4_0.update_tax_amount_after_discount
-execute:frappe.permissions.reset_perms("GL Entry") #2014-06-09
-execute:frappe.permissions.reset_perms("Stock Ledger Entry") #2014-06-09
-erpnext.patches.v4_0.create_custom_fields_for_india_specific_fields
-erpnext.patches.v4_0.save_default_letterhead
-erpnext.patches.v4_0.update_custom_print_formats_for_renamed_fields
-erpnext.patches.v4_0.update_other_charges_in_custom_purchase_print_formats
-erpnext.patches.v4_0.create_price_list_if_missing
-execute:frappe.db.sql("update `tabItem` set end_of_life=null where end_of_life='0000-00-00'") #2014-06-16
-erpnext.patches.v4_0.update_users_report_view_settings
-erpnext.patches.v4_0.set_pricing_rule_for_buying_or_selling
-erpnext.patches.v4_1.set_outgoing_email_footer
-erpnext.patches.v4_1.fix_sales_order_delivered_status
-erpnext.patches.v4_1.fix_delivery_and_billing_status
-execute:frappe.db.sql("update `tabAccount` set root_type='Liability' where root_type='Income' and report_type='Balance Sheet'")
-execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool") # 29-07-2014
-execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool Detail") # 29-07-2014
-execute:frappe.delete_doc("Page", "trial-balance") #2014-07-22
-erpnext.patches.v4_2.delete_old_print_formats #2014-07-29
-erpnext.patches.v4_2.toggle_rounded_total #2014-07-30
-erpnext.patches.v4_2.fix_account_master_type
-erpnext.patches.v4_2.update_project_milestones
-erpnext.patches.v4_2.add_currency_turkish_lira #2014-08-08
-execute:frappe.delete_doc("DocType", "Landed Cost Wizard")
-erpnext.patches.v4_2.default_website_style
-erpnext.patches.v4_2.set_company_country
-erpnext.patches.v4_2.update_sales_order_invoice_field_name
-erpnext.patches.v4_2.seprate_manufacture_and_repack
-execute:frappe.delete_doc("Report", "Warehouse-Wise Stock Balance")
-execute:frappe.delete_doc("DocType", "Purchase Request")
-execute:frappe.delete_doc("DocType", "Purchase Request Item")
-erpnext.patches.v4_2.recalculate_bom_cost
-erpnext.patches.v4_2.fix_gl_entries_for_stock_transactions
erpnext.patches.v4_2.update_requested_and_ordered_qty #2021-03-31
-execute:frappe.rename_doc("DocType", "Support Ticket", "Issue", force=True)
-erpnext.patches.v4_4.make_email_accounts
-execute:frappe.delete_doc("DocType", "Contact Control")
-erpnext.patches.v4_2.discount_amount
-erpnext.patches.v4_2.reset_bom_costs
-erpnext.patches.v5_0.update_frozen_accounts_permission_role
-erpnext.patches.v5_0.update_dn_against_doc_fields
-execute:frappe.db.sql("update `tabMaterial Request` set material_request_type = 'Material Transfer' where material_request_type = 'Transfer'")
-execute:frappe.reload_doc('stock', 'doctype', 'item')
-erpnext.patches.v5_0.set_default_company_in_bom
-execute:frappe.reload_doc('crm', 'doctype', 'lead')
-execute:frappe.reload_doc('crm', 'doctype', 'opportunity')
-erpnext.patches.v5_0.rename_taxes_and_charges_master
-erpnext.patches.v5_1.sales_bom_rename
-erpnext.patches.v5_0.rename_table_fieldnames
-execute:frappe.db.sql("update `tabJournal Entry` set voucher_type='Journal Entry' where ifnull(voucher_type, '')=''")
-erpnext.patches.v5_0.is_group
-erpnext.patches.v4_2.party_model
-erpnext.patches.v5_0.party_model_patch_fix
-erpnext.patches.v4_1.fix_jv_remarks
-erpnext.patches.v4_2.update_landed_cost_voucher
-erpnext.patches.v4_2.set_item_has_batch
-erpnext.patches.v4_2.update_stock_uom_for_dn_in_sle
-erpnext.patches.v5_0.recalculate_total_amount_in_jv
-erpnext.patches.v5_0.update_companywise_payment_account
-erpnext.patches.v5_0.remove_birthday_events
-erpnext.patches.v5_0.update_item_name_in_bom
-erpnext.patches.v5_0.rename_customer_issue
-erpnext.patches.v5_0.rename_total_fields
-erpnext.patches.v5_0.new_crm_module
-erpnext.patches.v5_0.rename_customer_issue
-erpnext.patches.v5_0.update_material_transfer_for_manufacture
-execute:frappe.reload_doc('crm', 'doctype', 'opportunity_item')
-erpnext.patches.v5_0.update_item_description_and_image
-erpnext.patches.v5_0.update_material_transferred_for_manufacturing
-erpnext.patches.v5_0.stock_entry_update_value
-erpnext.patches.v5_0.convert_stock_reconciliation
-erpnext.patches.v5_0.update_projects
-erpnext.patches.v5_0.item_patches
-erpnext.patches.v5_0.update_journal_entry_title
-erpnext.patches.v5_0.taxes_and_totals_in_party_currency
-erpnext.patches.v5_0.replace_renamed_fields_in_custom_scripts_and_print_formats
-erpnext.patches.v5_0.update_from_bom
-erpnext.patches.v5_0.update_account_types
-erpnext.patches.v5_0.update_sms_sender
-erpnext.patches.v5_0.set_appraisal_remarks
-erpnext.patches.v5_0.update_time_log_title
-erpnext.patches.v7_0.create_warehouse_nestedset
-erpnext.patches.v7_0.merge_account_type_stock_and_warehouse_to_stock
-erpnext.patches.v7_0.set_is_group_for_warehouse
-erpnext.patches.v7_2.stock_uom_in_selling
-erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse
-erpnext.patches.v5_0.newsletter
-execute:frappe.delete_doc("DocType", "Chart of Accounts")
-execute:frappe.delete_doc("DocType", "Style Settings")
-erpnext.patches.v5_0.update_opportunity
-erpnext.patches.v5_0.opportunity_not_submittable
-execute:frappe.permissions.reset_perms("Purchase Taxes and Charges Template") #2014-06-09
-execute:frappe.permissions.reset_perms("Expense Claim Type") #2014-06-19
-erpnext.patches.v5_0.execute_on_doctype_update
-erpnext.patches.v4_2.fix_recurring_orders
-erpnext.patches.v4_2.delete_gl_entries_for_cancelled_invoices
-erpnext.patches.v5_0.project_costing
-erpnext.patches.v5_0.update_temporary_account
-erpnext.patches.v5_0.update_advance_paid
-erpnext.patches.v5_0.link_warehouse_with_account
-execute:frappe.delete_doc("Page", "stock-ledger")
-execute:frappe.delete_doc("Page","stock-level")
-erpnext.patches.v5_0.reclculate_planned_operating_cost_in_production_order
-erpnext.patches.v5_0.repost_requested_qty
-erpnext.patches.v5_0.fix_taxes_and_totals_in_party_currency
-erpnext.patches.v5_0.update_tax_amount_after_discount_in_purchase_cycle
-erpnext.patches.v5_0.rename_pos_setting
-erpnext.patches.v5_0.update_operation_description
-erpnext.patches.v5_0.set_footer_address
-execute:frappe.db.set_value("Backup Manager", None, "send_backups_to_dropbox", 1 if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox") in ("Daily", "Weekly") else 0)
-execute:frappe.db.sql_list("delete from `tabDocPerm` where parent='Issue' and modified_by='Administrator' and role='Guest'")
-erpnext.patches.v5_0.update_item_and_description_again
-erpnext.patches.v6_0.multi_currency
-erpnext.patches.v7_0.create_budget_record
-erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
-erpnext.patches.v5_0.portal_fixes
-erpnext.patches.v5_0.reset_values_in_tools # 02-05-2016
-execute:frappe.delete_doc("Page", "users")
-erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
-erpnext.patches.v5_0.index_on_account_and_gl_entry
-execute:frappe.db.sql("""delete from `tabProject Task`""")
-erpnext.patches.v5_0.update_item_desc_in_invoice
-erpnext.patches.v5_1.fix_against_account
-execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
-erpnext.patches.v5_1.rename_roles
-erpnext.patches.v5_1.default_bom
-execute:frappe.delete_doc("DocType", "Party Type")
-execute:frappe.delete_doc("Module Def", "Contacts")
-erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items # 30-07-2015
-execute:frappe.reload_doctype("Leave Type")
-execute:frappe.db.sql("update `tabLeave Type` set include_holiday=0")
-erpnext.patches.v5_4.set_root_and_report_type
-erpnext.patches.v5_4.notify_system_managers_regarding_wrong_tax_calculation
-erpnext.patches.v5_4.fix_invoice_outstanding
-execute:frappe.db.sql("update `tabStock Ledger Entry` set stock_queue = '[]' where voucher_type = 'Stock Reconciliation' and ifnull(qty_after_transaction, 0) = 0")
-erpnext.patches.v5_4.fix_missing_item_images
-erpnext.patches.v5_4.stock_entry_additional_costs
-erpnext.patches.v5_4.cleanup_journal_entry #2015-08-14
erpnext.patches.v5_7.update_item_description_based_on_item_master
-erpnext.patches.v5_7.item_template_attributes
-execute:frappe.delete_doc_if_exists("DocType", "Manage Variants")
-execute:frappe.delete_doc_if_exists("DocType", "Manage Variants Item")
erpnext.patches.v4_2.repost_reserved_qty #2021-03-31
-erpnext.patches.v5_4.update_purchase_cost_against_project
-erpnext.patches.v5_8.update_order_reference_in_return_entries
-erpnext.patches.v5_8.add_credit_note_print_heading
-execute:frappe.delete_doc_if_exists("Print Format", "Credit Note - Negative Invoice")
-
-# V6.0
-erpnext.patches.v6_0.set_default_title # 2015-09-03
-erpnext.patches.v6_0.default_activity_rate
-execute:frappe.db.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1)
-execute:frappe.db.sql("""update `tabProject` set percent_complete=round(percent_complete, 2) where percent_complete is not null""")
-erpnext.patches.v6_0.fix_outstanding_amount
-erpnext.patches.v6_0.fix_planned_qty
-erpnext.patches.v6_2.remove_newsletter_duplicates
-erpnext.patches.v6_2.fix_missing_default_taxes_and_lead
-erpnext.patches.v6_3.convert_applicable_territory
-erpnext.patches.v6_4.round_status_updater_percentages
-erpnext.patches.v6_4.repost_gle_for_journal_entries_where_reference_name_missing
-erpnext.patches.v6_4.fix_journal_entries_due_to_reconciliation
-erpnext.patches.v6_4.fix_status_in_sales_and_purchase_order
-erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order
-erpnext.patches.v6_4.fix_duplicate_bins
-erpnext.patches.v6_4.fix_sales_order_maintenance_status
-erpnext.patches.v6_4.email_digest_update
-
-# delete shopping cart doctypes
-execute:frappe.delete_doc_if_exists("DocType", "Applicable Territory")
-execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Price List")
-execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Taxes and Charges Master")
-
-erpnext.patches.v6_4.set_user_in_contact
-erpnext.patches.v6_4.make_image_thumbnail #2015-10-20
-erpnext.patches.v6_5.show_in_website_for_template_item
-erpnext.patches.v6_4.fix_expense_included_in_valuation
-execute:frappe.delete_doc_if_exists("Report", "Item-wise Last Purchase Rate")
-erpnext.patches.v6_6.fix_website_image
-erpnext.patches.v6_6.remove_fiscal_year_from_leave_allocation
-execute:frappe.delete_doc_if_exists("DocType", "Stock UOM Replace Utility")
-erpnext.patches.v6_8.make_webform_standard #2015-11-23
-erpnext.patches.v6_8.move_drop_ship_to_po_items
-erpnext.patches.v6_10.fix_ordered_received_billed
-erpnext.patches.v6_10.fix_jv_total_amount #2015-11-30
-erpnext.patches.v6_10.email_digest_default_quote
-erpnext.patches.v6_10.fix_billed_amount_in_drop_ship_po
-erpnext.patches.v6_10.fix_delivery_status_of_drop_ship_item #2015-12-08
-erpnext.patches.v5_8.tax_rule #2015-12-08
-erpnext.patches.v6_12.set_overdue_tasks
-erpnext.patches.v6_16.update_billing_status_in_dn_and_pr
-erpnext.patches.v6_16.create_manufacturer_records
-execute:frappe.db.sql("update `tabPricing Rule` set title=name where title='' or title is null") #2016-01-27
-erpnext.patches.v6_20.set_party_account_currency_in_orders
-erpnext.patches.v6_19.comment_feed_communication
-erpnext.patches.v6_21.fix_reorder_level
-erpnext.patches.v6_21.rename_material_request_fields
-erpnext.patches.v6_23.update_stopped_status_to_closed
-erpnext.patches.v6_24.set_recurring_id
-erpnext.patches.v6_20x.set_compact_print
-execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10
-erpnext.patches.v6_20x.remove_fiscal_year_from_holiday_list
-erpnext.patches.v6_24.map_customer_address_to_shipping_address_on_po
-erpnext.patches.v6_27.fix_recurring_order_status
-erpnext.patches.v6_20x.update_product_bundle_description
-erpnext.patches.v7_0.update_party_status #2016-09-22
-erpnext.patches.v7_0.remove_features_setup
-erpnext.patches.v7_0.update_home_page
-execute:frappe.delete_doc_if_exists("Page", "financial-analytics")
-erpnext.patches.v7_0.update_project_in_gl_entry
-execute:frappe.db.sql('update tabQuotation set status="Cancelled" where docstatus=2')
-execute:frappe.rename_doc("DocType", "Payments", "Sales Invoice Payment", force=True)
-erpnext.patches.v7_0.update_mins_to_first_response
-erpnext.patches.v6_20x.repost_valuation_rate_for_negative_inventory
-erpnext.patches.v7_0.migrate_mode_of_payments_v6_to_v7
-erpnext.patches.v7_0.system_settings_setup_complete
-erpnext.patches.v7_0.set_naming_series_for_timesheet #2016-07-27
-execute:frappe.reload_doc('projects', 'doctype', 'project')
-execute:frappe.reload_doc('projects', 'doctype', 'project_user')
-erpnext.patches.v7_0.convert_timelogbatch_to_timesheet
-erpnext.patches.v7_0.convert_timelog_to_timesheet
-erpnext.patches.v7_0.move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet
-erpnext.patches.v7_0.remove_doctypes_and_reports #2016-10-29
-erpnext.patches.v7_0.update_maintenance_module_in_doctype
-erpnext.patches.v7_0.update_prevdoc_values_for_supplier_quotation_item
-erpnext.patches.v7_0.rename_advance_table_fields
-erpnext.patches.v7_0.rename_salary_components
-erpnext.patches.v7_0.rename_prevdoc_fields
-erpnext.patches.v7_0.rename_time_sheet_doctype
-execute:frappe.delete_doc_if_exists("Report", "Customers Not Buying Since Long Time")
-erpnext.patches.v7_0.make_is_group_fieldtype_as_check
-execute:frappe.reload_doc('projects', 'doctype', 'timesheet') #2016-09-12
-erpnext.patches.v7_1.rename_field_timesheet
-execute:frappe.delete_doc_if_exists("Report", "Employee Holiday Attendance")
-execute:frappe.delete_doc_if_exists("DocType", "Payment Tool")
-execute:frappe.delete_doc_if_exists("DocType", "Payment Tool Detail")
-erpnext.patches.v7_0.setup_account_table_for_expense_claim_type_if_exists
-erpnext.patches.v7_0.migrate_schools_to_erpnext
-erpnext.patches.v7_1.update_lead_source
-erpnext.patches.v6_20x.remove_customer_supplier_roles
-erpnext.patches.v7_0.remove_administrator_role_in_doctypes
-erpnext.patches.v7_0.rename_fee_amount_to_fee_component
-erpnext.patches.v7_0.calculate_total_costing_amount
-erpnext.patches.v7_0.fix_nonwarehouse_ledger_gl_entries_for_transactions
-erpnext.patches.v7_0.remove_old_earning_deduction_doctypes
-erpnext.patches.v7_0.make_guardian
-erpnext.patches.v7_0.update_refdoc_in_landed_cost_voucher
-erpnext.patches.v7_0.set_material_request_type_in_item
-erpnext.patches.v7_0.rename_examination_to_assessment
-erpnext.patches.v7_0.set_portal_settings
-erpnext.patches.v7_0.update_change_amount_account
-erpnext.patches.v7_0.fix_duplicate_icons
-erpnext.patches.v7_0.repost_gle_for_pos_sales_return
-erpnext.patches.v7_1.update_total_billing_hours
-erpnext.patches.v7_1.update_component_type
-erpnext.patches.v7_0.repost_gle_for_pos_sales_return
-erpnext.patches.v7_0.update_missing_employee_in_timesheet
-erpnext.patches.v7_0.update_status_for_timesheet
-erpnext.patches.v7_0.set_party_name_in_payment_entry
-erpnext.patches.v7_1.set_student_guardian
-erpnext.patches.v7_0.update_conversion_factor_in_supplier_quotation_item
-erpnext.patches.v7_1.move_sales_invoice_from_parent_to_child_timesheet
-execute:frappe.db.sql("update `tabTimesheet` ts, `tabEmployee` emp set ts.employee_name = emp.employee_name where emp.name = ts.employee and ts.employee_name is null and ts.employee is not null")
-erpnext.patches.v7_1.fix_link_for_customer_from_lead
-execute:frappe.db.sql("delete from `tabTimesheet Detail` where NOT EXISTS (select name from `tabTimesheet` where name = `tabTimesheet Detail`.parent)")
-erpnext.patches.v7_0.update_mode_of_payment_type
-
-execute:frappe.reload_doctype('Employee') #2016-10-18
-execute:frappe.db.sql("update `tabEmployee` set prefered_contact_email = IFNULL(prefered_contact_email,'') ")
execute:frappe.reload_doc("Payroll", "doctype", "salary_slip")
-execute:frappe.db.sql("update `tabSalary Slip` set posting_date=creation")
-execute:frappe.reload_doc("stock", "doctype", "stock_settings")
-erpnext.patches.v8_0.create_domain_docs #16-05-2017
-erpnext.patches.v7_1.update_portal_roles
-erpnext.patches.v7_1.set_total_amount_currency_in_je
-finally:erpnext.patches.v7_0.update_timesheet_communications
-erpnext.patches.v7_0.update_status_of_zero_amount_sales_order
-erpnext.patches.v7_1.add_field_for_task_dependent
-erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty
-erpnext.patches.v7_1.set_prefered_contact_email
-execute:frappe.reload_doc('accounts', 'doctype', 'accounts_settings')
-execute:frappe.db.set_value("Accounts Settings", "Accounts Settings", "unlink_payment_on_cancellation_of_invoice", 0)
-execute:frappe.db.sql("update `tabStock Entry` set total_amount = 0 where purpose in('Repack', 'Manufacture')")
-erpnext.patches.v7_1.save_stock_settings
-erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01
-erpnext.patches.v7_1.add_account_user_role_for_timesheet
-erpnext.patches.v7_0.set_base_amount_in_invoice_payment_table
-erpnext.patches.v7_1.update_invoice_status
-erpnext.patches.v7_0.po_status_issue_for_pr_return
-erpnext.patches.v7_1.update_missing_salary_component_type
-erpnext.patches.v7_1.rename_quality_inspection_field
-erpnext.patches.v7_0.update_autoname_field
-erpnext.patches.v7_1.update_bom_base_currency
-erpnext.patches.v7_0.update_status_of_po_so
-erpnext.patches.v7_1.set_budget_against_as_cost_center
-erpnext.patches.v7_1.set_currency_exchange_date
-erpnext.patches.v7_1.set_sales_person_status
-erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items
-erpnext.patches.v7_2.update_website_for_variant
-erpnext.patches.v7_2.update_assessment_modules
-erpnext.patches.v7_2.update_doctype_status
-erpnext.patches.v7_2.update_salary_slips
-erpnext.patches.v7_2.delete_fleet_management_module_def
-erpnext.patches.v7_2.contact_address_links
-erpnext.patches.v7_2.mark_students_active
-erpnext.patches.v7_2.set_null_value_to_fields
-erpnext.patches.v7_2.update_guardian_name_in_student_master
-erpnext.patches.v7_2.update_abbr_in_salary_slips
-erpnext.patches.v7_2.rename_evaluation_criteria
-erpnext.patches.v7_2.update_party_type
-erpnext.patches.v7_2.setup_auto_close_settings
-erpnext.patches.v7_2.empty_supplied_items_for_non_subcontracted
-erpnext.patches.v7_2.arrear_leave_encashment_as_salary_component
-erpnext.patches.v7_2.rename_att_date_attendance
-erpnext.patches.v7_2.update_attendance_docstatus
-erpnext.patches.v7_2.make_all_assessment_group
-erpnext.patches.v8_0.repost_reserved_qty_for_multiple_sales_uom
-erpnext.patches.v8_0.addresses_linked_to_lead
-execute:frappe.delete_doc('DocType', 'Purchase Common')
-erpnext.patches.v8_0.update_stock_qty_value_in_purchase_invoice
-erpnext.patches.v8_0.update_supplier_address_in_stock_entry
-erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate
-erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices
-erpnext.patches.v8_0.enable_booking_asset_depreciation_automatically
-erpnext.patches.v8_0.set_project_copied_from
-erpnext.patches.v8_0.update_status_as_paid_for_completed_expense_claim
-erpnext.patches.v7_2.stock_uom_in_selling
-erpnext.patches.v8_0.revert_manufacturers_table_from_item
-erpnext.patches.v8_0.disable_instructor_role
-erpnext.patches.v8_0.merge_student_batch_and_student_group
-erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
-erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding
-erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice
-erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note
-erpnext.patches.v8_0.delete_schools_depricated_doctypes
-erpnext.patches.v8_0.update_customer_pos_id
-erpnext.patches.v8_0.rename_items_in_status_field_of_material_request
-erpnext.patches.v8_0.delete_bin_indexes
-erpnext.patches.v8_0.move_account_head_from_account_to_warehouse_for_inventory
-erpnext.patches.v8_0.change_in_words_varchar_length
-erpnext.patches.v8_0.update_stock_qty_value_in_bom_item
-erpnext.patches.v8_0.update_sales_cost_in_project
-erpnext.patches.v8_0.save_system_settings
-erpnext.patches.v8_1.delete_deprecated_reports
-erpnext.patches.v9_0.remove_subscription_module
-erpnext.patches.v8_7.make_subscription_from_recurring_data
erpnext.patches.v8_1.setup_gst_india #2017-06-27
-execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account #16-08-2018
-erpnext.patches.v8_1.gst_fixes #2017-07-06
-erpnext.patches.v8_0.update_production_orders
-erpnext.patches.v8_1.remove_sales_invoice_from_returned_serial_no
-erpnext.patches.v8_1.allow_invoice_copy_to_edit_after_submit
-erpnext.patches.v8_1.add_hsn_sac_codes
-erpnext.patches.v8_1.update_gst_state #17-07-2017
-erpnext.patches.v8_1.removed_report_support_hours
-erpnext.patches.v8_1.add_indexes_in_transaction_doctypes
-erpnext.patches.v8_3.set_restrict_to_domain_for_module_def
-erpnext.patches.v8_1.update_expense_claim_status
-erpnext.patches.v8_3.update_company_total_sales #2017-08-16
-erpnext.patches.v8_4.make_scorecard_records
-erpnext.patches.v8_1.set_delivery_date_in_so_item #2017-07-28
-erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs
-erpnext.patches.v8_5.remove_quotations_route_in_sidebar
-erpnext.patches.v8_5.update_existing_data_in_project_type
-erpnext.patches.v8_5.set_default_mode_of_payment
-erpnext.patches.v8_5.update_customer_group_in_POS_profile
-erpnext.patches.v8_6.update_timesheet_company_from_PO
-erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager
-erpnext.patches.v8_5.remove_project_type_property_setter
erpnext.patches.v8_7.sync_india_custom_fields
-erpnext.patches.v8_7.fix_purchase_receipt_status
-erpnext.patches.v8_6.rename_bom_update_tool
-erpnext.patches.v8_9.add_setup_progress_actions #08-09-2017 #26-09-2017 #22-11-2017 #15-12-2017
-erpnext.patches.v8_9.rename_company_sales_target_field
-erpnext.patches.v8_8.set_bom_rate_as_per_uom
-erpnext.patches.v8_8.add_new_fields_in_accounts_settings
-erpnext.patches.v8_9.set_default_customer_group
-erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts
-erpnext.patches.v8_9.set_default_fields_in_variant_settings
-erpnext.patches.v8_9.update_billing_gstin_for_indian_account
-erpnext.patches.v8_9.set_member_party_type
-erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile
-erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
-erpnext.patches.v9_0.student_admission_childtable_migrate
-erpnext.patches.v9_0.add_healthcare_domain
-erpnext.patches.v9_0.set_variant_item_description
-erpnext.patches.v9_0.set_uoms_in_variant_field
-erpnext.patches.v9_0.copy_old_fees_field_data
-execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
-erpnext.patches.v9_0.set_pos_profile_name
-erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings
-execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
-erpnext.patches.v8_10.change_default_customer_credit_days
-erpnext.patches.v9_0.update_employee_loan_details
-erpnext.patches.v9_2.delete_healthcare_domain_default_items
-erpnext.patches.v9_1.create_issue_opportunity_type
-erpnext.patches.v9_2.rename_translated_domains_in_en
-erpnext.patches.v9_0.set_shipping_type_for_existing_shipping_rules
-erpnext.patches.v9_0.update_multi_uom_fields_in_material_request
-erpnext.patches.v9_2.repost_reserved_qty_for_production
-erpnext.patches.v9_2.remove_company_from_patient
-erpnext.patches.v9_2.set_item_name_in_production_order
-erpnext.patches.v10_0.update_lft_rgt_for_employee
-erpnext.patches.v9_2.rename_net_weight_in_item_master
-erpnext.patches.v9_2.delete_process_payroll
-erpnext.patches.v10_0.add_agriculture_domain
-erpnext.patches.v10_0.add_non_profit_domain
-erpnext.patches.v10_0.setup_vat_for_uae_and_saudi_arabia #2017-12-28
-erpnext.patches.v10_0.set_primary_contact_for_customer
-erpnext.patches.v10_0.copy_projects_renamed_fields
-erpnext.patches.v10_0.enabled_regional_print_format_based_on_country
-erpnext.patches.v10_0.update_asset_calculate_depreciation
-erpnext.patches.v10_0.add_guardian_role_for_parent_portal
-erpnext.patches.v10_0.set_numeric_ranges_in_template_if_blank
-erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
erpnext.patches.v10_0.fichier_des_ecritures_comptables_for_france
-erpnext.patches.v10_0.update_assessment_plan
-erpnext.patches.v10_0.update_assessment_result
-erpnext.patches.v10_0.set_default_payment_terms_based_on_company
-erpnext.patches.v10_0.update_sales_order_link_to_purchase_order
erpnext.patches.v10_0.rename_price_to_rate_in_pricing_rule
erpnext.patches.v10_0.set_currency_in_pricing_rule
-erpnext.patches.v10_0.set_b2c_limit
erpnext.patches.v10_0.update_translatable_fields
erpnext.patches.v10_0.rename_offer_letter_to_job_offer
execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True)
@@ -496,16 +21,6 @@ erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_
erpnext.patches.v10_0.add_default_cash_flow_mappers
erpnext.patches.v11_0.rename_duplicate_item_code_values
erpnext.patches.v11_0.make_quality_inspection_template
-erpnext.patches.v10_0.update_status_for_multiple_source_in_po
-erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
-erpnext.patches.v10_0.update_territory_and_customer_group
-erpnext.patches.v10_0.update_warehouse_address_details
-erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
-erpnext.patches.v10_0.update_hub_connector_domain
-erpnext.patches.v10_0.set_student_party_type
-erpnext.patches.v10_0.update_project_in_sle
-erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
-erpnext.patches.v10_0.repost_requested_qty_for_non_stock_uom_items
erpnext.patches.v11_0.merge_land_unit_with_location
erpnext.patches.v11_0.add_index_on_nestedset_doctypes
erpnext.patches.v11_0.remove_modules_setup_page
@@ -514,7 +29,6 @@ erpnext.patches.v11_0.update_department_lft_rgt
erpnext.patches.v11_0.add_default_email_template_for_leave
erpnext.patches.v11_0.set_default_email_template_in_hr #08-06-2018
erpnext.patches.v11_0.uom_conversion_data #30-06-2018
-erpnext.patches.v10_0.taxes_issue_with_pos
erpnext.patches.v11_0.update_account_type_in_party_type
erpnext.patches.v11_0.rename_healthcare_doctype_and_fields
erpnext.patches.v11_0.rename_supplier_type_to_supplier_group
@@ -522,8 +36,6 @@ erpnext.patches.v10_1.transfer_subscription_to_auto_repeat
erpnext.patches.v11_0.update_brand_in_item_price
erpnext.patches.v11_0.create_default_success_action
erpnext.patches.v11_0.add_healthcare_service_unit_tree_root
-erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
-erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
erpnext.patches.v11_0.rename_field_max_days_allowed
erpnext.patches.v11_0.create_salary_structure_assignments
erpnext.patches.v11_0.rename_health_insurance
@@ -536,7 +48,6 @@ erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-
erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07
erpnext.patches.v11_0.rename_overproduction_percent_field
erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom
-erpnext.patches.v10_0.update_status_in_purchase_receipt
erpnext.patches.v11_0.inter_state_field_for_gst
erpnext.patches.v11_0.rename_members_with_naming_series #04-06-2018
erpnext.patches.v11_0.set_update_field_and_value_in_workflow_state
@@ -550,13 +61,10 @@ erpnext.patches.v11_0.skip_user_permission_check_for_department
erpnext.patches.v11_0.set_department_for_doctypes
erpnext.patches.v11_0.update_allow_transfer_for_manufacture
erpnext.patches.v11_0.add_item_group_defaults
-erpnext.patches.v10_0.update_address_template_for_india
erpnext.patches.v11_0.add_expense_claim_default_account
execute:frappe.delete_doc("Page", "hub")
erpnext.patches.v11_0.reset_publish_in_hub_for_all_items
erpnext.patches.v11_0.update_hub_url # 2018-08-31 # 2018-09-03
-erpnext.patches.v10_0.set_discount_amount
-erpnext.patches.v10_0.recalculate_gross_margin_for_project
erpnext.patches.v11_0.make_job_card
erpnext.patches.v11_0.redesign_healthcare_billing_work_flow
erpnext.patches.v10_0.delete_hub_documents # 12-08-2018
@@ -570,9 +78,6 @@ execute:frappe.delete_doc_if_exists("Page", "stock-analytics")
execute:frappe.delete_doc_if_exists("Page", "production-analytics")
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01 #2019-04-26 #2019-05-03
erpnext.patches.v11_0.drop_column_max_days_allowed
-erpnext.patches.v10_0.update_user_image_in_employee
-erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
-erpnext.patches.v10_0.allow_operators_in_supplier_scorecard
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.update_delivery_trip_status
erpnext.patches.v11_0.set_missing_gst_hsn_code
From c68006b6078028d33b3872cc9569043f1d73bfad Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Thu, 3 Jun 2021 20:05:00 +0530
Subject: [PATCH 166/262] ci: Update ERPNext backup patch test >= v10
* Generated v10 backup archive
* used old v7 erpnext backup hosted via build.erpnext.com
* upgraded to v10 frappe + erpnext
* Hosted backup on https://erpnext.com/files/v10-erpnext.sql.gz
---
.github/workflows/patch.yml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
index 7c9e0272c9..b96a3d6bbe 100644
--- a/.github/workflows/patch.yml
+++ b/.github/workflows/patch.yml
@@ -66,4 +66,8 @@ jobs:
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
- name: Run Patch Tests
- run: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
+ run: |
+ cd ~/frappe-bench/
+ wget https://erpnext.com/files/v10-erpnext.sql.gz
+ bench --site test_site --force restore ~/frappe-bench/v10-erpnext.sql.gz
+ bench --site test_site migrate
From fb3ec7ccb8ade37c0180306fef57b2e491b9310d Mon Sep 17 00:00:00 2001
From: D Tim Cummings
Date: Fri, 4 Jun 2021 16:28:45 +1000
Subject: [PATCH 167/262] fix: AttributeError: 'PurchaseReceiptItem' object has
no attribute 'purchase_invoice' (#25902)
* fix: AttributeError: 'PurchaseReceiptItem' object has no attribute 'purchase_invoice'
This error occurs when upgrading from erpnext 13.0.1 to 13.4.0 after typing
bench update --patch --reset
* fix(minor): use .get instead of getattr
---
erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index f1292d8cbd..83ba324495 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -497,7 +497,7 @@ class PurchaseReceipt(BuyingController):
def update_billing_status(self, update_modified=True):
updated_pr = [self.name]
for d in self.get("items"):
- if d.purchase_invoice and d.purchase_invoice_item:
+ if d.get("purchase_invoice") and d.get("purchase_invoice_item"):
d.db_set('billed_amt', d.amount, update_modified=update_modified)
elif d.purchase_order_item:
updated_pr += update_billed_amount_based_on_po(d.purchase_order_item, update_modified)
@@ -748,4 +748,3 @@ def get_item_account_wise_additional_cost(purchase_document):
account.base_amount * item.get(based_on_field) / total_item_cost
return item_account_wise_cost
-
From e80902be8e3009777871bd0a3a6ad22decf994fa Mon Sep 17 00:00:00 2001
From: Sagar Vora
Date: Fri, 28 May 2021 21:28:42 +0530
Subject: [PATCH 168/262] fix: choose correct Salary Structure Assignment when
getting data for formula eval
---
.../doctype/salary_slip/salary_slip.py | 22 ++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index 3c2533131b..d1a76b38b9 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -493,8 +493,28 @@ class SalarySlip(TransactionBase):
'''Returns data for evaluating formula'''
data = frappe._dict()
+ salary_structure_assignment = frappe.get_value(
+ "Salary Structure Assignment",
+ {
+ "employee": self.employee,
+ "salary_structure": self.salary_structure,
+ "from_date": ("<=", self.start_date),
+ "docstatus": 1,
+ },
+ order_by="from_date desc",
+ )
+
+ if not salary_structure_assignment:
+ frappe.throw(
+ _("Please assign a Salary Structure for Employee {0} "
+ "applicable from or before {1} first").format(
+ frappe.bold(self.employee_name),
+ frappe.bold(self.start_date)
+ )
+ )
+
data.update(frappe.get_doc("Salary Structure Assignment",
- {"employee": self.employee, "salary_structure": self.salary_structure}).as_dict())
+ salary_structure_assignment).as_dict())
data.update(frappe.get_doc("Employee", self.employee).as_dict())
data.update(self.as_dict())
From 5657fddb7ae948d0784d86f093392af84e375243 Mon Sep 17 00:00:00 2001
From: Sagar Vora
Date: Sat, 29 May 2021 00:04:26 +0530
Subject: [PATCH 169/262] fix: improve filter for `from_date`; validation for
joining and relieving date
---
.../doctype/salary_slip/salary_slip.py | 40 +++++++++++++++----
1 file changed, 33 insertions(+), 7 deletions(-)
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index d1a76b38b9..f479f6be9e 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -115,10 +115,23 @@ class SalarySlip(TransactionBase):
status = "Cancelled"
return status
- def validate_dates(self):
+ def validate_dates(self, joining_date=None, relieving_date=None):
if date_diff(self.end_date, self.start_date) < 0:
frappe.throw(_("To date cannot be before From date"))
+ if not joining_date:
+ joining_date, relieving_date = frappe.get_cached_value(
+ "Employee",
+ self.employee,
+ ("date_of_joining", "relieving_date")
+ )
+
+ if date_diff(self.end_date, joining_date) < 0:
+ frappe.throw(_("Cannot create Salary Slip for Employee joining after Payroll Period"))
+
+ if relieving_date and date_diff(relieving_date, self.start_date) < 0:
+ frappe.throw(_("Cannot create Salary Slip for Employee who has left before Payroll Period"))
+
def is_rounding_total_disabled(self):
return cint(frappe.db.get_single_value("Payroll Settings", "disable_rounded_total"))
@@ -154,9 +167,14 @@ class SalarySlip(TransactionBase):
if not self.salary_slip_based_on_timesheet:
self.get_date_details()
- self.validate_dates()
- joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
- ["date_of_joining", "relieving_date"])
+
+ joining_date, relieving_date = frappe.get_cached_value(
+ "Employee",
+ self.employee,
+ ("date_of_joining", "relieving_date")
+ )
+
+ self.validate_dates(joining_date, relieving_date)
#getin leave details
self.get_working_days_details(joining_date, relieving_date)
@@ -492,13 +510,21 @@ class SalarySlip(TransactionBase):
def get_data_for_eval(self):
'''Returns data for evaluating formula'''
data = frappe._dict()
+ employee = frappe.get_doc("Employee", self.employee).as_dict()
+
+ start_date = getdate(self.start_date)
+ date_to_validate = (
+ employee.date_of_joining
+ if employee.date_of_joining > start_date
+ else start_date
+ )
salary_structure_assignment = frappe.get_value(
"Salary Structure Assignment",
{
"employee": self.employee,
"salary_structure": self.salary_structure,
- "from_date": ("<=", self.start_date),
+ "from_date": ("<=", date_to_validate),
"docstatus": 1,
},
order_by="from_date desc",
@@ -509,14 +535,14 @@ class SalarySlip(TransactionBase):
_("Please assign a Salary Structure for Employee {0} "
"applicable from or before {1} first").format(
frappe.bold(self.employee_name),
- frappe.bold(self.start_date)
+ frappe.bold(formatdate(date_to_validate)),
)
)
data.update(frappe.get_doc("Salary Structure Assignment",
salary_structure_assignment).as_dict())
- data.update(frappe.get_doc("Employee", self.employee).as_dict())
+ data.update(employee)
data.update(self.as_dict())
# set values for components
From bd92b4339cfef78f378ec23086c8e1371db72112 Mon Sep 17 00:00:00 2001
From: Sagar Vora
Date: Fri, 4 Jun 2021 13:51:45 +0530
Subject: [PATCH 170/262] perf: use frappe.get_value with wildcard instead of
another frappe.get_doc call
---
erpnext/payroll/doctype/salary_slip/salary_slip.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/payroll/doctype/salary_slip/salary_slip.py b/erpnext/payroll/doctype/salary_slip/salary_slip.py
index f479f6be9e..c55bec89be 100644
--- a/erpnext/payroll/doctype/salary_slip/salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/salary_slip.py
@@ -527,7 +527,9 @@ class SalarySlip(TransactionBase):
"from_date": ("<=", date_to_validate),
"docstatus": 1,
},
+ "*",
order_by="from_date desc",
+ as_dict=True,
)
if not salary_structure_assignment:
@@ -539,9 +541,7 @@ class SalarySlip(TransactionBase):
)
)
- data.update(frappe.get_doc("Salary Structure Assignment",
- salary_structure_assignment).as_dict())
-
+ data.update(salary_structure_assignment)
data.update(employee)
data.update(self.as_dict())
From 0b7da52ef17f192b72b5c034b0704dd7c2b061b4 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 17:07:45 +0530
Subject: [PATCH 171/262] fix(patch): Handle NULL values from fieldtype change
---
erpnext/patches/v11_0/rename_bom_wo_fields.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/erpnext/patches/v11_0/rename_bom_wo_fields.py b/erpnext/patches/v11_0/rename_bom_wo_fields.py
index b4a740fabb..882ec84e64 100644
--- a/erpnext/patches/v11_0/rename_bom_wo_fields.py
+++ b/erpnext/patches/v11_0/rename_bom_wo_fields.py
@@ -6,6 +6,10 @@ import frappe
from frappe.model.utils.rename_field import rename_field
def execute():
+ # updating column value to handle field change from Data to Currency
+ changed_field = "base_scrap_material_cost"
+ frappe.db.sql(f"update `tabBOM` set {changed_field} = '0' where trim(coalesce({changed_field}, ''))= ''")
+
for doctype in ['BOM Explosion Item', 'BOM Item', 'Work Order Item', 'Item']:
if frappe.db.has_column(doctype, 'allow_transfer_for_manufacture'):
if doctype != 'Item':
From 4e2e8daca9bb9ece93acde85df38a69304fb43a2 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 17:56:28 +0530
Subject: [PATCH 172/262] fix(patch): Reload linked doctypes before renaming dt
---
.../v13_0/healthcare_lab_module_rename_doctypes.py | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
index 9af0a8dbef..dcfbc3834d 100644
--- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
+++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
@@ -1,6 +1,7 @@
from __future__ import unicode_literals
import frappe
from frappe.model.utils.rename_field import rename_field
+from frappe.model.rename_doc import get_link_fields
def execute():
if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'):
@@ -17,9 +18,18 @@ def execute():
frappe.reload_doc('healthcare', 'doctype', 'lab_test_template')
for old_dt, new_dt in doctypes.items():
- if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt):
+ should_rename = (
+ frappe.db.table_exists(old_dt)
+ and not frappe.db.table_exists(new_dt)
+ )
+ if should_rename:
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(old_dt))
+
+ linked_doctypes = {x.parent for x in get_link_fields(old_dt)}
+ for linked_doctype in linked_doctypes:
+ frappe.reload_doctype(linked_doctype, force=True)
frappe.rename_doc('DocType', old_dt, new_dt, force=True)
+
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt))
frappe.delete_doc_if_exists('DocType', old_dt)
From ac99c719bcb901b622f2b5ceb2ebf9df5a285616 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 20:10:26 +0530
Subject: [PATCH 173/262] Revert "fix(patch): Reload linked doctypes before
renaming dt"
This reverts commit 4e2e8daca9bb9ece93acde85df38a69304fb43a2
because although it fixed it locally, didn't seem to do anything for erpnext CI
---
.../v13_0/healthcare_lab_module_rename_doctypes.py | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
index dcfbc3834d..9af0a8dbef 100644
--- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
+++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
@@ -1,7 +1,6 @@
from __future__ import unicode_literals
import frappe
from frappe.model.utils.rename_field import rename_field
-from frappe.model.rename_doc import get_link_fields
def execute():
if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'):
@@ -18,18 +17,9 @@ def execute():
frappe.reload_doc('healthcare', 'doctype', 'lab_test_template')
for old_dt, new_dt in doctypes.items():
- should_rename = (
- frappe.db.table_exists(old_dt)
- and not frappe.db.table_exists(new_dt)
- )
- if should_rename:
+ if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt):
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(old_dt))
-
- linked_doctypes = {x.parent for x in get_link_fields(old_dt)}
- for linked_doctype in linked_doctypes:
- frappe.reload_doctype(linked_doctype, force=True)
frappe.rename_doc('DocType', old_dt, new_dt, force=True)
-
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt))
frappe.delete_doc_if_exists('DocType', old_dt)
From 102afe7de1638b83fa906ad88746c9ca2bf4e58a Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 20:11:34 +0530
Subject: [PATCH 174/262] fix: Manually link_fields from flags before
rename_doc
---
.../v13_0/healthcare_lab_module_rename_doctypes.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
index 9af0a8dbef..2549a1e91e 100644
--- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
+++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
@@ -2,6 +2,7 @@ from __future__ import unicode_literals
import frappe
from frappe.model.utils.rename_field import rename_field
+
def execute():
if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'):
# rename child doctypes
@@ -17,7 +18,12 @@ def execute():
frappe.reload_doc('healthcare', 'doctype', 'lab_test_template')
for old_dt, new_dt in doctypes.items():
- if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt):
+ frappe.flags.link_fields = {}
+ should_rename = (
+ frappe.db.table_exists(old_dt)
+ and not frappe.db.table_exists(new_dt)
+ )
+ if should_rename:
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(old_dt))
frappe.rename_doc('DocType', old_dt, new_dt, force=True)
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt))
From 8a7e283926d51626d9114eaa4f6647b920ad8c9f Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 4 Jun 2021 22:53:26 +0530
Subject: [PATCH 175/262] feat: Item Taxes based on net rate
---
erpnext/controllers/taxes_and_totals.py | 4 +-
.../public/js/controllers/taxes_and_totals.js | 90 ++++++++++++++++---
erpnext/public/js/controllers/transaction.js | 66 +-------------
erpnext/stock/doctype/item/item.py | 6 ++
erpnext/stock/doctype/item_tax/item_tax.json | 20 ++++-
erpnext/stock/get_item_details.py | 34 +++++--
6 files changed, 137 insertions(+), 83 deletions(-)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 9fae49482d..8040435634 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -54,6 +54,7 @@ class calculate_taxes_and_totals(object):
if item.item_code and item.get('item_tax_template'):
item_doc = frappe.get_cached_doc("Item", item.item_code)
args = {
+ 'net_rate': item.net_rate or item.rate,
'tax_category': self.doc.get('tax_category'),
'posting_date': self.doc.get('posting_date'),
'bill_date': self.doc.get('bill_date'),
@@ -78,7 +79,8 @@ class calculate_taxes_and_totals(object):
taxes = _get_item_tax_template(args, item_taxes + item_group_taxes, for_validate=True)
if item.item_tax_template not in taxes:
- frappe.throw(_("Row {0}: Invalid Item Tax Template for item {1}").format(
+ item.item_tax_template = taxes[0]
+ frappe.msgprint(_("Row {0}: Item Tax template updated as per validity and rate applied").format(
item.idx, frappe.bold(item.item_code)
))
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 2e133bed2e..ff4898eeff 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -12,7 +12,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) {
effective_item_rate = item.blanket_order_rate;
}
- if(item.margin_type == "Percentage"){
+ if(item.margin_type == "Percentage") {
item.rate_with_margin = flt(effective_item_rate)
+ flt(effective_item_rate) * ( flt(item.margin_rate_or_amount) / 100);
} else {
@@ -73,15 +73,18 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
},
_calculate_taxes_and_totals: function() {
- this.validate_conversion_rate();
- this.calculate_item_values();
- this.initialize_taxes();
- this.determine_exclusive_rate();
- this.calculate_net_total();
- this.calculate_taxes();
- this.manipulate_grand_total_for_inclusive_tax();
- this.calculate_totals();
- this._cleanup();
+ frappe.run_serially([
+ () => this.validate_conversion_rate(),
+ () => this.calculate_item_values(),
+ () => this.update_item_tax_map(),
+ () => this.initialize_taxes(),
+ () => this.determine_exclusive_rate(),
+ () => this.calculate_net_total(),
+ () => this.calculate_taxes(),
+ () => this.manipulate_grand_total_for_inclusive_tax(),
+ () => this.calculate_totals(),
+ () => this._cleanup()
+ ]);
},
validate_conversion_rate: function() {
@@ -263,6 +266,68 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
frappe.model.round_floats_in(this.frm.doc, ["total", "base_total", "net_total", "base_net_total"]);
},
+ update_item_tax_map: function() {
+ let me = this;
+ let item_codes = [];
+ let item_rates = {};
+ $.each(this.frm.doc.items || [], function(i, item) {
+ if(item.item_code) {
+ // Use combination of name and item code in case same item is added multiple times
+ item_codes.push([item.item_code, item.name]);
+ item_rates[item.name] = item.net_rate;
+ }
+ });
+
+ if(item_codes.length) {
+ return this.frm.call({
+ method: "erpnext.stock.get_item_details.get_item_tax_info",
+ args: {
+ company: me.frm.doc.company,
+ tax_category: cstr(me.frm.doc.tax_category),
+ item_codes: item_codes,
+ item_rates: item_rates
+ },
+ callback: function(r) {
+ if(!r.exc) {
+ $.each(me.frm.doc.items || [], function(i, item) {
+ if(item.name && r.message.hasOwnProperty(item.name)) {
+ item.item_tax_template = r.message[item.name].item_tax_template;
+ item.item_tax_rate = r.message[item.name].item_tax_rate;
+ me.add_taxes_from_item_tax_template(item.item_tax_rate);
+ }
+ else {
+ item.item_tax_template = "";
+ item.item_tax_rate = "{}";
+ }
+ });
+ }
+
+ this.frm.refresh_fields();
+ }
+ });
+ }
+ },
+
+ add_taxes_from_item_tax_template: function(item_tax_map) {
+ let me = this;
+
+ if(item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) {
+ if(typeof (item_tax_map) == "string") {
+ item_tax_map = JSON.parse(item_tax_map);
+ }
+
+ $.each(item_tax_map, function(tax, rate) {
+ let found = (me.frm.doc.taxes || []).find(d => d.account_head === tax);
+ if(!found) {
+ let child = frappe.model.add_child(me.frm.doc, "taxes");
+ child.charge_type = "On Net Total";
+ child.account_head = tax;
+ child.rate = 0;
+ }
+ });
+ }
+ },
+
calculate_taxes: function() {
var me = this;
this.frm.doc.rounding_adjustment = 0;
@@ -406,6 +471,11 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
let tax_detail = tax.item_wise_tax_detail;
let key = item.item_code || item.item_name;
+ if(typeof (tax_detail) == "string") {
+ tax.item_wise_tax_detail = JSON.parse(tax.item_wise_tax_detail);
+ tax_detail = tax.item_wise_tax_detail;
+ }
+
let item_wise_tax_amount = current_tax_amount * this.frm.doc.conversion_rate;
if (tax_detail && tax_detail[key])
item_wise_tax_amount += tax_detail[key][1];
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index ad1976d2d2..ee6696b7d1 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -6,6 +6,7 @@ frappe.provide('erpnext.accounts.dimensions');
erpnext.TransactionController = erpnext.taxes_and_totals.extend({
setup: function() {
this._super();
+ let me = this;
frappe.flags.hide_serial_batch_dialog = true;
frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) {
var item = frappe.get_doc(cdt, cdn);
@@ -43,8 +44,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
cur_frm.cscript.calculate_stock_uom_rate(frm, cdt, cdn);
});
-
-
frappe.ui.form.on(this.frm.cscript.tax_table, "rate", function(frm, cdt, cdn) {
cur_frm.cscript.calculate_taxes_and_totals();
});
@@ -121,7 +120,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
- var me = this;
if(this.frm.fields_dict["items"].grid.get_field('batch_no')) {
this.frm.set_query("batch_no", "items", function(doc, cdt, cdn) {
return me.set_query_for_batch(doc, cdt, cdn);
@@ -556,6 +554,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
name: me.frm.doc.name,
project: item.project || me.frm.doc.project,
qty: item.qty || 1,
+ net_rate: item.rate,
stock_qty: item.stock_qty,
conversion_factor: item.conversion_factor,
weight_per_unit: item.weight_per_unit,
@@ -712,26 +711,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
});
},
- add_taxes_from_item_tax_template: function(item_tax_map) {
- let me = this;
-
- if(item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) {
- if(typeof (item_tax_map) == "string") {
- item_tax_map = JSON.parse(item_tax_map);
- }
-
- $.each(item_tax_map, function(tax, rate) {
- let found = (me.frm.doc.taxes || []).find(d => d.account_head === tax);
- if(!found) {
- let child = frappe.model.add_child(me.frm.doc, "taxes");
- child.charge_type = "On Net Total";
- child.account_head = tax;
- child.rate = 0;
- }
- });
- }
- },
-
serial_no: function(doc, cdt, cdn) {
var me = this;
var item = frappe.get_doc(cdt, cdn);
@@ -835,9 +814,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
frappe.run_serially([
() => me.frm.script_manager.trigger("currency"),
- () => me.update_item_tax_map(),
() => me.apply_default_taxes(),
- () => me.apply_pricing_rule()
+ () => me.apply_pricing_rule(),
+ () => me.calculate_taxes_and_totals()
]);
}
}
@@ -1816,7 +1795,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
callback: function(r) {
if(!r.exc) {
item.item_tax_rate = r.message;
- me.add_taxes_from_item_tax_template(item.item_tax_rate);
me.calculate_taxes_and_totals();
}
}
@@ -1827,43 +1805,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
},
- update_item_tax_map: function() {
- var me = this;
- var item_codes = [];
- $.each(this.frm.doc.items || [], function(i, item) {
- if(item.item_code) {
- item_codes.push(item.item_code);
- }
- });
- if(item_codes.length) {
- return this.frm.call({
- method: "erpnext.stock.get_item_details.get_item_tax_info",
- args: {
- company: me.frm.doc.company,
- tax_category: cstr(me.frm.doc.tax_category),
- item_codes: item_codes
- },
- callback: function(r) {
- if(!r.exc) {
- $.each(me.frm.doc.items || [], function(i, item) {
- if(item.item_code && r.message.hasOwnProperty(item.item_code)) {
- if (!item.item_tax_template) {
- item.item_tax_template = r.message[item.item_code].item_tax_template;
- item.item_tax_rate = r.message[item.item_code].item_tax_rate;
- }
- me.add_taxes_from_item_tax_template(item.item_tax_rate);
- } else {
- item.item_tax_template = "";
- item.item_tax_rate = "{}";
- }
- });
- me.calculate_taxes_and_totals();
- }
- }
- });
- }
- },
is_recurring: function() {
// set default values for recurring documents
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index dbac79465e..60f468e82e 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -128,6 +128,7 @@ class Item(WebsiteGenerator):
self.validate_auto_reorder_enabled_in_stock_settings()
self.cant_change()
self.update_show_in_website()
+ self.validate_item_tax_net_rate_range()
if not self.get("__islocal"):
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
@@ -490,6 +491,11 @@ class Item(WebsiteGenerator):
if self.disabled:
self.show_in_website = False
+ def validate_item_tax_net_rate_range(self):
+ for tax in self.get('taxes'):
+ if tax.maximum_net_rate < tax.minimum_net_rate:
+ frappe.throw(_("Row #{0}: Maximum Net Rate cannot be greater than Minimum Net Rate"))
+
def update_template_tables(self):
template = frappe.get_doc("Item", self.variant_of)
diff --git a/erpnext/stock/doctype/item_tax/item_tax.json b/erpnext/stock/doctype/item_tax/item_tax.json
index ae36efc7e3..fb100967f3 100644
--- a/erpnext/stock/doctype/item_tax/item_tax.json
+++ b/erpnext/stock/doctype/item_tax/item_tax.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"creation": "2013-02-22 01:28:01",
"doctype": "DocType",
"editable_grid": 1,
@@ -6,7 +7,9 @@
"field_order": [
"item_tax_template",
"tax_category",
- "valid_from"
+ "valid_from",
+ "minimum_net_rate",
+ "maximum_net_rate"
],
"fields": [
{
@@ -33,11 +36,24 @@
"fieldtype": "Date",
"in_list_view": 1,
"label": "Valid From"
+ },
+ {
+ "fieldname": "maximum_net_rate",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Maximum Net Rate"
+ },
+ {
+ "fieldname": "minimum_net_rate",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Minimum Net Rate"
}
],
"idx": 1,
"istable": 1,
- "modified": "2020-06-25 01:40:28.859752",
+ "links": [],
+ "modified": "2021-06-03 13:20:06.982303",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Tax",
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index d1dcdc21c8..6f510539a4 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -436,18 +436,22 @@ def get_barcode_data(items_list):
return itemwise_barcode
@frappe.whitelist()
-def get_item_tax_info(company, tax_category, item_codes):
+def get_item_tax_info(company, tax_category, item_codes, item_rates=None):
out = {}
if isinstance(item_codes, string_types):
item_codes = json.loads(item_codes)
+ if isinstance(item_rates, string_types):
+ item_rates = json.loads(item_rates)
+
for item_code in item_codes:
- if not item_code or item_code in out:
+ if not item_code or item_code[1] in out:
continue
- out[item_code] = {}
- item = frappe.get_cached_doc("Item", item_code)
- get_item_tax_template({"company": company, "tax_category": tax_category}, item, out[item_code])
- out[item_code]["item_tax_rate"] = get_item_tax_map(company, out[item_code].get("item_tax_template"), as_json=True)
+ out[item_code[1]] = {}
+ item = frappe.get_cached_doc("Item", item_code[0])
+ args = {"company": company, "tax_category": tax_category, "net_rate": item_rates[item_code[1]]}
+ get_item_tax_template(args, item, out[item_code[1]])
+ out[item_code[1]]["item_tax_rate"] = get_item_tax_map(company, out[item_code[1]].get("item_tax_template"), as_json=True)
return out
@@ -478,12 +482,13 @@ def _get_item_tax_template(args, taxes, out=None, for_validate=False):
for tax in taxes:
tax_company = frappe.get_value("Item Tax Template", tax.item_tax_template, 'company')
- if tax.valid_from and tax_company == args['company']:
+ if (tax.valid_from or tax.maximum_net_rate) and tax_company == args['company']:
# In purchase Invoice first preference will be given to supplier invoice date
# if supplier date is not present then posting date
validation_date = args.get('transaction_date') or args.get('bill_date') or args.get('posting_date')
- if getdate(tax.valid_from) <= getdate(validation_date):
+ if getdate(tax.valid_from) <= getdate(validation_date) \
+ and is_within_valid_range(args, tax):
taxes_with_validity.append(tax)
else:
if tax_company == args['company']:
@@ -502,12 +507,25 @@ def _get_item_tax_template(args, taxes, out=None, for_validate=False):
if not taxes_with_validity and (not taxes_with_no_validity):
return None
+ # do not change if already a valid template
+ if args.get('item_tax_template') in taxes:
+ return arg.get('item_tax_template')
+
for tax in taxes:
if cstr(tax.tax_category) == cstr(args.get("tax_category")):
out["item_tax_template"] = tax.item_tax_template
return tax.item_tax_template
return None
+def is_within_valid_range(args, tax):
+ if not flt(tax.maximum_net_rate):
+ # No range specified, just ignore
+ return True
+ elif flt(tax.minimum_net_rate) <= flt(args.get('net_rate')) <= flt(tax.maximum_net_rate):
+ return True
+
+ return False
+
@frappe.whitelist()
def get_item_tax_map(company, item_tax_template, as_json=True):
item_tax_map = {}
From e8a78bd43d027ea36ff2902ecf48835b76109038 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sat, 5 Jun 2021 13:16:39 +0530
Subject: [PATCH 176/262] fix: Add test cases
---
.../sales_invoice/test_sales_invoice.py | 69 +++++++++++++------
erpnext/stock/doctype/item/item.py | 2 +-
2 files changed, 49 insertions(+), 22 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index df6d483904..1b1bb3b18f 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -1963,6 +1963,54 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(value_details['TotInvVal'], si.base_grand_total)
self.assertTrue(einvoice['EwbDtls'])
+ def test_item_tax_validity(self):
+ item = frappe.get_doc("Item", "_Test Item 2")
+
+ if item.taxes:
+ item.taxes = []
+ item.save()
+
+ item.append("taxes", {
+ "item_tax_template": "_Test Item Tax Template 1 - _TC",
+ "valid_from": add_days(nowdate(), 1)
+ })
+
+ item.save()
+
+ sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1)
+ sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1 - _TC"
+ self.assertRaises(frappe.ValidationError, sales_invoice.save)
+
+ item.taxes = []
+ item.save()
+
+ def test_item_tax_net_range(self):
+ item = create_item("T Shirt")
+
+ item.set('taxes', [])
+ item.append("taxes", {
+ "item_tax_template": "_Test Account Excise Duty @ 10 - _TC",
+ "minimum_net_rate": 0,
+ "maximum_net_rate": 500
+ })
+
+ item.append("taxes", {
+ "item_tax_template": "_Test Account Excise Duty @ 12 - _TC",
+ "minimum_net_rate": 501,
+ "maximum_net_rate": 1000
+ })
+
+ item.save()
+
+ sales_invoice = create_sales_invoice(item = "T Shirt", rate=700, do_not_submit=True)
+ self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 12 - _TC")
+
+ # Apply discount
+ sales_invoice.apply_discount_on = 'Net Total'
+ sales_invoice.discount_amount = 300
+ sales_invoice.save()
+ self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC")
+
def make_test_address_for_ewaybill():
if not frappe.db.exists('Address', '_Test Address for Eway bill-Billing'):
address = frappe.get_doc({
@@ -2085,27 +2133,6 @@ def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
doc.assertEqual(expected_gle[i][2], gle.credit)
doc.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
- def test_item_tax_validity(self):
- item = frappe.get_doc("Item", "_Test Item 2")
-
- if item.taxes:
- item.taxes = []
- item.save()
-
- item.append("taxes", {
- "item_tax_template": "_Test Item Tax Template 1 - _TC",
- "valid_from": add_days(nowdate(), 1)
- })
-
- item.save()
-
- sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1)
- sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1 - _TC"
- self.assertRaises(frappe.ValidationError, sales_invoice.save)
-
- item.taxes = []
- item.save()
-
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")
args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index 60f468e82e..0420ea7c54 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -493,7 +493,7 @@ class Item(WebsiteGenerator):
def validate_item_tax_net_rate_range(self):
for tax in self.get('taxes'):
- if tax.maximum_net_rate < tax.minimum_net_rate:
+ if flt(tax.maximum_net_rate) < flt(tax.minimum_net_rate):
frappe.throw(_("Row #{0}: Maximum Net Rate cannot be greater than Minimum Net Rate"))
def update_template_tables(self):
From 3646c301edc1380efcd0eedcd590e8124dfe90d8 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sat, 5 Jun 2021 13:21:03 +0530
Subject: [PATCH 177/262] fix: Linting issues
---
.../public/js/controllers/taxes_and_totals.js | 25 +++++++++----------
erpnext/stock/get_item_details.py | 2 +-
2 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index ff4898eeff..0b9d771119 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -12,7 +12,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
if (in_list(["Sales Order", "Quotation"], item.parenttype) && item.blanket_order_rate) {
effective_item_rate = item.blanket_order_rate;
}
- if(item.margin_type == "Percentage") {
+ if (item.margin_type == "Percentage") {
item.rate_with_margin = flt(effective_item_rate)
+ flt(effective_item_rate) * ( flt(item.margin_rate_or_amount) / 100);
} else {
@@ -22,7 +22,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
item_rate = flt(item.rate_with_margin , precision("rate", item));
- if(item.discount_percentage){
+ if (item.discount_percentage) {
item.discount_amount = flt(item.rate_with_margin) * flt(item.discount_percentage) / 100;
}
@@ -271,14 +271,14 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
let item_codes = [];
let item_rates = {};
$.each(this.frm.doc.items || [], function(i, item) {
- if(item.item_code) {
+ if (item.item_code) {
// Use combination of name and item code in case same item is added multiple times
item_codes.push([item.item_code, item.name]);
item_rates[item.name] = item.net_rate;
}
});
- if(item_codes.length) {
+ if (item_codes.length) {
return this.frm.call({
method: "erpnext.stock.get_item_details.get_item_tax_info",
args: {
@@ -288,21 +288,18 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
item_rates: item_rates
},
callback: function(r) {
- if(!r.exc) {
+ if (!r.exc) {
$.each(me.frm.doc.items || [], function(i, item) {
- if(item.name && r.message.hasOwnProperty(item.name)) {
+ if (item.name && r.message.hasOwnProperty(item.name)) {
item.item_tax_template = r.message[item.name].item_tax_template;
item.item_tax_rate = r.message[item.name].item_tax_rate;
me.add_taxes_from_item_tax_template(item.item_tax_rate);
- }
- else {
+ } else {
item.item_tax_template = "";
item.item_tax_rate = "{}";
}
});
}
-
- this.frm.refresh_fields();
}
});
}
@@ -311,14 +308,14 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
add_taxes_from_item_tax_template: function(item_tax_map) {
let me = this;
- if(item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) {
- if(typeof (item_tax_map) == "string") {
+ if (item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) {
+ if (typeof (item_tax_map) == "string") {
item_tax_map = JSON.parse(item_tax_map);
}
$.each(item_tax_map, function(tax, rate) {
let found = (me.frm.doc.taxes || []).find(d => d.account_head === tax);
- if(!found) {
+ if (!found) {
let child = frappe.model.add_child(me.frm.doc, "taxes");
child.charge_type = "On Net Total";
child.account_head = tax;
@@ -632,6 +629,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
tax.item_wise_tax_detail = JSON.stringify(tax.item_wise_tax_detail);
});
}
+
+ this.frm.refresh_fields();
},
set_discount_amount: function() {
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 6f510539a4..746cbbf601 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -509,7 +509,7 @@ def _get_item_tax_template(args, taxes, out=None, for_validate=False):
# do not change if already a valid template
if args.get('item_tax_template') in taxes:
- return arg.get('item_tax_template')
+ return args.get('item_tax_template')
for tax in taxes:
if cstr(tax.tax_category) == cstr(args.get("tax_category")):
From bf0528413d7336b6e55aad70f0cfed12ee0db9fa Mon Sep 17 00:00:00 2001
From: Anupam
Date: Sun, 6 Jun 2021 13:12:13 +0530
Subject: [PATCH 178/262] fix: payroll entry employee detail issue
---
erpnext/payroll/doctype/payroll_entry/payroll_entry.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 3953b463f1..67893448ba 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -673,7 +673,7 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters):
include_employees = []
emp_cond = ''
if filters.start_date and filters.end_date:
- employee_list = get_employee_list(filters)
+ employee_list = get_employee_list(filters) or []
emp = filters.get('employees')
include_employees = [employee.employee for employee in employee_list if employee.employee not in emp]
filters.pop('start_date')
From 18be767f75b9c858fa66294d037f1a9b9d2c6ace Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 6 Jun 2021 13:25:34 +0530
Subject: [PATCH 179/262] fix: Remove invalid test
---
.../sales_invoice/test_sales_invoice.py | 21 -------------------
erpnext/controllers/taxes_and_totals.py | 11 +++++-----
2 files changed, 6 insertions(+), 26 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 1b1bb3b18f..0d61f67e52 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -1963,27 +1963,6 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(value_details['TotInvVal'], si.base_grand_total)
self.assertTrue(einvoice['EwbDtls'])
- def test_item_tax_validity(self):
- item = frappe.get_doc("Item", "_Test Item 2")
-
- if item.taxes:
- item.taxes = []
- item.save()
-
- item.append("taxes", {
- "item_tax_template": "_Test Item Tax Template 1 - _TC",
- "valid_from": add_days(nowdate(), 1)
- })
-
- item.save()
-
- sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1)
- sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1 - _TC"
- self.assertRaises(frappe.ValidationError, sales_invoice.save)
-
- item.taxes = []
- item.save()
-
def test_item_tax_net_range(self):
item = create_item("T Shirt")
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 8040435634..fb22a1d608 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -78,11 +78,12 @@ class calculate_taxes_and_totals(object):
taxes = _get_item_tax_template(args, item_taxes + item_group_taxes, for_validate=True)
- if item.item_tax_template not in taxes:
- item.item_tax_template = taxes[0]
- frappe.msgprint(_("Row {0}: Item Tax template updated as per validity and rate applied").format(
- item.idx, frappe.bold(item.item_code)
- ))
+ if taxes:
+ if item.item_tax_template not in taxes:
+ item.item_tax_template = taxes[0]
+ frappe.msgprint(_("Row {0}: Item Tax template updated as per validity and rate applied").format(
+ item.idx, frappe.bold(item.item_code)
+ ))
def validate_conversion_rate(self):
# validate conversion rate
From 7a20c3b92ae05395bf75703a1e6aaad31f537a79 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Sun, 6 Jun 2021 19:23:21 +0530
Subject: [PATCH 180/262] fix: Ignore internal transfer inoices from GST
Reports
---
erpnext/regional/report/gstr_1/gstr_1.py | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/erpnext/regional/report/gstr_1/gstr_1.py b/erpnext/regional/report/gstr_1/gstr_1.py
index b7c096248f..80e2d725a2 100644
--- a/erpnext/regional/report/gstr_1/gstr_1.py
+++ b/erpnext/regional/report/gstr_1/gstr_1.py
@@ -147,6 +147,13 @@ class Gstr1Report(object):
def get_invoice_data(self):
self.invoices = frappe._dict()
conditions = self.get_conditions()
+
+ company_gstins = get_company_gstin_number(self.filters.get('company'), all_gstins=True)
+
+ self.filters.update({
+ 'company_gstins': company_gstins
+ })
+
invoice_data = frappe.db.sql("""
select
{select_columns}
@@ -193,6 +200,9 @@ class Gstr1Report(object):
elif self.filters.get("type_of_business") == "EXPORT":
conditions += """ AND is_return !=1 and gst_category = 'Overseas' """
+
+ conditions += " AND billing_address_gstin NOT IN %(company_gstins)s"
+
return conditions
def get_invoice_items(self):
@@ -810,7 +820,8 @@ def get_rate_and_tax_details(row, gstin):
return {"num": int(num), "itm_det": itm_det}
-def get_company_gstin_number(company, address=None):
+def get_company_gstin_number(company, address=None, all_gstins=False):
+ gstin = ''
if address:
gstin = frappe.db.get_value("Address", address, "gstin")
@@ -822,9 +833,9 @@ def get_company_gstin_number(company, address=None):
["Dynamic Link", "parenttype", "=", "Address"],
]
gstin = frappe.get_all("Address", filters=filters, pluck="gstin")
- if gstin:
- gstin[0]
-
+ if gstin and not all_gstins:
+ gstin = gstin[0]
+
if not gstin:
address = frappe.bold(address) if address else ""
frappe.throw(_("Please set valid GSTIN No. in Company Address {} for company {}").format(
From 7f5378d98ac3bee8175d972fda5cc6e958fe23e2 Mon Sep 17 00:00:00 2001
From: Sagar Vora
Date: Mon, 7 Jun 2021 18:40:54 +0530
Subject: [PATCH 181/262] fix: tests
---
.../doctype/salary_slip/test_salary_slip.py | 51 +++++++++++--------
.../salary_structure/test_salary_structure.py | 39 +++++++++-----
2 files changed, 57 insertions(+), 33 deletions(-)
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index 01e4170d31..9e7db977ab 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -8,7 +8,6 @@ import erpnext
import calendar
import random
from erpnext.accounts.utils import get_fiscal_year
-from frappe.utils.make_random import get_random
from frappe.utils import getdate, nowdate, add_days, add_months, flt, get_first_day, get_last_day, cstr
from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip
from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details
@@ -155,12 +154,14 @@ class TestSalarySlip(unittest.TestCase):
self.assertEqual(ss.gross_pay, 78000)
def test_payment_days(self):
+ from erpnext.payroll.doctype.salary_structure.test_salary_structure import create_salary_structure_assignment
+
no_of_days = self.get_no_of_days()
# Holidays not included in working days
frappe.db.set_value("Payroll Settings", None, "include_holidays_in_total_working_days", 1)
# set joinng date in the same month
- make_employee("test_payment_days@salary.com")
+ employee = make_employee("test_payment_days@salary.com")
if getdate(nowdate()).day >= 15:
relieving_date = getdate(add_days(nowdate(),-10))
date_of_joining = getdate(add_days(nowdate(),-10))
@@ -174,25 +175,30 @@ class TestSalarySlip(unittest.TestCase):
date_of_joining = getdate(nowdate())
relieving_date = getdate(nowdate())
- frappe.db.set_value("Employee", frappe.get_value("Employee",
- {"employee_name":"test_payment_days@salary.com"}, "name"), "date_of_joining", date_of_joining)
- frappe.db.set_value("Employee", frappe.get_value("Employee",
- {"employee_name":"test_payment_days@salary.com"}, "name"), "relieving_date", None)
- frappe.db.set_value("Employee", frappe.get_value("Employee",
- {"employee_name":"test_payment_days@salary.com"}, "name"), "status", "Active")
+ frappe.db.set_value("Employee", employee, {
+ "date_of_joining": date_of_joining,
+ "relieving_date": None,
+ "status": "Active"
+ })
- ss = make_employee_salary_slip("test_payment_days@salary.com", "Monthly", "Test Payment Days")
+ salary_structure = "Test Payment Days"
+ ss = make_employee_salary_slip("test_payment_days@salary.com", "Monthly", salary_structure)
self.assertEqual(ss.total_working_days, no_of_days[0])
self.assertEqual(ss.payment_days, (no_of_days[0] - getdate(date_of_joining).day + 1))
# set relieving date in the same month
- frappe.db.set_value("Employee",frappe.get_value("Employee",
- {"employee_name":"test_payment_days@salary.com"}, "name"), "date_of_joining", (add_days(nowdate(),-60)))
- frappe.db.set_value("Employee", frappe.get_value("Employee",
- {"employee_name":"test_payment_days@salary.com"}, "name"), "relieving_date", relieving_date)
- frappe.db.set_value("Employee", frappe.get_value("Employee",
- {"employee_name":"test_payment_days@salary.com"}, "name"), "status", "Left")
+ frappe.db.set_value("Employee", employee, {
+ "date_of_joining": add_days(nowdate(),-60),
+ "relieving_date": relieving_date,
+ "status": "Left"
+ })
+
+ if date_of_joining.day > 1:
+ self.assertRaises(frappe.ValidationError, ss.save)
+
+ create_salary_structure_assignment(employee, salary_structure)
+ ss.reload()
ss.save()
self.assertEqual(ss.total_working_days, no_of_days[0])
@@ -285,6 +291,7 @@ class TestSalarySlip(unittest.TestCase):
def test_multi_currency_salary_slip(self):
from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
+
applicant = make_employee("test_multi_currency_salary_slip@salary.com", company="_Test Company")
frappe.db.sql("""delete from `tabSalary Structure` where name='Test Multi Currency Salary Slip'""")
salary_structure = make_salary_structure("Test Multi Currency Salary Slip", "Monthly", employee=applicant, company="_Test Company", currency='USD')
@@ -325,7 +332,8 @@ class TestSalarySlip(unittest.TestCase):
def test_component_wise_year_to_date_computation(self):
from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
- applicant = make_employee("test_ytd@salary.com", company="_Test Company")
+ employee_name = "test_component_wise_ytd@salary.com"
+ applicant = make_employee(employee_name, company="_Test Company")
payroll_period = create_payroll_period(name="_Test Payroll Period 1", company="_Test Company")
@@ -336,13 +344,13 @@ class TestSalarySlip(unittest.TestCase):
"Monthly", employee=applicant, company="_Test Company", currency="INR", payroll_period=payroll_period)
# clear salary slip for this employee
- frappe.db.sql("DELETE FROM `tabSalary Slip` where employee_name = 'test_ytd@salary.com'")
+ frappe.db.sql("DELETE FROM `tabSalary Slip` where employee_name = '%s'" % employee_name)
create_salary_slips_for_payroll_period(applicant, salary_structure.name,
payroll_period, deduct_random=False, num=3)
salary_slips = frappe.get_all("Salary Slip", fields=["name"], filters={"employee_name":
- "test_ytd@salary.com"}, order_by = "posting_date")
+ employee_name}, order_by="posting_date")
year_to_date = dict()
for slip in salary_slips:
@@ -380,10 +388,10 @@ class TestSalarySlip(unittest.TestCase):
from erpnext.payroll.doctype.salary_structure.test_salary_structure import \
make_salary_structure, create_salary_structure_assignment
+
salary_structure = make_salary_structure("Stucture to test tax", "Monthly",
- other_details={"max_benefits": 100000}, test_tax=True)
- create_salary_structure_assignment(employee, salary_structure.name,
- payroll_period.start_date)
+ other_details={"max_benefits": 100000}, test_tax=True,
+ employee=employee, payroll_period=payroll_period)
# create salary slip for whole period deducting tax only on last period
# to find the total tax amount paid
@@ -469,6 +477,7 @@ class TestSalarySlip(unittest.TestCase):
def make_employee_salary_slip(user, payroll_frequency, salary_structure=None):
from erpnext.payroll.doctype.salary_structure.test_salary_structure import make_salary_structure
+
if not salary_structure:
salary_structure = payroll_frequency + " Salary Structure Test for Salary Slip"
diff --git a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
index 36387f23df..26cd9922e4 100644
--- a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
+++ b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
@@ -6,7 +6,7 @@ import frappe
import unittest
import erpnext
from frappe.utils.make_random import get_random
-from frappe.utils import nowdate, add_days, add_years, getdate, add_months
+from frappe.utils import nowdate, add_days, add_years, getdate, add_months, get_first_day, date_diff
from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip
from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_earning_salary_component,\
make_deduction_salary_component, make_employee_salary_slip, create_tax_slab
@@ -113,8 +113,9 @@ class TestSalaryStructure(unittest.TestCase):
sal_struct = make_salary_structure("Salary Structure Multi Currency", "Monthly", currency='USD')
self.assertEqual(sal_struct.currency, 'USD')
-def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None,
- test_tax=False, company=None, currency=erpnext.get_default_currency(), payroll_period=None):
+def make_salary_structure(salary_structure, payroll_frequency, employee=None,
+ from_date=None, dont_submit=False, other_details=None,test_tax=False,
+ company=None, currency=erpnext.get_default_currency(), payroll_period=None):
if test_tax:
frappe.db.sql("""delete from `tabSalary Structure` where name=%s""",(salary_structure))
@@ -139,10 +140,23 @@ def make_salary_structure(salary_structure, payroll_frequency, employee=None, do
else:
salary_structure_doc = frappe.get_doc("Salary Structure", salary_structure)
+ filters = {'employee':employee, 'docstatus': 1}
+ if not from_date and payroll_period:
+ from_date = payroll_period.start_date
+
+ if from_date:
+ filters['from_date'] = from_date
+
if employee and not frappe.db.get_value("Salary Structure Assignment",
- {'employee':employee, 'docstatus': 1}) and salary_structure_doc.docstatus==1:
- create_salary_structure_assignment(employee, salary_structure, company=company, currency=currency,
- payroll_period=payroll_period)
+ filters) and salary_structure_doc.docstatus==1:
+ create_salary_structure_assignment(
+ employee,
+ salary_structure,
+ from_date=from_date,
+ company=company,
+ currency=currency,
+ payroll_period=payroll_period
+ )
return salary_structure_doc
@@ -165,12 +179,13 @@ def create_salary_structure_assignment(employee, salary_structure, from_date=Non
salary_structure_assignment.base = 50000
salary_structure_assignment.variable = 5000
- if getdate(nowdate()).day == 1:
- date = from_date or nowdate()
- else:
- date = from_date or add_days(nowdate(), -1)
+ if not from_date:
+ from_date = get_first_day(nowdate())
+ joining_date = frappe.get_cached_value("Employee", employee, "date_of_joining")
+ if date_diff(joining_date, from_date) > 0:
+ from_date = joining_date
- salary_structure_assignment.from_date = date
+ salary_structure_assignment.from_date = from_date
salary_structure_assignment.salary_structure = salary_structure
salary_structure_assignment.currency = currency
salary_structure_assignment.payroll_payable_account = get_payable_account(company)
@@ -183,4 +198,4 @@ def create_salary_structure_assignment(employee, salary_structure, from_date=Non
def get_payable_account(company=None):
if not company:
company = erpnext.get_default_company()
- return frappe.db.get_value("Company", company, "default_payroll_payable_account")
\ No newline at end of file
+ return frappe.db.get_value("Company", company, "default_payroll_payable_account")
From 5b1e7a61b88e354038db2a2dd74edba55d5d92a0 Mon Sep 17 00:00:00 2001
From: Sagar Vora
Date: Mon, 7 Jun 2021 19:34:02 +0530
Subject: [PATCH 182/262] test: remove unused imports
---
.../payroll/doctype/salary_structure/test_salary_structure.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
index 26cd9922e4..dce6b7aa3d 100644
--- a/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
+++ b/erpnext/payroll/doctype/salary_structure/test_salary_structure.py
@@ -6,7 +6,7 @@ import frappe
import unittest
import erpnext
from frappe.utils.make_random import get_random
-from frappe.utils import nowdate, add_days, add_years, getdate, add_months, get_first_day, date_diff
+from frappe.utils import nowdate, add_years, get_first_day, date_diff
from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip
from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_earning_salary_component,\
make_deduction_salary_component, make_employee_salary_slip, create_tax_slab
From e4fcc5562f3e4a26177eacc9d455596da1135aa8 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 8 Jun 2021 16:35:47 +0530
Subject: [PATCH 183/262] refactor: Advance taxes and charges calculation
---
.../advance_taxes_and_charges.json | 11 +-
.../doctype/payment_entry/payment_entry.js | 162 +++++++++++++----
.../doctype/payment_entry/payment_entry.py | 163 +++++++++++++-----
3 files changed, 255 insertions(+), 81 deletions(-)
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
index c127601259..3e4e679c91 100644
--- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
@@ -19,6 +19,7 @@
"section_break_8",
"rate",
"section_break_9",
+ "currency",
"tax_amount",
"total",
"allocated_amount",
@@ -172,12 +173,20 @@
"fieldtype": "Currency",
"label": "Allocated Amount (Company Currency)",
"options": "Company:company:default_currency"
+ },
+ {
+ "fetch_from": "account_head.account_currency",
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "label": "Account Currency",
+ "options": "Currency",
+ "read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-05-31 02:03:57.444647",
+ "modified": "2021-06-08 07:04:44.287002",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index b1cf9e02e6..6a3b717b12 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -1071,7 +1071,7 @@ frappe.ui.form.on('Payment Entry', {
}
me.frm.add_child("taxes", tax);
}
- frm.trigger('calculate_taxes');
+ frm.events.apply_taxes(frm);
frm.events.set_unallocated_amount(frm);
}
}
@@ -1079,52 +1079,112 @@ frappe.ui.form.on('Payment Entry', {
});
},
+ apply_taxes: function(frm) {
+ frm.events.initialize_taxes(frm);
+ frm.events.determine_exclusive_rate(frm);
+ frm.events.calculate_taxes(frm);
+ },
+
+ initialize_taxes: function(frm) {
+ $.each(frm.doc["taxes"] || [], function(i, tax) {
+ tax.item_wise_tax_detail = {};
+ let tax_fields = ["total", "tax_fraction_for_current_item",
+ "grand_total_fraction_for_current_item"];
+
+ if (cstr(tax.charge_type) != "Actual") {
+ tax_fields.push("tax_amount");
+ }
+
+ $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0; });
+
+ frm.doc.paid_amount_after_tax = frm.doc.paid_amount;
+ });
+ },
+
+ determine_exclusive_rate: function(frm) {
+ let has_inclusive_tax = false;
+ $.each(frm.doc["taxes"] || [], function(i, row) {
+ if(cint(row.included_in_paid_amount)) has_inclusive_tax = true;
+ });
+ if(has_inclusive_tax==false) return;
+
+ let cumulated_tax_fraction = 0.0;
+ $.each(frm.doc["taxes"] || [], function(i, tax) {
+ let current_tax_fraction = frm.events.get_current_tax_fraction(frm, tax);
+ tax.tax_fraction_for_current_item = current_tax_fraction[0];
+
+ if(i==0) {
+ tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
+ } else {
+ tax.grand_total_fraction_for_current_item =
+ me.frm.doc["taxes"][i-1].grand_total_fraction_for_current_item +
+ tax.tax_fraction_for_current_item;
+ }
+
+ cumulated_tax_fraction += tax.tax_fraction_for_current_item;
+ frm.doc.paid_amount_after_tax = flt(frm.doc.paid_amount/(1+cumulated_tax_fraction))
+ });
+ },
+
+ get_current_tax_fraction: function(frm, tax) {
+ let current_tax_fraction = 0.0;
+
+ if(cint(tax.included_in_paid_amount)) {
+ let tax_rate = tax.rate;
+
+ if (tax.charge_type == "Actual") {
+ current_tax_fraction = tax.tax_amount/frm.doc.paid_amount_after_tax;
+ } else if(tax.charge_type == "On Paid Amount") {
+ current_tax_fraction = (tax_rate / 100.0);
+ } else if(tax.charge_type == "On Previous Row Amount") {
+ current_tax_fraction = (tax_rate / 100.0) *
+ frm.doc["taxes"][cint(tax.row_id) - 1].tax_fraction_for_current_item;
+ } else if(tax.charge_type == "On Previous Row Total") {
+ current_tax_fraction = (tax_rate / 100.0) *
+ frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item;
+ }
+ }
+
+ if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") {
+ current_tax_fraction *= -1;
+ inclusive_tax_amount_per_qty *= -1;
+ }
+ return current_tax_fraction;
+ },
+
+
calculate_taxes: function(frm) {
frm.doc.total_taxes_and_charges = 0.0;
frm.doc.base_total_taxes_and_charges = 0.0;
- $.each(me.frm.doc["taxes"] || [], function(i, tax) {
- let tax_rate = tax.rate;
- let current_tax_amount = 0.0;
+ let actual_tax_dict = {};
- // To set row_id by default as previous row.
- if(["On Previous Row Amount", "On Previous Row Total"].includes(tax.charge_type)) {
- if (tax.idx === 1) {
- frappe.throw(__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"));
- }
- if (!tax.row_id) {
- tax.row_id = tax.idx - 1;
- }
+ // maintain actual tax rate based on idx
+ $.each(frm.doc["taxes"] || [], function(i, tax) {
+ if (tax.charge_type == "Actual") {
+ actual_tax_dict[tax.idx] = flt(tax.tax_amount, precision("tax_amount", tax));
}
+ });
- if(tax.charge_type == "Actual") {
- current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
- } else if(tax.charge_type == "On Paid Amount") {
- current_tax_amount = (tax_rate / 100.0) * frm.doc.paid_amount;
- } else if(tax.charge_type == "On Previous Row Amount") {
- current_tax_amount = (tax_rate / 100.0) *
- frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount;
+ $.each(me.frm.doc["taxes"] || [], function(i, tax) {
+ let current_tax_amount = frm.events.get_current_tax_amount(frm, tax);
- } else if(tax.charge_type == "On Previous Row Total") {
- current_tax_amount = (tax_rate / 100.0) *
- frm.doc["taxes"][cint(tax.row_id) - 1].total;
+ // Adjust divisional loss to the last item
+ if (tax.charge_type == "Actual") {
+ actual_tax_dict[tax.idx] -= current_tax_amount;
+ if (i == frm.doc["taxes"].length - 1) {
+ current_tax_amount += actual_tax_dict[tax.idx];
+ }
}
tax.tax_amount = current_tax_amount;
tax.base_tax_amount = tax.tax_amount * frm.doc.source_exchange_rate;
-
current_tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0;
- let applicable_tax_amount = 0
-
- if (!tax.included_in_paid_amount) {
- applicable_tax_amount = current_tax_amount
- }
-
if(i==0) {
- tax.total = flt(frm.doc.paid_amount + applicable_tax_amount, precision("total", tax));
+ tax.total = flt(frm.doc.paid_amount_after_tax + current_tax_amount, precision("total", tax));
} else {
- tax.total = flt(frm.doc["taxes"][i-1].total + applicable_tax_amount, precision("total", tax));
+ tax.total = flt(frm.doc["taxes"][i-1].total + current_tax_amount, precision("total", tax));
}
tax.base_total = tax.total * frm.doc.source_exchange_rate;
@@ -1136,6 +1196,36 @@ frappe.ui.form.on('Payment Entry', {
frm.refresh_field('base_total_taxes_and_charges');
});
},
+
+ get_current_tax_amount: function(frm, tax) {
+ let tax_rate = tax.rate;
+ let current_tax_amount = 0.0;
+
+ // To set row_id by default as previous row.
+ if(["On Previous Row Amount", "On Previous Row Total"].includes(tax.charge_type)) {
+ if (tax.idx === 1) {
+ frappe.throw(
+ __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"));
+ }
+ if (!tax.row_id) {
+ tax.row_id = tax.idx - 1;
+ }
+ }
+ if(tax.charge_type == "Actual") {
+ current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax))
+ } else if(tax.charge_type == "On Paid Amount") {
+ current_tax_amount = flt((tax_rate / 100.0) * frm.doc.paid_amount_after_tax);
+ } else if(tax.charge_type == "On Previous Row Amount") {
+ current_tax_amount = flt((tax_rate / 100.0) *
+ frm.doc["taxes"][cint(tax.row_id) - 1].tax_amount);
+
+ } else if(tax.charge_type == "On Previous Row Total") {
+ current_tax_amount = flt((tax_rate / 100.0) *
+ frm.doc["taxes"][cint(tax.row_id) - 1].total);
+ }
+
+ return current_tax_amount;
+ },
});
@@ -1184,27 +1274,27 @@ frappe.ui.form.on('Payment Entry Reference', {
frappe.ui.form.on('Advance Taxes and Charges', {
rate: function(frm) {
- frm.events.calculate_taxes(frm);
+ frm.events.apply_taxes(frm);
frm.events.set_unallocated_amount(frm);
},
tax_amount : function(frm) {
- frm.events.calculate_taxes(frm);
+ frm.events.apply_taxes(frm);
frm.events.set_unallocated_amount(frm);
},
row_id: function(frm) {
- frm.events.calculate_taxes(frm);
+ frm.events.apply_taxes(frm);
frm.events.set_unallocated_amount(frm);
},
taxes_remove: function(frm) {
- frm.events.calculate_taxes(frm);
+ frm.events.apply_taxes(frm);
frm.events.set_unallocated_amount(frm);
},
included_in_paid_amount: function(frm) {
- frm.events.calculate_taxes(frm);
+ frm.events.apply_taxes(frm);
frm.events.set_unallocated_amount(frm);
}
})
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index d960156670..83d52fa5f6 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -54,7 +54,7 @@ class PaymentEntry(AccountsController):
self.validate_mandatory()
self.validate_reference_documents()
self.set_tax_withholding()
- self.calculate_taxes()
+ self.apply_taxes()
self.set_amounts()
self.clear_unallocated_reference_document_rows()
self.validate_payment_against_negative_invoice()
@@ -65,7 +65,6 @@ class PaymentEntry(AccountsController):
self.validate_allocated_amount()
self.validate_paid_invoices()
self.ensure_supplier_is_not_blocked()
- self.set_advance_tax_account()
self.set_status()
def on_submit(self):
@@ -311,14 +310,6 @@ class PaymentEntry(AccountsController):
+ "
" + _("If this is undesirable please cancel the corresponding Payment Entry."),
title=_("Warning"), indicator="orange")
- def set_advance_tax_account(self):
- if self.get('taxes') and not self.advance_tax_account:
- unrealized_profit_loss_account = frappe.db.get_value('Company', self.company, 'unrealized_profit_loss_account')
- if not unrealized_profit_loss_account:
- frappe.throw(_("Please select advance tax account or add Unrealized Profit / Loss Account in company master"))
-
- self.advance_tax_account = unrealized_profit_loss_account
-
def validate_journal_entry(self):
for d in self.get("references"):
if d.allocated_amount and d.reference_doctype == "Journal Entry":
@@ -461,6 +452,11 @@ class PaymentEntry(AccountsController):
for d in to_remove:
self.remove(d)
+ def apply_taxes(self):
+ self.initialize_taxes()
+ self.determine_exclusive_rate()
+ self.calculate_taxes()
+
def set_amounts(self):
self.set_received_amount()
self.set_amounts_in_company_currency()
@@ -715,12 +711,12 @@ class PaymentEntry(AccountsController):
if account_currency != self.company_currency:
frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency))
- if self.payment_type == 'Pay':
+ if (self.payment_type == 'Pay' and self.advance_tax_account) or self.payment_type == 'Receive':
dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
- rev_dr_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
- elif self.payment_type == 'Receive':
+ elif (self.payment_type == 'Receive' and self.advance_tax_account) or self.payment_type == 'Pay':
dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
- rev_dr_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
+
+ payment_or_advance_account = self.get_party_account_for_taxes()
gl_entries.append(
self.get_gl_dict({
@@ -733,15 +729,16 @@ class PaymentEntry(AccountsController):
"cost_center": d.cost_center
}, account_currency, item=d))
+ #Intentionally use -1 to get net values in party account
gl_entries.append(
self.get_gl_dict({
- "account": self.advance_tax_account,
+ "account": payment_or_advance_account,
"against": self.party if self.payment_type=="Receive" else self.paid_from,
- rev_dr_cr: d.base_tax_amount,
- rev_dr_cr + "_in_account_currency": d.base_tax_amount
+ dr_or_cr: -1 * d.base_tax_amount,
+ dr_or_cr + "_in_account_currency": -1*d.base_tax_amount
if account_currency==self.company_currency
else d.tax_amount,
- "cost_center": d.cost_center or self.cost_center
+ "cost_center": self.cost_center,
}, account_currency, item=d))
def add_deductions_gl_entries(self, gl_entries):
@@ -762,6 +759,14 @@ class PaymentEntry(AccountsController):
}, item=d)
)
+ def get_party_account_for_taxes(self):
+ if self.advance_tax_account:
+ return self.advance_tax_account
+ elif self.payment_type == 'Pay':
+ return self.paid_from
+ elif self.payment_type == 'Receive':
+ return self.paid_to
+
def update_advance_paid(self):
if self.payment_type in ("Receive", "Pay") and self.party:
for d in self.get("references"):
@@ -808,32 +813,52 @@ class PaymentEntry(AccountsController):
self.append('deductions', row)
self.set_unallocated_amount()
+ def initialize_taxes(self):
+ for tax in self.get("taxes"):
+ tax_fields = ["total", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
+
+ if tax.charge_type != "Actual":
+ tax_fields.append("tax_amount")
+
+ for fieldname in tax_fields:
+ tax.set(fieldname, 0.0)
+
+ self.paid_amount_after_tax = self.paid_amount
+
+ def determine_exclusive_rate(self):
+ if not any((cint(tax.included_in_paid_amount) for tax in self.get("taxes"))):
+ return
+
+ cumulated_tax_fraction = 0
+ total_inclusive_tax_amount_per_qty = 0
+ for i, tax in enumerate(self.get("taxes")):
+
+ tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax)
+ if i==0:
+ tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
+ else:
+ tax.grand_total_fraction_for_current_item = \
+ self.get("taxes")[i-1].grand_total_fraction_for_current_item \
+ + tax.tax_fraction_for_current_item
+
+ cumulated_tax_fraction += tax.tax_fraction_for_current_item
+
+ self.paid_amount_after_tax = flt(self.paid_amount/(1+cumulated_tax_fraction))
+
def calculate_taxes(self):
self.total_taxes_and_charges = 0.0
self.base_total_taxes_and_charges = 0.0
+ actual_tax_dict = dict([[tax.idx, flt(tax.tax_amount, tax.precision("tax_amount"))]
+ for tax in self.get("taxes") if tax.charge_type == "Actual"])
+
for i, tax in enumerate(self.get('taxes')):
- tax_rate = tax.rate
-
- # To set row_id by default as previous row.
- if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"]:
- if tax.idx == 1:
- frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"))
-
- if not tax.row_id:
- tax.row_id = tax.idx - 1
+ current_tax_amount = self.get_current_tax_amount(tax)
if tax.charge_type == "Actual":
- current_tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
- elif tax.charge_type == "On Paid Amount":
- current_tax_amount = (tax_rate / 100.0) * self.paid_amount
- elif tax.charge_type == "On Previous Row Amount":
- current_tax_amount = (tax_rate / 100.0) * \
- self.get('taxes')[cint(tax.row_id) - 1].tax_amount
-
- elif tax.charge_type == "On Previous Row Total":
- current_tax_amount = (tax_rate / 100.0) * \
- self.get('taxes')[cint(tax.row_id) - 1].total
+ actual_tax_dict[tax.idx] -= current_tax_amount
+ if i == len(self.get("taxes")) - 1:
+ current_tax_amount += actual_tax_dict[tax.idx]
tax.tax_amount = current_tax_amount
tax.base_tax_amount = tax.tax_amount * self.source_exchange_rate
@@ -843,21 +868,68 @@ class PaymentEntry(AccountsController):
else:
current_tax_amount *= 1.0
- if not tax.included_in_paid_amount:
- applicable_tax = current_tax_amount
- else:
- applicable_tax = 0
-
if i == 0:
- tax.total = flt(self.paid_amount + applicable_tax, self.precision("total", tax))
+ tax.total = flt(self.paid_amount_after_tax + current_tax_amount, self.precision("total", tax))
else:
- tax.total = flt(self.get('taxes')[i-1].total + applicable_tax, self.precision("total", tax))
+ tax.total = flt(self.get('taxes')[i-1].total + current_tax_amount, self.precision("total", tax))
tax.base_total = tax.total * self.source_exchange_rate
self.total_taxes_and_charges += current_tax_amount
self.base_total_taxes_and_charges += current_tax_amount * self.source_exchange_rate
+ if self.get('taxes'):
+ self.paid_amount_after_tax = self.get('taxes')[-1].base_total
+
+ def get_current_tax_amount(self, tax):
+ tax_rate = tax.rate
+
+ # To set row_id by default as previous row.
+ if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"]:
+ if tax.idx == 1:
+ frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"))
+
+ if not tax.row_id:
+ tax.row_id = tax.idx - 1
+
+ if tax.charge_type == "Actual":
+ current_tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
+ elif tax.charge_type == "On Paid Amount":
+ current_tax_amount = (tax_rate / 100.0) * self.paid_amount_after_tax
+ elif tax.charge_type == "On Previous Row Amount":
+ current_tax_amount = (tax_rate / 100.0) * \
+ self.get('taxes')[cint(tax.row_id) - 1].tax_amount
+
+ elif tax.charge_type == "On Previous Row Total":
+ current_tax_amount = (tax_rate / 100.0) * \
+ self.get('taxes')[cint(tax.row_id) - 1].total
+
+ return current_tax_amount
+
+ def get_current_tax_fraction(self, tax):
+ current_tax_fraction = 0
+
+ if cint(tax.included_in_paid_amount):
+ tax_rate = tax.rate
+
+ if tax.charge_type == 'Actual':
+ current_tax_fraction = tax.tax_amount/self.paid_amount_after_tax
+ elif tax.charge_type == "On Paid Amount":
+ current_tax_fraction = tax_rate / 100.0
+
+ elif tax.charge_type == "On Previous Row Amount":
+ current_tax_fraction = (tax_rate / 100.0) * \
+ self.get("taxes")[cint(tax.row_id) - 1].tax_fraction_for_current_item
+
+ elif tax.charge_type == "On Previous Row Total":
+ current_tax_fraction = (tax_rate / 100.0) * \
+ self.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
+
+ if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
+ current_tax_fraction *= -1.0
+
+ return current_tax_fraction
+
@frappe.whitelist()
def get_outstanding_reference_documents(args):
@@ -1426,6 +1498,9 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
pe.apply_tax_withholding_amount = 1
pe.tax_withholding_category = doc.tax_withholding_category
+ if not pe.advance_tax_account:
+ pe.advance_tax_account = frappe.db.get_value('Company', pe.company, 'unrealized_profit_loss_account')
+
return pe
def get_bank_cash_account(doc, bank_account):
From bbf07d9214bf86eb120a7ad14989b2bd21a5d9d7 Mon Sep 17 00:00:00 2001
From: pateljannat
Date: Tue, 8 Jun 2021 17:05:44 +0530
Subject: [PATCH 184/262] fix: quiz timer issues
---
erpnext/education/utils.py | 13 +++++++------
erpnext/public/js/education/lms/quiz.js | 10 ++++------
erpnext/www/lms/content.html | 1 +
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py
index 8f51fef847..9d5653c170 100644
--- a/erpnext/education/utils.py
+++ b/erpnext/education/utils.py
@@ -219,7 +219,6 @@ def get_quiz(quiz_name, course):
try:
quiz = frappe.get_doc("Quiz", quiz_name)
questions = quiz.get_questions()
- duration = quiz.duration
except:
frappe.throw(_("Quiz {0} does not exist").format(quiz_name), frappe.DoesNotExistError)
return None
@@ -236,15 +235,17 @@ def get_quiz(quiz_name, course):
return {
'questions': questions,
'activity': None,
- 'duration':duration
+ 'is_time_bound': quiz.is_time_bound,
+ 'duration': quiz.duration
}
student = get_current_student()
course_enrollment = get_enrollment("course", course, student.name)
status, score, result, time_taken = check_quiz_completion(quiz, course_enrollment)
return {
- 'questions': questions,
+ 'questions': questions,
'activity': {'is_complete': status, 'score': score, 'result': result, 'time_taken': time_taken},
+ 'is_time_bound': quiz.is_time_bound,
'duration': quiz.duration
}
@@ -372,9 +373,9 @@ def check_content_completion(content_name, content_type, enrollment_name):
def check_quiz_completion(quiz, enrollment_name):
attempts = frappe.get_all("Quiz Activity",
filters={
- 'enrollment': enrollment_name,
+ 'enrollment': enrollment_name,
'quiz': quiz.name
- },
+ },
fields=["name", "activity_date", "score", "status", "time_taken"]
)
status = False if quiz.max_attempts == 0 else bool(len(attempts) >= quiz.max_attempts)
@@ -389,4 +390,4 @@ def check_quiz_completion(quiz, enrollment_name):
time_taken = attempts[0]['time_taken']
if result == 'Pass':
status = True
- return status, score, result, time_taken
\ No newline at end of file
+ return status, score, result, time_taken
diff --git a/erpnext/public/js/education/lms/quiz.js b/erpnext/public/js/education/lms/quiz.js
index 32fa4ab1ec..5bb8425c85 100644
--- a/erpnext/public/js/education/lms/quiz.js
+++ b/erpnext/public/js/education/lms/quiz.js
@@ -20,10 +20,8 @@ class Quiz {
}
make(data) {
- if (data.duration) {
- const timer_display = document.createElement("div");
- timer_display.classList.add("lms-timer", "float-right", "font-weight-bold");
- document.getElementsByClassName("lms-title")[0].appendChild(timer_display);
+ if (data.is_time_bound) {
+ $(".lms-timer").removeClass("hide")
if (!data.activity || (data.activity && !data.activity.is_complete)) {
this.initialiseTimer(data.duration);
this.is_time_bound = true;
@@ -118,7 +116,7 @@ class Quiz {
quiz_response: this.get_selected(),
course: this.course,
program: this.program,
- time_taken: this.is_time_bound ? this.time_taken : ""
+ time_taken: this.is_time_bound ? this.time_taken : 0
}).then(res => {
this.submit_btn.remove()
if (!res.message) {
@@ -237,4 +235,4 @@ class Question {
this.options = option_list
this.wrapper.appendChild(options_wrapper)
}
-}
\ No newline at end of file
+}
diff --git a/erpnext/www/lms/content.html b/erpnext/www/lms/content.html
index 15afb097b9..d22ef66d2a 100644
--- a/erpnext/www/lms/content.html
+++ b/erpnext/www/lms/content.html
@@ -64,6 +64,7 @@
{{ content.name }} ({{ position + 1 }}/{{length}})
+
{% endmacro %}
From 646f0c3b53239f05ad39c8eaecdfcccaca5bd564 Mon Sep 17 00:00:00 2001
From: walstanb
Date: Tue, 8 Jun 2021 17:54:34 +0530
Subject: [PATCH 185/262] fix: variable declaration
---
erpnext/selling/doctype/quotation/quotation.js | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 7fecd4bc34..1223449549 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -53,8 +53,11 @@ erpnext.selling.QuotationController = class QuotationController extends erpnext.
}
refresh(doc, dt, dn) {
super.refresh(doc, dt, dn);
- doctype = doc.quotation_to == 'Customer' ? 'Customer':'Lead';
- frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'party_name', doctype: doctype}
+ frappe.dynamic_link = {
+ doc: this.frm.doc,
+ fieldname: 'party_name',
+ doctype: doc.quotation_to == 'Customer' ? 'Customer' : 'Lead',
+ };
var me = this;
From 7ace06ac21c7d29d8470df139979c15f46a82ed1 Mon Sep 17 00:00:00 2001
From: pateljannat
Date: Tue, 8 Jun 2021 18:26:23 +0530
Subject: [PATCH 186/262] fix: sider
---
erpnext/education/utils.py | 2 +-
erpnext/public/js/education/lms/quiz.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py
index 9d5653c170..9db8a4a90d 100644
--- a/erpnext/education/utils.py
+++ b/erpnext/education/utils.py
@@ -245,7 +245,7 @@ def get_quiz(quiz_name, course):
return {
'questions': questions,
'activity': {'is_complete': status, 'score': score, 'result': result, 'time_taken': time_taken},
- 'is_time_bound': quiz.is_time_bound,
+ 'is_time_bound': quiz.is_time_bound,
'duration': quiz.duration
}
diff --git a/erpnext/public/js/education/lms/quiz.js b/erpnext/public/js/education/lms/quiz.js
index 5bb8425c85..66160a7610 100644
--- a/erpnext/public/js/education/lms/quiz.js
+++ b/erpnext/public/js/education/lms/quiz.js
@@ -21,7 +21,7 @@ class Quiz {
make(data) {
if (data.is_time_bound) {
- $(".lms-timer").removeClass("hide")
+ $(".lms-timer").removeClass("hide");
if (!data.activity || (data.activity && !data.activity.is_complete)) {
this.initialiseTimer(data.duration);
this.is_time_bound = true;
From 6b8c123fd99dcc15f1b959a99573b5abb94419fe Mon Sep 17 00:00:00 2001
From: Jannat Patel <31363128+pateljannat@users.noreply.github.com>
Date: Tue, 8 Jun 2021 18:57:49 +0530
Subject: [PATCH 187/262] fix: Quiz timer (#25983)
* fix: quiz timer
* fix: pass time bound parameter
* fix: sider
---
.../doctype/course_enrollment/course_enrollment.py | 2 +-
erpnext/education/utils.py | 13 +++++++------
erpnext/public/js/education/lms/quiz.js | 8 +++-----
erpnext/www/lms/content.html | 1 +
4 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/erpnext/education/doctype/course_enrollment/course_enrollment.py b/erpnext/education/doctype/course_enrollment/course_enrollment.py
index 2b3acf1b93..ce88990a70 100644
--- a/erpnext/education/doctype/course_enrollment/course_enrollment.py
+++ b/erpnext/education/doctype/course_enrollment/course_enrollment.py
@@ -91,4 +91,4 @@ def check_activity_exists(enrollment, content_type, content):
if activity:
return activity[0].name
else:
- return None
\ No newline at end of file
+ return None
diff --git a/erpnext/education/utils.py b/erpnext/education/utils.py
index 8f51fef847..819106bde7 100644
--- a/erpnext/education/utils.py
+++ b/erpnext/education/utils.py
@@ -219,7 +219,6 @@ def get_quiz(quiz_name, course):
try:
quiz = frappe.get_doc("Quiz", quiz_name)
questions = quiz.get_questions()
- duration = quiz.duration
except:
frappe.throw(_("Quiz {0} does not exist").format(quiz_name), frappe.DoesNotExistError)
return None
@@ -236,15 +235,17 @@ def get_quiz(quiz_name, course):
return {
'questions': questions,
'activity': None,
- 'duration':duration
+ 'is_time_bound': quiz.is_time_bound,
+ 'duration':quiz.duration
}
student = get_current_student()
course_enrollment = get_enrollment("course", course, student.name)
status, score, result, time_taken = check_quiz_completion(quiz, course_enrollment)
return {
- 'questions': questions,
+ 'questions': questions,
'activity': {'is_complete': status, 'score': score, 'result': result, 'time_taken': time_taken},
+ 'is_time_bound': quiz.is_time_bound,
'duration': quiz.duration
}
@@ -372,9 +373,9 @@ def check_content_completion(content_name, content_type, enrollment_name):
def check_quiz_completion(quiz, enrollment_name):
attempts = frappe.get_all("Quiz Activity",
filters={
- 'enrollment': enrollment_name,
+ 'enrollment': enrollment_name,
'quiz': quiz.name
- },
+ },
fields=["name", "activity_date", "score", "status", "time_taken"]
)
status = False if quiz.max_attempts == 0 else bool(len(attempts) >= quiz.max_attempts)
@@ -389,4 +390,4 @@ def check_quiz_completion(quiz, enrollment_name):
time_taken = attempts[0]['time_taken']
if result == 'Pass':
status = True
- return status, score, result, time_taken
\ No newline at end of file
+ return status, score, result, time_taken
diff --git a/erpnext/public/js/education/lms/quiz.js b/erpnext/public/js/education/lms/quiz.js
index 5683f73d1b..66160a7610 100644
--- a/erpnext/public/js/education/lms/quiz.js
+++ b/erpnext/public/js/education/lms/quiz.js
@@ -20,10 +20,8 @@ class Quiz {
}
make(data) {
- if (data.duration) {
- const timer_display = document.createElement("div");
- timer_display.classList.add("lms-timer", "float-right", "font-weight-bold");
- document.getElementsByClassName("lms-title")[0].appendChild(timer_display);
+ if (data.is_time_bound) {
+ $(".lms-timer").removeClass("hide");
if (!data.activity || (data.activity && !data.activity.is_complete)) {
this.initialiseTimer(data.duration);
this.is_time_bound = true;
@@ -237,4 +235,4 @@ class Question {
this.options = option_list
this.wrapper.appendChild(options_wrapper)
}
-}
\ No newline at end of file
+}
diff --git a/erpnext/www/lms/content.html b/erpnext/www/lms/content.html
index 15afb097b9..d22ef66d2a 100644
--- a/erpnext/www/lms/content.html
+++ b/erpnext/www/lms/content.html
@@ -64,6 +64,7 @@
{{ content.name }} ({{ position + 1 }}/{{length}})
+
{% endmacro %}
From 18eed58fc5afa1ef95037a1c297b308c34de58ee Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Tue, 8 Jun 2021 20:52:14 +0530
Subject: [PATCH 188/262] fix(e-invoicing): service item check
---
erpnext/regional/india/e_invoice/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index 843fb012b9..a1179ff9b6 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -199,7 +199,7 @@ def get_item_list(invoice):
item.batch_expiry_date = frappe.db.get_value('Batch', d.batch_no, 'expiry_date') if d.batch_no else None
item.batch_expiry_date = format_date(item.batch_expiry_date, 'dd/mm/yyyy') if item.batch_expiry_date else None
- item.is_service_item = 'N' if frappe.db.get_value('Item', d.item_code, 'is_stock_item') else 'Y'
+ item.is_service_item = 'Y' if item.gst_hsn_code[:2] == "99" else 'N'
item.serial_no = ""
item = update_item_taxes(invoice, item)
From 99b583f688966cc89d069f8c5b7c4cf88108abb5 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Wed, 9 Jun 2021 00:06:35 +0530
Subject: [PATCH 189/262] fix: on click of duplicate button system copy the
difference account from first row
---
erpnext/stock/doctype/stock_entry/stock_entry.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 93a6fc0e0a..1a25994b24 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -986,7 +986,10 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
items_add: function(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
- this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]);
+
+ if (!(row.expense_account && row.cost_center)) {
+ this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]);
+ }
if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse;
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
From 21b8e2f0d8f18972b05783eface42404cc104c30 Mon Sep 17 00:00:00 2001
From: Anupam Kumar
Date: Wed, 9 Jun 2021 12:57:21 +0530
Subject: [PATCH 190/262] fix: hiding Rounding Adjustment field (#25380)
* fix: hiding Rounding Adjustment field
* fix: updating purchase_invoice.json
---
.../accounts/doctype/purchase_invoice/purchase_invoice.json | 4 +++-
erpnext/buying/doctype/purchase_order/purchase_order.json | 4 +++-
.../buying/doctype/supplier_quotation/supplier_quotation.json | 4 +++-
erpnext/stock/doctype/purchase_receipt/purchase_receipt.json | 4 +++-
4 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index d3d3ffa17f..9157821520 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -837,6 +837,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "base_rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment (Company Currency)",
@@ -883,6 +884,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment",
@@ -1380,7 +1382,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-30 22:45:58.334107",
+ "modified": "2021-06-09 12:30:25.632109",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index ee2beea67f..8677c71bc5 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -765,6 +765,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "base_rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment (Company Currency)",
@@ -810,6 +811,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment",
@@ -1124,7 +1126,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2021-01-20 22:07:23.487138",
+ "modified": "2021-04-19 00:55:30.781375",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
index 40fbe2c26e..0a51a8e9a1 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
@@ -576,6 +576,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "base_rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment (Company Currency",
@@ -620,6 +621,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment",
@@ -802,7 +804,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2020-12-03 15:18:29.073368",
+ "modified": "2021-04-19 00:58:20.995491",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index 32d349f303..ad350d344f 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -762,6 +762,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "base_rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment (Company Currency)",
@@ -805,6 +806,7 @@
"read_only": 1
},
{
+ "depends_on": "eval:!doc.disable_rounded_total",
"fieldname": "rounding_adjustment",
"fieldtype": "Currency",
"label": "Rounding Adjustment",
@@ -1147,7 +1149,7 @@
"idx": 261,
"is_submittable": 1,
"links": [],
- "modified": "2020-12-26 20:49:39.106049",
+ "modified": "2021-04-19 01:01:00.754119",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
From 8090965162fc314ff8f41d71e5890f8c7f060802 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 9 Jun 2021 13:45:42 +0530
Subject: [PATCH 191/262] fix: Debug test
---
.../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 8afb9a29f4..5187ca1b5e 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1017,6 +1017,9 @@ class TestPurchaseInvoice(unittest.TestCase):
where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", (purchase_invoice.name), as_dict=1)
+ for i, gle in enumerate(gl_entries):
+ print(gle.account, gle.debit, gle.credit)
+
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_gle[i][0], gle.account)
self.assertEqual(expected_gle[i][1], gle.debit)
From 4c1dad820780b88ca7c5710e570003974c11bd54 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 9 Jun 2021 14:18:23 +0530
Subject: [PATCH 192/262] fix: Debug tests
---
.../accounts/doctype/purchase_invoice/test_purchase_invoice.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 5187ca1b5e..3299ecc5bc 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -991,6 +991,9 @@ class TestPurchaseInvoice(unittest.TestCase):
where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", (payment_entry.name), as_dict=1)
+ for i, gle in enumerate(gl_entries):
+ print(gle.account, gle.debit, gle.credit)
+
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_gle[i][0], gle.account)
self.assertEqual(expected_gle[i][1], gle.debit)
From b57ebba3fd8af3cb70b16a340d41961ba6eb7223 Mon Sep 17 00:00:00 2001
From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
Date: Wed, 9 Jun 2021 17:56:41 +0530
Subject: [PATCH 193/262] fix: Validate negative allocated amount in Payment
Entry (#25799)
---
.../invoice_discounting/invoice_discounting.py | 7 +++++--
.../doctype/payment_entry/payment_entry.py | 14 ++++++++++----
.../doctype/payment_request/payment_request.py | 3 +--
.../accounts_receivable/accounts_receivable.py | 1 +
4 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
index 7b62b617f9..95d2ee56d9 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
@@ -49,11 +49,11 @@ class InvoiceDiscounting(AccountsController):
self.make_gl_entries()
def on_cancel(self):
- self.set_status()
+ self.set_status(cancel=1)
self.update_sales_invoice()
self.make_gl_entries()
- def set_status(self, status=None):
+ def set_status(self, status=None, cancel=0):
if status:
self.status = status
self.db_set("status", status)
@@ -66,6 +66,9 @@ class InvoiceDiscounting(AccountsController):
elif self.docstatus == 2:
self.status = "Cancelled"
+ if cancel:
+ self.db_set('status', self.status, update_modified = True)
+
def update_sales_invoice(self):
for d in self.invoices:
if self.docstatus == 1:
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 62ab76c323..e01c651a93 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -65,7 +65,6 @@ class PaymentEntry(AccountsController):
self.set_status()
def on_submit(self):
- self.setup_party_account_field()
if self.difference_amount:
frappe.throw(_("Difference Amount must be zero"))
self.make_gl_entries()
@@ -78,7 +77,6 @@ class PaymentEntry(AccountsController):
def on_cancel(self):
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry')
- self.setup_party_account_field()
self.make_gl_entries(cancel=1)
self.update_outstanding_amounts()
self.update_advance_paid()
@@ -122,6 +120,11 @@ class PaymentEntry(AccountsController):
if flt(d.allocated_amount) > flt(d.outstanding_amount):
frappe.throw(_("Row #{0}: Allocated Amount cannot be greater than outstanding amount.").format(d.idx))
+ # Check for negative outstanding invoices as well
+ if flt(d.allocated_amount) < 0:
+ if flt(d.allocated_amount) < flt(d.outstanding_amount):
+ frappe.throw(_("Row #{0}: Allocated Amount cannot be greater than outstanding amount.").format(d.idx))
+
def delink_advance_entry_references(self):
for reference in self.references:
if reference.reference_doctype in ("Sales Invoice", "Purchase Invoice"):
@@ -177,7 +180,7 @@ class PaymentEntry(AccountsController):
for field, value in iteritems(ref_details):
if field == 'exchange_rate' or not d.get(field) or force:
- d.set(field, value)
+ d.db_set(field, value)
def validate_payment_type(self):
if self.payment_type not in ("Receive", "Pay", "Internal Transfer"):
@@ -386,6 +389,8 @@ class PaymentEntry(AccountsController):
else:
self.status = 'Draft'
+ self.db_set('status', self.status, update_modified = True)
+
def set_amounts(self):
self.set_amounts_in_company_currency()
self.set_total_allocated_amount()
@@ -791,7 +796,7 @@ def split_invoices_based_on_payment_terms(outstanding_invoices):
outstanding_invoices.pop(idx - 1)
outstanding_invoices += invoice_ref_based_on_payment_terms[idx]
-
+
return outstanding_invoices
def get_orders_to_be_billed(posting_date, party_type, party,
@@ -989,6 +994,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
outstanding_amount = ref_doc.get("outstanding_amount")
elif reference_doctype == "Donation":
total_amount = ref_doc.get("amount")
+ outstanding_amount = total_amount
exchange_rate = 1
elif reference_doctype == "Dunning":
total_amount = ref_doc.get("dunning_amount")
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 53ac996290..468978785b 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -101,7 +101,7 @@ class PaymentRequest(Document):
controller.validate_transaction_currency(self.currency)
controller.request_for_payment(**payment_record)
-
+
def get_request_amount(self):
data_of_completed_requests = frappe.get_all("Integration Request", filters={
'reference_doctype': self.doctype,
@@ -492,7 +492,6 @@ def update_payment_req_status(doc, method):
status = 'Requested'
pay_req_doc.db_set('status', status)
- frappe.db.commit()
def get_dummy_message(doc):
return frappe.render_template("""{% if doc.contact_person -%}
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index db605f7285..a11b77a6f6 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -584,6 +584,7 @@ class ReceivablePayableReport(object):
`tabGL Entry`
where
docstatus < 2
+ and is_cancelled = 0
and party_type=%s
and (party is not null and party != '')
{1} {2} {3}"""
From 8eab59b06240d27dea1ea443a21bf285b1e53de2 Mon Sep 17 00:00:00 2001
From: ChillarAnand
Date: Wed, 9 Jun 2021 18:05:39 +0530
Subject: [PATCH 194/262] chore: Upgrade PyGithub to 1.55
Frappe has upgraded to PyJWT>2. Upgrading PyGithub to resolve
dependency issues
---
requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index e30746a538..f28906ae35 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,7 +5,7 @@ googlemaps # used in ERPNext, but dependency is defined in Frappe
pandas~=1.1.5
plaid-python~=7.2.1
pycountry~=20.7.3
-PyGithub~=1.54.1
+PyGithub~=1.55
python-stdnum~=1.16
python-youtube~=0.8.0
taxjar~=1.9.2
From 9e648183dbc52ee526b3a3dd15b1f57110ebccb5 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 9 Jun 2021 18:26:16 +0530
Subject: [PATCH 195/262] fix: Test case
---
erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 --
.../doctype/purchase_invoice/test_purchase_invoice.py | 8 +-------
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 5796fc0800..d04d6a0d15 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -835,9 +835,7 @@ class PaymentEntry(AccountsController):
return
cumulated_tax_fraction = 0
- total_inclusive_tax_amount_per_qty = 0
for i, tax in enumerate(self.get("taxes")):
-
tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax)
if i==0:
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 3299ecc5bc..8e72dc6321 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -991,9 +991,6 @@ class TestPurchaseInvoice(unittest.TestCase):
where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", (payment_entry.name), as_dict=1)
- for i, gle in enumerate(gl_entries):
- print(gle.account, gle.debit, gle.credit)
-
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_gle[i][0], gle.account)
self.assertEqual(expected_gle[i][1], gle.debit)
@@ -1011,8 +1008,8 @@ class TestPurchaseInvoice(unittest.TestCase):
['_Test Account Cost for Goods Sold - _TC', 30000, 0],
['_Test Account Excise Duty - _TC', 0, 3000],
['Creditors - _TC', 0, 27000],
- ['TDS Payable - _TC', 0, 3000],
['TDS Payable - _TC', 3000, 0]
+ ['TDS Payable - _TC', 0, 3000],
]
gl_entries = frappe.db.sql("""select account, debit, credit
@@ -1020,9 +1017,6 @@ class TestPurchaseInvoice(unittest.TestCase):
where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", (purchase_invoice.name), as_dict=1)
- for i, gle in enumerate(gl_entries):
- print(gle.account, gle.debit, gle.credit)
-
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_gle[i][0], gle.account)
self.assertEqual(expected_gle[i][1], gle.debit)
From 26f06093903036bdb222e523d3dba12888869086 Mon Sep 17 00:00:00 2001
From: Saqib
Date: Wed, 9 Jun 2021 19:47:28 +0530
Subject: [PATCH 196/262] feat: enable/disable gl entry posting for change
given in pos (#25822)
---
.../accounts_settings/accounts_settings.json | 9 +++-
.../doctype/sales_invoice/sales_invoice.py | 12 ++++-
.../sales_invoice/test_sales_invoice.py | 44 +++++++++++++++++--
3 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 781f94e203..2735b1ccee 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -18,6 +18,7 @@
"delete_linked_ledger_entries",
"book_asset_depreciation_entry_automatically",
"unlink_advance_payment_on_cancelation_of_order",
+ "post_change_gl_entries",
"tax_settings_section",
"determine_address_tax_category_from",
"column_break_19",
@@ -253,6 +254,12 @@
{
"fieldname": "column_break_19",
"fieldtype": "Column Break"
+ },
+ {
+ "default": "1",
+ "fieldname": "post_change_gl_entries",
+ "fieldtype": "Check",
+ "label": "Post Ledger Entries for Given Change"
}
],
"icon": "icon-cog",
@@ -260,7 +267,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2021-04-30 15:25:10.381008",
+ "modified": "2021-05-25 12:34:05.858669",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index f8b5179d2c..0b8d28aef0 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -849,7 +849,6 @@ class SalesInvoice(SellingController):
self.make_loyalty_point_redemption_gle(gl_entries)
self.make_pos_gl_entries(gl_entries)
- self.make_gle_for_change_amount(gl_entries)
self.make_write_off_gl_entry(gl_entries)
self.make_gle_for_rounding_adjustment(gl_entries)
@@ -983,7 +982,13 @@ class SalesInvoice(SellingController):
def make_pos_gl_entries(self, gl_entries):
if cint(self.is_pos):
+
+ skip_change_gl_entries = not cint(frappe.db.get_single_value('Accounts Settings', 'post_change_gl_entries'))
+
for payment_mode in self.payments:
+ if skip_change_gl_entries and payment_mode.account == self.account_for_change_amount:
+ payment_mode.base_amount -= self.change_amount
+
if payment_mode.amount:
# POS, make payment entries
gl_entries.append(
@@ -1015,8 +1020,11 @@ class SalesInvoice(SellingController):
}, payment_mode_account_currency, item=self)
)
+ if not skip_change_gl_entries:
+ self.make_gle_for_change_amount(gl_entries)
+
def make_gle_for_change_amount(self, gl_entries):
- if cint(self.is_pos) and self.change_amount:
+ if self.change_amount:
if self.account_for_change_amount:
gl_entries.append(
self.get_gl_dict({
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index df6d483904..5409a6f192 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -713,7 +713,7 @@ class TestSalesInvoice(unittest.TestCase):
si.submit()
self.assertEqual(si.paid_amount, 100.0)
- self.pos_gl_entry(si, pos, 50)
+ self.validate_pos_gl_entry(si, pos, 50)
def test_pos_returns_with_repayment(self):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_sales_return
@@ -749,7 +749,7 @@ class TestSalesInvoice(unittest.TestCase):
make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1",
expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
- pr = make_purchase_receipt(company= "_Test Company with perpetual inventory",
+ make_purchase_receipt(company= "_Test Company with perpetual inventory",
item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
@@ -770,7 +770,45 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(pos.grand_total, 100.0)
self.assertEqual(pos.write_off_amount, -5)
- def pos_gl_entry(self, si, pos, cash_amount):
+ def test_pos_with_no_gl_entry_for_change_amount(self):
+ frappe.db.set_value('Accounts Settings', None, 'post_change_gl_entries', 0)
+
+ make_pos_profile(company="_Test Company with perpetual inventory", income_account = "Sales - TCP1",
+ expense_account = "Cost of Goods Sold - TCP1", warehouse="Stores - TCP1", cost_center = "Main - TCP1", write_off_account="_Test Write Off - TCP1")
+
+ make_purchase_receipt(company= "_Test Company with perpetual inventory",
+ item_code= "_Test FG Item",warehouse= "Stores - TCP1", cost_center= "Main - TCP1")
+
+ pos = create_sales_invoice(company= "_Test Company with perpetual inventory",
+ debit_to="Debtors - TCP1", item_code= "_Test FG Item", warehouse="Stores - TCP1",
+ income_account = "Sales - TCP1", expense_account = "Cost of Goods Sold - TCP1",
+ cost_center = "Main - TCP1", do_not_save=True)
+
+ pos.is_pos = 1
+ pos.update_stock = 1
+
+ taxes = get_taxes_and_charges()
+ pos.taxes = []
+ for tax in taxes:
+ pos.append("taxes", tax)
+
+ pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 50})
+ pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - TCP1', 'amount': 60})
+
+ pos.insert()
+ pos.submit()
+
+ self.assertEqual(pos.grand_total, 100.0)
+ self.assertEqual(pos.change_amount, 10)
+
+ self.validate_pos_gl_entry(pos, pos, 60, validate_without_change_gle=True)
+
+ frappe.db.set_value('Accounts Settings', None, 'post_change_gl_entries', 1)
+
+ def validate_pos_gl_entry(self, si, pos, cash_amount, validate_without_change_gle=False):
+ if validate_without_change_gle:
+ cash_amount -= pos.change_amount
+
# check stock ledger entries
sle = frappe.db.sql("""select * from `tabStock Ledger Entry`
where voucher_type = 'Sales Invoice' and voucher_no = %s""",
From 42557c4ad387db7ea4956ac80dfaea085614481d Mon Sep 17 00:00:00 2001
From: Saqib
Date: Wed, 9 Jun 2021 19:48:31 +0530
Subject: [PATCH 197/262] feat: cost-center wise period closing entry (#25766)
---
.../period_closing_voucher.json | 452 +++++-------------
.../period_closing_voucher.py | 111 +++--
.../test_period_closing_voucher.py | 85 ++++
3 files changed, 277 insertions(+), 371 deletions(-)
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json
index 47546c07a4..84c941ecc1 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json
@@ -1,350 +1,138 @@
{
- "allow_copy": 0,
- "allow_guest_to_view": 0,
- "allow_import": 0,
- "allow_rename": 0,
- "autoname": "ACC-PCV-.YYYY.-.#####",
- "beta": 0,
- "creation": "2013-01-10 16:34:07",
- "custom": 0,
- "docstatus": 0,
- "doctype": "DocType",
- "editable_grid": 0,
- "engine": "InnoDB",
+ "actions": [],
+ "autoname": "ACC-PCV-.YYYY.-.#####",
+ "creation": "2013-01-10 16:34:07",
+ "doctype": "DocType",
+ "engine": "InnoDB",
+ "field_order": [
+ "transaction_date",
+ "posting_date",
+ "fiscal_year",
+ "amended_from",
+ "company",
+ "cost_center_wise_pnl",
+ "column_break1",
+ "closing_account_head",
+ "remarks"
+ ],
"fields": [
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "transaction_date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Transaction Date",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "transaction_date",
- "oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "transaction_date",
+ "fieldtype": "Date",
+ "label": "Transaction Date",
+ "oldfieldname": "transaction_date",
+ "oldfieldtype": "Date"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "posting_date",
- "fieldtype": "Date",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Posting Date",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "posting_date",
- "oldfieldtype": "Date",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "posting_date",
+ "fieldtype": "Date",
+ "label": "Posting Date",
+ "oldfieldname": "posting_date",
+ "oldfieldtype": "Date",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "fiscal_year",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Closing Fiscal Year",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "fiscal_year",
- "oldfieldtype": "Select",
- "options": "Fiscal Year",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "fiscal_year",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "in_standard_filter": 1,
+ "label": "Closing Fiscal Year",
+ "oldfieldname": "fiscal_year",
+ "oldfieldtype": "Select",
+ "options": "Fiscal Year",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 1,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Amended From",
- "length": 0,
- "no_copy": 1,
- "oldfieldname": "amended_from",
- "oldfieldtype": "Data",
- "options": "Period Closing Voucher",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 1,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "oldfieldname": "amended_from",
+ "oldfieldtype": "Data",
+ "options": "Period Closing Voucher",
+ "read_only": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "company",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Company",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "company",
- "oldfieldtype": "Select",
- "options": "Company",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "company",
+ "fieldtype": "Link",
+ "label": "Company",
+ "oldfieldname": "company",
+ "oldfieldtype": "Select",
+ "options": "Company",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "column_break1",
- "fieldtype": "Column Break",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "length": 0,
- "no_copy": 0,
- "oldfieldtype": "Column Break",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "fieldname": "column_break1",
+ "fieldtype": "Column Break",
+ "oldfieldtype": "Column Break"
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "description": "The account head under Liability or Equity, in which Profit/Loss will be booked",
- "fieldname": "closing_account_head",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Closing Account Head",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "closing_account_head",
- "oldfieldtype": "Link",
- "options": "Account",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
- },
+ "description": "The account head under Liability or Equity, in which Profit/Loss will be booked",
+ "fieldname": "closing_account_head",
+ "fieldtype": "Link",
+ "label": "Closing Account Head",
+ "oldfieldname": "closing_account_head",
+ "oldfieldtype": "Link",
+ "options": "Account",
+ "reqd": 1
+ },
{
- "allow_bulk_edit": 0,
- "allow_in_quick_entry": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "remarks",
- "fieldtype": "Small Text",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Remarks",
- "length": 0,
- "no_copy": 0,
- "oldfieldname": "remarks",
- "oldfieldtype": "Small Text",
- "permlevel": 0,
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 1,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
+ "fieldname": "remarks",
+ "fieldtype": "Small Text",
+ "label": "Remarks",
+ "oldfieldname": "remarks",
+ "oldfieldtype": "Small Text",
+ "reqd": 1
+ },
+ {
+ "default": "0",
+ "fieldname": "cost_center_wise_pnl",
+ "fieldtype": "Check",
+ "label": "Book Cost Center Wise Profit/Loss"
}
- ],
- "has_web_view": 0,
- "hide_heading": 0,
- "hide_toolbar": 0,
- "icon": "fa fa-file-text",
- "idx": 1,
- "image_view": 0,
- "in_create": 0,
- "is_submittable": 1,
- "issingle": 0,
- "istable": 0,
- "max_attachments": 0,
- "modified": "2020-09-18 17:26:09.703215",
- "modified_by": "Administrator",
- "module": "Accounts",
- "name": "Period Closing Voucher",
- "owner": "Administrator",
+ ],
+ "icon": "fa fa-file-text",
+ "idx": 1,
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2021-05-20 15:27:37.210458",
+ "modified_by": "Administrator",
+ "module": "Accounts",
+ "name": "Period Closing Voucher",
+ "owner": "Administrator",
"permissions": [
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "System Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
- },
+ },
{
- "amend": 1,
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 0,
- "if_owner": 0,
- "import": 0,
- "permlevel": 0,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Accounts Manager",
- "set_user_permissions": 0,
- "share": 1,
- "submit": 1,
+ "amend": 1,
+ "cancel": 1,
+ "create": 1,
+ "delete": 1,
+ "email": 1,
+ "print": 1,
+ "read": 1,
+ "report": 1,
+ "role": "Accounts Manager",
+ "share": 1,
+ "submit": 1,
"write": 1
}
- ],
- "quick_entry": 0,
- "read_only": 0,
- "read_only_onload": 0,
- "search_fields": "posting_date, fiscal_year",
- "show_name_in_global_search": 0,
- "sort_field": "modified",
- "sort_order": "DESC",
- "title_field": "closing_account_head",
- "track_changes": 0,
- "track_seen": 0,
- "track_views": 0
+ ],
+ "search_fields": "posting_date, fiscal_year",
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "title_field": "closing_account_head"
}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
index a74fa062b6..b0a5b04de6 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py
@@ -51,63 +51,96 @@ class PeriodClosingVoucher(AccountsController):
def make_gl_entries(self):
gl_entries = []
- net_pl_balance = 0
- dimension_fields = ['t1.cost_center']
+ net_pl_balance = 0
- accounting_dimensions = get_accounting_dimensions()
- for dimension in accounting_dimensions:
- dimension_fields.append('t1.{0}'.format(dimension))
-
- dimension_filters, default_dimensions = get_dimensions()
-
- pl_accounts = self.get_pl_balances(dimension_fields)
+ pl_accounts = self.get_pl_balances()
for acc in pl_accounts:
- if flt(acc.balance_in_company_currency):
+ if flt(acc.bal_in_company_currency):
gl_entries.append(self.get_gl_dict({
"account": acc.account,
"cost_center": acc.cost_center,
"account_currency": acc.account_currency,
- "debit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
- if flt(acc.balance_in_account_currency) < 0 else 0,
- "debit": abs(flt(acc.balance_in_company_currency)) \
- if flt(acc.balance_in_company_currency) < 0 else 0,
- "credit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
- if flt(acc.balance_in_account_currency) > 0 else 0,
- "credit": abs(flt(acc.balance_in_company_currency)) \
- if flt(acc.balance_in_company_currency) > 0 else 0
+ "debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
+ "debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
+ "credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
+ "credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0
}, item=acc))
- net_pl_balance += flt(acc.balance_in_company_currency)
+ net_pl_balance += flt(acc.bal_in_company_currency)
if net_pl_balance:
- cost_center = frappe.db.get_value("Company", self.company, "cost_center")
- gl_entry = self.get_gl_dict({
- "account": self.closing_account_head,
- "debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
- "debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
- "credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
- "credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
- "cost_center": cost_center
- })
-
- for dimension in accounting_dimensions:
- gl_entry.update({
- dimension: default_dimensions.get(self.company, {}).get(dimension)
- })
-
- gl_entries.append(gl_entry)
+ if self.cost_center_wise_pnl:
+ costcenter_wise_gl_entries = self.get_costcenter_wise_pnl_gl_entries(pl_accounts)
+ gl_entries += costcenter_wise_gl_entries
+ else:
+ gl_entry = self.get_pnl_gl_entry(net_pl_balance)
+ gl_entries.append(gl_entry)
from erpnext.accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries)
+
+ def get_pnl_gl_entry(self, net_pl_balance):
+ cost_center = frappe.db.get_value("Company", self.company, "cost_center")
+ gl_entry = self.get_gl_dict({
+ "account": self.closing_account_head,
+ "debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
+ "debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
+ "credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
+ "credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
+ "cost_center": cost_center
+ })
+
+ self.update_default_dimensions(gl_entry)
+
+ return gl_entry
+
+ def get_costcenter_wise_pnl_gl_entries(self, pl_accounts):
+ company_cost_center = frappe.db.get_value("Company", self.company, "cost_center")
+ gl_entries = []
+
+ for acc in pl_accounts:
+ if flt(acc.bal_in_company_currency):
+ gl_entry = self.get_gl_dict({
+ "account": self.closing_account_head,
+ "cost_center": acc.cost_center or company_cost_center,
+ "account_currency": acc.account_currency,
+ "debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
+ "debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
+ "credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
+ "credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0
+ }, item=acc)
+
+ self.update_default_dimensions(gl_entry)
+
+ gl_entries.append(gl_entry)
+
+ return gl_entries
+
+ def update_default_dimensions(self, gl_entry):
+ if not self.accounting_dimensions:
+ self.accounting_dimensions = get_accounting_dimensions()
+
+ _, default_dimensions = get_dimensions()
+ for dimension in self.accounting_dimensions:
+ gl_entry.update({
+ dimension: default_dimensions.get(self.company, {}).get(dimension)
+ })
+
+ def get_pl_balances(self):
+ """Get balance for dimension-wise pl accounts"""
+
+ dimension_fields = ['t1.cost_center']
+
+ self.accounting_dimensions = get_accounting_dimensions()
+ for dimension in self.accounting_dimensions:
+ dimension_fields.append('t1.{0}'.format(dimension))
- def get_pl_balances(self, dimension_fields):
- """Get balance for pl accounts"""
return frappe.db.sql("""
select
t1.account, t2.account_currency, {dimension_fields},
- sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as balance_in_account_currency,
- sum(t1.debit) - sum(t1.credit) as balance_in_company_currency
+ sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as bal_in_account_currency,
+ sum(t1.debit) - sum(t1.credit) as bal_in_company_currency
from `tabGL Entry` t1, `tabAccount` t2
where t1.account = t2.name and t2.report_type = 'Profit and Loss'
and t2.docstatus < 2 and t2.company = %s
diff --git a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
index eb02d97b78..2f29372b01 100644
--- a/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
+++ b/erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
@@ -8,6 +8,7 @@ import frappe
from frappe.utils import flt, today
from erpnext.accounts.utils import get_fiscal_year, now
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
+from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
class TestPeriodClosingVoucher(unittest.TestCase):
def test_closing_entry(self):
@@ -65,6 +66,58 @@ class TestPeriodClosingVoucher(unittest.TestCase):
self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency,
-1*random_expense_account[0].balance_in_account_currency)
+ def test_cost_center_wise_posting(self):
+ frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
+
+ company = create_company()
+ surplus_account = create_account()
+
+ cost_center1 = create_cost_center("Test Cost Center 1")
+ cost_center2 = create_cost_center("Test Cost Center 2")
+
+ create_sales_invoice(
+ company=company,
+ cost_center=cost_center1,
+ income_account="Sales - TPC",
+ expense_account="Cost of Goods Sold - TPC",
+ rate=400,
+ debit_to="Debtors - TPC"
+ )
+ create_sales_invoice(
+ company=company,
+ cost_center=cost_center2,
+ income_account="Sales - TPC",
+ expense_account="Cost of Goods Sold - TPC",
+ rate=200,
+ debit_to="Debtors - TPC"
+ )
+
+ pcv = frappe.get_doc({
+ "transaction_date": today(),
+ "posting_date": today(),
+ "fiscal_year": get_fiscal_year(today())[0],
+ "company": "Test PCV Company",
+ "cost_center_wise_pnl": 1,
+ "closing_account_head": surplus_account,
+ "remarks": "Test",
+ "doctype": "Period Closing Voucher"
+ })
+ pcv.insert()
+ pcv.submit()
+
+ expected_gle = (
+ ('Sales - TPC', 200.0, 0.0, cost_center2),
+ (surplus_account, 0.0, 200.0, cost_center2),
+ ('Sales - TPC', 400.0, 0.0, cost_center1),
+ (surplus_account, 0.0, 400.0, cost_center1)
+ )
+
+ pcv_gle = frappe.db.sql("""
+ select account, debit, credit, cost_center from `tabGL Entry` where voucher_no=%s
+ """, (pcv.name))
+
+ self.assertTrue(pcv_gle, expected_gle)
+
def make_period_closing_voucher(self):
pcv = frappe.get_doc({
"doctype": "Period Closing Voucher",
@@ -80,6 +133,38 @@ class TestPeriodClosingVoucher(unittest.TestCase):
return pcv
+def create_company():
+ company = frappe.get_doc({
+ 'doctype': 'Company',
+ 'company_name': "Test PCV Company",
+ 'country': 'United States',
+ 'default_currency': 'USD'
+ })
+ company.insert(ignore_if_duplicate = True)
+ return company.name
+
+def create_account():
+ account = frappe.get_doc({
+ "account_name": "Reserve and Surplus",
+ "is_group": 0,
+ "company": "Test PCV Company",
+ "root_type": "Liability",
+ "report_type": "Balance Sheet",
+ "account_currency": "USD",
+ "parent_account": "Current Liabilities - TPC",
+ "doctype": "Account"
+ }).insert(ignore_if_duplicate = True)
+ return account.name
+
+def create_cost_center(cc_name):
+ costcenter = frappe.get_doc({
+ "company": "Test PCV Company",
+ "cost_center_name": cc_name,
+ "doctype": "Cost Center",
+ "parent_cost_center": "Test PCV Company - TPC"
+ })
+ costcenter.insert(ignore_if_duplicate = True)
+ return costcenter.name
test_dependencies = ["Customer", "Cost Center"]
test_records = frappe.get_test_records("Period Closing Voucher")
From 911818a9e2101c63f7bdacc06a07f1c511ba1578 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Wed, 9 Jun 2021 22:55:10 +0530
Subject: [PATCH 198/262] fix: Add multiple fixes
---
.../advance_taxes_and_charges.json | 4 ++--
erpnext/accounts/doctype/payment_entry/payment_entry.js | 2 +-
erpnext/accounts/doctype/payment_entry/payment_entry.json | 7 +++++--
erpnext/accounts/doctype/payment_entry/payment_entry.py | 5 ++++-
.../accounts/doctype/purchase_invoice/purchase_invoice.py | 3 ---
.../doctype/purchase_invoice/test_purchase_invoice.py | 1 +
.../purchase_taxes_and_charges.json | 4 ++--
.../sales_taxes_and_charges/sales_taxes_and_charges.json | 4 ++--
erpnext/controllers/accounts_controller.py | 5 ++++-
9 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
index 3e4e679c91..4d63499431 100644
--- a/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
@@ -160,7 +160,7 @@
"default": "0",
"fieldname": "included_in_paid_amount",
"fieldtype": "Check",
- "label": "Included In Paid Amount"
+ "label": "Considered In Paid Amount"
},
{
"fieldname": "allocated_amount",
@@ -186,7 +186,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-06-08 07:04:44.287002",
+ "modified": "2021-06-09 11:46:58.373170",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 6a3b717b12..939f3546ff 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -1133,7 +1133,7 @@ frappe.ui.form.on('Payment Entry', {
let tax_rate = tax.rate;
if (tax.charge_type == "Actual") {
- current_tax_fraction = tax.tax_amount/frm.doc.paid_amount_after_tax;
+ current_tax_fraction = tax.tax_amount/(frm.doc.paid_amount_after_tax + frm.doc.tax_amount);
} else if(tax.charge_type == "On Paid Amount") {
current_tax_fraction = (tax_rate / 100.0);
} else if(tax.charge_type == "On Previous Row Amount") {
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json
index 0b4178a547..54623dd6cd 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.json
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json
@@ -681,13 +681,16 @@
"hide_border": 1
},
{
+ "depends_on": "eval:doc.apply_tax_withholding_amount",
+ "description": "Provisional tax account for advance tax. Taxes are parked in this account until payments are allocated to invoices",
"fieldname": "advance_tax_account",
"fieldtype": "Link",
"label": "Advance Tax Account",
- "mandatory_depends_on": "doc.base_total_taxes_and_charges",
+ "mandatory_depends_on": "eval:doc.apply_tax_withholding_amount",
"options": "Account"
},
{
+ "depends_on": "eval:doc.received_amount",
"fieldname": "received_amount_after_tax",
"fieldtype": "Currency",
"label": "Received Amount After Tax",
@@ -704,7 +707,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-05-31 01:54:18.378910",
+ "modified": "2021-06-09 11:55:04.215050",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index d04d6a0d15..edca210142 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -400,6 +400,9 @@ class PaymentEntry(AccountsController):
if not self.apply_tax_withholding_amount:
return
+ if not self.advance_tax_account:
+ frappe.throw(_("Advance TDS account is mandatory for advance TDS deduction"))
+
reference_doclist = []
net_total = self.paid_amount
included_in_paid_amount = 0
@@ -916,7 +919,7 @@ class PaymentEntry(AccountsController):
tax_rate = tax.rate
if tax.charge_type == 'Actual':
- current_tax_fraction = tax.tax_amount/self.paid_amount_after_tax
+ current_tax_fraction = tax.tax_amount/ (self.paid_amount_after_tax + tax.tax_amount)
elif tax.charge_type == "On Paid Amount":
current_tax_fraction = tax_rate / 100.0
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 934c731cf1..0ee0bc7e11 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -68,9 +68,6 @@ class PurchaseInvoice(BuyingController):
super(PurchaseInvoice, self).validate()
- # apply tax withholding only if checked and applicable
- self.set_tax_withholding()
-
if not self.is_return:
self.po_required()
self.pr_required()
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 8e72dc6321..fb4b8d4c1f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -975,6 +975,7 @@ class TestPurchaseInvoice(unittest.TestCase):
# Create Payment Entry Against the order
payment_entry = get_payment_entry(dt='Purchase Order', dn=po.name)
+ payment_entry.paid_from = 'Cash - _TC'
payment_entry.save()
payment_entry.submit()
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index f6703315fa..9b07645ccc 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -221,13 +221,13 @@
"description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
"fieldname": "included_in_paid_amount",
"fieldtype": "Check",
- "label": "Included In Paid Amount"
+ "label": "Considered In Paid Amount"
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2021-05-31 03:41:38.298937",
+ "modified": "2021-06-09 11:48:25.335733",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
index 36fd634b50..170d34e651 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
@@ -198,14 +198,14 @@
"description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
"fieldname": "included_in_paid_amount",
"fieldtype": "Check",
- "label": "Included In Paid Amount"
+ "label": "Considered In Paid Amount"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-05-31 05:40:32.856780",
+ "modified": "2021-06-09 11:48:04.691596",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index d8d0312ff6..53ded33b6f 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -116,6 +116,8 @@ class AccountsController(TransactionBase):
if self.doctype == 'Purchase Invoice':
self.calculate_paid_amount()
+ # apply tax withholding only if checked and applicable
+ self.set_tax_withholding()
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid"
@@ -742,7 +744,8 @@ class AccountsController(TransactionBase):
def allocate_advance_taxes(self, gl_entries):
tax_map = self.get_tax_map()
for pe in self.get("advances"):
- if pe.reference_type == "Payment Entry":
+ if pe.reference_type == "Payment Entry" and \
+ frappe.db.get_value('Payment Entry', pe.reference_name, 'advance_tax_account'):
pe = frappe.get_doc("Payment Entry", pe.reference_name)
for tax in pe.get("taxes"):
account_currency = get_account_currency(tax.account_head)
From 0b5fe1b5eb0fb24a4a37a6513e76f26b9a1f3bee Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 10 Jun 2021 10:34:49 +0530
Subject: [PATCH 199/262] fix: Failing test case
---
.../doctype/purchase_invoice/test_purchase_invoice.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index fb4b8d4c1f..c656c8aeec 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1009,8 +1009,8 @@ class TestPurchaseInvoice(unittest.TestCase):
['_Test Account Cost for Goods Sold - _TC', 30000, 0],
['_Test Account Excise Duty - _TC', 0, 3000],
['Creditors - _TC', 0, 27000],
- ['TDS Payable - _TC', 3000, 0]
- ['TDS Payable - _TC', 0, 3000],
+ ['TDS Payable - _TC', 3000, 0],
+ ['TDS Payable - _TC', 0, 3000]
]
gl_entries = frappe.db.sql("""select account, debit, credit
From 076bd5eaab52c9ad7805ff511787f8de045743b3 Mon Sep 17 00:00:00 2001
From: GangaManoj
Date: Thu, 10 Jun 2021 12:08:44 +0530
Subject: [PATCH 200/262] fix: Only display GST card in Accounting Workspace if
it's in India
---
.../workspace/accounting/accounting.json | 34 +++++++++++++------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json
index df68318052..10a4001502 100644
--- a/erpnext/accounts/workspace/accounting/accounting.json
+++ b/erpnext/accounts/workspace/accounting/accounting.json
@@ -445,15 +445,15 @@
"type": "Link"
},
{
- "dependencies": "GL Entry",
- "hidden": 0,
- "is_query_report": 1,
- "label": "UAE VAT 201",
- "link_to": "UAE VAT 201",
- "link_type": "Report",
- "onboard": 0,
- "type": "Link"
- },
+ "dependencies": "GL Entry",
+ "hidden": 0,
+ "is_query_report": 1,
+ "label": "UAE VAT 201",
+ "link_to": "UAE VAT 201",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
{
"hidden": 0,
"is_query_report": 0,
@@ -684,6 +684,7 @@
"is_query_report": 0,
"label": "Goods and Services Tax (GST India)",
"onboard": 0,
+ "only_for": "India",
"type": "Card Break"
},
{
@@ -694,6 +695,7 @@
"link_to": "GST Settings",
"link_type": "DocType",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -704,6 +706,7 @@
"link_to": "GST HSN Code",
"link_type": "DocType",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -714,6 +717,7 @@
"link_to": "GSTR-1",
"link_type": "Report",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -724,6 +728,7 @@
"link_to": "GSTR-2",
"link_type": "Report",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -734,6 +739,7 @@
"link_to": "GSTR 3B Report",
"link_type": "DocType",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -744,6 +750,7 @@
"link_to": "GST Sales Register",
"link_type": "Report",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -754,6 +761,7 @@
"link_to": "GST Purchase Register",
"link_type": "Report",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -764,6 +772,7 @@
"link_to": "GST Itemised Sales Register",
"link_type": "Report",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -774,6 +783,7 @@
"link_to": "GST Itemised Purchase Register",
"link_type": "Report",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -784,6 +794,7 @@
"link_to": "C-Form",
"link_type": "DocType",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -794,6 +805,7 @@
"link_to": "Lower Deduction Certificate",
"link_type": "DocType",
"onboard": 0,
+ "only_for": "India",
"type": "Link"
},
{
@@ -1052,7 +1064,7 @@
"type": "Link"
}
],
- "modified": "2021-05-12 11:48:01.905144",
+ "modified": "2021-06-10 03:17:31.427945",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting",
@@ -1107,4 +1119,4 @@
"type": "Dashboard"
}
]
-}
+}
\ No newline at end of file
From d063f9a5d185e9f481991b11c8fa8c0dcf9a39a5 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 10 Jun 2021 12:26:21 +0530
Subject: [PATCH 201/262] fix: GL Entry ordering
---
.../doctype/purchase_invoice/test_purchase_invoice.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index c656c8aeec..723d151ad8 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -1000,6 +1000,7 @@ class TestPurchaseInvoice(unittest.TestCase):
# Create Purchase Invoice against Purchase Order
purchase_invoice = get_mapped_purchase_invoice(po.name)
purchase_invoice.allocate_advances_automatically = 1
+ purchase_invoice.items[0].expense_account = '_Test Account Cost for Goods Sold - _TC'
purchase_invoice.save()
purchase_invoice.submit()
@@ -1009,8 +1010,7 @@ class TestPurchaseInvoice(unittest.TestCase):
['_Test Account Cost for Goods Sold - _TC', 30000, 0],
['_Test Account Excise Duty - _TC', 0, 3000],
['Creditors - _TC', 0, 27000],
- ['TDS Payable - _TC', 3000, 0],
- ['TDS Payable - _TC', 0, 3000]
+ ['TDS Payable - _TC', 3000, 3000]
]
gl_entries = frappe.db.sql("""select account, debit, credit
From aedf25ba46d20d8a7d40b6c77f880cfdc426cf90 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 11:44:40 +0530
Subject: [PATCH 202/262] chore: Drop old patches
v7 backup was restored and upgraded to latest v10.x.x branch. The
patches run uptil the upgrade are removed in this change. This means
only existing v10 sites are allowed direct upgrade to v13 and newer
---
erpnext/patches/repair_tools/__init__.py | 0
.../set_stock_balance_as_per_serial_no.py | 13 -
erpnext/patches/v10_0/__init__.py | 0
.../patches/v10_0/add_agriculture_domain.py | 13 -
.../add_guardian_role_for_parent_portal.py | 23 --
.../patches/v10_0/add_non_profit_domain.py | 20 --
.../allow_operators_in_supplier_scorecard.py | 23 --
.../v10_0/copy_projects_renamed_fields.py | 13 -
..._regional_print_format_based_on_country.py | 22 --
.../fix_reserved_qty_for_sub_contract.py | 31 ---
.../recalculate_gross_margin_for_project.py | 14 -
.../v10_0/rename_schools_to_education.py | 32 ---
...r_purchase_receipts_with_rejected_items.py | 32 ---
...t_requested_qty_for_non_stock_uom_items.py | 21 --
...t_auto_created_serial_no_in_stock_entry.py | 56 ----
erpnext/patches/v10_0/set_b2c_limit.py | 12 -
..._default_payment_terms_based_on_company.py | 37 ---
erpnext/patches/v10_0/set_discount_amount.py | 35 ---
...set_numeric_ranges_in_template_if_blank.py | 35 ---
.../v10_0/set_primary_contact_for_customer.py | 21 --
...n_transactions_based_on_serial_no_input.py | 21 --
.../patches/v10_0/set_student_party_type.py | 8 -
.../setup_vat_for_uae_and_saudi_arabia.py | 13 -
...s_of_all_department_members_in_calendar.py | 6 -
erpnext/patches/v10_0/taxes_issue_with_pos.py | 26 --
.../update_address_template_for_india.py | 12 -
.../patches/v10_0/update_assessment_plan.py | 17 --
.../patches/v10_0/update_assessment_result.py | 20 --
.../update_asset_calculate_depreciation.py | 12 -
.../v10_0/update_hub_connector_domain.py | 10 -
.../v10_0/update_lft_rgt_for_employee.py | 9 -
.../patches/v10_0/update_project_in_sle.py | 15 --
.../update_reserved_qty_for_purchase_order.py | 53 ----
...date_sales_order_link_to_purchase_order.py | 18 --
...update_status_for_multiple_source_in_po.py | 40 ---
.../update_status_in_purchase_receipt.py | 8 -
.../update_territory_and_customer_group.py | 29 ---
.../v10_0/update_user_image_in_employee.py | 19 --
.../v10_0/update_warehouse_address_details.py | 37 ---
erpnext/patches/v10_1/__init__.py | 0
erpnext/patches/v11_0/__init__.py | 1 -
.../v11_0/remove_subscriber_doctype.py | 16 --
erpnext/patches/v11_1/__init__.py | 0
erpnext/patches/v12_0/__init__.py | 0
erpnext/patches/v13_0/__init__.py | 1 -
erpnext/patches/v4_0/__init__.py | 0
.../patches/v4_0/apply_user_permissions.py | 50 ----
erpnext/patches/v4_0/countrywise_coa.py | 29 ---
...custom_fields_for_india_specific_fields.py | 63 -----
.../v4_0/create_price_list_if_missing.py | 35 ---
.../v4_0/customer_discount_to_pricing_rule.py | 33 ---
erpnext/patches/v4_0/fields_to_be_renamed.py | 109 --------
erpnext/patches/v4_0/fix_address_template.py | 12 -
.../patches/v4_0/fix_case_of_hr_module_def.py | 13 -
erpnext/patches/v4_0/fix_contact_address.py | 13 -
erpnext/patches/v4_0/fix_employee_user_id.py | 23 --
.../global_defaults_to_system_settings.py | 39 ---
erpnext/patches/v4_0/import_country_codes.py | 15 --
.../v4_0/map_charge_to_taxes_and_charges.py | 16 --
.../move_warehouse_user_to_restrictions.py | 13 -
erpnext/patches/v4_0/new_address_template.py | 14 -
.../patches/v4_0/reload_sales_print_format.py | 8 -
.../remove_employee_role_if_no_employee.py | 18 --
.../patches/v4_0/remove_module_home_pages.py | 10 -
.../patches/v4_0/rename_sitemap_to_route.py | 17 --
.../v4_0/reset_permissions_for_masters.py | 20 --
.../patches/v4_0/save_default_letterhead.py | 13 -
.../set_pricing_rule_for_buying_or_selling.py | 13 -
erpnext/patches/v4_0/split_email_settings.py | 67 -----
.../patches/v4_0/update_account_root_type.py | 34 ---
...custom_print_formats_for_renamed_fields.py | 36 ---
...to_sales_person_in_maintenance_schedule.py | 12 -
...harges_in_custom_purchase_print_formats.py | 12 -
.../v4_0/update_tax_amount_after_discount.py | 20 --
.../patches/v4_0/update_user_properties.py | 51 ----
.../v4_0/update_users_report_view_settings.py | 12 -
erpnext/patches/v4_0/validate_v3_patch.py | 11 -
erpnext/patches/v4_1/__init__.py | 0
.../v4_1/fix_delivery_and_billing_status.py | 12 -
erpnext/patches/v4_1/fix_jv_remarks.py | 21 --
.../v4_1/fix_sales_order_delivered_status.py | 15 --
.../patches/v4_1/set_outgoing_email_footer.py | 12 -
erpnext/patches/v4_2/__init__.py | 0
.../patches/v4_2/add_currency_turkish_lira.py | 10 -
erpnext/patches/v4_2/default_website_style.py | 11 -
...elete_gl_entries_for_cancelled_invoices.py | 14 -
.../patches/v4_2/delete_old_print_formats.py | 23 --
erpnext/patches/v4_2/discount_amount.py | 12 -
.../patches/v4_2/fix_account_master_type.py | 12 -
.../fix_gl_entries_for_stock_transactions.py | 54 ----
erpnext/patches/v4_2/fix_recurring_orders.py | 41 ---
erpnext/patches/v4_2/party_model.py | 117 ---------
erpnext/patches/v4_2/recalculate_bom_cost.py | 16 --
.../repost_sle_for_si_with_no_warehouse.py | 34 ---
.../v4_2/repost_stock_reconciliation.py | 31 ---
erpnext/patches/v4_2/reset_bom_costs.py | 17 --
.../v4_2/seprate_manufacture_and_repack.py | 9 -
erpnext/patches/v4_2/set_company_country.py | 15 --
erpnext/patches/v4_2/set_item_has_batch.py | 65 -----
erpnext/patches/v4_2/toggle_rounded_total.py | 9 -
.../v4_2/update_landed_cost_voucher.py | 10 -
.../patches/v4_2/update_project_milestones.py | 9 -
.../update_sales_order_invoice_field_name.py | 7 -
.../v4_2/update_stock_uom_for_dn_in_sle.py | 11 -
erpnext/patches/v4_4/__init__.py | 0
erpnext/patches/v4_4/make_email_accounts.py | 96 -------
erpnext/patches/v5_0/__init__.py | 0
.../v5_0/convert_stock_reconciliation.py | 31 ---
.../patches/v5_0/execute_on_doctype_update.py | 9 -
.../fix_taxes_and_totals_in_party_currency.py | 66 -----
.../v5_0/index_on_account_and_gl_entry.py | 30 ---
erpnext/patches/v5_0/is_group.py | 9 -
erpnext/patches/v5_0/item_patches.py | 6 -
.../v5_0/link_warehouse_with_account.py | 10 -
erpnext/patches/v5_0/new_crm_module.py | 24 --
erpnext/patches/v5_0/newsletter.py | 38 ---
.../v5_0/opportunity_not_submittable.py | 10 -
erpnext/patches/v5_0/party_model_patch_fix.py | 18 --
erpnext/patches/v5_0/portal_fixes.py | 7 -
erpnext/patches/v5_0/project_costing.py | 8 -
.../v5_0/recalculate_total_amount_in_jv.py | 26 --
...nned_operating_cost_in_production_order.py | 13 -
.../patches/v5_0/remove_birthday_events.py | 7 -
erpnext/patches/v5_0/rename_customer_issue.py | 6 -
erpnext/patches/v5_0/rename_pos_setting.py | 6 -
.../patches/v5_0/rename_table_fieldnames.py | 243 ------------------
.../v5_0/rename_taxes_and_charges_master.py | 14 -
erpnext/patches/v5_0/rename_total_fields.py | 55 ----
...lds_in_custom_scripts_and_print_formats.py | 65 -----
.../repost_gle_for_jv_with_multiple_party.py | 26 --
erpnext/patches/v5_0/repost_requested_qty.py | 21 --
erpnext/patches/v5_0/reset_values_in_tools.py | 12 -
erpnext/patches/v5_0/set_appraisal_remarks.py | 9 -
.../v5_0/set_default_company_in_bom.py | 10 -
erpnext/patches/v5_0/set_footer_address.py | 9 -
.../patches/v5_0/stock_entry_update_value.py | 8 -
.../taxes_and_totals_in_party_currency.py | 80 ------
erpnext/patches/v5_0/update_account_types.py | 20 --
erpnext/patches/v5_0/update_advance_paid.py | 13 -
.../update_companywise_payment_account.py | 21 --
.../v5_0/update_dn_against_doc_fields.py | 14 -
erpnext/patches/v5_0/update_from_bom.py | 9 -
.../update_frozen_accounts_permission_role.py | 13 -
.../v5_0/update_item_and_description_again.py | 50 ----
.../v5_0/update_item_desc_in_invoice.py | 52 ----
.../v5_0/update_item_description_and_image.py | 54 ----
.../patches/v5_0/update_item_name_in_bom.py | 18 --
.../v5_0/update_journal_entry_title.py | 12 -
...pdate_material_transfer_for_manufacture.py | 6 -
..._material_transferred_for_manufacturing.py | 10 -
...ial_transferred_for_manufacturing_again.py | 19 --
.../v5_0/update_operation_description.py | 11 -
erpnext/patches/v5_0/update_opportunity.py | 14 -
erpnext/patches/v5_0/update_projects.py | 34 ---
erpnext/patches/v5_0/update_sms_sender.py | 9 -
...amount_after_discount_in_purchase_cycle.py | 17 --
.../patches/v5_0/update_temporary_account.py | 9 -
erpnext/patches/v5_0/update_time_log_title.py | 12 -
erpnext/patches/v5_1/__init__.py | 0
erpnext/patches/v5_1/default_bom.py | 7 -
erpnext/patches/v5_1/fix_against_account.py | 37 ---
erpnext/patches/v5_1/rename_roles.py | 10 -
erpnext/patches/v5_1/sales_bom_rename.py | 12 -
erpnext/patches/v5_2/__init__.py | 1 -
.../v5_2/change_item_selects_to_checks.py | 19 --
erpnext/patches/v5_4/__init__.py | 0
erpnext/patches/v5_4/cleanup_journal_entry.py | 21 --
.../patches/v5_4/fix_invoice_outstanding.py | 13 -
.../patches/v5_4/fix_missing_item_images.py | 126 ---------
...x_reserved_qty_and_sle_for_packed_items.py | 22 --
...anagers_regarding_wrong_tax_calculation.py | 41 ---
.../patches/v5_4/set_root_and_report_type.py | 12 -
.../v5_4/stock_entry_additional_costs.py | 53 ----
.../update_purchase_cost_against_project.py | 13 -
erpnext/patches/v5_7/__init__.py | 1 -
.../patches/v5_7/item_template_attributes.py | 124 ---------
erpnext/patches/v5_8/__init__.py | 1 -
.../v5_8/add_credit_note_print_heading.py | 14 -
erpnext/patches/v5_8/tax_rule.py | 31 ---
...pdate_order_reference_in_return_entries.py | 92 -------
erpnext/patches/v6_0/__init__.py | 0
erpnext/patches/v6_0/default_activity_rate.py | 14 -
.../patches/v6_0/fix_outstanding_amount.py | 16 --
erpnext/patches/v6_0/fix_planned_qty.py | 14 -
erpnext/patches/v6_0/multi_currency.py | 65 -----
erpnext/patches/v6_0/set_default_title.py | 36 ---
erpnext/patches/v6_10/__init__.py | 1 -
.../v6_10/email_digest_default_quote.py | 6 -
.../fix_billed_amount_in_drop_ship_po.py | 18 --
.../fix_delivery_status_of_drop_ship_item.py | 10 -
erpnext/patches/v6_10/fix_jv_total_amount.py | 14 -
.../v6_10/fix_ordered_received_billed.py | 17 --
erpnext/patches/v6_12/__init__.py | 0
.../repost_entries_with_target_warehouse.py | 175 -------------
erpnext/patches/v6_12/set_overdue_tasks.py | 8 -
erpnext/patches/v6_16/__init__.py | 1 -
.../v6_16/create_manufacturer_records.py | 19 --
.../update_billing_status_in_dn_and_pr.py | 42 ---
erpnext/patches/v6_19/__init__.py | 1 -
.../v6_19/comment_feed_communication.py | 7 -
erpnext/patches/v6_2/__init__.py | 1 -
.../fix_missing_default_taxes_and_lead.py | 25 --
.../v6_2/remove_newsletter_duplicates.py | 13 -
erpnext/patches/v6_20/__init__.py | 0
.../set_party_account_currency_in_orders.py | 24 --
erpnext/patches/v6_20x/__init__.py | 1 -
.../v6_20x/remove_customer_supplier_roles.py | 23 --
.../remove_fiscal_year_from_holiday_list.py | 19 --
.../v6_20x/rename_project_name_to_project.py | 17 --
...t_valuation_rate_for_negative_inventory.py | 11 -
erpnext/patches/v6_20x/set_compact_print.py | 8 -
.../update_product_bundle_description.py | 11 -
erpnext/patches/v6_21/__init__.py | 1 -
erpnext/patches/v6_21/fix_reorder_level.py | 24 --
.../v6_21/rename_material_request_fields.py | 14 -
erpnext/patches/v6_23/__init__.py | 0
.../v6_23/update_stopped_status_to_closed.py | 9 -
erpnext/patches/v6_24/__init__.py | 0
...tomer_address_to_shipping_address_on_po.py | 19 --
erpnext/patches/v6_24/set_recurring_id.py | 13 -
erpnext/patches/v6_27/__init__.py | 1 -
.../v6_27/fix_recurring_order_status.py | 54 ----
erpnext/patches/v6_3/__init__.py | 0
.../v6_3/convert_applicable_territory.py | 24 --
erpnext/patches/v6_4/__init__.py | 1 -
erpnext/patches/v6_4/email_digest_update.py | 10 -
erpnext/patches/v6_4/fix_duplicate_bins.py | 20 --
.../v6_4/fix_expense_included_in_valuation.py | 74 ------
...x_journal_entries_due_to_reconciliation.py | 53 ----
...ified_in_sales_order_and_purchase_order.py | 10 -
.../fix_sales_order_maintenance_status.py | 8 -
.../fix_status_in_sales_and_purchase_order.py | 8 -
erpnext/patches/v6_4/make_image_thumbnail.py | 15 --
...al_entries_where_reference_name_missing.py | 23 --
.../v6_4/round_status_updater_percentages.py | 14 -
erpnext/patches/v6_4/set_user_in_contact.py | 7 -
erpnext/patches/v6_5/__init__.py | 1 -
.../v6_5/show_in_website_for_template_item.py | 15 --
erpnext/patches/v6_6/__init__.py | 1 -
erpnext/patches/v6_6/fix_website_image.py | 32 ---
...emove_fiscal_year_from_leave_allocation.py | 17 --
erpnext/patches/v6_8/__init__.py | 0
erpnext/patches/v6_8/make_webform_standard.py | 14 -
.../v6_8/move_drop_ship_to_po_items.py | 43 ----
erpnext/patches/v7_0/__init__.py | 0
.../v7_0/calculate_total_costing_amount.py | 18 --
.../v7_0/convert_timelog_to_timesheet.py | 69 -----
.../v7_0/convert_timelogbatch_to_timesheet.py | 32 ---
erpnext/patches/v7_0/create_budget_record.py | 57 ----
.../v7_0/create_warehouse_nestedset.py | 128 ---------
erpnext/patches/v7_0/fix_duplicate_icons.py | 27 --
...ouse_ledger_gl_entries_for_transactions.py | 51 ----
erpnext/patches/v7_0/make_guardian.py | 37 ---
.../v7_0/make_is_group_fieldtype_as_check.py | 18 --
...count_type_stock_and_warehouse_to_stock.py | 10 -
.../v7_0/migrate_mode_of_payments_v6_to_v7.py | 38 ---
.../v7_0/migrate_schools_to_erpnext.py | 30 ---
...lesinvoiceitem_to_salesinvoicetimesheet.py | 17 --
.../v7_0/po_status_issue_for_pr_return.py | 40 ---
erpnext/patches/v7_0/re_route.py | 5 -
.../remove_administrator_role_in_doctypes.py | 9 -
.../v7_0/remove_doctypes_and_reports.py | 27 --
erpnext/patches/v7_0/remove_features_setup.py | 29 ---
.../remove_old_earning_deduction_doctypes.py | 16 --
.../v7_0/rename_advance_table_fields.py | 18 --
.../v7_0/rename_examination_to_assessment.py | 24 --
.../rename_fee_amount_to_fee_component.py | 16 --
erpnext/patches/v7_0/rename_prevdoc_fields.py | 76 ------
.../patches/v7_0/rename_salary_components.py | 149 -----------
.../patches/v7_0/rename_time_sheet_doctype.py | 14 -
.../repost_bin_qty_and_item_projected_qty.py | 15 --
.../repost_gle_for_pi_with_update_stock.py | 20 --
.../v7_0/repost_gle_for_pos_sales_return.py | 25 --
...et_base_amount_in_invoice_payment_table.py | 24 --
.../v7_0/set_is_group_for_warehouse.py | 7 -
.../v7_0/set_material_request_type_in_item.py | 16 --
.../v7_0/set_naming_series_for_timesheet.py | 15 --
.../v7_0/set_party_name_in_payment_entry.py | 20 --
erpnext/patches/v7_0/set_portal_settings.py | 28 --
..._table_for_expense_claim_type_if_exists.py | 20 --
.../v7_0/system_settings_setup_complete.py | 16 --
erpnext/patches/v7_0/update_autoname_field.py | 14 -
.../v7_0/update_change_amount_account.py | 19 --
...rsion_factor_in_supplier_quotation_item.py | 19 --
erpnext/patches/v7_0/update_home_page.py | 27 --
.../update_maintenance_module_in_doctype.py | 11 -
.../v7_0/update_mins_to_first_response.py | 24 --
.../update_missing_employee_in_timesheet.py | 20 --
.../v7_0/update_mode_of_payment_type.py | 29 ---
erpnext/patches/v7_0/update_party_status.py | 21 --
...vdoc_values_for_supplier_quotation_item.py | 9 -
.../v7_0/update_project_in_gl_entry.py | 21 --
.../update_refdoc_in_landed_cost_voucher.py | 15 --
.../v7_0/update_status_for_timesheet.py | 11 -
.../patches/v7_0/update_status_of_po_so.py | 68 -----
...pdate_status_of_zero_amount_sales_order.py | 7 -
.../v7_0/update_timesheet_communications.py | 27 --
erpnext/patches/v7_1/__init__.py | 1 -
.../add_account_user_role_for_timesheet.py | 31 ---
.../v7_1/add_field_for_task_dependent.py | 10 -
.../v7_1/fix_link_for_customer_from_lead.py | 7 -
..._invoice_from_parent_to_child_timesheet.py | 20 --
.../patches/v7_1/rename_field_timesheet.py | 11 -
.../v7_1/rename_quality_inspection_field.py | 38 ---
...tock_for_deleted_bins_for_merging_items.py | 44 ----
erpnext/patches/v7_1/save_stock_settings.py | 15 --
.../v7_1/set_budget_against_as_cost_center.py | 11 -
.../v7_1/set_currency_exchange_date.py | 10 -
.../v7_1/set_prefered_contact_email.py | 17 --
.../patches/v7_1/set_sales_person_status.py | 8 -
erpnext/patches/v7_1/set_student_guardian.py | 23 --
.../v7_1/set_total_amount_currency_in_je.py | 24 --
.../patches/v7_1/update_bom_base_currency.py | 20 --
erpnext/patches/v7_1/update_component_type.py | 15 --
erpnext/patches/v7_1/update_invoice_status.py | 34 ---
erpnext/patches/v7_1/update_lead_source.py | 29 ---
.../update_missing_salary_component_type.py | 50 ----
erpnext/patches/v7_1/update_portal_roles.py | 21 --
.../v7_1/update_total_billing_hours.py | 14 -
erpnext/patches/v7_2/__init__.py | 1 -
...ar_leave_encashment_as_salary_component.py | 36 ---
erpnext/patches/v7_2/contact_address_links.py | 32 ---
.../delete_fleet_management_module_def.py | 10 -
...ty_supplied_items_for_non_subcontracted.py | 14 -
.../patches/v7_2/make_all_assessment_group.py | 14 -
erpnext/patches/v7_2/mark_students_active.py | 9 -
.../v7_2/rename_att_date_attendance.py | 15 --
.../v7_2/rename_evaluation_criteria.py | 39 ---
.../patches/v7_2/set_null_value_to_fields.py | 11 -
.../patches/v7_2/setup_auto_close_settings.py | 18 --
erpnext/patches/v7_2/stock_uom_in_selling.py | 15 --
.../v7_2/update_abbr_in_salary_slips.py | 14 -
.../patches/v7_2/update_assessment_modules.py | 51 ----
.../v7_2/update_attendance_docstatus.py | 10 -
erpnext/patches/v7_2/update_doctype_status.py | 11 -
.../update_guardian_name_in_student_master.py | 14 -
erpnext/patches/v7_2/update_party_type.py | 16 --
erpnext/patches/v7_2/update_salary_slips.py | 22 --
.../v7_2/update_website_for_variant.py | 13 -
erpnext/patches/v8_0/__init__.py | 1 -
.../patches/v8_0/addresses_linked_to_lead.py | 5 -
.../v8_0/change_in_words_varchar_length.py | 16 --
...dress_doc_from_address_field_in_company.py | 33 ---
erpnext/patches/v8_0/create_domain_docs.py | 53 ----
erpnext/patches/v8_0/delete_bin_indexes.py | 16 --
.../delete_schools_depricated_doctypes.py | 14 -
.../patches/v8_0/disable_instructor_role.py | 18 --
...ooking_asset_depreciation_automatically.py | 9 -
..._for_invoices_with_negative_outstanding.py | 23 --
...ayments_table_blank_for_non_pos_invoice.py | 15 --
.../merge_student_batch_and_student_group.py | 73 ------
...from_account_to_warehouse_for_inventory.py | 15 --
.../v8_0/move_perpetual_inventory_setting.py | 13 -
...ample_item_to_allow_zero_valuation_rate.py | 13 -
...ems_in_status_field_of_material_request.py | 25 --
...rename_total_margin_to_rate_with_margin.py | 24 --
...ost_reserved_qty_for_multiple_sales_uom.py | 19 --
.../revert_manufacturers_table_from_item.py | 22 --
erpnext/patches/v8_0/save_system_settings.py | 20 --
..._serial_nos_for_disabled_sales_invoices.py | 14 -
.../patches/v8_0/set_project_copied_from.py | 11 -
...nvoice_serial_number_from_delivery_note.py | 42 ---
.../patches/v8_0/update_customer_pos_id.py | 9 -
.../patches/v8_0/update_production_orders.py | 49 ----
.../v8_0/update_sales_cost_in_project.py | 11 -
...tus_as_paid_for_completed_expense_claim.py | 19 --
.../update_stock_qty_value_in_bom_item.py | 14 -
...ate_stock_qty_value_in_purchase_invoice.py | 9 -
...ate_student_groups_from_student_batches.py | 38 ---
.../update_supplier_address_in_stock_entry.py | 22 --
erpnext/patches/v8_1/__init__.py | 0
erpnext/patches/v8_1/add_hsn_sac_codes.py | 11 -
.../add_indexes_in_transaction_doctypes.py | 10 -
...allow_invoice_copy_to_edit_after_submit.py | 13 -
.../patches/v8_1/delete_deprecated_reports.py | 33 ---
erpnext/patches/v8_1/gst_fixes.py | 62 -----
...e_sales_invoice_from_returned_serial_no.py | 18 --
.../v8_1/removed_report_support_hours.py | 14 -
.../v8_1/set_delivery_date_in_so_item.py | 22 --
.../v8_1/update_expense_claim_status.py | 23 --
erpnext/patches/v8_1/update_gst_state.py | 15 --
erpnext/patches/v8_10/__init__.py | 0
.../change_default_customer_credit_days.py | 89 -------
erpnext/patches/v8_3/__init__.py | 0
.../set_restrict_to_domain_for_module_def.py | 9 -
.../v8_3/update_company_total_sales.py | 15 --
erpnext/patches/v8_4/__init__.py | 1 -
.../patches/v8_4/make_scorecard_records.py | 11 -
erpnext/patches/v8_5/__init__.py | 0
.../fix_tax_breakup_for_non_invoice_docs.py | 48 ----
.../remove_project_type_property_setter.py | 18 --
.../remove_quotations_route_in_sidebar.py | 16 --
.../v8_5/set_default_mode_of_payment.py | 17 --
.../update_customer_group_in_POS_profile.py | 9 -
.../update_existing_data_in_project_type.py | 19 --
erpnext/patches/v8_6/__init__.py | 0
...point_sms_doctype_module_to_frappe_core.py | 9 -
.../patches/v8_6/rename_bom_update_tool.py | 9 -
...mission_for_quotation_for_sales_manager.py | 11 -
.../v8_6/update_timesheet_company_from_PO.py | 15 --
erpnext/patches/v8_7/__init__.py | 0
.../v8_7/fix_purchase_receipt_status.py | 13 -
.../make_subscription_from_recurring_data.py | 58 -----
erpnext/patches/v8_8/__init__.py | 0
.../add_new_fields_in_accounts_settings.py | 9 -
.../patches/v8_8/set_bom_rate_as_per_uom.py | 13 -
erpnext/patches/v8_9/__init__.py | 1 -
.../v8_9/add_setup_progress_actions.py | 47 ----
...gst_doctypes_for_outside_india_accounts.py | 14 -
...e_employee_from_salary_structure_parent.py | 6 -
.../v8_9/rename_company_sales_target_field.py | 8 -
.../v8_9/set_default_customer_group.py | 8 -
.../set_default_fields_in_variant_settings.py | 13 -
erpnext/patches/v8_9/set_member_party_type.py | 9 -
.../v8_9/set_print_zero_amount_taxes.py | 9 -
...update_billing_gstin_for_indian_account.py | 15 --
erpnext/patches/v9_0/__init__.py | 1 -
erpnext/patches/v9_0/add_healthcare_domain.py | 13 -
.../add_user_to_child_table_in_pos_profile.py | 38 ---
.../patches/v9_0/copy_old_fees_field_data.py | 15 --
..._existing_warehouse_from_stock_settings.py | 8 -
.../v9_0/remove_subscription_module.py | 9 -
.../v9_0/revert_manufacturing_user_role.py | 22 --
erpnext/patches/v9_0/set_pos_profile_name.py | 24 --
...for_material_request_and_purchase_order.py | 24 --
...ipping_type_for_existing_shipping_rules.py | 18 --
.../patches/v9_0/set_uoms_in_variant_field.py | 14 -
.../v9_0/set_variant_item_description.py | 46 ----
.../student_admission_childtable_migrate.py | 31 ---
.../v9_0/update_employee_loan_details.py | 24 --
...te_multi_uom_fields_in_material_request.py | 12 -
erpnext/patches/v9_1/__init__.py | 0
.../v9_1/create_issue_opportunity_type.py | 34 ---
erpnext/patches/v9_2/__init__.py | 0
.../delete_healthcare_domain_default_items.py | 17 --
.../patches/v9_2/delete_process_payroll.py | 5 -
.../v9_2/remove_company_from_patient.py | 7 -
.../v9_2/rename_net_weight_in_item_master.py | 8 -
.../v9_2/rename_translated_domains_in_en.py | 39 ---
.../repost_reserved_qty_for_production.py | 9 -
.../v9_2/set_item_name_in_production_order.py | 12 -
441 files changed, 9599 deletions(-)
delete mode 100644 erpnext/patches/repair_tools/__init__.py
delete mode 100644 erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py
delete mode 100644 erpnext/patches/v10_0/__init__.py
delete mode 100644 erpnext/patches/v10_0/add_agriculture_domain.py
delete mode 100644 erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py
delete mode 100644 erpnext/patches/v10_0/add_non_profit_domain.py
delete mode 100644 erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py
delete mode 100644 erpnext/patches/v10_0/copy_projects_renamed_fields.py
delete mode 100644 erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py
delete mode 100644 erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
delete mode 100644 erpnext/patches/v10_0/recalculate_gross_margin_for_project.py
delete mode 100644 erpnext/patches/v10_0/rename_schools_to_education.py
delete mode 100644 erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
delete mode 100644 erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py
delete mode 100644 erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py
delete mode 100644 erpnext/patches/v10_0/set_b2c_limit.py
delete mode 100644 erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py
delete mode 100644 erpnext/patches/v10_0/set_discount_amount.py
delete mode 100644 erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py
delete mode 100644 erpnext/patches/v10_0/set_primary_contact_for_customer.py
delete mode 100644 erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py
delete mode 100644 erpnext/patches/v10_0/set_student_party_type.py
delete mode 100644 erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py
delete mode 100644 erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py
delete mode 100644 erpnext/patches/v10_0/taxes_issue_with_pos.py
delete mode 100644 erpnext/patches/v10_0/update_address_template_for_india.py
delete mode 100644 erpnext/patches/v10_0/update_assessment_plan.py
delete mode 100644 erpnext/patches/v10_0/update_assessment_result.py
delete mode 100644 erpnext/patches/v10_0/update_asset_calculate_depreciation.py
delete mode 100644 erpnext/patches/v10_0/update_hub_connector_domain.py
delete mode 100644 erpnext/patches/v10_0/update_lft_rgt_for_employee.py
delete mode 100644 erpnext/patches/v10_0/update_project_in_sle.py
delete mode 100644 erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py
delete mode 100644 erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py
delete mode 100644 erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py
delete mode 100644 erpnext/patches/v10_0/update_status_in_purchase_receipt.py
delete mode 100644 erpnext/patches/v10_0/update_territory_and_customer_group.py
delete mode 100644 erpnext/patches/v10_0/update_user_image_in_employee.py
delete mode 100644 erpnext/patches/v10_0/update_warehouse_address_details.py
delete mode 100644 erpnext/patches/v10_1/__init__.py
delete mode 100644 erpnext/patches/v11_0/__init__.py
delete mode 100644 erpnext/patches/v11_0/remove_subscriber_doctype.py
delete mode 100644 erpnext/patches/v11_1/__init__.py
delete mode 100644 erpnext/patches/v12_0/__init__.py
delete mode 100644 erpnext/patches/v13_0/__init__.py
delete mode 100644 erpnext/patches/v4_0/__init__.py
delete mode 100644 erpnext/patches/v4_0/apply_user_permissions.py
delete mode 100644 erpnext/patches/v4_0/countrywise_coa.py
delete mode 100644 erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py
delete mode 100644 erpnext/patches/v4_0/create_price_list_if_missing.py
delete mode 100644 erpnext/patches/v4_0/customer_discount_to_pricing_rule.py
delete mode 100644 erpnext/patches/v4_0/fields_to_be_renamed.py
delete mode 100644 erpnext/patches/v4_0/fix_address_template.py
delete mode 100644 erpnext/patches/v4_0/fix_case_of_hr_module_def.py
delete mode 100644 erpnext/patches/v4_0/fix_contact_address.py
delete mode 100644 erpnext/patches/v4_0/fix_employee_user_id.py
delete mode 100644 erpnext/patches/v4_0/global_defaults_to_system_settings.py
delete mode 100644 erpnext/patches/v4_0/import_country_codes.py
delete mode 100644 erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py
delete mode 100644 erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
delete mode 100644 erpnext/patches/v4_0/new_address_template.py
delete mode 100644 erpnext/patches/v4_0/reload_sales_print_format.py
delete mode 100644 erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
delete mode 100644 erpnext/patches/v4_0/remove_module_home_pages.py
delete mode 100644 erpnext/patches/v4_0/rename_sitemap_to_route.py
delete mode 100644 erpnext/patches/v4_0/reset_permissions_for_masters.py
delete mode 100644 erpnext/patches/v4_0/save_default_letterhead.py
delete mode 100644 erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
delete mode 100644 erpnext/patches/v4_0/split_email_settings.py
delete mode 100644 erpnext/patches/v4_0/update_account_root_type.py
delete mode 100644 erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py
delete mode 100644 erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py
delete mode 100644 erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py
delete mode 100644 erpnext/patches/v4_0/update_tax_amount_after_discount.py
delete mode 100644 erpnext/patches/v4_0/update_user_properties.py
delete mode 100644 erpnext/patches/v4_0/update_users_report_view_settings.py
delete mode 100644 erpnext/patches/v4_0/validate_v3_patch.py
delete mode 100644 erpnext/patches/v4_1/__init__.py
delete mode 100644 erpnext/patches/v4_1/fix_delivery_and_billing_status.py
delete mode 100644 erpnext/patches/v4_1/fix_jv_remarks.py
delete mode 100644 erpnext/patches/v4_1/fix_sales_order_delivered_status.py
delete mode 100644 erpnext/patches/v4_1/set_outgoing_email_footer.py
delete mode 100644 erpnext/patches/v4_2/__init__.py
delete mode 100644 erpnext/patches/v4_2/add_currency_turkish_lira.py
delete mode 100644 erpnext/patches/v4_2/default_website_style.py
delete mode 100644 erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
delete mode 100644 erpnext/patches/v4_2/delete_old_print_formats.py
delete mode 100644 erpnext/patches/v4_2/discount_amount.py
delete mode 100644 erpnext/patches/v4_2/fix_account_master_type.py
delete mode 100644 erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
delete mode 100644 erpnext/patches/v4_2/fix_recurring_orders.py
delete mode 100644 erpnext/patches/v4_2/party_model.py
delete mode 100644 erpnext/patches/v4_2/recalculate_bom_cost.py
delete mode 100644 erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
delete mode 100644 erpnext/patches/v4_2/repost_stock_reconciliation.py
delete mode 100644 erpnext/patches/v4_2/reset_bom_costs.py
delete mode 100644 erpnext/patches/v4_2/seprate_manufacture_and_repack.py
delete mode 100644 erpnext/patches/v4_2/set_company_country.py
delete mode 100644 erpnext/patches/v4_2/set_item_has_batch.py
delete mode 100644 erpnext/patches/v4_2/toggle_rounded_total.py
delete mode 100644 erpnext/patches/v4_2/update_landed_cost_voucher.py
delete mode 100644 erpnext/patches/v4_2/update_project_milestones.py
delete mode 100644 erpnext/patches/v4_2/update_sales_order_invoice_field_name.py
delete mode 100644 erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py
delete mode 100644 erpnext/patches/v4_4/__init__.py
delete mode 100644 erpnext/patches/v4_4/make_email_accounts.py
delete mode 100644 erpnext/patches/v5_0/__init__.py
delete mode 100644 erpnext/patches/v5_0/convert_stock_reconciliation.py
delete mode 100644 erpnext/patches/v5_0/execute_on_doctype_update.py
delete mode 100644 erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py
delete mode 100644 erpnext/patches/v5_0/index_on_account_and_gl_entry.py
delete mode 100644 erpnext/patches/v5_0/is_group.py
delete mode 100644 erpnext/patches/v5_0/item_patches.py
delete mode 100644 erpnext/patches/v5_0/link_warehouse_with_account.py
delete mode 100644 erpnext/patches/v5_0/new_crm_module.py
delete mode 100644 erpnext/patches/v5_0/newsletter.py
delete mode 100644 erpnext/patches/v5_0/opportunity_not_submittable.py
delete mode 100644 erpnext/patches/v5_0/party_model_patch_fix.py
delete mode 100644 erpnext/patches/v5_0/portal_fixes.py
delete mode 100644 erpnext/patches/v5_0/project_costing.py
delete mode 100644 erpnext/patches/v5_0/recalculate_total_amount_in_jv.py
delete mode 100644 erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py
delete mode 100644 erpnext/patches/v5_0/remove_birthday_events.py
delete mode 100644 erpnext/patches/v5_0/rename_customer_issue.py
delete mode 100644 erpnext/patches/v5_0/rename_pos_setting.py
delete mode 100644 erpnext/patches/v5_0/rename_table_fieldnames.py
delete mode 100644 erpnext/patches/v5_0/rename_taxes_and_charges_master.py
delete mode 100644 erpnext/patches/v5_0/rename_total_fields.py
delete mode 100644 erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py
delete mode 100644 erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
delete mode 100644 erpnext/patches/v5_0/repost_requested_qty.py
delete mode 100644 erpnext/patches/v5_0/reset_values_in_tools.py
delete mode 100644 erpnext/patches/v5_0/set_appraisal_remarks.py
delete mode 100644 erpnext/patches/v5_0/set_default_company_in_bom.py
delete mode 100644 erpnext/patches/v5_0/set_footer_address.py
delete mode 100644 erpnext/patches/v5_0/stock_entry_update_value.py
delete mode 100644 erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py
delete mode 100644 erpnext/patches/v5_0/update_account_types.py
delete mode 100644 erpnext/patches/v5_0/update_advance_paid.py
delete mode 100644 erpnext/patches/v5_0/update_companywise_payment_account.py
delete mode 100644 erpnext/patches/v5_0/update_dn_against_doc_fields.py
delete mode 100644 erpnext/patches/v5_0/update_from_bom.py
delete mode 100644 erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
delete mode 100644 erpnext/patches/v5_0/update_item_and_description_again.py
delete mode 100644 erpnext/patches/v5_0/update_item_desc_in_invoice.py
delete mode 100644 erpnext/patches/v5_0/update_item_description_and_image.py
delete mode 100644 erpnext/patches/v5_0/update_item_name_in_bom.py
delete mode 100644 erpnext/patches/v5_0/update_journal_entry_title.py
delete mode 100644 erpnext/patches/v5_0/update_material_transfer_for_manufacture.py
delete mode 100644 erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py
delete mode 100644 erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py
delete mode 100644 erpnext/patches/v5_0/update_operation_description.py
delete mode 100644 erpnext/patches/v5_0/update_opportunity.py
delete mode 100644 erpnext/patches/v5_0/update_projects.py
delete mode 100644 erpnext/patches/v5_0/update_sms_sender.py
delete mode 100644 erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py
delete mode 100644 erpnext/patches/v5_0/update_temporary_account.py
delete mode 100644 erpnext/patches/v5_0/update_time_log_title.py
delete mode 100644 erpnext/patches/v5_1/__init__.py
delete mode 100644 erpnext/patches/v5_1/default_bom.py
delete mode 100644 erpnext/patches/v5_1/fix_against_account.py
delete mode 100644 erpnext/patches/v5_1/rename_roles.py
delete mode 100644 erpnext/patches/v5_1/sales_bom_rename.py
delete mode 100644 erpnext/patches/v5_2/__init__.py
delete mode 100644 erpnext/patches/v5_2/change_item_selects_to_checks.py
delete mode 100644 erpnext/patches/v5_4/__init__.py
delete mode 100644 erpnext/patches/v5_4/cleanup_journal_entry.py
delete mode 100644 erpnext/patches/v5_4/fix_invoice_outstanding.py
delete mode 100644 erpnext/patches/v5_4/fix_missing_item_images.py
delete mode 100644 erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py
delete mode 100644 erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
delete mode 100644 erpnext/patches/v5_4/set_root_and_report_type.py
delete mode 100644 erpnext/patches/v5_4/stock_entry_additional_costs.py
delete mode 100644 erpnext/patches/v5_4/update_purchase_cost_against_project.py
delete mode 100644 erpnext/patches/v5_7/__init__.py
delete mode 100644 erpnext/patches/v5_7/item_template_attributes.py
delete mode 100644 erpnext/patches/v5_8/__init__.py
delete mode 100644 erpnext/patches/v5_8/add_credit_note_print_heading.py
delete mode 100644 erpnext/patches/v5_8/tax_rule.py
delete mode 100644 erpnext/patches/v5_8/update_order_reference_in_return_entries.py
delete mode 100644 erpnext/patches/v6_0/__init__.py
delete mode 100644 erpnext/patches/v6_0/default_activity_rate.py
delete mode 100644 erpnext/patches/v6_0/fix_outstanding_amount.py
delete mode 100644 erpnext/patches/v6_0/fix_planned_qty.py
delete mode 100644 erpnext/patches/v6_0/multi_currency.py
delete mode 100644 erpnext/patches/v6_0/set_default_title.py
delete mode 100644 erpnext/patches/v6_10/__init__.py
delete mode 100644 erpnext/patches/v6_10/email_digest_default_quote.py
delete mode 100644 erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py
delete mode 100644 erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py
delete mode 100644 erpnext/patches/v6_10/fix_jv_total_amount.py
delete mode 100644 erpnext/patches/v6_10/fix_ordered_received_billed.py
delete mode 100644 erpnext/patches/v6_12/__init__.py
delete mode 100644 erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
delete mode 100644 erpnext/patches/v6_12/set_overdue_tasks.py
delete mode 100644 erpnext/patches/v6_16/__init__.py
delete mode 100644 erpnext/patches/v6_16/create_manufacturer_records.py
delete mode 100644 erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py
delete mode 100644 erpnext/patches/v6_19/__init__.py
delete mode 100644 erpnext/patches/v6_19/comment_feed_communication.py
delete mode 100644 erpnext/patches/v6_2/__init__.py
delete mode 100644 erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py
delete mode 100644 erpnext/patches/v6_2/remove_newsletter_duplicates.py
delete mode 100644 erpnext/patches/v6_20/__init__.py
delete mode 100644 erpnext/patches/v6_20/set_party_account_currency_in_orders.py
delete mode 100644 erpnext/patches/v6_20x/__init__.py
delete mode 100644 erpnext/patches/v6_20x/remove_customer_supplier_roles.py
delete mode 100644 erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py
delete mode 100644 erpnext/patches/v6_20x/rename_project_name_to_project.py
delete mode 100644 erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py
delete mode 100644 erpnext/patches/v6_20x/set_compact_print.py
delete mode 100644 erpnext/patches/v6_20x/update_product_bundle_description.py
delete mode 100644 erpnext/patches/v6_21/__init__.py
delete mode 100644 erpnext/patches/v6_21/fix_reorder_level.py
delete mode 100644 erpnext/patches/v6_21/rename_material_request_fields.py
delete mode 100644 erpnext/patches/v6_23/__init__.py
delete mode 100644 erpnext/patches/v6_23/update_stopped_status_to_closed.py
delete mode 100644 erpnext/patches/v6_24/__init__.py
delete mode 100644 erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py
delete mode 100644 erpnext/patches/v6_24/set_recurring_id.py
delete mode 100644 erpnext/patches/v6_27/__init__.py
delete mode 100644 erpnext/patches/v6_27/fix_recurring_order_status.py
delete mode 100644 erpnext/patches/v6_3/__init__.py
delete mode 100644 erpnext/patches/v6_3/convert_applicable_territory.py
delete mode 100644 erpnext/patches/v6_4/__init__.py
delete mode 100644 erpnext/patches/v6_4/email_digest_update.py
delete mode 100644 erpnext/patches/v6_4/fix_duplicate_bins.py
delete mode 100644 erpnext/patches/v6_4/fix_expense_included_in_valuation.py
delete mode 100644 erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
delete mode 100644 erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py
delete mode 100644 erpnext/patches/v6_4/fix_sales_order_maintenance_status.py
delete mode 100644 erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py
delete mode 100644 erpnext/patches/v6_4/make_image_thumbnail.py
delete mode 100644 erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
delete mode 100644 erpnext/patches/v6_4/round_status_updater_percentages.py
delete mode 100644 erpnext/patches/v6_4/set_user_in_contact.py
delete mode 100644 erpnext/patches/v6_5/__init__.py
delete mode 100644 erpnext/patches/v6_5/show_in_website_for_template_item.py
delete mode 100644 erpnext/patches/v6_6/__init__.py
delete mode 100644 erpnext/patches/v6_6/fix_website_image.py
delete mode 100644 erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py
delete mode 100644 erpnext/patches/v6_8/__init__.py
delete mode 100644 erpnext/patches/v6_8/make_webform_standard.py
delete mode 100644 erpnext/patches/v6_8/move_drop_ship_to_po_items.py
delete mode 100644 erpnext/patches/v7_0/__init__.py
delete mode 100644 erpnext/patches/v7_0/calculate_total_costing_amount.py
delete mode 100644 erpnext/patches/v7_0/convert_timelog_to_timesheet.py
delete mode 100644 erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py
delete mode 100644 erpnext/patches/v7_0/create_budget_record.py
delete mode 100644 erpnext/patches/v7_0/create_warehouse_nestedset.py
delete mode 100644 erpnext/patches/v7_0/fix_duplicate_icons.py
delete mode 100644 erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
delete mode 100644 erpnext/patches/v7_0/make_guardian.py
delete mode 100644 erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py
delete mode 100644 erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py
delete mode 100644 erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py
delete mode 100644 erpnext/patches/v7_0/migrate_schools_to_erpnext.py
delete mode 100644 erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py
delete mode 100644 erpnext/patches/v7_0/po_status_issue_for_pr_return.py
delete mode 100644 erpnext/patches/v7_0/re_route.py
delete mode 100644 erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py
delete mode 100644 erpnext/patches/v7_0/remove_doctypes_and_reports.py
delete mode 100644 erpnext/patches/v7_0/remove_features_setup.py
delete mode 100644 erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py
delete mode 100644 erpnext/patches/v7_0/rename_advance_table_fields.py
delete mode 100644 erpnext/patches/v7_0/rename_examination_to_assessment.py
delete mode 100644 erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py
delete mode 100644 erpnext/patches/v7_0/rename_prevdoc_fields.py
delete mode 100644 erpnext/patches/v7_0/rename_salary_components.py
delete mode 100644 erpnext/patches/v7_0/rename_time_sheet_doctype.py
delete mode 100644 erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
delete mode 100644 erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
delete mode 100644 erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py
delete mode 100644 erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py
delete mode 100644 erpnext/patches/v7_0/set_is_group_for_warehouse.py
delete mode 100644 erpnext/patches/v7_0/set_material_request_type_in_item.py
delete mode 100644 erpnext/patches/v7_0/set_naming_series_for_timesheet.py
delete mode 100644 erpnext/patches/v7_0/set_party_name_in_payment_entry.py
delete mode 100644 erpnext/patches/v7_0/set_portal_settings.py
delete mode 100644 erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py
delete mode 100644 erpnext/patches/v7_0/system_settings_setup_complete.py
delete mode 100644 erpnext/patches/v7_0/update_autoname_field.py
delete mode 100644 erpnext/patches/v7_0/update_change_amount_account.py
delete mode 100644 erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py
delete mode 100644 erpnext/patches/v7_0/update_home_page.py
delete mode 100644 erpnext/patches/v7_0/update_maintenance_module_in_doctype.py
delete mode 100644 erpnext/patches/v7_0/update_mins_to_first_response.py
delete mode 100644 erpnext/patches/v7_0/update_missing_employee_in_timesheet.py
delete mode 100644 erpnext/patches/v7_0/update_mode_of_payment_type.py
delete mode 100644 erpnext/patches/v7_0/update_party_status.py
delete mode 100644 erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py
delete mode 100644 erpnext/patches/v7_0/update_project_in_gl_entry.py
delete mode 100644 erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py
delete mode 100644 erpnext/patches/v7_0/update_status_for_timesheet.py
delete mode 100644 erpnext/patches/v7_0/update_status_of_po_so.py
delete mode 100644 erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py
delete mode 100644 erpnext/patches/v7_0/update_timesheet_communications.py
delete mode 100644 erpnext/patches/v7_1/__init__.py
delete mode 100644 erpnext/patches/v7_1/add_account_user_role_for_timesheet.py
delete mode 100644 erpnext/patches/v7_1/add_field_for_task_dependent.py
delete mode 100644 erpnext/patches/v7_1/fix_link_for_customer_from_lead.py
delete mode 100644 erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py
delete mode 100644 erpnext/patches/v7_1/rename_field_timesheet.py
delete mode 100644 erpnext/patches/v7_1/rename_quality_inspection_field.py
delete mode 100644 erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py
delete mode 100644 erpnext/patches/v7_1/save_stock_settings.py
delete mode 100644 erpnext/patches/v7_1/set_budget_against_as_cost_center.py
delete mode 100644 erpnext/patches/v7_1/set_currency_exchange_date.py
delete mode 100644 erpnext/patches/v7_1/set_prefered_contact_email.py
delete mode 100644 erpnext/patches/v7_1/set_sales_person_status.py
delete mode 100644 erpnext/patches/v7_1/set_student_guardian.py
delete mode 100644 erpnext/patches/v7_1/set_total_amount_currency_in_je.py
delete mode 100644 erpnext/patches/v7_1/update_bom_base_currency.py
delete mode 100644 erpnext/patches/v7_1/update_component_type.py
delete mode 100644 erpnext/patches/v7_1/update_invoice_status.py
delete mode 100644 erpnext/patches/v7_1/update_lead_source.py
delete mode 100644 erpnext/patches/v7_1/update_missing_salary_component_type.py
delete mode 100644 erpnext/patches/v7_1/update_portal_roles.py
delete mode 100644 erpnext/patches/v7_1/update_total_billing_hours.py
delete mode 100644 erpnext/patches/v7_2/__init__.py
delete mode 100644 erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py
delete mode 100644 erpnext/patches/v7_2/contact_address_links.py
delete mode 100644 erpnext/patches/v7_2/delete_fleet_management_module_def.py
delete mode 100644 erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py
delete mode 100644 erpnext/patches/v7_2/make_all_assessment_group.py
delete mode 100644 erpnext/patches/v7_2/mark_students_active.py
delete mode 100644 erpnext/patches/v7_2/rename_att_date_attendance.py
delete mode 100644 erpnext/patches/v7_2/rename_evaluation_criteria.py
delete mode 100644 erpnext/patches/v7_2/set_null_value_to_fields.py
delete mode 100644 erpnext/patches/v7_2/setup_auto_close_settings.py
delete mode 100644 erpnext/patches/v7_2/stock_uom_in_selling.py
delete mode 100644 erpnext/patches/v7_2/update_abbr_in_salary_slips.py
delete mode 100644 erpnext/patches/v7_2/update_assessment_modules.py
delete mode 100644 erpnext/patches/v7_2/update_attendance_docstatus.py
delete mode 100644 erpnext/patches/v7_2/update_doctype_status.py
delete mode 100644 erpnext/patches/v7_2/update_guardian_name_in_student_master.py
delete mode 100644 erpnext/patches/v7_2/update_party_type.py
delete mode 100644 erpnext/patches/v7_2/update_salary_slips.py
delete mode 100644 erpnext/patches/v7_2/update_website_for_variant.py
delete mode 100644 erpnext/patches/v8_0/__init__.py
delete mode 100644 erpnext/patches/v8_0/addresses_linked_to_lead.py
delete mode 100644 erpnext/patches/v8_0/change_in_words_varchar_length.py
delete mode 100644 erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py
delete mode 100644 erpnext/patches/v8_0/create_domain_docs.py
delete mode 100644 erpnext/patches/v8_0/delete_bin_indexes.py
delete mode 100644 erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
delete mode 100644 erpnext/patches/v8_0/disable_instructor_role.py
delete mode 100644 erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py
delete mode 100644 erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py
delete mode 100644 erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py
delete mode 100644 erpnext/patches/v8_0/merge_student_batch_and_student_group.py
delete mode 100644 erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py
delete mode 100644 erpnext/patches/v8_0/move_perpetual_inventory_setting.py
delete mode 100644 erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py
delete mode 100644 erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py
delete mode 100644 erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py
delete mode 100644 erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py
delete mode 100644 erpnext/patches/v8_0/revert_manufacturers_table_from_item.py
delete mode 100644 erpnext/patches/v8_0/save_system_settings.py
delete mode 100644 erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py
delete mode 100644 erpnext/patches/v8_0/set_project_copied_from.py
delete mode 100644 erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
delete mode 100644 erpnext/patches/v8_0/update_customer_pos_id.py
delete mode 100644 erpnext/patches/v8_0/update_production_orders.py
delete mode 100644 erpnext/patches/v8_0/update_sales_cost_in_project.py
delete mode 100644 erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py
delete mode 100644 erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py
delete mode 100644 erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py
delete mode 100644 erpnext/patches/v8_0/update_student_groups_from_student_batches.py
delete mode 100644 erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py
delete mode 100644 erpnext/patches/v8_1/__init__.py
delete mode 100644 erpnext/patches/v8_1/add_hsn_sac_codes.py
delete mode 100644 erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py
delete mode 100644 erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py
delete mode 100644 erpnext/patches/v8_1/delete_deprecated_reports.py
delete mode 100644 erpnext/patches/v8_1/gst_fixes.py
delete mode 100644 erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py
delete mode 100644 erpnext/patches/v8_1/removed_report_support_hours.py
delete mode 100644 erpnext/patches/v8_1/set_delivery_date_in_so_item.py
delete mode 100644 erpnext/patches/v8_1/update_expense_claim_status.py
delete mode 100644 erpnext/patches/v8_1/update_gst_state.py
delete mode 100644 erpnext/patches/v8_10/__init__.py
delete mode 100644 erpnext/patches/v8_10/change_default_customer_credit_days.py
delete mode 100644 erpnext/patches/v8_3/__init__.py
delete mode 100644 erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py
delete mode 100644 erpnext/patches/v8_3/update_company_total_sales.py
delete mode 100644 erpnext/patches/v8_4/__init__.py
delete mode 100644 erpnext/patches/v8_4/make_scorecard_records.py
delete mode 100644 erpnext/patches/v8_5/__init__.py
delete mode 100644 erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py
delete mode 100644 erpnext/patches/v8_5/remove_project_type_property_setter.py
delete mode 100644 erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py
delete mode 100644 erpnext/patches/v8_5/set_default_mode_of_payment.py
delete mode 100644 erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
delete mode 100644 erpnext/patches/v8_5/update_existing_data_in_project_type.py
delete mode 100644 erpnext/patches/v8_6/__init__.py
delete mode 100644 erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py
delete mode 100644 erpnext/patches/v8_6/rename_bom_update_tool.py
delete mode 100644 erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
delete mode 100644 erpnext/patches/v8_6/update_timesheet_company_from_PO.py
delete mode 100644 erpnext/patches/v8_7/__init__.py
delete mode 100644 erpnext/patches/v8_7/fix_purchase_receipt_status.py
delete mode 100644 erpnext/patches/v8_7/make_subscription_from_recurring_data.py
delete mode 100644 erpnext/patches/v8_8/__init__.py
delete mode 100644 erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py
delete mode 100644 erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
delete mode 100644 erpnext/patches/v8_9/__init__.py
delete mode 100644 erpnext/patches/v8_9/add_setup_progress_actions.py
delete mode 100644 erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py
delete mode 100644 erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py
delete mode 100644 erpnext/patches/v8_9/rename_company_sales_target_field.py
delete mode 100644 erpnext/patches/v8_9/set_default_customer_group.py
delete mode 100644 erpnext/patches/v8_9/set_default_fields_in_variant_settings.py
delete mode 100644 erpnext/patches/v8_9/set_member_party_type.py
delete mode 100644 erpnext/patches/v8_9/set_print_zero_amount_taxes.py
delete mode 100644 erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py
delete mode 100644 erpnext/patches/v9_0/__init__.py
delete mode 100644 erpnext/patches/v9_0/add_healthcare_domain.py
delete mode 100644 erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py
delete mode 100644 erpnext/patches/v9_0/copy_old_fees_field_data.py
delete mode 100644 erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py
delete mode 100644 erpnext/patches/v9_0/remove_subscription_module.py
delete mode 100644 erpnext/patches/v9_0/revert_manufacturing_user_role.py
delete mode 100644 erpnext/patches/v9_0/set_pos_profile_name.py
delete mode 100644 erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
delete mode 100644 erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py
delete mode 100644 erpnext/patches/v9_0/set_uoms_in_variant_field.py
delete mode 100644 erpnext/patches/v9_0/set_variant_item_description.py
delete mode 100644 erpnext/patches/v9_0/student_admission_childtable_migrate.py
delete mode 100644 erpnext/patches/v9_0/update_employee_loan_details.py
delete mode 100644 erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py
delete mode 100644 erpnext/patches/v9_1/__init__.py
delete mode 100644 erpnext/patches/v9_1/create_issue_opportunity_type.py
delete mode 100644 erpnext/patches/v9_2/__init__.py
delete mode 100644 erpnext/patches/v9_2/delete_healthcare_domain_default_items.py
delete mode 100644 erpnext/patches/v9_2/delete_process_payroll.py
delete mode 100644 erpnext/patches/v9_2/remove_company_from_patient.py
delete mode 100644 erpnext/patches/v9_2/rename_net_weight_in_item_master.py
delete mode 100644 erpnext/patches/v9_2/rename_translated_domains_in_en.py
delete mode 100644 erpnext/patches/v9_2/repost_reserved_qty_for_production.py
delete mode 100644 erpnext/patches/v9_2/set_item_name_in_production_order.py
diff --git a/erpnext/patches/repair_tools/__init__.py b/erpnext/patches/repair_tools/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py b/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py
deleted file mode 100644
index 5a421d146f..0000000000
--- a/erpnext/patches/repair_tools/set_stock_balance_as_per_serial_no.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from erpnext.stock.stock_balance import set_stock_balance_as_per_serial_no
- frappe.db.auto_commit_on_many_writes = 1
-
- set_stock_balance_as_per_serial_no()
-
- frappe.db.auto_commit_on_many_writes = 0
diff --git a/erpnext/patches/v10_0/__init__.py b/erpnext/patches/v10_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v10_0/add_agriculture_domain.py b/erpnext/patches/v10_0/add_agriculture_domain.py
deleted file mode 100644
index c18e69f3e6..0000000000
--- a/erpnext/patches/v10_0/add_agriculture_domain.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- domain = 'Agriculture'
- if not frappe.db.exists('Domain', domain):
- frappe.get_doc({
- 'doctype': 'Domain',
- 'domain': domain
- }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py b/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py
deleted file mode 100644
index 0b891f21f4..0000000000
--- a/erpnext/patches/v10_0/add_guardian_role_for_parent_portal.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # create guardian role
- if not frappe.get_value('Role', dict(role_name='Guardian')):
- frappe.get_doc({
- 'doctype': 'Role',
- 'role_name': 'Guardian',
- 'desk_access': 0,
- 'restrict_to_domain': 'Education'
- }).insert(ignore_permissions=True)
-
- # set guardian roles in already created users
- if frappe.db.exists("Doctype", "Guardian"):
- for user in frappe.db.sql_list("""select u.name from `tabUser` u , `tabGuardian` g where g.email_address = u.name"""):
- user = frappe.get_doc('User', user)
- user.flags.ignore_validate = True
- user.flags.ignore_mandatory = True
- user.save()
diff --git a/erpnext/patches/v10_0/add_non_profit_domain.py b/erpnext/patches/v10_0/add_non_profit_domain.py
deleted file mode 100644
index b03d669515..0000000000
--- a/erpnext/patches/v10_0/add_non_profit_domain.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- domain = 'Non Profit'
- if not frappe.db.exists('Domain', domain):
- frappe.get_doc({
- 'doctype': 'Domain',
- 'domain': domain
- }).insert(ignore_permissions=True)
-
- frappe.get_doc({
- 'doctype': 'Role',
- 'role_name': 'Non Profit Portal User',
- 'desk_access': 0,
- 'restrict_to_domain': domain
- }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py b/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py
deleted file mode 100644
index 827f9bc94f..0000000000
--- a/erpnext/patches/v10_0/allow_operators_in_supplier_scorecard.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2019, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_criteria')
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_scoring_criteria')
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard')
-
- for criteria in frappe.get_all('Supplier Scorecard Criteria', fields=['name', 'formula'], limit_page_length=None):
- frappe.db.set_value('Supplier Scorecard Criteria', criteria.name,
- 'formula', criteria.formula.replace('<','<').replace('>','>'))
-
- for criteria in frappe.get_all('Supplier Scorecard Scoring Criteria', fields=['name', 'formula'], limit_page_length=None):
- if criteria.formula: # not mandatory
- frappe.db.set_value('Supplier Scorecard Scoring Criteria', criteria.name,
- 'formula', criteria.formula.replace('<','<').replace('>','>'))
-
- for sc in frappe.get_all('Supplier Scorecard', fields=['name', 'weighting_function'], limit_page_length=None):
- frappe.db.set_value('Supplier Scorecard', sc.name, 'weighting_function',
- sc.weighting_function.replace('<','<').replace('>','>'))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/copy_projects_renamed_fields.py b/erpnext/patches/v10_0/copy_projects_renamed_fields.py
deleted file mode 100644
index 80db3bdd1e..0000000000
--- a/erpnext/patches/v10_0/copy_projects_renamed_fields.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- """ copy data from old fields to new """
- frappe.reload_doc("projects", "doctype", "project")
-
- if frappe.db.has_column('Project', 'total_sales_cost'):
- rename_field('Project', "total_sales_cost", "total_sales_amount")
-
- if frappe.db.has_column('Project', 'total_billing_amount'):
- rename_field('Project', "total_billing_amount", "total_billable_amount")
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py b/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py
deleted file mode 100644
index 38b04cebc2..0000000000
--- a/erpnext/patches/v10_0/enabled_regional_print_format_based_on_country.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- print_format_mapper = {
- 'India': ['GST POS Invoice', 'GST Tax Invoice'],
- 'Saudi Arabia': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice'],
- 'United Arab Emirates': ['Simplified Tax Invoice', 'Detailed Tax Invoice', 'Tax Invoice']
- }
-
- frappe.db.sql(""" update `tabPrint Format` set disabled = 1 where name
- in ('GST POS Invoice', 'GST Tax Invoice', 'Simplified Tax Invoice', 'Detailed Tax Invoice')""")
-
- for d in frappe.get_all('Company', fields = ["country"],
- filters={'country': ('in', ['India', 'Saudi Arabia', 'United Arab Emirates'])}):
- if print_format_mapper.get(d.country):
- print_formats = print_format_mapper.get(d.country)
- frappe.db.sql(""" update `tabPrint Format` set disabled = 0
- where name in (%s)""" % ", ".join(["%s"]*len(print_formats)), tuple(print_formats))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py b/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
deleted file mode 100644
index c0a9e5eb5b..0000000000
--- a/erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.utils import get_bin
-
-def execute():
- frappe.reload_doc("stock", "doctype", "bin")
- frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied")
- for d in frappe.db.sql("""
- select distinct rm_item_code, reserve_warehouse
- from `tabPurchase Order Item Supplied`
- where docstatus=1 and reserve_warehouse is not null and reserve_warehouse != ''"""):
-
- try:
- bin_doc = get_bin(d[0], d[1])
- bin_doc.update_reserved_qty_for_sub_contracting()
- except:
- pass
-
- for d in frappe.db.sql("""select distinct item_code, source_warehouse
- from `tabWork Order Item`
- where docstatus=1 and transferred_qty > required_qty
- and source_warehouse is not null and source_warehouse != ''""", as_list=1):
-
- try:
- bin_doc = get_bin(d[0], d[1])
- bin_doc.update_reserved_qty_for_production()
- except:
- pass
diff --git a/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py b/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py
deleted file mode 100644
index 6d461f3bc9..0000000000
--- a/erpnext/patches/v10_0/recalculate_gross_margin_for_project.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'project')
- for d in frappe.db.sql(""" select name from `tabProject` where
- ifnull(total_consumed_material_cost, 0 ) > 0 and ifnull(total_billed_amount, 0) > 0""", as_dict=1):
- doc = frappe.get_doc("Project", d.name)
- doc.calculate_gross_margin()
- doc.db_set('gross_margin', doc.gross_margin)
- doc.db_set('per_gross_margin', doc.per_gross_margin)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/rename_schools_to_education.py b/erpnext/patches/v10_0/rename_schools_to_education.py
deleted file mode 100644
index 85c25a8943..0000000000
--- a/erpnext/patches/v10_0/rename_schools_to_education.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # rename the School module as Education
-
- # rename the school module
- if frappe.db.exists('Module Def', 'Schools') and not frappe.db.exists('Module Def', 'Education'):
- frappe.rename_doc("Module Def", "Schools", "Education")
-
- # delete the school module
- if frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Education'):
- frappe.db.sql("""delete from `tabModule Def` where module_name = 'Schools'""")
-
-
- # rename "School Settings" to the "Education Settings
- if frappe.db.exists('DocType', 'School Settings'):
- frappe.rename_doc("DocType", "School Settings", "Education Settings", force=True)
- frappe.reload_doc("education", "doctype", "education_settings")
-
- # delete the discussion web form if exists
- if frappe.db.exists('Web Form', 'Discussion'):
- frappe.db.sql("""delete from `tabWeb Form` where name = 'discussion'""")
-
- # rename the select option field from "School Bus" to "Institute's Bus"
- frappe.reload_doc("education", "doctype", "Program Enrollment")
- if "mode_of_transportation" in frappe.db.get_table_columns("Program Enrollment"):
- frappe.db.sql("""update `tabProgram Enrollment` set mode_of_transportation = "Institute's Bus"
- where mode_of_transportation = "School Bus" """)
diff --git a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
deleted file mode 100644
index e6546e386b..0000000000
--- a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe, erpnext
-
-def execute():
- for company in frappe.get_all("Company"):
- if not erpnext.is_perpetual_inventory_enabled(company.name):
- continue
-
- acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
- pr_with_rejected_warehouse = frappe.db.sql("""
- select pr.name
- from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
- where pr.name = pr_item.parent
- and pr.posting_date > %s
- and pr.docstatus=1
- and pr.company = %s
- and pr_item.rejected_qty > 0
- """, (acc_frozen_upto, company.name), as_dict=1)
-
- for d in pr_with_rejected_warehouse:
- doc = frappe.get_doc("Purchase Receipt", d.name)
-
- doc.docstatus = 2
- doc.make_gl_entries_on_cancel()
-
-
- # update gl entries for submit state of PR
- doc.docstatus = 1
- doc.make_gl_entries()
diff --git a/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py b/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py
deleted file mode 100644
index 4fe4e97cf5..0000000000
--- a/erpnext/patches/v10_0/repost_requested_qty_for_non_stock_uom_items.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2019, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
-
- count=0
- for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse
- from `tabMaterial Request Item` where docstatus = 1 and stock_uom<>uom"""):
- try:
- count += 1
- update_bin_qty(item_code, warehouse, {
- "indented_qty": get_indented_qty(item_code, warehouse),
- })
- if count % 200 == 0:
- frappe.db.commit()
- except:
- frappe.db.rollback()
diff --git a/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py b/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py
deleted file mode 100644
index c6470f21d7..0000000000
--- a/erpnext/patches/v10_0/set_auto_created_serial_no_in_stock_entry.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- serialised_items = [d.name for d in frappe.get_all("Item", filters={"has_serial_no": 1})]
-
- if not serialised_items:
- return
-
- for dt in ["Stock Entry Detail", "Purchase Receipt Item", "Purchase Invoice Item"]:
- cond = ""
- if dt=="Purchase Invoice Item":
- cond = """ and parent in (select name from `tabPurchase Invoice`
- where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.parent and update_stock=1)"""
-
- item_rows = frappe.db.sql("""
- select name
- from `tab{0}`
- where conversion_factor != 1
- and docstatus = 1
- and ifnull(serial_no, '') = ''
- and item_code in ({1})
- {2}
- """.format(dt, ', '.join(['%s']*len(serialised_items)), cond), tuple(serialised_items))
-
- if item_rows:
- sle_serial_nos = dict(frappe.db.sql("""
- select voucher_detail_no, serial_no
- from `tabStock Ledger Entry`
- where ifnull(serial_no, '') != ''
- and voucher_detail_no in (%s)
- """.format(', '.join(['%s']*len(item_rows))),
- tuple([d[0] for d in item_rows])))
-
- batch_size = 100
- for i in range(0, len(item_rows), batch_size):
- batch_item_rows = item_rows[i:i + batch_size]
- when_then = []
- for item_row in batch_item_rows:
-
- when_then.append('WHEN `name` = "{row_name}" THEN "{value}"'.format(
- row_name=item_row[0],
- value=sle_serial_nos.get(item_row[0])))
-
- frappe.db.sql("""
- update
- `tab{doctype}`
- set
- serial_no = CASE {when_then_cond} ELSE `serial_no` END
- """.format(
- doctype = dt,
- when_then_cond=" ".join(when_then)
- ))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_b2c_limit.py b/erpnext/patches/v10_0/set_b2c_limit.py
deleted file mode 100644
index 5d964e681a..0000000000
--- a/erpnext/patches/v10_0/set_b2c_limit.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("regional", "doctype", "gst_settings")
- frappe.reload_doc("accounts", "doctype", "gst_account")
- gst_settings = frappe.get_doc("GST Settings")
- gst_settings.b2c_limit = 250000
- gst_settings.save()
diff --git a/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py b/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py
deleted file mode 100644
index a90e096390..0000000000
--- a/erpnext/patches/v10_0/set_default_payment_terms_based_on_company.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.patches.v8_10.change_default_customer_credit_days import make_payment_term, make_template
-
-def execute():
- for dt in ("Company", "Customer Group"):
- frappe.reload_doc("setup", "doctype", frappe.scrub(dt))
-
- credit_records = frappe.db.sql("""
- SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name`
- from `tab{0}`
- where
- ((credit_days_based_on='Fixed Days' or credit_days_based_on is null) and credit_days is not null)
- or credit_days_based_on='Last Day of the Next Month'
- """.format(dt), as_dict=1)
-
- for d in credit_records:
- template = create_payment_terms_template(d)
-
- frappe.db.sql("""
- update `tab{0}`
- set `payment_terms` = %s
- where name = %s
- """.format(dt), (template.name, d.name))
-
-def create_payment_terms_template(data):
- if data.credit_days_based_on == "Fixed Days":
- pyt_template_name = 'Default Payment Term - N{0}'.format(data.credit_days)
- else:
- pyt_template_name = 'Default Payment Term - EO2M'
-
- if not frappe.db.exists("Payment Terms Template", pyt_template_name):
- payment_term = make_payment_term(data.credit_days, data.credit_days_based_on)
- template = make_template(payment_term)
- else:
- template = frappe.get_doc("Payment Terms Template", pyt_template_name)
- return template
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_discount_amount.py b/erpnext/patches/v10_0/set_discount_amount.py
deleted file mode 100644
index d5e2c5a84b..0000000000
--- a/erpnext/patches/v10_0/set_discount_amount.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "sales_invoice_item")
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_item')
- frappe.reload_doc('buying', 'doctype', 'purchase_order_item')
- frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item')
- frappe.reload_doc('selling', 'doctype', 'sales_order_item')
- frappe.reload_doc('selling', 'doctype', 'quotation_item')
- frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
-
- selling_doctypes = ["Sales Order Item", "Sales Invoice Item", "Delivery Note Item", "Quotation Item"]
- buying_doctypes = ["Purchase Order Item", "Purchase Invoice Item", "Purchase Receipt Item", "Supplier Quotation Item"]
-
- for doctype in selling_doctypes:
- frappe.db.sql('''
- UPDATE
- `tab%s`
- SET
- discount_amount = if(rate_with_margin > 0, rate_with_margin, price_list_rate) * discount_percentage / 100
- WHERE
- discount_percentage > 0
- ''' % (doctype))
- for doctype in buying_doctypes:
- frappe.db.sql('''
- UPDATE
- `tab%s`
- SET
- discount_amount = price_list_rate * discount_percentage / 100
- WHERE
- discount_percentage > 0
- ''' % (doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py b/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py
deleted file mode 100644
index 6825f19d74..0000000000
--- a/erpnext/patches/v10_0/set_numeric_ranges_in_template_if_blank.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- item_numeric_attributes = frappe.db.sql("""
- select name, numeric_values, from_range, to_range, increment
- from `tabItem Attribute`
- where numeric_values = 1
- """, as_dict=1)
-
- for d in item_numeric_attributes:
- frappe.db.sql("""
- update `tabItem Variant Attribute`
- set
- from_range = CASE
- WHEN from_range = 0 THEN %(from_range)s
- ELSE from_range
- END,
- to_range = CASE
- WHEN to_range = 0 THEN %(to_range)s
- ELSE to_range
- END,
- increment = CASE
- WHEN increment = 0 THEN %(increment)s
- ELSE increment
- END,
- numeric_values = %(numeric_values)s
- where
- attribute = %(name)s
- and exists(select name from tabItem
- where name=`tabItem Variant Attribute`.parent and has_variants=1)
- """, d)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_primary_contact_for_customer.py b/erpnext/patches/v10_0/set_primary_contact_for_customer.py
deleted file mode 100644
index ae0b31c21f..0000000000
--- a/erpnext/patches/v10_0/set_primary_contact_for_customer.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Customer')
-
- frappe.db.sql("""
- update
- `tabCustomer`, (
- select `tabContact`.name, `tabContact`.mobile_no, `tabContact`.email_id,
- `tabDynamic Link`.link_name from `tabContact`, `tabDynamic Link`
- where `tabContact`.name = `tabDynamic Link`.parent and
- `tabDynamic Link`.link_doctype = 'Customer' and `tabContact`.is_primary_contact = 1
- ) as contact
- set
- `tabCustomer`.customer_primary_contact = contact.name,
- `tabCustomer`.mobile_no = contact.mobile_no, `tabCustomer`.email_id = contact.email_id
- where `tabCustomer`.name = contact.link_name""")
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py b/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py
deleted file mode 100644
index 083b7f4b20..0000000000
--- a/erpnext/patches/v10_0/set_qty_in_transactions_based_on_serial_no_input.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "stock_settings")
-
- ss = frappe.get_doc("Stock Settings")
- ss.set_qty_in_transactions_based_on_serial_no_input = 1
-
- if ss.default_warehouse \
- and not frappe.db.exists("Warehouse", ss.default_warehouse):
- ss.default_warehouse = None
-
- if ss.stock_uom and not frappe.db.exists("UOM", ss.stock_uom):
- ss.stock_uom = None
-
- ss.flags.ignore_mandatory = True
- ss.save()
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/set_student_party_type.py b/erpnext/patches/v10_0/set_student_party_type.py
deleted file mode 100644
index 08376ae894..0000000000
--- a/erpnext/patches/v10_0/set_student_party_type.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists("Party Type", "Student"):
- party = frappe.new_doc("Party Type")
- party.party_type = "Student"
- party.save()
diff --git a/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py b/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py
deleted file mode 100644
index a8d90499d8..0000000000
--- a/erpnext/patches/v10_0/setup_vat_for_uae_and_saudi_arabia.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.setup.doctype.company.company import install_country_fixtures
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
- frappe.reload_doc("accounts", "doctype", "payment_schedule")
- for d in frappe.get_all('Company',
- filters={'country': ('in', ['Saudi Arabia', 'United Arab Emirates'])}):
- install_country_fixtures(d.name)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py b/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py
deleted file mode 100644
index 7e2ff7a8a7..0000000000
--- a/erpnext/patches/v10_0/show_leaves_of_all_department_members_in_calendar.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("hr", "doctype", "hr_settings")
- frappe.db.set_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar", 1)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/taxes_issue_with_pos.py b/erpnext/patches/v10_0/taxes_issue_with_pos.py
deleted file mode 100644
index 2a3275ac2c..0000000000
--- a/erpnext/patches/v10_0/taxes_issue_with_pos.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.get_all('Sales Invoice', fields=["name"],
- filters = {'is_pos':1, 'docstatus': 1, 'creation': ('>', '2018-04-23')}):
- doc = frappe.get_doc('Sales Invoice', d.name)
- if (not doc.taxes and doc.taxes_and_charges and doc.pos_profile and doc.outstanding_amount != 0 and
- frappe.db.get_value('POS Profile', doc.pos_profile, 'taxes_and_charges', cache=True) == doc.taxes_and_charges):
-
- doc.append_taxes_from_master()
- doc.calculate_taxes_and_totals()
- for d in doc.taxes:
- d.db_update()
-
- doc.db_update()
-
- delete_gle_for_voucher(doc.name)
- doc.make_gl_entries()
-
-def delete_gle_for_voucher(voucher_no):
- frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
- {'voucher_no': voucher_no})
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_address_template_for_india.py b/erpnext/patches/v10_0/update_address_template_for_india.py
deleted file mode 100644
index 1ddca93760..0000000000
--- a/erpnext/patches/v10_0/update_address_template_for_india.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.address_template.setup import set_up_address_templates
-
-def execute():
- if frappe.db.get_value('Company', {'country': 'India'}, 'name'):
- address_template = frappe.db.get_value('Address Template', 'India', 'template')
- if not address_template or "gstin" not in address_template:
- set_up_address_templates(default_country='India')
diff --git a/erpnext/patches/v10_0/update_assessment_plan.py b/erpnext/patches/v10_0/update_assessment_plan.py
deleted file mode 100644
index 174623c1a4..0000000000
--- a/erpnext/patches/v10_0/update_assessment_plan.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('education', 'doctype', 'assessment_plan')
-
- frappe.db.sql("""
- UPDATE `tabAssessment Plan` as ap
- INNER JOIN `tabStudent Group` as sg ON sg.name = ap.student_group
- SET ap.academic_term = sg.academic_term,
- ap.academic_year = sg.academic_year,
- ap.program = sg.program
- WHERE ap.docstatus = 1
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_assessment_result.py b/erpnext/patches/v10_0/update_assessment_result.py
deleted file mode 100644
index 96218db972..0000000000
--- a/erpnext/patches/v10_0/update_assessment_result.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('education', 'doctype', 'assessment_result')
-
- frappe.db.sql("""
- UPDATE `tabAssessment Result` AS ar
- INNER JOIN `tabAssessment Plan` AS ap ON ap.name = ar.assessment_plan
- SET ar.academic_term = ap.academic_term,
- ar.academic_year = ap.academic_year,
- ar.program = ap.program,
- ar.course = ap.course,
- ar.assessment_group = ap.assessment_group,
- ar.student_group = ap.student_group
- WHERE ap.docstatus = 1
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_asset_calculate_depreciation.py b/erpnext/patches/v10_0/update_asset_calculate_depreciation.py
deleted file mode 100644
index b947a40b4a..0000000000
--- a/erpnext/patches/v10_0/update_asset_calculate_depreciation.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('assets', 'doctype', 'asset')
- frappe.reload_doc('assets', 'doctype', 'depreciation_schedule')
-
- frappe.db.sql("""
- update tabAsset a
- set calculate_depreciation = 1
- where exists(select ds.name from `tabDepreciation Schedule` ds where ds.parent=a.name)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_hub_connector_domain.py b/erpnext/patches/v10_0/update_hub_connector_domain.py
deleted file mode 100644
index baf580a369..0000000000
--- a/erpnext/patches/v10_0/update_hub_connector_domain.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Data Migration Connector"):
- frappe.db.sql("""
- UPDATE `tabData Migration Connector`
- SET hostname = 'https://hubmarket.org'
- WHERE connector_name = 'Hub Connector'
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_lft_rgt_for_employee.py b/erpnext/patches/v10_0/update_lft_rgt_for_employee.py
deleted file mode 100644
index 46ca786e0d..0000000000
--- a/erpnext/patches/v10_0/update_lft_rgt_for_employee.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils.nestedset import rebuild_tree
-
-def execute():
- """ assign lft and rgt appropriately """
- frappe.reload_doc("hr", "doctype", "employee")
-
- rebuild_tree("Employee", "reports_to")
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_project_in_sle.py b/erpnext/patches/v10_0/update_project_in_sle.py
deleted file mode 100644
index 08c64f18d8..0000000000
--- a/erpnext/patches/v10_0/update_project_in_sle.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ['Sales Invoice', 'Delivery Note', 'Stock Entry']:
- frappe.db.sql(""" update
- `tabStock Ledger Entry` sle, `tab{0}` parent_doc
- set
- sle.project = parent_doc.project
- where
- sle.voucher_no = parent_doc.name and sle.voucher_type = %s and sle.project is null
- and parent_doc.project is not null and parent_doc.project != ''""".format(doctype), doctype)
diff --git a/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py b/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py
deleted file mode 100644
index 7b2c36698a..0000000000
--- a/erpnext/patches/v10_0/update_reserved_qty_for_purchase_order.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.utils import get_bin
-
-def execute():
- po_item = list(frappe.db.sql(("""
- select distinct po.name as poname, poitem.rm_item_code as rm_item_code, po.company
- from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitem
- where po.name = poitem.parent
- and po.is_subcontracted = "Yes"
- and po.docstatus = 1"""), as_dict=1))
- if not po_item:
- return
-
- frappe.reload_doc("stock", "doctype", "bin")
- frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied")
- company_warehouse = frappe._dict(frappe.db.sql("""select company, min(name) from `tabWarehouse`
- where is_group = 0 group by company"""))
-
- items = list(set([d.rm_item_code for d in po_item]))
- item_wh = frappe._dict(frappe.db.sql("""select item_code, default_warehouse
- from `tabItem` where name in ({0})""".format(", ".join(["%s"] * len(items))), items))
-
- # Update reserved warehouse
- for item in po_item:
- reserve_warehouse = get_warehouse(item.rm_item_code, item.company, company_warehouse, item_wh)
- frappe.db.sql("""update `tabPurchase Order Item Supplied`
- set reserve_warehouse = %s
- where parent = %s and rm_item_code = %s
- """, (reserve_warehouse, item["poname"], item["rm_item_code"]))
-
- # Update bin
- item_wh_bin = frappe.db.sql(("""
- select distinct poitemsup.rm_item_code as rm_item_code,
- poitemsup.reserve_warehouse as reserve_warehouse
- from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
- where po.name = poitemsup.parent
- and po.is_subcontracted = "Yes"
- and po.docstatus = 1"""), as_dict=1)
- for d in item_wh_bin:
- try:
- stock_bin = get_bin(d["rm_item_code"], d["reserve_warehouse"])
- stock_bin.update_reserved_qty_for_sub_contracting()
- except:
- pass
-
-def get_warehouse(item_code, company, company_warehouse, item_wh):
- reserve_warehouse = item_wh.get(item_code)
- if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != company:
- reserve_warehouse = None
- if not reserve_warehouse:
- reserve_warehouse = company_warehouse.get(company)
- return reserve_warehouse
diff --git a/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py b/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py
deleted file mode 100644
index b4f58384bf..0000000000
--- a/erpnext/patches/v10_0/update_sales_order_link_to_purchase_order.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("buying", "doctype", "supplier_quotation_item")
-
- for doctype in ['Purchase Order','Supplier Quotation']:
- frappe.db.sql("""
- Update
- `tab{doctype} Item`, `tabMaterial Request Item`
- set
- `tab{doctype} Item`.sales_order = `tabMaterial Request Item`.sales_order
- where
- `tab{doctype} Item`.material_request= `tabMaterial Request Item`.parent
- and `tab{doctype} Item`.material_request_item = `tabMaterial Request Item`.name
- and `tabMaterial Request Item`.sales_order is not null""".format(doctype=doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py b/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py
deleted file mode 100644
index fd3be08b89..0000000000
--- a/erpnext/patches/v10_0/update_status_for_multiple_source_in_po.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
-
-
- # update the sales order item in the material request
- frappe.reload_doc('stock', 'doctype', 'material_request_item')
- frappe.db.sql('''update `tabMaterial Request Item` mri, `tabSales Order Item` soi
- set mri.sales_order_item = soi.name
- where ifnull(mri.sales_order, "")!="" and soi.parent=mri.sales_order
- and soi.item_code=mri.item_code and mri.docstatus=1
- ''')
-
- # update the sales order item in the purchase order
- frappe.db.sql('''update `tabPurchase Order Item` poi, `tabSales Order Item` soi
- set poi.sales_order_item = soi.name
- where ifnull(poi.sales_order, "")!="" and soi.parent=poi.sales_order
- and soi.item_code=poi.item_code and poi.docstatus = 1
- ''')
-
- # Update the status in material request and sales order
- po_list = frappe.db.sql('''
- select parent from `tabPurchase Order Item` where ifnull(material_request, "")!="" and
- ifnull(sales_order, "")!="" and docstatus=1
- ''',as_dict=1)
-
- for po in list(set([d.get("parent") for d in po_list if d.get("parent")])):
- try:
- po_doc = frappe.get_doc("Purchase Order", po)
-
- # update the so in the status updater
- po_doc.update_status_updater()
- po_doc.update_qty(update_modified=False)
-
- except Exception:
- pass
diff --git a/erpnext/patches/v10_0/update_status_in_purchase_receipt.py b/erpnext/patches/v10_0/update_status_in_purchase_receipt.py
deleted file mode 100644
index a0bdd9e2cc..0000000000
--- a/erpnext/patches/v10_0/update_status_in_purchase_receipt.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "purchase_receipt")
- frappe.db.sql('''
- UPDATE `tabPurchase Receipt` SET status = "Completed" WHERE per_billed = 100 AND docstatus = 1
- ''')
\ No newline at end of file
diff --git a/erpnext/patches/v10_0/update_territory_and_customer_group.py b/erpnext/patches/v10_0/update_territory_and_customer_group.py
deleted file mode 100644
index 7f3dae991d..0000000000
--- a/erpnext/patches/v10_0/update_territory_and_customer_group.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.rename_doc import get_fetch_fields
-
-def execute():
- ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"]
- customers = frappe.get_all('Customer', fields=["name", "customer_group"])
- customer_group_fetch = get_fetch_fields('Customer', 'Customer Group', ignore_doctypes)
-
- batch_size = 1000
- for i in range(0, len(customers), batch_size):
- batch_customers = customers[i:i + batch_size]
- for d in customer_group_fetch:
- when_then = []
- for customer in batch_customers:
- value = frappe.db.escape(frappe.as_unicode(customer.get("customer_group")))
-
- when_then.append('''
- WHEN `%s` = %s and %s != %s
- THEN %s
- '''%(d["master_fieldname"], frappe.db.escape(frappe.as_unicode(customer.name)),
- d["linked_to_fieldname"], value, value))
-
- frappe.db.sql("""
- update
- `tab%s`
- set
- %s = CASE %s ELSE `%s` END
- """%(d['doctype'], d.linked_to_fieldname, " ".join(when_then), d.linked_to_fieldname))
diff --git a/erpnext/patches/v10_0/update_user_image_in_employee.py b/erpnext/patches/v10_0/update_user_image_in_employee.py
deleted file mode 100644
index 72d5d2a857..0000000000
--- a/erpnext/patches/v10_0/update_user_image_in_employee.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('hr', 'doctype', 'employee')
-
- frappe.db.sql("""
- UPDATE
- `tabEmployee`, `tabUser`
- SET
- `tabEmployee`.image = `tabUser`.user_image
- WHERE
- `tabEmployee`.user_id = `tabUser`.name and
- `tabEmployee`.user_id is not null and
- `tabEmployee`.user_id != '' and `tabEmployee`.image is null
- """)
diff --git a/erpnext/patches/v10_0/update_warehouse_address_details.py b/erpnext/patches/v10_0/update_warehouse_address_details.py
deleted file mode 100644
index b982b9a662..0000000000
--- a/erpnext/patches/v10_0/update_warehouse_address_details.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- warehouse = frappe.db.sql("""select name, email_id, phone_no, mobile_no, address_line_1,
- address_line_2, city, state, pin from `tabWarehouse` where ifnull(address_line_1, '') != ''
- or ifnull(mobile_no, '') != ''
- or ifnull(email_id, '') != '' """, as_dict=1)
-
- for d in warehouse:
- try:
- address = frappe.new_doc('Address')
- address.name = d.name
- address.address_title = d.name
- address.address_line1 = d.address_line_1
- address.city = d.city
- address.state = d.state
- address.pincode = d.pin
- address.db_insert()
- address.append('links',{'link_doctype':'Warehouse','link_name':d.name})
- address.links[0].db_insert()
- if d.name and (d.email_id or d.mobile_no or d.phone_no):
- contact = frappe.new_doc('Contact')
- contact.name = d.name
- contact.first_name = d.name
- contact.mobile_no = d.mobile_no
- contact.email_id = d.email_id
- contact.phone = d.phone_no
- contact.db_insert()
- contact.append('links',{'link_doctype':'Warehouse','link_name':d.name})
- contact.links[0].db_insert()
- except frappe.DuplicateEntryError:
- pass
-
\ No newline at end of file
diff --git a/erpnext/patches/v10_1/__init__.py b/erpnext/patches/v10_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v11_0/__init__.py b/erpnext/patches/v11_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v11_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v11_0/remove_subscriber_doctype.py b/erpnext/patches/v11_0/remove_subscriber_doctype.py
deleted file mode 100644
index 4839a20f91..0000000000
--- a/erpnext/patches/v11_0/remove_subscriber_doctype.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- """ copy subscribe field to customer """
- frappe.reload_doc("accounts","doctype","subscription")
-
- if frappe.db.exists("DocType", "Subscriber"):
- if frappe.db.has_column('Subscription','subscriber'):
- frappe.db.sql("""
- update `tabSubscription` s1
- set customer=(select customer from tabSubscriber where name=s1.subscriber)
- """)
-
- frappe.delete_doc("DocType", "Subscriber")
\ No newline at end of file
diff --git a/erpnext/patches/v11_1/__init__.py b/erpnext/patches/v11_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v12_0/__init__.py b/erpnext/patches/v12_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v13_0/__init__.py b/erpnext/patches/v13_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v13_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v4_0/__init__.py b/erpnext/patches/v4_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_0/apply_user_permissions.py b/erpnext/patches/v4_0/apply_user_permissions.py
deleted file mode 100644
index 3c5d612c18..0000000000
--- a/erpnext/patches/v4_0/apply_user_permissions.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.hr.doctype.employee.employee import EmployeeUserDisabledError
-
-def execute():
- update_hr_permissions()
- update_permissions()
- remove_duplicate_user_permissions()
- frappe.clear_cache()
-
-def update_hr_permissions():
- # add set user permissions rights to HR Manager
- frappe.db.sql("""update `tabDocPerm` set `set_user_permissions`=1 where parent in ('Employee', 'Leave Application')
- and role='HR Manager' and permlevel=0 and `read`=1""")
- docperm_meta = frappe.get_meta('DocPerm')
- if docperm_meta.get_field('apply_user_permissions'):
- # apply user permissions on Employee and Leave Application
- frappe.db.sql("""update `tabDocPerm` set `apply_user_permissions`=1 where parent in ('Employee', 'Leave Application')
- and role in ('Employee', 'Leave Approver') and permlevel=0 and `read`=1""")
-
- frappe.clear_cache()
-
- # save employees to run on_update events
- for employee in frappe.db.sql_list("""select name from `tabEmployee` where docstatus < 2"""):
- try:
- emp = frappe.get_doc("Employee", employee)
- emp.flags.ignore_mandatory = True
- emp.save()
- except EmployeeUserDisabledError:
- pass
-
-def update_permissions():
- # clear match conditions other than owner
- frappe.db.sql("""update tabDocPerm set `match`=''
- where ifnull(`match`,'') not in ('', 'owner')""")
-
-def remove_duplicate_user_permissions():
- # remove duplicate user_permissions (if they exist)
- for d in frappe.db.sql("""select parent, defkey, defvalue,
- count(*) as cnt from tabDefaultValue
- where parent not in ('__global', '__default')
- group by parent, defkey, defvalue""", as_dict=1):
- if d.cnt > 1:
- # order by parenttype so that user permission does not get removed!
- frappe.db.sql("""delete from tabDefaultValue where `parent`=%s and `defkey`=%s and
- `defvalue`=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))
-
diff --git a/erpnext/patches/v4_0/countrywise_coa.py b/erpnext/patches/v4_0/countrywise_coa.py
deleted file mode 100644
index f45e6028c8..0000000000
--- a/erpnext/patches/v4_0/countrywise_coa.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("setup", 'doctype', "company")
- frappe.reload_doc("accounts", 'doctype', "account")
-
- frappe.db.sql("""update tabAccount set account_type='Cash'
- where account_type='Bank or Cash' and account_name in ('Cash', 'Cash In Hand')""")
-
- frappe.db.sql("""update tabAccount set account_type='Stock'
- where account_name = 'Stock Assets'""")
-
- ac_types = {"Fixed Asset Account": "Fixed Asset", "Bank or Cash": "Bank"}
- for old, new in ac_types.items():
- frappe.db.sql("""update tabAccount set account_type=%s
- where account_type=%s""", (new, old))
-
- try:
- frappe.db.sql("""update `tabAccount` set report_type =
- if(is_pl_account='Yes', 'Profit and Loss', 'Balance Sheet')""")
-
- frappe.db.sql("""update `tabAccount` set balance_must_be=debit_or_credit
- where ifnull(allow_negative_balance, 0) = 0""")
- except:
- pass
diff --git a/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py b/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py
deleted file mode 100644
index fe50e444b5..0000000000
--- a/erpnext/patches/v4_0/create_custom_fields_for_india_specific_fields.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.custom.doctype.custom_field.custom_field import create_custom_field_if_values_exist
-
-def execute():
- frappe.reload_doc("stock", "doctype", "purchase_receipt")
- frappe.reload_doc("hr", "doctype", "employee")
- frappe.reload_doc("Payroll", "doctype", "salary_slip")
-
- india_specific_fields = {
- "Purchase Receipt": [{
- "label": "Supplier Shipment No",
- "fieldname": "challan_no",
- "fieldtype": "Data",
- "insert_after": "is_subcontracted"
- }, {
- "label": "Supplier Shipment Date",
- "fieldname": "challan_date",
- "fieldtype": "Date",
- "insert_after": "is_subcontracted"
- }],
- "Employee": [{
- "label": "PAN Number",
- "fieldname": "pan_number",
- "fieldtype": "Data",
- "insert_after": "company_email"
- }, {
- "label": "Gratuity LIC Id",
- "fieldname": "gratuity_lic_id",
- "fieldtype": "Data",
- "insert_after": "company_email"
- }, {
- "label": "Esic Card No",
- "fieldname": "esic_card_no",
- "fieldtype": "Data",
- "insert_after": "bank_ac_no"
- }, {
- "label": "PF Number",
- "fieldname": "pf_number",
- "fieldtype": "Data",
- "insert_after": "bank_ac_no"
- }],
- "Salary Slip": [{
- "label": "Esic No",
- "fieldname": "esic_no",
- "fieldtype": "Data",
- "insert_after": "letter_head",
- "permlevel": 1
- }, {
- "label": "PF Number",
- "fieldname": "pf_no",
- "fieldtype": "Data",
- "insert_after": "letter_head",
- "permlevel": 1
- }]
- }
-
- for dt, docfields in india_specific_fields.items():
- for df in docfields:
- create_custom_field_if_values_exist(dt, df)
diff --git a/erpnext/patches/v4_0/create_price_list_if_missing.py b/erpnext/patches/v4_0/create_price_list_if_missing.py
deleted file mode 100644
index 039e52111c..0000000000
--- a/erpnext/patches/v4_0/create_price_list_if_missing.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-from frappe.utils.nestedset import get_root_of
-
-def execute():
- # setup not complete
- if not frappe.db.sql("""select name from tabCompany limit 1"""):
- return
-
- if "shopping_cart" in frappe.get_installed_apps():
- frappe.reload_doc("shopping_cart", "doctype", "shopping_cart_settings")
-
- if not frappe.db.sql("select name from `tabPrice List` where buying=1"):
- create_price_list(_("Standard Buying"), buying=1)
-
- if not frappe.db.sql("select name from `tabPrice List` where selling=1"):
- create_price_list(_("Standard Selling"), selling=1)
-
-def create_price_list(pl_name, buying=0, selling=0):
- price_list = frappe.get_doc({
- "doctype": "Price List",
- "price_list_name": pl_name,
- "enabled": 1,
- "buying": buying,
- "selling": selling,
- "currency": frappe.db.get_default("currency"),
- "territories": [{
- "territory": get_root_of("Territory")
- }]
- })
- price_list.insert()
diff --git a/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py b/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py
deleted file mode 100644
index 1b260c48cc..0000000000
--- a/erpnext/patches/v4_0/customer_discount_to_pricing_rule.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils.nestedset import get_root_of
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "pricing_rule")
-
- frappe.db.auto_commit_on_many_writes = True
-
- default_item_group = get_root_of("Item Group")
-
- for d in frappe.db.sql("""select * from `tabCustomer Discount`
- where ifnull(parent, '') != ''""", as_dict=1):
- if not d.discount:
- continue
-
- frappe.get_doc({
- "doctype": "Pricing Rule",
- "apply_on": "Item Group",
- "item_group": d.item_group or default_item_group,
- "applicable_for": "Customer",
- "customer": d.parent,
- "price_or_discount": "Discount Percentage",
- "discount_percentage": d.discount,
- "selling": 1
- }).insert()
-
- frappe.db.auto_commit_on_many_writes = False
-
- frappe.delete_doc("DocType", "Customer Discount")
diff --git a/erpnext/patches/v4_0/fields_to_be_renamed.py b/erpnext/patches/v4_0/fields_to_be_renamed.py
deleted file mode 100644
index cc17697132..0000000000
--- a/erpnext/patches/v4_0/fields_to_be_renamed.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-from frappe.modules import scrub, get_doctype_module
-
-rename_map = {
- "Quotation Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"]
- ],
-
- "Sales Order Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"],
- ["reserved_warehouse", "warehouse"]
- ],
-
- "Delivery Note Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"]
- ],
-
- "Sales Invoice Item": [
- ["ref_rate", "price_list_rate"],
- ["base_ref_rate", "base_price_list_rate"],
- ["adj_rate", "discount_percentage"],
- ["export_rate", "rate"],
- ["basic_rate", "base_rate"],
- ["amount", "base_amount"],
- ["export_amount", "amount"]
- ],
-
- "Supplier Quotation Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["purchase_rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"]
- ],
-
- "Purchase Order Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["purchase_rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"]
- ],
-
- "Purchase Receipt Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["purchase_rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"]
- ],
-
- "Purchase Invoice Item": [
- ["import_ref_rate", "price_list_rate"],
- ["purchase_ref_rate", "base_price_list_rate"],
- ["discount_rate", "discount_percentage"],
- ["import_rate", "rate"],
- ["rate", "base_rate"],
- ["amount", "base_amount"],
- ["import_amount", "amount"],
- ["expense_head", "expense_account"]
- ],
-
- "Item": [
- ["purchase_account", "expense_account"],
- ["default_sales_cost_center", "selling_cost_center"],
- ["cost_center", "buying_cost_center"],
- ["default_income_account", "income_account"],
- ],
- "Item Price": [
- ["ref_rate", "price_list_rate"]
- ]
-}
-
-def execute():
- for dn in rename_map:
- frappe.reload_doc(get_doctype_module(dn), "doctype", scrub(dn))
-
- for dt, field_list in rename_map.items():
- for field in field_list:
- rename_field(dt, field[0], field[1])
diff --git a/erpnext/patches/v4_0/fix_address_template.py b/erpnext/patches/v4_0/fix_address_template.py
deleted file mode 100644
index 905e3db3e8..0000000000
--- a/erpnext/patches/v4_0/fix_address_template.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- missing_line = """{{ address_line1 }}
"""
- for name, template in frappe.db.sql("select name, template from `tabAddress Template`"):
- if missing_line not in template:
- d = frappe.get_doc("Address Template", name)
- d.template = missing_line + d.template
- d.save()
diff --git a/erpnext/patches/v4_0/fix_case_of_hr_module_def.py b/erpnext/patches/v4_0/fix_case_of_hr_module_def.py
deleted file mode 100644
index e77b427b77..0000000000
--- a/erpnext/patches/v4_0/fix_case_of_hr_module_def.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- hr = frappe.db.get_value("Module Def", "HR")
- if hr == "Hr":
- frappe.rename_doc("Module Def", "Hr", "HR")
- frappe.db.set_value("Module Def", "HR", "module_name", "HR")
-
- frappe.clear_cache()
- frappe.setup_module_map()
diff --git a/erpnext/patches/v4_0/fix_contact_address.py b/erpnext/patches/v4_0/fix_contact_address.py
deleted file mode 100644
index 6a3e106b8c..0000000000
--- a/erpnext/patches/v4_0/fix_contact_address.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("website", "doctype", "contact_us_settings")
- address = frappe.db.get_value("Contact Us Settings", None, "address")
- if address:
- address = frappe.get_doc("Address", address)
- contact = frappe.get_doc("Contact Us Settings", "Contact Us Settings")
- for f in ("address_title", "address_line1", "address_line2", "city", "state", "country", "pincode"):
- contact.set(f, address.get(f))
-
- contact.save()
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/fix_employee_user_id.py b/erpnext/patches/v4_0/fix_employee_user_id.py
deleted file mode 100644
index 6f449f97bb..0000000000
--- a/erpnext/patches/v4_0/fix_employee_user_id.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-from frappe.utils import get_fullname
-
-def execute():
- for user_id in frappe.db.sql_list("""select distinct user_id from `tabEmployee`
- where ifnull(user_id, '')!=''
- group by user_id having count(name) > 1"""):
-
- fullname = get_fullname(user_id)
- employee = frappe.db.get_value("Employee", {"employee_name": fullname, "user_id": user_id})
-
- if employee:
- frappe.db.sql("""update `tabEmployee` set user_id=null
- where user_id=%s and name!=%s""", (user_id, employee))
- else:
- count = frappe.db.sql("""select count(*) from `tabEmployee` where user_id=%s""", user_id)[0][0]
- frappe.db.sql("""update `tabEmployee` set user_id=null
- where user_id=%s limit %s""", (user_id, count - 1))
diff --git a/erpnext/patches/v4_0/global_defaults_to_system_settings.py b/erpnext/patches/v4_0/global_defaults_to_system_settings.py
deleted file mode 100644
index 2905fe1e6a..0000000000
--- a/erpnext/patches/v4_0/global_defaults_to_system_settings.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# MIT License. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-from collections import Counter
-from frappe.core.doctype.user.user import STANDARD_USERS
-
-def execute():
- frappe.reload_doc("core", "doctype", "system_settings")
- system_settings = frappe.get_doc("System Settings")
-
- # set values from global_defauls
- global_defaults = frappe.db.get_value("Global Defaults", None,
- ["time_zone", "date_format", "number_format", "float_precision", "session_expiry"], as_dict=True)
-
- if global_defaults:
- for key, val in global_defaults.items():
- if not system_settings.get(key):
- system_settings.set(key, val)
-
- # language
- if not system_settings.get("language"):
- # find most common language
- lang = frappe.db.sql_list("""select language from `tabUser`
- where ifnull(language, '')!='' and language not like "Loading%%" and name not in ({standard_users})""".format(
- standard_users=", ".join(["%s"]*len(STANDARD_USERS))), tuple(STANDARD_USERS))
- lang = Counter(lang).most_common(1)
- lang = (len(lang) > 0) and lang[0][0] or "english"
-
- system_settings.language = lang
-
- system_settings.flags.ignore_mandatory = True
- system_settings.save()
-
- global_defaults = frappe.get_doc("Global Defaults")
- global_defaults.flags.ignore_mandatory = True
- global_defaults.save()
diff --git a/erpnext/patches/v4_0/import_country_codes.py b/erpnext/patches/v4_0/import_country_codes.py
deleted file mode 100644
index 43e23d5b63..0000000000
--- a/erpnext/patches/v4_0/import_country_codes.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# MIT License. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.geo.country_info import get_all
-from frappe.utils.install import import_country_and_currency
-
-from six import iteritems
-
-def execute():
- frappe.reload_doc("setup", "doctype", "country")
- import_country_and_currency()
- for name, country in iteritems(get_all()):
- frappe.set_value("Country", name, "code", country.get("code"))
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py b/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py
deleted file mode 100644
index 97e217aa05..0000000000
--- a/erpnext/patches/v4_0/map_charge_to_taxes_and_charges.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # update sales cycle
- for d in ['Sales Invoice', 'Sales Order', 'Quotation', 'Delivery Note']:
- frappe.db.sql("""update `tab%s` set taxes_and_charges=charge""" % d)
-
- # update purchase cycle
- for d in ['Purchase Invoice', 'Purchase Order', 'Supplier Quotation', 'Purchase Receipt']:
- frappe.db.sql("""update `tab%s` set taxes_and_charges=purchase_other_charges""" % d)
-
- frappe.db.sql("""update `tabPurchase Taxes and Charges` set parentfield='other_charges'""")
diff --git a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py b/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
deleted file mode 100644
index 8b81936d8d..0000000000
--- a/erpnext/patches/v4_0/move_warehouse_user_to_restrictions.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- for warehouse, user in frappe.db.sql("""select parent, user from `tabWarehouse User`"""):
- frappe.permissions.add_user_permission("Warehouse", warehouse, user)
-
- frappe.delete_doc_if_exists("DocType", "Warehouse User")
- frappe.reload_doc("stock", "doctype", "warehouse")
diff --git a/erpnext/patches/v4_0/new_address_template.py b/erpnext/patches/v4_0/new_address_template.py
deleted file mode 100644
index fa6602706e..0000000000
--- a/erpnext/patches/v4_0/new_address_template.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("utilities", "doctype", "address_template")
- if not frappe.db.sql("select name from `tabAddress Template`"):
- try:
- d = frappe.new_doc("Address Template")
- d.update({"country":frappe.db.get_default("country") or
- frappe.db.get_value("Global Defaults", "Global Defaults", "country")})
- d.insert()
- except:
- print(frappe.get_traceback())
-
diff --git a/erpnext/patches/v4_0/reload_sales_print_format.py b/erpnext/patches/v4_0/reload_sales_print_format.py
deleted file mode 100644
index b8f090f9f3..0000000000
--- a/erpnext/patches/v4_0/reload_sales_print_format.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'Print Format', 'POS Invoice')
diff --git a/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py b/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
deleted file mode 100644
index 8766ace54f..0000000000
--- a/erpnext/patches/v4_0/remove_employee_role_if_no_employee.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- for user in frappe.db.sql_list("select distinct parent from `tabHas Role` where role='Employee'"):
- # if employee record does not exists, remove employee role!
- if not frappe.db.get_value("Employee", {"user_id": user}):
- try:
- user = frappe.get_doc("User", user)
- for role in user.get("roles", {"role": "Employee"}):
- user.get("roles").remove(role)
- user.save()
- except frappe.DoesNotExistError:
- pass
diff --git a/erpnext/patches/v4_0/remove_module_home_pages.py b/erpnext/patches/v4_0/remove_module_home_pages.py
deleted file mode 100644
index a2720e0ebf..0000000000
--- a/erpnext/patches/v4_0/remove_module_home_pages.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for page in ("accounts-home", "website-home", "support-home", "stock-home", "selling-home", "projects-home",
- "manufacturing-home", "hr-home", "buying-home"):
- frappe.delete_doc("Page", page)
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/rename_sitemap_to_route.py b/erpnext/patches/v4_0/rename_sitemap_to_route.py
deleted file mode 100644
index ffb1fda144..0000000000
--- a/erpnext/patches/v4_0/rename_sitemap_to_route.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import frappe.model
-
-def execute():
- frappe.reload_doc("setup", "doctype", "item_group")
- frappe.reload_doc("stock", "doctype", "item")
- frappe.reload_doc("setup", "doctype", "sales_partner")
-
- try:
- frappe.model.rename_field("Item Group", "parent_website_sitemap", "parent_website_route")
- frappe.model.rename_field("Item", "parent_website_sitemap", "parent_website_route")
- frappe.model.rename_field("Sales Partner", "parent_website_sitemap",
- "parent_website_route")
- except Exception as e:
- if e.args[0]!=1054:
- raise
diff --git a/erpnext/patches/v4_0/reset_permissions_for_masters.py b/erpnext/patches/v4_0/reset_permissions_for_masters.py
deleted file mode 100644
index bc1b438e2b..0000000000
--- a/erpnext/patches/v4_0/reset_permissions_for_masters.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-from frappe.permissions import reset_perms
-
-def execute():
- for doctype in ("About Us Settings", "Accounts Settings", "Activity Type",
- "Blog Category", "Blog Settings", "Blogger", "Branch", "Brand", "Buying Settings",
- "Communication", "Company", "Contact Us Settings",
- "Country", "Currency", "Currency Exchange", "Deduction Type", "Department",
- "Designation", "Earning Type", "Event", "Feed", "File", "Fiscal Year",
- "HR Settings", "Industry Type", "Leave Type", "Letter Head",
- "Mode of Payment", "Module Def", "Naming Series", "POS Setting", "Print Heading",
- "Report", "Role", "Selling Settings", "Stock Settings", "Supplier Type", "UOM"):
- try:
- reset_perms(doctype)
- except:
- print("Error resetting perms for", doctype)
- raise
diff --git a/erpnext/patches/v4_0/save_default_letterhead.py b/erpnext/patches/v4_0/save_default_letterhead.py
deleted file mode 100644
index 5d75f096b3..0000000000
--- a/erpnext/patches/v4_0/save_default_letterhead.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """save default letterhead to set default_letter_head_content"""
- try:
- letter_head = frappe.get_doc("Letter Head", {"is_default": 1})
- letter_head.save()
- except frappe.DoesNotExistError:
- pass
diff --git a/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py b/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
deleted file mode 100644
index 7e472e2195..0000000000
--- a/erpnext/patches/v4_0/set_pricing_rule_for_buying_or_selling.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "pricing_rule")
- frappe.db.sql("""update `tabPricing Rule` set selling=1 where ifnull(applicable_for, '') in
- ('', 'Customer', 'Customer Group', 'Territory', 'Sales Partner', 'Campaign')""")
-
- frappe.db.sql("""update `tabPricing Rule` set buying=1 where ifnull(applicable_for, '') in
- ('', 'Supplier', 'Supplier Type')""")
diff --git a/erpnext/patches/v4_0/split_email_settings.py b/erpnext/patches/v4_0/split_email_settings.py
deleted file mode 100644
index 5d1dea60ee..0000000000
--- a/erpnext/patches/v4_0/split_email_settings.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- print("WARNING!!!! Email Settings not migrated. Please setup your email again.")
-
- # this will happen if you are migrating very old accounts
- # comment out this line below and remember to create new Email Accounts
- # for incoming and outgoing mails
- raise Exception
-
- return
-
-
- frappe.reload_doc("core", "doctype", "outgoing_email_settings")
- frappe.reload_doc("support", "doctype", "support_email_settings")
-
- email_settings = get_email_settings()
- map_outgoing_email_settings(email_settings)
- map_support_email_settings(email_settings)
-
-
-def map_outgoing_email_settings(email_settings):
- outgoing_email_settings = frappe.get_doc("Outgoing Email Settings")
- for fieldname in (("outgoing_mail_server", "mail_server"),
- "use_ssl", "mail_port", "mail_login", "mail_password",
- "always_use_login_id_as_sender", "auto_email_id"):
-
- if isinstance(fieldname, tuple):
- from_fieldname, to_fieldname = fieldname
- else:
- from_fieldname = to_fieldname = fieldname
-
- outgoing_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
-
- outgoing_email_settings._fix_numeric_types()
- outgoing_email_settings.save()
-
-def map_support_email_settings(email_settings):
- support_email_settings = frappe.get_doc("Support Email Settings")
-
- for fieldname in ("sync_support_mails", "support_email",
- ("support_host", "mail_server"),
- ("support_use_ssl", "use_ssl"),
- ("support_username", "mail_login"),
- ("support_password", "mail_password"),
- "support_signature", "send_autoreply", "support_autoreply"):
-
- if isinstance(fieldname, tuple):
- from_fieldname, to_fieldname = fieldname
- else:
- from_fieldname = to_fieldname = fieldname
-
- support_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
-
- support_email_settings._fix_numeric_types()
- support_email_settings.save()
-
-def get_email_settings():
- ret = {}
- for field, value in frappe.db.sql("select field, value from tabSingles where doctype='Email Settings'"):
- ret[field] = value
- return ret
-
diff --git a/erpnext/patches/v4_0/update_account_root_type.py b/erpnext/patches/v4_0/update_account_root_type.py
deleted file mode 100644
index 15ddf032a4..0000000000
--- a/erpnext/patches/v4_0/update_account_root_type.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
-
- account_table_columns = frappe.db.get_table_columns("Account")
- if "debit_or_credit" in account_table_columns and "is_pl_account" in account_table_columns:
- frappe.db.sql("""UPDATE tabAccount
- SET root_type = CASE
- WHEN (debit_or_credit='Debit' and is_pl_account = 'No') THEN 'Asset'
- WHEN (debit_or_credit='Credit' and is_pl_account = 'No') THEN 'Liability'
- WHEN (debit_or_credit='Debit' and is_pl_account = 'Yes') THEN 'Expense'
- WHEN (debit_or_credit='Credit' and is_pl_account = 'Yes') THEN 'Income'
- END
- WHERE ifnull(parent_account, '') = ''
- """)
-
- else:
- for key, root_type in (("asset", "Asset"), ("liabilities", "Liability"), ("expense", "Expense"),
- ("income", "Income")):
- frappe.db.sql("""update tabAccount set root_type=%s where name like %s
- and ifnull(parent_account, '')=''""", (root_type, "%" + key + "%"))
-
- for root in frappe.db.sql("""SELECT name, lft, rgt, root_type FROM `tabAccount`
- WHERE ifnull(parent_account, '')=''""", as_dict=True):
- if root.root_type:
- frappe.db.sql("""UPDATE tabAccount SET root_type=%s WHERE lft>%s and rgt<%s""",
- (root.root_type, root.lft, root.rgt))
- else:
- print(b"Root type not found for {0}".format(root.name.encode("utf-8")))
diff --git a/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py b/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py
deleted file mode 100644
index d784a1b182..0000000000
--- a/erpnext/patches/v4_0/update_custom_print_formats_for_renamed_fields.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import re
-
-def execute():
- # NOTE: sequence is important
- fields_list = (
- ("amount", "base_amount"),
- ("ref_rate", "price_list_rate"),
- ("base_ref_rate", "base_price_list_rate"),
- ("adj_rate", "discount_percentage"),
- ("export_rate", "rate"),
- ("basic_rate", "base_rate"),
- ("export_amount", "amount"),
- ("reserved_warehouse", "warehouse"),
- ("import_ref_rate", "price_list_rate"),
- ("purchase_ref_rate", "base_price_list_rate"),
- ("discount_rate", "discount_percentage"),
- ("import_rate", "rate"),
- ("purchase_rate", "base_rate"),
- ("import_amount", "amount")
- )
-
- condition = " or ".join("""html like "%%{}%%" """.format(d[0].replace("_", "\\_")) for d in fields_list
- if d[0] != "amount")
-
- for name, html in frappe.db.sql("""select name, html from `tabPrint Format`
- where standard = 'No' and ({}) and html not like '%%frappe.%%'""".format(condition)):
- html = html.replace("wn.", "frappe.")
- for from_field, to_field in fields_list:
- html = re.sub(r"\b{}\b".format(from_field), to_field, html)
-
- frappe.db.set_value("Print Format", name, "html", html)
diff --git a/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py b/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py
deleted file mode 100644
index fe66a5e3ef..0000000000
--- a/erpnext/patches/v4_0/update_incharge_name_to_sales_person_in_maintenance_schedule.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("support", "doctype", "schedules")
- frappe.reload_doc("support", "doctype", "maintenance_schedule_item")
-
- frappe.db.sql("""update `tabMaintenance Schedule Detail` set sales_person=incharge_name""")
- frappe.db.sql("""update `tabMaintenance Schedule Item` set sales_person=incharge_name""")
\ No newline at end of file
diff --git a/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py b/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py
deleted file mode 100644
index 2e2e77a9fc..0000000000
--- a/erpnext/patches/v4_0/update_other_charges_in_custom_purchase_print_formats.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import re
-
-def execute():
- for name, html in frappe.db.sql("""select name, html from `tabPrint Format`
- where standard = 'No' and html like '%%purchase\\_tax\\_details%%'"""):
- html = re.sub(r"\bpurchase_tax_details\b", "taxes", html)
- frappe.db.set_value("Print Format", name, "html", html)
diff --git a/erpnext/patches/v4_0/update_tax_amount_after_discount.py b/erpnext/patches/v4_0/update_tax_amount_after_discount.py
deleted file mode 100644
index d10329ef37..0000000000
--- a/erpnext/patches/v4_0/update_tax_amount_after_discount.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "sales_taxes_and_charges")
- docs_with_discount_amount = frappe._dict()
- for dt in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
- records = frappe.db.sql_list("""select name from `tab%s`
- where ifnull(discount_amount, 0) > 0 and docstatus=1""" % dt)
- docs_with_discount_amount[dt] = records
-
- for dt, discounted_records in docs_with_discount_amount.items():
- frappe.db.sql("""update `tabSales Taxes and Charges`
- set tax_amount_after_discount_amount = tax_amount
- where parenttype = %s and parent not in (%s)""" %
- ('%s', ', '.join(['%s']*(len(discounted_records)+1))),
- tuple([dt, ''] + discounted_records))
diff --git a/erpnext/patches/v4_0/update_user_properties.py b/erpnext/patches/v4_0/update_user_properties.py
deleted file mode 100644
index f2085ce4df..0000000000
--- a/erpnext/patches/v4_0/update_user_properties.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-import frappe.defaults
-
-def execute():
- frappe.reload_doc("core", "doctype", "docfield")
- frappe.reload_doc("hr", "doctype", "employee")
-
- set_print_email_permissions()
- migrate_user_properties_to_user_permissions()
-
- frappe.clear_cache()
-
-def migrate_user_properties_to_user_permissions():
- for d in frappe.db.sql("""select parent, defkey, defvalue from tabDefaultValue
- where parent not in ('__global', '__default')""", as_dict=True):
- df = frappe.db.sql("""select options from tabDocField
- where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True)
-
- if df:
- frappe.db.sql("""update tabDefaultValue
- set defkey=%s, parenttype='User Permission'
- where defkey=%s and
- parent not in ('__global', '__default')""", (df[0].options, d.defkey))
-
-def set_print_email_permissions():
- # reset Page perms
- from frappe.core.page.permission_manager.permission_manager import reset
- reset("Page")
- reset("Report")
-
- if "allow_print" not in frappe.db.get_table_columns("DocType"):
- return
-
- # patch to move print, email into DocPerm
- # NOTE: allow_print and allow_email are misnamed. They were used to hide print / hide email
- for doctype, hide_print, hide_email in frappe.db.sql("""select name, ifnull(allow_print, 0), ifnull(allow_email, 0)
- from `tabDocType` where ifnull(issingle, 0)=0 and ifnull(istable, 0)=0 and
- (ifnull(allow_print, 0)=0 or ifnull(allow_email, 0)=0)"""):
-
- if not hide_print:
- frappe.db.sql("""update `tabDocPerm` set `print`=1
- where permlevel=0 and `read`=1 and parent=%s""", doctype)
-
- if not hide_email:
- frappe.db.sql("""update `tabDocPerm` set `email`=1
- where permlevel=0 and `read`=1 and parent=%s""", doctype)
diff --git a/erpnext/patches/v4_0/update_users_report_view_settings.py b/erpnext/patches/v4_0/update_users_report_view_settings.py
deleted file mode 100644
index 6f216f5b38..0000000000
--- a/erpnext/patches/v4_0/update_users_report_view_settings.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-from frappe.model.utils.rename_field import update_users_report_view_settings
-from erpnext.patches.v4_0.fields_to_be_renamed import rename_map
-
-def execute():
- for dt, field_list in rename_map.items():
- for field in field_list:
- update_users_report_view_settings(dt, field[0], field[1])
diff --git a/erpnext/patches/v4_0/validate_v3_patch.py b/erpnext/patches/v4_0/validate_v3_patch.py
deleted file mode 100644
index 3df39edea6..0000000000
--- a/erpnext/patches/v4_0/validate_v3_patch.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from frappe.modules.patch_handler import executed
- last_v3_patch = 'patches.1401.fix_pos_outstanding'
- if not executed(last_v3_patch):
- raise Exception("site not ready to migrate to version 4")
diff --git a/erpnext/patches/v4_1/__init__.py b/erpnext/patches/v4_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_1/fix_delivery_and_billing_status.py b/erpnext/patches/v4_1/fix_delivery_and_billing_status.py
deleted file mode 100644
index 8cc6a4b0be..0000000000
--- a/erpnext/patches/v4_1/fix_delivery_and_billing_status.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabSales Order` set delivery_status = 'Not Delivered'
- where delivery_status = 'Delivered' and ifnull(per_delivered, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""")
-
- frappe.db.sql("""update `tabSales Order` set billing_status = 'Not Billed'
- where billing_status = 'Billed' and ifnull(per_billed, 0) = 0 and ifnull(docstatus, 0) in (0, 1)""")
diff --git a/erpnext/patches/v4_1/fix_jv_remarks.py b/erpnext/patches/v4_1/fix_jv_remarks.py
deleted file mode 100644
index e07bf05f1a..0000000000
--- a/erpnext/patches/v4_1/fix_jv_remarks.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- reference_date = guess_reference_date()
- for name in frappe.db.sql_list("""select name from `tabJournal Entry`
- where date(creation)>=%s""", reference_date):
- jv = frappe.get_doc("Journal Entry", name)
- try:
- jv.create_remarks()
- except frappe.MandatoryError:
- pass
- else:
- frappe.db.set_value("Journal Entry", jv.name, "remark", jv.remark)
-
-def guess_reference_date():
- return (frappe.db.get_value("Patch Log", {"patch": "erpnext.patches.v4_0.validate_v3_patch"}, "creation")
- or "2014-05-06")
diff --git a/erpnext/patches/v4_1/fix_sales_order_delivered_status.py b/erpnext/patches/v4_1/fix_sales_order_delivered_status.py
deleted file mode 100644
index 66037b8958..0000000000
--- a/erpnext/patches/v4_1/fix_sales_order_delivered_status.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for si in frappe.db.sql_list("""select name
- from `tabSales Invoice`
- where ifnull(update_stock,0) = 1 and docstatus = 1 and exists(
- select name from `tabSales Invoice Item` where parent=`tabSales Invoice`.name and
- ifnull(so_detail, "") != "")"""):
-
- invoice = frappe.get_doc("Sales Invoice", si)
- invoice.update_qty()
diff --git a/erpnext/patches/v4_1/set_outgoing_email_footer.py b/erpnext/patches/v4_1/set_outgoing_email_footer.py
deleted file mode 100644
index 54d016bf5f..0000000000
--- a/erpnext/patches/v4_1/set_outgoing_email_footer.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.setup.install import default_mail_footer
-
-def execute():
- return
- mail_footer = frappe.db.get_default('mail_footer') or ''
- mail_footer += default_mail_footer
- frappe.db.set_value("Outgoing Email Settings", "Outgoing Email Settings", "footer", mail_footer)
diff --git a/erpnext/patches/v4_2/__init__.py b/erpnext/patches/v4_2/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_2/add_currency_turkish_lira.py b/erpnext/patches/v4_2/add_currency_turkish_lira.py
deleted file mode 100644
index 1a46089f94..0000000000
--- a/erpnext/patches/v4_2/add_currency_turkish_lira.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- return
- # country = get_country_info(country="Turkey")
- # add_country_and_currency("Turkey", country)
diff --git a/erpnext/patches/v4_2/default_website_style.py b/erpnext/patches/v4_2/default_website_style.py
deleted file mode 100644
index e8f9502ea6..0000000000
--- a/erpnext/patches/v4_2/default_website_style.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- return
- # frappe.reload_doc('website', 'doctype', 'style_settings')
- # style_settings = frappe.get_doc("Style Settings", "Style Settings")
- # if not style_settings.apply_style:
- # style_settings.update(default_properties)
- # style_settings.apply_style = 1
- # style_settings.save()
diff --git a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py b/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
deleted file mode 100644
index 169b1e2927..0000000000
--- a/erpnext/patches/v4_2/delete_gl_entries_for_cancelled_invoices.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice`
- where docstatus = 2 and ifnull(update_stock, 0) = 1""")
-
- if cancelled_invoices:
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
- % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/delete_old_print_formats.py b/erpnext/patches/v4_2/delete_old_print_formats.py
deleted file mode 100644
index cacdb85ce0..0000000000
--- a/erpnext/patches/v4_2/delete_old_print_formats.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- old_formats = ("Sales Invoice", "Sales Invoice Spartan", "Sales Invoice Modern",
- "Sales Invoice Classic",
- "Sales Order Spartan", "Sales Order Modern", "Sales Order Classic",
- "Purchase Order Spartan", "Purchase Order Modern", "Purchase Order Classic",
- "Quotation Spartan", "Quotation Modern", "Quotation Classic",
- "Delivery Note Spartan", "Delivery Note Modern", "Delivery Note Classic")
-
- for fmt in old_formats:
- # update property setter
- for ps in frappe.db.sql_list("""select name from `tabProperty Setter`
- where property='default_print_format' and value=%s""", fmt):
- ps = frappe.get_doc("Property Setter", ps)
- ps.value = "Standard"
- ps.save(ignore_permissions = True)
-
- frappe.delete_doc_if_exists("Print Format", fmt)
diff --git a/erpnext/patches/v4_2/discount_amount.py b/erpnext/patches/v4_2/discount_amount.py
deleted file mode 100644
index 7ab61bdbea..0000000000
--- a/erpnext/patches/v4_2/discount_amount.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.modules import scrub, get_doctype_module
-
-def execute():
- for dt in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
- frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt))
- frappe.db.sql("""update `tab{0}` set base_discount_amount=discount_amount,
- discount_amount=discount_amount/conversion_rate""".format(dt))
diff --git a/erpnext/patches/v4_2/fix_account_master_type.py b/erpnext/patches/v4_2/fix_account_master_type.py
deleted file mode 100644
index 99444ce83b..0000000000
--- a/erpnext/patches/v4_2/fix_account_master_type.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.db.sql("""select name from `tabAccount`
- where ifnull(master_type, '') not in ('Customer', 'Supplier', 'Employee', '') and docstatus=0"""):
- ac = frappe.get_doc("Account", d[0])
- ac.master_type = None
- ac.save()
diff --git a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py b/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
deleted file mode 100644
index c6c94d4179..0000000000
--- a/erpnext/patches/v4_2/fix_gl_entries_for_stock_transactions.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- from erpnext.stock.stock_balance import repost
- repost(allow_zero_rate=True, only_actual=True)
-
- frappe.reload_doctype("Account")
-
- warehouse_account = frappe.db.sql("""select name, master_name from tabAccount
- where ifnull(account_type, '') = 'Warehouse'""")
- if warehouse_account:
- warehouses = [d[1] for d in warehouse_account]
- accounts = [d[0] for d in warehouse_account]
-
- stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
- from `tabStock Ledger Entry` sle
- where sle.warehouse in (%s)
- order by sle.posting_date""" %
- ', '.join(['%s']*len(warehouses)), tuple(warehouses))
-
- rejected = []
- for voucher_type, voucher_no in stock_vouchers:
- stock_bal = frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry`
- where voucher_type=%s and voucher_no =%s and warehouse in (%s)""" %
- ('%s', '%s', ', '.join(['%s']*len(warehouses))), tuple([voucher_type, voucher_no] + warehouses))
-
- account_bal = frappe.db.sql("""select ifnull(sum(ifnull(debit, 0) - ifnull(credit, 0)), 0)
- from `tabGL Entry`
- where voucher_type=%s and voucher_no =%s and account in (%s)
- group by voucher_type, voucher_no""" %
- ('%s', '%s', ', '.join(['%s']*len(accounts))), tuple([voucher_type, voucher_no] + accounts))
-
- if stock_bal and account_bal and abs(flt(stock_bal[0][0]) - flt(account_bal[0][0])) > 0.1:
- try:
- print(voucher_type, voucher_no, stock_bal[0][0], account_bal[0][0])
-
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
-
- voucher = frappe.get_doc(voucher_type, voucher_no)
- voucher.make_gl_entries()
- frappe.db.commit()
- except Exception as e:
- print(frappe.get_traceback())
- rejected.append([voucher_type, voucher_no])
- frappe.db.rollback()
-
- print("Failed to repost: ")
- print(rejected)
diff --git a/erpnext/patches/v4_2/fix_recurring_orders.py b/erpnext/patches/v4_2/fix_recurring_orders.py
deleted file mode 100644
index ea1724a040..0000000000
--- a/erpnext/patches/v4_2/fix_recurring_orders.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- sales_orders = frappe.db.sql("""select name from `tabSales Order`
- where docstatus = 1 and ifnull(is_recurring, 0) = 1
- and (per_delivered > 0 or per_billed > 0)""", as_dict=1)
-
- for so in sales_orders:
- if not frappe.db.exists("Delivery Note Item", {"against_sales_order": so.name, "docstatus": 1}):
- frappe.db.sql("""update `tabSales Order` set per_delivered = 0,
- delivery_status = 'Not Delivered' where name = %s""", so.name)
- frappe.db.sql("""update `tabSales Order Item` set delivered_qty = 0
- where parent = %s""", so.name)
-
- if not frappe.db.exists("Sales Invoice Item", {"sales_order": so.name, "docstatus": 1}):
- frappe.db.sql("""update `tabSales Order` set per_billed = 0,
- billing_status = 'Not Billed' where name = %s""", so.name)
- frappe.db.sql("""update `tabSales Order Item` set billed_amt = 0
- where parent = %s""", so.name)
-
- purchase_orders = frappe.db.sql("""select name from `tabPurchase Order`
- where docstatus = 1 and ifnull(is_recurring, 0) = 1
- and (per_received > 0 or per_billed > 0)""", as_dict=1)
-
- for po in purchase_orders:
- if not frappe.db.exists("Purchase Receipt Item", {"prevdoc_doctype": "Purchase Order",
- "prevdoc_docname": po.name, "docstatus": 1}):
- frappe.db.sql("""update `tabPurchase Order` set per_received = 0
- where name = %s""", po.name)
- frappe.db.sql("""update `tabPurchase Order Item` set received_qty = 0
- where parent = %s""", po.name)
-
- if not frappe.db.exists("Purchase Invoice Item", {"purchase_order": po.name, "docstatus": 1}):
- frappe.db.sql("""update `tabPurchase Order` set per_billed = 0
- where name = %s""", po.name)
- frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0
- where parent = %s""", po.name)
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/party_model.py b/erpnext/patches/v4_2/party_model.py
deleted file mode 100644
index 46d7fffee1..0000000000
--- a/erpnext/patches/v4_2/party_model.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
- frappe.reload_doc("setup", "doctype", "company")
- frappe.reload_doc("accounts", "doctype", "gl_entry")
- frappe.reload_doc("accounts", "doctype", "journal_entry_account")
- receivable_payable_accounts = create_receivable_payable_account()
- if receivable_payable_accounts:
- set_party_in_jv_and_gl_entry(receivable_payable_accounts)
- delete_individual_party_account()
- remove_customer_supplier_account_report()
-
-def create_receivable_payable_account():
- receivable_payable_accounts = frappe._dict()
-
- def _create_account(args):
- if args["parent_account"] and frappe.db.exists("Account", args["parent_account"]):
- account_id = frappe.db.get_value("Account",
- {"account_name": args["account_name"], "company": args["company"]})
- if not account_id:
- account = frappe.new_doc("Account")
- account.is_group = 0
- account.update(args)
- account.insert()
-
- account_id = account.name
-
- frappe.db.set_value("Company", args["company"], ("default_receivable_account"
- if args["account_type"]=="Receivable" else "default_payable_account"), account_id)
-
- receivable_payable_accounts.setdefault(args["company"], {}).setdefault(args["account_type"], account_id)
-
- for company in frappe.db.sql_list("select name from tabCompany"):
- _create_account({
- "account_name": "Debtors",
- "account_type": "Receivable",
- "company": company,
- "parent_account": get_parent_account(company, "Customer")
- })
-
- _create_account({
- "account_name": "Creditors",
- "account_type": "Payable",
- "company": company,
- "parent_account": get_parent_account(company, "Supplier")
- })
-
- return receivable_payable_accounts
-
-def get_parent_account(company, master_type):
- parent_account = None
-
- if "receivables_group" in frappe.db.get_table_columns("Company"):
- parent_account = frappe.get_cached_value('Company', company,
- "receivables_group" if master_type=="Customer" else "payables_group")
- if not parent_account:
- parent_account = frappe.db.get_value("Account", {"company": company,
- "account_name": "Accounts Receivable" if master_type=="Customer" else "Accounts Payable"})
-
- if not parent_account:
- parent_account = frappe.db.sql_list("""select parent_account from tabAccount
- where company=%s and ifnull(master_type, '')=%s and ifnull(master_name, '')!='' limit 1""",
- (company, master_type))
- parent_account = parent_account[0][0] if parent_account else None
-
- return parent_account
-
-def set_party_in_jv_and_gl_entry(receivable_payable_accounts):
- accounts = frappe.db.sql("""select name, master_type, master_name, company from `tabAccount`
- where ifnull(master_type, '') in ('Customer', 'Supplier') and ifnull(master_name, '') != ''""", as_dict=1)
-
- account_map = frappe._dict()
- for d in accounts:
- account_map.setdefault(d.name, d)
-
- if not account_map:
- return
-
- for dt in ["Journal Entry Account", "GL Entry"]:
- records = frappe.db.sql("""select name, account from `tab%s`
- where account in (%s) and ifnull(party, '') = '' and docstatus < 2""" %
- (dt, ", ".join(['%s']*len(account_map))), tuple(account_map.keys()), as_dict=1)
- for i, d in enumerate(records):
- account_details = account_map.get(d.account, {})
- account_type = "Receivable" if account_details.get("master_type")=="Customer" else "Payable"
- new_account = receivable_payable_accounts[account_details.get("company")][account_type]
-
- frappe.db.sql("update `tab{0}` set account=%s, party_type=%s, party=%s where name=%s".format(dt),
- (new_account, account_details.get("master_type"), account_details.get("master_name"), d.name))
-
- if i%500 == 0:
- frappe.db.commit()
-
-def delete_individual_party_account():
- frappe.db.sql("""delete from `tabAccount`
- where ifnull(master_type, '') in ('Customer', 'Supplier')
- and ifnull(master_name, '') != ''
- and not exists(select gle.name from `tabGL Entry` gle
- where gle.account = tabAccount.name)""")
-
- accounts_not_deleted = frappe.db.sql_list("""select tabAccount.name from `tabAccount`
- where ifnull(master_type, '') in ('Customer', 'Supplier')
- and ifnull(master_name, '') != ''
- and exists(select gle.name from `tabGL Entry` gle where gle.account = tabAccount.name)""")
-
- if accounts_not_deleted:
- print("Accounts not deleted: " + "\n".join(accounts_not_deleted))
-
-
-def remove_customer_supplier_account_report():
- for d in ["Customer Account Head", "Supplier Account Head"]:
- frappe.delete_doc("Report", d)
diff --git a/erpnext/patches/v4_2/recalculate_bom_cost.py b/erpnext/patches/v4_2/recalculate_bom_cost.py
deleted file mode 100644
index eee89fce96..0000000000
--- a/erpnext/patches/v4_2/recalculate_bom_cost.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.db.sql("select name from `tabBOM` where docstatus < 2"):
- try:
- document = frappe.get_doc('BOM', d[0])
- if document.docstatus == 1:
- document.flags.ignore_validate_update_after_submit = True
- document.calculate_cost()
- document.save()
- except:
- pass
diff --git a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py b/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
deleted file mode 100644
index 1356129dc0..0000000000
--- a/erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from erpnext.stock.stock_ledger import NegativeStockError
-
-def execute():
- si_list = frappe.db.sql("""select distinct si.name
- from `tabSales Invoice Item` si_item, `tabSales Invoice` si
- where si.name = si_item.parent and si.modified > '2015-02-16' and si.docstatus=1
- and ifnull(si_item.warehouse, '') = '' and ifnull(si.update_stock, 0) = 1
- order by posting_date, posting_time""", as_dict=1)
-
- failed_list = []
- for si in si_list:
- try:
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- si_doc.docstatus = 2
- si_doc.on_cancel()
-
- si_doc.docstatus = 1
- si_doc.set_missing_item_details()
- si_doc.on_submit()
- frappe.db.commit()
- except:
- failed_list.append(si.name)
- frappe.local.stockledger_exceptions = None
- frappe.db.rollback()
-
- print("Failed to repost: ", failed_list)
-
-
-
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/repost_stock_reconciliation.py b/erpnext/patches/v4_2/repost_stock_reconciliation.py
deleted file mode 100644
index ad20ebbae4..0000000000
--- a/erpnext/patches/v4_2/repost_stock_reconciliation.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import json
-
-def execute():
- existing_allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
- frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
-
- head_row = ["Item Code", "Warehouse", "Quantity", "Valuation Rate"]
- stock_reco_to_be_reposted = []
- for d in frappe.db.sql("""select name, reconciliation_json from `tabStock Reconciliation`
- where docstatus=1 and creation > '2014-03-01'""", as_dict=1):
- data = json.loads(d.reconciliation_json)
- for row in data[data.index(head_row)+1:]:
- if row[3] in ["", None]:
- stock_reco_to_be_reposted.append(d.name)
- break
-
- for dn in stock_reco_to_be_reposted:
- reco = frappe.get_doc("Stock Reconciliation", dn)
- reco.docstatus = 2
- reco.on_cancel()
-
- reco.docstatus = 1
- reco.validate()
- reco.on_submit()
-
- frappe.db.set_value("Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock)
diff --git a/erpnext/patches/v4_2/reset_bom_costs.py b/erpnext/patches/v4_2/reset_bom_costs.py
deleted file mode 100644
index 42ca759467..0000000000
--- a/erpnext/patches/v4_2/reset_bom_costs.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('manufacturing', 'doctype', 'bom_operation')
- for d in frappe.db.sql("""select name from `tabBOM` where docstatus < 2""", as_dict=1):
- try:
- bom = frappe.get_doc('BOM', d.name)
- bom.flags.ignore_validate_update_after_submit = True
- bom.calculate_cost()
- bom.save()
- frappe.db.commit()
- except:
- frappe.db.rollback()
diff --git a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py b/erpnext/patches/v4_2/seprate_manufacture_and_repack.py
deleted file mode 100644
index 2c935436a2..0000000000
--- a/erpnext/patches/v4_2/seprate_manufacture_and_repack.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabStock Entry` set purpose='Manufacture' where purpose='Manufacture/Repack' and ifnull(work_order,"")!="" """)
- frappe.db.sql("""update `tabStock Entry` set purpose='Repack' where purpose='Manufacture/Repack' and ifnull(work_order,"")="" """)
\ No newline at end of file
diff --git a/erpnext/patches/v4_2/set_company_country.py b/erpnext/patches/v4_2/set_company_country.py
deleted file mode 100644
index 89f07f2873..0000000000
--- a/erpnext/patches/v4_2/set_company_country.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- country = frappe.db.get_single_value("Global Defaults", "country")
- if not country:
- print("Country not specified in Global Defaults")
- return
-
- for company in frappe.db.sql_list("""select name from `tabCompany`
- where ifnull(country, '')=''"""):
- frappe.db.set_value("Company", company, "country", country)
diff --git a/erpnext/patches/v4_2/set_item_has_batch.py b/erpnext/patches/v4_2/set_item_has_batch.py
deleted file mode 100644
index 7e52d2def0..0000000000
--- a/erpnext/patches/v4_2/set_item_has_batch.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("update tabItem set has_batch_no = 0 where ifnull(has_batch_no, '') = ''")
- frappe.db.sql("update tabItem set has_serial_no = 0 where ifnull(has_serial_no, '') = ''")
-
- item_list = frappe.db.sql("""select name, has_batch_no, has_serial_no from tabItem
- where is_stock_item = 1""", as_dict=1)
-
- sle_count = get_sle_count()
- sle_with_batch = get_sle_with_batch()
- sle_with_serial = get_sle_with_serial()
-
- batch_items = get_items_with_batch()
- serialized_items = get_items_with_serial()
-
- for d in item_list:
- if d.has_batch_no == 1:
- if d.name not in batch_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_batch.get(d.name):
- frappe.db.set_value("Item", d.name, "has_batch_no", 0)
- else:
- if d.name in batch_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_batch.get(d.name)):
- frappe.db.set_value("Item", d.name, "has_batch_no", 1)
-
- if d.has_serial_no == 1:
- if d.name not in serialized_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_serial.get(d.name):
- frappe.db.set_value("Item", d.name, "has_serial_no", 0)
- else:
- if d.name in serialized_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_serial.get(d.name)):
- frappe.db.set_value("Item", d.name, "has_serial_no", 1)
-
-
-def get_sle_count():
- sle_count = {}
- for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` group by item_code""", as_dict=1):
- sle_count.setdefault(d.item_code, d.cnt)
-
- return sle_count
-
-def get_sle_with_batch():
- sle_with_batch = {}
- for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
- where ifnull(batch_no, '') != '' group by item_code""", as_dict=1):
- sle_with_batch.setdefault(d.item_code, d.cnt)
-
- return sle_with_batch
-
-
-def get_sle_with_serial():
- sle_with_serial = {}
- for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
- where ifnull(serial_no, '') != '' group by item_code""", as_dict=1):
- sle_with_serial.setdefault(d.item_code, d.cnt)
-
- return sle_with_serial
-
-def get_items_with_batch():
- return frappe.db.sql_list("select item from tabBatch")
-
-def get_items_with_serial():
- return frappe.db.sql_list("select item_code from `tabSerial No`")
diff --git a/erpnext/patches/v4_2/toggle_rounded_total.py b/erpnext/patches/v4_2/toggle_rounded_total.py
deleted file mode 100644
index e571208eb6..0000000000
--- a/erpnext/patches/v4_2/toggle_rounded_total.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
- global_defaults.toggle_rounded_total()
diff --git a/erpnext/patches/v4_2/update_landed_cost_voucher.py b/erpnext/patches/v4_2/update_landed_cost_voucher.py
deleted file mode 100644
index ec0029671e..0000000000
--- a/erpnext/patches/v4_2/update_landed_cost_voucher.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "landed_cost_voucher")
- frappe.db.sql("""update `tabLanded Cost Voucher` set distribute_charges_based_on = 'Amount'
- where docstatus=1""")
diff --git a/erpnext/patches/v4_2/update_project_milestones.py b/erpnext/patches/v4_2/update_project_milestones.py
deleted file mode 100644
index e704116d05..0000000000
--- a/erpnext/patches/v4_2/update_project_milestones.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for project in frappe.db.sql_list("select name from tabProject"):
- frappe.reload_doc("projects", "doctype", "project")
- p = frappe.get_doc("Project", project)
- p.update_milestones_completed()
- p.db_set("percent_milestones_completed", p.percent_milestones_completed)
diff --git a/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py b/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py
deleted file mode 100644
index 28dd5c0d4e..0000000000
--- a/erpnext/patches/v4_2/update_sales_order_invoice_field_name.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.db.sql("""update `tabSales Invoice` set from_date = invoice_period_from_date,
- to_date = invoice_period_to_date, is_recurring = convert_into_recurring_invoice""")
diff --git a/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py b/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py
deleted file mode 100644
index 89bf795534..0000000000
--- a/erpnext/patches/v4_2/update_stock_uom_for_dn_in_sle.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabStock Ledger Entry` sle, tabItem item
- set sle.stock_uom = item.stock_uom
- where sle.voucher_type="Delivery Note" and item.name = sle.item_code
- and sle.stock_uom != item.stock_uom""")
diff --git a/erpnext/patches/v4_4/__init__.py b/erpnext/patches/v4_4/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v4_4/make_email_accounts.py b/erpnext/patches/v4_4/make_email_accounts.py
deleted file mode 100644
index 57df1ae491..0000000000
--- a/erpnext/patches/v4_4/make_email_accounts.py
+++ /dev/null
@@ -1,96 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model import default_fields
-
-from six import iteritems
-
-def execute():
- frappe.reload_doc("email", "doctype", "email_account")
-
- # outgoing
- outgoing = dict(frappe.db.sql("select field, value from tabSingles where doctype='Outgoing Email Settings'"))
- if outgoing and outgoing['mail_server'] and outgoing['mail_login']:
- account = frappe.new_doc("Email Account")
- mapping = {
- "login_id_is_different": 1,
- "email_id": "auto_email_id",
- "login_id": "mail_login",
- "password": "mail_password",
- "footer": "footer",
- "smtp_server": "mail_server",
- "smtp_port": "mail_port",
- "use_tls": "use_ssl"
- }
-
- for target_fieldname, source_fieldname in iteritems(mapping):
- account.set(target_fieldname, outgoing.get(source_fieldname))
-
- account.enable_outgoing = 1
- account.enable_incoming = 0
-
- account.insert()
-
- # support
- support = dict(frappe.db.sql("select field, value from tabSingles where doctype='Support Email Settings'"))
- if support and support['mail_server'] and support['mail_login']:
- account = frappe.new_doc("Email Account")
- mapping = {
- "enable_incoming": "sync_support_mails",
- "email_id": "mail_login",
- "password": "mail_password",
- "email_server": "mail_server",
- "use_ssl": "use_ssl",
- "signature": "support_signature",
- "enable_auto_reply": "send_autoreply",
- "auto_reply_message": "support_autoreply"
- }
-
- for target_fieldname, source_fieldname in iteritems(mapping):
- account.set(target_fieldname, support.get(source_fieldname))
-
- account.enable_outgoing = 0
- account.append_to = "Issue"
-
- insert_or_update(account)
-
- # sales, jobs
- for doctype in ("Sales Email Settings", "Jobs Email Settings"):
- source = dict(frappe.db.sql("select field, value from tabSingles where doctype=%s", doctype))
- if source and source.get('host') and source.get('username'):
- account = frappe.new_doc("Email Account")
- mapping = {
- "enable_incoming": "extract_emails",
- "email_id": "username",
- "password": "password",
- "email_server": "host",
- "use_ssl": "use_ssl",
- }
-
- for target_fieldname, source_fieldname in iteritems(mapping):
- account.set(target_fieldname, source.get(source_fieldname))
-
- account.enable_outgoing = 0
- account.append_to = "Lead" if doctype=="Sales Email Settings" else "Job Applicant"
-
- insert_or_update(account)
-
- for doctype in ("Outgoing Email Settings", "Support Email Settings",
- "Sales Email Settings", "Jobs Email Settings"):
- frappe.delete_doc("DocType", doctype)
-
-def insert_or_update(account):
- try:
- account.insert()
- except frappe.NameError as e:
- if e.args[0]=="Email Account":
- existing_account = frappe.get_doc("Email Account", e.args[1])
- for key, value in account.as_dict().items():
- if not existing_account.get(key) and value \
- and key not in default_fields \
- and key != "__islocal":
- existing_account.set(key, value)
-
- existing_account.save()
- else:
- raise
-
diff --git a/erpnext/patches/v5_0/__init__.py b/erpnext/patches/v5_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v5_0/convert_stock_reconciliation.py b/erpnext/patches/v5_0/convert_stock_reconciliation.py
deleted file mode 100644
index 75d1da752f..0000000000
--- a/erpnext/patches/v5_0/convert_stock_reconciliation.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from __future__ import unicode_literals
-import frappe, json
-
-def execute():
- # stock reco now amendable
- frappe.db.sql("""update tabDocPerm set `amend` = 1 where parent='Stock Reconciliation' and submit = 1""")
-
- frappe.reload_doc("stock", "doctype", "stock_reconciliation_item")
- frappe.reload_doctype("Stock Reconciliation")
-
- if frappe.db.has_column("Stock Reconciliation", "reconciliation_json"):
- for sr in frappe.db.get_all("Stock Reconciliation", ["name"],
- {"reconciliation_json": ["!=", ""]}):
- start = False
- sr = frappe.get_doc("Stock Reconciliation", sr.name)
- for row in json.loads(sr.reconciliation_json):
- if start:
- sr.append("items", {
- "item_code": row[0],
- "warehouse": row[1],
- "qty": row[2] if len(row) > 2 else None,
- "valuation_rate": row[3] if len(row) > 3 else None
- })
-
- elif row[0]=="Item Code":
- start = True
-
-
- for item in sr.items:
- item.db_update()
-
diff --git a/erpnext/patches/v5_0/execute_on_doctype_update.py b/erpnext/patches/v5_0/execute_on_doctype_update.py
deleted file mode 100644
index 70b1d8ded6..0000000000
--- a/erpnext/patches/v5_0/execute_on_doctype_update.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Stock Ledger Entry", "Communication", "DefaultValue", "DocShare", "File", "ToDo"):
- frappe.get_doc("DocType", dt).run_module_method("on_doctype_update")
diff --git a/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py b/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py
deleted file mode 100644
index 30dc0f8db4..0000000000
--- a/erpnext/patches/v5_0/fix_taxes_and_totals_in_party_currency.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.meta import get_field_precision
-
-def execute():
- if not frappe.db.sql("""select name from `tabPatch Log`
- where patch = 'erpnext.patches.v5_0.taxes_and_totals_in_party_currency'"""):
- return
- selling_doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]
- buying_doctypes = ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
-
- for dt in selling_doctypes:
- update_values(dt, "Sales Taxes and Charges")
-
- for dt in buying_doctypes:
- update_values(dt, "Purchase Taxes and Charges")
-
-def update_values(dt, tax_table):
- rate_field_precision = get_field_precision(frappe.get_meta(dt + " Item").get_field("rate"))
- tax_amount_precision = get_field_precision(frappe.get_meta(tax_table).get_field("tax_amount"))
-
- # update net_total, discount_on
- frappe.db.sql("""
- UPDATE
- `tab{0}`
- SET
- total_taxes_and_charges = round(base_total_taxes_and_charges / conversion_rate, {1})
- WHERE
- docstatus < 2
- and ifnull(base_total_taxes_and_charges, 0) != 0
- and ifnull(total_taxes_and_charges, 0) = 0
- """.format(dt, tax_amount_precision))
-
- # update net_amount
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` item
- SET
- item.net_amount = round(item.base_net_amount / par.conversion_rate, {2}),
- item.net_rate = round(item.base_net_rate / par.conversion_rate, {2})
- WHERE
- par.name = item.parent
- and par.docstatus < 2
- and ((ifnull(item.base_net_amount, 0) != 0 and ifnull(item.net_amount, 0) = 0)
- or (ifnull(item.base_net_rate, 0) != 0 and ifnull(item.net_rate, 0) = 0))
- """.format(dt, dt + " Item", rate_field_precision))
-
- # update tax in party currency
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` tax
- SET
- tax.tax_amount = round(tax.base_tax_amount / par.conversion_rate, {2}),
- tax.total = round(tax.base_total / conversion_rate, {2}),
- tax.tax_amount_after_discount_amount = round(tax.base_tax_amount_after_discount_amount / conversion_rate, {2})
- WHERE
- par.name = tax.parent
- and par.docstatus < 2
- and ((ifnull(tax.base_tax_amount, 0) != 0 and ifnull(tax.tax_amount, 0) = 0)
- or (ifnull(tax.base_total, 0) != 0 and ifnull(tax.total, 0) = 0)
- or (ifnull(tax.base_tax_amount_after_discount_amount, 0) != 0 and
- ifnull(tax.tax_amount_after_discount_amount, 0) = 0))
- """.format(dt, tax_table, tax_amount_precision))
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/index_on_account_and_gl_entry.py b/erpnext/patches/v5_0/index_on_account_and_gl_entry.py
deleted file mode 100644
index 2920e9293d..0000000000
--- a/erpnext/patches/v5_0/index_on_account_and_gl_entry.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- index_map = {
- "Account": ["parent_account", "lft", "rgt"],
- "GL Entry": ["posting_date", "account", 'party', "voucher_no"],
- "Sales Invoice": ["posting_date", "debit_to", "customer"],
- "Purchase Invoice": ["posting_date", "credit_to", "supplier"]
- }
-
- for dt, indexes in index_map.items():
- existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
- where Column_name != 'name'""".format(dt), as_dict=1)]
-
- for old, column in existing_indexes:
- if column in ("parent", "group_or_ledger", "is_group", "is_pl_account", "debit_or_credit",
- "account_name", "company", "project", "voucher_date", "due_date", "bill_no",
- "bill_date", "is_opening", "fiscal_year", "outstanding_amount"):
- frappe.db.sql("alter table `tab{0}` drop index {1}".format(dt, old))
-
- existing_indexes = [(d.Key_name, d.Column_name) for d in frappe.db.sql("""show index from `tab{0}`
- where Column_name != 'name'""".format(dt), as_dict=1)]
-
- existing_indexed_columns = list(set([x[1] for x in existing_indexes]))
-
- for new in indexes:
- if new not in existing_indexed_columns:
- frappe.db.sql("alter table `tab{0}` add index ({1})".format(dt, new))
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/is_group.py b/erpnext/patches/v5_0/is_group.py
deleted file mode 100644
index 4e3f760bed..0000000000
--- a/erpnext/patches/v5_0/is_group.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.reload_doctype("Account")
- frappe.reload_doctype("Cost Center")
- frappe.db.sql("update tabAccount set is_group = if(group_or_ledger='Group', 1, 0)")
- frappe.db.sql("update `tabCost Center` set is_group = if(group_or_ledger='Group', 1, 0)")
diff --git a/erpnext/patches/v5_0/item_patches.py b/erpnext/patches/v5_0/item_patches.py
deleted file mode 100644
index e223e09f5b..0000000000
--- a/erpnext/patches/v5_0/item_patches.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("update `tabItem` set end_of_life='2099-12-31' where ifnull(end_of_life, '0000-00-00')='0000-00-00'")
- frappe.db.sql("update `tabItem` set website_image = image where ifnull(website_image, '') = 'attach_files:'")
diff --git a/erpnext/patches/v5_0/link_warehouse_with_account.py b/erpnext/patches/v5_0/link_warehouse_with_account.py
deleted file mode 100644
index 338fd7ad7f..0000000000
--- a/erpnext/patches/v5_0/link_warehouse_with_account.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if "master_name" in frappe.db.get_table_columns("Account"):
- frappe.db.sql("""update tabAccount set warehouse=master_name
- where ifnull(account_type, '') = 'Warehouse' and ifnull(master_name, '') != ''""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/new_crm_module.py b/erpnext/patches/v5_0/new_crm_module.py
deleted file mode 100644
index f5dda1f273..0000000000
--- a/erpnext/patches/v5_0/new_crm_module.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import json
-import frappe
-
-def execute():
- frappe.reload_doc('crm', 'doctype', 'lead')
- frappe.reload_doc('crm', 'doctype', 'opportunity')
-
- add_crm_to_user_desktop_items()
-
-def add_crm_to_user_desktop_items():
- key = "_user_desktop_items"
- for user in frappe.get_all("User", filters={"enabled": 1, "user_type": "System User"}):
- user = user.name
- user_desktop_items = frappe.db.get_defaults(key, parent=user)
- if user_desktop_items:
- user_desktop_items = json.loads(user_desktop_items)
- if "CRM" not in user_desktop_items:
- user_desktop_items.append("CRM")
- frappe.db.set_default(key, json.dumps(user_desktop_items), parent=user)
-
diff --git a/erpnext/patches/v5_0/newsletter.py b/erpnext/patches/v5_0/newsletter.py
deleted file mode 100644
index 63e3312413..0000000000
--- a/erpnext/patches/v5_0/newsletter.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- frappe.reload_doc("core", "doctype", "block_module")
- frappe.reload_doctype("User")
- frappe.reload_doctype("Lead")
- frappe.reload_doctype("Contact")
-
- frappe.reload_doc('email', 'doctype', 'email_group')
- frappe.reload_doc('email', 'doctype', 'email_group_member')
- frappe.reload_doc('email', 'doctype', 'newsletter')
-
- frappe.permissions.reset_perms("Newsletter")
-
- if not frappe.db.exists("Role", "Newsletter Manager"):
- frappe.get_doc({"doctype": "Role", "role": "Newsletter Manager"}).insert()
-
- for userrole in frappe.get_all("Has Role", "parent", {"role": "Sales Manager", "parenttype": "User"}):
- if frappe.db.exists("User", userrole.parent):
- user = frappe.get_doc("User", userrole.parent)
- user.append("roles", {
- "doctype": "Has Role",
- "role": "Newsletter Manager"
- })
- user.flags.ignore_mandatory = True
- user.save()
-
- # create default lists
- general = frappe.new_doc("Email Group")
- general.title = "General"
- general.insert()
- general.import_from("Lead")
- general.import_from("Contact")
diff --git a/erpnext/patches/v5_0/opportunity_not_submittable.py b/erpnext/patches/v5_0/opportunity_not_submittable.py
deleted file mode 100644
index e29d66f284..0000000000
--- a/erpnext/patches/v5_0/opportunity_not_submittable.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Opportunity")
- frappe.db.sql("update tabDocPerm set submit=0, cancel=0, amend=0 where parent='Opportunity'")
- frappe.db.sql("update tabOpportunity set docstatus=0 where docstatus=1")
diff --git a/erpnext/patches/v5_0/party_model_patch_fix.py b/erpnext/patches/v5_0/party_model_patch_fix.py
deleted file mode 100644
index d9b6709792..0000000000
--- a/erpnext/patches/v5_0/party_model_patch_fix.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for company in frappe.get_all("Company",
- ["name", "default_receivable_account", "default_payable_account"]):
-
- if company.default_receivable_account:
- frappe.db.sql("""update `tabSales Invoice` invoice set `debit_to`=%(account)s
- where company=%(company)s
- and not exists (select name from `tabAccount` account where account.name=invoice.debit_to)""",
- {"company": company.name, "account": company.default_receivable_account})
-
- if company.default_payable_account:
- frappe.db.sql("""update `tabPurchase Invoice` invoice set `credit_to`=%(account)s
- where company=%(company)s
- and not exists (select name from `tabAccount` account where account.name=invoice.credit_to)""",
- {"company": company.name, "account": company.default_payable_account})
diff --git a/erpnext/patches/v5_0/portal_fixes.py b/erpnext/patches/v5_0/portal_fixes.py
deleted file mode 100644
index 1fefd99167..0000000000
--- a/erpnext/patches/v5_0/portal_fixes.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import erpnext.setup.install
-
-def execute():
- frappe.reload_doc("website", "doctype", "web_form_field", force=True, reset_permissions=True)
- #erpnext.setup.install.add_web_forms()
diff --git a/erpnext/patches/v5_0/project_costing.py b/erpnext/patches/v5_0/project_costing.py
deleted file mode 100644
index e2d65d0594..0000000000
--- a/erpnext/patches/v5_0/project_costing.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Project")
- frappe.db.sql("update `tabProject` set expected_start_date = project_start_date, \
- expected_end_date = completion_date, actual_end_date = act_completion_date, \
- estimated_costing = project_value, gross_margin = gross_margin_value")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py b/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py
deleted file mode 100644
index d5af43c541..0000000000
--- a/erpnext/patches/v5_0/recalculate_total_amount_in_jv.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import money_in_words
-
-def execute():
- company_currency = dict(frappe.db.sql("select name, default_currency from `tabCompany`"))
- bank_or_cash_accounts = frappe.db.sql_list("""select name from `tabAccount`
- where account_type in ('Bank', 'Cash') and docstatus < 2""")
-
- for je in frappe.db.sql_list("""select name from `tabJournal Entry` where docstatus < 2"""):
- total_amount = 0
- total_amount_in_words = ""
-
- je_doc = frappe.get_doc('Journal Entry', je)
- for d in je_doc.get("accounts"):
- if (d.party_type and d.party) or d.account in bank_or_cash_accounts:
- total_amount = d.debit or d.credit
- if total_amount:
- total_amount_in_words = money_in_words(total_amount, company_currency.get(je_doc.company))
-
- if total_amount:
- frappe.db.sql("""update `tabJournal Entry` set total_amount=%s, total_amount_in_words=%s
- where name = %s""", (total_amount, total_amount_in_words, je))
diff --git a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py b/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py
deleted file mode 100644
index 6d392831b4..0000000000
--- a/erpnext/patches/v5_0/reclculate_planned_operating_cost_in_production_order.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for wo in frappe.db.sql("""select name from `tabWork Order` where docstatus < 2""", as_dict=1):
- work_order = frappe.get_doc("Work Order", wo.name)
- if work_order.operations:
- work_order.flags.ignore_validate_update_after_submit = True
- work_order.calculate_time()
- work_order.save()
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/remove_birthday_events.py b/erpnext/patches/v5_0/remove_birthday_events.py
deleted file mode 100644
index 3ead8669b8..0000000000
--- a/erpnext/patches/v5_0/remove_birthday_events.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for e in frappe.db.sql_list("""select name from tabEvent where
- repeat_on='Every Year' and ref_type='Employee'"""):
- frappe.delete_doc("Event", e, force=True)
diff --git a/erpnext/patches/v5_0/rename_customer_issue.py b/erpnext/patches/v5_0/rename_customer_issue.py
deleted file mode 100644
index 1bd69ceec1..0000000000
--- a/erpnext/patches/v5_0/rename_customer_issue.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Customer Issue"):
- frappe.rename_doc("DocType", "Customer Issue", "Warranty Claim")
diff --git a/erpnext/patches/v5_0/rename_pos_setting.py b/erpnext/patches/v5_0/rename_pos_setting.py
deleted file mode 100644
index bf10333564..0000000000
--- a/erpnext/patches/v5_0/rename_pos_setting.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("POS Setting"):
- frappe.rename_doc("DocType", "POS Setting", "POS Profile")
diff --git a/erpnext/patches/v5_0/rename_table_fieldnames.py b/erpnext/patches/v5_0/rename_table_fieldnames.py
deleted file mode 100644
index aefb0a2037..0000000000
--- a/erpnext/patches/v5_0/rename_table_fieldnames.py
+++ /dev/null
@@ -1,243 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-from frappe.modules import scrub, get_doctype_module
-
-rename_map = {
- "Opportunity": [
- ["enquiry_details", "items"]
- ],
- "Quotation": [
- ["quotation_details", "items"],
- ["other_charges", "taxes"]
- ],
- "Sales Order": [
- ["sales_order_details", "items"],
- ["other_charges", "taxes"],
- ["packing_details", "packed_items"]
- ],
- "Delivery Note": [
- ["delivery_note_details", "items"],
- ["other_charges", "taxes"],
- ["packing_details", "packed_items"]
- ],
- "Sales Invoice": [
- ["entries", "items"],
- ["other_charges", "taxes"],
- ["packing_details", "packed_items"],
- ["advance_adjustment_details", "advances"]
- ],
- "Material Request": [
- ["indent_details", "items"]
- ],
- "Supplier Quotation": [
- ["quotation_items", "items"],
- ["other_charges", "taxes"]
- ],
- "Purchase Order": [
- ["po_details", "items"],
- ["other_charges", "taxes"],
- ["po_raw_material_details", "supplied_items"]
- ],
- "Purchase Receipt": [
- ["purchase_receipt_details", "items"],
- ["other_charges", "taxes"],
- ["pr_raw_material_details", "supplied_items"]
- ],
- "Purchase Invoice": [
- ["entries", "items"],
- ["other_charges", "taxes"],
- ["advance_allocation_details", "advances"]
- ],
- "Work Order": [
- ["production_order_operations", "operations"]
- ],
- "BOM": [
- ["bom_operations", "operations"],
- ["bom_materials", "items"],
- ["flat_bom_details", "exploded_items"]
- ],
- "Payment Reconciliation": [
- ["payment_reconciliation_payments", "payments"],
- ["payment_reconciliation_invoices", "invoices"]
- ],
- "Sales Taxes and Charges Template": [
- ["other_charges", "taxes"],
- ["valid_for_territories", "territories"]
- ],
- "Purchase Taxes and Charges Template": [
- ["other_charges", "taxes"]
- ],
- "Shipping Rule": [
- ["shipping_rule_conditions", "conditions"],
- ["valid_for_territories", "territories"]
- ],
- "Price List": [
- ["valid_for_territories", "territories"]
- ],
- "Appraisal": [
- ["appraisal_details", "goals"]
- ],
- "Appraisal Template": [
- ["kra_sheet", "goals"]
- ],
- "Bank Reconciliation": [
- ["entries", "journal_entries"]
- ],
- "C-Form": [
- ["invoice_details", "invoices"]
- ],
- "Employee": [
- ["employee_leave_approvers", "leave_approvers"],
- ["educational_qualification_details", "education"],
- ["previous_experience_details", "external_work_history"],
- ["experience_in_company_details", "internal_work_history"]
- ],
- "Expense Claim": [
- ["expense_voucher_details", "expenses"]
- ],
- "Fiscal Year": [
- ["fiscal_year_companies", "companies"]
- ],
- "Holiday List": [
- ["holiday_list_details", "holidays"]
- ],
- "Installation Note": [
- ["installed_item_details", "items"]
- ],
- "Item": [
- ["item_reorder", "reorder_levels"],
- ["uom_conversion_details", "uoms"],
- ["item_supplier_details", "supplier_items"],
- ["item_customer_details", "customer_items"],
- ["item_tax", "taxes"],
- ["item_specification_details", "quality_parameters"],
- ["item_website_specifications", "website_specifications"]
- ],
- "Item Group": [
- ["item_website_specifications", "website_specifications"]
- ],
- "Landed Cost Voucher": [
- ["landed_cost_purchase_receipts", "purchase_receipts"],
- ["landed_cost_items", "items"],
- ["landed_cost_taxes_and_charges", "taxes"]
- ],
- "Maintenance Schedule": [
- ["item_maintenance_detail", "items"],
- ["maintenance_schedule_detail", "schedules"]
- ],
- "Maintenance Visit": [
- ["maintenance_visit_details", "purposes"]
- ],
- "Packing Slip": [
- ["item_details", "items"]
- ],
- "Customer": [
- ["party_accounts", "accounts"]
- ],
- "Customer Group": [
- ["party_accounts", "accounts"]
- ],
- "Supplier": [
- ["party_accounts", "accounts"]
- ],
- "Supplier Type": [
- ["party_accounts", "accounts"]
- ],
- "Payment Tool": [
- ["payment_tool_details", "vouchers"]
- ],
- "Production Planning Tool": [
- ["pp_so_details", "sales_orders"],
- ["pp_details", "items"]
- ],
- "Quality Inspection": [
- ["qa_specification_details", "readings"]
- ],
- "Salary Slip": [
- ["earning_details", "earnings"],
- ["deduction_details", "deductions"]
- ],
- "Salary Structure": [
- ["earning_details", "earnings"],
- ["deduction_details", "deductions"]
- ],
- "Product Bundle": [
- ["sales_bom_items", "items"]
- ],
- "SMS Settings": [
- ["static_parameter_details", "parameters"]
- ],
- "Stock Entry": [
- ["mtn_details", "items"]
- ],
- "Sales Partner": [
- ["partner_target_details", "targets"]
- ],
- "Sales Person": [
- ["target_details", "targets"]
- ],
- "Territory": [
- ["target_details", "targets"]
- ],
- "Time Sheet": [
- ["time_sheet_details", "time_logs"]
- ],
- "Workstation": [
- ["workstation_operation_hours", "working_hours"]
- ],
- "Payment Reconciliation Payment": [
- ["journal_voucher", "journal_entry"],
- ],
- "Purchase Invoice Advance": [
- ["journal_voucher", "journal_entry"],
- ],
- "Sales Invoice Advance": [
- ["journal_voucher", "journal_entry"],
- ],
- "Journal Entry": [
- ["entries", "accounts"]
- ],
- "Monthly Distribution": [
- ["budget_distribution_details", "percentages"]
- ]
-}
-
-def execute():
- # rename doctypes
- tables = frappe.db.sql_list("show tables")
- for old_dt, new_dt in [["Journal Voucher Detail", "Journal Entry Account"],
- ["Journal Voucher", "Journal Entry"],
- ["Budget Distribution Detail", "Monthly Distribution Percentage"],
- ["Budget Distribution", "Monthly Distribution"]]:
- if "tab"+new_dt not in tables:
- frappe.rename_doc("DocType", old_dt, new_dt, force=True)
-
- # reload new child doctypes
- frappe.reload_doc("manufacturing", "doctype", "work_order_operation")
- frappe.reload_doc("manufacturing", "doctype", "workstation_working_hour")
- frappe.reload_doc("stock", "doctype", "item_variant")
- frappe.reload_doc("Payroll", "doctype", "salary_detail")
- frappe.reload_doc("accounts", "doctype", "party_account")
- frappe.reload_doc("accounts", "doctype", "fiscal_year_company")
-
- #rename table fieldnames
- for dn in rename_map:
- if not frappe.db.exists("DocType", dn):
- continue
- frappe.reload_doc(get_doctype_module(dn), "doctype", scrub(dn))
-
- for dt, field_list in rename_map.items():
- if not frappe.db.exists("DocType", dt):
- continue
- for field in field_list:
- rename_field(dt, field[0], field[1])
-
- # update voucher type
- for old, new in [["Bank Voucher", "Bank Entry"], ["Cash Voucher", "Cash Entry"],
- ["Credit Card Voucher", "Credit Card Entry"], ["Contra Voucher", "Contra Entry"],
- ["Write Off Voucher", "Write Off Entry"], ["Excise Voucher", "Excise Entry"]]:
- frappe.db.sql("update `tabJournal Entry` set voucher_type=%s where voucher_type=%s", (new, old))
diff --git a/erpnext/patches/v5_0/rename_taxes_and_charges_master.py b/erpnext/patches/v5_0/rename_taxes_and_charges_master.py
deleted file mode 100644
index e26f48cda1..0000000000
--- a/erpnext/patches/v5_0/rename_taxes_and_charges_master.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- if frappe.db.table_exists("Sales Taxes and Charges Master"):
- frappe.rename_doc("DocType", "Sales Taxes and Charges Master",
- "Sales Taxes and Charges Template")
- frappe.delete_doc("DocType", "Sales Taxes and Charges Master")
-
- if frappe.db.table_exists("Purchase Taxes and Charges Master"):
- frappe.rename_doc("DocType", "Purchase Taxes and Charges Master",
- "Purchase Taxes and Charges Template")
- frappe.delete_doc("DocType", "Purchase Taxes and Charges Master")
diff --git a/erpnext/patches/v5_0/rename_total_fields.py b/erpnext/patches/v5_0/rename_total_fields.py
deleted file mode 100644
index 6657dd843e..0000000000
--- a/erpnext/patches/v5_0/rename_total_fields.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-from frappe.modules import scrub, get_doctype_module
-
-selling_doctypes = ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice")
-
-buying_doctypes = ("Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice")
-
-selling_renamed_fields = (
- ("net_total", "base_net_total"),
- ("net_total_export", "net_total"),
- ("other_charges_total", "base_total_taxes_and_charges"),
- ("other_charges_total_export", "total_taxes_and_charges"),
- ("grand_total", "base_grand_total"),
- ("grand_total_export", "grand_total"),
- ("rounded_total", "base_rounded_total"),
- ("rounded_total_export", "rounded_total"),
- ("in_words", "base_in_words"),
- ("in_words_export", "in_words")
-)
-
-buying_renamed_fields = (
- ("net_total", "base_net_total"),
- ("net_total_import", "net_total"),
- ("grand_total", "base_grand_total"),
- ("grand_total_import", "grand_total"),
- ("rounded_total", "base_rounded_total"),
- ("in_words", "base_in_words"),
- ("in_words_import", "in_words"),
- ("other_charges_added", "base_taxes_and_charges_added"),
- ("other_charges_added_import", "taxes_and_charges_added"),
- ("other_charges_deducted", "base_taxes_and_charges_deducted"),
- ("other_charges_deducted_import", "taxes_and_charges_deducted"),
- ("total_tax", "base_total_taxes_and_charges")
-)
-
-def execute():
- for doctypes, fields in [[selling_doctypes, selling_renamed_fields], [buying_doctypes, buying_renamed_fields]]:
- for dt in doctypes:
- frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt))
- table_columns = frappe.db.get_table_columns(dt)
- base_net_total = frappe.db.sql("select sum(ifnull({0}, 0)) from `tab{1}`".format(fields[0][1], dt))[0][0]
- if not base_net_total:
- for f in fields:
- if f[0] in table_columns:
- rename_field(dt, f[0], f[1])
-
- # Added new field "total_taxes_and_charges" in buying cycle, updating value
- if dt in ("Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"):
- frappe.db.sql("""update `tab{0}` set total_taxes_and_charges =
- round(base_total_taxes_and_charges/conversion_rate, 2)""".format(dt))
diff --git a/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py b/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py
deleted file mode 100644
index c564f8b02a..0000000000
--- a/erpnext/patches/v5_0/replace_renamed_fields_in_custom_scripts_and_print_formats.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import re
-
-def execute():
- # NOTE: sequence is important
- renamed_fields = get_all_renamed_fields()
-
- for dt, script_field, ref_dt_field in (("Client Script", "script", "dt"), ("Print Format", "html", "doc_type")):
-
- cond1 = " or ".join("""{0} like "%%{1}%%" """.format(script_field, d[0].replace("_", "\\_")) for d in renamed_fields)
- cond2 = " and standard = 'No'" if dt == "Print Format" else ""
-
- for name, script, ref_dt in frappe.db.sql("select name, {0} as script, {1} as ref_dt from `tab{2}` where ({3}) {4}".format(script_field, ref_dt_field, dt, cond1, cond2)):
- update_script(dt, name, ref_dt, script_field, script, renamed_fields)
-
-def get_all_renamed_fields():
- from erpnext.patches.v5_0.rename_table_fieldnames import rename_map
-
- renamed_fields = (
- ("base_amount", "base_net_amount"),
- ("net_total", "base_net_total"),
- ("net_total_export", "total"),
- ("net_total_import", "total"),
- ("other_charges_total", "base_total_taxes_and_charges"),
- ("other_charges_total_export", "total_taxes_and_charges"),
- ("other_charges_added", "base_taxes_and_charges_added"),
- ("other_charges_added_import", "taxes_and_charges_added"),
- ("other_charges_deducted", "base_taxes_and_charges_deducted"),
- ("other_charges_deducted_import", "taxes_and_charges_deducted"),
- ("total_tax", "base_total_taxes_and_charges"),
- ("grand_total", "base_grand_total"),
- ("grand_total_export", "grand_total"),
- ("grand_total_import", "grand_total"),
- ("rounded_total", "base_rounded_total"),
- ("rounded_total_export", "rounded_total"),
- ("rounded_total_import", "rounded_total"),
- ("in_words", "base_in_words"),
- ("in_words_export", "in_words"),
- ("in_words_import", "in_words"),
- ("tax_amount", "base_tax_amount"),
- ("tax_amount_after_discount_amount", "base_tax_amount_after_discount_amount"),
- )
-
- for fields in rename_map.values():
- renamed_fields += tuple(fields)
-
- return renamed_fields
-
-def update_script(dt, name, ref_dt, script_field, script, renamed_fields):
- for from_field, to_field in renamed_fields:
- if from_field != "entries":
- script = re.sub(r"\b{}\b".format(from_field), to_field, script)
-
- if ref_dt == "Journal Entry":
- script = re.sub(r"\bentries\b", "accounts", script)
- elif ref_dt == "Bank Reconciliation":
- script = re.sub(r"\bentries\b", "journal_entries", script)
- elif ref_dt in ("Sales Invoice", "Purchase Invoice"):
- script = re.sub(r"\bentries\b", "items", script)
-
- frappe.db.set_value(dt, name, script_field, script)
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py b/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
deleted file mode 100644
index 76efdcc7c6..0000000000
--- a/erpnext/patches/v5_0/repost_gle_for_jv_with_multiple_party.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- je_list = frappe.db.sql_list("""
- select par.name from `tabJournal Entry` par
- where par.docstatus=1 and par.creation > '2015-03-01'
- and (select count(distinct child.party) from `tabJournal Entry Account` child
- where par.name=child.parent and ifnull(child.party, '') != '') > 1
- """)
-
- for d in je_list:
- # delete existing gle
- frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
-
- # repost gl entries
- je = frappe.get_doc("Journal Entry", d)
- je.make_gl_entries()
-
- if je_list:
- print(je_list)
-
-
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/repost_requested_qty.py b/erpnext/patches/v5_0/repost_requested_qty.py
deleted file mode 100644
index 6af71f3fc4..0000000000
--- a/erpnext/patches/v5_0/repost_requested_qty.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- from erpnext.stock.stock_balance import update_bin_qty, get_indented_qty
-
- count=0
- for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse
- from `tabMaterial Request Item` where docstatus = 1"""):
- try:
- count += 1
- update_bin_qty(item_code, warehouse, {
- "indented_qty": get_indented_qty(item_code, warehouse),
- })
- if count % 200 == 0:
- frappe.db.commit()
- except:
- frappe.db.rollback()
diff --git a/erpnext/patches/v5_0/reset_values_in_tools.py b/erpnext/patches/v5_0/reset_values_in_tools.py
deleted file mode 100644
index fd970ba1b0..0000000000
--- a/erpnext/patches/v5_0/reset_values_in_tools.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ["Payment Tool", "Bank Reconciliation", "Payment Reconciliation", "Leave Control Panel",
- "Salary Manager", "Upload Attenadance", "Production Planning Tool", "BOM Update Tool", "Customize Form",
- "Employee Attendance Tool", "Rename Tool", "BOM Update Tool", "Process Payroll", "Naming Series"]:
- frappe.db.sql("delete from `tabSingles` where doctype=%s", dt)
-
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/set_appraisal_remarks.py b/erpnext/patches/v5_0/set_appraisal_remarks.py
deleted file mode 100644
index 8652c32cf0..0000000000
--- a/erpnext/patches/v5_0/set_appraisal_remarks.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Appraisal")
- frappe.db.sql("update `tabAppraisal` set remarks = comments")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/set_default_company_in_bom.py b/erpnext/patches/v5_0/set_default_company_in_bom.py
deleted file mode 100644
index a5cd761119..0000000000
--- a/erpnext/patches/v5_0/set_default_company_in_bom.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("manufacturing", "doctype", "bom")
- company = frappe.db.get_value("Global Defaults", None, "default_company")
- frappe.db.sql("""update `tabBOM` set company = %s""",company)
diff --git a/erpnext/patches/v5_0/set_footer_address.py b/erpnext/patches/v5_0/set_footer_address.py
deleted file mode 100644
index 8120d834e1..0000000000
--- a/erpnext/patches/v5_0/set_footer_address.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("System Settings")
- ss = frappe.get_doc("System Settings", "System Settings")
- ss.email_footer_address = frappe.db.get_default("company")
- ss.flags.ignore_mandatory = True
- ss.save()
diff --git a/erpnext/patches/v5_0/stock_entry_update_value.py b/erpnext/patches/v5_0/stock_entry_update_value.py
deleted file mode 100644
index ba1af310f5..0000000000
--- a/erpnext/patches/v5_0/stock_entry_update_value.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for d in frappe.db.get_all("Stock Entry"):
- se = frappe.get_doc("Stock Entry", d.name)
- se.set_total_incoming_outgoing_value()
- se.db_update()
diff --git a/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py b/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py
deleted file mode 100644
index 76d10820b5..0000000000
--- a/erpnext/patches/v5_0/taxes_and_totals_in_party_currency.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.meta import get_field_precision
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
-
-def execute():
- selling_doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]
- buying_doctypes = ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
-
- for dt in selling_doctypes:
- update_values(dt, "Sales Taxes and Charges")
-
- for dt in buying_doctypes:
- update_values(dt, "Purchase Taxes and Charges")
-
-def update_values(dt, tax_table):
- frappe.reload_doctype(dt)
- frappe.reload_doctype(dt + " Item")
- frappe.reload_doctype(tax_table)
-
- net_total_precision = get_field_precision(frappe.get_meta(dt).get_field("net_total"))
- for field in ("total", "base_total", "base_net_total"):
- make_property_setter(dt, field, "precision", net_total_precision, "Select")
-
- rate_field_precision = get_field_precision(frappe.get_meta(dt + " Item").get_field("rate"))
- for field in ("net_rate", "base_net_rate", "net_amount", "base_net_amount", "base_rate", "base_amount"):
- make_property_setter(dt + " Item", field, "precision", rate_field_precision, "Select")
-
- tax_amount_precision = get_field_precision(frappe.get_meta(tax_table).get_field("tax_amount"))
- for field in ("base_tax_amount", "total", "base_total", "tax_amount_after_discount_amount",
- "base_tax_amount_after_discount_amount"):
- make_property_setter(tax_table, field, "precision", tax_amount_precision, "Select")
-
- # update net_total, discount_on
- frappe.db.sql("""
- UPDATE
- `tab{0}`
- SET
- total = round(net_total, {1}),
- base_total = round(net_total*conversion_rate, {1}),
- net_total = round(base_net_total / conversion_rate, {1}),
- apply_discount_on = "Grand Total"
- WHERE
- docstatus < 2
- """.format(dt, net_total_precision))
-
- # update net_amount
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` item
- SET
- item.base_net_amount = round(item.base_amount, {2}),
- item.base_net_rate = round(item.base_rate, {2}),
- item.net_amount = round(item.base_amount / par.conversion_rate, {2}),
- item.net_rate = round(item.base_rate / par.conversion_rate, {2}),
- item.base_amount = round(item.amount * par.conversion_rate, {2}),
- item.base_rate = round(item.rate * par.conversion_rate, {2})
- WHERE
- par.name = item.parent
- and par.docstatus < 2
- """.format(dt, dt + " Item", rate_field_precision))
-
- # update tax in party currency
- frappe.db.sql("""
- UPDATE
- `tab{0}` par, `tab{1}` tax
- SET
- tax.base_tax_amount = round(tax.tax_amount, {2}),
- tax.tax_amount = round(tax.tax_amount / par.conversion_rate, {2}),
- tax.base_total = round(tax.total, {2}),
- tax.total = round(tax.total / conversion_rate, {2}),
- tax.base_tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount, {2}),
- tax.tax_amount_after_discount_amount = round(tax.tax_amount_after_discount_amount / conversion_rate, {2})
- WHERE
- par.name = tax.parent
- and par.docstatus < 2
- """.format(dt, tax_table, tax_amount_precision))
diff --git a/erpnext/patches/v5_0/update_account_types.py b/erpnext/patches/v5_0/update_account_types.py
deleted file mode 100644
index 424743efaa..0000000000
--- a/erpnext/patches/v5_0/update_account_types.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for company in frappe.db.get_all("Company"):
- company = frappe.get_doc("Company", company.name)
-
- match_types = ("Stock Received But Not Billed", "Stock Adjustment", "Expenses Included In Valuation",
- "Cost of Goods Sold")
-
- for account_type in match_types:
- account_name = "{0} - {1}".format(account_type, company.abbr)
- current_account_type = frappe.db.get_value("Account", account_name, "account_type")
- if current_account_type != account_type:
- frappe.db.set_value("Account", account_name, "account_type", account_type)
-
- company.set_default_accounts()
diff --git a/erpnext/patches/v5_0/update_advance_paid.py b/erpnext/patches/v5_0/update_advance_paid.py
deleted file mode 100644
index 74e71e84c8..0000000000
--- a/erpnext/patches/v5_0/update_advance_paid.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Sales Order", "Purchase Order"):
- orders_with_advance = frappe.db.sql("""select name from `tab{0}`
- where docstatus < 2 and ifnull(advance_paid, 0) != 0""".format(dt), as_dict=1)
-
- for order in orders_with_advance:
- frappe.get_doc(dt, order.name).set_total_advance_paid()
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_companywise_payment_account.py b/erpnext/patches/v5_0/update_companywise_payment_account.py
deleted file mode 100644
index fb4b919c85..0000000000
--- a/erpnext/patches/v5_0/update_companywise_payment_account.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment')
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment_account')
-
- mode_of_payment_list = frappe.db.sql("""select name, default_account
- from `tabMode of Payment`""", as_dict=1)
-
- for d in mode_of_payment_list:
- if d.get("default_account"):
- parent_doc = frappe.get_doc("Mode of Payment", d.get("name"))
-
- parent_doc.set("accounts",
- [{"company": frappe.db.get_value("Account", d.get("default_account"), "company"),
- "default_account": d.get("default_account")}])
- parent_doc.save()
diff --git a/erpnext/patches/v5_0/update_dn_against_doc_fields.py b/erpnext/patches/v5_0/update_dn_against_doc_fields.py
deleted file mode 100644
index 56f4f484b1..0000000000
--- a/erpnext/patches/v5_0/update_dn_against_doc_fields.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'delivery_note_item')
-
- frappe.db.sql("""update `tabDelivery Note Item` set so_detail = prevdoc_detail_docname
- where ifnull(against_sales_order, '') != ''""")
-
- frappe.db.sql("""update `tabDelivery Note Item` set si_detail = prevdoc_detail_docname
- where ifnull(against_sales_invoice, '') != ''""")
diff --git a/erpnext/patches/v5_0/update_from_bom.py b/erpnext/patches/v5_0/update_from_bom.py
deleted file mode 100644
index 4b3e62d7a5..0000000000
--- a/erpnext/patches/v5_0/update_from_bom.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Stock Entry")
- frappe.db.sql("update `tabStock Entry` set from_bom = if(ifnull(bom_no, '')='', 0, 1)")
diff --git a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py b/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
deleted file mode 100644
index b52785ae60..0000000000
--- a/erpnext/patches/v5_0/update_frozen_accounts_permission_role.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- account_settings = frappe.get_doc("Accounts Settings")
-
- if not account_settings.frozen_accounts_modifier and account_settings.bde_auth_role:
- frappe.db.set_value("Accounts Settings", None,
- "frozen_accounts_modifier", account_settings.bde_auth_role)
-
diff --git a/erpnext/patches/v5_0/update_item_and_description_again.py b/erpnext/patches/v5_0/update_item_and_description_again.py
deleted file mode 100644
index 35dedcc072..0000000000
--- a/erpnext/patches/v5_0/update_item_and_description_again.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cstr
-import re
-
-def execute():
- item_details = frappe._dict()
- for d in frappe.db.sql("select name, description from `tabItem`", as_dict=1):
- description = cstr(d.description).strip()
- new_desc = extract_description(description)
-
- item_details.setdefault(d.name, frappe._dict({
- "old_description": description,
- "new_description": new_desc
- }))
-
-
- dt_list= ["Purchase Order Item","Supplier Quotation Item", "BOM", "BOM Explosion Item" , \
- "BOM Item", "Opportunity Item" , "Quotation Item" , "Sales Order Item" , "Delivery Note Item" , \
- "Material Request Item" , "Purchase Receipt Item" , "Stock Entry Detail"]
- for dt in dt_list:
- frappe.reload_doctype(dt)
- records = frappe.db.sql("""select name, `{0}` as item_code, description from `tab{1}`
- where description is not null and description like '%%]*\>".format(tag), "", desc)
-
- return desc
diff --git a/erpnext/patches/v5_0/update_item_desc_in_invoice.py b/erpnext/patches/v5_0/update_item_desc_in_invoice.py
deleted file mode 100644
index dba35d5693..0000000000
--- a/erpnext/patches/v5_0/update_item_desc_in_invoice.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.website.utils import find_first_image
-from frappe.utils import cstr
-import re
-
-def execute():
- item_details = frappe._dict()
- for d in frappe.db.sql("select name, description, image from `tabItem`", as_dict=1):
- description = cstr(d.description).strip()
- item_details.setdefault(d.name, frappe._dict({
- "description": description,
- "image": d.image
- }))
-
-
- dt_list= ["Sales Invoice Item","Purchase Invoice Item"]
- for dt in dt_list:
- frappe.reload_doctype(dt)
- records = frappe.db.sql("""select name, item_code, description from `tab{0}`
- where ifnull(item_code, '') != '' and description is not null """.format(dt), as_dict=1)
-
- count = 1
- for d in records:
- if item_details.get(d.item_code) and cstr(d.description) == item_details.get(d.item_code).description:
- desc = item_details.get(d.item_code).description
- image = item_details.get(d.item_code).image
- else:
- desc, image = extract_image_and_description(cstr(d.description))
-
- if not image:
- item_detail = item_details.get(d.item_code)
- if item_detail:
- image = item_detail.image
-
- frappe.db.sql("""update `tab{0}` set description = %s, image = %s
- where name = %s """.format(dt), (desc, image, d.name))
-
- count += 1
- if count % 500 == 0:
- frappe.db.commit()
-
-
-def extract_image_and_description(data):
- image_url = find_first_image(data)
- desc = data
- for tag in ("img", "table", "tr", "td"):
- desc = re.sub("\*{0}[^>]*\>".format(tag), "", desc)
- return desc, image_url
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_item_description_and_image.py b/erpnext/patches/v5_0/update_item_description_and_image.py
deleted file mode 100644
index 75df39ee39..0000000000
--- a/erpnext/patches/v5_0/update_item_description_and_image.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.website.utils import find_first_image
-from frappe.utils import cstr
-import re
-
-def execute():
- item_details = frappe._dict()
- for d in frappe.db.sql("select name, description_html, description from `tabItem`", as_dict=1):
- description = cstr(d.description_html).strip() or cstr(d.description).strip()
- image_url, new_desc = extract_image_and_description(description)
-
- item_details.setdefault(d.name, frappe._dict({
- "old_description": description,
- "new_description": new_desc,
- "image_url": image_url
- }))
-
-
- dt_list= ["Purchase Order Item","Supplier Quotation Item", "BOM", "BOM Explosion Item" , \
- "BOM Item", "Opportunity Item" , "Quotation Item" , "Sales Order Item" , "Delivery Note Item" , \
- "Material Request Item" , "Purchase Receipt Item" , "Stock Entry Detail"]
- for dt in dt_list:
- frappe.reload_doctype(dt)
- records = frappe.db.sql("""select name, `{0}` as item_code, description from `tab{1}`
- where description is not null and image is null and description like '%%
]+\>", "", data)
-
- return image_url, desc
diff --git a/erpnext/patches/v5_0/update_item_name_in_bom.py b/erpnext/patches/v5_0/update_item_name_in_bom.py
deleted file mode 100644
index 5781542a2a..0000000000
--- a/erpnext/patches/v5_0/update_item_name_in_bom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("manufacturing", "doctype", "bom")
- frappe.reload_doc("manufacturing", "doctype", "bom_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_explosion_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_operation")
-
- frappe.db.sql("""update `tabBOM` as bom set bom.item_name = \
- ( select item.item_name from `tabItem` as item where item.name = bom.item)""")
- frappe.db.sql("""update `tabBOM Item` as bomItem set bomItem.item_name = ( select item.item_name \
- from `tabItem` as item where item.name = bomItem.item_code)""")
- frappe.db.sql("""update `tabBOM Explosion Item` as explosionItem set explosionItem.item_name = \
- ( select item.item_name from `tabItem` as item where item.name = explosionItem.item_code)""")
diff --git a/erpnext/patches/v5_0/update_journal_entry_title.py b/erpnext/patches/v5_0/update_journal_entry_title.py
deleted file mode 100644
index eaa2be054f..0000000000
--- a/erpnext/patches/v5_0/update_journal_entry_title.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Journal Entry")
- frappe.db.sql("""update `tabJournal Entry` set title =
- if(ifnull(pay_to_recd_from, "")!="", pay_to_recd_from,
- (select account from `tabJournal Entry Account`
- where parent=`tabJournal Entry`.name and idx=1 limit 1))""")
diff --git a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py b/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py
deleted file mode 100644
index f31c9fed4d..0000000000
--- a/erpnext/patches/v5_0/update_material_transfer_for_manufacture.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabStock Entry` set purpose='Material Transfer for Manufacture'
- where ifnull(work_order, '')!='' and purpose='Material Transfer'""")
diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py
deleted file mode 100644
index 2a09aa29af..0000000000
--- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Work Order")
- frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing=
- (select sum(fg_completed_qty) from `tabStock Entry`
- where docstatus=1
- and work_order=`tabWork Order`.name
- and purpose = "Material Transfer for Manufacture")""")
diff --git a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py b/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py
deleted file mode 100644
index 5847c83d38..0000000000
--- a/erpnext/patches/v5_0/update_material_transferred_for_manufacturing_again.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- wo_order_qty_transferred = frappe._dict()
- for se in frappe.db.sql("""select work_order, sum(fg_completed_qty) as transferred_qty
- from `tabStock Entry`
- where docstatus=1 and ifnull(work_order, '') != ''
- and purpose = 'Material Transfer for Manufacture'
- group by work_order""", as_dict=1):
- wo_order_qty_transferred.setdefault(se.work_order, se.transferred_qty)
-
- for d in frappe.get_all("Work Order", filters={"docstatus": 1}, fields=["name", "qty"]):
- if d.name in wo_order_qty_transferred:
- material_transferred_for_manufacturing = wo_order_qty_transferred.get(d.name) \
- if wo_order_qty_transferred.get(d.name) <= d.qty else d.qty
-
- frappe.db.sql("""update `tabWork Order` set material_transferred_for_manufacturing=%s
- where name=%s""", (material_transferred_for_manufacturing, d.name))
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_operation_description.py b/erpnext/patches/v5_0/update_operation_description.py
deleted file mode 100644
index 4ce32f35f1..0000000000
--- a/erpnext/patches/v5_0/update_operation_description.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import frappe.permissions
-
-def execute():
- if "opn_description" in frappe.db.get_table_columns("BOM Operation"):
- frappe.db.sql("""update `tabBOM Operation` set description = opn_description
- where ifnull(description, '') = ''""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_opportunity.py b/erpnext/patches/v5_0/update_opportunity.py
deleted file mode 100644
index 8eb45c48e7..0000000000
--- a/erpnext/patches/v5_0/update_opportunity.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('crm', 'doctype', 'opportunity')
- frappe.reload_doc('crm', 'doctype', 'opportunity_item')
-
- # all existing opportunities were with items
- frappe.db.sql("update `tabDocType` set module = 'CRM' where name='Opportunity Item'")
- frappe.db.sql("update tabOpportunity set with_items=1, title=customer_name")
- frappe.db.sql("update `tabEmail Account` set append_to='Opportunity' where append_to='Lead'")
diff --git a/erpnext/patches/v5_0/update_projects.py b/erpnext/patches/v5_0/update_projects.py
deleted file mode 100644
index 68e03c9bdb..0000000000
--- a/erpnext/patches/v5_0/update_projects.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # convert milestones to tasks
- frappe.reload_doctype("Project")
- frappe.reload_doc("projects", "doctype", "project_task")
- frappe.reload_doctype("Task")
- frappe.reload_doc("projects", "doctype", "task_depends_on")
- frappe.reload_doc("projects", "doctype", "time_log")
-
- for m in frappe.get_all("Project Milestone", "*"):
- if (m.milestone and m.milestone_date
- and frappe.db.exists("Project", m.parent)):
- subject = (m.milestone[:139] + "…") if (len(m.milestone) > 140) else m.milestone
- description = m.milestone
- task = frappe.get_doc({
- "doctype": "Task",
- "subject": subject,
- "description": description if description!=subject else None,
- "expected_start_date": m.milestone_date,
- "status": "Open" if m.status=="Pending" else "Closed",
- "project": m.parent,
- })
- task.flags.ignore_mandatory = True
- task.insert(ignore_permissions=True)
-
- # remove project milestone
- frappe.delete_doc("DocType", "Project Milestone")
-
- # remove calendar events for milestone
- for e in frappe.get_all("Event", ["name"], {"ref_type": "Project"}):
- frappe.delete_doc("Event", e.name)
diff --git a/erpnext/patches/v5_0/update_sms_sender.py b/erpnext/patches/v5_0/update_sms_sender.py
deleted file mode 100644
index 7ffc703c43..0000000000
--- a/erpnext/patches/v5_0/update_sms_sender.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.set_value("SMS Settings", "SMS Settings", "sms_sender_name",
- frappe.db.get_single_value("Global Defaults", "sms_sender_name"))
diff --git a/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py b/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py
deleted file mode 100644
index 53df9422b3..0000000000
--- a/erpnext/patches/v5_0/update_tax_amount_after_discount_in_purchase_cycle.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""
- update
- `tabPurchase Taxes and Charges`
- set
- tax_amount_after_discount_amount = tax_amount,
- base_tax_amount_after_discount_amount = base_tax_amount
- where
- ifnull(tax_amount_after_discount_amount, 0) = 0
- and ifnull(base_tax_amount_after_discount_amount, 0) = 0
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_temporary_account.py b/erpnext/patches/v5_0/update_temporary_account.py
deleted file mode 100644
index 078c8714ff..0000000000
--- a/erpnext/patches/v5_0/update_temporary_account.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""Update `tabAccount` set account_type = 'Temporary'
- where account_name in ('Temporary Assets', 'Temporary Liabilities', 'Temporary Opening')""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_0/update_time_log_title.py b/erpnext/patches/v5_0/update_time_log_title.py
deleted file mode 100644
index 8263be0007..0000000000
--- a/erpnext/patches/v5_0/update_time_log_title.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Time Log")
- for d in frappe.get_all("Time Log"):
- time_log = frappe.get_doc("Time Log", d.name)
- time_log.set_title()
- frappe.db.set_value("Time Log", time_log.name, "title", time_log.title)
diff --git a/erpnext/patches/v5_1/__init__.py b/erpnext/patches/v5_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v5_1/default_bom.py b/erpnext/patches/v5_1/default_bom.py
deleted file mode 100644
index 6484edd603..0000000000
--- a/erpnext/patches/v5_1/default_bom.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.db.sql("""Update `tabItem` as item set default_bom = NULL where
- not exists(select name from `tabBOM` as bom where item.default_bom = bom.name and bom.docstatus =1 )""")
\ No newline at end of file
diff --git a/erpnext/patches/v5_1/fix_against_account.py b/erpnext/patches/v5_1/fix_against_account.py
deleted file mode 100644
index a62c15b7d1..0000000000
--- a/erpnext/patches/v5_1/fix_against_account.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-from erpnext.accounts.doctype.gl_entry.gl_entry import update_against_account
-
-def execute():
- from_date = "2015-05-01"
-
- for doc in frappe.get_all("Journal Entry",
- filters={"creation": (">", from_date), "docstatus": "1"}):
-
- # update in gl_entry
- update_against_account("Journal Entry", doc.name)
-
- # update in jv
- doc = frappe.get_doc("Journal Entry", doc.name)
- doc.set_against_account()
- doc.db_update()
-
- for doc in frappe.get_all("Sales Invoice",
- filters={"creation": (">", from_date), "docstatus": "1"},
- fields=["name", "customer"]):
-
- frappe.db.sql("""update `tabGL Entry` set against=%s
- where voucher_type='Sales Invoice' and voucher_no=%s
- and credit > 0 and ifnull(party, '')=''""",
- (doc.customer, doc.name))
-
- for doc in frappe.get_all("Purchase Invoice",
- filters={"creation": (">", from_date), "docstatus": "1"},
- fields=["name", "supplier"]):
-
- frappe.db.sql("""update `tabGL Entry` set against=%s
- where voucher_type='Purchase Invoice' and voucher_no=%s
- and debit > 0 and ifnull(party, '')=''""",
- (doc.supplier, doc.name))
diff --git a/erpnext/patches/v5_1/rename_roles.py b/erpnext/patches/v5_1/rename_roles.py
deleted file mode 100644
index e19c22a614..0000000000
--- a/erpnext/patches/v5_1/rename_roles.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists("Role", "Stock User"):
- frappe.rename_doc("Role", "Material User", "Stock User")
- if not frappe.db.exists("Role", "Stock Manager"):
- frappe.rename_doc("Role", "Material Manager", "Stock Manager")
- if not frappe.db.exists("Role", "Item Manager"):
- frappe.rename_doc("Role", "Material Master Manager", "Item Manager")
diff --git a/erpnext/patches/v5_1/sales_bom_rename.py b/erpnext/patches/v5_1/sales_bom_rename.py
deleted file mode 100644
index e06012f3e4..0000000000
--- a/erpnext/patches/v5_1/sales_bom_rename.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- tables = frappe.db.sql_list("show tables")
- for old_dt, new_dt in [["Sales BOM Item", "Product Bundle Item"],
- ["Sales BOM", "Product Bundle"]]:
- if "tab"+new_dt not in tables:
- frappe.rename_doc("DocType", old_dt, new_dt, force=True)
diff --git a/erpnext/patches/v5_2/__init__.py b/erpnext/patches/v5_2/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v5_2/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v5_2/change_item_selects_to_checks.py b/erpnext/patches/v5_2/change_item_selects_to_checks.py
deleted file mode 100644
index 1ee8f6caa5..0000000000
--- a/erpnext/patches/v5_2/change_item_selects_to_checks.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- fields = ("is_stock_item", "is_asset_item", "has_batch_no", "has_serial_no",
- "is_sales_item", "is_purchase_item", "inspection_required", "is_sub_contracted_item")
-
- # convert to 1 or 0
- update_str = ", ".join(["`{0}`=if(`{0}`='Yes',1,0)".format(f) for f in fields])
- frappe.db.sql("update tabItem set {0}".format(update_str))
-
- frappe.db.commit()
-
- # alter fields to int
- for f in fields:
- frappe.db.sql("alter table tabItem change {0} {0} int(1) default '0'".format(f, f))
-
- frappe.reload_doctype("Item")
diff --git a/erpnext/patches/v5_4/__init__.py b/erpnext/patches/v5_4/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v5_4/cleanup_journal_entry.py b/erpnext/patches/v5_4/cleanup_journal_entry.py
deleted file mode 100644
index 6860e6ad09..0000000000
--- a/erpnext/patches/v5_4/cleanup_journal_entry.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from pymysql import InternalError
-
-def execute():
- frappe.reload_doctype("Journal Entry Account")
- for doctype, fieldname in (
- ("Sales Order", "against_sales_order"),
- ("Purchase Order", "against_purchase_order"),
- ("Sales Invoice", "against_invoice"),
- ("Purchase Invoice", "against_voucher"),
- ("Journal Entry", "against_jv"),
- ("Expense Claim", "against_expense_claim"),
- ):
- try:
- frappe.db.sql("""update `tabJournal Entry Account`
- set reference_type=%s, reference_name={0} where ifnull({0}, '') != ''
- """.format(fieldname), doctype)
- except InternalError:
- # column not found
- pass
diff --git a/erpnext/patches/v5_4/fix_invoice_outstanding.py b/erpnext/patches/v5_4/fix_invoice_outstanding.py
deleted file mode 100644
index 54a1da69ef..0000000000
--- a/erpnext/patches/v5_4/fix_invoice_outstanding.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
-
-def execute():
- frappe.reload_doctype("Sales Invoice")
- return_entries = frappe.get_list("Sales Invoice", filters={"is_return": 1, "docstatus": 1},
- fields=["debit_to", "customer", "return_against"])
- for d in return_entries:
- update_outstanding_amt(d.debit_to, "Customer", d.customer, "Sales Invoice", d.return_against)
diff --git a/erpnext/patches/v5_4/fix_missing_item_images.py b/erpnext/patches/v5_4/fix_missing_item_images.py
deleted file mode 100644
index c6fe57896f..0000000000
--- a/erpnext/patches/v5_4/fix_missing_item_images.py
+++ /dev/null
@@ -1,126 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-import os
-from frappe.utils import get_files_path
-from frappe.core.doctype.file.file import get_content_hash
-
-def execute():
- files_path = get_files_path()
-
- # get files that don't have attached_to_name but exist
- unlinked_files = get_unlinked_files(files_path)
- if not unlinked_files:
- return
-
- fixed_files = fix_files_for_item(files_path, unlinked_files)
-
- # fix remaining files
- for key, file_data in unlinked_files.items():
- if key not in fixed_files:
- rename_and_set_content_hash(files_path, unlinked_files, key)
- frappe.db.commit()
-
-def fix_files_for_item(files_path, unlinked_files):
- fixed_files = []
-
- # make a list of files/something and /files/something to check in child table's image column
- file_urls = [key for key in unlinked_files.keys()] + ["/" + key for key in unlinked_files.keys()]
- file_item_code = get_file_item_code(file_urls)
-
- for (file_url, item_code), children in file_item_code.items():
- new_file_url = "/files/{0}".format(unlinked_files[file_url]["file_name"])
-
- for row in children:
- # print file_url, new_file_url, item_code, row.doctype, row.name
-
- # replace image in these rows with the new file url
- frappe.db.set_value(row.doctype, row.name, "image", new_file_url, update_modified=False)
-
- # set it as attachment of this item code
- file_data = frappe.get_doc("File", unlinked_files[file_url]["file"])
- file_data.attached_to_doctype = "Item"
- file_data.attached_to_name = item_code
- file_data.flags.ignore_folder_validate = True
-
- try:
- file_data.save()
- except IOError:
- print("File {0} does not exist".format(new_file_url))
-
- # marking fix to prevent further errors
- fixed_files.append(file_url)
-
- continue
-
- # set it as image in Item
- if not frappe.db.get_value("Item", item_code, "image"):
- frappe.db.set_value("Item", item_code, "image", new_file_url, update_modified=False)
-
- rename_and_set_content_hash(files_path, unlinked_files, file_url)
-
- fixed_files.append(file_url)
-
- # commit
- frappe.db.commit()
-
- return fixed_files
-
-def rename_and_set_content_hash(files_path, unlinked_files, file_url):
- # rename this file
- old_filename = os.path.join(files_path, unlinked_files[file_url]["file"])
- new_filename = os.path.join(files_path, unlinked_files[file_url]["file_name"])
-
- if not os.path.exists(new_filename):
- os.rename(old_filename, new_filename)
-
- # set content hash if missing
- file_data_name = unlinked_files[file_url]["file"]
- if not frappe.db.get_value("File", file_data_name, "content_hash"):
- with open(new_filename, "r") as f:
- content_hash = get_content_hash(f.read())
- frappe.db.set_value("File", file_data_name, "content_hash", content_hash)
-
-def get_unlinked_files(files_path):
- # find files that have the same name as a File doc
- # and the file_name mentioned in that File doc doesn't exist
- # and it isn't already attached to a doc
- unlinked_files = {}
- files = os.listdir(files_path)
- for file in files:
- if not frappe.db.exists("File", {"file_name": file}):
- file_data = frappe.db.get_value("File", {"name": file},
- ["file_name", "attached_to_doctype", "attached_to_name"], as_dict=True)
-
- if (file_data
- and file_data.file_name
- and file_data.file_name not in files
- and not file_data.attached_to_doctype
- and not file_data.attached_to_name):
-
- file_data["file"] = file
- unlinked_files["files/{0}".format(file)] = file_data
-
- return unlinked_files
-
-def get_file_item_code(file_urls):
- # get a map of file_url, item_code and list of documents where file_url will need to be changed in image field
- file_item_code = {}
-
- doctypes = frappe.db.sql_list("""select name from `tabDocType` dt
- where istable=1
- and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='item_code')
- and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='image')""")
-
- for doctype in doctypes:
- result = frappe.db.sql("""select name, image, item_code, '{0}' as doctype from `tab{0}`
- where image in ({1})""".format(doctype, ", ".join(["%s"]*len(file_urls))),
- file_urls, as_dict=True)
-
- for r in result:
- key = (r.image, r.item_code)
- if key not in file_item_code:
- file_item_code[key] = []
-
- file_item_code[key].append(r)
-
- return file_item_code
diff --git a/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py b/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py
deleted file mode 100644
index 6eb3994c7c..0000000000
--- a/erpnext/patches/v5_4/fix_reserved_qty_and_sle_for_packed_items.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import repost_actual_qty
-
-def execute():
- cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice`
- where docstatus = 2 and ifnull(update_stock, 0) = 1""")
-
- if cancelled_invoices:
- repost_for = frappe.db.sql("""select distinct item_code, warehouse from `tabStock Ledger Entry`
- where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
- % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
-
- frappe.db.sql("""delete from `tabStock Ledger Entry`
- where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
- % (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
-
- for item_code, warehouse in repost_for:
- repost_actual_qty(item_code, warehouse)
\ No newline at end of file
diff --git a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
deleted file mode 100644
index ba311225bb..0000000000
--- a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.email import sendmail_to_system_managers
-from frappe.utils import get_link_to_form
-
-def execute():
- wrong_records = []
- for dt in ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
- "Purchase Order", "Purchase Receipt", "Purchase Invoice"):
- records = frappe.db.sql_list("""select name from `tab{0}`
- where apply_discount_on = 'Net Total' and ifnull(discount_amount, 0) != 0
- and modified >= '2015-02-17' and docstatus=1""".format(dt))
-
- if records:
- records = [get_link_to_form(dt, d) for d in records]
- wrong_records.append([dt, records])
-
- if wrong_records:
- content = """Dear System Manager,
-
-Due to an error related to Discount Amount on Net Total, tax calculation might be wrong in the following records. We did not fix the tax amount automatically because it can corrupt the entries, so we request you to check these records and amend if you found the calculation wrong.
-
-Please check following Entries:
-
-%s
-
-
-Regards,
-
-Administrator""" % "\n".join([(d[0] + ": " + ", ".join(d[1])) for d in wrong_records])
- try:
- sendmail_to_system_managers("[Important] [ERPNext] Tax calculation might be wrong, please check.", content)
- except:
- pass
-
- print("="*50)
- print(content)
- print("="*50)
\ No newline at end of file
diff --git a/erpnext/patches/v5_4/set_root_and_report_type.py b/erpnext/patches/v5_4/set_root_and_report_type.py
deleted file mode 100644
index 9147644da2..0000000000
--- a/erpnext/patches/v5_4/set_root_and_report_type.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- roots = frappe.db.sql("""select lft, rgt, report_type, root_type
- from `tabAccount` where ifnull(parent_account, '')=''""", as_dict=1)
- for d in roots:
- frappe.db.sql("update `tabAccount` set report_type=%s, root_type=%s where lft > %s and rgt < %s",
- (d.report_type, d.root_type, d.lft, d.rgt))
\ No newline at end of file
diff --git a/erpnext/patches/v5_4/stock_entry_additional_costs.py b/erpnext/patches/v5_4/stock_entry_additional_costs.py
deleted file mode 100644
index 3a98deb918..0000000000
--- a/erpnext/patches/v5_4/stock_entry_additional_costs.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doctype("Stock Entry")
- frappe.reload_doctype("Stock Entry Detail")
- frappe.reload_doctype("Landed Cost Taxes and Charges")
-
- stock_entry_db_columns = frappe.db.get_table_columns("Stock Entry")
- if "additional_operating_cost" in stock_entry_db_columns:
- operating_cost_fieldname = "additional_operating_cost"
- elif "total_fixed_cost" in stock_entry_db_columns:
- operating_cost_fieldname = "total_fixed_cost"
- else:
- return
-
-
- frappe.db.sql("""update `tabStock Entry Detail` sed, `tabStock Entry` se
- set sed.valuation_rate=sed.incoming_rate, sed.basic_rate=sed.incoming_rate, sed.basic_amount=sed.amount
- where sed.parent = se.name
- and (se.purpose not in ('Manufacture', 'Repack') or ifnull({0}, 0)=0)
- """.format(operating_cost_fieldname))
-
-
- stock_entries = frappe.db.sql_list("""select name from `tabStock Entry`
- where purpose in ('Manufacture', 'Repack') and ifnull({0}, 0)!=0
- and docstatus < 2""".format(operating_cost_fieldname))
-
- for d in stock_entries:
- stock_entry = frappe.get_doc("Stock Entry", d)
- stock_entry.append("additional_costs", {
- "description": "Additional Operating Cost",
- "amount": stock_entry.get(operating_cost_fieldname)
- })
-
- number_of_fg_items = len([t.t_warehouse for t in stock_entry.get("items") if t.t_warehouse])
-
- for d in stock_entry.get("items"):
- d.valuation_rate = d.incoming_rate
-
- if d.bom_no or (d.t_warehouse and number_of_fg_items == 1):
- d.additional_cost = stock_entry.get(operating_cost_fieldname)
-
- d.basic_rate = flt(d.valuation_rate) - flt(d.additional_cost)
- d.basic_amount = flt(flt(d.basic_rate) *flt(d.transfer_qty), d.precision("basic_amount"))
-
- stock_entry.flags.ignore_validate = True
- stock_entry.flags.ignore_validate_update_after_submit = True
- stock_entry.save()
diff --git a/erpnext/patches/v5_4/update_purchase_cost_against_project.py b/erpnext/patches/v5_4/update_purchase_cost_against_project.py
deleted file mode 100644
index 1b917c83c4..0000000000
--- a/erpnext/patches/v5_4/update_purchase_cost_against_project.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for p in frappe.get_all("Project"):
- purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
- from `tabPurchase Invoice Item` where project = %s and docstatus=1""", p.name)
- purchase_cost = purchase_cost and purchase_cost[0][0] or 0
-
- frappe.db.set_value("Project", p.name, "total_purchase_cost", purchase_cost)
\ No newline at end of file
diff --git a/erpnext/patches/v5_7/__init__.py b/erpnext/patches/v5_7/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v5_7/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v5_7/item_template_attributes.py b/erpnext/patches/v5_7/item_template_attributes.py
deleted file mode 100644
index 6aa81f79b2..0000000000
--- a/erpnext/patches/v5_7/item_template_attributes.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.exceptions import SQLError
-
-def execute():
- """
- Structure History:
- 1. Item and Item Variant
- 2. Item, Variant Attribute, Manage Variants and Manage Variant Items
- 3. Item, Item Variant Attribute, Item Attribute and Item Attribute Type (latest)
- """
- rename_and_reload_doctypes()
-
- variant_templates = frappe.get_all("Item", filters={"has_variants": 1}, limit_page_length=1)
- if not variant_templates:
- # database does not have items that have variants
- # so no point in running the patch
- return
-
- variant_attributes = frappe.get_all("Item Variant Attribute", fields=["*"], limit_page_length=1)
-
- if variant_attributes:
- # manage variant patch is already applied
- migrate_manage_variants()
-
- else:
- # old structure based on "Item Variant" table
- try:
- migrate_item_variants()
-
- except SQLError:
- print("`tabItem Variant` not found")
-
-def rename_and_reload_doctypes():
- if "tabVariant Attribute" in frappe.db.get_tables():
- frappe.rename_doc("DocType", "Variant Attribute", "Item Variant Attribute")
-
- frappe.reload_doctype("Item")
- frappe.reload_doc("Stock", "DocType", "Item Variant Attribute")
- frappe.reload_doc("Stock", "DocType", "Item Attribute Value")
- frappe.reload_doc("Stock", "DocType", "Item Attribute")
-
-def migrate_manage_variants():
- item_attribute = {}
- for d in frappe.db.sql("""select DISTINCT va.attribute, i.variant_of
- from `tabItem Variant Attribute` va, `tabItem` i
- where va.parent = i.name and ifnull(i.variant_of, '')!=''""", as_dict=1):
- item_attribute.setdefault(d.variant_of, []).append({"attribute": d.attribute})
-
- for item, attributes in item_attribute.items():
- template = frappe.get_doc("Item", item)
- template.set('attributes', attributes)
- template.save()
-
-# patch old style
-def migrate_item_variants():
- for item in frappe.get_all("Item", filters={"has_variants": 1}):
- all_variants = frappe.get_all("Item", filters={"variant_of": item.name}, fields=["name", "description"])
- item_attributes = frappe.db.sql("""select distinct item_attribute, item_attribute_value
- from `tabItem Variant` where parent=%s""", item.name)
-
- if not item_attributes and not all_variants:
- item = frappe.get_doc("Item", item.name)
- item.has_variants = 0
- item.save()
- continue
-
- attribute_value_options = {}
- for attribute, value in item_attributes:
- attribute_value_options.setdefault(attribute, []).append(value)
-
- possible_combinations = get_possible_combinations(attribute_value_options)
-
- for variant in all_variants:
- for combination in possible_combinations:
- match = True
- for attribute, value in combination.items():
- if "{0}: {1}".format(attribute, value) not in variant.description:
- match = False
- break
-
- if match:
- # found the right variant
- save_attributes_in_variant(variant, combination)
- break
-
- save_attributes_in_template(item, attribute_value_options)
-
- frappe.delete_doc("DocType", "Item Variant")
-
-def save_attributes_in_template(item, attribute_value_options):
- # store attribute in Item Variant Attribute table for template
- template = frappe.get_doc("Item", item)
- template.set("attributes", [{"attribute": attribute} for attribute in attribute_value_options.keys()])
- template.save()
-
-def get_possible_combinations(attribute_value_options):
- possible_combinations = []
-
- for attribute, values in attribute_value_options.items():
- if not possible_combinations:
- for v in values:
- possible_combinations.append({attribute: v})
-
- else:
- for v in values:
- for combination in possible_combinations:
- combination[attribute] = v
-
- return possible_combinations
-
-def save_attributes_in_variant(variant, combination):
- # add data into attributes table
- variant_item = frappe.get_doc("Item", variant.name)
- variant_item.set("attributes", [])
- for attribute, value in combination.items():
- variant_item.append("attributes", {
- "attribute": attribute,
- "attribute_value": value
- })
- variant_item.save()
diff --git a/erpnext/patches/v5_8/__init__.py b/erpnext/patches/v5_8/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v5_8/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v5_8/add_credit_note_print_heading.py b/erpnext/patches/v5_8/add_credit_note_print_heading.py
deleted file mode 100644
index 476cbc8956..0000000000
--- a/erpnext/patches/v5_8/add_credit_note_print_heading.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- for print_heading in (_("Credit Note"), _("Debit Note")):
- if not frappe.db.exists("Print Heading", print_heading):
- frappe.get_doc({
- "doctype": "Print Heading",
- "print_heading": print_heading
- }).insert()
diff --git a/erpnext/patches/v5_8/tax_rule.py b/erpnext/patches/v5_8/tax_rule.py
deleted file mode 100644
index 8da28ba4c9..0000000000
--- a/erpnext/patches/v5_8/tax_rule.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "tax_rule")
-
- customers = frappe.db.sql("""select name, default_taxes_and_charges from tabCustomer where
- ifnull(default_taxes_and_charges, '') != '' """, as_dict=1)
-
- for d in customers:
- if not frappe.db.sql("select name from `tabTax Rule` where customer=%s", d.name):
- tr = frappe.new_doc("Tax Rule")
- tr.tax_type = "Sales"
- tr.customer = d.name
- tr.sales_tax_template = d.default_taxes_and_charges
- tr.save()
-
-
- suppliers = frappe.db.sql("""select name, default_taxes_and_charges from tabSupplier where
- ifnull(default_taxes_and_charges, '') != '' """, as_dict=1)
-
- for d in suppliers:
- if not frappe.db.sql("select name from `tabTax Rule` where supplier=%s", d.name):
- tr = frappe.new_doc("Tax Rule")
- tr.tax_type = "Purchase"
- tr.supplier = d.name
- tr.purchase_tax_template = d.default_taxes_and_charges
- tr.save()
\ No newline at end of file
diff --git a/erpnext/patches/v5_8/update_order_reference_in_return_entries.py b/erpnext/patches/v5_8/update_order_reference_in_return_entries.py
deleted file mode 100644
index 503263834c..0000000000
--- a/erpnext/patches/v5_8/update_order_reference_in_return_entries.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Delivery Note")
- frappe.reload_doctype("Sales Invoice")
- frappe.reload_doctype("Purchase Receipt")
- frappe.reload_doctype("Sales Order Item")
- frappe.reload_doctype("Purchase Order Item")
- frappe.reload_doctype("Purchase Order Item Supplied")
-
- # sales return
- return_entries = list(frappe.db.sql("""
- select dn.name as name, dn_item.name as row_id, dn.return_against,
- dn_item.item_code, "Delivery Note" as doctype
- from `tabDelivery Note Item` dn_item, `tabDelivery Note` dn
- where dn_item.parent=dn.name and dn.is_return=1 and dn.docstatus < 2
- """, as_dict=1))
-
- return_entries += list(frappe.db.sql("""
- select si.name as name, si_item.name as row_id, si.return_against,
- si_item.item_code, "Sales Invoice" as doctype, update_stock
- from `tabSales Invoice Item` si_item, `tabSales Invoice` si
- where si_item.parent=si.name and si.is_return=1 and si.docstatus < 2
- """, as_dict=1))
-
- for d in return_entries:
- ref_field = "against_sales_order" if d.doctype == "Delivery Note" else "sales_order"
- order_details = frappe.db.sql("""
- select {ref_field} as sales_order, so_detail,
- (select transaction_date from `tabSales Order` where name=item.{ref_field}) as sales_order_date
- from `tab{doctype} Item` item
- where
- parent=%s
- and item_code=%s
- and ifnull(so_detail, '') !=''
- order by sales_order_date DESC limit 1
- """.format(ref_field=ref_field, doctype=d.doctype), (d.return_against, d.item_code), as_dict=1)
-
- if order_details:
- frappe.db.sql("""
- update `tab{doctype} Item`
- set {ref_field}=%s, so_detail=%s
- where name=%s
- """.format(doctype=d.doctype, ref_field=ref_field),
- (order_details[0].sales_order, order_details[0].so_detail, d.row_id))
-
- if (d.doctype=="Sales Invoice" and d.update_stock) or d.doctype=="Delivery Note":
- doc = frappe.get_doc(d.doctype, d.name)
- doc.update_reserved_qty()
-
- if d.doctype=="Sales Invoice":
- doc.status_updater = []
- doc.update_status_updater_args()
-
- doc.update_prevdoc_status()
-
- #--------------------------
- # purchase return
- return_entries = frappe.db.sql("""
- select pr.name as name, pr_item.name as row_id, pr.return_against, pr_item.item_code
- from `tabPurchase Receipt Item` pr_item, `tabPurchase Receipt` pr
- where pr_item.parent=pr.name and pr.is_return=1 and pr.docstatus < 2
- """, as_dict=1)
-
- for d in return_entries:
- order_details = frappe.db.sql("""
- select prevdoc_docname as purchase_order, prevdoc_detail_docname as po_detail,
- (select transaction_date from `tabPurchase Order` where name=item.prevdoc_detail_docname) as purchase_order_date
- from `tabPurchase Receipt Item` item
- where
- parent=%s
- and item_code=%s
- and ifnull(prevdoc_detail_docname, '') !=''
- and ifnull(prevdoc_doctype, '') = 'Purchase Order' and ifnull(prevdoc_detail_docname, '') != ''
- order by purchase_order_date DESC limit 1
- """, (d.return_against, d.item_code), as_dict=1)
-
- if order_details:
- frappe.db.sql("""
- update `tabPurchase Receipt Item`
- set prevdoc_doctype='Purchase Order', prevdoc_docname=%s, prevdoc_detail_docname=%s
- where name=%s
- """, (order_details[0].purchase_order, order_details[0].po_detail, d.row_id))
-
- pr = frappe.get_doc("Purchase Receipt", d.name)
- pr.update_ordered_and_reserved_qty()
- pr.update_prevdoc_status()
-
diff --git a/erpnext/patches/v6_0/__init__.py b/erpnext/patches/v6_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_0/default_activity_rate.py b/erpnext/patches/v6_0/default_activity_rate.py
deleted file mode 100644
index cfbfb723bc..0000000000
--- a/erpnext/patches/v6_0/default_activity_rate.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("projects", "doctype", "activity_cost")
-
- for cost in frappe.db.get_list("Activity Cost", filters = {"employee": ""},
- fields = ("name", "activity_type", "costing_rate", "billing_rate")):
- activity_type = frappe.get_doc("Activity Type", cost.activity_type)
- activity_type.costing_rate = cost.costing_rate
- activity_type.billing_rate = cost.billing_rate
- activity_type.save()
-
- frappe.delete_doc("Activity Cost", cost.name)
diff --git a/erpnext/patches/v6_0/fix_outstanding_amount.py b/erpnext/patches/v6_0/fix_outstanding_amount.py
deleted file mode 100644
index 0de689074f..0000000000
--- a/erpnext/patches/v6_0/fix_outstanding_amount.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
-
-def execute():
- for dt, party_field, account_field in (("Sales Invoice", "customer", "debit_to"),
- ("Purchase Invoice", "supplier", "credit_to")):
-
- wrong_invoices = frappe.db.sql("""select name, {0} as account from `tab{1}`
- where docstatus=1 and ifnull({2}, '')=''""".format(account_field, dt, party_field))
-
- for invoice, account in wrong_invoices:
- update_outstanding_amt(account, party_field.title(), None, dt, invoice)
\ No newline at end of file
diff --git a/erpnext/patches/v6_0/fix_planned_qty.py b/erpnext/patches/v6_0/fix_planned_qty.py
deleted file mode 100644
index cf7b429249..0000000000
--- a/erpnext/patches/v6_0/fix_planned_qty.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
-
-def execute():
- for item_code, warehouse in frappe.db.sql("""select distinct production_item, fg_warehouse
- from `tabWork Order`"""):
- if frappe.db.exists("Item", item_code) and frappe.db.exists("Warehouse", warehouse):
- update_bin_qty(item_code, warehouse, {
- "planned_qty": get_planned_qty(item_code, warehouse)
- })
diff --git a/erpnext/patches/v6_0/multi_currency.py b/erpnext/patches/v6_0/multi_currency.py
deleted file mode 100644
index b4c37fc253..0000000000
--- a/erpnext/patches/v6_0/multi_currency.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # Reload doctype
- for dt in ("Account", "GL Entry", "Journal Entry",
- "Journal Entry Account", "Sales Invoice", "Purchase Invoice", "Customer", "Supplier"):
- frappe.reload_doctype(dt)
-
- company_list = frappe.get_all("Company", fields=["name", "default_currency", "default_receivable_account"])
- for company in company_list:
-
- # update currency in account and gl entry as per company currency
- frappe.db.sql("""update `tabAccount` set account_currency = %s
- where ifnull(account_currency, '') = '' and company=%s""", (company.default_currency, company.name))
-
- # update newly introduced field's value in sales / purchase invoice
- frappe.db.sql("""
- update
- `tabSales Invoice`
- set
- base_paid_amount=paid_amount,
- base_write_off_amount=write_off_amount,
- party_account_currency=%s
- where company=%s
- """, (company.default_currency, company.name))
-
- frappe.db.sql("""
- update
- `tabPurchase Invoice`
- set
- base_write_off_amount=write_off_amount,
- party_account_currency=%s
- where company=%s
- """, (company.default_currency, company.name))
-
- # update exchange rate, debit/credit in account currency in Journal Entry
- frappe.db.sql("""
- update `tabJournal Entry Account` jea
- set exchange_rate=1,
- debit_in_account_currency=debit,
- credit_in_account_currency=credit,
- account_type=(select account_type from `tabAccount` where name=jea.account)
- """)
-
- frappe.db.sql("""
- update `tabJournal Entry Account` jea, `tabJournal Entry` je
- set account_currency=%s
- where jea.parent = je.name and je.company=%s
- """, (company.default_currency, company.name))
-
- # update debit/credit in account currency in GL Entry
- frappe.db.sql("""
- update
- `tabGL Entry`
- set
- debit_in_account_currency=debit,
- credit_in_account_currency=credit,
- account_currency=%s
- where
- company=%s
- """, (company.default_currency, company.name))
diff --git a/erpnext/patches/v6_0/set_default_title.py b/erpnext/patches/v6_0/set_default_title.py
deleted file mode 100644
index cceff3f480..0000000000
--- a/erpnext/patches/v6_0/set_default_title.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Quotation")
- frappe.db.sql("""update tabQuotation set title = customer_name""")
-
- frappe.reload_doctype("Sales Order")
- frappe.db.sql("""update `tabSales Order` set title = customer_name""")
-
- frappe.reload_doctype("Delivery Note")
- frappe.db.sql("""update `tabDelivery Note` set title = customer_name""")
-
- frappe.reload_doctype("Material Request")
- frappe.db.sql("""update `tabMaterial Request` set title = material_request_type""")
-
- frappe.reload_doctype("Supplier Quotation")
- frappe.db.sql("""update `tabSupplier Quotation` set title = supplier_name""")
-
- frappe.reload_doctype("Purchase Order")
- frappe.db.sql("""update `tabPurchase Order` set title = supplier_name""")
-
- frappe.reload_doctype("Purchase Receipt")
- frappe.db.sql("""update `tabPurchase Receipt` set title = supplier_name""")
-
- frappe.reload_doctype("Purchase Invoice")
- frappe.db.sql("""update `tabPurchase Invoice` set title = supplier_name""")
-
- frappe.reload_doctype("Stock Entry")
- frappe.db.sql("""update `tabStock Entry` set title = purpose""")
-
- frappe.reload_doctype("Sales Invoice")
- frappe.db.sql("""update `tabSales Invoice` set title = customer_name""")
-
- frappe.reload_doctype("Expense Claim")
- frappe.db.sql("""update `tabExpense Claim` set title = employee_name""")
diff --git a/erpnext/patches/v6_10/__init__.py b/erpnext/patches/v6_10/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_10/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_10/email_digest_default_quote.py b/erpnext/patches/v6_10/email_digest_default_quote.py
deleted file mode 100644
index 6139f1a88a..0000000000
--- a/erpnext/patches/v6_10/email_digest_default_quote.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Email Digest")
- frappe.db.sql("update `tabEmail Digest` set add_quote = 1")
diff --git a/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py b/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py
deleted file mode 100644
index d7f72b5880..0000000000
--- a/erpnext/patches/v6_10/fix_billed_amount_in_drop_ship_po.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update `tabPurchase Order Item` set billed_amt = 0
- where delivered_by_supplier=1 and docstatus=1""")
-
- drop_ship_pos = frappe.db.sql("""select distinct parent from `tabPurchase Order Item`
- where delivered_by_supplier=1 and docstatus=1""")
-
- for po in drop_ship_pos:
- invoices = frappe.db.sql("""select distinct parent from `tabPurchase Invoice Item`
- where purchase_order=%s and docstatus=1""", po[0])
- if invoices:
- for inv in invoices:
- frappe.get_doc("Purchase Invoice", inv[0]).update_qty(update_modified=False)
- else:
- frappe.db.sql("""update `tabPurchase Order` set per_billed=0 where name=%s""", po[0])
\ No newline at end of file
diff --git a/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py b/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py
deleted file mode 100644
index 9a53b7f5d3..0000000000
--- a/erpnext/patches/v6_10/fix_delivery_status_of_drop_ship_item.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Sales Order Item")
- for so_name in frappe.db.sql("""select distinct parent from `tabSales Order Item`
- where delivered_by_supplier=1 and docstatus=1"""):
- so = frappe.get_doc("Sales Order", so_name[0])
- so.update_delivery_status()
- so.set_status(update=True, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v6_10/fix_jv_total_amount.py b/erpnext/patches/v6_10/fix_jv_total_amount.py
deleted file mode 100644
index 42cb9e9e15..0000000000
--- a/erpnext/patches/v6_10/fix_jv_total_amount.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-# patch all for-print field (total amount) in Journal Entry in 2015
-def execute():
- for je in frappe.get_all("Journal Entry", filters={"creation": (">", "2015-01-01")}):
- je = frappe.get_doc("Journal Entry", je.name)
- original = je.total_amount
-
- je.set_print_format_fields()
-
- if je.total_amount != original:
- je.db_set("total_amount", je.total_amount, update_modified=False)
- je.db_set("total_amount_in_words", je.total_amount_in_words, update_modified=False)
diff --git a/erpnext/patches/v6_10/fix_ordered_received_billed.py b/erpnext/patches/v6_10/fix_ordered_received_billed.py
deleted file mode 100644
index c81a20ec54..0000000000
--- a/erpnext/patches/v6_10/fix_ordered_received_billed.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- not_null_patch_date = frappe.db.sql("""select date(creation) from `tabPatch Log` where patch='frappe.patches.v6_9.int_float_not_null'""")
- if not not_null_patch_date:
- return
-
- not_null_patch_date = not_null_patch_date[0][0]
-
- for doctype in ("Purchase Invoice", "Sales Invoice", "Purchase Order", "Delivery Note", "Installation Note", "Delivery Note", "Purchase Receipt"):
- for name in frappe.db.sql_list("""select name from `tab{doctype}`
- where docstatus > 0 and (date(creation) >= %(patch_date)s or date(modified) >= %(patch_date)s)""".format(doctype=doctype),
- {"patch_date": not_null_patch_date}):
-
- doc = frappe.get_doc(doctype, name)
- doc.update_qty(update_modified=False)
diff --git a/erpnext/patches/v6_12/__init__.py b/erpnext/patches/v6_12/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py b/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
deleted file mode 100644
index fb5eab4e05..0000000000
--- a/erpnext/patches/v6_12/repost_entries_with_target_warehouse.py
+++ /dev/null
@@ -1,175 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-"""
-This patch is written to fix Stock Ledger Entries and GL Entries
-against Delivery Notes and Sales Invoice where Target Warehouse has been set wrongly
-due to User Permissions on Warehouse.
-
-This cannot be run automatically because we can't take a call that
-Target Warehouse has been set purposefully or by mistake.
-Thats why we left it to the users to take the call, and manually run the patch.
-
-This patch has 2 main functions, `check()` and `repost()`.
-- Run `check` function, to list out all the Sales Orders, Delivery Notes
- and Sales Invoice with Target Warehouse.
-- Run `repost` function to remove the Target Warehouse value and repost SLE and GLE again.
-
-To execute this patch run following commands from frappe-bench directory:
-```
- bench --site [your-site-name] execute erpnext.patches.v6_12.repost_entries_with_target_warehouse.check
- bench --site [your-site-name] backup
- bench --site [your-site-name] execute erpnext.patches.v6_12.repost_entries_with_target_warehouse.repost
-```
-
-Exception Handling:
-While reposting, if you get any exception, it will printed on screen.
-Mostly it can be due to negative stock issue. If that is the case, follow these steps
- - Ensure that stock is available for those items in the mentioned warehouse on the date mentioned in the error
- - Execute `repost` funciton again
-"""
-
-def check():
- so_list = get_affected_sales_order()
- dn_list = get_affected_delivery_notes()
- si_list = get_affected_sales_invoice()
-
- if so_list or dn_list or si_list:
- print("Entries with Target Warehouse:")
-
- if so_list:
- print("Sales Order")
- print(so_list)
-
- if dn_list:
- print("Delivery Notes")
- print([d.name for d in dn_list])
-
- if si_list:
- print("Sales Invoice")
- print([d.name for d in si_list])
-
-
-def repost():
- dn_failed_list, si_failed_list = [], []
- repost_dn(dn_failed_list)
- repost_si(si_failed_list)
- repost_so()
- frappe.db.commit()
-
- if dn_failed_list:
- print("-"*40)
- print("Delivery Note Failed to Repost")
- print(dn_failed_list)
-
- if si_failed_list:
- print("-"*40)
- print("Sales Invoice Failed to Repost")
- print(si_failed_list)
- print()
-
- print("""
-If above Delivery Notes / Sales Invoice failed due to negative stock, follow these steps:
- - Ensure that stock is available for those items in the mentioned warehouse on the date mentioned in the error
- - Run this patch again
-""")
-
-def repost_dn(dn_failed_list):
- dn_list = get_affected_delivery_notes()
-
- if dn_list:
- print("-"*40)
- print("Reposting Delivery Notes")
-
- for dn in dn_list:
- if dn.docstatus == 0:
- continue
-
- print(dn.name)
-
- try:
- dn_doc = frappe.get_doc("Delivery Note", dn.name)
- dn_doc.docstatus = 2
- dn_doc.update_prevdoc_status()
- dn_doc.update_stock_ledger()
- dn_doc.cancel_packing_slips()
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type='Delivery Note' and voucher_no=%s""", dn.name)
-
- frappe.db.sql("update `tabDelivery Note Item` set target_warehouse='' where parent=%s", dn.name)
- dn_doc = frappe.get_doc("Delivery Note", dn.name)
- dn_doc.docstatus = 1
- dn_doc.on_submit()
- frappe.db.commit()
- except Exception:
- dn_failed_list.append(dn.name)
- frappe.local.stockledger_exceptions = None
- print(frappe.get_traceback())
- frappe.db.rollback()
-
- frappe.db.sql("update `tabDelivery Note Item` set target_warehouse='' where docstatus=0")
-
-def repost_si(si_failed_list):
- si_list = get_affected_sales_invoice()
-
- if si_list:
- print("-"*40)
- print("Reposting Sales Invoice")
-
- for si in si_list:
- if si.docstatus == 0:
- continue
-
- print(si.name)
-
- try:
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- si_doc.docstatus = 2
- si_doc.update_stock_ledger()
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
-
- frappe.db.sql("update `tabSales Invoice Item` set target_warehouse='' where parent=%s", si.name)
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- si_doc.docstatus = 1
- si_doc.update_stock_ledger()
- si_doc.make_gl_entries()
- frappe.db.commit()
- except Exception:
- si_failed_list.append(si.name)
- frappe.local.stockledger_exceptions = None
- print(frappe.get_traceback())
- frappe.db.rollback()
-
- frappe.db.sql("update `tabSales Invoice Item` set target_warehouse='' where docstatus=0")
-
-def repost_so():
- so_list = get_affected_sales_order()
-
- frappe.db.sql("update `tabSales Order Item` set target_warehouse=''")
-
- if so_list:
- print("-"*40)
- print("Sales Order reposted")
-
-
-def get_affected_delivery_notes():
- return frappe.db.sql("""select distinct dn.name, dn.docstatus
- from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
- where dn.name=dn_item.parent and dn.docstatus < 2
- and dn_item.target_warehouse is not null and dn_item.target_warehouse != ''
- order by dn.posting_date asc""", as_dict=1)
-
-def get_affected_sales_invoice():
- return frappe.db.sql("""select distinct si.name, si.docstatus
- from `tabSales Invoice` si, `tabSales Invoice Item` si_item
- where si.name=si_item.parent and si.docstatus < 2 and si.update_stock=1
- and si_item.target_warehouse is not null and si_item.target_warehouse != ''
- order by si.posting_date asc""", as_dict=1)
-
-def get_affected_sales_order():
- return frappe.db.sql_list("""select distinct parent from `tabSales Order Item`
- where target_warehouse is not null and target_warehouse != '' and docstatus <2""")
\ No newline at end of file
diff --git a/erpnext/patches/v6_12/set_overdue_tasks.py b/erpnext/patches/v6_12/set_overdue_tasks.py
deleted file mode 100644
index 7dbb8ba8b6..0000000000
--- a/erpnext/patches/v6_12/set_overdue_tasks.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Task")
-
- from erpnext.projects.doctype.task.task import set_tasks_as_overdue
- set_tasks_as_overdue()
diff --git a/erpnext/patches/v6_16/__init__.py b/erpnext/patches/v6_16/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_16/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_16/create_manufacturer_records.py b/erpnext/patches/v6_16/create_manufacturer_records.py
deleted file mode 100644
index 5ae65f0660..0000000000
--- a/erpnext/patches/v6_16/create_manufacturer_records.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cstr
-
-def execute():
- frappe.reload_doc("stock", "doctype", "manufacturer")
- frappe.reload_doctype("Item")
-
- for d in frappe.db.sql("""select distinct manufacturer from tabItem
- where ifnull(manufacturer, '') != '' and disabled=0"""):
- manufacturer_name = cstr(d[0]).strip()
- if manufacturer_name and not frappe.db.exists("Manufacturer", manufacturer_name):
- man = frappe.new_doc("Manufacturer")
- man.short_name = manufacturer_name
- man.full_name = manufacturer_name
- man.save()
diff --git a/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py b/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py
deleted file mode 100644
index 481f13005b..0000000000
--- a/erpnext/patches/v6_16/update_billing_status_in_dn_and_pr.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Delivery Note", "Purchase Receipt"):
- frappe.reload_doctype(dt)
- frappe.reload_doctype(dt + " Item")
-
- # Update billed_amt in DN and PR which are not against any order
- for d in frappe.db.sql("""select name from `tabDelivery Note Item` item
- where (so_detail is null or so_detail = '') and docstatus=1""", as_dict=1):
-
- billed_amt = frappe.db.sql("""select sum(amount) from `tabSales Invoice Item`
- where dn_detail=%s and docstatus=1""", d.name)
- billed_amt = billed_amt and billed_amt[0][0] or 0
- frappe.db.set_value("Delivery Note Item", d.name, "billed_amt", billed_amt, update_modified=False)
-
- frappe.db.commit()
-
- # Update billed_amt in DN and PR which are not against any order
- for d in frappe.db.sql("""select name from `tabPurchase Receipt Item` item
- where (purchase_order_item is null or purchase_order_item = '') and docstatus=1""", as_dict=1):
-
- billed_amt = frappe.db.sql("""select sum(amount) from `tabPurchase Invoice Item`
- where pr_detail=%s and docstatus=1""", d.name)
- billed_amt = billed_amt and billed_amt[0][0] or 0
- frappe.db.set_value("Purchase Receipt Item", d.name, "billed_amt", billed_amt, update_modified=False)
-
- frappe.db.commit()
-
- for dt in ("Delivery Note", "Purchase Receipt"):
- # Update billed amt which are against order or invoice
- # Update billing status for all
- for d in frappe.db.sql("select name from `tab{0}` where docstatus=1".format(dt), as_dict=1):
- doc = frappe.get_doc(dt, d.name)
- doc.update_billing_status(update_modified=False)
- doc.set_status(update=True, update_modified=False)
-
- frappe.db.commit()
diff --git a/erpnext/patches/v6_19/__init__.py b/erpnext/patches/v6_19/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_19/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_19/comment_feed_communication.py b/erpnext/patches/v6_19/comment_feed_communication.py
deleted file mode 100644
index bc41c2d8ff..0000000000
--- a/erpnext/patches/v6_19/comment_feed_communication.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.patches.v6_19.comment_feed_communication import update_timeline_doc_for
-
-def execute():
- for doctype in ("Customer", "Supplier", "Employee", "Project"):
- update_timeline_doc_for(doctype)
diff --git a/erpnext/patches/v6_2/__init__.py b/erpnext/patches/v6_2/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_2/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py b/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py
deleted file mode 100644
index b0cfc3d3bf..0000000000
--- a/erpnext/patches/v6_2/fix_missing_default_taxes_and_lead.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # remove missing lead
- for customer in frappe.db.sql_list("""select name from `tabCustomer`
- where ifnull(lead_name, '')!='' and not exists (select name from `tabLead` where name=`tabCustomer`.lead_name)"""):
- frappe.db.set_value("Customer", customer, "lead_name", None)
-
- # remove missing default taxes
- for customer in frappe.db.sql_list("""select name from `tabCustomer`
- where ifnull(default_taxes_and_charges, '')!='' and not exists (
- select name from `tabSales Taxes and Charges Template` where name=`tabCustomer`.default_taxes_and_charges
- )"""):
- c = frappe.get_doc("Customer", customer)
- c.default_taxes_and_charges = None
- c.save()
-
- for supplier in frappe.db.sql_list("""select name from `tabSupplier`
- where ifnull(default_taxes_and_charges, '')!='' and not exists (
- select name from `tabPurchase Taxes and Charges Template` where name=`tabSupplier`.default_taxes_and_charges
- )"""):
- c = frappe.get_doc("Supplier", supplier)
- c.default_taxes_and_charges = None
- c.save()
diff --git a/erpnext/patches/v6_2/remove_newsletter_duplicates.py b/erpnext/patches/v6_2/remove_newsletter_duplicates.py
deleted file mode 100644
index f9d15475d1..0000000000
--- a/erpnext/patches/v6_2/remove_newsletter_duplicates.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- duplicates = frappe.db.sql("""select email_group, email, count(name)
- from `tabEmail Group Member`
- group by email_group, email
- having count(name) > 1""")
-
- # delete all duplicates except 1
- for email_group, email, count in duplicates:
- frappe.db.sql("""delete from `tabEmail Group Member`
- where email_group=%s and email=%s limit %s""", (email_group, email, count-1))
diff --git a/erpnext/patches/v6_20/__init__.py b/erpnext/patches/v6_20/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_20/set_party_account_currency_in_orders.py b/erpnext/patches/v6_20/set_party_account_currency_in_orders.py
deleted file mode 100644
index ae7ad9592d..0000000000
--- a/erpnext/patches/v6_20/set_party_account_currency_in_orders.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Sales Order", "Purchase Order"):
- frappe.reload_doctype(doctype)
-
- for order in frappe.db.sql("""select name, {0} as party from `tab{1}`
- where advance_paid > 0 and docstatus=1"""
- .format(("customer" if doctype=="Sales Order" else "supplier"), doctype), as_dict=1):
-
- party_account_currency = frappe.db.get_value("Journal Entry Account", {
- "reference_type": doctype,
- "reference_name": order.name,
- "party": order.party,
- "docstatus": 1,
- "is_advance": "Yes"
- }, "account_currency")
-
- frappe.db.set_value(doctype, order.name, "party_account_currency", party_account_currency)
-
\ No newline at end of file
diff --git a/erpnext/patches/v6_20x/__init__.py b/erpnext/patches/v6_20x/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_20x/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_20x/remove_customer_supplier_roles.py b/erpnext/patches/v6_20x/remove_customer_supplier_roles.py
deleted file mode 100644
index a651576887..0000000000
--- a/erpnext/patches/v6_20x/remove_customer_supplier_roles.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("buying", "doctype", "request_for_quotation_supplier")
- frappe.reload_doc("buying", "doctype", "request_for_quotation_item")
- frappe.reload_doc("buying", "doctype", "request_for_quotation")
- frappe.reload_doc("projects", "doctype", "timesheet")
-
- for role in ('Customer', 'Supplier'):
- frappe.db.sql('''delete from `tabHas Role`
- where role=%s and parent in ("Administrator", "Guest")''', role)
-
- if not frappe.db.sql('select name from `tabHas Role` where role=%s', role):
-
- # delete DocPerm
- for doctype in frappe.db.sql('select parent from tabDocPerm where role=%s', role):
- d = frappe.get_doc("DocType", doctype[0])
- d.permissions = [p for p in d.permissions if p.role != role]
- d.save()
-
- # delete Role
- frappe.delete_doc_if_exists('Role', role)
diff --git a/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py b/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py
deleted file mode 100644
index d440c6859e..0000000000
--- a/erpnext/patches/v6_20x/remove_fiscal_year_from_holiday_list.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Holiday List")
-
- default_holiday_list = frappe.db.get_value("Holiday List", {"is_default": 1})
- if default_holiday_list:
- for company in frappe.get_all("Company", fields=["name", "default_holiday_list"]):
- if not company.default_holiday_list:
- frappe.db.set_value("Company", company.name, "default_holiday_list", default_holiday_list)
-
-
- fiscal_years = frappe._dict((fy.name, fy) for fy in frappe.get_all("Fiscal Year", fields=["name", "year_start_date", "year_end_date"]))
-
- for holiday_list in frappe.get_all("Holiday List", fields=["name", "fiscal_year"]):
- fy = fiscal_years[holiday_list.fiscal_year]
- frappe.db.set_value("Holiday List", holiday_list.name, "from_date", fy.year_start_date)
- frappe.db.set_value("Holiday List", holiday_list.name, "to_date", fy.year_end_date)
diff --git a/erpnext/patches/v6_20x/rename_project_name_to_project.py b/erpnext/patches/v6_20x/rename_project_name_to_project.py
deleted file mode 100644
index 49ec9d22bc..0000000000
--- a/erpnext/patches/v6_20x/rename_project_name_to_project.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
-
- doc_list = ["Work Order", "BOM", "Purchase Invoice Item", "Sales Invoice",
- "Purchase Order Item", "Stock Entry", "Delivery Note", "Sales Order",
- "Purchase Receipt Item", "Supplier Quotation Item"]
-
- for doctype in doc_list:
- frappe.reload_doctype(doctype)
- rename_field(doctype, "project_name", "project")
-
\ No newline at end of file
diff --git a/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py b/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py
deleted file mode 100644
index 8369fea317..0000000000
--- a/erpnext/patches/v6_20x/repost_valuation_rate_for_negative_inventory.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-from erpnext.stock.stock_balance import repost
-
-def execute():
- if cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")):
- repost(only_actual=True)
\ No newline at end of file
diff --git a/erpnext/patches/v6_20x/set_compact_print.py b/erpnext/patches/v6_20x/set_compact_print.py
deleted file mode 100644
index 495407f0e0..0000000000
--- a/erpnext/patches/v6_20x/set_compact_print.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.setup.install import create_compact_item_print_custom_field
-
-def execute():
- create_compact_item_print_custom_field()
- frappe.db.set_value("Print Settings", None, "compact_item_print", 1)
diff --git a/erpnext/patches/v6_20x/update_product_bundle_description.py b/erpnext/patches/v6_20x/update_product_bundle_description.py
deleted file mode 100644
index 1fac44b001..0000000000
--- a/erpnext/patches/v6_20x/update_product_bundle_description.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import sanitize_html
-
-def execute():
- for product_bundle in frappe.get_all('Product Bundle'):
- doc = frappe.get_doc('Product Bundle', product_bundle.name)
- for item in doc.items:
- if item.description:
- description = sanitize_html(item.description)
- item.db_set('description', description, update_modified=False)
diff --git a/erpnext/patches/v6_21/__init__.py b/erpnext/patches/v6_21/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_21/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_21/fix_reorder_level.py b/erpnext/patches/v6_21/fix_reorder_level.py
deleted file mode 100644
index 82a35ebab1..0000000000
--- a/erpnext/patches/v6_21/fix_reorder_level.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-from erpnext.stock.doctype.item.item import DuplicateReorderRows
-
-def execute():
- if frappe.db.has_column("Item", "re_order_level"):
- for item in frappe.db.sql("""select name, default_warehouse, re_order_level, re_order_qty
- from tabItem
- where ifnull(re_order_level, 0) != 0
- and ifnull(re_order_qty, 0) != 0""", as_dict=1):
-
- item_doc = frappe.get_doc("Item", item.name)
- item_doc.append("reorder_levels", {
- "warehouse": item.default_warehouse,
- "warehouse_reorder_level": item.re_order_level,
- "warehouse_reorder_qty": item.re_order_qty,
- "material_request_type": "Purchase"
- })
-
- try:
- item_doc.save()
- except DuplicateReorderRows:
- pass
diff --git a/erpnext/patches/v6_21/rename_material_request_fields.py b/erpnext/patches/v6_21/rename_material_request_fields.py
deleted file mode 100644
index 07be27a5d6..0000000000
--- a/erpnext/patches/v6_21/rename_material_request_fields.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'material_request_item')
- rename_field("Material Request Item", "sales_order_no", "sales_order")
-
- frappe.reload_doc('support', 'doctype', 'maintenance_schedule_item')
- rename_field("Maintenance Schedule Item", "prevdoc_docname", "sales_order")
-
\ No newline at end of file
diff --git a/erpnext/patches/v6_23/__init__.py b/erpnext/patches/v6_23/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_23/update_stopped_status_to_closed.py b/erpnext/patches/v6_23/update_stopped_status_to_closed.py
deleted file mode 100644
index 79d1e0ac30..0000000000
--- a/erpnext/patches/v6_23/update_stopped_status_to_closed.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Sales Order", "Purchase Order"):
- frappe.db.sql("update `tab{0}` set status='Closed' where status='Stopped'".format(dt))
\ No newline at end of file
diff --git a/erpnext/patches/v6_24/__init__.py b/erpnext/patches/v6_24/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py b/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py
deleted file mode 100644
index 1dd8083c7c..0000000000
--- a/erpnext/patches/v6_24/map_customer_address_to_shipping_address_on_po.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Purchase Order")
-
- if not frappe.db.has_column("Purchase Order", "shipping_address"):
- return
-
- if not frappe.db.has_column("Purchase Order", "customer_address"):
- return
-
- frappe.db.sql("""update `tabPurchase Order` set shipping_address=customer_address,
- shipping_address_display=customer_address_display""")
-
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v6_24/set_recurring_id.py b/erpnext/patches/v6_24/set_recurring_id.py
deleted file mode 100644
index 527a2fd3d9..0000000000
--- a/erpnext/patches/v6_24/set_recurring_id.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ('Sales Order', 'Purchase Order', 'Sales Invoice',
- 'Purchase Invoice'):
- frappe.reload_doctype(doctype)
- frappe.db.sql('''update `tab{0}` set submit_on_creation=1, notify_by_email=1
- where is_recurring=1'''.format(doctype))
- frappe.db.sql('''update `tab{0}` set notify_by_email=1
- where is_recurring=1'''.format(doctype))
- frappe.db.sql('''update `tab{0}` set recurring_id = name
- where is_recurring=1 and ifnull(recurring_id, '') = "" '''.format(doctype))
diff --git a/erpnext/patches/v6_27/__init__.py b/erpnext/patches/v6_27/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_27/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_27/fix_recurring_order_status.py b/erpnext/patches/v6_27/fix_recurring_order_status.py
deleted file mode 100644
index 5843c9fbe5..0000000000
--- a/erpnext/patches/v6_27/fix_recurring_order_status.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doc in (
- {
- "doctype": "Sales Order",
- "stock_doctype": "Delivery Note",
- "invoice_doctype": "Sales Invoice",
- "stock_doctype_ref_field": "against_sales_order",
- "invoice_ref_field": "sales_order",
- "qty_field": "delivered_qty"
- },
- {
- "doctype": "Purchase Order",
- "stock_doctype": "Purchase Receipt",
- "invoice_doctype": "Purchase Invoice",
- "stock_doctype_ref_field": "prevdoc_docname",
- "invoice_ref_field": "purchase_order",
- "qty_field": "received_qty"
- }):
-
- order_list = frappe.db.sql("""select name from `tab{0}`
- where docstatus=1 and is_recurring=1
- and ifnull(recurring_id, '') != name and creation >= '2016-01-25'"""
- .format(doc["doctype"]), as_dict=1)
-
- for order in order_list:
- frappe.db.sql("""update `tab{0} Item`
- set {1}=0, billed_amt=0 where parent=%s""".format(doc["doctype"],
- doc["qty_field"]), order.name)
-
- # Check against Delivery Note and Purchase Receipt
- stock_doc_list = frappe.db.sql("""select distinct parent from `tab{0} Item`
- where docstatus=1 and ifnull({1}, '')=%s"""
- .format(doc["stock_doctype"], doc["stock_doctype_ref_field"]), order.name)
-
- if stock_doc_list:
- for dn in stock_doc_list:
- frappe.get_doc(doc["stock_doctype"], dn[0]).update_qty(update_modified=False)
-
- # Check against Invoice
- invoice_list = frappe.db.sql("""select distinct parent from `tab{0} Item`
- where docstatus=1 and ifnull({1}, '')=%s"""
- .format(doc["invoice_doctype"], doc["invoice_ref_field"]), order.name)
-
- if invoice_list:
- for dn in invoice_list:
- frappe.get_doc(doc["invoice_doctype"], dn[0]).update_qty(update_modified=False)
-
- frappe.get_doc(doc["doctype"], order.name).set_status(update=True, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v6_3/__init__.py b/erpnext/patches/v6_3/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_3/convert_applicable_territory.py b/erpnext/patches/v6_3/convert_applicable_territory.py
deleted file mode 100644
index 231a483ea2..0000000000
--- a/erpnext/patches/v6_3/convert_applicable_territory.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "price_list_country")
- frappe.reload_doc("accounts", "doctype", "shipping_rule_country")
- frappe.reload_doctype("Price List")
- frappe.reload_doctype("Shipping Rule")
- frappe.reload_doctype("shopping_cart", "doctype", "shopping_cart_settings")
-
- # for price list
- countries = frappe.db.sql_list("select name from tabCountry")
-
- for doctype in ("Price List", "Shipping Rule"):
- for at in frappe.db.sql("""select name, parent, territory from `tabApplicable Territory` where
- parenttype = %s """, doctype, as_dict=True):
- if at.territory in countries:
- parent = frappe.get_doc(doctype, at.parent)
- if not parent.countries:
- parent.append("countries", {"country": at.territory})
- parent.save()
-
-
- frappe.delete_doc("DocType", "Applicable Territory")
diff --git a/erpnext/patches/v6_4/__init__.py b/erpnext/patches/v6_4/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_4/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_4/email_digest_update.py b/erpnext/patches/v6_4/email_digest_update.py
deleted file mode 100644
index 8342b7fce6..0000000000
--- a/erpnext/patches/v6_4/email_digest_update.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Email Digest")
- frappe.db.sql("""update `tabEmail Digest` set expense_year_to_date =
- income_year_to_date""")
-
- if frappe.db.exists("Email Digest", "Scheduler Errors"):
- frappe.delete_doc("Email Digest", "Scheduler Errors")
diff --git a/erpnext/patches/v6_4/fix_duplicate_bins.py b/erpnext/patches/v6_4/fix_duplicate_bins.py
deleted file mode 100644
index 77d05273e8..0000000000
--- a/erpnext/patches/v6_4/fix_duplicate_bins.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import repost_stock
-
-def execute():
- bins = frappe.db.sql("""select item_code, warehouse, count(*) from `tabBin`
- group by item_code, warehouse having count(*) > 1""", as_dict=True)
-
- for d in bins:
- try:
- frappe.db.sql("delete from tabBin where item_code=%s and warehouse=%s", (d.item_code, d.warehouse))
-
- repost_stock(d.item_code, d.warehouse, allow_zero_rate=True, only_actual=False, only_bin=True)
-
- frappe.db.commit()
- except:
- frappe.db.rollback()
\ No newline at end of file
diff --git a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py b/erpnext/patches/v6_4/fix_expense_included_in_valuation.py
deleted file mode 100644
index 7ed15ab010..0000000000
--- a/erpnext/patches/v6_4/fix_expense_included_in_valuation.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.utils import cstr
-
-def execute():
- for company in frappe.db.sql("select name, expenses_included_in_valuation from tabCompany", as_dict=1):
- frozen_date = get_frozen_date(company.name, company.expenses_included_in_valuation)
-
- # Purchase Invoices after frozen date
- # which are not against Receipt, but valuation related tax is there
- pi_list = frappe.db.sql("""
- select distinct pi.name
- from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
- where
- pi.name = pi_item.parent
- and pi.company = %s
- and pi.posting_date > %s
- and pi.docstatus = 1
- and pi.is_opening = 'No'
- and (pi_item.item_tax_amount is not null and pi_item.item_tax_amount > 0)
- and (pi_item.purchase_receipt is null or pi_item.purchase_receipt = '')
- and (pi_item.item_code is not null and pi_item.item_code != '')
- and exists(select name from `tabItem` where name=pi_item.item_code and is_stock_item=1)
- """, (company.name, frozen_date), as_dict=1)
-
- for pi in pi_list:
- # Check whether gle exists for Expenses Included in Valuation account against the PI
- gle_for_expenses_included_in_valuation = frappe.db.sql("""select name from `tabGL Entry`
- where voucher_type='Purchase Invoice' and voucher_no=%s and account=%s""",
- (pi.name, company.expenses_included_in_valuation))
-
- if gle_for_expenses_included_in_valuation:
- print(pi.name)
-
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type='Purchase Invoice' and voucher_no=%s""", pi.name)
-
- purchase_invoice = frappe.get_doc("Purchase Invoice", pi.name)
-
- # some old entries have missing expense accounts
- if purchase_invoice.against_expense_account:
- expense_account = purchase_invoice.against_expense_account.split(",")
- if len(expense_account) == 1:
- expense_account = expense_account[0]
- for item in purchase_invoice.items:
- if not item.expense_account:
- item.db_set("expense_account", expense_account, update_modified=False)
-
- purchase_invoice.make_gl_entries()
-
-def get_frozen_date(company, account):
- # Accounting frozen upto
- accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
-
- # Last adjustment entry to correct Expenses Included in Valuation account balance
- last_adjustment_entry = frappe.db.sql("""select posting_date from `tabGL Entry`
- where account=%s and company=%s and voucher_type = 'Journal Entry'
- order by posting_date desc limit 1""", (account, company))
-
- last_adjustment_date = cstr(last_adjustment_entry[0][0]) if last_adjustment_entry else None
-
- # Last period closing voucher
- last_closing_entry = frappe.db.sql("""select posting_date from `tabGL Entry`
- where company=%s and voucher_type = 'Period Closing Voucher'
- order by posting_date desc limit 1""", company)
-
- last_closing_date = cstr(last_closing_entry[0][0]) if last_closing_entry else None
-
- frozen_date = max([accounts_frozen_upto, last_adjustment_date, last_closing_date])
-
- return frozen_date or '1900-01-01'
diff --git a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py b/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
deleted file mode 100644
index b53412d7eb..0000000000
--- a/erpnext/patches/v6_4/fix_journal_entries_due_to_reconciliation.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Sales Invoice Advance")
- frappe.reload_doctype("Purchase Invoice Advance")
-
- je_rows = frappe.db.sql("""
- select name, parent, reference_type, reference_name, debit, credit
- from `tabJournal Entry Account`
- where docstatus=1 and date(modified) >= '2015-09-17'
- and ((ifnull(debit_in_account_currency, 0)*exchange_rate != ifnull(debit, 0))
- or (ifnull(credit_in_account_currency, 0)*exchange_rate != ifnull(credit, 0)))
- order by parent
- """, as_dict=True)
-
- journal_entries = []
-
- for d in je_rows:
- if d.parent not in journal_entries:
- journal_entries.append(d.parent)
-
- is_advance_entry=None
- if d.reference_type in ("Sales Invoice", "Purchase Invoice") and d.reference_name:
- is_advance_entry = frappe.db.sql("""select name from `tab{0}`
- where reference_name=%s and reference_row=%s
- and ifnull(allocated_amount, 0) > 0 and docstatus=1"""
- .format(d.reference_type + " Advance"), (d.parent, d.name))
-
- if is_advance_entry or not (d.debit or d.credit):
- frappe.db.sql("""
- update `tabJournal Entry Account`
- set debit=debit_in_account_currency*exchange_rate,
- credit=credit_in_account_currency*exchange_rate
- where name=%s""", d.name)
- else:
- frappe.db.sql("""
- update `tabJournal Entry Account`
- set debit_in_account_currency=debit/exchange_rate,
- credit_in_account_currency=credit/exchange_rate
- where name=%s""", d.name)
-
- for d in journal_entries:
- print(d)
- # delete existing gle
- frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
-
- # repost gl entries
- je = frappe.get_doc("Journal Entry", d)
- je.make_gl_entries()
\ No newline at end of file
diff --git a/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py b/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py
deleted file mode 100644
index f27489e7b0..0000000000
--- a/erpnext/patches/v6_4/fix_modified_in_sales_order_and_purchase_order.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Sales Order", "Purchase Order"):
- data = frappe.db.sql("""select parent, modified_by, modified
- from `tab{doctype} Item` where docstatus=1 group by parent""".format(doctype=doctype), as_dict=True)
- for item in data:
- frappe.db.sql("""update `tab{doctype}` set modified_by=%(modified_by)s, modified=%(modified)s
- where name=%(parent)s""".format(doctype=doctype), item)
diff --git a/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py b/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py
deleted file mode 100644
index 50aa9e542e..0000000000
--- a/erpnext/patches/v6_4/fix_sales_order_maintenance_status.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doc in frappe.get_all("Sales Order", filters={"docstatus": 1,
- "order_type": "Maintenance"}):
- doc = frappe.get_doc("Sales Order", doc.name)
- doc.set_status(update=True)
diff --git a/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py b/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py
deleted file mode 100644
index 746a99004a..0000000000
--- a/erpnext/patches/v6_4/fix_status_in_sales_and_purchase_order.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Sales Order", "Purchase Order"):
- for doc in frappe.get_all(doctype, filters={"docstatus": 1}):
- doc = frappe.get_doc(doctype, doc.name)
- doc.set_status(update=True)
diff --git a/erpnext/patches/v6_4/make_image_thumbnail.py b/erpnext/patches/v6_4/make_image_thumbnail.py
deleted file mode 100644
index 2c86e8af86..0000000000
--- a/erpnext/patches/v6_4/make_image_thumbnail.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("File")
- frappe.reload_doctype("Item")
- for item in frappe.get_all("Item", fields=("name", "website_image", "thumbnail")):
- if item.website_image and not item.thumbnail:
- item_doc = frappe.get_doc("Item", item.name)
- try:
- item_doc.make_thumbnail()
- if item_doc.thumbnail:
- item_doc.db_set("thumbnail", item_doc.thumbnail, update_modified=False)
- except Exception:
- print("Unable to make thumbnail for {0}".format(item.website_image.encode("utf-8")))
diff --git a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py b/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
deleted file mode 100644
index 1319b53558..0000000000
--- a/erpnext/patches/v6_4/repost_gle_for_journal_entries_where_reference_name_missing.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe
-
-def execute():
- je_list = frappe.db.sql_list("""select distinct parent from `tabJournal Entry Account` je
- where docstatus=1 and ifnull(reference_name, '') !='' and creation > '2015-03-01'
- and not exists(select name from `tabGL Entry`
- where voucher_type='Journal Entry' and voucher_no=je.parent
- and against_voucher_type=je.reference_type
- and against_voucher=je.reference_name)""")
-
- for d in je_list:
- print(d)
-
- # delete existing gle
- frappe.db.sql("delete from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s", d)
-
- # repost gl entries
- je = frappe.get_doc("Journal Entry", d)
- je.make_gl_entries()
\ No newline at end of file
diff --git a/erpnext/patches/v6_4/round_status_updater_percentages.py b/erpnext/patches/v6_4/round_status_updater_percentages.py
deleted file mode 100644
index 900e906b7b..0000000000
--- a/erpnext/patches/v6_4/round_status_updater_percentages.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype, fieldname in (
- ("Sales Order", "per_billed"),
- ("Sales Order", "per_delivered"),
- ("Delivery Note", "per_installed"),
- ("Purchase Order", "per_billed"),
- ("Purchase Order", "per_received"),
- ("Material Request", "per_ordered"),
- ):
- frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=round(`{fieldname}`, 2)""".format(
- doctype=doctype, fieldname=fieldname))
diff --git a/erpnext/patches/v6_4/set_user_in_contact.py b/erpnext/patches/v6_4/set_user_in_contact.py
deleted file mode 100644
index 7e8a6eecd5..0000000000
--- a/erpnext/patches/v6_4/set_user_in_contact.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Contact")
- frappe.db.sql("""update tabContact, tabUser set tabContact.user = tabUser.name
- where tabContact.email_id = tabUser.email""")
diff --git a/erpnext/patches/v6_5/__init__.py b/erpnext/patches/v6_5/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_5/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_5/show_in_website_for_template_item.py b/erpnext/patches/v6_5/show_in_website_for_template_item.py
deleted file mode 100644
index af6e8304d6..0000000000
--- a/erpnext/patches/v6_5/show_in_website_for_template_item.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import frappe.website.render
-
-def execute():
- for item_code in frappe.db.sql_list("""select distinct variant_of from `tabItem`
- where variant_of is not null and variant_of !='' and show_in_website=1"""):
-
- item = frappe.get_doc("Item", item_code)
- item.db_set("show_in_website", 1, update_modified=False)
-
- item.make_route()
- item.db_set("route", item.route, update_modified=False)
-
- frappe.website.render.clear_cache()
diff --git a/erpnext/patches/v6_6/__init__.py b/erpnext/patches/v6_6/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v6_6/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v6_6/fix_website_image.py b/erpnext/patches/v6_6/fix_website_image.py
deleted file mode 100644
index cc3e2d852c..0000000000
--- a/erpnext/patches/v6_6/fix_website_image.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import print_function, unicode_literals
-import frappe
-from frappe.utils import encode
-
-def execute():
- """Fix the File records created via item.py even if the website_image file didn't exist"""
- for item in frappe.db.sql_list("""select name from `tabItem`
- where website_image is not null and website_image != ''
- and website_image like '/files/%'
- and exists (
- select name from `tabFile`
- where attached_to_doctype='Item'
- and attached_to_name=`tabItem`.name
- and file_url=`tabItem`.website_image
- and (file_name is null or file_name = '')
- )"""):
-
- item = frappe.get_doc("Item", item)
- file = frappe.get_doc("File", {
- "attached_to_doctype": "Item",
- "attached_to_name": item.name,
- "file_url": item.website_image
- })
-
- try:
- file.validate_file()
- except IOError:
- print(encode(item.website_image), "does not exist")
- file.delete()
- item.db_set("website_image", None, update_modified=False)
-
-
diff --git a/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py b/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py
deleted file mode 100644
index 11c582fc49..0000000000
--- a/erpnext/patches/v6_6/remove_fiscal_year_from_leave_allocation.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Leave Allocation")
- if frappe.db.has_column("Leave Allocation", "fiscal_year"):
- for leave_allocation in frappe.db.sql("select name, fiscal_year from `tabLeave Allocation`", as_dict=True):
- dates = frappe.db.get_value("Fiscal Year", leave_allocation["fiscal_year"],
- ["year_start_date", "year_end_date"])
-
- if dates:
- year_start_date, year_end_date = dates
-
- frappe.db.sql("""update `tabLeave Allocation`
- set from_date=%s, to_date=%s where name=%s""",
- (year_start_date, year_end_date, leave_allocation["name"]))
-
diff --git a/erpnext/patches/v6_8/__init__.py b/erpnext/patches/v6_8/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v6_8/make_webform_standard.py b/erpnext/patches/v6_8/make_webform_standard.py
deleted file mode 100644
index 2cc16a286f..0000000000
--- a/erpnext/patches/v6_8/make_webform_standard.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- pass
-
- # done via fixtures
-
- # frappe.reload_doctype("Web Form")
- # frappe.delete_doc("Web Form", "Issues")
- # frappe.delete_doc("Web Form", "Addresses")
-
- # from erpnext.setup.install import add_web_forms
- # add_web_forms()
diff --git a/erpnext/patches/v6_8/move_drop_ship_to_po_items.py b/erpnext/patches/v6_8/move_drop_ship_to_po_items.py
deleted file mode 100644
index 7184deeccc..0000000000
--- a/erpnext/patches/v6_8/move_drop_ship_to_po_items.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Purchase Order")
- frappe.reload_doctype("Purchase Order Item")
-
- if not frappe.db.has_column("Purchase Order", "delivered_by_supplier"):
- return
-
- for po in frappe.get_all("Purchase Order", filters={"delivered_by_supplier": 1}, fields=["name"]):
- purchase_order = frappe.get_doc("Purchase Order", po)
-
- for item in purchase_order.items:
- if item.prevdoc_doctype == "Sales Order":
- delivered_by_supplier = frappe.get_value("Sales Order Item", item.prevdoc_detail_docname,
- "delivered_by_supplier")
-
- if delivered_by_supplier:
- frappe.db.sql("""update `tabPurchase Order Item`
- set delivered_by_supplier=1, billed_amt=amount, received_qty=qty
- where name=%s """, item.name)
-
- update_per_received(purchase_order)
- update_per_billed(purchase_order)
-
-def update_per_received(po):
- frappe.db.sql(""" update `tabPurchase Order`
- set per_received = round((select sum(if(qty > ifnull(received_qty, 0),
- ifnull(received_qty, 0), qty)) / sum(qty) *100
- from `tabPurchase Order Item`
- where parent = %(name)s), 2)
- where name = %(name)s """, {"name": po.name})
-
-def update_per_billed(po):
- frappe.db.sql(""" update `tabPurchase Order`
- set per_billed = round((select sum( if(amount > ifnull(billed_amt, 0),
- ifnull(billed_amt, 0), amount)) / sum(amount) *100
- from `tabPurchase Order Item`
- where parent = %(name)s), 2)
- where name = %(name)s """, {"name": po.name})
-
-
diff --git a/erpnext/patches/v7_0/__init__.py b/erpnext/patches/v7_0/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v7_0/calculate_total_costing_amount.py b/erpnext/patches/v7_0/calculate_total_costing_amount.py
deleted file mode 100644
index 8ed60a2955..0000000000
--- a/erpnext/patches/v7_0/calculate_total_costing_amount.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet')
-
- for data in frappe.get_all('Timesheet', fields=["name, total_costing_amount"],
- filters = [["docstatus", "<", "2"]]):
- if flt(data.total_costing_amount) == 0.0:
- ts = frappe.get_doc('Timesheet', data.name)
- ts.update_cost()
- ts.calculate_total_amounts()
- ts.flags.ignore_validate = True
- ts.flags.ignore_mandatory = True
- ts.flags.ignore_validate_update_after_submit = True
- ts.flags.ignore_links = True
- ts.save()
diff --git a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py b/erpnext/patches/v7_0/convert_timelog_to_timesheet.py
deleted file mode 100644
index 8c60b5b71e..0000000000
--- a/erpnext/patches/v7_0/convert_timelog_to_timesheet.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'task')
- frappe.reload_doc('projects', 'doctype', 'timesheet')
- if not frappe.db.table_exists("Time Log"):
- return
-
- from erpnext.manufacturing.doctype.work_order.work_order \
- import make_timesheet, add_timesheet_detail
-
- for data in frappe.db.sql("select * from `tabTime Log`", as_dict=1):
- if data.task:
- company = frappe.db.get_value("Task", data.task, "company")
- elif data.work_order:
- company = frappe.db.get_value("Work Order", data.work_order, "company")
- else:
- company = frappe.db.get_single_value('Global Defaults', 'default_company')
-
- time_sheet = make_timesheet(data.work_order, company)
- args = get_timelog_data(data)
- add_timesheet_detail(time_sheet, args)
- if data.docstatus == 2:
- time_sheet.docstatus = 0
- else:
- time_sheet.docstatus = data.docstatus
- time_sheet.employee = data.employee
- time_sheet.note = data.note
- time_sheet.company = company
-
- time_sheet.set_status()
- time_sheet.set_dates()
- time_sheet.update_cost()
- time_sheet.calculate_total_amounts()
- time_sheet.flags.ignore_validate = True
- time_sheet.flags.ignore_links = True
- time_sheet.save(ignore_permissions=True)
-
- # To ignore validate_mandatory_fields function
- if data.docstatus == 1:
- time_sheet.db_set("docstatus", 1)
- for d in time_sheet.get("time_logs"):
- d.db_set("docstatus", 1)
- time_sheet.update_work_order(time_sheet.name)
- time_sheet.update_task_and_project()
- if data.docstatus == 2:
- time_sheet.db_set("docstatus", 2)
- for d in time_sheet.get("time_logs"):
- d.db_set("docstatus", 2)
-
-def get_timelog_data(data):
- return {
- 'is_billable': data.billable,
- 'from_time': data.from_time,
- 'hours': data.hours,
- 'to_time': data.to_time,
- 'project': data.project,
- 'task': data.task,
- 'activity_type': data.activity_type,
- 'operation': data.operation,
- 'operation_id': data.operation_id,
- 'workstation': data.workstation,
- 'completed_qty': data.completed_qty,
- 'billing_rate': data.billing_rate,
- 'billing_amount': data.billing_amount,
- 'costing_rate': data.costing_rate,
- 'costing_amount': data.costing_amount
- }
diff --git a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py b/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py
deleted file mode 100644
index e78f163e07..0000000000
--- a/erpnext/patches/v7_0/convert_timelogbatch_to_timesheet.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-
-def execute():
- if not frappe.db.exists("DocType", "Time Log Batch"):
- return
-
- from erpnext.manufacturing.doctype.work_order.work_order import add_timesheet_detail
-
- for tlb in frappe.get_all('Time Log Batch', fields=["*"],
- filters = [["docstatus", "<", "2"]]):
- time_sheet = frappe.new_doc('Timesheet')
- time_sheet.employee= ""
- time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company')
- time_sheet.sales_invoice = tlb.sales_invoice
-
- for data in frappe.get_all('Time Log Batch Detail', fields=["*"],
- filters = {'parent': tlb.name}):
- args = get_timesheet_data(data)
- add_timesheet_detail(time_sheet, args)
-
- time_sheet.docstatus = tlb.docstatus
- time_sheet.flags.ignore_links = True
- time_sheet.save(ignore_permissions=True)
-
-def get_timesheet_data(data):
- from erpnext.patches.v7_0.convert_timelog_to_timesheet import get_timelog_data
-
- time_log = frappe.get_all('Time Log', fields=["*"], filters = {'name': data.time_log})
- if time_log:
- return get_timelog_data(time_log[0])
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/create_budget_record.py b/erpnext/patches/v7_0/create_budget_record.py
deleted file mode 100644
index fd8bec9f32..0000000000
--- a/erpnext/patches/v7_0/create_budget_record.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.accounts.doctype.budget.budget import DuplicateBudgetError
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "budget")
- frappe.reload_doc("accounts", "doctype", "budget_account")
-
- existing_budgets = frappe.db.sql("""
- select
- cc.name, cc.company, cc.distribution_id,
- budget.account, budget.budget_allocated, budget.fiscal_year
- from
- `tabCost Center` cc, `tabBudget Detail` budget
- where
- cc.name=budget.parent
- """, as_dict=1)
-
- actions = {}
- for d in frappe.db.sql("select name, yearly_bgt_flag, monthly_bgt_flag from tabCompany", as_dict=1):
- actions.setdefault(d.name, d)
-
- budget_records = []
- for d in existing_budgets:
- budget = frappe.db.get_value("Budget",
- {"cost_center": d.name, "fiscal_year": d.fiscal_year, "company": d.company})
-
- if not budget:
- budget = frappe.new_doc("Budget")
- budget.cost_center = d.name
- budget.fiscal_year = d.fiscal_year
- budget.monthly_distribution = d.distribution_id
- budget.company = d.company
- if actions[d.company]["yearly_bgt_flag"]:
- budget.action_if_annual_budget_exceeded = actions[d.company]["yearly_bgt_flag"]
- if actions[d.company]["monthly_bgt_flag"]:
- budget.action_if_accumulated_monthly_budget_exceeded = actions[d.company]["monthly_bgt_flag"]
- else:
- budget = frappe.get_doc("Budget", budget)
-
- budget.append("accounts", {
- "account": d.account,
- "budget_amount": d.budget_allocated
- })
-
- try:
- budget.insert()
- budget_records.append(budget)
- except DuplicateBudgetError:
- pass
-
- for budget in budget_records:
- budget.submit()
-
- if frappe.db.get_value("DocType", "Budget Detail"):
- frappe.delete_doc("DocType", "Budget Detail")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/create_warehouse_nestedset.py b/erpnext/patches/v7_0/create_warehouse_nestedset.py
deleted file mode 100644
index 1c9fc32142..0000000000
--- a/erpnext/patches/v7_0/create_warehouse_nestedset.py
+++ /dev/null
@@ -1,128 +0,0 @@
-
-from __future__ import unicode_literals
-import frappe, erpnext
-from frappe import _
-from frappe.utils import cint
-from frappe.utils.nestedset import rebuild_tree
-
-def execute():
- """
- Patch Reference:
- 1. check whether warehouse is associated to company or not
- 2. if warehouse is associated with company
- a. create warehouse group for company
- b. set warehouse group as parent to other warehouses and set is_group as 0
- 3. if warehouses is not associated with company
- a. get distinct companies from stock ledger entries
- b. if sle have only company,
- i. set default company to all warehouse
- ii. repeat 2.a and 2.b
- c. if have multiple companies,
- i. create group warehouse without company
- ii. repeat 2.b
- """
-
- frappe.reload_doc("stock", "doctype", "warehouse")
-
- if check_is_warehouse_associated_with_company():
- for company in frappe.get_all("Company", fields=["name", "abbr"]):
- make_warehouse_nestedset(company)
- else:
- sle_against_companies = frappe.db.sql_list("""select distinct company from `tabStock Ledger Entry`""")
-
- if len(sle_against_companies) == 1:
- company = frappe.get_cached_value('Company', sle_against_companies[0],
- fieldname=["name", "abbr"], as_dict=1)
- set_company_to_warehouse(company.name)
- make_warehouse_nestedset(company)
-
- elif len(sle_against_companies) > 1:
- make_warehouse_nestedset()
-
-def check_is_warehouse_associated_with_company():
- warehouse_associcated_with_company = False
-
- for warehouse in frappe.get_all("Warehouse", fields=["name", "company"]):
- if warehouse.company:
- warehouse_associcated_with_company = True
-
- return warehouse_associcated_with_company
-
-def make_warehouse_nestedset(company=None):
- validate_parent_account_for_warehouse(company)
- stock_account_group = get_stock_account_group(company.name)
- enable_perpetual_inventory = cint(erpnext.is_perpetual_inventory_enabled(company.name)) or 0
- if not stock_account_group and enable_perpetual_inventory:
- return
-
- if company:
- warehouse_group = "{0} - {1}".format(_("All Warehouses"), company.abbr)
- ignore_mandatory = False
- else:
- warehouse_group = _("All Warehouses")
- ignore_mandatory = True
-
- if not frappe.db.get_value("Warehouse", warehouse_group):
- create_default_warehouse_group(company, stock_account_group, ignore_mandatory)
-
- set_parent_to_warehouse(warehouse_group, company)
- if enable_perpetual_inventory:
- set_parent_to_warehouse_account(company)
-
-def validate_parent_account_for_warehouse(company=None):
- if not company:
- return
-
- if cint(erpnext.is_perpetual_inventory_enabled(company.name)):
- parent_account = frappe.db.sql("""select name from tabAccount
- where account_type='Stock' and company=%s and is_group=1
- and (warehouse is null or warehouse = '')""", company.name)
-
- if not parent_account:
- current_parent_accounts_for_warehouse = frappe.db.sql("""select parent_account from tabAccount
- where account_type='Warehouse' and (warehouse is not null or warehouse != '') """)
-
- if current_parent_accounts_for_warehouse:
- frappe.db.set_value("Account", current_parent_accounts_for_warehouse[0][0], "account_type", "Stock")
-
-def create_default_warehouse_group(company=None, stock_account_group=None, ignore_mandatory=False):
- wh = frappe.get_doc({
- "doctype": "Warehouse",
- "warehouse_name": _("All Warehouses"),
- "is_group": 1,
- "company": company.name if company else "",
- "parent_warehouse": ""
- })
-
- if ignore_mandatory:
- wh.flags.ignore_mandatory = ignore_mandatory
-
- wh.insert(ignore_permissions=True)
-
-def set_parent_to_warehouse(warehouse_group, company=None):
- frappe.db.sql(""" update tabWarehouse set parent_warehouse = %s, is_group = 0
- where (is_group = 0 or is_group is null or is_group = '') and ifnull(company, '') = %s
- """,(warehouse_group, company.name if company else ""))
-
- rebuild_tree("Warehouse", "parent_warehouse")
-
-def set_parent_to_warehouse_account(company):
- frappe.db.sql(""" update tabAccount set parent_account = %s
- where is_group = 0 and account_type = "Warehouse"
- and (warehouse is not null or warehouse != '') and company = %s
- """,("{0} - {1}".format(_("All Warehouses"), company.abbr), company.name))
-
- rebuild_tree("Account", "parent_account")
-
-def set_company_to_warehouse(company):
- frappe.db.sql("update tabWahouse set company=%s", company)
-
-def get_stock_account_group(company):
- stock_account_group = frappe.db.get_all('Account', filters = {'company': company, 'is_group': 1,
- 'account_type': 'Stock', 'root_type': 'Asset'}, limit=1)
-
- if not stock_account_group:
- stock_account_group = frappe.db.get_all('Account', filters = {'company': company, 'is_group': 1,
- 'parent_account': '', 'root_type': 'Asset'}, limit=1)
-
- return stock_account_group[0].name if stock_account_group else None
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/fix_duplicate_icons.py b/erpnext/patches/v7_0/fix_duplicate_icons.py
deleted file mode 100644
index 9f442029b5..0000000000
--- a/erpnext/patches/v7_0/fix_duplicate_icons.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from frappe.desk.doctype.desktop_icon.desktop_icon import (sync_desktop_icons,
- get_desktop_icons, set_hidden)
-from erpnext.patches.v7_0.migrate_schools_to_erpnext import reload_doctypes_for_schools_icons
-
-def execute():
- '''hide new style icons if old ones are set'''
- frappe.reload_doc('desk', 'doctype', 'desktop_icon')
-
- reload_doctypes_for_schools_icons()
-
- sync_desktop_icons()
-
- for user in frappe.get_all('User', filters={'user_type': 'System User'}):
- desktop_icons = get_desktop_icons(user.name)
- icons_dict = {}
- for d in desktop_icons:
- if not d.hidden:
- icons_dict[d.module_name] = d
-
- for key in (('Selling', 'Customer'), ('Stock', 'Item'), ('Buying', 'Supplier'),
- ('HR', 'Employee'), ('CRM', 'Lead'), ('Support', 'Issue'), ('Projects', 'Project')):
- if key[0] in icons_dict and key[1] in icons_dict:
- set_hidden(key[1], user.name, 1)
-
diff --git a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py b/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
deleted file mode 100644
index 2bc09714d8..0000000000
--- a/erpnext/patches/v7_0/fix_nonwarehouse_ledger_gl_entries_for_transactions.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import print_function, unicode_literals
-import frappe, erpnext
-
-def execute():
- frappe.reload_doctype("Account")
-
- warehouses = frappe.db.sql("""select name, company from tabAccount
- where account_type = 'Stock' and is_group = 0
- and (warehouse is null or warehouse = '')""", as_dict=1)
- warehouses = [d.name for d in warehouses if erpnext.is_perpetual_inventory_enabled(d.company)]
-
- if len(warehouses) > 0:
- warehouses = set_warehouse_for_stock_account(warehouses)
- if not warehouses:
- return
-
- stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
- from `tabStock Ledger Entry` sle
- where sle.warehouse in (%s) and creation > '2016-05-01'
- and not exists(select name from `tabGL Entry`
- where account=sle.warehouse and voucher_type=sle.voucher_type and voucher_no=sle.voucher_no)
- order by sle.posting_date""" %
- ', '.join(['%s']*len(warehouses)), tuple(warehouses))
-
- rejected = []
- for voucher_type, voucher_no in stock_vouchers:
- try:
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
-
- voucher = frappe.get_doc(voucher_type, voucher_no)
- voucher.make_gl_entries()
- frappe.db.commit()
- except Exception as e:
- print(frappe.get_traceback())
- rejected.append([voucher_type, voucher_no])
- frappe.db.rollback()
-
- print(rejected)
-
-def set_warehouse_for_stock_account(warehouse_account):
- for account in warehouse_account:
- if frappe.db.exists('Warehouse', account):
- frappe.db.set_value("Account", account, "warehouse", account)
- else:
- warehouse_account.remove(account)
-
- return warehouse_account
diff --git a/erpnext/patches/v7_0/make_guardian.py b/erpnext/patches/v7_0/make_guardian.py
deleted file mode 100644
index 519969b38d..0000000000
--- a/erpnext/patches/v7_0/make_guardian.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Student"):
- student_table_cols = frappe.db.get_table_columns("Student")
- if "father_name" in student_table_cols:
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "student")
- # frappe.reload_doc("schools", "doctype", "guardian")
- # frappe.reload_doc("schools", "doctype", "guardian_interest")
-
- frappe.reload_doc("education", "doctype", "student")
- frappe.reload_doc("education", "doctype", "guardian")
- frappe.reload_doc("education", "doctype", "guardian_interest")
- frappe.reload_doc("hr", "doctype", "interest")
-
- fields = ["name", "father_name", "mother_name"]
-
- if "father_email_id" in student_table_cols:
- fields += ["father_email_id", "mother_email_id"]
-
- students = frappe.get_all("Student", fields)
- for stud in students:
- if stud.father_name:
- make_guardian(stud.father_name, stud.name, stud.father_email_id)
- if stud.mother_name:
- make_guardian(stud.mother_name, stud.name, stud.mother_email_id)
-
-def make_guardian(name, student, email=None):
- frappe.get_doc({
- 'doctype': 'Guardian',
- 'guardian_name': name,
- 'email': email,
- 'student': student
- }).insert()
diff --git a/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py b/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py
deleted file mode 100644
index ba82e869fa..0000000000
--- a/erpnext/patches/v7_0/make_is_group_fieldtype_as_check.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ["Sales Person", "Customer Group", "Item Group", "Territory"]:
-
- # convert to 1 or 0
- frappe.db.sql("update `tab{doctype}` set is_group = if(is_group='Yes',1,0) "
- .format(doctype=doctype))
-
- frappe.db.commit()
-
- # alter fields to int
-
- frappe.db.sql("alter table `tab{doctype}` change is_group is_group int(1) default '0'"
- .format(doctype=doctype))
-
- frappe.reload_doctype(doctype)
diff --git a/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py b/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py
deleted file mode 100644
index 02808a742f..0000000000
--- a/erpnext/patches/v7_0/merge_account_type_stock_and_warehouse_to_stock.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "account")
-
- frappe.db.sql(""" update tabAccount set account_type = "Stock"
- where account_type = "Warehouse" """)
-
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py b/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py
deleted file mode 100644
index e0e3f7075a..0000000000
--- a/erpnext/patches/v7_0/migrate_mode_of_payments_v6_to_v7.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_payment')
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment')
-
- count = 0
- for data in frappe.db.sql("""select name, mode_of_payment, cash_bank_account, paid_amount, company
- from `tabSales Invoice` si
- where si.is_pos = 1 and si.docstatus < 2
- and si.cash_bank_account is not null and si.cash_bank_account != ''
- and not exists(select name from `tabSales Invoice Payment` where parent=si.name)""", as_dict=1):
-
- if not data.mode_of_payment and not frappe.db.exists("Mode of Payment", "Cash"):
- mop = frappe.new_doc("Mode of Payment")
- mop.mode_of_payment = "Cash"
- mop.type = "Cash"
- mop.save()
-
- si_doc = frappe.get_doc('Sales Invoice', data.name)
- row = si_doc.append('payments', {
- 'mode_of_payment': data.mode_of_payment or 'Cash',
- 'account': data.cash_bank_account,
- 'type': frappe.db.get_value('Mode of Payment', data.mode_of_payment, 'type') or 'Cash',
- 'amount': data.paid_amount
- })
- row.db_update()
-
- si_doc.set_paid_amount()
- si_doc.db_set("paid_amount", si_doc.paid_amount, update_modified = False)
- si_doc.db_set("base_paid_amount", si_doc.base_paid_amount, update_modified = False)
-
- count +=1
-
- if count % 200 == 0:
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py b/erpnext/patches/v7_0/migrate_schools_to_erpnext.py
deleted file mode 100644
index b72bc137b6..0000000000
--- a/erpnext/patches/v7_0/migrate_schools_to_erpnext.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import unicode_literals
-import frappe, os
-from frappe.installer import remove_from_installed_apps
-
-def execute():
- reload_doctypes_for_schools_icons()
-
- frappe.reload_doc('website', 'doctype', 'portal_settings')
- frappe.reload_doc('website', 'doctype', 'portal_menu_item')
- frappe.reload_doc('buying', 'doctype', 'request_for_quotation')
-
- if 'schools' in frappe.get_installed_apps():
- if not frappe.db.exists('Module Def', 'Schools') and frappe.db.exists('Module Def', 'Academics'):
-
- # 'Schools' module changed to the 'Education'
- # frappe.rename_doc("Module Def", "Academics", "Schools")
-
- frappe.rename_doc("Module Def", "Academics", "Education")
-
- remove_from_installed_apps("schools")
-
-def reload_doctypes_for_schools_icons():
- # 'Schools' module changed to the 'Education'
- # base_path = frappe.get_app_path('erpnext', 'schools', 'doctype')
-
- base_path = frappe.get_app_path('erpnext', 'education', 'doctype')
- for doctype in os.listdir(base_path):
- if os.path.exists(os.path.join(base_path, doctype, doctype + '.json')) \
- and doctype not in ("fee_component", "assessment", "assessment_result"):
- frappe.reload_doc('education', 'doctype', doctype)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py b/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py
deleted file mode 100644
index 998c4b674b..0000000000
--- a/erpnext/patches/v7_0/move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_payment')
- for time_sheet in frappe.db.sql(""" select sales_invoice, name, total_billable_amount from `tabTimesheet`
- where sales_invoice is not null and docstatus < 2""", as_dict=True):
- if not frappe.db.exists('Sales Invoice', time_sheet.sales_invoice):
- continue
- si_doc = frappe.get_doc('Sales Invoice', time_sheet.sales_invoice)
- ts = si_doc.append('timesheets',{})
- ts.time_sheet = time_sheet.name
- ts.billing_amount = time_sheet.total_billable_amount
- ts.db_update()
- si_doc.calculate_billing_amount_from_timesheet()
- si_doc.db_set("total_billing_amount", si_doc.total_billing_amount, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py b/erpnext/patches/v7_0/po_status_issue_for_pr_return.py
deleted file mode 100644
index 910814fd22..0000000000
--- a/erpnext/patches/v7_0/po_status_issue_for_pr_return.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- parent_list = []
- count = 0
-
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt_item')
-
- for data in frappe.db.sql("""
- select
- `tabPurchase Receipt Item`.purchase_order, `tabPurchase Receipt Item`.name,
- `tabPurchase Receipt Item`.item_code, `tabPurchase Receipt Item`.idx,
- `tabPurchase Receipt Item`.parent
- from
- `tabPurchase Receipt Item`, `tabPurchase Receipt`
- where
- `tabPurchase Receipt Item`.parent = `tabPurchase Receipt`.name and
- `tabPurchase Receipt Item`.purchase_order_item is null and
- `tabPurchase Receipt Item`.purchase_order is not null and
- `tabPurchase Receipt`.is_return = 1""", as_dict=1):
- name = frappe.db.get_value('Purchase Order Item',
- {'item_code': data.item_code, 'parent': data.purchase_order, 'idx': data.idx}, 'name')
-
- if name:
- frappe.db.set_value('Purchase Receipt Item', data.name, 'purchase_order_item', name, update_modified=False)
- parent_list.append(data.parent)
-
- count +=1
- if count % 200 == 0:
- frappe.db.commit()
-
- if len(parent_list) > 0:
- for parent in set(parent_list):
- doc = frappe.get_doc('Purchase Receipt', parent)
- doc.update_qty(update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/re_route.py b/erpnext/patches/v7_0/re_route.py
deleted file mode 100644
index 3cec6f39b2..0000000000
--- a/erpnext/patches/v7_0/re_route.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-from frappe.patches.v7_0.re_route import update_routes
-
-def execute():
- update_routes(['Item', 'Item Group', 'Sales Partner', 'Job Opening'])
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py b/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py
deleted file mode 100644
index 8c87c4e3d3..0000000000
--- a/erpnext/patches/v7_0/remove_administrator_role_in_doctypes.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""delete from tabDocPerm where role="Administrator" and parent in
- ("Payment Gateway", "Payment Gateway Account", "Payment Request", "Academic Term", "Academic Year", "Course",
- "Course Schedule", "Examination", "Fee Category", "Fee Structure", "Fees", "Instructor", "Program", "Program Enrollment Tool",
- "Room", "Scheduling Tool", "Student", "Student Applicant", "Student Attendance", "Student Group", "Student Group Creation Tool")
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/remove_doctypes_and_reports.py b/erpnext/patches/v7_0/remove_doctypes_and_reports.py
deleted file mode 100644
index 2356e2f6ee..0000000000
--- a/erpnext/patches/v7_0/remove_doctypes_and_reports.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Log"):
- frappe.db.sql("""delete from `tabDocType`
- where name in('Time Log Batch', 'Time Log Batch Detail', 'Time Log')""")
-
- frappe.db.sql("""delete from `tabDocField` where parent in ('Time Log', 'Time Log Batch')""")
- frappe.db.sql("""update `tabClient Script` set dt = 'Timesheet' where dt = 'Time Log'""")
-
- for data in frappe.db.sql(""" select label, fieldname from `tabCustom Field` where dt = 'Time Log'""", as_dict=1):
- custom_field = frappe.get_doc({
- 'doctype': 'Custom Field',
- 'label': data.label,
- 'dt': 'Timesheet Detail',
- 'fieldname': data.fieldname,
- 'fieldtype': data.fieldtype or "Data"
- }).insert(ignore_permissions=True)
-
- frappe.db.sql("""delete from `tabCustom Field` where dt = 'Time Log'""")
- frappe.reload_doc('projects', 'doctype', 'timesheet')
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
-
- report = "Daily Time Log Summary"
- if frappe.db.exists("Report", report):
- frappe.delete_doc('Report', report)
diff --git a/erpnext/patches/v7_0/remove_features_setup.py b/erpnext/patches/v7_0/remove_features_setup.py
deleted file mode 100644
index 49393cc248..0000000000
--- a/erpnext/patches/v7_0/remove_features_setup.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.setup.install import create_compact_item_print_custom_field
-from frappe.utils import cint
-
-def execute():
- frappe.reload_doctype('Stock Settings')
- stock_settings = frappe.get_doc('Stock Settings', 'Stock Settings')
- stock_settings.show_barcode_field = cint(frappe.db.get_value("Features Setup", None, "fs_item_barcode"))
- if not frappe.db.exists("UOM", stock_settings.stock_uom):
- stock_settings.stock_uom = None
- stock_settings.save()
-
- create_compact_item_print_custom_field()
-
- compact_item_print = frappe.db.get_value("Features Setup", None, "compact_item_print")
- frappe.db.set_value("Print Settings", None, "compact_item_print", compact_item_print)
-
- # remove defaults
- frappe.db.sql("""delete from tabDefaultValue where defkey in ('fs_item_serial_nos',
- 'fs_item_batch_nos', 'fs_brands', 'fs_item_barcode',
- 'fs_item_advanced', 'fs_packing_details', 'fs_item_group_in_details',
- 'fs_exports', 'fs_imports', 'fs_discounts', 'fs_purchase_discounts',
- 'fs_after_sales_installations', 'fs_projects', 'fs_sales_extras',
- 'fs_recurring_invoice', 'fs_pos', 'fs_manufacturing', 'fs_quality',
- 'fs_page_break', 'fs_more_info', 'fs_pos_view', 'compact_item_print')""")
-
- frappe.delete_doc('DocType', 'Features Setup')
diff --git a/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py b/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py
deleted file mode 100644
index 05a2c49461..0000000000
--- a/erpnext/patches/v7_0/remove_old_earning_deduction_doctypes.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Salary Component"):
- for dt in ("Salary Structure Earning", "Salary Structure Deduction", "Salary Slip Earning",
- "Salary Slip Deduction", "Earning Type", "Deduction Type"):
- frappe.delete_doc("DocType", dt)
-
-
- for d in frappe.db.sql("""select name from `tabCustom Field`
- where dt in ('Salary Detail', 'Salary Component')"""):
- frappe.get_doc("Custom Field", d[0]).save()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_advance_table_fields.py b/erpnext/patches/v7_0/rename_advance_table_fields.py
deleted file mode 100644
index 34d81343e2..0000000000
--- a/erpnext/patches/v7_0/rename_advance_table_fields.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- for dt in ("Sales Invoice Advance", "Purchase Invoice Advance"):
- frappe.reload_doctype(dt)
-
- frappe.db.sql("update `tab{0}` set reference_type = 'Journal Entry'".format(dt))
-
- if frappe.get_meta(dt).has_field('journal_entry'):
- rename_field(dt, "journal_entry", "reference_name")
-
- if frappe.get_meta(dt).has_field('jv_detail_no'):
- rename_field(dt, "jv_detail_no", "reference_row")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_examination_to_assessment.py b/erpnext/patches/v7_0/rename_examination_to_assessment.py
deleted file mode 100644
index dc248de4fa..0000000000
--- a/erpnext/patches/v7_0/rename_examination_to_assessment.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- if frappe.db.exists("DocType", "Examination"):
- frappe.rename_doc("DocType", "Examination", "Assessment")
- frappe.rename_doc("DocType", "Examination Result", "Assessment Result")
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "assessment")
- # frappe.reload_doc("schools", "doctype", "assessment_result")
-
- frappe.reload_doc("education", "doctype", "assessment")
- frappe.reload_doc("education", "doctype", "assessment_result")
-
- rename_field("Assessment", "exam_name", "assessment_name")
- rename_field("Assessment", "exam_code", "assessment_code")
-
- frappe.db.sql("delete from `tabPortal Menu Item` where route = '/examination'")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py b/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py
deleted file mode 100644
index 5cb6a3b7c4..0000000000
--- a/erpnext/patches/v7_0/rename_fee_amount_to_fee_component.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- if frappe.db.exists("DocType", "Fee Amount"):
- frappe.rename_doc("DocType", "Fee Amount", "Fee Component")
- for dt in ("Fees", "Fee Structure"):
- frappe.reload_doctype(dt)
- rename_field(dt, "amount", "components")
-
-
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/rename_prevdoc_fields.py b/erpnext/patches/v7_0/rename_prevdoc_fields.py
deleted file mode 100644
index ded4ad4aae..0000000000
--- a/erpnext/patches/v7_0/rename_prevdoc_fields.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import json
-from frappe.model.utils.rename_field import update_reports, rename_field, update_property_setters
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
-
-def execute():
- frappe.reload_doctype('Purchase Order Item')
- frappe.reload_doctype('Purchase Receipt Item')
- update_po_fields()
- update_prop_setters_reports_print_format_for_po()
- set_sales_order_field()
- rename_pr_fields()
-
-def update_po_fields():
- for data in frappe.db.sql(""" select prevdoc_docname, prevdoc_detail_docname, name, prevdoc_doctype
- from `tabPurchase Order Item` where prevdoc_doctype is not null""", as_dict=True):
- if data.prevdoc_doctype == 'Material Request':
- frappe.db.set_value("Purchase Order Item", data.name, "material_request", data.prevdoc_docname, update_modified=False)
- frappe.db.set_value("Purchase Order Item", data.name, "material_request_item", data.prevdoc_detail_docname, update_modified=False)
- elif data.prevdoc_doctype == 'Sales Order':
- frappe.db.set_value("Purchase Order Item", data.name, "sales_order", data.prevdoc_docname, update_modified=False)
- frappe.db.set_value("Purchase Order Item", data.name, "sales_order_item", data.prevdoc_detail_docname, update_modified=False)
-
-def get_columns():
- return {
- 'prevdoc_docname': 'material_request',
- 'prevdoc_detail_docname': 'material_request_item'
- }
-
-def update_prop_setters_reports_print_format_for_po():
- for key, val in get_columns().items():
- update_property_setters('Purchase Order Item', key, val)
- update_reports('Purchase Order Item', key, val)
- update_print_format_for_po(key, val, 'Purchase Order')
-
-def update_print_format_for_po(old_fieldname, new_fieldname, doc_type):
- column_mapper = get_columns()
-
- for data in frappe.db.sql(""" select name, format_data from `tabPrint Format` where
- format_data like %(old_fieldname)s and doc_type = %(doc_type)s""",
- {'old_fieldname': '%%%s%%'%(old_fieldname), 'doc_type': doc_type}, as_dict=True):
-
- update_print_format_fields(old_fieldname, new_fieldname, data)
-
-def update_print_format_fields(old_fieldname, new_fieldname, args):
- report_dict = json.loads(args.format_data)
- update = False
-
- for col in report_dict:
- if col.get('fieldname') and col.get('fieldname') == old_fieldname:
- col['fieldname'] = new_fieldname
- update = True
-
- if col.get('visible_columns'):
- for key in col.get('visible_columns'):
- if key.get('fieldname') == old_fieldname:
- key['fieldname'] = new_fieldname
- update = True
-
- if update:
- val = json.dumps(report_dict)
- frappe.db.sql("""update `tabPrint Format` set `format_data`=%s where name=%s""", (val, args.name))
-
-def set_sales_order_field():
- for data in frappe.db.sql("""select doc_type, field_name, property, value, property_type
- from `tabProperty Setter` where doc_type = 'Purchase Order Item'
- and field_name in('material_request', 'material_request_item')""", as_dict=True):
- if data.field_name == 'material_request':
- make_property_setter(data.doc_type, 'sales_order', data.property, data.value, data.property_type)
- else:
- make_property_setter(data.doc_type, 'sales_order_item', data.property, data.value, data.property_type)
-
-def rename_pr_fields():
- rename_field("Purchase Receipt Item", "prevdoc_docname", "purchase_order")
- rename_field("Purchase Receipt Item", "prevdoc_detail_docname", "purchase_order_item")
diff --git a/erpnext/patches/v7_0/rename_salary_components.py b/erpnext/patches/v7_0/rename_salary_components.py
deleted file mode 100644
index 1693f3bdf1..0000000000
--- a/erpnext/patches/v7_0/rename_salary_components.py
+++ /dev/null
@@ -1,149 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import update_property_setters
-
-def execute():
- if not frappe.db.exists("DocType", "Salary Structure Earning"):
- return
-
- frappe.reload_doc("Payroll", "doctype", "salary_detail")
- frappe.reload_doc("Payroll", "doctype", "salary_component")
-
- standard_cols = ["name", "creation", "modified", "owner", "modified_by", "parent", "parenttype", "parentfield", "idx"]
-
- dt_cols = {
- "Salary Structure Deduction": ["d_type", "d_modified_amt", "depend_on_lwp"],
- "Salary Structure Earning": ["e_type", "modified_value", "depend_on_lwp"],
- "Salary Slip Earning": ["e_type", "e_modified_amount", "e_depends_on_lwp", "e_amount"],
- "Salary Slip Deduction": ["d_type", "d_modified_amount", "d_depends_on_lwp", "d_amount"],
- }
-
- earning_type_exists = True if "earning_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
- e_type_exists = True if "e_type" in frappe.db.get_table_columns("Salary Slip Earning") else False
-
-
- if e_type_exists and earning_type_exists:
- frappe.db.sql("""update `tabSalary Slip Earning`
- set e_type = earning_type, e_modified_amount = earning_amount
- where e_type is null and earning_type is not null""")
-
- frappe.db.sql("""update `tabSalary Structure Earning` set e_type = earning_type
- where e_type is null and earning_type is not null""")
-
- frappe.db.sql("""update `tabSalary Slip Deduction` set
- d_type = deduction_type, d_modified_amount = deduction_amount
- where d_type is null and deduction_type is not null""")
-
- frappe.db.sql("""update `tabSalary Structure Deduction` set d_type = deduction_type
- where d_type is null and deduction_type is not null""")
-
- if earning_type_exists and not e_type_exists:
- for val in dt_cols.values():
- if val[0] == "e_type":
- val[0] = "earning_type"
-
- if val[0] == "d_type":
- val[0] = "deduction_type"
-
- if val[1] == "e_modified_amount":
- val[1] ="earning_amount"
-
- if val[1] == "d_modified_amount":
- val[1] ="deduction_amount"
-
-
-
- target_cols = standard_cols + ["salary_component", "amount", "depends_on_payment_days", "default_amount"]
- target_cols = "`" + "`, `".join(target_cols) + "`"
-
- for doctype, cols in dt_cols.items():
- source_cols = "`" + "`, `".join(standard_cols + cols) + "`"
- if len(cols) == 3:
- source_cols += ", 0"
-
-
- frappe.db.sql("""INSERT INTO `tabSalary Detail` ({0}) SELECT {1} FROM `tab{2}`"""
- .format(target_cols, source_cols, doctype))
-
-
- dt_cols_de = {
- "Deduction Type": ["deduction_name", "description"],
- "Earning Type": ["earning_name", "description"],
- }
-
- standard_cols_de = standard_cols
-
-
- target_cols = standard_cols_de + ["salary_component", "description"]
- target_cols = "`" + "`, `".join(target_cols) + "`"
-
- for doctype, cols in dt_cols_de.items():
- source_cols = "`" + "`, `".join(standard_cols_de + cols) + "`"
- try:
- frappe.db.sql("""INSERT INTO `tabSalary Component` ({0}) SELECT {1} FROM `tab{2}`"""
- .format(target_cols, source_cols, doctype))
- except Exception as e:
- if e.args[0]==1062:
- pass
-
- update_customizations()
-
- for doctype in ["Salary Structure Deduction", "Salary Structure Earning", "Salary Slip Earning",
- "Salary Slip Deduction", "Deduction Type", "Earning Type"] :
- frappe.delete_doc("DocType", doctype)
-
-
-def update_customizations():
- dt_cols = {
- "Salary Structure Deduction": {
- "d_type": "salary_component",
- "deduction_type": "salary_component",
- "d_modified_amt": "amount",
- "depend_on_lwp": "depends_on_payment_days"
- },
- "Salary Structure Earning": {
- "e_type": "salary_component",
- "earning_type": "salary_component",
- "modified_value": "amount",
- "depend_on_lwp": "depends_on_payment_days"
- },
- "Salary Slip Earning": {
- "e_type": "salary_component",
- "earning_type": "salary_component",
- "e_modified_amount": "amount",
- "e_amount" : "default_amount",
- "e_depends_on_lwp": "depends_on_payment_days"
- },
- "Salary Slip Deduction": {
- "d_type": "salary_component",
- "deduction_type": "salary_component",
- "d_modified_amount": "amount",
- "d_amount" : "default_amount",
- "d_depends_on_lwp": "depends_on_payment_days"
- }
- }
-
- update_property_setters_and_custom_fields("Salary Detail", dt_cols)
-
- dt_cols = {
- "Earning Type": {
- "earning_name": "salary_component"
- },
- "Deduction Type": {
- "deduction_name": "salary_component"
- }
- }
-
- update_property_setters_and_custom_fields("Salary Component", dt_cols)
-
-
-
-
-def update_property_setters_and_custom_fields(new_dt, dt_cols):
- for doctype, cols in dt_cols.items():
- frappe.db.sql("update `tabProperty Setter` set doc_type = %s where doc_type=%s", (new_dt, doctype))
- frappe.db.sql("update `tabCustom Field` set dt = %s where dt=%s", (new_dt, doctype))
-
-
- for old_fieldname, new_fieldname in cols.items():
- update_property_setters(new_dt, old_fieldname, new_fieldname)
diff --git a/erpnext/patches/v7_0/rename_time_sheet_doctype.py b/erpnext/patches/v7_0/rename_time_sheet_doctype.py
deleted file mode 100644
index f80a8301d7..0000000000
--- a/erpnext/patches/v7_0/rename_time_sheet_doctype.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Sheet") and not frappe.db.table_exists("Timesheet"):
- frappe.rename_doc("DocType", "Time Sheet", "Timesheet")
- frappe.rename_doc("DocType", "Time Sheet Detail", "Timesheet Detail")
-
- for doctype in ['Time Sheet', 'Time Sheet Detail']:
- frappe.delete_doc('DocType', doctype)
-
- report = "Daily Time Sheet Summary"
- if frappe.db.exists("Report", report):
- frappe.delete_doc('Report', report)
diff --git a/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py b/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
deleted file mode 100644
index a5cf22cf01..0000000000
--- a/erpnext/patches/v7_0/repost_bin_qty_and_item_projected_qty.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- repost_bin_qty()
-
-def repost_bin_qty():
- for bin in frappe.db.sql(""" select name from `tabBin`
- where (actual_qty + ordered_qty + indented_qty + planned_qty - reserved_qty - reserved_qty_for_production - reserved_qty_for_sub_contract) != projected_qty """, as_dict=1):
- bin_doc = frappe.get_doc('Bin', bin.name)
- bin_doc.set_projected_qty()
- bin_doc.db_set("projected_qty", bin_doc.projected_qty, update_modified = False)
diff --git a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py b/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
deleted file mode 100644
index b864e597b8..0000000000
--- a/erpnext/patches/v7_0/repost_gle_for_pi_with_update_stock.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-
-def execute():
- frappe.reload_doctype("Purchase Invoice")
-
- for pi in frappe.db.sql("""select name from `tabPurchase Invoice`
- where company in(select name from tabCompany where enable_perpetual_inventory = 1) and
- update_stock=1 and docstatus=1 order by posting_date asc""", as_dict=1):
-
- frappe.db.sql("""delete from `tabGL Entry`
- where voucher_type = 'Purchase Invoice' and voucher_no = %s""", pi.name)
-
- pi_doc = frappe.get_doc("Purchase Invoice", pi.name)
- pi_doc.make_gl_entries()
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py b/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py
deleted file mode 100644
index 77ecafd6f1..0000000000
--- a/erpnext/patches/v7_0/repost_gle_for_pos_sales_return.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint, flt
-
-def execute():
- frappe.reload_doctype("Sales Invoice")
- frappe.reload_doctype("Sales Invoice Item")
-
- for si in frappe.get_all("Sales Invoice", fields = ["name"],
- filters={"docstatus": 1, "is_pos": 1, "is_return": 1}):
- si_doc = frappe.get_doc("Sales Invoice", si.name)
- if len(si_doc.payments) > 0:
- si_doc.set_paid_amount()
- si_doc.flags.ignore_validate_update_after_submit = True
- si_doc.save()
- if si_doc.grand_total <= si_doc.paid_amount and si_doc.paid_amount < 0:
- delete_gle_for_voucher(si_doc.name)
- si_doc.run_method("make_gl_entries")
-
-def delete_gle_for_voucher(voucher_no):
- frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
- {'voucher_no': voucher_no})
diff --git a/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py b/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py
deleted file mode 100644
index 5dd61a06cc..0000000000
--- a/erpnext/patches/v7_0/set_base_amount_in_invoice_payment_table.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- si_list = frappe.db.sql("""
- select distinct parent
- from `tabSales Invoice Payment`
- where docstatus!=2 and parenttype = 'Sales Invoice'
- and amount != 0 and base_amount = 0
- """)
-
- count = 0
- for d in si_list:
- si = frappe.get_doc("Sales Invoice", d[0])
- for p in si.get("payments"):
- if p.amount and not p.base_amount:
- base_amount = flt(p.amount*si.conversion_rate, si.precision("base_paid_amount"))
- frappe.db.set_value("Sales Invoice Payment", p.name, "base_amount", base_amount, update_modified=False)
-
- count +=1
-
- if count % 200 == 0:
- frappe.db.commit()
diff --git a/erpnext/patches/v7_0/set_is_group_for_warehouse.py b/erpnext/patches/v7_0/set_is_group_for_warehouse.py
deleted file mode 100644
index 3e69616b80..0000000000
--- a/erpnext/patches/v7_0/set_is_group_for_warehouse.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "warehouse")
- frappe.db.sql("""update tabWarehouse
- set is_group = if ((ifnull(is_group, "No") = "Yes" or ifnull(is_group, 0) = 1), 1, 0)""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/set_material_request_type_in_item.py b/erpnext/patches/v7_0/set_material_request_type_in_item.py
deleted file mode 100644
index 5fb14adbc8..0000000000
--- a/erpnext/patches/v7_0/set_material_request_type_in_item.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Item")
- if "default_bom" in frappe.db.get_table_columns("Item"):
- frappe.db.sql("""update `tabItem`
- set default_material_request_type = (
- case
- when (default_bom is not null and default_bom != '')
- then 'Manufacture'
- else 'Purchase'
- end )""")
-
- else:
- frappe.db.sql("update tabItem set default_material_request_type='Purchase'")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/set_naming_series_for_timesheet.py b/erpnext/patches/v7_0/set_naming_series_for_timesheet.py
deleted file mode 100644
index d4d1a69d21..0000000000
--- a/erpnext/patches/v7_0/set_naming_series_for_timesheet.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-from frappe.custom.doctype.property_setter.property_setter import make_property_setter
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet')
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
-
- make_property_setter('Timesheet', "naming_series", "options", 'TS-', "Text")
- make_property_setter('Timesheet', "naming_series", "default", 'TS-', "Text")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/set_party_name_in_payment_entry.py b/erpnext/patches/v7_0/set_party_name_in_payment_entry.py
deleted file mode 100644
index bbdcf5cf3c..0000000000
--- a/erpnext/patches/v7_0/set_party_name_in_payment_entry.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- customers = frappe._dict(frappe.db.sql("select name, customer_name from tabCustomer"))
- suppliers = frappe._dict(frappe.db.sql("select name, supplier_name from tabSupplier"))
-
- frappe.reload_doc('accounts', 'doctype', 'payment_entry')
-
- pe_list = frappe.db.sql("""select name, party_type, party from `tabPayment Entry`
- where party is not null and party != ''""", as_dict=1)
- for pe in pe_list:
- party_name = customers.get(pe.party) if pe.party_type=="Customer" else suppliers.get(pe.party)
-
- frappe.db.set_value("Payment Entry", pe.name, "party_name", party_name, update_modified=False)
-
diff --git a/erpnext/patches/v7_0/set_portal_settings.py b/erpnext/patches/v7_0/set_portal_settings.py
deleted file mode 100644
index 5259d4fbd4..0000000000
--- a/erpnext/patches/v7_0/set_portal_settings.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.reload_doctype('Role')
- for dt in ("assessment", "course", "fees"):
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", dt)
- frappe.reload_doc("education", "doctype", dt)
-
- for dt in ("domain", "has_domain", "domain_settings"):
- frappe.reload_doc("core", "doctype", dt)
-
- frappe.reload_doc('website', 'doctype', 'portal_menu_item')
-
- frappe.get_doc('Portal Settings').sync_menu()
-
- if 'schools' in frappe.get_installed_apps():
- domain = frappe.get_doc('Domain', 'Education')
- domain.setup_domain()
- else:
- domain = frappe.get_doc('Domain', 'Manufacturing')
- domain.setup_data()
- domain.setup_sidebar_items()
diff --git a/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py b/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py
deleted file mode 100644
index c5657079b3..0000000000
--- a/erpnext/patches/v7_0/setup_account_table_for_expense_claim_type_if_exists.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("hr", "doctype", "expense_claim_type")
- frappe.reload_doc("hr", "doctype", "expense_claim_account")
-
- if not frappe.db.has_column('Expense Claim Type', 'default_account'):
- return
-
- for expense_claim_type in frappe.get_all("Expense Claim Type", fields=["name", "default_account"]):
- if expense_claim_type.default_account \
- and frappe.db.exists("Account", expense_claim_type.default_account):
- doc = frappe.get_doc("Expense Claim Type", expense_claim_type.name)
- doc.append("accounts", {
- "company": frappe.db.get_value("Account", expense_claim_type.default_account, "company"),
- "default_account": expense_claim_type.default_account,
- })
- doc.flags.ignore_mandatory = True
- doc.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/system_settings_setup_complete.py b/erpnext/patches/v7_0/system_settings_setup_complete.py
deleted file mode 100644
index 0feeee981e..0000000000
--- a/erpnext/patches/v7_0/system_settings_setup_complete.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('System Settings')
- companies = frappe.db.sql("""select name, country
- from tabCompany order by creation asc""", as_dict=True)
- if companies:
- frappe.db.set_value('System Settings', 'System Settings', 'setup_complete', 1)
-
- for company in companies:
- if company.country:
- frappe.db.set_value('System Settings', 'System Settings', 'country', company.country)
- break
-
-
diff --git a/erpnext/patches/v7_0/update_autoname_field.py b/erpnext/patches/v7_0/update_autoname_field.py
deleted file mode 100644
index bfa9b281df..0000000000
--- a/erpnext/patches/v7_0/update_autoname_field.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctypes = frappe.db.sql(""" select name, autoname from `tabDocType`
- where autoname like 'field:%' and allow_rename = 1""", as_dict=1)
-
- for doctype in doctypes:
- fieldname = doctype.autoname.split(":")[1]
- if fieldname:
- frappe.db.sql(""" update `tab%s` set %s = name """%(doctype.name, fieldname))
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_change_amount_account.py b/erpnext/patches/v7_0/update_change_amount_account.py
deleted file mode 100644
index 1741095ea9..0000000000
--- a/erpnext/patches/v7_0/update_change_amount_account.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
-
- for company in frappe.db.sql("""select company from `tabSales Invoice`
- where change_amount <> 0 and account_for_change_amount is null group by company""", as_list = 1):
- cash_account = get_default_bank_cash_account(company[0], 'Cash').get('account')
- if not cash_account:
- bank_account = get_default_bank_cash_account(company[0], 'Bank').get('account')
- cash_account = bank_account
-
- if cash_account:
- frappe.db.sql("""update `tabSales Invoice`
- set account_for_change_amount = %(cash_account)s where change_amount <> 0
- and company = %(company)s and account_for_change_amount is null""",
- {'cash_account': cash_account, 'company': company[0]})
diff --git a/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py b/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py
deleted file mode 100644
index 24da4b1aeb..0000000000
--- a/erpnext/patches/v7_0/update_conversion_factor_in_supplier_quotation_item.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('buying', 'doctype', 'supplier_quotation_item')
-
- frappe.db.sql("""update
- `tabSupplier Quotation Item` as sqi_t,
- (select sqi.item_code as item_code, sqi.uom as uom, ucd.conversion_factor as conversion_factor
- from `tabSupplier Quotation Item` sqi left join `tabUOM Conversion Detail` ucd
- on ucd.uom = sqi.uom and sqi.item_code = ucd.parent) as conversion_data,
- `tabItem` as item
- set
- sqi_t.conversion_factor= ifnull(conversion_data.conversion_factor, 1),
- sqi_t.stock_qty = (ifnull(conversion_data.conversion_factor, 1) * sqi_t.qty),
- sqi_t.stock_uom = item.stock_uom
- where
- sqi_t.item_code = conversion_data.item_code and
- sqi_t.uom = conversion_data.uom and sqi_t.item_code = item.name""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_home_page.py b/erpnext/patches/v7_0/update_home_page.py
deleted file mode 100644
index 909825c572..0000000000
--- a/erpnext/patches/v7_0/update_home_page.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-import erpnext
-
-def execute():
- frappe.reload_doc('portal', 'doctype', 'homepage_featured_product')
- frappe.reload_doc('portal', 'doctype', 'homepage')
- frappe.reload_doc('portal', 'doctype', 'products_settings')
- frappe.reload_doctype('Item')
- frappe.reload_doctype('Item Group')
-
- website_settings = frappe.get_doc('Website Settings', 'Website Settings')
- if frappe.db.exists('Web Page', website_settings.home_page):
- header = frappe.db.get_value('Web Page', website_settings.home_page, 'header')
- if header and header.startswith(""):
- homepage = frappe.get_doc('Homepage', 'Homepage')
- homepage.company = erpnext.get_default_company() or frappe.get_all("Company")[0].name
- if '
' in header:
- homepage.tag_line = header.split('')[1].split('
')[0] or 'Default Website'
- else:
- homepage.tag_line = 'Default Website'
- homepage.setup_items()
- homepage.save()
-
- website_settings.home_page = 'home'
- website_settings.save()
-
diff --git a/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py b/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py
deleted file mode 100644
index 4c0c6a9313..0000000000
--- a/erpnext/patches/v7_0/update_maintenance_module_in_doctype.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.set_value("DocType", "Maintenance Schedule", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Schedule Detail", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Schedule Item", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Visit", "module", "Maintenance")
- frappe.db.set_value("DocType", "Maintenance Visit Purpose", "module", "Maintenance")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_mins_to_first_response.py b/erpnext/patches/v7_0/update_mins_to_first_response.py
deleted file mode 100644
index 16681357e6..0000000000
--- a/erpnext/patches/v7_0/update_mins_to_first_response.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from frappe.core.doctype.communication.communication import update_mins_to_first_communication
-
-def execute():
- frappe.reload_doctype('Issue')
- frappe.reload_doctype('Opportunity')
-
- for doctype in ('Issue', 'Opportunity'):
- frappe.db.sql('update tab{0} set mins_to_first_response=0'.format(doctype))
- for parent in frappe.get_all(doctype, order_by='creation desc', limit=500):
- parent_doc = frappe.get_doc(doctype, parent.name)
- for communication in frappe.get_all('Communication',
- filters={'reference_doctype': doctype, 'reference_name': parent.name,
- 'communication_medium': 'Email'},
- order_by = 'creation asc', limit=2):
-
- communication_doc = frappe.get_doc('Communication', communication.name)
-
- update_mins_to_first_communication(parent_doc, communication_doc)
-
- if parent_doc.mins_to_first_response:
- continue
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py b/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py
deleted file mode 100644
index 54d492b265..0000000000
--- a/erpnext/patches/v7_0/update_missing_employee_in_timesheet.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Log") and "employee" in frappe.db.get_table_columns("Time Log"):
- timesheet = frappe.db.sql("""select tl.employee as employee, ts.name as name,
- tl.modified as modified, tl.modified_by as modified_by, tl.creation as creation, tl.owner as owner
- from
- `tabTimesheet` ts, `tabTimesheet Detail` tsd, `tabTime Log` tl
- where
- tsd.parent = ts.name and tl.from_time = tsd.from_time and tl.to_time = tsd.to_time
- and tl.hours = tsd.hours and tl.billing_rate = tsd.billing_rate and tsd.idx=1
- and tl.docstatus < 2 and (ts.employee = '' or ts.employee is null)""", as_dict=1)
-
- for data in timesheet:
- ts_doc = frappe.get_doc('Timesheet', data.name)
- if len(ts_doc.time_logs) == 1:
- frappe.db.sql(""" update `tabTimesheet` set creation = %(creation)s,
- owner = %(owner)s, modified = %(modified)s, modified_by = %(modified_by)s,
- employee = %(employee)s where name = %(name)s""", data)
diff --git a/erpnext/patches/v7_0/update_mode_of_payment_type.py b/erpnext/patches/v7_0/update_mode_of_payment_type.py
deleted file mode 100644
index 9292a1be1b..0000000000
--- a/erpnext/patches/v7_0/update_mode_of_payment_type.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'mode_of_payment')
-
- frappe.db.sql(""" update `tabMode of Payment` set type = 'Cash' where (type is null or type = '') and name = 'Cash'""")
-
- for data in frappe.db.sql("""select name from `tabSales Invoice` where is_pos=1 and docstatus<2 and
- (ifnull(paid_amount, 0) - ifnull(change_amount, 0)) > ifnull(grand_total, 0) and modified > '2016-05-01'""", as_dict=1):
- if data.name:
- si_doc = frappe.get_doc("Sales Invoice", data.name)
- remove_payment = []
- mode_of_payment = [d.mode_of_payment for d in si_doc.payments if flt(d.amount) > 0]
- if mode_of_payment != set(mode_of_payment):
- for payment_data in si_doc.payments:
- if payment_data.idx != 1 and payment_data.amount == si_doc.grand_total:
- remove_payment.append(payment_data)
- frappe.db.sql(""" delete from `tabSales Invoice Payment`
- where name = %(name)s""", {'name': payment_data.name})
-
- if len(remove_payment) > 0:
- for d in remove_payment:
- si_doc.remove(d)
-
- si_doc.set_paid_amount()
- si_doc.db_set("paid_amount", si_doc.paid_amount, update_modified = False)
- si_doc.db_set("base_paid_amount", si_doc.base_paid_amount, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_party_status.py b/erpnext/patches/v7_0/update_party_status.py
deleted file mode 100644
index 0c6b4ea598..0000000000
--- a/erpnext/patches/v7_0/update_party_status.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- return
- # for party_type in ('Customer', 'Supplier'):
- # frappe.reload_doctype(party_type)
- #
- # # set all as default status
- # frappe.db.sql('update `tab{0}` set status=%s'.format(party_type), default_status[party_type])
- #
- # for doctype in status_depends_on[party_type]:
- # filters = get_filters_for(doctype)
- # parties = frappe.get_all(doctype, fields="{0} as party".format(party_type.lower()),
- # filters=filters, limit_page_length=1)
- #
- # parties = filter(None, [p.party for p in parties])
- #
- # if parties:
- # frappe.db.sql('update `tab{0}` set status="Open" where name in ({1})'.format(party_type,
- # ', '.join(len(parties) * ['%s'])), parties)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py b/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py
deleted file mode 100644
index e90de50c1e..0000000000
--- a/erpnext/patches/v7_0/update_prevdoc_values_for_supplier_quotation_item.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Supplier Quotation Item')
- for data in frappe.db.sql(""" select prevdoc_docname, prevdoc_detail_docname, name
- from `tabSupplier Quotation Item` where prevdoc_docname is not null""", as_dict=True):
- frappe.db.set_value("Supplier Quotation Item", data.name, "material_request", data.prevdoc_docname)
- frappe.db.set_value("Supplier Quotation Item", data.name, "material_request_item", data.prevdoc_detail_docname)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_project_in_gl_entry.py b/erpnext/patches/v7_0/update_project_in_gl_entry.py
deleted file mode 100644
index d99e9a41e3..0000000000
--- a/erpnext/patches/v7_0/update_project_in_gl_entry.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("GL Entry")
-
- for doctype in ("Delivery Note", "Sales Invoice", "Stock Entry"):
- frappe.db.sql("""
- update `tabGL Entry` gle, `tab{0}` dt
- set gle.project = dt.project
- where gle.voucher_type=%s and gle.voucher_no = dt.name
- and ifnull(gle.cost_center, '') != '' and ifnull(dt.project, '') != ''
- """.format(doctype), doctype)
-
- for doctype in ("Purchase Receipt", "Purchase Invoice"):
- frappe.db.sql("""
- update `tabGL Entry` gle, `tab{0} Item` dt
- set gle.project = dt.project
- where gle.voucher_type=%s and gle.voucher_no = dt.parent and gle.cost_center=dt.cost_center
- and ifnull(gle.cost_center, '') != '' and ifnull(dt.project, '') != ''
- """.format(doctype), doctype)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py b/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py
deleted file mode 100644
index 2d562bb40e..0000000000
--- a/erpnext/patches/v7_0/update_refdoc_in_landed_cost_voucher.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if "purchase_receipt" not in frappe.db.get_table_columns("Landed Cost Purchase Receipt"):
- return
-
- frappe.reload_doctype("Landed Cost Purchase Receipt")
-
- frappe.db.sql("""
- update `tabLanded Cost Purchase Receipt`
- set receipt_document_type = 'Purchase Receipt', receipt_document = purchase_receipt
- where (receipt_document is null or receipt_document = '')
- and (purchase_receipt is not null and purchase_receipt != '')
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_status_for_timesheet.py b/erpnext/patches/v7_0/update_status_for_timesheet.py
deleted file mode 100644
index 117c40c59f..0000000000
--- a/erpnext/patches/v7_0/update_status_for_timesheet.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""update
- `tabTimesheet` as ts,
- (
- select min(from_time)as from_time, max(to_time) as to_time, parent from `tabTimesheet Detail` group by parent
- ) as tsd
- set ts.status = 'Submitted', ts.start_date = tsd.from_time, ts.end_date = tsd.to_time
- where tsd.parent = ts.name and ts.status = 'Draft' and ts.docstatus =1""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_status_of_po_so.py b/erpnext/patches/v7_0/update_status_of_po_so.py
deleted file mode 100644
index d630e8f0f2..0000000000
--- a/erpnext/patches/v7_0/update_status_of_po_so.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint, flt
-
-def execute():
- update_po_per_received_per_billed()
- update_so_per_delivered_per_billed()
- update_status()
-
-def update_po_per_received_per_billed():
- frappe.db.sql("""
- update
- `tabPurchase Order`
- set
- `tabPurchase Order`.per_received = round((select sum(if(qty > ifnull(received_qty, 0),
- ifnull(received_qty, 0), qty)) / sum(qty) *100 from `tabPurchase Order Item`
- where parent = `tabPurchase Order`.name), 2),
- `tabPurchase Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0),
- ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabPurchase Order Item`
- where parent = `tabPurchase Order`.name), 2), 0)
- where
- net_total > 0
- """)
-
-def update_so_per_delivered_per_billed():
- frappe.db.sql("""
- update
- `tabSales Order`
- set
- `tabSales Order`.per_delivered = round((select sum( if(qty > ifnull(delivered_qty, 0),
- ifnull(delivered_qty, 0), qty)) / sum(qty) *100 from `tabSales Order Item`
- where parent = `tabSales Order`.name), 2),
- `tabSales Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0),
- ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabSales Order Item`
- where parent = `tabSales Order`.name), 2), 0)
- where
- net_total > 0
- """)
-
-def update_status():
- frappe.db.sql("""
- update
- `tabSales Order`
- set status = (Case when status = 'Closed' then 'Closed'
- When per_delivered < 100 and per_billed < 100 and docstatus = 1 then 'To Deliver and Bill'
- when per_delivered = 100 and per_billed < 100 and docstatus = 1 then 'To Bill'
- when per_delivered < 100 and per_billed = 100 and docstatus = 1 then 'To Deliver'
- when per_delivered = 100 and per_billed = 100 and docstatus = 1 then 'Completed'
- when order_type = 'Maintenance' and per_billed = 100 and docstatus = 1 then 'Completed'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
-
- frappe.db.sql("""
- update
- `tabPurchase Order`
- set status = (Case when status = 'Closed' then 'Closed'
- when status = 'Delivered' then 'Delivered'
- When per_received < 100 and per_billed < 100 and docstatus = 1 then 'To Receive and Bill'
- when per_received = 100 and per_billed < 100 and docstatus = 1 then 'To Bill'
- when per_received < 100 and per_billed = 100 and docstatus = 1 then 'To Receive'
- when per_received = 100 and per_billed = 100 and docstatus = 1 then 'Completed'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py b/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py
deleted file mode 100644
index 9b2b24785a..0000000000
--- a/erpnext/patches/v7_0/update_status_of_zero_amount_sales_order.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for data in frappe.get_all('Sales Order', fields = ["name"], filters = [["docstatus", "=", "1"], ["grand_total", "=", "0"]]):
- sales_order = frappe.get_doc('Sales Order', data.name)
- sales_order.set_status(update=True, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v7_0/update_timesheet_communications.py b/erpnext/patches/v7_0/update_timesheet_communications.py
deleted file mode 100644
index 203471ea8f..0000000000
--- a/erpnext/patches/v7_0/update_timesheet_communications.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("Time Log"):
- timesheet = frappe.db.sql("""SELECT ts.name AS name, tl.name AS timelogname,
- tl.modified AS modified, tl.modified_by AS modified_by, tl.creation AS creation, tl.owner AS owner
- FROM
- `tabTimesheet` ts, `tabTimesheet Detail` tsd, `tabTime Log` tl
- WHERE
- tsd.parent = ts.name AND tl.from_time = tsd.from_time AND tl.to_time = tsd.to_time
- AND tl.hours = tsd.hours AND tl.billing_rate = tsd.billing_rate AND tsd.idx=1
- AND tl.docstatus < 2""", as_dict=1)
-
- for data in timesheet:
- frappe.db.sql(""" update `tabTimesheet` set creation = %(creation)s,
- owner = %(owner)s, modified = %(modified)s, modified_by = %(modified_by)s
- where name = %(name)s""", data)
-
- frappe.db.sql("""
- update
- tabCommunication
- set
- reference_doctype = "Timesheet", reference_name = %(timesheet)s
- where
- reference_doctype = "Time Log" and reference_name = %(timelog)s
- """, {'timesheet': data.name, 'timelog': data.timelogname}, auto_commit=1)
diff --git a/erpnext/patches/v7_1/__init__.py b/erpnext/patches/v7_1/__init__.py
deleted file mode 100644
index 519ff49eac..0000000000
--- a/erpnext/patches/v7_1/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py b/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py
deleted file mode 100644
index 7372b0cc5f..0000000000
--- a/erpnext/patches/v7_1/add_account_user_role_for_timesheet.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.get_value('DocPerm', {'parent': 'Timesheet', 'role': 'Accounts User', 'permlevel': 1}):
- doc = frappe.get_doc('DocType', 'Timesheet')
- doc.append('permissions', {
- 'role': "Accounts User",
- 'permlevel': 0,
- 'read': 1,
- 'write': 1,
- 'create': 1,
- 'delete': 1,
- 'submit': 1,
- 'cancel': 1,
- 'amend': 1,
- 'report': 1,
- 'email': 1
- })
-
- doc.append('permissions', {
- 'role': "Accounts User",
- 'permlevel': 1,
- 'read': 1,
- 'write': 1
- })
-
- doc.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/add_field_for_task_dependent.py b/erpnext/patches/v7_1/add_field_for_task_dependent.py
deleted file mode 100644
index 65b1c74e87..0000000000
--- a/erpnext/patches/v7_1/add_field_for_task_dependent.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Task')
- for t in frappe.get_all('Task', fields=['name']):
- task = frappe.get_doc('Task', t.name)
- task.update_depends_on()
- if task.depends_on_tasks:
- task.db_set('depends_on_tasks', task.depends_on_tasks, update_modified=False)
diff --git a/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py b/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py
deleted file mode 100644
index 33f809fe37..0000000000
--- a/erpnext/patches/v7_1/fix_link_for_customer_from_lead.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for c in frappe.db.sql('select name from tabCustomer where ifnull(lead_name,"")!=""'):
- customer = frappe.get_doc('Customer', c[0])
- customer.update_lead_status()
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py b/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py
deleted file mode 100644
index d1ec7c697e..0000000000
--- a/erpnext/patches/v7_1/move_sales_invoice_from_parent_to_child_timesheet.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
-
- frappe.db.sql(""" update
- `tabTimesheet` as ts,
- (select
- sum(billing_amount) as billing_amount, sum(billing_hours) as billing_hours, time_sheet
- from `tabSales Invoice Timesheet` where docstatus = 1 group by time_sheet
- ) as sit
- set
- ts.total_billed_amount = sit.billing_amount, ts.total_billed_hours = sit.billing_hours,
- ts.per_billed = ((sit.billing_amount * 100)/ts.total_billable_amount)
- where ts.name = sit.time_sheet and ts.docstatus = 1""")
-
- frappe.db.sql(""" update `tabTimesheet Detail` tsd, `tabTimesheet` ts set tsd.sales_invoice = ts.sales_invoice
- where tsd.parent = ts.name and ts.sales_invoice is not null""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/rename_field_timesheet.py b/erpnext/patches/v7_1/rename_field_timesheet.py
deleted file mode 100644
index 3690a2e79d..0000000000
--- a/erpnext/patches/v7_1/rename_field_timesheet.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- doctype = 'Timesheet'
- fields_dict = {'total_billing_amount': 'total_billable_amount', 'total_billing_hours': 'total_billable_hours'}
-
- for old_fieldname, new_fieldname in fields_dict.items():
- if old_fieldname in frappe.db.get_table_columns(doctype):
- rename_field(doctype, old_fieldname, new_fieldname)
diff --git a/erpnext/patches/v7_1/rename_quality_inspection_field.py b/erpnext/patches/v7_1/rename_quality_inspection_field.py
deleted file mode 100644
index 3b5a7d95eb..0000000000
--- a/erpnext/patches/v7_1/rename_quality_inspection_field.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import *
-
-def execute():
- for doctype in ("Purchase Receipt Item", "Delivery Note Item"):
- frappe.reload_doctype(doctype)
-
- table_columns = frappe.db.get_table_columns(doctype)
- if "qa_no" in table_columns:
- rename_field(doctype, "qa_no", "quality_inspection")
-
- frappe.reload_doctype("Item")
- rename_field("Item", "inspection_required", "inspection_required_before_purchase")
-
- frappe.reload_doc('stock', 'doctype', 'quality_inspection')
- frappe.db.sql("""
- update
- `tabQuality Inspection`
- set
- reference_type = 'Purchase Receipt', reference_name = purchase_receipt_no
- where
- ifnull(purchase_receipt_no, '') != '' and inspection_type = 'Incoming'
- """)
-
- frappe.db.sql("""
- update
- `tabQuality Inspection`
- set
- reference_type = 'Delivery Note', reference_name = delivery_note_no
- where
- ifnull(delivery_note_no, '') != '' and inspection_type = 'Outgoing'
- """)
-
- for old_fieldname in ["purchase_receipt_no", "delivery_note_no"]:
- update_reports("Quality Inspection", old_fieldname, "reference_name")
- update_users_report_view_settings("Quality Inspection", old_fieldname, "reference_name")
- update_property_setters("Quality Inspection", old_fieldname, "reference_name")
diff --git a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py
deleted file mode 100644
index aca21085cc..0000000000
--- a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import repost_stock
-
-def execute():
- frappe.reload_doc('manufacturing', 'doctype', 'work_order_item')
- frappe.reload_doc('manufacturing', 'doctype', 'work_order')
-
- modified_items = frappe.db.sql_list("""
- select name from `tabItem`
- where is_stock_item=1 and modified >= '2016-10-31'
- """)
-
- if not modified_items:
- return
-
- item_warehouses_with_transactions = []
- transactions = ("Sales Order Item", "Material Request Item", "Purchase Order Item",
- "Stock Ledger Entry", "Packed Item")
-
- for doctype in transactions:
- item_warehouses_with_transactions += list(frappe.db.sql("""
- select distinct item_code, warehouse
- from `tab{0}` where docstatus=1 and item_code in ({1})"""
- .format(doctype, ', '.join(['%s']*len(modified_items))), tuple(modified_items)))
-
- item_warehouses_with_transactions += list(frappe.db.sql("""
- select distinct production_item, fg_warehouse
- from `tabWork Order` where docstatus=1 and production_item in ({0})"""
- .format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
-
- item_warehouses_with_transactions += list(frappe.db.sql("""
- select distinct pr_item.item_code, pr_item.source_warehouse
- from `tabWork Order` pr, `tabWork Order Item` pr_item
- where pr_item.parent and pr.name and pr.docstatus=1 and pr_item.item_code in ({0})"""
- .format(', '.join(['%s']*len(modified_items))), tuple(modified_items)))
-
- item_warehouses_with_bin = list(frappe.db.sql("select distinct item_code, warehouse from `tabBin`"))
-
- item_warehouses_with_missing_bin = list(
- set(item_warehouses_with_transactions) - set(item_warehouses_with_bin))
-
- for item_code, warehouse in item_warehouses_with_missing_bin:
- repost_stock(item_code, warehouse)
diff --git a/erpnext/patches/v7_1/save_stock_settings.py b/erpnext/patches/v7_1/save_stock_settings.py
deleted file mode 100644
index d3f0263c10..0000000000
--- a/erpnext/patches/v7_1/save_stock_settings.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- stock_settings = frappe.get_doc('Stock Settings')
-
- if stock_settings.default_warehouse \
- and not frappe.db.exists("Warehouse", stock_settings.default_warehouse):
- stock_settings.default_warehouse = None
-
- if stock_settings.stock_uom and not frappe.db.exists("UOM", stock_settings.stock_uom):
- stock_settings.stock_uom = None
-
- stock_settings.flags.ignore_mandatory = True
- stock_settings.save()
diff --git a/erpnext/patches/v7_1/set_budget_against_as_cost_center.py b/erpnext/patches/v7_1/set_budget_against_as_cost_center.py
deleted file mode 100644
index dd9a432cf0..0000000000
--- a/erpnext/patches/v7_1/set_budget_against_as_cost_center.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "budget")
- frappe.db.sql("""
- update
- `tabBudget`
- set
- budget_against = 'Cost Center'
- """)
diff --git a/erpnext/patches/v7_1/set_currency_exchange_date.py b/erpnext/patches/v7_1/set_currency_exchange_date.py
deleted file mode 100644
index 2a2d420f21..0000000000
--- a/erpnext/patches/v7_1/set_currency_exchange_date.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Currency Exchange")
- frappe.db.sql("""
- update `tabCurrency Exchange`
- set `date` = '2010-01-01'
- where date is null or date = '0000-00-00'
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/set_prefered_contact_email.py b/erpnext/patches/v7_1/set_prefered_contact_email.py
deleted file mode 100644
index 3b68e22269..0000000000
--- a/erpnext/patches/v7_1/set_prefered_contact_email.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('User')
- for d in frappe.get_all("Employee"):
- employee = frappe.get_doc("Employee", d.name)
- if employee.company_email:
- employee.prefered_contact_email = "Company Email"
- employee.prefered_email = employee.company_email
- elif employee.personal_email:
- employee.prefered_contact_email = "Personal Email"
- employee.prefered_email = employee.personal_email
- elif employee.user_id:
- employee.prefered_contact_email = "User ID"
- employee.prefered_email = employee.user_id
- employee.db_update()
diff --git a/erpnext/patches/v7_1/set_sales_person_status.py b/erpnext/patches/v7_1/set_sales_person_status.py
deleted file mode 100644
index 929beac27f..0000000000
--- a/erpnext/patches/v7_1/set_sales_person_status.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('setup','doctype','sales_person')
- frappe.db.sql("""update `tabSales Person` set enabled=1
- where (employee is null or employee = ''
- or employee IN (select employee from tabEmployee where status != "Left"))""")
diff --git a/erpnext/patches/v7_1/set_student_guardian.py b/erpnext/patches/v7_1/set_student_guardian.py
deleted file mode 100644
index 093c0bf6d9..0000000000
--- a/erpnext/patches/v7_1/set_student_guardian.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Guardian"):
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "student")
- # frappe.reload_doc("schools", "doctype", "student_guardian")
- # frappe.reload_doc("schools", "doctype", "student_sibling")
-
- frappe.reload_doc("education", "doctype", "student")
- frappe.reload_doc("education", "doctype", "student_guardian")
- frappe.reload_doc("education", "doctype", "student_sibling")
- if "student" not in frappe.db.get_table_columns("Guardian"):
- return
- guardian = frappe.get_all("Guardian", fields=["name", "student"])
- for d in guardian:
- if d.student:
- student = frappe.get_doc("Student", d.student)
- if student:
- student.append("guardians", {"guardian": d.name})
- student.save()
diff --git a/erpnext/patches/v7_1/set_total_amount_currency_in_je.py b/erpnext/patches/v7_1/set_total_amount_currency_in_je.py
deleted file mode 100644
index 8426ddcd7d..0000000000
--- a/erpnext/patches/v7_1/set_total_amount_currency_in_je.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext import get_default_currency
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "journal_entry")
-
- frappe.db.sql(""" update `tabJournal Entry` set total_amount_currency = %s
- where ifnull(multi_currency, 0) = 0
- and (pay_to_recd_from is not null or pay_to_recd_from != "") """, get_default_currency())
-
- for je in frappe.db.sql(""" select name from `tabJournal Entry` where multi_currency = 1
- and (pay_to_recd_from is not null or pay_to_recd_from != "")""", as_dict=1):
-
- doc = frappe.get_doc("Journal Entry", je.name)
- for d in doc.get('accounts'):
- if d.party_type and d.party:
- total_amount_currency = d.account_currency
-
- elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]:
- total_amount_currency = d.account_currency
-
- frappe.db.set_value("Journal Entry", je.name, "total_amount_currency",
- total_amount_currency, update_modified=False)
diff --git a/erpnext/patches/v7_1/update_bom_base_currency.py b/erpnext/patches/v7_1/update_bom_base_currency.py
deleted file mode 100644
index 9a59209ea5..0000000000
--- a/erpnext/patches/v7_1/update_bom_base_currency.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext import get_default_currency
-
-def execute():
- frappe.reload_doc("manufacturing", "doctype", "bom")
- frappe.reload_doc("manufacturing", "doctype", "bom_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_explosion_item")
- frappe.reload_doc("manufacturing", "doctype", "bom_operation")
- frappe.reload_doc("manufacturing", "doctype", "bom_scrap_item")
-
- frappe.db.sql(""" update `tabBOM Operation` set base_hour_rate = hour_rate,
- base_operating_cost = operating_cost """)
-
- frappe.db.sql(""" update `tabBOM Item` set base_rate = rate, base_amount = amount """)
- frappe.db.sql(""" update `tabBOM Scrap Item` set base_rate = rate, base_amount = amount """)
-
- frappe.db.sql(""" update `tabBOM` set `tabBOM`.base_operating_cost = `tabBOM`.operating_cost,
- `tabBOM`.base_raw_material_cost = `tabBOM`.raw_material_cost,
- `tabBOM`.currency = (select default_currency from `tabCompany` where name = `tabBOM`.company)""")
diff --git a/erpnext/patches/v7_1/update_component_type.py b/erpnext/patches/v7_1/update_component_type.py
deleted file mode 100644
index 24ca0570e0..0000000000
--- a/erpnext/patches/v7_1/update_component_type.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import flt
-
-def execute():
- frappe.reload_doc('Payroll', 'doctype', 'salary_component')
- sal_components = frappe.db.sql("""
- select DISTINCT salary_component, parentfield from `tabSalary Detail`""", as_dict=True)
-
- if sal_components:
- for sal_component in sal_components:
- if sal_component.parentfield == "earnings":
- frappe.db.sql("""update `tabSalary Component` set type='Earning' where salary_component=%(sal_comp)s""",{"sal_comp": sal_component.salary_component})
- else:
- frappe.db.sql("""update `tabSalary Component` set type='Deduction' where salary_component=%(sal_comp)s""",{"sal_comp": sal_component.salary_component})
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/update_invoice_status.py b/erpnext/patches/v7_1/update_invoice_status.py
deleted file mode 100644
index 851af80f7a..0000000000
--- a/erpnext/patches/v7_1/update_invoice_status.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice')
-
- frappe.db.sql("""
- update
- `tabPurchase Invoice`
- set
- status = (Case When outstanding_amount = 0 and docstatus = 1 and is_return = 0 then 'Paid'
- when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue'
- when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid'
- when outstanding_amount < 0 and docstatus =1 then 'Debit Note Issued'
- when is_return = 1 and docstatus =1 then 'Return'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
-
- frappe.db.sql("""
- update
- `tabSales Invoice`
- set status = (Case When outstanding_amount = 0 and docstatus = 1 and is_return = 0 then 'Paid'
- when due_date < CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Overdue'
- when due_date >= CURDATE() and outstanding_amount > 0 and docstatus =1 then 'Unpaid'
- when outstanding_amount < 0 and docstatus =1 then 'Credit Note Issued'
- when is_return = 1 and docstatus =1 then 'Return'
- when docstatus = 2 then 'Cancelled'
- else 'Draft'
- End)""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_1/update_lead_source.py b/erpnext/patches/v7_1/update_lead_source.py
deleted file mode 100644
index a2a48a62e1..0000000000
--- a/erpnext/patches/v7_1/update_lead_source.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- from erpnext.setup.setup_wizard.operations.install_fixtures import default_lead_sources
-
- frappe.reload_doc('crm', 'doctype', 'lead_source')
-
- frappe.local.lang = frappe.db.get_default("lang") or 'en'
-
- for s in default_lead_sources:
- insert_lead_source(_(s))
-
- # get lead sources in existing forms (customized)
- # and create a document if not created
- for d in ['Lead', 'Opportunity', 'Quotation', 'Sales Order', 'Delivery Note', 'Sales Invoice']:
- sources = frappe.db.sql_list('select distinct source from `tab{0}`'.format(d))
- for s in sources:
- if s and s not in default_lead_sources:
- insert_lead_source(s)
-
- # remove customization for source
- for p in frappe.get_all('Property Setter', {'doc_type':d, 'field_name':'source', 'property':'options'}):
- frappe.delete_doc('Property Setter', p.name)
-
-def insert_lead_source(s):
- if not frappe.db.exists('Lead Source', s):
- frappe.get_doc(dict(doctype='Lead Source', source_name=s)).insert()
diff --git a/erpnext/patches/v7_1/update_missing_salary_component_type.py b/erpnext/patches/v7_1/update_missing_salary_component_type.py
deleted file mode 100644
index 824f2b881f..0000000000
--- a/erpnext/patches/v7_1/update_missing_salary_component_type.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-from frappe.utils import cstr
-
-'''
-Some components do not have type set, try and guess whether they turn up in
-earnings or deductions in existing salary slips
-'''
-
-def execute():
- frappe.reload_doc("accounts", "doctype", "salary_component_account")
- frappe.reload_doc("Payroll", "doctype", "salary_component")
- frappe.reload_doc("Payroll", "doctype", "taxable_salary_slab")
-
- for s in frappe.db.sql('''select name, type, salary_component_abbr from `tabSalary Component`
- where ifnull(type, "")="" or ifnull(salary_component_abbr, "") = ""''', as_dict=1):
-
- component = frappe.get_doc('Salary Component', s.name)
-
- # guess
- if not s.type:
- guess = frappe.db.sql('''select
- parentfield from `tabSalary Detail`
- where salary_component=%s limit 1''', s.name)
-
- if guess:
- component.type = 'Earning' if guess[0][0]=='earnings' else 'Deduction'
-
- else:
- component.type = 'Deduction'
-
- if not s.salary_component_abbr:
- abbr = ''.join([c[0] for c in component.salary_component.split()]).upper()
-
- abbr_count = frappe.db.sql("""
- select
- count(name)
- from
- `tabSalary Component`
- where
- salary_component_abbr = %s or salary_component_abbr like %s
- """, (abbr, abbr + "-%%"))
-
- if abbr_count and abbr_count[0][0] > 0:
- abbr = abbr + "-" + cstr(abbr_count[0][0])
-
- component.salary_component_abbr = abbr
-
- component.save()
diff --git a/erpnext/patches/v7_1/update_portal_roles.py b/erpnext/patches/v7_1/update_portal_roles.py
deleted file mode 100644
index 482586b8ef..0000000000
--- a/erpnext/patches/v7_1/update_portal_roles.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Role')
- frappe.reload_doctype('User')
- for role_name in ('Customer', 'Supplier', 'Student'):
- if frappe.db.exists('Role', role_name):
- frappe.db.set_value('Role', role_name, 'desk_access', 0)
- else:
- frappe.get_doc(dict(doctype='Role', role_name=role_name, desk_access=0)).insert()
-
-
- # set customer, supplier roles
- for c in frappe.get_all('Contact', fields=['user'], filters={'ifnull(user, "")': ('!=', '')}):
- user = frappe.get_doc('User', c.user)
- user.flags.ignore_validate = True
- user.flags.ignore_mandatory = True
- user.save()
-
-
diff --git a/erpnext/patches/v7_1/update_total_billing_hours.py b/erpnext/patches/v7_1/update_total_billing_hours.py
deleted file mode 100644
index b9c96028f5..0000000000
--- a/erpnext/patches/v7_1/update_total_billing_hours.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
-
- frappe.db.sql("""update tabTimesheet set total_billable_hours=total_hours
- where total_billable_amount>0 and docstatus = 1""")
-
- frappe.db.sql("""update `tabTimesheet Detail` set billing_hours=hours where docstatus < 2""")
-
- frappe.db.sql(""" update `tabSales Invoice Timesheet` set billing_hours = (select total_billable_hours from `tabTimesheet`
- where name = time_sheet) where time_sheet is not null""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/__init__.py b/erpnext/patches/v7_2/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v7_2/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py b/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py
deleted file mode 100644
index d2583b9422..0000000000
--- a/erpnext/patches/v7_2/arrear_leave_encashment_as_salary_component.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # frappe.reload_doctype('Salary Slip', 'Salary Component')
- frappe.reload_doc("Payroll", "doctype", "Salary Slip")
- frappe.reload_doc("Payroll", "doctype", "Salary Component")
- salary_components = [['Arrear', "ARR"], ['Leave Encashment', 'LENC']]
- for salary_component, salary_abbr in salary_components:
- if not frappe.db.exists('Salary Component', salary_component):
- sal_comp = frappe.get_doc({
- "doctype": "Salary Component",
- "salary_component": salary_component,
- "type": "Earning",
- "salary_component_abbr": salary_abbr
- }).insert()
-
- salary_slips = frappe.db.sql("""select name, arrear_amount, leave_encashment_amount from `tabSalary Slip`
- where docstatus !=2 and (arrear_amount > 0 or leave_encashment_amount > 0)""", as_dict=True)
-
- for salary_slip in salary_slips:
- doc = frappe.get_doc('Salary Slip', salary_slip.name)
-
- if salary_slip.get("arrear_amount") > 0:
- r = doc.append('earnings', {
- 'salary_component': 'Arrear',
- 'amount': salary_slip.arrear_amount
- })
- r.db_update()
-
- if salary_slip.get("leave_encashment_amount") > 0:
- r = doc.append('earnings', {
- 'salary_component': 'Leave Encashment',
- 'amount': salary_slip.leave_encashment_amount
- })
- r.db_update()
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/contact_address_links.py b/erpnext/patches/v7_2/contact_address_links.py
deleted file mode 100644
index 200434c208..0000000000
--- a/erpnext/patches/v7_2/contact_address_links.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.core.doctype.dynamic_link.dynamic_link import deduplicate_dynamic_links
-from frappe.utils import update_progress_bar
-
-def execute():
- frappe.reload_doc('core', 'doctype', 'dynamic_link')
- frappe.reload_doc('contacts', 'doctype', 'contact')
- frappe.reload_doc('contacts', 'doctype', 'address')
- map_fields = (
- ('Customer', 'customer'),
- ('Supplier', 'supplier'),
- ('Lead', 'lead'),
- ('Sales Partner', 'sales_partner')
- )
- for doctype in ('Contact', 'Address'):
- if frappe.db.has_column(doctype, 'customer'):
- items = frappe.get_all(doctype)
- for i, doc in enumerate(items):
- doc = frappe.get_doc(doctype, doc.name)
- dirty = False
- for field in map_fields:
- if doc.get(field[1]):
- doc.append('links', dict(link_doctype=field[0], link_name=doc.get(field[1])))
- dirty = True
-
- if dirty:
- deduplicate_dynamic_links(doc)
- doc.update_children()
-
- update_progress_bar('Updating {0}'.format(doctype), i, len(items))
- print
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/delete_fleet_management_module_def.py b/erpnext/patches/v7_2/delete_fleet_management_module_def.py
deleted file mode 100644
index 542ac11e3f..0000000000
--- a/erpnext/patches/v7_2/delete_fleet_management_module_def.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists('Module Def', 'Fleet Management'):
- frappe.db.sql("""delete from `tabModule Def`
- where module_name = 'Fleet Management'""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py b/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py
deleted file mode 100644
index ec6f8afc3a..0000000000
--- a/erpnext/patches/v7_2/empty_supplied_items_for_non_subcontracted.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]:
- child_table = 'Purchase Receipt Item Supplied' if doctype != 'Purchase Order' else 'Purchase Order Item Supplied'
- for data in frappe.db.sql(""" select distinct `tab{doctype}`.name from `tab{doctype}` , `tab{child_table}`
- where `tab{doctype}`.name = `tab{child_table}`.parent and `tab{doctype}`.docstatus != 2
- and `tab{doctype}`.is_subcontracted = 'No' """.format(doctype = doctype, child_table = child_table), as_dict=1):
- frappe.db.sql(""" delete from `tab{child_table}`
- where parent = %s and parenttype = %s""".format(child_table= child_table), (data.name, doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/make_all_assessment_group.py b/erpnext/patches/v7_2/make_all_assessment_group.py
deleted file mode 100644
index f3ec628374..0000000000
--- a/erpnext/patches/v7_2/make_all_assessment_group.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists({"doctype": "Assessment Group","assessment_group_name": "All Assessment Groups"}):
- frappe.reload_doc("education", "doctype", "assessment_group")
- doc = frappe.new_doc("Assessment Group")
- doc.assessment_group_name = "All Assessment Groups"
- doc.is_group = 1
- doc.flags.ignore_mandatory = True
- doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/mark_students_active.py b/erpnext/patches/v7_2/mark_students_active.py
deleted file mode 100644
index 7289e4a915..0000000000
--- a/erpnext/patches/v7_2/mark_students_active.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc('schools', 'doctype', 'student_group_student')
-
- frappe.reload_doc('education', 'doctype', 'student_group_student')
- frappe.db.sql("update `tabStudent Group Student` set active=1")
diff --git a/erpnext/patches/v7_2/rename_att_date_attendance.py b/erpnext/patches/v7_2/rename_att_date_attendance.py
deleted file mode 100644
index 7f06d8f123..0000000000
--- a/erpnext/patches/v7_2/rename_att_date_attendance.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import update_reports, update_users_report_view_settings, update_property_setters
-
-def execute():
- if "att_date" not in frappe.db.get_table_columns("Attendance"):
- return
- frappe.reload_doc("hr", "doctype", "attendance")
- frappe.db.sql("""update `tabAttendance`
- set attendance_date = att_date
- where attendance_date is null or attendance_date = '0000-00-00'""")
-
- update_reports("Attendance", "att_date", "attendance_date")
- update_users_report_view_settings("Attendance", "att_date", "attendance_date")
- update_property_setters("Attendance", "att_date", "attendance_date")
diff --git a/erpnext/patches/v7_2/rename_evaluation_criteria.py b/erpnext/patches/v7_2/rename_evaluation_criteria.py
deleted file mode 100644
index c6520b1b72..0000000000
--- a/erpnext/patches/v7_2/rename_evaluation_criteria.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- # 'Schools' module changed to the 'Education'
-
-
- frappe.rename_doc("DocType", "Evaluation Criteria", "Assessment Criteria", force=True)
- # frappe.reload_doc("schools", "doctype", "assessment_criteria")
- frappe.reload_doc("education", "doctype", "assessment_criteria")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Criteria'):
- rename_field("Assessment Criteria", "evaluation_criteria", "assessment_criteria")
-
- frappe.rename_doc("DocType", "Assessment Evaluation Criteria", "Assessment Plan Criteria", force=True)
- # frappe.reload_doc("schools", "doctype", "assessment_plan_criteria")
- frappe.reload_doc("education", "doctype", "assessment_plan_criteria")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Plan'):
- rename_field("Assessment Plan Criteria", "evaluation_criteria", "assessment_criteria")
-
- # frappe.reload_doc("schools", "doctype", "assessment_plan")
- frappe.reload_doc("education", "doctype", "assessment_plan")
- rename_field("Assessment Plan", "evaluation_criterias", "assessment_criteria")
-
- # frappe.reload_doc("schools", "doctype", "assessment_result_detail")
- frappe.reload_doc("education", "doctype", "assessment_result_detail")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Assessment Result Detail'):
- rename_field("Assessment Result Detail", "evaluation_criteria", "assessment_criteria")
-
- frappe.rename_doc("DocType", "Course Evaluation Criteria", "Course Assessment Criteria", force=True)
- # frappe.reload_doc("schools", "doctype", "course_assessment_criteria")
- frappe.reload_doc("education", "doctype", "course_assessment_criteria")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Course Assessment Criteria'):
- rename_field("Course Assessment Criteria", "evaluation_criteria", "assessment_criteria")
-
- # frappe.reload_doc("schools", "doctype", "course")
- frappe.reload_doc("education", "doctype", "course")
- if 'evaluation_criteria' in frappe.db.get_table_columns('Course'):
- rename_field("Course", "evaluation_criterias", "assessment_criteria")
diff --git a/erpnext/patches/v7_2/set_null_value_to_fields.py b/erpnext/patches/v7_2/set_null_value_to_fields.py
deleted file mode 100644
index 6388be438d..0000000000
--- a/erpnext/patches/v7_2/set_null_value_to_fields.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- fields = {"Cost Center": "project", "Project": "cost_center"}
- for budget_against, field in fields.items():
- frappe.db.sql(""" update `tabBudget` set {field} = null
- where budget_against = %s """.format(field = field), budget_against)
diff --git a/erpnext/patches/v7_2/setup_auto_close_settings.py b/erpnext/patches/v7_2/setup_auto_close_settings.py
deleted file mode 100644
index 4eef2b9c8a..0000000000
--- a/erpnext/patches/v7_2/setup_auto_close_settings.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # update the selling settings and set the close_opportunity_after_days
- frappe.reload_doc("selling", "doctype", "selling_settings")
- frappe.db.set_value("Selling Settings", "Selling Settings", "close_opportunity_after_days", 15)
-
- # Auto close Replied opportunity
- frappe.db.sql("""update `tabOpportunity` set status='Closed' where status='Replied'
- and date_sub(curdate(), interval 15 Day)>modified""")
-
- # create Support Settings doctype and update close_issue_after_days
- frappe.reload_doc("support", "doctype", "support_settings")
- frappe.db.set_value("Support Settings", "Support Settings", "close_issue_after_days", 7)
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/stock_uom_in_selling.py b/erpnext/patches/v7_2/stock_uom_in_selling.py
deleted file mode 100644
index d029555747..0000000000
--- a/erpnext/patches/v7_2/stock_uom_in_selling.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Sales Order')
- frappe.reload_doctype('Sales Invoice')
- frappe.reload_doctype('Quotation')
- frappe.reload_doctype('Delivery Note')
-
- doctype_list = ['Sales Order Item', 'Delivery Note Item', 'Quotation Item', 'Sales Invoice Item']
-
- for doctype in doctype_list:
- frappe.reload_doctype(doctype)
- frappe.db.sql("""update `tab{doctype}`
- set uom = stock_uom, conversion_factor = 1, stock_qty = qty""".format(doctype=doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_abbr_in_salary_slips.py b/erpnext/patches/v7_2/update_abbr_in_salary_slips.py
deleted file mode 100644
index 57432fe986..0000000000
--- a/erpnext/patches/v7_2/update_abbr_in_salary_slips.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('Payroll', 'doctype', 'Salary Slip')
- if not frappe.db.has_column('Salary Detail', 'abbr'):
- return
-
- salary_details = frappe.db.sql("""select abbr, salary_component, name from `tabSalary Detail`
- where abbr is null or abbr = ''""", as_dict=True)
-
- for salary_detail in salary_details:
- salary_component_abbr = frappe.get_value("Salary Component", salary_detail.salary_component, "salary_component_abbr")
- frappe.db.sql("""update `tabSalary Detail` set abbr = %s where name = %s""",(salary_component_abbr, salary_detail.name))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_assessment_modules.py b/erpnext/patches/v7_2/update_assessment_modules.py
deleted file mode 100644
index 2b5e774d46..0000000000
--- a/erpnext/patches/v7_2/update_assessment_modules.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- #Rename Grading Structure to Grading Scale
- if not frappe.db.exists("DocType", "Grading Scale"):
- frappe.rename_doc("DocType", "Grading Structure", "Grading Scale", force=True)
- if not frappe.db.exists("DocType", "Grading Scale Interval"):
- frappe.rename_doc("DocType", "Grade Interval", "Grading Scale Interval", force=True)
-
- # frappe.reload_doc("schools", "doctype", "grading_scale_interval")
- frappe.reload_doc("education", "doctype", "grading_scale_interval")
- if "to_score" in frappe.db.get_table_columns("Grading Scale Interval"):
- rename_field("Grading Scale Interval", "to_score", "threshold")
-
- if not frappe.db.exists("DocType", "Assessment Plan"):
- frappe.rename_doc("DocType", "Assessment", "Assessment Plan", force=True)
-
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "assessment_plan")
-
- #Rename Assessment Results
- frappe.reload_doc("education", "doctype", "assessment_plan")
- if "grading_structure" in frappe.db.get_table_columns("Assessment Plan"):
- rename_field("Assessment Plan", "grading_structure", "grading_scale")
-
- # frappe.reload_doc("schools", "doctype", "assessment_result")
- # frappe.reload_doc("schools", "doctype", "assessment_result_detail")
- # frappe.reload_doc("schools", "doctype", "assessment_criteria")
- frappe.reload_doc("education", "doctype", "assessment_result")
- frappe.reload_doc("education", "doctype", "assessment_result_detail")
- frappe.reload_doc("education", "doctype", "assessment_criteria")
-
-
- for assessment in frappe.get_all("Assessment Plan",
- fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]):
- for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s",
- assessment.name, as_dict=True):
- if stud_result.result:
- assessment_result = frappe.new_doc("Assessment Result")
- assessment_result.student = stud_result.student
- assessment_result.student_name = stud_result.student_name
- assessment_result.assessment_plan = assessment.name
- assessment_result.grading_scale = assessment.grading_scale
- assessment_result.total_score = stud_result.result
- assessment_result.flags.ignore_validate = True
- assessment_result.flags.ignore_mandatory = True
- assessment_result.save()
-
- frappe.db.sql("""delete from `tabAssessment Result` where parent != '' or parent is not null""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_attendance_docstatus.py b/erpnext/patches/v7_2/update_attendance_docstatus.py
deleted file mode 100644
index a69052657d..0000000000
--- a/erpnext/patches/v7_2/update_attendance_docstatus.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("education", "doctype", "student_attendance")
- frappe.db.sql('''
- update `tabStudent Attendance` set
- docstatus=0
- where
- docstatus=1''')
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_doctype_status.py b/erpnext/patches/v7_2/update_doctype_status.py
deleted file mode 100644
index c66f3f2e73..0000000000
--- a/erpnext/patches/v7_2/update_doctype_status.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctypes = ["Opportunity", "Quotation", "Sales Order", "Sales Invoice", "Purchase Invoice", "Purchase Order", "Delivery Note", "Purchase Receipt"]
- for doctype in doctypes:
- frappe.db.sql(""" update `tab{doctype}` set status = 'Draft'
- where status = 'Cancelled' and docstatus = 0 """.format(doctype = doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_guardian_name_in_student_master.py b/erpnext/patches/v7_2/update_guardian_name_in_student_master.py
deleted file mode 100644
index 9f589ef00e..0000000000
--- a/erpnext/patches/v7_2/update_guardian_name_in_student_master.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "student_guardian")
- frappe.reload_doc("education", "doctype", "student_guardian")
-
- student_guardians = frappe.get_all("Student Guardian", fields=["guardian"])
- for student_guardian in student_guardians:
- guardian_name = frappe.db.get_value("Guardian", student_guardian.guardian, "guardian_name")
- frappe.db.sql("update `tabStudent Guardian` set guardian_name = %s where guardian= %s",
- (guardian_name, student_guardian.guardian))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_party_type.py b/erpnext/patches/v7_2/update_party_type.py
deleted file mode 100644
index 147f5a3643..0000000000
--- a/erpnext/patches/v7_2/update_party_type.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('setup', 'doctype', 'party_type')
- make_party_type()
-
-def make_party_type():
- for party_type in ["Customer", "Supplier", "Employee"]:
- if not frappe.db.get_value("Party Type", party_type):
- doc = frappe.new_doc("Party Type")
- doc.party_type = party_type
- doc.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py
deleted file mode 100644
index 9fcce62d8f..0000000000
--- a/erpnext/patches/v7_2/update_salary_slips.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_month_details
-from frappe.utils import cint
-
-def execute():
- frappe.reload_doc("Payroll", "doctype", "Salary Slip")
- if not frappe.db.has_column('Salary Slip', 'fiscal_year'):
- return
-
- salary_slips = frappe.db.sql("""select month, name, fiscal_year from `tabSalary Slip`
- where (month is not null and month != '') and
- start_date is null and end_date is null and docstatus != 2""", as_dict=True)
-
- for salary_slip in salary_slips:
- if not cint(salary_slip.month):
- continue
- get_start_end_date = get_month_details(salary_slip.fiscal_year, cint(salary_slip.month))
- start_date = get_start_end_date['month_start_date']
- end_date = get_start_end_date['month_end_date']
- frappe.db.sql("""update `tabSalary Slip` set start_date = %s, end_date = %s where name = %s""",
- (start_date, end_date, salary_slip.name))
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/update_website_for_variant.py b/erpnext/patches/v7_2/update_website_for_variant.py
deleted file mode 100644
index e8eef6e7da..0000000000
--- a/erpnext/patches/v7_2/update_website_for_variant.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # variant must have show_in_website = 0
- frappe.reload_doctype('Item')
- frappe.db.sql('''
- update tabItem set
- show_variant_in_website = 1,
- show_in_website = 0
- where
- show_in_website=1
- and ifnull(variant_of, "")!=""''')
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/__init__.py b/erpnext/patches/v8_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v8_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v8_0/addresses_linked_to_lead.py b/erpnext/patches/v8_0/addresses_linked_to_lead.py
deleted file mode 100644
index b5f2234228..0000000000
--- a/erpnext/patches/v8_0/addresses_linked_to_lead.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""UPDATE `tabDynamic Link` SET link_doctype = 'Lead' WHERE link_doctype = 'Load'""")
diff --git a/erpnext/patches/v8_0/change_in_words_varchar_length.py b/erpnext/patches/v8_0/change_in_words_varchar_length.py
deleted file mode 100644
index 68ff95b5ed..0000000000
--- a/erpnext/patches/v8_0/change_in_words_varchar_length.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctypes = frappe.db.sql_list("""select parent from tabDocField where fieldname = 'in_words'""")
-
- for dt in doctypes:
- for fieldname in ("in_words", "base_in_words"):
- frappe.db.sql("alter table `tab{0}` change column `{1}` `{2}` varchar(255)"
- .format(dt, fieldname, fieldname))
-
- frappe.db.sql("""alter table `tabJournal Entry`
- change column `total_amount_in_words` `total_amount_in_words` varchar(255)""")
diff --git a/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py b/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py
deleted file mode 100644
index cf1bc5af05..0000000000
--- a/erpnext/patches/v8_0/create_address_doc_from_address_field_in_company.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # new field address_html is created in place of address field for the company's address in PR #8754 (without patch)
- # so here is the patch for moving the address details in the address doc
- company_list = []
- if 'address' in frappe.db.get_table_columns('Company'):
- company_list = frappe.db.sql('''select name, address from `tabCompany`
- where address is not null and address != ""''', as_dict=1)
-
- for company in company_list:
- add_list = company.address.split(" ")
- if ',' in company.address:
- add_list = company.address.rpartition(',')
- elif ' ' in company.address:
- add_list = company.address.rpartition(' ')
- else:
- add_list = [company.address, None, company.address]
-
- doc = frappe.get_doc({
- "doctype":"Address",
- "address_line1": add_list[0],
- "city": add_list[2],
- "links": [{
- "link_doctype": "Company",
- "link_name": company.name
- }]
- })
- doc.save()
diff --git a/erpnext/patches/v8_0/create_domain_docs.py b/erpnext/patches/v8_0/create_domain_docs.py
deleted file mode 100644
index 3ef4f3c1bb..0000000000
--- a/erpnext/patches/v8_0/create_domain_docs.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-import erpnext
-
-def execute():
- """Create domain documents"""
- frappe.reload_doc("core", "doctype", "domain")
- frappe.reload_doc("core", "doctype", "domain_settings")
- frappe.reload_doc("core", "doctype", "has_domain")
- frappe.reload_doc("core", "doctype", "role")
-
- for domain in ("Distribution", "Manufacturing", "Retail", "Services", "Education"):
- if not frappe.db.exists({"doctype": "Domain", "domain": domain}):
- create_domain(domain)
-
- # set domain in domain settings based on company domain
-
- domains = []
- condition = ""
- company = erpnext.get_default_company()
- if company:
- condition = " and name={0}".format(frappe.db.escape(company))
-
- domains = frappe.db.sql_list("select distinct domain from `tabCompany` where domain != 'Other' {0}".format(condition))
-
- if not domains:
- return
-
- domain_settings = frappe.get_doc("Domain Settings", "Domain Settings")
- checked_domains = [row.domain for row in domain_settings.active_domains]
-
- for domain in domains:
- # check and ignore if the domains is already checked in domain settings
- if domain in checked_domains:
- continue
-
- if not frappe.db.get_value("Domain", domain):
- # user added custom domain in companies domain field
- create_domain(domain)
-
- row = domain_settings.append("active_domains", dict(domain=domain))
-
- domain_settings.save(ignore_permissions=True)
-
-def create_domain(domain):
- # create new domain
-
- doc = frappe.new_doc("Domain")
- doc.domain = domain
- doc.db_update()
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/delete_bin_indexes.py b/erpnext/patches/v8_0/delete_bin_indexes.py
deleted file mode 100644
index 12cacdb952..0000000000
--- a/erpnext/patches/v8_0/delete_bin_indexes.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-# -*- coding: utf-8 -*-
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # delete bin indexes
- unwanted_indexes = ["item_code", "warehouse"]
-
- for k in unwanted_indexes:
- try:
- frappe.db.sql("drop index {0} on `tabBin`".format(k))
- except:
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py b/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
deleted file mode 100644
index 09a78ed3ca..0000000000
--- a/erpnext/patches/v8_0/delete_schools_depricated_doctypes.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ delete doctypes """
-
- if frappe.db.exists("DocType", "Grading Structure"):
- frappe.delete_doc("DocType", "Grading Structure", force=1)
-
- if frappe.db.exists("DocType", "Grade Interval"):
- frappe.delete_doc("DocType", "Grade Interval", force=1)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/disable_instructor_role.py b/erpnext/patches/v8_0/disable_instructor_role.py
deleted file mode 100644
index 4ba78d172c..0000000000
--- a/erpnext/patches/v8_0/disable_instructor_role.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """
- disable the instructor role for companies with domain other than
- Education.
- """
-
- domains = frappe.db.sql_list("select domain from tabCompany")
- if "Education" not in domains:
- if frappe.db.exists("Role", "Instructor"):
- role = frappe.get_doc("Role", "Instructor")
- role.disabled = 1
- role.save(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py b/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py
deleted file mode 100644
index 1088d702dd..0000000000
--- a/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.set_value("Accounts Settings", None,
- "book_asset_depreciation_entry_automatically", 1)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py b/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py
deleted file mode 100644
index 2e7f360c97..0000000000
--- a/erpnext/patches/v8_0/fix_status_for_invoices_with_negative_outstanding.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt, status in [["Sales Invoice", "Credit Note Issued"], ["Purchase Invoice", "Debit Note Issued"]]:
- invoices = frappe.db.sql("""
- select name
- from `tab{0}`
- where
- status = %s
- and outstanding_amount < 0
- and docstatus=1
- and is_return=0
- """.format(dt), status)
-
- for inv in invoices:
- return_inv = frappe.db.sql("""select name from `tab{0}`
- where is_return=1 and return_against=%s and docstatus=1""".format(dt), inv[0])
- if not return_inv:
- frappe.db.sql("update `tab{0}` set status='Paid' where name = %s".format(dt), inv[0])
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py b/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py
deleted file mode 100644
index 9750fb7222..0000000000
--- a/erpnext/patches/v8_0/make_payments_table_blank_for_non_pos_invoice.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Sales Invoice')
-
- frappe.db.sql("""
- delete from
- `tabSales Invoice Payment`
- where
- parent in (select name from `tabSales Invoice` where is_pos = 0)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py b/erpnext/patches/v8_0/merge_student_batch_and_student_group.py
deleted file mode 100644
index fb9021fd68..0000000000
--- a/erpnext/patches/v8_0/merge_student_batch_and_student_group.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import *
-from frappe.model.mapper import get_mapped_doc
-
-
-def execute():
- # for converting student batch into student group
- for doctype in ["Student Group", "Student Group Student", 'Program Enrollment',
- "Student Group Instructor", "Student Attendance", "Student", "Student Batch Name"]:
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", frappe.scrub(doctype))
-
- frappe.reload_doc("education", "doctype", frappe.scrub(doctype))
-
- if frappe.db.table_exists("Student Batch"):
- student_batches = frappe.db.sql('''select name as student_group_name, student_batch_name as batch,
- program, academic_year, academic_term from `tabStudent Batch`''', as_dict=1)
-
- for student_batch in student_batches:
- # create student batch name if does not exists !!
- if student_batch.get("batch") and not frappe.db.exists("Student Batch Name", student_batch.get("batch")):
- frappe.get_doc({
- "doctype": "Student Batch Name",
- "batch_name": student_batch.get("batch")
- }).insert(ignore_permissions=True)
-
- student_batch.update({"doctype":"Student Group", "group_based_on": "Batch"})
- doc = frappe.get_doc(student_batch)
-
- if frappe.db.sql("SHOW COLUMNS FROM `tabStudent Batch Student` LIKE 'active'"):
- cond = ", active"
- else:
- cond = " "
- student_list = frappe.db.sql('''select student, student_name {cond} from `tabStudent Batch Student`
- where parent=%s'''.format(cond=cond), (doc.student_group_name), as_dict=1)
-
- if student_list:
- for i, student in enumerate(student_list):
- student.update({"group_roll_number": i+1})
- doc.extend("students", student_list)
-
- instructor_list = None
- if frappe.db.table_exists("Student Batch Instructor"):
- instructor_list = frappe.db.sql('''select instructor, instructor_name from `tabStudent Batch Instructor`
- where parent=%s''', (doc.student_group_name), as_dict=1)
- if instructor_list:
- doc.extend("instructors", instructor_list)
- doc.save()
-
- # delete the student batch and child-table
- if frappe.db.table_exists("Student Batch"):
- frappe.delete_doc("DocType", "Student Batch", force=1)
- if frappe.db.table_exists("Student Batch Student"):
- frappe.delete_doc("DocType", "Student Batch Student", force=1)
- if frappe.db.table_exists("Student Batch Instructor"):
- frappe.delete_doc("DocType", "Student Batch Instructor", force=1)
-
- # delete the student batch creation tool
- if frappe.db.table_exists("Student Batch Creation Tool"):
- frappe.delete_doc("DocType", "Student Batch Creation Tool", force=1)
-
- # delete the student batch creation tool
- if frappe.db.table_exists("Attendance Tool Student"):
- frappe.delete_doc("DocType", "Attendance Tool Student", force=1)
-
- # change the student batch to student group in the student attendance
- table_columns = frappe.db.get_table_columns("Student Attendance")
- if "student_batch" in table_columns:
- rename_field("Student Attendance", "student_batch", "student_group")
diff --git a/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py b/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py
deleted file mode 100644
index b59d81831f..0000000000
--- a/erpnext/patches/v8_0/move_account_head_from_account_to_warehouse_for_inventory.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Warehouse")
- frappe.db.sql("""
- update
- `tabWarehouse`
- set
- account = (select name from `tabAccount`
- where account_type = 'Stock' and
- warehouse = `tabWarehouse`.name and is_group = 0 limit 1)""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/move_perpetual_inventory_setting.py b/erpnext/patches/v8_0/move_perpetual_inventory_setting.py
deleted file mode 100644
index 78322d4575..0000000000
--- a/erpnext/patches/v8_0/move_perpetual_inventory_setting.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Company')
- enabled = frappe.db.get_single_value("Accounts Settings", "auto_accounting_for_stock") or 0
- for data in frappe.get_all('Company', fields = ["name"]):
- doc = frappe.get_doc('Company', data.name)
- doc.enable_perpetual_inventory = enabled
- doc.db_update()
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py b/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py
deleted file mode 100644
index e517df5fdb..0000000000
--- a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
-
- doc_list = ["Purchase Invoice Item", "Stock Entry Detail", "Delivery Note Item",
- "Purchase Receipt Item", "Sales Invoice Item"]
-
- for doctype in doc_list:
- frappe.reload_doctype(doctype)
- if "is_sample_item" in frappe.db.get_table_columns(doctype):
- rename_field(doctype, "is_sample_item", "allow_zero_valuation_rate")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py b/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py
deleted file mode 100644
index 5ad862a436..0000000000
--- a/erpnext/patches/v8_0/rename_items_in_status_field_of_material_request.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql(
- """
- UPDATE `tabMaterial Request`
- SET status = CASE
- WHEN docstatus = 2 THEN 'Cancelled'
- WHEN docstatus = 0 THEN 'Draft'
- ELSE CASE
- WHEN status = 'Stopped' THEN 'Stopped'
- WHEN status != 'Stopped' AND per_ordered = 0 THEN 'Pending'
- WHEN per_ordered < 100 AND per_ordered > 0 AND status != 'Stopped'
- THEN 'Partially Ordered'
- WHEN per_ordered = 100 AND material_request_type = 'Purchase'
- AND status != 'Stopped' THEN 'Ordered'
- WHEN per_ordered = 100 AND material_request_type = 'Material Transfer'
- AND status != 'Stopped' THEN 'Transferred'
- WHEN per_ordered = 100 AND material_request_type = 'Material Issue'
- AND status != 'Stopped' THEN 'Issued'
- END
- END
- """
- )
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py b/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py
deleted file mode 100644
index 4065438796..0000000000
--- a/erpnext/patches/v8_0/rename_total_margin_to_rate_with_margin.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- """
- Rename Total Margin field to Rate With Margin in
- "Sales Order Item", "Sales Invoice Item", "Delivery Note Item",
- "Quotation Item"
- """
-
- for d in ("Sales Order Item", "Sales Invoice Item",
- "Delivery Note Item", "Quotation Item"):
- frappe.reload_doctype(d)
- rename_field_if_exists(d, "total_margin", "rate_with_margin")
-
-
-def rename_field_if_exists(doctype, old_fieldname, new_fieldname):
- try:
- rename_field(doctype, old_fieldname, new_fieldname)
- except Exception as e:
- if e.args[0] != 1054:
- raise
diff --git a/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py b/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py
deleted file mode 100644
index 3030b8e2f3..0000000000
--- a/erpnext/patches/v8_0/repost_reserved_qty_for_multiple_sales_uom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
-
-def execute():
- for doctype in ("Sales Order Item", "Bin"):
- frappe.reload_doctype(doctype)
-
- repost_for = frappe.db.sql("""select distinct item_code, warehouse
- from `tabSales Order Item` where docstatus=1 and uom != stock_uom and
- exists(select name from tabItem where name=`tabSales Order Item`.item_code and ifnull(is_stock_item, 0)=1)""")
-
- for item_code, warehouse in repost_for:
- update_bin_qty(item_code, warehouse, {
- "reserved_qty": get_reserved_qty(item_code, warehouse)
- })
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py b/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py
deleted file mode 100644
index 60cbb33b80..0000000000
--- a/erpnext/patches/v8_0/revert_manufacturers_table_from_item.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Item Manufacturer"):
- frappe.reload_doctype("Item")
- item_manufacturers = frappe.db.sql("""
- select parent, manufacturer, manufacturer_part_no
- from `tabItem Manufacturer`
- """, as_dict=1)
-
- for im in item_manufacturers:
- frappe.db.sql("""
- update tabItem
- set manufacturer=%s, manufacturer_part_no=%s
- where name=%s
- """, (im.manufacturer, im.manufacturer_part_no, im.parent))
-
- frappe.delete_doc("DocType", "Item Manufacturer")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/save_system_settings.py b/erpnext/patches/v8_0/save_system_settings.py
deleted file mode 100644
index d479ece8a6..0000000000
--- a/erpnext/patches/v8_0/save_system_settings.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cint
-
-def execute():
- """
- save system settings document
- """
-
- frappe.reload_doc("core", "doctype", "system_settings")
- doc = frappe.get_doc("System Settings")
- doc.flags.ignore_mandatory = True
-
- if cint(doc.currency_precision) == 0:
- doc.currency_precision = ''
-
- doc.save(ignore_permissions=True)
diff --git a/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py b/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py
deleted file mode 100644
index 197d6ded61..0000000000
--- a/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
-
-def execute():
- frappe.db.sql("""
- update
- `tabSales Invoice Item`
- set serial_no = NULL
- where
- parent in (select name from `tabSales Invoice` where update_stock = 0 and docstatus = 1)""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/set_project_copied_from.py b/erpnext/patches/v8_0/set_project_copied_from.py
deleted file mode 100644
index d4287978cf..0000000000
--- a/erpnext/patches/v8_0/set_project_copied_from.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Project")
-
- frappe.db.sql('''
- UPDATE `tabProject`
- SET copied_from=name
- WHERE copied_from is NULL
- ''')
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
deleted file mode 100644
index 8a4ef4086b..0000000000
--- a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
-
-def execute():
- """ Set the Serial Numbers in Sales Invoice Item from Delivery Note Item """
-
- frappe.reload_doc("stock", "doctype", "serial_no")
-
- frappe.db.sql(""" update `tabSales Invoice Item` sii inner join
- `tabDelivery Note Item` dni on sii.dn_detail=dni.name and sii.qty=dni.qty
- set sii.serial_no=dni.serial_no where sii.parent IN (select si.name
- from `tabSales Invoice` si where si.update_stock=0 and si.docstatus=1)""")
-
- items = frappe.db.sql(""" select sii.parent, sii.serial_no from `tabSales Invoice Item` sii
- left join `tabSales Invoice` si on sii.parent=si.name
- where si.docstatus=1 and si.update_stock=0""", as_dict=True)
-
- for item in items:
- sales_invoice = item.get("parent", None)
- serial_nos = item.get("serial_no", "")
-
- if not sales_invoice or not serial_nos:
- continue
-
- serial_nos = ["{}".format(frappe.db.escape(no)) for no in serial_nos.split("\n")]
-
- frappe.db.sql("""
- UPDATE
- `tabSerial No`
- SET
- sales_invoice={sales_invoice}
- WHERE
- name in ({serial_nos})
- """.format(
- sales_invoice=frappe.db.escape(sales_invoice),
- serial_nos=",".join(serial_nos)
- )
- )
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_customer_pos_id.py b/erpnext/patches/v8_0/update_customer_pos_id.py
deleted file mode 100644
index a772ae90c5..0000000000
--- a/erpnext/patches/v8_0/update_customer_pos_id.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Customer")
- frappe.db.sql(""" update `tabCustomer` set customer_pos_id = name """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_production_orders.py b/erpnext/patches/v8_0/update_production_orders.py
deleted file mode 100644
index 8e993cc102..0000000000
--- a/erpnext/patches/v8_0/update_production_orders.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # reload schema
- for doctype in ("Work Order", "Work Order Item", "Work Order Operation",
- "BOM Item", "BOM Explosion Item", "BOM"):
- frappe.reload_doctype(doctype)
-
- frappe.reload_doc("stock", "doctype", "item")
- frappe.reload_doc("stock", "doctype", "item_default")
-
- # fetch all draft and submitted work orders
- fields = ["name"]
- if "source_warehouse" in frappe.db.get_table_columns("Work Order"):
- fields.append("source_warehouse")
-
- wo_orders = frappe.get_all("Work Order", filters={"docstatus": ["!=", 2]}, fields=fields)
-
- count = 0
- for p in wo_orders:
- wo_order = frappe.get_doc("Work Order", p.name)
- count += 1
-
- # set required items table
- wo_order.set_required_items()
-
- for item in wo_order.get("required_items"):
- # set source warehouse based on parent
- if not item.source_warehouse and "source_warehouse" in fields:
- item.source_warehouse = wo_order.get("source_warehouse")
- item.db_update()
-
- if wo_order.docstatus == 1:
- # update transferred qty based on Stock Entry, it also updates db
- wo_order.update_transaferred_qty_for_required_items()
-
- # Set status where it was 'Unstopped', as it is deprecated
- if wo_order.status == "Unstopped":
- status = wo_order.get_status()
- wo_order.db_set("status", status)
- elif wo_order.status == "Stopped":
- wo_order.update_reserved_qty_for_production()
-
- if count % 200 == 0:
- frappe.db.commit()
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_sales_cost_in_project.py b/erpnext/patches/v8_0/update_sales_cost_in_project.py
deleted file mode 100644
index 1a29fc4db4..0000000000
--- a/erpnext/patches/v8_0/update_sales_cost_in_project.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("projects", "doctype", "project")
-
- frappe.db.sql("""
- update `tabProject` p
- set total_sales_amount = ifnull((select sum(base_grand_total)
- from `tabSales Order` where project=p.name and docstatus=1), 0)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py b/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py
deleted file mode 100644
index 19d27b206b..0000000000
--- a/erpnext/patches/v8_0/update_status_as_paid_for_completed_expense_claim.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ set status as Paid in Expense Claim if total_sactioned_amount
- and total_amount_reimbursed is equal """
-
- frappe.reload_doctype('Expense Claim')
-
- frappe.db.sql("""
- update
- `tabExpense Claim`
- set status = 'Paid'
- where
- total_sanctioned_amount = total_amount_reimbursed
- """)
diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py
deleted file mode 100644
index 1f937bb8af..0000000000
--- a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('manufacturing', 'doctype', 'bom_item')
- frappe.reload_doc('manufacturing', 'doctype', 'bom_explosion_item')
- frappe.reload_doc('manufacturing', 'doctype', 'bom_scrap_item')
- frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom, conversion_factor = 1")
- frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty")
- if "qty" in frappe.db.get_table_columns("BOM Scrap Item"):
- frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py b/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py
deleted file mode 100644
index be5cf3aed7..0000000000
--- a/erpnext/patches/v8_0/update_stock_qty_value_in_purchase_invoice.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice_item')
- frappe.db.sql("update `tabPurchase Invoice Item` set stock_qty = qty, stock_uom = uom")
\ No newline at end of file
diff --git a/erpnext/patches/v8_0/update_student_groups_from_student_batches.py b/erpnext/patches/v8_0/update_student_groups_from_student_batches.py
deleted file mode 100644
index ae24fe4a14..0000000000
--- a/erpnext/patches/v8_0/update_student_groups_from_student_batches.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import *
-from frappe.model.mapper import get_mapped_doc
-
-
-def execute():
- if frappe.db.table_exists("Student Batch"):
- student_batches = frappe.db.sql('''select name from `tabStudent Batch`''', as_dict=1)
-
- for student_batch in student_batches:
- if frappe.db.exists("Student Group", student_batch.get("name")):
- student_group = frappe.get_doc("Student Group", student_batch.get("name"))
-
- if frappe.db.table_exists("Student Batch Student"):
- current_student_list = frappe.db.sql_list('''select student from `tabStudent Group Student`
- where parent=%s''', (student_group.name))
- batch_student_list = frappe.db.sql_list('''select student from `tabStudent Batch Student`
- where parent=%s''', (student_group.name))
-
- student_list = list(set(batch_student_list)-set(current_student_list))
- if student_list:
- student_group.extend("students", [{"student":d} for d in student_list])
-
- if frappe.db.table_exists("Student Batch Instructor"):
- current_instructor_list = frappe.db.sql_list('''select instructor from `tabStudent Group Instructor`
- where parent=%s''', (student_group.name))
- batch_instructor_list = frappe.db.sql_list('''select instructor from `tabStudent Batch Instructor`
- where parent=%s''', (student_group.name))
-
- instructor_list = list(set(batch_instructor_list)-set(current_instructor_list))
- if instructor_list:
- student_group.extend("instructors", [{"instructor":d} for d in instructor_list])
-
- student_group.save()
diff --git a/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py b/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py
deleted file mode 100644
index a2173048fd..0000000000
--- a/erpnext/patches/v8_0/update_supplier_address_in_stock_entry.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # copy supplier_address to address_display, and set supplier_address to blank
-
- stock_entries = frappe.db.sql(""" select name, purchase_order, supplier_address from `tabStock Entry`
- where ifnull(supplier_address, '') <> ''""", as_dict=True)
-
- frappe.reload_doc('stock', 'doctype', 'stock_entry')
-
- for stock_entry in stock_entries:
- # move supplier address to address_display, and fetch the supplier address from purchase order
-
- se = frappe.get_doc("Stock Entry", stock_entry.get("name"))
- se.address_display = stock_entry.get("supplier_address")
- se.supplier_address = frappe.db.get_value("Purchase Order", stock_entry.get("purchase_order"),"supplier_address") or None
-
- se.db_update()
diff --git a/erpnext/patches/v8_1/__init__.py b/erpnext/patches/v8_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_1/add_hsn_sac_codes.py b/erpnext/patches/v8_1/add_hsn_sac_codes.py
deleted file mode 100644
index 0fce96a8d4..0000000000
--- a/erpnext/patches/v8_1/add_hsn_sac_codes.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.india.setup import setup
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- return
-
- # call setup for india
- setup(patch=True)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py b/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py
deleted file mode 100644
index 4631602606..0000000000
--- a/erpnext/patches/v8_1/add_indexes_in_transaction_doctypes.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for dt in ("Sales Order Item", "Purchase Order Item",
- "Material Request Item", "Work Order Item", "Packed Item"):
- frappe.get_doc("DocType", dt).run_module_method("on_doctype_update")
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py b/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py
deleted file mode 100644
index 4c606af424..0000000000
--- a/erpnext/patches/v8_1/allow_invoice_copy_to_edit_after_submit.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- inv_copy_options = "ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nDUPLICATE FOR SUPPLIER\nTRIPLICATE FOR SUPPLIER"
-
- frappe.db.sql("""update `tabCustom Field` set allow_on_submit=1, options=%s
- where fieldname='invoice_copy' and dt = 'Sales Invoice'
- """, inv_copy_options)
-
- frappe.db.sql("""update `tabCustom Field` set read_only=1
- where fieldname='gst_state_number' and dt = 'Address'
- """)
diff --git a/erpnext/patches/v8_1/delete_deprecated_reports.py b/erpnext/patches/v8_1/delete_deprecated_reports.py
deleted file mode 100644
index 3e0fdee719..0000000000
--- a/erpnext/patches/v8_1/delete_deprecated_reports.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ delete deprecated reports """
-
- reports = [
- "Monthly Salary Register", "Customer Addresses And Contacts",
- "Supplier Addresses And Contacts"
- ]
-
- for report in reports:
- if frappe.db.exists("Report", report):
- check_and_update_auto_email_report(report)
- frappe.db.commit()
-
- frappe.delete_doc("Report", report, ignore_permissions=True)
-
-def check_and_update_auto_email_report(report):
- """ delete or update auto email report for deprecated report """
-
- auto_email_report = frappe.db.get_value("Auto Email Report", {"report": report})
- if not auto_email_report:
- return
-
- if report == "Monthly Salary Register":
- frappe.delete_doc("Auto Email Report", auto_email_report)
-
- elif report in ["Customer Addresses And Contacts", "Supplier Addresses And Contacts"]:
- frappe.db.set_value("Auto Email Report", auto_email_report, "report", report)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/gst_fixes.py b/erpnext/patches/v8_1/gst_fixes.py
deleted file mode 100644
index 34255eb0a4..0000000000
--- a/erpnext/patches/v8_1/gst_fixes.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.custom.doctype.custom_field.custom_field import create_custom_field
-from erpnext.regional.address_template.setup import set_up_address_templates
-
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- return
-
- update_existing_custom_fields()
- add_custom_fields()
- set_up_address_templates(default_country='India')
- frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
-
-
-def update_existing_custom_fields():
- frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC'
- where fieldname='gst_hsn_code' and label='GST HSN Code'
- """)
-
- frappe.db.sql("""update `tabCustom Field` set print_hide = 1
- where fieldname in ('customer_gstin', 'supplier_gstin', 'company_gstin')
- """)
-
- frappe.db.sql("""update `tabCustom Field` set insert_after = 'address_display'
- where fieldname in ('customer_gstin', 'supplier_gstin')
- """)
-
- frappe.db.sql("""update `tabCustom Field` set insert_after = 'company_address_display'
- where fieldname = 'company_gstin'
- """)
-
- frappe.db.sql("""update `tabCustom Field` set insert_after = 'description'
- where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item')
- """)
-
-
-def add_custom_fields():
- hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
- fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
-
- custom_fields = {
- 'Address': [
- dict(fieldname='gst_state_number', label='GST State Number',
- fieldtype='Int', insert_after='gst_state'),
- ],
- 'Sales Invoice': [
- dict(fieldname='invoice_copy', label='Invoice Copy',
- fieldtype='Select', insert_after='project', print_hide=1, allow_on_submit=1,
- options='ORIGINAL FOR RECIPIENT\nDUPLICATE FOR TRANSPORTER\nTRIPLICATE FOR SUPPLIER'),
- ],
- 'Sales Order Item': [hsn_sac_field],
- 'Delivery Note Item': [hsn_sac_field],
- 'Purchase Order Item': [hsn_sac_field],
- 'Purchase Receipt Item': [hsn_sac_field]
- }
-
- for doctype, fields in custom_fields.items():
- for df in fields:
- create_custom_field(doctype, df)
diff --git a/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py b/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py
deleted file mode 100644
index 3962f8f1f2..0000000000
--- a/erpnext/patches/v8_1/remove_sales_invoice_from_returned_serial_no.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Serial No")
-
- frappe.db.sql("""
- update
- `tabSerial No`
- set
- sales_invoice = NULL
- where
- sales_invoice in (select return_against from
- `tabSales Invoice` where docstatus =1 and is_return=1)
- and sales_invoice is not null and sales_invoice !='' """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/removed_report_support_hours.py b/erpnext/patches/v8_1/removed_report_support_hours.py
deleted file mode 100644
index 0936b2231b..0000000000
--- a/erpnext/patches/v8_1/removed_report_support_hours.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql(""" update `tabAuto Email Report` set report = %s
- where name = %s""", ('Support Hour Distribution', 'Support Hours'))
-
- frappe.db.sql(""" update `tabCustom Role` set report = %s
- where report = %s""", ('Support Hour Distribution', 'Support Hours'))
-
- frappe.delete_doc('Report', 'Support Hours')
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
deleted file mode 100644
index af2d28b857..0000000000
--- a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Sales Order")
- frappe.reload_doctype("Sales Order Item")
-
- if "final_delivery_date" in frappe.db.get_table_columns("Sales Order"):
- frappe.db.sql("""
- update `tabSales Order`
- set delivery_date = final_delivery_date
- where (delivery_date is null or delivery_date = '0000-00-00')
- and order_type = 'Sales'""")
-
- frappe.db.sql("""
- update `tabSales Order` so, `tabSales Order Item` so_item
- set so_item.delivery_date = so.delivery_date
- where so.name = so_item.parent
- and so.order_type = 'Sales'
- and (so_item.delivery_date is null or so_item.delivery_date = '0000-00-00')
- and (so.delivery_date is not null and so.delivery_date != '0000-00-00')
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/update_expense_claim_status.py b/erpnext/patches/v8_1/update_expense_claim_status.py
deleted file mode 100644
index 4c1b85a13f..0000000000
--- a/erpnext/patches/v8_1/update_expense_claim_status.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Expense Claim')
-
- for data in frappe.db.sql(""" select name from `tabExpense Claim`
- where (docstatus=1 and total_sanctioned_amount=0 and status = 'Paid') or
- (docstatus = 1 and approval_status = 'Rejected' and total_sanctioned_amount > 0)""", as_dict=1):
- doc = frappe.get_doc('Expense Claim', data.name)
- if doc.approval_status == 'Rejected':
- for d in doc.expenses:
- d.db_set("sanctioned_amount", 0, update_modified = False)
- doc.db_set("total_sanctioned_amount", 0, update_modified = False)
-
- frappe.db.sql(""" delete from `tabGL Entry` where voucher_type = 'Expense Claim'
- and voucher_no = %s""", (doc.name))
-
- doc.set_status()
- doc.db_set("status", doc.status, update_modified = False)
\ No newline at end of file
diff --git a/erpnext/patches/v8_1/update_gst_state.py b/erpnext/patches/v8_1/update_gst_state.py
deleted file mode 100644
index 7aaf2d5ff3..0000000000
--- a/erpnext/patches/v8_1/update_gst_state.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.india import states
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- return
-
- if not frappe.db.get_value("Custom Field", filters={'fieldname':'gst_state'}):
- return
-
- frappe.db.sql("update `tabCustom Field` set options=%s where fieldname='gst_state'", '\n'.join(states))
- frappe.db.sql("update `tabAddress` set gst_state='Chhattisgarh' where gst_state='Chattisgarh'")
- frappe.db.sql("update `tabAddress` set gst_state_number='05' where gst_state='Uttarakhand'")
diff --git a/erpnext/patches/v8_10/__init__.py b/erpnext/patches/v8_10/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_10/change_default_customer_credit_days.py b/erpnext/patches/v8_10/change_default_customer_credit_days.py
deleted file mode 100644
index 992be17da0..0000000000
--- a/erpnext/patches/v8_10/change_default_customer_credit_days.py
+++ /dev/null
@@ -1,89 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- frappe.reload_doc("selling", "doctype", "customer")
- frappe.reload_doc("buying", "doctype", "supplier")
- frappe.reload_doc("setup", "doctype", "supplier_type")
- frappe.reload_doc("accounts", "doctype", "payment_term")
- frappe.reload_doc("accounts", "doctype", "payment_terms_template_detail")
- frappe.reload_doc("accounts", "doctype", "payment_terms_template")
-
- payment_terms = []
- records = []
- for doctype in ("Customer", "Supplier", "Supplier Type"):
- credit_days = frappe.db.sql("""
- SELECT DISTINCT `credit_days`, `credit_days_based_on`, `name`
- from `tab{0}`
- where
- ((credit_days_based_on='Fixed Days' or credit_days_based_on is null)
- and credit_days is not null)
- or credit_days_based_on='Last Day of the Next Month'
- """.format(doctype))
-
- credit_records = ((record[0], record[1], record[2]) for record in credit_days)
- for days, based_on, party_name in credit_records:
- if based_on == "Fixed Days":
- pyt_template_name = 'Default Payment Term - N{0}'.format(days)
- else:
- pyt_template_name = 'Default Payment Term - EO2M'
-
- if not frappe.db.exists("Payment Terms Template", pyt_template_name):
- payment_term = make_payment_term(days, based_on)
- template = make_template(payment_term)
- else:
- template = frappe.get_doc("Payment Terms Template", pyt_template_name)
-
- payment_terms.append('WHEN `name`={0} THEN {1}'.format(frappe.db.escape(party_name), template.template_name))
- records.append(frappe.db.escape(party_name))
-
- begin_query_str = "UPDATE `tab{0}` SET `payment_terms` = CASE ".format(doctype)
- value_query_str = " ".join(payment_terms)
- cond_query_str = " ELSE `payment_terms` END WHERE "
-
- if records:
- frappe.db.sql(
- begin_query_str + value_query_str + cond_query_str + '`name` IN %s',
- (records,)
- )
-
-
-def make_template(payment_term):
- doc = frappe.new_doc('Payment Terms Template Detail')
- doc.payment_term = payment_term.payment_term_name
- doc.due_date_based_on = payment_term.due_date_based_on
- doc.invoice_portion = payment_term.invoice_portion
- doc.description = payment_term.description
- doc.credit_days = payment_term.credit_days
- doc.credit_months = payment_term.credit_months
-
- template = frappe.new_doc('Payment Terms Template')
- template.template_name = 'Default Payment Term - {0}'.format(payment_term.payment_term_name)
- template.append('terms', doc)
- template.save()
-
- return template
-
-
-def make_payment_term(days, based_on):
- based_on_map = {
- 'Fixed Days': 'Day(s) after invoice date',
- 'Last Day of the Next Month': 'Month(s) after the end of the invoice month'
- }
-
- doc = frappe.new_doc('Payment Term')
- doc.due_date_based_on = based_on_map.get(based_on)
- doc.invoice_portion = 100
-
- if based_on == 'Fixed Days':
- doc.credit_days = days
- doc.description = 'Net payable within {0} days'.format(days)
- doc.payment_term_name = 'N{0}'.format(days)
- else:
- doc.credit_months = 1
- doc.description = 'Net payable by the end of next month'
- doc.payment_term_name = 'EO2M'
-
- doc.save()
- return doc
diff --git a/erpnext/patches/v8_3/__init__.py b/erpnext/patches/v8_3/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py b/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py
deleted file mode 100644
index 6c4c6d5bd8..0000000000
--- a/erpnext/patches/v8_3/set_restrict_to_domain_for_module_def.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- """ set the restrict to domain in module def """
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v8_3/update_company_total_sales.py b/erpnext/patches/v8_3/update_company_total_sales.py
deleted file mode 100644
index 78efecb387..0000000000
--- a/erpnext/patches/v8_3/update_company_total_sales.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from erpnext.setup.doctype.company.company import update_company_current_month_sales, update_company_monthly_sales
-
-def execute():
- '''Update company monthly sales history based on sales invoices'''
- frappe.reload_doctype("Company")
- companies = [d['name'] for d in frappe.get_list("Company")]
-
- for company in companies:
- update_company_current_month_sales(company)
- update_company_monthly_sales(company)
diff --git a/erpnext/patches/v8_4/__init__.py b/erpnext/patches/v8_4/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v8_4/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v8_4/make_scorecard_records.py b/erpnext/patches/v8_4/make_scorecard_records.py
deleted file mode 100644
index 73afa277b4..0000000000
--- a/erpnext/patches/v8_4/make_scorecard_records.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
-def execute():
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_variable')
- frappe.reload_doc('buying', 'doctype', 'supplier_scorecard_standing')
- make_default_records()
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/__init__.py b/erpnext/patches/v8_5/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py b/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py
deleted file mode 100644
index 82beba3770..0000000000
--- a/erpnext/patches/v8_5/fix_tax_breakup_for_non_invoice_docs.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from erpnext.regional.india.setup import make_custom_fields
-from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_html
-
-def execute():
- companies = [d.name for d in frappe.get_all('Company', filters = {'country': 'India'})]
- if not companies:
- return
-
- make_custom_fields()
-
- # update invoice copy value
- values = ["Original for Recipient", "Duplicate for Transporter",
- "Duplicate for Supplier", "Triplicate for Supplier"]
- for d in values:
- frappe.db.sql("update `tabSales Invoice` set invoice_copy=%s where invoice_copy=%s", (d, d))
-
- # update tax breakup in transactions made after 1st July 2017
- doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
- "Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
-
- for doctype in doctypes:
- frappe.reload_doctype(doctype)
-
- date_field = "posting_date"
- if doctype in ["Quotation", "Sales Order", "Supplier Quotation", "Purchase Order"]:
- date_field = "transaction_date"
-
- records = [d.name for d in frappe.get_all(doctype, filters={
- "docstatus": ["!=", 2],
- date_field: [">=", "2017-07-01"],
- "company": ["in", companies],
- "total_taxes_and_charges": [">", 0],
- "other_charges_calculation": ""
- })]
- if records:
- frappe.db.sql("""
- update `tab%s Item` dt_item
- set gst_hsn_code = (select gst_hsn_code from tabItem where name=dt_item.item_code)
- where parent in (%s)
- and (gst_hsn_code is null or gst_hsn_code = '')
- """ % (doctype, ', '.join(['%s']*len(records))), tuple(records))
-
- for record in records:
- doc = frappe.get_doc(doctype, record)
- html = get_itemised_tax_breakup_html(doc)
- doc.db_set("other_charges_calculation", html, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/remove_project_type_property_setter.py b/erpnext/patches/v8_5/remove_project_type_property_setter.py
deleted file mode 100644
index 70a08f5377..0000000000
--- a/erpnext/patches/v8_5/remove_project_type_property_setter.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- ps = frappe.db.get_value('Property Setter', dict(doc_type='Project', field_name='project_type',
- property='options'))
- if ps:
- frappe.delete_doc('Property Setter', ps)
-
- project_types = frappe.db.sql_list('select distinct project_type from tabProject')
-
- for project_type in project_types:
- if project_type and not frappe.db.exists("Project Type", project_type):
- p_type = frappe.get_doc({
- "doctype": "Project Type",
- "project_type": project_type
- })
- p_type.insert()
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py b/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py
deleted file mode 100644
index 2d7df4a179..0000000000
--- a/erpnext/patches/v8_5/remove_quotations_route_in_sidebar.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Portal Settings")
-
- frappe.db.sql("""
- delete from
- `tabPortal Menu Item`
- where
- (route = '/quotations' and title = 'Supplier Quotation')
- or (route = '/quotation' and title = 'Quotations')
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/set_default_mode_of_payment.py b/erpnext/patches/v8_5/set_default_mode_of_payment.py
deleted file mode 100644
index 34ecbb0a3c..0000000000
--- a/erpnext/patches/v8_5/set_default_mode_of_payment.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("POS Profile")
- frappe.reload_doctype("Sales Invoice Payment")
-
- frappe.db.sql("""
- update
- `tabSales Invoice Payment`
- set `tabSales Invoice Payment`.default = 1
- where
- `tabSales Invoice Payment`.parenttype = 'POS Profile'
- and `tabSales Invoice Payment`.idx=1""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
deleted file mode 100644
index 2661914401..0000000000
--- a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('POS Profile')
- customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
- if customer_group:
- frappe.db.sql(""" update `tabPOS Profile`
- set customer_group = %s where customer_group is null """, (customer_group))
\ No newline at end of file
diff --git a/erpnext/patches/v8_5/update_existing_data_in_project_type.py b/erpnext/patches/v8_5/update_existing_data_in_project_type.py
deleted file mode 100644
index 497da0602e..0000000000
--- a/erpnext/patches/v8_5/update_existing_data_in_project_type.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("projects", "doctype", "project_type")
- frappe.reload_doc("projects", "doctype", "project")
-
- project_types = ["Internal", "External", "Other"]
-
- for project_type in project_types:
- if not frappe.db.exists("Project Type", project_type):
- p_type = frappe.get_doc({
- "doctype": "Project Type",
- "project_type": project_type
- })
- p_type.insert()
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/__init__.py b/erpnext/patches/v8_6/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py b/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py
deleted file mode 100644
index 014a74abe3..0000000000
--- a/erpnext/patches/v8_6/point_sms_doctype_module_to_frappe_core.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql('''UPDATE `tabDocType` SET module="Core"
- WHERE name IN ("SMS Parameter", "SMS Settings");''')
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/rename_bom_update_tool.py b/erpnext/patches/v8_6/rename_bom_update_tool.py
deleted file mode 100644
index ef5f335e45..0000000000
--- a/erpnext/patches/v8_6/rename_bom_update_tool.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.delete_doc_if_exists("DocType", "BOM Replace Tool")
-
- frappe.reload_doctype("BOM")
- frappe.db.sql("update tabBOM set conversion_rate=1 where conversion_rate is null or conversion_rate=0")
- frappe.db.sql("update tabBOM set set_rate_of_sub_assembly_item_based_on_bom=1")
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
deleted file mode 100644
index db4f94748e..0000000000
--- a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py
+++ /dev/null
@@ -1,11 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # Set write permission to permlevel 1 for sales manager role in Quotation doctype
- frappe.db.sql(""" update `tabCustom DocPerm` set `tabCustom DocPerm`.write = 1
- where `tabCustom DocPerm`.parent = 'Quotation' and `tabCustom DocPerm`.role = 'Sales Manager'
- and `tabCustom DocPerm`.permlevel = 1 """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py
deleted file mode 100644
index 2d46bee7ca..0000000000
--- a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Timesheet')
- company = frappe.get_all('Company')
-
- #Check more than one company exists
- if len(company) > 1:
- frappe.db.sql(""" update `tabTimesheet` set `tabTimesheet`.company =
- (select company from `tabWork Order` where name = `tabTimesheet`.work_order)
- where workn_order is not null and work_order !=''""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_7/__init__.py b/erpnext/patches/v8_7/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_7/fix_purchase_receipt_status.py b/erpnext/patches/v8_7/fix_purchase_receipt_status.py
deleted file mode 100644
index 99ecb44214..0000000000
--- a/erpnext/patches/v8_7/fix_purchase_receipt_status.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # there is no more status called "Submitted", there was an old issue that used
- # to set it as Submitted, fixed in this commit
- frappe.db.sql("""
- update
- `tabPurchase Receipt`
- set
- status = 'To Bill'
- where
- status = 'Submitted'""")
\ No newline at end of file
diff --git a/erpnext/patches/v8_7/make_subscription_from_recurring_data.py b/erpnext/patches/v8_7/make_subscription_from_recurring_data.py
deleted file mode 100644
index 2932749116..0000000000
--- a/erpnext/patches/v8_7/make_subscription_from_recurring_data.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import today
-
-def execute():
- frappe.reload_doc('accounts', 'doctype', 'subscription')
- frappe.reload_doc('selling', 'doctype', 'sales_order')
- frappe.reload_doc('selling', 'doctype', 'quotation')
- frappe.reload_doc('buying', 'doctype', 'purchase_order')
- frappe.reload_doc('buying', 'doctype', 'supplier_quotation')
- frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
- frappe.reload_doc('accounts', 'doctype', 'purchase_invoice')
- frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
- frappe.reload_doc('stock', 'doctype', 'delivery_note')
- frappe.reload_doc('accounts', 'doctype', 'journal_entry')
- frappe.reload_doc('accounts', 'doctype', 'payment_entry')
-
- for doctype in ['Sales Order', 'Sales Invoice', 'Purchase Order', 'Purchase Invoice']:
- date_field = "transaction_date"
- if doctype in ("Sales Invoice", "Purchase Invoice"):
- date_field = "posting_date"
-
- for data in get_data(doctype, date_field):
- make_subscription(doctype, data, date_field)
-
-def get_data(doctype, date_field):
- return frappe.db.sql(""" select name, from_date, end_date, recurring_type, recurring_id,
- next_date, notify_by_email, notification_email_address, recurring_print_format,
- repeat_on_day_of_month, submit_on_creation, docstatus, {0}
- from `tab{1}` where is_recurring = 1 and next_date >= %s and docstatus < 2
- order by next_date desc
- """.format(date_field, doctype), today(), as_dict=1)
-
-def make_subscription(doctype, data, date_field):
- if data.name == data.recurring_id:
- start_date = data.get(date_field)
- else:
- start_date = frappe.db.get_value(doctype, data.recurring_id, date_field)
-
- doc = frappe.get_doc({
- 'doctype': 'Subscription',
- 'reference_doctype': doctype,
- 'reference_document': data.recurring_id,
- 'start_date': start_date,
- 'end_date': data.end_date,
- 'frequency': data.recurring_type,
- 'repeat_on_day': data.repeat_on_day_of_month,
- 'notify_by_email': data.notify_by_email,
- 'recipients': data.notification_email_address,
- 'next_schedule_date': data.next_date,
- 'submit_on_creation': data.submit_on_creation
- }).insert(ignore_permissions=True)
-
- if data.docstatus == 1:
- doc.submit()
\ No newline at end of file
diff --git a/erpnext/patches/v8_8/__init__.py b/erpnext/patches/v8_8/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py b/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py
deleted file mode 100644
index bd25f15d78..0000000000
--- a/erpnext/patches/v8_8/add_new_fields_in_accounts_settings.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- frappe.db.sql(
- "INSERT INTO `tabSingles` (`doctype`, `field`, `value`) VALUES ('Accounts Settings', 'allow_stale', '1'), "
- "('Accounts Settings', 'stale_days', '1')"
- )
diff --git a/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py b/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
deleted file mode 100644
index 5b169cdff2..0000000000
--- a/erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.db.sql("""
- update `tabBOM Item`
- set rate = rate * conversion_factor
- where uom != stock_uom and docstatus < 2
- and conversion_factor not in (0, 1)
- """)
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/__init__.py b/erpnext/patches/v8_9/__init__.py
deleted file mode 100644
index 8b13789179..0000000000
--- a/erpnext/patches/v8_9/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/erpnext/patches/v8_9/add_setup_progress_actions.py b/erpnext/patches/v8_9/add_setup_progress_actions.py
deleted file mode 100644
index 77501073cf..0000000000
--- a/erpnext/patches/v8_9/add_setup_progress_actions.py
+++ /dev/null
@@ -1,47 +0,0 @@
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- """Add setup progress actions"""
- if not frappe.db.exists('DocType', 'Setup Progress') or not frappe.db.exists('DocType', 'Setup Progress Action'):
- return
-
- frappe.reload_doc("setup", "doctype", "setup_progress")
- frappe.reload_doc("setup", "doctype", "setup_progress_action")
-
- actions = [
- {"action_name": "Add Company", "action_doctype": "Company", "min_doc_count": 1, "is_completed": 1,
- "domains": '[]' },
- {"action_name": "Set Sales Target", "action_doctype": "Company", "min_doc_count": 99,
- "action_document": frappe.defaults.get_defaults().get("company") or '',
- "action_field": "monthly_sales_target", "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Customers", "action_doctype": "Customer", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Suppliers", "action_doctype": "Supplier", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Products", "action_doctype": "Item", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Manufacturing", "Services", "Retail", "Distribution"]' },
- {"action_name": "Add Programs", "action_doctype": "Program", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Instructors", "action_doctype": "Instructor", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Courses", "action_doctype": "Course", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Rooms", "action_doctype": "Room", "min_doc_count": 1, "is_completed": 0,
- "domains": '["Education"]' },
- {"action_name": "Add Users", "action_doctype": "User", "min_doc_count": 4, "is_completed": 0,
- "domains": '[]' },
- {"action_name": "Add Letterhead", "action_doctype": "Letter Head", "min_doc_count": 1, "is_completed": 0,
- "domains": '[]' }
- ]
-
- setup_progress = frappe.get_doc("Setup Progress", "Setup Progress")
- setup_progress.actions = []
- for action in actions:
- setup_progress.append("actions", action)
-
- setup_progress.save(ignore_permissions=True)
-
diff --git a/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py b/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py
deleted file mode 100644
index f67af90555..0000000000
--- a/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
- if not company:
- if frappe.db.exists("DocType", "GST Settings"):
- frappe.delete_doc("DocType", "GST Settings")
- frappe.delete_doc("DocType", "GST HSN Code")
-
- for report_name in ('GST Sales Register', 'GST Purchase Register',
- 'GST Itemised Sales Register', 'GST Itemised Purchase Register'):
-
- frappe.delete_doc('Report', report_name)
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py b/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py
deleted file mode 100644
index 808ae6d527..0000000000
--- a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if 'employee' in frappe.db.get_table_columns("Salary Structure"):
- frappe.db.sql("alter table `tabSalary Structure` drop column employee")
diff --git a/erpnext/patches/v8_9/rename_company_sales_target_field.py b/erpnext/patches/v8_9/rename_company_sales_target_field.py
deleted file mode 100644
index 5433eb673e..0000000000
--- a/erpnext/patches/v8_9/rename_company_sales_target_field.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- frappe.reload_doc("setup", "doctype", "company")
- if frappe.db.has_column('Company', 'sales_target'):
- rename_field("Company", "sales_target", "monthly_sales_target")
diff --git a/erpnext/patches/v8_9/set_default_customer_group.py b/erpnext/patches/v8_9/set_default_customer_group.py
deleted file mode 100644
index cbbe09daf5..0000000000
--- a/erpnext/patches/v8_9/set_default_customer_group.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- selling_settings = frappe.get_single('Selling Settings')
- selling_settings.set_default_customer_group_and_territory()
- selling_settings.flags.ignore_mandatory = True
- selling_settings.save()
diff --git a/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py b/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py
deleted file mode 100644
index a550d093fa..0000000000
--- a/erpnext/patches/v8_9/set_default_fields_in_variant_settings.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'item_variant_settings')
- frappe.reload_doc('stock', 'doctype', 'variant_field')
-
- doc = frappe.get_doc('Item Variant Settings')
- doc.set_default_fields()
- doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/set_member_party_type.py b/erpnext/patches/v8_9/set_member_party_type.py
deleted file mode 100644
index 33bbc11a93..0000000000
--- a/erpnext/patches/v8_9/set_member_party_type.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if not frappe.db.exists("Party Type", "Member"):
- frappe.reload_doc("non_profit", "doctype", "member")
- party = frappe.new_doc("Party Type")
- party.party_type = "Member"
- party.save()
diff --git a/erpnext/patches/v8_9/set_print_zero_amount_taxes.py b/erpnext/patches/v8_9/set_print_zero_amount_taxes.py
deleted file mode 100644
index 3c508eaa09..0000000000
--- a/erpnext/patches/v8_9/set_print_zero_amount_taxes.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-from erpnext.setup.install import create_print_zero_amount_taxes_custom_field
-
-def execute():
- frappe.reload_doc('printing', 'doctype', 'print_style')
- frappe.reload_doc('printing', 'doctype', 'print_settings')
- create_print_zero_amount_taxes_custom_field()
\ No newline at end of file
diff --git a/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py b/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py
deleted file mode 100644
index 24e20409c1..0000000000
--- a/erpnext/patches/v8_9/update_billing_gstin_for_indian_account.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- company = frappe.get_all('Company', filters = {'country': 'India'})
-
- if company:
- for doctype in ['Sales Invoice', 'Delivery Note']:
- frappe.db.sql(""" update `tab{0}`
- set billing_address_gstin = (select gstin from `tabAddress`
- where name = customer_address)
- where customer_address is not null and customer_address != ''""".format(doctype))
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/__init__.py b/erpnext/patches/v9_0/__init__.py
deleted file mode 100644
index baffc48825..0000000000
--- a/erpnext/patches/v9_0/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/erpnext/patches/v9_0/add_healthcare_domain.py b/erpnext/patches/v9_0/add_healthcare_domain.py
deleted file mode 100644
index 3c0433b9d4..0000000000
--- a/erpnext/patches/v9_0/add_healthcare_domain.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- domain = 'Healthcare'
- if not frappe.db.exists('Domain', domain):
- frappe.get_doc({
- 'doctype': 'Domain',
- 'domain': domain
- }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py b/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py
deleted file mode 100644
index 8a8c8064dd..0000000000
--- a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.table_exists("POS Profile User"):
- frappe.reload_doc('accounts', 'doctype', 'pos_profile_user')
-
- frappe.db.sql(""" update `tabPOS Profile User`,
- (select `tabPOS Profile User`.name from `tabPOS Profile User`, `tabPOS Profile`
- where `tabPOS Profile`.name = `tabPOS Profile User`.parent
- group by `tabPOS Profile User`.user, `tabPOS Profile`.company) as pfu
- set
- `tabPOS Profile User`.default = 1
- where `tabPOS Profile User`.name = pfu.name""")
- else:
- doctype = 'POS Profile'
- frappe.reload_doc('accounts', 'doctype', doctype)
- frappe.reload_doc('accounts', 'doctype', 'pos_profile_user')
- frappe.reload_doc('accounts', 'doctype', 'pos_item_group')
- frappe.reload_doc('accounts', 'doctype', 'pos_customer_group')
-
- for doc in frappe.get_all(doctype):
- _doc = frappe.get_doc(doctype, doc.name)
- user = frappe.db.get_value(doctype, doc.name, 'user')
-
- if not user: continue
-
- _doc.append('applicable_for_users', {
- 'user': user,
- 'default': 1
- })
-
- _doc.flags.ignore_validate = True
- _doc.flags.ignore_mandatory = True
- _doc.save()
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/copy_old_fees_field_data.py b/erpnext/patches/v9_0/copy_old_fees_field_data.py
deleted file mode 100644
index 14278209c7..0000000000
--- a/erpnext/patches/v9_0/copy_old_fees_field_data.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc("schools", "doctype", "fees")
- frappe.reload_doc("education", "doctype", "fees")
-
- if "total_amount" not in frappe.db.get_table_columns("Fees"):
- return
-
- frappe.db.sql("""update tabFees set grand_total=total_amount where grand_total = 0.0""")
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py b/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py
deleted file mode 100644
index c685bbc681..0000000000
--- a/erpnext/patches/v9_0/remove_non_existing_warehouse_from_stock_settings.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- default_warehouse = frappe.db.get_value("Stock Settings", None, "default_warehouse")
- if default_warehouse:
- if not frappe.db.get_value("Warehouse", {"name": default_warehouse}):
- frappe.db.set_value("Stock Settings", None, "default_warehouse", "")
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/remove_subscription_module.py b/erpnext/patches/v9_0/remove_subscription_module.py
deleted file mode 100644
index 493873f3e8..0000000000
--- a/erpnext/patches/v9_0/remove_subscription_module.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists('Module Def', 'Subscription'):
- frappe.db.sql(""" delete from `tabModule Def` where name = 'Subscription'""")
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/revert_manufacturing_user_role.py b/erpnext/patches/v9_0/revert_manufacturing_user_role.py
deleted file mode 100644
index f38b7f29ce..0000000000
--- a/erpnext/patches/v9_0/revert_manufacturing_user_role.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if 'Manufacturing' in frappe.get_active_domains(): return
-
- role = 'Manufacturing User'
- frappe.db.set_value('Role', role, 'restrict_to_domain', '')
- frappe.db.set_value('Role', role, 'disabled', 0)
-
- users = frappe.get_all('Has Role', filters = {
- 'parenttype': 'User',
- 'role': ('in', ['System Manager', 'Manufacturing Manager'])
- }, fields=['parent'], as_list=1)
-
- for user in users:
- _user = frappe.get_doc('User', user[0])
- _user.append('roles', {
- 'role': role
- })
- _user.flags.ignore_validate = True
- _user.save()
diff --git a/erpnext/patches/v9_0/set_pos_profile_name.py b/erpnext/patches/v9_0/set_pos_profile_name.py
deleted file mode 100644
index a3a9735215..0000000000
--- a/erpnext/patches/v9_0/set_pos_profile_name.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- doctype = 'POS Profile'
- frappe.reload_doctype(doctype)
-
- for pos in frappe.get_all(doctype, filters={'disabled': 0}):
- doc = frappe.get_doc(doctype, pos.name)
-
- if not doc.user: continue
-
- try:
- pos_profile_name = doc.user + ' - ' + doc.company
- doc.flags.ignore_validate = True
- doc.flags.ignore_mandatory = True
- doc.save()
-
- frappe.rename_doc(doctype, doc.name, pos_profile_name, force=True)
- except frappe.LinkValidationError:
- frappe.db.set_value("POS Profile", doc.name, 'disabled', 1)
diff --git a/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py b/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
deleted file mode 100644
index 3d012978fa..0000000000
--- a/erpnext/patches/v9_0/set_schedule_date_for_material_request_and_purchase_order.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- for doctype in ("Material Request", "Purchase Order"):
- frappe.reload_doctype(doctype)
- frappe.reload_doctype(doctype + " Item")
-
- if not frappe.db.has_column(doctype, "schedule_date"):
- continue
-
- #Update only submitted MR
- for record in frappe.get_all(doctype, filters= [["docstatus", "=", 1]], fields=["name"]):
- doc = frappe.get_doc(doctype, record)
- if doc.items:
- if not doc.schedule_date:
- schedule_dates = [d.schedule_date for d in doc.items if d.schedule_date]
- if len(schedule_dates) > 0:
- min_schedule_date = min(schedule_dates)
- frappe.db.set_value(doctype, record,
- "schedule_date", min_schedule_date, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py b/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py
deleted file mode 100644
index 5092695b7d..0000000000
--- a/erpnext/patches/v9_0/set_shipping_type_for_existing_shipping_rules.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype("Shipping Rule")
-
- # default "calculate_based_on"
- frappe.db.sql('''update `tabShipping Rule`
- set calculate_based_on = "Net Weight"
- where ifnull(calculate_based_on, '') = '' ''')
-
- # default "shipping_rule_type"
- frappe.db.sql('''update `tabShipping Rule`
- set shipping_rule_type = "Selling"
- where ifnull(shipping_rule_type, '') = '' ''')
diff --git a/erpnext/patches/v9_0/set_uoms_in_variant_field.py b/erpnext/patches/v9_0/set_uoms_in_variant_field.py
deleted file mode 100644
index 9e783d99be..0000000000
--- a/erpnext/patches/v9_0/set_uoms_in_variant_field.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-
-def execute():
- doc = frappe.get_doc('Item Variant Settings')
- variant_field_names = [vf.field_name for vf in doc.fields]
- if 'uoms' not in variant_field_names:
- doc.append(
- 'fields', {
- 'field_name': 'uoms'
- }
- )
- doc.save()
diff --git a/erpnext/patches/v9_0/set_variant_item_description.py b/erpnext/patches/v9_0/set_variant_item_description.py
deleted file mode 100644
index 82d6148508..0000000000
--- a/erpnext/patches/v9_0/set_variant_item_description.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import cstr
-
-def execute():
- '''
- Issue:
- While copying data from template item to variant item,
- the system appending description multiple times to the respective variant.
-
- Purpose:
- Check variant description,
- if variant have user defined description remove all system appended descriptions
- else replace multiple system generated descriptions with single description
-
- Steps:
- 1. Get all variant items
- 2. Create system generated variant description
- 3. If variant have user defined description, remove all system generated descriptions
- 4. If variant description only contains system generated description,
- replace multiple descriptions by new description.
- '''
- for item in frappe.db.sql(""" select name from tabItem
- where ifnull(variant_of, '') != '' """,as_dict=1):
- variant = frappe.get_doc("Item", item.name)
- temp_variant_description = '\n'
-
- if variant.attributes:
- for d in variant.attributes:
- temp_variant_description += "
" + d.attribute + ": " + cstr(d.attribute_value) + "
"
-
- variant_description = variant.description.replace(temp_variant_description, '').rstrip()
- if variant_description:
- splitted_desc = variant.description.strip().split(temp_variant_description)
-
- if len(splitted_desc) > 2:
- if splitted_desc[0] == '':
- variant_description = temp_variant_description + variant_description
- elif splitted_desc[1] == '' or splitted_desc[1] == '\n':
- variant_description += temp_variant_description
- variant.db_set('description', variant_description, update_modified=False)
- else:
- variant.db_set('description', variant_description, update_modified=False)
-
- else:
- variant.db_set('description', temp_variant_description, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v9_0/student_admission_childtable_migrate.py b/erpnext/patches/v9_0/student_admission_childtable_migrate.py
deleted file mode 100644
index a5712c76dc..0000000000
--- a/erpnext/patches/v9_0/student_admission_childtable_migrate.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- # 'Schools' module changed to the 'Education'
- # frappe.reload_doc('schools', 'doctype', 'Student Admission Program')
- # frappe.reload_doc('schools', 'doctype', 'student_admission')
- frappe.reload_doc('education', 'doctype', 'Student Admission Program')
- frappe.reload_doc('education', 'doctype', 'student_admission')
-
- if "program" not in frappe.db.get_table_columns("Student Admission"):
- return
-
- student_admissions = frappe.get_all("Student Admission", fields=["name", "application_fee", \
- "naming_series_for_student_applicant", "program", "introduction", "eligibility"])
- for student_admission in student_admissions:
- doc = frappe.get_doc("Student Admission", student_admission.name)
- doc.append("program_details", {
- "program": student_admission.get("program"),
- "application_fee": student_admission.get("application_fee"),
- "applicant_naming_series": student_admission.get("naming_series_for_student_applicant"),
- })
- if student_admission.eligibility and student_admission.introduction:
- doc.introduction = student_admission.introduction + "
" + \
- student_admission.eligibility + "
"
- doc.flags.ignore_validate = True
- doc.flags.ignore_mandatory = True
- doc.save()
diff --git a/erpnext/patches/v9_0/update_employee_loan_details.py b/erpnext/patches/v9_0/update_employee_loan_details.py
deleted file mode 100644
index ef8d32855f..0000000000
--- a/erpnext/patches/v9_0/update_employee_loan_details.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc('Payroll', 'doctype', 'salary_slip_loan')
- frappe.reload_doc('Payroll', 'doctype', 'salary_slip')
-
- for data in frappe.db.sql(""" select name,
- start_date, end_date, total_loan_repayment
- from
- `tabSalary Slip`
- where
- docstatus < 2 and ifnull(total_loan_repayment, 0) > 0""", as_dict=1):
- salary_slip = frappe.get_doc('Salary Slip', data.name)
- salary_slip.set_loan_repayment()
-
- if salary_slip.total_loan_repayment == data.total_loan_repayment:
- for row in salary_slip.loans:
- row.db_update()
-
- salary_slip.db_update()
diff --git a/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py b/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py
deleted file mode 100644
index 45610ed5a7..0000000000
--- a/erpnext/patches/v9_0/update_multi_uom_fields_in_material_request.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doctype('Material Request')
- frappe.reload_doctype('Material Request Item')
-
- frappe.db.sql(""" update `tabMaterial Request Item`
- set stock_uom = uom, stock_qty = qty, conversion_factor = 1.0""")
\ No newline at end of file
diff --git a/erpnext/patches/v9_1/__init__.py b/erpnext/patches/v9_1/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v9_1/create_issue_opportunity_type.py b/erpnext/patches/v9_1/create_issue_opportunity_type.py
deleted file mode 100644
index aa8bbd1e79..0000000000
--- a/erpnext/patches/v9_1/create_issue_opportunity_type.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (c) 2017, Frappe and Contributors
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-
-def execute():
- # delete custom field if exists
- for doctype, fieldname in (('Issue', 'issue_type'), ('Opportunity', 'opportunity_type')):
- custom_field = frappe.db.get_value("Custom Field", {"fieldname": fieldname, 'dt': doctype})
- if custom_field:
- frappe.delete_doc("Custom Field", custom_field, ignore_permissions=True)
-
- frappe.reload_doc('support', 'doctype', 'issue_type')
- frappe.reload_doc('support', 'doctype', 'issue')
- frappe.reload_doc('crm', 'doctype', 'opportunity_type')
- frappe.reload_doc('crm', 'doctype', 'opportunity')
-
- # rename enquiry_type -> opportunity_type
- from frappe.model.utils.rename_field import rename_field
- rename_field('Opportunity', 'enquiry_type', 'opportunity_type')
-
- # create values if already set
- for opts in (('Issue', 'issue_type', 'Issue Type'),
- ('Opportunity', 'opportunity_type', 'Opportunity Type')):
- for d in frappe.db.sql('select distinct {0} from `tab{1}`'.format(opts[1], opts[0])):
- if d[0] and not frappe.db.exists(opts[2], d[0]):
- frappe.get_doc(dict(doctype = opts[2], name=d[0])).insert()
-
- # fixtures
- for name in ('Hub', _('Sales'), _('Support'), _('Maintenance')):
- if not frappe.db.exists('Opportunity Type', name):
- frappe.get_doc(dict(doctype = 'Opportunity Type', name=name)).insert()
diff --git a/erpnext/patches/v9_2/__init__.py b/erpnext/patches/v9_2/__init__.py
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py b/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py
deleted file mode 100644
index 54ae18b8e2..0000000000
--- a/erpnext/patches/v9_2/delete_healthcare_domain_default_items.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.utils import getdate
-
-def execute():
- domain_settings = frappe.get_doc('Domain Settings')
- active_domains = [d.domain for d in domain_settings.active_domains]
-
- if "Healthcare" not in active_domains:
- items = ["TTT", "MCH", "LDL", "GTT", "HDL", "BILT", "BILD", "BP", "BS"]
- for item_code in items:
- try:
- item = frappe.db.get_value("Item", {"item_code": item_code}, ["name", "creation"], as_dict=1)
- if item and getdate(item.creation) >= getdate("2017-11-10"):
- frappe.delete_doc("Item", item.name)
- except:
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v9_2/delete_process_payroll.py b/erpnext/patches/v9_2/delete_process_payroll.py
deleted file mode 100644
index 91c49f577f..0000000000
--- a/erpnext/patches/v9_2/delete_process_payroll.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.delete_doc("DocType", "Process Payroll")
diff --git a/erpnext/patches/v9_2/remove_company_from_patient.py b/erpnext/patches/v9_2/remove_company_from_patient.py
deleted file mode 100644
index 1a50088f23..0000000000
--- a/erpnext/patches/v9_2/remove_company_from_patient.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- if frappe.db.exists("DocType", "Patient"):
- if 'company' in frappe.db.get_table_columns("Patient"):
- frappe.db.sql("alter table `tabPatient` drop column company")
diff --git a/erpnext/patches/v9_2/rename_net_weight_in_item_master.py b/erpnext/patches/v9_2/rename_net_weight_in_item_master.py
deleted file mode 100644
index cad979deab..0000000000
--- a/erpnext/patches/v9_2/rename_net_weight_in_item_master.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe.model.utils.rename_field import rename_field
-
-def execute():
- frappe.reload_doc("stock", "doctype", "item")
- if frappe.db.has_column('Item', 'net_weight'):
- rename_field("Item", "net_weight", "weight_per_unit")
diff --git a/erpnext/patches/v9_2/rename_translated_domains_in_en.py b/erpnext/patches/v9_2/rename_translated_domains_in_en.py
deleted file mode 100644
index e5a9e2461f..0000000000
--- a/erpnext/patches/v9_2/rename_translated_domains_in_en.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-from frappe import _
-from frappe.model.rename_doc import rename_doc
-
-def execute():
- frappe.reload_doc('stock', 'doctype', 'item')
- language = frappe.get_single("System Settings").language
-
- if language and language.startswith('en'): return
-
- frappe.local.lang = language
-
- all_domains = frappe.get_hooks("domains")
-
- for domain in all_domains:
- translated_domain = _(domain, lang=language)
- if frappe.db.exists("Domain", translated_domain):
- #if domain already exists merged translated_domain and domain
- merge = False
- if frappe.db.exists("Domain", domain):
- merge=True
-
- rename_doc("Domain", translated_domain, domain, ignore_permissions=True, merge=merge)
-
- domain_settings = frappe.get_single("Domain Settings")
- active_domains = [d.domain for d in domain_settings.active_domains]
-
- try:
- for domain in active_domains:
- domain = frappe.get_doc("Domain", domain)
- domain.setup_domain()
-
- if int(frappe.db.get_single_value('System Settings', 'setup_complete')):
- domain.setup_sidebar_items()
- domain.setup_desktop_icons()
- domain.set_default_portal_role()
- except frappe.LinkValidationError:
- pass
\ No newline at end of file
diff --git a/erpnext/patches/v9_2/repost_reserved_qty_for_production.py b/erpnext/patches/v9_2/repost_reserved_qty_for_production.py
deleted file mode 100644
index 040e655bd8..0000000000
--- a/erpnext/patches/v9_2/repost_reserved_qty_for_production.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
- frappe.reload_doc("stock", "doctype", "bin")
- bins = frappe.db.sql("select name from `tabBin` where reserved_qty_for_production > 0")
- for d in bins:
- bin_doc = frappe.get_doc("Bin", d[0])
- bin_doc.update_reserved_qty_for_production()
diff --git a/erpnext/patches/v9_2/set_item_name_in_production_order.py b/erpnext/patches/v9_2/set_item_name_in_production_order.py
deleted file mode 100644
index 1f490e62c8..0000000000
--- a/erpnext/patches/v9_2/set_item_name_in_production_order.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import unicode_literals
-import frappe
-
-def execute():
-
- frappe.db.sql("""
- update `tabBOM Item` bom, `tabWork Order Item` po_item
- set po_item.item_name = bom.item_name,
- po_item.description = bom.description
- where po_item.item_code = bom.item_code
- and (po_item.item_name is null or po_item.description is null)
- """)
From 3dfbfe87e9e67a3605cf6f92c05a63455fd1bff1 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 11:47:09 +0530
Subject: [PATCH 203/262] chore: Drop < v10 patches from list
v7 backup was restored and upgraded to latest v10.x.x branch. The patches run uptil the upgrade are removed in this change. This means only existing v10 sites are allowed direct upgrade to v13 and newer
There are older version patches still left since they're being used in later ERPNext versions too.
---
erpnext/patches.txt | 495 --------------------------------------------
1 file changed, 495 deletions(-)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 93689a0ef3..ed6fefdd87 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -1,494 +1,19 @@
-execute:import unidecode # new requirement
-erpnext.patches.v8_0.move_perpetual_inventory_setting
-erpnext.patches.v8_9.set_print_zero_amount_taxes
erpnext.patches.v12_0.update_is_cancelled_field
erpnext.patches.v11_0.rename_production_order_to_work_order
erpnext.patches.v11_0.refactor_naming_series
erpnext.patches.v11_0.refactor_autoname_naming
-erpnext.patches.v10_0.rename_schools_to_education
-erpnext.patches.v4_0.validate_v3_patch
-erpnext.patches.v4_0.fix_employee_user_id
-erpnext.patches.v4_0.remove_employee_role_if_no_employee
-erpnext.patches.v4_0.update_user_properties
-erpnext.patches.v4_0.apply_user_permissions
-erpnext.patches.v4_0.move_warehouse_user_to_restrictions
-erpnext.patches.v4_0.global_defaults_to_system_settings
-erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28
execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16 #2020-07-24
-execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24
-execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31
-execute:frappe.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-29
-execute:frappe.reload_doc('selling', 'doctype', 'quotation') # 2014-01-29
-execute:frappe.reload_doc('stock', 'doctype', 'delivery_note') # 2014-01-29
-erpnext.patches.v4_0.reload_sales_print_format
-execute:frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') # 2014-01-29
-execute:frappe.reload_doc('buying', 'doctype', 'purchase_order') # 2014-01-29
-execute:frappe.reload_doc('buying', 'doctype', 'supplier_quotation') # 2014-01-29
-execute:frappe.reload_doc('stock', 'doctype', 'purchase_receipt') # 2014-01-29
-execute:frappe.reload_doc('accounts', 'doctype', 'pos_setting') # 2014-01-29
-execute:frappe.reload_doc('selling', 'doctype', 'customer') # 2014-01-29
-execute:frappe.reload_doc('buying', 'doctype', 'supplier') # 2014-01-29
-execute:frappe.reload_doc('accounts', 'doctype', 'asset_category')
-execute:frappe.reload_doc('accounts', 'doctype', 'pricing_rule')
-erpnext.patches.v4_0.map_charge_to_taxes_and_charges
-execute:frappe.reload_doc('support', 'doctype', 'newsletter') # 2014-01-31
-execute:frappe.reload_doc('hr', 'doctype', 'employee') # 2014-02-03
-execute:frappe.db.sql("update tabPage set module='Core' where name='Setup'")
-erpnext.patches.v5_2.change_item_selects_to_checks
-execute:frappe.reload_doctype('Item')
-erpnext.patches.v4_0.fields_to_be_renamed
-erpnext.patches.v4_0.rename_sitemap_to_route
-erpnext.patches.v7_0.re_route #2016-06-27
-erpnext.patches.v4_0.fix_contact_address
-erpnext.patches.v4_0.customer_discount_to_pricing_rule
-execute:frappe.db.sql("""delete from `tabWebsite Item Group` where ifnull(item_group, '')=''""")
-erpnext.patches.v4_0.remove_module_home_pages
-erpnext.patches.v4_0.split_email_settings
-erpnext.patches.v4_0.import_country_codes
-erpnext.patches.v4_0.countrywise_coa
-execute:frappe.delete_doc("DocType", "MIS Control")
-execute:frappe.delete_doc("Page", "Financial Statements")
-execute:frappe.delete_doc("DocType", "Stock Ledger")
-execute:frappe.delete_doc("DocType", "Grade")
-execute:frappe.db.sql("delete from `tabWebsite Item Group` where ifnull(item_group, '')=''")
-execute:frappe.delete_doc("Print Format", "SalesInvoice")
-execute:import frappe.defaults;frappe.defaults.clear_default("price_list_currency")
-erpnext.patches.v4_0.update_account_root_type
-execute:frappe.delete_doc("Report", "Purchase In Transit")
-erpnext.patches.v4_0.new_address_template
-execute:frappe.delete_doc("DocType", "SMS Control")
-execute:frappe.delete_doc_if_exists("DocType", "Bulk SMS") #2015-08-18
-erpnext.patches.v4_0.fix_case_of_hr_module_def
-erpnext.patches.v4_0.fix_address_template
-
-# WATCHOUT: This patch reload's documents
-erpnext.patches.v4_0.reset_permissions_for_masters
-erpnext.patches.v6_20x.rename_project_name_to_project #2016-03-14
-
-erpnext.patches.v4_0.update_tax_amount_after_discount
-execute:frappe.permissions.reset_perms("GL Entry") #2014-06-09
-execute:frappe.permissions.reset_perms("Stock Ledger Entry") #2014-06-09
-erpnext.patches.v4_0.create_custom_fields_for_india_specific_fields
-erpnext.patches.v4_0.save_default_letterhead
-erpnext.patches.v4_0.update_custom_print_formats_for_renamed_fields
-erpnext.patches.v4_0.update_other_charges_in_custom_purchase_print_formats
-erpnext.patches.v4_0.create_price_list_if_missing
-execute:frappe.db.sql("update `tabItem` set end_of_life=null where end_of_life='0000-00-00'") #2014-06-16
-erpnext.patches.v4_0.update_users_report_view_settings
-erpnext.patches.v4_0.set_pricing_rule_for_buying_or_selling
-erpnext.patches.v4_1.set_outgoing_email_footer
-erpnext.patches.v4_1.fix_sales_order_delivered_status
-erpnext.patches.v4_1.fix_delivery_and_billing_status
-execute:frappe.db.sql("update `tabAccount` set root_type='Liability' where root_type='Income' and report_type='Balance Sheet'")
-execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool") # 29-07-2014
-execute:frappe.delete_doc("DocType", "Payment to Invoice Matching Tool Detail") # 29-07-2014
-execute:frappe.delete_doc("Page", "trial-balance") #2014-07-22
-erpnext.patches.v4_2.delete_old_print_formats #2014-07-29
-erpnext.patches.v4_2.toggle_rounded_total #2014-07-30
-erpnext.patches.v4_2.fix_account_master_type
-erpnext.patches.v4_2.update_project_milestones
-erpnext.patches.v4_2.add_currency_turkish_lira #2014-08-08
-execute:frappe.delete_doc("DocType", "Landed Cost Wizard")
-erpnext.patches.v4_2.default_website_style
-erpnext.patches.v4_2.set_company_country
-erpnext.patches.v4_2.update_sales_order_invoice_field_name
-erpnext.patches.v4_2.seprate_manufacture_and_repack
-execute:frappe.delete_doc("Report", "Warehouse-Wise Stock Balance")
-execute:frappe.delete_doc("DocType", "Purchase Request")
-execute:frappe.delete_doc("DocType", "Purchase Request Item")
-erpnext.patches.v4_2.recalculate_bom_cost
-erpnext.patches.v4_2.fix_gl_entries_for_stock_transactions
erpnext.patches.v4_2.update_requested_and_ordered_qty #2021-03-31
-execute:frappe.rename_doc("DocType", "Support Ticket", "Issue", force=True)
-erpnext.patches.v4_4.make_email_accounts
-execute:frappe.delete_doc("DocType", "Contact Control")
-erpnext.patches.v4_2.discount_amount
-erpnext.patches.v4_2.reset_bom_costs
-erpnext.patches.v5_0.update_frozen_accounts_permission_role
-erpnext.patches.v5_0.update_dn_against_doc_fields
-execute:frappe.db.sql("update `tabMaterial Request` set material_request_type = 'Material Transfer' where material_request_type = 'Transfer'")
-execute:frappe.reload_doc('stock', 'doctype', 'item')
-erpnext.patches.v5_0.set_default_company_in_bom
-execute:frappe.reload_doc('crm', 'doctype', 'lead')
-execute:frappe.reload_doc('crm', 'doctype', 'opportunity')
-erpnext.patches.v5_0.rename_taxes_and_charges_master
-erpnext.patches.v5_1.sales_bom_rename
-erpnext.patches.v5_0.rename_table_fieldnames
-execute:frappe.db.sql("update `tabJournal Entry` set voucher_type='Journal Entry' where ifnull(voucher_type, '')=''")
-erpnext.patches.v5_0.is_group
-erpnext.patches.v4_2.party_model
-erpnext.patches.v5_0.party_model_patch_fix
-erpnext.patches.v4_1.fix_jv_remarks
-erpnext.patches.v4_2.update_landed_cost_voucher
-erpnext.patches.v4_2.set_item_has_batch
-erpnext.patches.v4_2.update_stock_uom_for_dn_in_sle
-erpnext.patches.v5_0.recalculate_total_amount_in_jv
-erpnext.patches.v5_0.update_companywise_payment_account
-erpnext.patches.v5_0.remove_birthday_events
-erpnext.patches.v5_0.update_item_name_in_bom
-erpnext.patches.v5_0.rename_customer_issue
-erpnext.patches.v5_0.rename_total_fields
-erpnext.patches.v5_0.new_crm_module
-erpnext.patches.v5_0.rename_customer_issue
-erpnext.patches.v5_0.update_material_transfer_for_manufacture
-execute:frappe.reload_doc('crm', 'doctype', 'opportunity_item')
-erpnext.patches.v5_0.update_item_description_and_image
-erpnext.patches.v5_0.update_material_transferred_for_manufacturing
-erpnext.patches.v5_0.stock_entry_update_value
-erpnext.patches.v5_0.convert_stock_reconciliation
-erpnext.patches.v5_0.update_projects
-erpnext.patches.v5_0.item_patches
-erpnext.patches.v5_0.update_journal_entry_title
-erpnext.patches.v5_0.taxes_and_totals_in_party_currency
-erpnext.patches.v5_0.replace_renamed_fields_in_custom_scripts_and_print_formats
-erpnext.patches.v5_0.update_from_bom
-erpnext.patches.v5_0.update_account_types
-erpnext.patches.v5_0.update_sms_sender
-erpnext.patches.v5_0.set_appraisal_remarks
-erpnext.patches.v5_0.update_time_log_title
-erpnext.patches.v7_0.create_warehouse_nestedset
-erpnext.patches.v7_0.merge_account_type_stock_and_warehouse_to_stock
-erpnext.patches.v7_0.set_is_group_for_warehouse
-erpnext.patches.v7_2.stock_uom_in_selling
-erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse
-erpnext.patches.v5_0.newsletter
-execute:frappe.delete_doc("DocType", "Chart of Accounts")
-execute:frappe.delete_doc("DocType", "Style Settings")
-erpnext.patches.v5_0.update_opportunity
-erpnext.patches.v5_0.opportunity_not_submittable
-execute:frappe.permissions.reset_perms("Purchase Taxes and Charges Template") #2014-06-09
-execute:frappe.permissions.reset_perms("Expense Claim Type") #2014-06-19
-erpnext.patches.v5_0.execute_on_doctype_update
-erpnext.patches.v4_2.fix_recurring_orders
-erpnext.patches.v4_2.delete_gl_entries_for_cancelled_invoices
-erpnext.patches.v5_0.project_costing
-erpnext.patches.v5_0.update_temporary_account
-erpnext.patches.v5_0.update_advance_paid
-erpnext.patches.v5_0.link_warehouse_with_account
-execute:frappe.delete_doc("Page", "stock-ledger")
-execute:frappe.delete_doc("Page","stock-level")
-erpnext.patches.v5_0.reclculate_planned_operating_cost_in_production_order
-erpnext.patches.v5_0.repost_requested_qty
-erpnext.patches.v5_0.fix_taxes_and_totals_in_party_currency
-erpnext.patches.v5_0.update_tax_amount_after_discount_in_purchase_cycle
-erpnext.patches.v5_0.rename_pos_setting
-erpnext.patches.v5_0.update_operation_description
-erpnext.patches.v5_0.set_footer_address
-execute:frappe.db.set_value("Backup Manager", None, "send_backups_to_dropbox", 1 if frappe.db.get_value("Backup Manager", None, "upload_backups_to_dropbox") in ("Daily", "Weekly") else 0)
-execute:frappe.db.sql_list("delete from `tabDocPerm` where parent='Issue' and modified_by='Administrator' and role='Guest'")
-erpnext.patches.v5_0.update_item_and_description_again
-erpnext.patches.v6_0.multi_currency
-erpnext.patches.v7_0.create_budget_record
-erpnext.patches.v5_0.repost_gle_for_jv_with_multiple_party
-erpnext.patches.v5_0.portal_fixes
-erpnext.patches.v5_0.reset_values_in_tools # 02-05-2016
-execute:frappe.delete_doc("Page", "users")
-erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
-erpnext.patches.v5_0.index_on_account_and_gl_entry
-execute:frappe.db.sql("""delete from `tabProject Task`""")
-erpnext.patches.v5_0.update_item_desc_in_invoice
-erpnext.patches.v5_1.fix_against_account
-execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
-erpnext.patches.v5_1.rename_roles
-erpnext.patches.v5_1.default_bom
-execute:frappe.delete_doc("DocType", "Party Type")
-execute:frappe.delete_doc("Module Def", "Contacts")
-erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items # 30-07-2015
-execute:frappe.reload_doctype("Leave Type")
-execute:frappe.db.sql("update `tabLeave Type` set include_holiday=0")
-erpnext.patches.v5_4.set_root_and_report_type
-erpnext.patches.v5_4.notify_system_managers_regarding_wrong_tax_calculation
-erpnext.patches.v5_4.fix_invoice_outstanding
-execute:frappe.db.sql("update `tabStock Ledger Entry` set stock_queue = '[]' where voucher_type = 'Stock Reconciliation' and ifnull(qty_after_transaction, 0) = 0")
-erpnext.patches.v5_4.fix_missing_item_images
-erpnext.patches.v5_4.stock_entry_additional_costs
-erpnext.patches.v5_4.cleanup_journal_entry #2015-08-14
erpnext.patches.v5_7.update_item_description_based_on_item_master
-erpnext.patches.v5_7.item_template_attributes
-execute:frappe.delete_doc_if_exists("DocType", "Manage Variants")
-execute:frappe.delete_doc_if_exists("DocType", "Manage Variants Item")
erpnext.patches.v4_2.repost_reserved_qty #2021-03-31
-erpnext.patches.v5_4.update_purchase_cost_against_project
-erpnext.patches.v5_8.update_order_reference_in_return_entries
-erpnext.patches.v5_8.add_credit_note_print_heading
-execute:frappe.delete_doc_if_exists("Print Format", "Credit Note - Negative Invoice")
-
-# V6.0
-erpnext.patches.v6_0.set_default_title # 2015-09-03
-erpnext.patches.v6_0.default_activity_rate
-execute:frappe.db.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1)
-execute:frappe.db.sql("""update `tabProject` set percent_complete=round(percent_complete, 2) where percent_complete is not null""")
-erpnext.patches.v6_0.fix_outstanding_amount
-erpnext.patches.v6_0.fix_planned_qty
-erpnext.patches.v6_2.remove_newsletter_duplicates
-erpnext.patches.v6_2.fix_missing_default_taxes_and_lead
-erpnext.patches.v6_3.convert_applicable_territory
-erpnext.patches.v6_4.round_status_updater_percentages
-erpnext.patches.v6_4.repost_gle_for_journal_entries_where_reference_name_missing
-erpnext.patches.v6_4.fix_journal_entries_due_to_reconciliation
-erpnext.patches.v6_4.fix_status_in_sales_and_purchase_order
-erpnext.patches.v6_4.fix_modified_in_sales_order_and_purchase_order
-erpnext.patches.v6_4.fix_duplicate_bins
-erpnext.patches.v6_4.fix_sales_order_maintenance_status
-erpnext.patches.v6_4.email_digest_update
-
-# delete shopping cart doctypes
-execute:frappe.delete_doc_if_exists("DocType", "Applicable Territory")
-execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Price List")
-execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Taxes and Charges Master")
-
-erpnext.patches.v6_4.set_user_in_contact
-erpnext.patches.v6_4.make_image_thumbnail #2015-10-20
-erpnext.patches.v6_5.show_in_website_for_template_item
-erpnext.patches.v6_4.fix_expense_included_in_valuation
-execute:frappe.delete_doc_if_exists("Report", "Item-wise Last Purchase Rate")
-erpnext.patches.v6_6.fix_website_image
-erpnext.patches.v6_6.remove_fiscal_year_from_leave_allocation
-execute:frappe.delete_doc_if_exists("DocType", "Stock UOM Replace Utility")
-erpnext.patches.v6_8.make_webform_standard #2015-11-23
-erpnext.patches.v6_8.move_drop_ship_to_po_items
-erpnext.patches.v6_10.fix_ordered_received_billed
-erpnext.patches.v6_10.fix_jv_total_amount #2015-11-30
-erpnext.patches.v6_10.email_digest_default_quote
-erpnext.patches.v6_10.fix_billed_amount_in_drop_ship_po
-erpnext.patches.v6_10.fix_delivery_status_of_drop_ship_item #2015-12-08
-erpnext.patches.v5_8.tax_rule #2015-12-08
-erpnext.patches.v6_12.set_overdue_tasks
-erpnext.patches.v6_16.update_billing_status_in_dn_and_pr
-erpnext.patches.v6_16.create_manufacturer_records
-execute:frappe.db.sql("update `tabPricing Rule` set title=name where title='' or title is null") #2016-01-27
-erpnext.patches.v6_20.set_party_account_currency_in_orders
-erpnext.patches.v6_19.comment_feed_communication
-erpnext.patches.v6_21.fix_reorder_level
-erpnext.patches.v6_21.rename_material_request_fields
-erpnext.patches.v6_23.update_stopped_status_to_closed
-erpnext.patches.v6_24.set_recurring_id
-erpnext.patches.v6_20x.set_compact_print
-execute:frappe.delete_doc_if_exists("Web Form", "contact") #2016-03-10
-erpnext.patches.v6_20x.remove_fiscal_year_from_holiday_list
-erpnext.patches.v6_24.map_customer_address_to_shipping_address_on_po
-erpnext.patches.v6_27.fix_recurring_order_status
-erpnext.patches.v6_20x.update_product_bundle_description
-erpnext.patches.v7_0.update_party_status #2016-09-22
-erpnext.patches.v7_0.remove_features_setup
-erpnext.patches.v7_0.update_home_page
-execute:frappe.delete_doc_if_exists("Page", "financial-analytics")
-erpnext.patches.v7_0.update_project_in_gl_entry
-execute:frappe.db.sql('update tabQuotation set status="Cancelled" where docstatus=2')
-execute:frappe.rename_doc("DocType", "Payments", "Sales Invoice Payment", force=True)
-erpnext.patches.v7_0.update_mins_to_first_response
-erpnext.patches.v6_20x.repost_valuation_rate_for_negative_inventory
-erpnext.patches.v7_0.migrate_mode_of_payments_v6_to_v7
-erpnext.patches.v7_0.system_settings_setup_complete
-erpnext.patches.v7_0.set_naming_series_for_timesheet #2016-07-27
-execute:frappe.reload_doc('projects', 'doctype', 'project')
-execute:frappe.reload_doc('projects', 'doctype', 'project_user')
-erpnext.patches.v7_0.convert_timelogbatch_to_timesheet
-erpnext.patches.v7_0.convert_timelog_to_timesheet
-erpnext.patches.v7_0.move_timelogbatch_from_salesinvoiceitem_to_salesinvoicetimesheet
-erpnext.patches.v7_0.remove_doctypes_and_reports #2016-10-29
-erpnext.patches.v7_0.update_maintenance_module_in_doctype
-erpnext.patches.v7_0.update_prevdoc_values_for_supplier_quotation_item
-erpnext.patches.v7_0.rename_advance_table_fields
-erpnext.patches.v7_0.rename_salary_components
-erpnext.patches.v7_0.rename_prevdoc_fields
-erpnext.patches.v7_0.rename_time_sheet_doctype
-execute:frappe.delete_doc_if_exists("Report", "Customers Not Buying Since Long Time")
-erpnext.patches.v7_0.make_is_group_fieldtype_as_check
-execute:frappe.reload_doc('projects', 'doctype', 'timesheet') #2016-09-12
-erpnext.patches.v7_1.rename_field_timesheet
-execute:frappe.delete_doc_if_exists("Report", "Employee Holiday Attendance")
-execute:frappe.delete_doc_if_exists("DocType", "Payment Tool")
-execute:frappe.delete_doc_if_exists("DocType", "Payment Tool Detail")
-erpnext.patches.v7_0.setup_account_table_for_expense_claim_type_if_exists
-erpnext.patches.v7_0.migrate_schools_to_erpnext
-erpnext.patches.v7_1.update_lead_source
-erpnext.patches.v6_20x.remove_customer_supplier_roles
-erpnext.patches.v7_0.remove_administrator_role_in_doctypes
-erpnext.patches.v7_0.rename_fee_amount_to_fee_component
-erpnext.patches.v7_0.calculate_total_costing_amount
-erpnext.patches.v7_0.fix_nonwarehouse_ledger_gl_entries_for_transactions
-erpnext.patches.v7_0.remove_old_earning_deduction_doctypes
-erpnext.patches.v7_0.make_guardian
-erpnext.patches.v7_0.update_refdoc_in_landed_cost_voucher
-erpnext.patches.v7_0.set_material_request_type_in_item
-erpnext.patches.v7_0.rename_examination_to_assessment
-erpnext.patches.v7_0.set_portal_settings
-erpnext.patches.v7_0.update_change_amount_account
-erpnext.patches.v7_0.fix_duplicate_icons
-erpnext.patches.v7_0.repost_gle_for_pos_sales_return
-erpnext.patches.v7_1.update_total_billing_hours
-erpnext.patches.v7_1.update_component_type
-erpnext.patches.v7_0.repost_gle_for_pos_sales_return
-erpnext.patches.v7_0.update_missing_employee_in_timesheet
-erpnext.patches.v7_0.update_status_for_timesheet
-erpnext.patches.v7_0.set_party_name_in_payment_entry
-erpnext.patches.v7_1.set_student_guardian
-erpnext.patches.v7_0.update_conversion_factor_in_supplier_quotation_item
-erpnext.patches.v7_1.move_sales_invoice_from_parent_to_child_timesheet
-execute:frappe.db.sql("update `tabTimesheet` ts, `tabEmployee` emp set ts.employee_name = emp.employee_name where emp.name = ts.employee and ts.employee_name is null and ts.employee is not null")
-erpnext.patches.v7_1.fix_link_for_customer_from_lead
-execute:frappe.db.sql("delete from `tabTimesheet Detail` where NOT EXISTS (select name from `tabTimesheet` where name = `tabTimesheet Detail`.parent)")
-erpnext.patches.v7_0.update_mode_of_payment_type
-
-execute:frappe.reload_doctype('Employee') #2016-10-18
-execute:frappe.db.sql("update `tabEmployee` set prefered_contact_email = IFNULL(prefered_contact_email,'') ")
execute:frappe.reload_doc("Payroll", "doctype", "salary_slip")
-execute:frappe.db.sql("update `tabSalary Slip` set posting_date=creation")
-execute:frappe.reload_doc("stock", "doctype", "stock_settings")
-erpnext.patches.v8_0.create_domain_docs #16-05-2017
-erpnext.patches.v7_1.update_portal_roles
-erpnext.patches.v7_1.set_total_amount_currency_in_je
-finally:erpnext.patches.v7_0.update_timesheet_communications
-erpnext.patches.v7_0.update_status_of_zero_amount_sales_order
-erpnext.patches.v7_1.add_field_for_task_dependent
-erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty
-erpnext.patches.v7_1.set_prefered_contact_email
-execute:frappe.reload_doc('accounts', 'doctype', 'accounts_settings')
-execute:frappe.db.set_value("Accounts Settings", "Accounts Settings", "unlink_payment_on_cancellation_of_invoice", 0)
-execute:frappe.db.sql("update `tabStock Entry` set total_amount = 0 where purpose in('Repack', 'Manufacture')")
-erpnext.patches.v7_1.save_stock_settings
-erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01
-erpnext.patches.v7_1.add_account_user_role_for_timesheet
-erpnext.patches.v7_0.set_base_amount_in_invoice_payment_table
-erpnext.patches.v7_1.update_invoice_status
-erpnext.patches.v7_0.po_status_issue_for_pr_return
-erpnext.patches.v7_1.update_missing_salary_component_type
-erpnext.patches.v7_1.rename_quality_inspection_field
-erpnext.patches.v7_0.update_autoname_field
-erpnext.patches.v7_1.update_bom_base_currency
-erpnext.patches.v7_0.update_status_of_po_so
-erpnext.patches.v7_1.set_budget_against_as_cost_center
-erpnext.patches.v7_1.set_currency_exchange_date
-erpnext.patches.v7_1.set_sales_person_status
-erpnext.patches.v7_1.repost_stock_for_deleted_bins_for_merging_items
-erpnext.patches.v7_2.update_website_for_variant
-erpnext.patches.v7_2.update_assessment_modules
-erpnext.patches.v7_2.update_doctype_status
-erpnext.patches.v7_2.update_salary_slips
-erpnext.patches.v7_2.delete_fleet_management_module_def
-erpnext.patches.v7_2.contact_address_links
-erpnext.patches.v7_2.mark_students_active
-erpnext.patches.v7_2.set_null_value_to_fields
-erpnext.patches.v7_2.update_guardian_name_in_student_master
-erpnext.patches.v7_2.update_abbr_in_salary_slips
-erpnext.patches.v7_2.rename_evaluation_criteria
-erpnext.patches.v7_2.update_party_type
-erpnext.patches.v7_2.setup_auto_close_settings
-erpnext.patches.v7_2.empty_supplied_items_for_non_subcontracted
-erpnext.patches.v7_2.arrear_leave_encashment_as_salary_component
-erpnext.patches.v7_2.rename_att_date_attendance
-erpnext.patches.v7_2.update_attendance_docstatus
-erpnext.patches.v7_2.make_all_assessment_group
-erpnext.patches.v8_0.repost_reserved_qty_for_multiple_sales_uom
-erpnext.patches.v8_0.addresses_linked_to_lead
-execute:frappe.delete_doc('DocType', 'Purchase Common')
-erpnext.patches.v8_0.update_stock_qty_value_in_purchase_invoice
-erpnext.patches.v8_0.update_supplier_address_in_stock_entry
-erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate
-erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices
-erpnext.patches.v8_0.enable_booking_asset_depreciation_automatically
-erpnext.patches.v8_0.set_project_copied_from
-erpnext.patches.v8_0.update_status_as_paid_for_completed_expense_claim
-erpnext.patches.v7_2.stock_uom_in_selling
-erpnext.patches.v8_0.revert_manufacturers_table_from_item
-erpnext.patches.v8_0.disable_instructor_role
-erpnext.patches.v8_0.merge_student_batch_and_student_group
-erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
-erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding
-erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice
-erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note
-erpnext.patches.v8_0.delete_schools_depricated_doctypes
-erpnext.patches.v8_0.update_customer_pos_id
-erpnext.patches.v8_0.rename_items_in_status_field_of_material_request
-erpnext.patches.v8_0.delete_bin_indexes
-erpnext.patches.v8_0.move_account_head_from_account_to_warehouse_for_inventory
-erpnext.patches.v8_0.change_in_words_varchar_length
-erpnext.patches.v8_0.update_stock_qty_value_in_bom_item
-erpnext.patches.v8_0.update_sales_cost_in_project
-erpnext.patches.v8_0.save_system_settings
-erpnext.patches.v8_1.delete_deprecated_reports
-erpnext.patches.v9_0.remove_subscription_module
-erpnext.patches.v8_7.make_subscription_from_recurring_data
erpnext.patches.v8_1.setup_gst_india #2017-06-27
-execute:frappe.reload_doc('regional', 'doctype', 'gst_hsn_code')
erpnext.patches.v8_1.removed_roles_from_gst_report_non_indian_account #16-08-2018
-erpnext.patches.v8_1.gst_fixes #2017-07-06
-erpnext.patches.v8_0.update_production_orders
-erpnext.patches.v8_1.remove_sales_invoice_from_returned_serial_no
-erpnext.patches.v8_1.allow_invoice_copy_to_edit_after_submit
-erpnext.patches.v8_1.add_hsn_sac_codes
-erpnext.patches.v8_1.update_gst_state #17-07-2017
-erpnext.patches.v8_1.removed_report_support_hours
-erpnext.patches.v8_1.add_indexes_in_transaction_doctypes
-erpnext.patches.v8_3.set_restrict_to_domain_for_module_def
-erpnext.patches.v8_1.update_expense_claim_status
-erpnext.patches.v8_3.update_company_total_sales #2017-08-16
-erpnext.patches.v8_4.make_scorecard_records
-erpnext.patches.v8_1.set_delivery_date_in_so_item #2017-07-28
-erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs
-erpnext.patches.v8_5.remove_quotations_route_in_sidebar
-erpnext.patches.v8_5.update_existing_data_in_project_type
-erpnext.patches.v8_5.set_default_mode_of_payment
-erpnext.patches.v8_5.update_customer_group_in_POS_profile
-erpnext.patches.v8_6.update_timesheet_company_from_PO
-erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager
-erpnext.patches.v8_5.remove_project_type_property_setter
erpnext.patches.v8_7.sync_india_custom_fields
-erpnext.patches.v8_7.fix_purchase_receipt_status
-erpnext.patches.v8_6.rename_bom_update_tool
-erpnext.patches.v8_9.add_setup_progress_actions #08-09-2017 #26-09-2017 #22-11-2017 #15-12-2017
-erpnext.patches.v8_9.rename_company_sales_target_field
-erpnext.patches.v8_8.set_bom_rate_as_per_uom
-erpnext.patches.v8_8.add_new_fields_in_accounts_settings
-erpnext.patches.v8_9.set_default_customer_group
-erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts
-erpnext.patches.v8_9.set_default_fields_in_variant_settings
-erpnext.patches.v8_9.update_billing_gstin_for_indian_account
-erpnext.patches.v8_9.set_member_party_type
-erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile
-erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
-erpnext.patches.v9_0.student_admission_childtable_migrate
-erpnext.patches.v9_0.add_healthcare_domain
-erpnext.patches.v9_0.set_variant_item_description
-erpnext.patches.v9_0.set_uoms_in_variant_field
-erpnext.patches.v9_0.copy_old_fees_field_data
-execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
-erpnext.patches.v9_0.set_pos_profile_name
-erpnext.patches.v9_0.remove_non_existing_warehouse_from_stock_settings
-execute:frappe.delete_doc_if_exists("DocType", "Program Fee")
-erpnext.patches.v8_10.change_default_customer_credit_days
-erpnext.patches.v9_0.update_employee_loan_details
-erpnext.patches.v9_2.delete_healthcare_domain_default_items
-erpnext.patches.v9_1.create_issue_opportunity_type
-erpnext.patches.v9_2.rename_translated_domains_in_en
-erpnext.patches.v9_0.set_shipping_type_for_existing_shipping_rules
-erpnext.patches.v9_0.update_multi_uom_fields_in_material_request
-erpnext.patches.v9_2.repost_reserved_qty_for_production
-erpnext.patches.v9_2.remove_company_from_patient
-erpnext.patches.v9_2.set_item_name_in_production_order
-erpnext.patches.v10_0.update_lft_rgt_for_employee
-erpnext.patches.v9_2.rename_net_weight_in_item_master
-erpnext.patches.v9_2.delete_process_payroll
-erpnext.patches.v10_0.add_agriculture_domain
-erpnext.patches.v10_0.add_non_profit_domain
-erpnext.patches.v10_0.setup_vat_for_uae_and_saudi_arabia #2017-12-28
-erpnext.patches.v10_0.set_primary_contact_for_customer
-erpnext.patches.v10_0.copy_projects_renamed_fields
-erpnext.patches.v10_0.enabled_regional_print_format_based_on_country
-erpnext.patches.v10_0.update_asset_calculate_depreciation
-erpnext.patches.v10_0.add_guardian_role_for_parent_portal
-erpnext.patches.v10_0.set_numeric_ranges_in_template_if_blank
-erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
erpnext.patches.v10_0.fichier_des_ecritures_comptables_for_france
-erpnext.patches.v10_0.update_assessment_plan
-erpnext.patches.v10_0.update_assessment_result
-erpnext.patches.v10_0.set_default_payment_terms_based_on_company
-erpnext.patches.v10_0.update_sales_order_link_to_purchase_order
erpnext.patches.v10_0.rename_price_to_rate_in_pricing_rule
erpnext.patches.v10_0.set_currency_in_pricing_rule
-erpnext.patches.v10_0.set_b2c_limit
erpnext.patches.v10_0.update_translatable_fields
erpnext.patches.v10_0.rename_offer_letter_to_job_offer
execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True)
@@ -496,16 +21,6 @@ erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_
erpnext.patches.v10_0.add_default_cash_flow_mappers
erpnext.patches.v11_0.rename_duplicate_item_code_values
erpnext.patches.v11_0.make_quality_inspection_template
-erpnext.patches.v10_0.update_status_for_multiple_source_in_po
-erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
-erpnext.patches.v10_0.update_territory_and_customer_group
-erpnext.patches.v10_0.update_warehouse_address_details
-erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
-erpnext.patches.v10_0.update_hub_connector_domain
-erpnext.patches.v10_0.set_student_party_type
-erpnext.patches.v10_0.update_project_in_sle
-erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
-erpnext.patches.v10_0.repost_requested_qty_for_non_stock_uom_items
erpnext.patches.v11_0.merge_land_unit_with_location
erpnext.patches.v11_0.add_index_on_nestedset_doctypes
erpnext.patches.v11_0.remove_modules_setup_page
@@ -514,7 +29,6 @@ erpnext.patches.v11_0.update_department_lft_rgt
erpnext.patches.v11_0.add_default_email_template_for_leave
erpnext.patches.v11_0.set_default_email_template_in_hr #08-06-2018
erpnext.patches.v11_0.uom_conversion_data #30-06-2018
-erpnext.patches.v10_0.taxes_issue_with_pos
erpnext.patches.v11_0.update_account_type_in_party_type
erpnext.patches.v11_0.rename_healthcare_doctype_and_fields
erpnext.patches.v11_0.rename_supplier_type_to_supplier_group
@@ -522,8 +36,6 @@ erpnext.patches.v10_1.transfer_subscription_to_auto_repeat
erpnext.patches.v11_0.update_brand_in_item_price
erpnext.patches.v11_0.create_default_success_action
erpnext.patches.v11_0.add_healthcare_service_unit_tree_root
-erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
-erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
erpnext.patches.v11_0.rename_field_max_days_allowed
erpnext.patches.v11_0.create_salary_structure_assignments
erpnext.patches.v11_0.rename_health_insurance
@@ -536,7 +48,6 @@ erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-
erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07
erpnext.patches.v11_0.rename_overproduction_percent_field
erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom
-erpnext.patches.v10_0.update_status_in_purchase_receipt
erpnext.patches.v11_0.inter_state_field_for_gst
erpnext.patches.v11_0.rename_members_with_naming_series #04-06-2018
erpnext.patches.v11_0.set_update_field_and_value_in_workflow_state
@@ -550,13 +61,10 @@ erpnext.patches.v11_0.skip_user_permission_check_for_department
erpnext.patches.v11_0.set_department_for_doctypes
erpnext.patches.v11_0.update_allow_transfer_for_manufacture
erpnext.patches.v11_0.add_item_group_defaults
-erpnext.patches.v10_0.update_address_template_for_india
erpnext.patches.v11_0.add_expense_claim_default_account
execute:frappe.delete_doc("Page", "hub")
erpnext.patches.v11_0.reset_publish_in_hub_for_all_items
erpnext.patches.v11_0.update_hub_url # 2018-08-31 # 2018-09-03
-erpnext.patches.v10_0.set_discount_amount
-erpnext.patches.v10_0.recalculate_gross_margin_for_project
erpnext.patches.v11_0.make_job_card
erpnext.patches.v11_0.redesign_healthcare_billing_work_flow
erpnext.patches.v10_0.delete_hub_documents # 12-08-2018
@@ -570,9 +78,6 @@ execute:frappe.delete_doc_if_exists("Page", "stock-analytics")
execute:frappe.delete_doc_if_exists("Page", "production-analytics")
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01 #2019-04-26 #2019-05-03
erpnext.patches.v11_0.drop_column_max_days_allowed
-erpnext.patches.v10_0.update_user_image_in_employee
-erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
-erpnext.patches.v10_0.allow_operators_in_supplier_scorecard
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.update_delivery_trip_status
erpnext.patches.v11_0.set_missing_gst_hsn_code
From 43a24f2aa87eef372cf2fddf1b99ef68245cb643 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Thu, 3 Jun 2021 20:05:00 +0530
Subject: [PATCH 204/262] ci: Update ERPNext backup patch test >= v10
* Generated v10 backup archive
* used old v7 erpnext backup hosted via build.erpnext.com
* upgraded to v10 frappe + erpnext
* Hosted backup on https://erpnext.com/files/v10-erpnext.sql.gz
---
.github/workflows/patch.yml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/patch.yml b/.github/workflows/patch.yml
index 7c9e0272c9..b96a3d6bbe 100644
--- a/.github/workflows/patch.yml
+++ b/.github/workflows/patch.yml
@@ -66,4 +66,8 @@ jobs:
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
- name: Run Patch Tests
- run: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
+ run: |
+ cd ~/frappe-bench/
+ wget https://erpnext.com/files/v10-erpnext.sql.gz
+ bench --site test_site --force restore ~/frappe-bench/v10-erpnext.sql.gz
+ bench --site test_site migrate
From 96f8ebc308ba2ceada92ab5a46ec582a7a9ba15f Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 17:07:45 +0530
Subject: [PATCH 205/262] fix(patch): Handle NULL values from fieldtype change
---
erpnext/patches/v11_0/rename_bom_wo_fields.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/erpnext/patches/v11_0/rename_bom_wo_fields.py b/erpnext/patches/v11_0/rename_bom_wo_fields.py
index b4a740fabb..882ec84e64 100644
--- a/erpnext/patches/v11_0/rename_bom_wo_fields.py
+++ b/erpnext/patches/v11_0/rename_bom_wo_fields.py
@@ -6,6 +6,10 @@ import frappe
from frappe.model.utils.rename_field import rename_field
def execute():
+ # updating column value to handle field change from Data to Currency
+ changed_field = "base_scrap_material_cost"
+ frappe.db.sql(f"update `tabBOM` set {changed_field} = '0' where trim(coalesce({changed_field}, ''))= ''")
+
for doctype in ['BOM Explosion Item', 'BOM Item', 'Work Order Item', 'Item']:
if frappe.db.has_column(doctype, 'allow_transfer_for_manufacture'):
if doctype != 'Item':
From 137d08a9d7bddb5903e5b01612a07c5a1223c378 Mon Sep 17 00:00:00 2001
From: Gavin D'souza
Date: Fri, 4 Jun 2021 20:11:34 +0530
Subject: [PATCH 206/262] fix: Manually link_fields from flags before
rename_doc
---
.../v13_0/healthcare_lab_module_rename_doctypes.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
index 9af0a8dbef..2549a1e91e 100644
--- a/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
+++ b/erpnext/patches/v13_0/healthcare_lab_module_rename_doctypes.py
@@ -2,6 +2,7 @@ from __future__ import unicode_literals
import frappe
from frappe.model.utils.rename_field import rename_field
+
def execute():
if frappe.db.exists('DocType', 'Lab Test') and frappe.db.exists('DocType', 'Lab Test Template'):
# rename child doctypes
@@ -17,7 +18,12 @@ def execute():
frappe.reload_doc('healthcare', 'doctype', 'lab_test_template')
for old_dt, new_dt in doctypes.items():
- if not frappe.db.table_exists(new_dt) and frappe.db.table_exists(old_dt):
+ frappe.flags.link_fields = {}
+ should_rename = (
+ frappe.db.table_exists(old_dt)
+ and not frappe.db.table_exists(new_dt)
+ )
+ if should_rename:
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(old_dt))
frappe.rename_doc('DocType', old_dt, new_dt, force=True)
frappe.reload_doc('healthcare', 'doctype', frappe.scrub(new_dt))
From 8f5ae0470df5270a2384ffdc1b4e376840d591ce Mon Sep 17 00:00:00 2001
From: walstanb
Date: Thu, 10 Jun 2021 16:35:27 +0530
Subject: [PATCH 207/262] fix: syntax error in stock entry
---
erpnext/stock/doctype/stock_entry/stock_entry.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 786285ae4f..9c4f0ddcbc 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -984,7 +984,7 @@ erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockControlle
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
}
- from_warehouse: function(doc) {
+ from_warehouse(doc) {
this.frm.trigger('set_transit_warehouse');
this.set_warehouse_in_children(doc.items, "s_warehouse", doc.from_warehouse);
}
From a5c3427293a8bfeb38bd83c08fe155b9d33179a4 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 10 Jun 2021 18:09:49 +0530
Subject: [PATCH 208/262] fix: Sort account balances by account name
---
.../report/account_balance/account_balance.py | 4 +---
.../account_balance/test_account_balance.py | 22 +++++++++----------
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/report/account_balance/account_balance.py b/erpnext/accounts/report/account_balance/account_balance.py
index 65e7d789bb..be64c327fd 100644
--- a/erpnext/accounts/report/account_balance/account_balance.py
+++ b/erpnext/accounts/report/account_balance/account_balance.py
@@ -58,11 +58,9 @@ def get_conditions(filters):
def get_data(filters):
data = []
-
conditions = get_conditions(filters)
-
accounts = frappe.db.get_all("Account", fields=["name", "account_currency"],
- filters=conditions)
+ filters=conditions, order_by='name')
for d in accounts:
balance = get_balance_on(d.name, date=filters.report_date)
diff --git a/erpnext/accounts/report/account_balance/test_account_balance.py b/erpnext/accounts/report/account_balance/test_account_balance.py
index b6ced312d0..14ddf4a30f 100644
--- a/erpnext/accounts/report/account_balance/test_account_balance.py
+++ b/erpnext/accounts/report/account_balance/test_account_balance.py
@@ -23,7 +23,7 @@ class TestAccountBalance(unittest.TestCase):
expected_data = [
{
- "account": 'Sales - _TC2',
+ "account": 'Direct Income - _TC2',
"currency": 'EUR',
"balance": -100.0,
},
@@ -32,21 +32,21 @@ class TestAccountBalance(unittest.TestCase):
"currency": 'EUR',
"balance": -100.0,
},
- {
- "account": 'Service - _TC2',
- "currency": 'EUR',
- "balance": 0.0,
- },
- {
- "account": 'Direct Income - _TC2',
- "currency": 'EUR',
- "balance": -100.0,
- },
{
"account": 'Indirect Income - _TC2',
"currency": 'EUR',
"balance": 0.0,
},
+ {
+ "account": 'Sales - _TC2',
+ "currency": 'EUR',
+ "balance": -100.0,
+ },
+ {
+ "account": 'Service - _TC2',
+ "currency": 'EUR',
+ "balance": 0.0,
+ }
]
self.assertEqual(expected_data, report[1])
From 9a243ed4699f2ae9e96397b221193f1fe40a2cb0 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 10 Jun 2021 18:09:49 +0530
Subject: [PATCH 209/262] fix: Sort account balances by account name
---
.../report/account_balance/account_balance.py | 4 +---
.../account_balance/test_account_balance.py | 22 +++++++++----------
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/report/account_balance/account_balance.py b/erpnext/accounts/report/account_balance/account_balance.py
index 65e7d789bb..be64c327fd 100644
--- a/erpnext/accounts/report/account_balance/account_balance.py
+++ b/erpnext/accounts/report/account_balance/account_balance.py
@@ -58,11 +58,9 @@ def get_conditions(filters):
def get_data(filters):
data = []
-
conditions = get_conditions(filters)
-
accounts = frappe.db.get_all("Account", fields=["name", "account_currency"],
- filters=conditions)
+ filters=conditions, order_by='name')
for d in accounts:
balance = get_balance_on(d.name, date=filters.report_date)
diff --git a/erpnext/accounts/report/account_balance/test_account_balance.py b/erpnext/accounts/report/account_balance/test_account_balance.py
index b6ced312d0..14ddf4a30f 100644
--- a/erpnext/accounts/report/account_balance/test_account_balance.py
+++ b/erpnext/accounts/report/account_balance/test_account_balance.py
@@ -23,7 +23,7 @@ class TestAccountBalance(unittest.TestCase):
expected_data = [
{
- "account": 'Sales - _TC2',
+ "account": 'Direct Income - _TC2',
"currency": 'EUR',
"balance": -100.0,
},
@@ -32,21 +32,21 @@ class TestAccountBalance(unittest.TestCase):
"currency": 'EUR',
"balance": -100.0,
},
- {
- "account": 'Service - _TC2',
- "currency": 'EUR',
- "balance": 0.0,
- },
- {
- "account": 'Direct Income - _TC2',
- "currency": 'EUR',
- "balance": -100.0,
- },
{
"account": 'Indirect Income - _TC2',
"currency": 'EUR',
"balance": 0.0,
},
+ {
+ "account": 'Sales - _TC2',
+ "currency": 'EUR',
+ "balance": -100.0,
+ },
+ {
+ "account": 'Service - _TC2',
+ "currency": 'EUR',
+ "balance": 0.0,
+ }
]
self.assertEqual(expected_data, report[1])
From 9a67141bfb0069d9254a902dd2f366d7a22b36be Mon Sep 17 00:00:00 2001
From: Saqib
Date: Thu, 10 Jun 2021 18:48:55 +0530
Subject: [PATCH 210/262] fix(einvoicing): service item check (#26010)
---
erpnext/regional/india/e_invoice/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index a1179ff9b6..0eaf790538 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -199,7 +199,7 @@ def get_item_list(invoice):
item.batch_expiry_date = frappe.db.get_value('Batch', d.batch_no, 'expiry_date') if d.batch_no else None
item.batch_expiry_date = format_date(item.batch_expiry_date, 'dd/mm/yyyy') if item.batch_expiry_date else None
- item.is_service_item = 'Y' if item.gst_hsn_code[:2] == "99" else 'N'
+ item.is_service_item = 'Y' if item.gst_hsn_code and item.gst_hsn_code[:2] == "99" else 'N'
item.serial_no = ""
item = update_item_taxes(invoice, item)
From 48f2839079639aa279adb5106398ab9a1224101f Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 10 Jun 2021 18:09:49 +0530
Subject: [PATCH 211/262] fix: Sort account balances by account name
---
.../report/account_balance/account_balance.py | 4 +---
.../account_balance/test_account_balance.py | 22 +++++++++----------
2 files changed, 12 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/report/account_balance/account_balance.py b/erpnext/accounts/report/account_balance/account_balance.py
index 65e7d789bb..be64c327fd 100644
--- a/erpnext/accounts/report/account_balance/account_balance.py
+++ b/erpnext/accounts/report/account_balance/account_balance.py
@@ -58,11 +58,9 @@ def get_conditions(filters):
def get_data(filters):
data = []
-
conditions = get_conditions(filters)
-
accounts = frappe.db.get_all("Account", fields=["name", "account_currency"],
- filters=conditions)
+ filters=conditions, order_by='name')
for d in accounts:
balance = get_balance_on(d.name, date=filters.report_date)
diff --git a/erpnext/accounts/report/account_balance/test_account_balance.py b/erpnext/accounts/report/account_balance/test_account_balance.py
index b6ced312d0..14ddf4a30f 100644
--- a/erpnext/accounts/report/account_balance/test_account_balance.py
+++ b/erpnext/accounts/report/account_balance/test_account_balance.py
@@ -23,7 +23,7 @@ class TestAccountBalance(unittest.TestCase):
expected_data = [
{
- "account": 'Sales - _TC2',
+ "account": 'Direct Income - _TC2',
"currency": 'EUR',
"balance": -100.0,
},
@@ -32,21 +32,21 @@ class TestAccountBalance(unittest.TestCase):
"currency": 'EUR',
"balance": -100.0,
},
- {
- "account": 'Service - _TC2',
- "currency": 'EUR',
- "balance": 0.0,
- },
- {
- "account": 'Direct Income - _TC2',
- "currency": 'EUR',
- "balance": -100.0,
- },
{
"account": 'Indirect Income - _TC2',
"currency": 'EUR',
"balance": 0.0,
},
+ {
+ "account": 'Sales - _TC2',
+ "currency": 'EUR',
+ "balance": -100.0,
+ },
+ {
+ "account": 'Service - _TC2',
+ "currency": 'EUR',
+ "balance": 0.0,
+ }
]
self.assertEqual(expected_data, report[1])
From 32ebb1001e0eaff0110e5785f4c0fdbde6794c77 Mon Sep 17 00:00:00 2001
From: Anupam
Date: Thu, 10 Jun 2021 19:32:00 +0530
Subject: [PATCH 212/262] fix: review chnages
---
erpnext/payroll/doctype/payroll_entry/payroll_entry.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
index 67893448ba..7a70679db4 100644
--- a/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/payroll_entry.py
@@ -665,6 +665,8 @@ def get_employee_list(filters):
emp_list = remove_payrolled_employees(emp_list, filters.start_date, filters.end_date)
return emp_list
+ return []
+
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def employee_query(doctype, txt, searchfield, start, page_len, filters):
@@ -673,7 +675,7 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters):
include_employees = []
emp_cond = ''
if filters.start_date and filters.end_date:
- employee_list = get_employee_list(filters) or []
+ employee_list = get_employee_list(filters)
emp = filters.get('employees')
include_employees = [employee.employee for employee in employee_list if employee.employee not in emp]
filters.pop('start_date')
From f310501d7dd8142bd50cd072e794eeaeab272820 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Thu, 3 Jun 2021 17:57:01 +0530
Subject: [PATCH 213/262] fix: filter type for item query
---
erpnext/controllers/queries.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 638503edfa..81ac234e70 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
import erpnext
+import json
from frappe.desk.reportview import get_match_cond, get_filters_cond
from frappe.utils import nowdate, getdate
from collections import defaultdict
@@ -198,6 +199,9 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
conditions = []
+ if isinstance(filters, str):
+ filters = json.loads(filters)
+
#Get searchfields from meta and use in Item Link field query
meta = frappe.get_meta("Item", cached=True)
searchfields = meta.get_search_fields()
From b103b24ae164aaa5702b50f091c699e09a77898a Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Thu, 27 May 2021 17:05:36 +0530
Subject: [PATCH 214/262] fix: timeout error in the repost item valuation
---
erpnext/hooks.py | 4 +++-
.../repost_item_valuation/repost_item_valuation.py | 13 ++++---------
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 0cdbbde61b..22ce4df97c 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -333,7 +333,9 @@ scheduler_events = {
"erpnext.projects.doctype.project.project.collect_project_status",
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
"erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
- "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
+ "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders"
+ ],
+ "hourly_long": [
"erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries"
],
"daily": [
diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
index 5b626ea345..55f2ebb224 100644
--- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
+++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
@@ -37,6 +37,9 @@ class RepostItemValuation(Document):
self.db_set('status', status)
def on_submit(self):
+ if not frappe.flags.in_test:
+ return
+
frappe.enqueue(repost, timeout=1800, queue='long',
job_name='repost_sle', now=frappe.flags.in_test, doc=self)
@@ -115,12 +118,6 @@ def notify_error_to_stock_managers(doc, traceback):
frappe.sendmail(recipients=recipients, subject=subject, message=message)
def repost_entries():
- job_log = frappe.get_all('Scheduled Job Log', fields = ['status', 'creation'],
- filters = {'scheduled_job_type': 'repost_item_valuation.repost_entries'}, order_by='creation desc', limit=1)
-
- if job_log and job_log[0]['status'] == 'Start' and time_diff_in_hours(now(), job_log[0]['creation']) < 2:
- return
-
riv_entries = get_repost_item_valuation_entries()
for row in riv_entries:
@@ -135,9 +132,7 @@ def repost_entries():
check_if_stock_and_account_balance_synced(today(), d.name)
def get_repost_item_valuation_entries():
- date = add_to_date(now(), hours=-3)
-
return frappe.db.sql(""" SELECT name from `tabRepost Item Valuation`
WHERE status != 'Completed' and creation <= %s and docstatus = 1
ORDER BY timestamp(posting_date, posting_time) asc, creation asc
- """, date, as_dict=1)
+ """, now(), as_dict=1)
From 9cfd3adad93a5138895b5a47ec5a85802bcfd691 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Fri, 4 Jun 2021 10:53:44 +0530
Subject: [PATCH 215/262] fix: custom conversion factor field not mapped from
job card to stock entry
---
erpnext/manufacturing/doctype/job_card/job_card.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index fb26062566..d764db33f8 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -433,7 +433,8 @@ def make_material_request(source_name, target_doc=None):
def make_stock_entry(source_name, target_doc=None):
def update_item(obj, target, source_parent):
target.t_warehouse = source_parent.wip_warehouse
- target.conversion_factor = 1
+ if not target.conversion_factor:
+ target.conversion_factor = 1
def set_missing_values(source, target):
target.purpose = "Material Transfer for Manufacture"
From 17408c63885b5cfc1abc95131b69b4b6c1364c68 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Wed, 9 Jun 2021 00:06:35 +0530
Subject: [PATCH 216/262] fix: on click of duplicate button system copy the
difference account from first row
---
erpnext/stock/doctype/stock_entry/stock_entry.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 9c4f0ddcbc..7952adb032 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -978,7 +978,10 @@ erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockControlle
items_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
- this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]);
+
+ if (!(row.expense_account && row.cost_center)) {
+ this.frm.script_manager.copy_from_first_row("items", row, ["expense_account", "cost_center"]);
+ }
if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse;
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
From c5da51dd7ad43016450ee3f72543b30c07d6a5d6 Mon Sep 17 00:00:00 2001
From: marination
Date: Thu, 10 Jun 2021 21:18:19 +0530
Subject: [PATCH 217/262] fix: Report Raw Materials to be Transferred
---
...tracted_raw_materials_to_be_transferred.py | 118 ++++++------------
1 file changed, 39 insertions(+), 79 deletions(-)
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
index de2ae8fc73..5a0381b017 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
@@ -9,10 +9,10 @@ def execute(filters=None):
if filters.from_date >= filters.to_date:
frappe.msgprint(_("To Date must be greater than From Date"))
- data = []
columns = get_columns()
- get_data(data , filters)
- return columns, data
+ data = get_data(filters)
+
+ return columns, data or []
def get_columns():
return [
@@ -21,13 +21,12 @@ def get_columns():
"fieldtype": "Link",
"fieldname": "purchase_order",
"options": "Purchase Order",
- "width": 150
+ "width": 200
},
{
"label": _("Date"),
"fieldtype": "Date",
"fieldname": "date",
- "hidden": 1,
"width": 150
},
{
@@ -41,97 +40,58 @@ def get_columns():
"label": _("Item Code"),
"fieldtype": "Data",
"fieldname": "rm_item_code",
- "width": 100
+ "width": 150
},
{
"label": _("Required Quantity"),
"fieldtype": "Float",
- "fieldname": "r_qty",
- "width": 100
+ "fieldname": "reqd_qty",
+ "width": 150
},
{
"label": _("Transferred Quantity"),
"fieldtype": "Float",
- "fieldname": "t_qty",
- "width": 100
+ "fieldname": "transferred_qty",
+ "width": 200
},
{
"label": _("Pending Quantity"),
"fieldtype": "Float",
"fieldname": "p_qty",
- "width": 100
+ "width": 150
}
]
-def get_data(data, filters):
- po = get_po(filters)
- po_transferred_qty_map = frappe._dict(get_transferred_quantity([v.name for v in po]))
+def get_data(filters):
+ po_rm_item_details = get_po_items_to_supply(filters)
- sub_items = get_purchase_order_item_supplied([v.name for v in po])
+ data = []
+ for row in po_rm_item_details:
+ transferred_qty = row.get("transferred_qty") or 0
+ if transferred_qty < row.get("reqd_qty", 0):
+ pending_qty = frappe.utils.flt(row.get("reqd_qty", 0) - transferred_qty)
+ row.p_qty = pending_qty if pending_qty > 0 else 0
+ data.append(row)
- for order in po:
- for item in sub_items:
- if order.name == item.parent and order.name in po_transferred_qty_map and \
- item.required_qty != po_transferred_qty_map.get(order.name).get(item.rm_item_code):
- transferred_qty = po_transferred_qty_map.get(order.name).get(item.rm_item_code) \
- if po_transferred_qty_map.get(order.name).get(item.rm_item_code) else 0
- row ={
- 'purchase_order': item.parent,
- 'date': order.transaction_date,
- 'supplier': order.supplier,
- 'rm_item_code': item.rm_item_code,
- 'r_qty': item.required_qty,
- 't_qty':transferred_qty,
- 'p_qty':item.required_qty - transferred_qty
- }
+ return data
- data.append(row)
-
- return(data)
-
-def get_po(filters):
- record_filters = [
- ["is_subcontracted", "=", "Yes"],
- ["supplier", "=", filters.supplier],
- ["transaction_date", "<=", filters.to_date],
- ["transaction_date", ">=", filters.from_date],
- ["docstatus", "=", 1]
- ]
- return frappe.get_all("Purchase Order", filters=record_filters, fields=["name", "transaction_date", "supplier"])
-
-def get_transferred_quantity(po_name):
- stock_entries = get_stock_entry(po_name)
- stock_entries_detail = get_stock_entry_detail([v.name for v in stock_entries])
- po_transferred_qty_map = {}
-
-
- for entry in stock_entries:
- for details in stock_entries_detail:
- if details.parent == entry.name:
- details["Purchase_order"] = entry.purchase_order
- if entry.purchase_order not in po_transferred_qty_map:
- po_transferred_qty_map[entry.purchase_order] = {}
- po_transferred_qty_map[entry.purchase_order][details.item_code] = details.qty
- else:
- po_transferred_qty_map[entry.purchase_order][details.item_code] = po_transferred_qty_map[entry.purchase_order].get(details.item_code, 0) + details.qty
-
- return po_transferred_qty_map
-
-
-def get_stock_entry(po):
- return frappe.get_all("Stock Entry", filters=[
- ('purchase_order', 'IN', po),
- ('stock_entry_type', '=', 'Send to Subcontractor'),
- ('docstatus', '=', 1)
- ], fields=["name", "purchase_order"])
-
-def get_stock_entry_detail(se):
- return frappe.get_all("Stock Entry Detail", filters=[
- ["parent", "in", se]
+def get_po_items_to_supply(filters):
+ return frappe.db.get_all(
+ "Purchase Order",
+ fields=[
+ "name as purchase_order",
+ "transaction_date as date",
+ "supplier as supplier",
+ "`tabPurchase Order Item Supplied`.rm_item_code as rm_item_code",
+ "`tabPurchase Order Item Supplied`.required_qty as reqd_qty",
+ "`tabPurchase Order Item Supplied`.supplied_qty as transferred_qty"
],
- fields=["parent", "item_code", "qty"])
-
-def get_purchase_order_item_supplied(po):
- return frappe.get_all("Purchase Order Item Supplied", filters=[
- ('parent', 'IN', po)
- ], fields=['parent', 'rm_item_code', 'required_qty'])
+ filters = [
+ ["Purchase Order", "per_received", "<", "100"],
+ ["Purchase Order", "is_subcontracted", "=", "Yes"],
+ ["Purchase Order", "supplier", "=", filters.supplier],
+ ["Purchase Order", "transaction_date", "<=", filters.to_date],
+ ["Purchase Order", "transaction_date", ">=", filters.from_date],
+ ["Purchase Order", "docstatus", "=", 1]
+ ]
+ )
\ No newline at end of file
From a4ed6a3519ce96328dcd6da1b280b5bb903c1671 Mon Sep 17 00:00:00 2001
From: marination
Date: Fri, 11 Jun 2021 12:47:06 +0530
Subject: [PATCH 218/262] fix: Sider
---
.../subcontracted_raw_materials_to_be_transferred.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
index 5a0381b017..68426abbb0 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/subcontracted_raw_materials_to_be_transferred.py
@@ -70,7 +70,7 @@ def get_data(filters):
transferred_qty = row.get("transferred_qty") or 0
if transferred_qty < row.get("reqd_qty", 0):
pending_qty = frappe.utils.flt(row.get("reqd_qty", 0) - transferred_qty)
- row.p_qty = pending_qty if pending_qty > 0 else 0
+ row.p_qty = pending_qty if pending_qty > 0 else 0
data.append(row)
return data
From a424c0c023e11647f09a55fbda0321fc5f3c31ef Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Fri, 11 Jun 2021 16:49:39 +0530
Subject: [PATCH 219/262] test(perf): eliminate repeat creation of HSN codes
(bp #25947)
---
erpnext/regional/india/setup.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index 229e0c031e..3e0b9b733b 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -27,6 +27,9 @@ def setup_company_independent_fixtures(patch=False):
add_print_formats()
def add_hsn_sac_codes():
+ if frappe.flags.in_test and frappe.flags.created_hsn_codes:
+ return
+
# HSN codes
with open(os.path.join(os.path.dirname(__file__), 'hsn_code_data.json'), 'r') as f:
hsn_codes = json.loads(f.read())
@@ -38,6 +41,9 @@ def add_hsn_sac_codes():
sac_codes = json.loads(f.read())
create_hsn_codes(sac_codes, code_field="sac_code")
+ if frappe.flags.in_test:
+ frappe.flags.created_hsn_codes = True
+
def create_hsn_codes(data, code_field):
for d in data:
hsn_code = frappe.new_doc('GST HSN Code')
From ea3e61d3b01687565271f12ab8ed48105d645963 Mon Sep 17 00:00:00 2001
From: marination
Date: Fri, 11 Jun 2021 17:27:43 +0530
Subject: [PATCH 220/262] fix: Test
---
...tracted_raw_materials_to_be_transferred.py | 68 ++++++++++++++-----
1 file changed, 51 insertions(+), 17 deletions(-)
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
index c1fc6fb82f..11ec7669b0 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
@@ -12,34 +12,68 @@ import json, frappe, unittest
class TestSubcontractedItemToBeTransferred(unittest.TestCase):
def test_pending_and_transferred_qty(self):
- po = create_purchase_order(item_code='_Test FG Item', is_subcontracted='Yes')
+ po = create_purchase_order(item_code='_Test FG Item', is_subcontracted='Yes', supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ # Material Receipt of RMs
make_stock_entry(item_code='_Test Item', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
make_stock_entry(item_code='_Test Item Home Desktop 100', target='_Test Warehouse - _TC', qty=100, basic_rate=100)
- transfer_subcontracted_raw_materials(po.name)
- col, data = execute(filters=frappe._dict({'supplier': po.supplier,
- 'from_date': frappe.utils.get_datetime(frappe.utils.add_to_date(po.transaction_date, days=-10)),
- 'to_date': frappe.utils.get_datetime(frappe.utils.add_to_date(po.transaction_date, days=10))}))
- self.assertEqual(data[0]['purchase_order'], po.name)
- self.assertIn(data[0]['rm_item_code'], ['_Test Item', '_Test Item Home Desktop 100'])
- self.assertIn(data[0]['p_qty'], [9, 18])
- self.assertIn(data[0]['t_qty'], [1, 2])
+
+ se = transfer_subcontracted_raw_materials(po)
+
+ col, data = execute(filters=frappe._dict(
+ {
+ 'supplier': po.supplier,
+ 'from_date': frappe.utils.get_datetime(frappe.utils.add_to_date(po.transaction_date, days=-10)),
+ 'to_date': frappe.utils.get_datetime(frappe.utils.add_to_date(po.transaction_date, days=10))
+ }
+ ))
+ po.reload()
+
+ po_data = [row for row in data if row.get('purchase_order') == po.name]
+
+ self.assertEqual(len(po_data), 2)
+ self.assertIn(po_data[0]['rm_item_code'], ['_Test Item', '_Test Item Home Desktop 100'])
+ self.assertIn(po_data[0]['p_qty'], [9, 18])
+ self.assertIn(po_data[0]['transferred_qty'], [1, 2])
self.assertEqual(data[1]['purchase_order'], po.name)
self.assertIn(data[1]['rm_item_code'], ['_Test Item', '_Test Item Home Desktop 100'])
self.assertIn(data[1]['p_qty'], [9, 18])
- self.assertIn(data[1]['t_qty'], [1, 2])
+ self.assertIn(data[1]['transferred_qty'], [1, 2])
+ se.cancel()
+ po.cancel()
def transfer_subcontracted_raw_materials(po):
rm_item = [
- {'item_code': '_Test Item', 'rm_item_code': '_Test Item', 'item_name': '_Test Item', 'qty': 1,
- 'warehouse': '_Test Warehouse - _TC', 'rate': 100, 'amount': 100, 'stock_uom': 'Nos'},
- {'item_code': '_Test Item Home Desktop 100', 'rm_item_code': '_Test Item Home Desktop 100', 'item_name': '_Test Item Home Desktop 100', 'qty': 2,
- 'warehouse': '_Test Warehouse - _TC', 'rate': 100, 'amount': 200, 'stock_uom': 'Nos'}]
+ {
+ 'name': po.supplied_items[0].name,
+ 'item_code': '_Test Item Home Desktop 100',
+ 'rm_item_code': '_Test Item Home Desktop 100',
+ 'item_name': '_Test Item Home Desktop 100',
+ 'qty': 2,
+ 'warehouse': '_Test Warehouse - _TC',
+ 'rate': 100,
+ 'amount': 200,
+ 'stock_uom': 'Nos'
+ },
+ {
+ 'name': po.supplied_items[1].name,
+ 'item_code': '_Test Item',
+ 'rm_item_code': '_Test Item',
+ 'item_name': '_Test Item',
+ 'qty': 1,
+ 'warehouse': '_Test Warehouse - _TC',
+ 'rate': 100,
+ 'amount': 100,
+ 'stock_uom': 'Nos'
+ }
+ ]
rm_item_string = json.dumps(rm_item)
- se = frappe.get_doc(make_rm_stock_entry(po, rm_item_string))
- se.from_warehouse = '_Test Warehouse 1 - _TC'
- se.to_warehouse = '_Test Warehouse 1 - _TC'
+ se = frappe.get_doc(make_rm_stock_entry(po.name, rm_item_string))
+ se.from_warehouse = '_Test Warehouse - _TC'
+ se.to_warehouse = '_Test Warehouse - _TC'
se.stock_entry_type = 'Send to Subcontractor'
se.save()
se.submit()
+ return se
From 9891780f5aaa76a2dd6cf49c189013cead668e70 Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Fri, 11 Jun 2021 18:40:22 +0530
Subject: [PATCH 221/262] perf(minor): remove unnecessary comprehensions (port
#25645)
---
erpnext/accounts/doctype/c_form/c_form.py | 2 +-
.../doctype/coupon_code/coupon_code.py | 2 +-
.../invoice_discounting/invoice_discounting.py | 2 +-
.../doctype/journal_entry/journal_entry.py | 4 ++--
.../monthly_distribution.py | 2 +-
.../doctype/payment_entry/payment_entry.py | 10 +++++-----
.../doctype/payment_request/payment_request.py | 2 +-
erpnext/accounts/doctype/pricing_rule/utils.py | 18 +++++++++---------
.../purchase_invoice/test_purchase_invoice.py | 2 +-
.../test_tax_withholding_category.py | 2 +-
erpnext/accounts/general_ledger.py | 2 +-
.../report/cash_flow/custom_cash_flow.py | 8 ++++----
.../customer_ledger_summary.py | 2 +-
.../accounts/report/financial_statements.py | 2 +-
.../item_wise_purchase_register.py | 2 +-
.../item_wise_sales_register.py | 2 +-
.../report/pos_register/pos_register.py | 6 +++---
.../purchase_register/purchase_register.py | 14 +++++++-------
.../sales_payment_summary.py | 4 ++--
.../report/sales_register/sales_register.py | 16 ++++++++--------
.../tds_computation_summary.py | 4 ++--
erpnext/accounts/report/utils.py | 2 +-
erpnext/accounts/utils.py | 2 +-
erpnext/assets/doctype/asset/test_asset.py | 2 +-
.../asset_value_adjustment.py | 2 +-
.../doctype/purchase_order/purchase_order.py | 6 +++---
.../purchase_order/test_purchase_order.py | 2 +-
.../request_for_quotation.py | 2 +-
erpnext/controllers/accounts_controller.py | 8 ++++----
erpnext/controllers/buying_controller.py | 6 +++---
erpnext/controllers/queries.py | 2 +-
erpnext/controllers/selling_controller.py | 2 +-
erpnext/controllers/status_updater.py | 4 ++--
erpnext/controllers/stock_controller.py | 6 +++---
erpnext/controllers/taxes_and_totals.py | 12 ++++++------
erpnext/controllers/tests/test_mapper.py | 4 ++--
.../controllers/website_list_for_contact.py | 2 +-
.../manufacturing/doctype/job_card/job_card.py | 2 +-
erpnext/projects/doctype/task/task.py | 2 +-
.../projects/doctype/timesheet/timesheet.py | 4 ++--
.../report/project_summary/project_summary.py | 2 +-
erpnext/selling/doctype/customer/customer.py | 2 +-
erpnext/selling/doctype/quotation/quotation.py | 2 +-
.../selling/doctype/sales_order/sales_order.py | 2 +-
erpnext/setup/doctype/company/company.py | 4 ++--
erpnext/setup/doctype/item_group/item_group.py | 4 ++--
erpnext/stock/doctype/batch/batch.py | 2 +-
.../doctype/delivery_note/delivery_note.py | 2 +-
.../doctype/delivery_trip/delivery_trip.py | 6 +++---
.../landed_cost_voucher/landed_cost_voucher.py | 8 ++++----
.../test_landed_cost_voucher.py | 2 +-
.../stock/doctype/packing_slip/packing_slip.py | 4 ++--
.../purchase_receipt/test_purchase_receipt.py | 2 +-
erpnext/stock/doctype/serial_no/serial_no.py | 2 +-
.../stock/doctype/stock_entry/stock_entry.py | 2 +-
.../item_price_stock/item_price_stock.py | 2 +-
.../itemwise_recommended_reorder_level.py | 2 +-
.../product_bundle_balance.py | 2 +-
.../report/stock_balance/stock_balance.py | 6 +++---
.../stock/report/stock_ledger/stock_ledger.py | 4 ++--
erpnext/stock/stock_ledger.py | 2 +-
.../doctype/warranty_claim/warranty_claim.py | 2 +-
erpnext/utilities/product.py | 2 +-
erpnext/utilities/transaction_base.py | 4 ++--
64 files changed, 126 insertions(+), 126 deletions(-)
diff --git a/erpnext/accounts/doctype/c_form/c_form.py b/erpnext/accounts/doctype/c_form/c_form.py
index fd86ed4c90..cfe28f3ff9 100644
--- a/erpnext/accounts/doctype/c_form/c_form.py
+++ b/erpnext/accounts/doctype/c_form/c_form.py
@@ -54,7 +54,7 @@ class CForm(Document):
frappe.throw(_("Please enter atleast 1 invoice in the table"))
def set_total_invoiced_amount(self):
- total = sum([flt(d.grand_total) for d in self.get('invoices')])
+ total = sum(flt(d.grand_total) for d in self.get('invoices'))
frappe.db.set(self, 'total_invoiced_amount', total)
@frappe.whitelist()
diff --git a/erpnext/accounts/doctype/coupon_code/coupon_code.py b/erpnext/accounts/doctype/coupon_code/coupon_code.py
index 7829c9320d..55c119315e 100644
--- a/erpnext/accounts/doctype/coupon_code/coupon_code.py
+++ b/erpnext/accounts/doctype/coupon_code/coupon_code.py
@@ -14,7 +14,7 @@ class CouponCode(Document):
if not self.coupon_code:
if self.coupon_type == "Promotional":
- self.coupon_code =''.join([i for i in self.coupon_name if not i.isdigit()])[0:8].upper()
+ self.coupon_code =''.join(i for i in self.coupon_name if not i.isdigit())[0:8].upper()
elif self.coupon_type == "Gift Card":
self.coupon_code = frappe.generate_hash()[:10].upper()
diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
index 7b62b617f9..d1e5afc48f 100644
--- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
+++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py
@@ -42,7 +42,7 @@ class InvoiceDiscounting(AccountsController):
record.idx, frappe.bold(actual_outstanding), frappe.bold(record.sales_invoice)))
def calculate_total_amount(self):
- self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices])
+ self.total_amount = sum(flt(d.outstanding_amount) for d in self.invoices)
def on_submit(self):
self.update_sales_invoice()
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index ed1bd28223..937597bc55 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -196,8 +196,8 @@ class JournalEntry(AccountsController):
frappe.throw(_("Row {0}: Party Type and Party is required for Receivable / Payable account {1}").format(d.idx, d.account))
def check_credit_limit(self):
- customers = list(set([d.party for d in self.get("accounts")
- if d.party_type=="Customer" and d.party and flt(d.debit) > 0]))
+ customers = list(set(d.party for d in self.get("accounts")
+ if d.party_type=="Customer" and d.party and flt(d.debit) > 0))
if customers:
from erpnext.selling.doctype.customer.customer import check_credit_limit
for customer in customers:
diff --git a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py
index 88667d7207..bff6422732 100644
--- a/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py
+++ b/erpnext/accounts/doctype/monthly_distribution/monthly_distribution.py
@@ -21,7 +21,7 @@ class MonthlyDistribution(Document):
idx += 1
def validate(self):
- total = sum([flt(d.percentage_allocation) for d in self.get("percentages")])
+ total = sum(flt(d.percentage_allocation) for d in self.get("percentages"))
if flt(total, 2) != 100.0:
frappe.throw(_("Percentage Allocation should be equal to 100%") + \
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index 62ab76c323..544d530551 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -303,7 +303,7 @@ class PaymentEntry(AccountsController):
for k, v in no_oustanding_refs.items():
frappe.msgprint(
_("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.")
- .format(k, frappe.bold(", ".join([d.reference_name for d in v])), frappe.bold("negative outstanding amount"))
+ .format(k, frappe.bold(", ".join(d.reference_name for d in v)), frappe.bold("negative outstanding amount"))
+ "
" + _("If this is undesirable please cancel the corresponding Payment Entry."),
title=_("Warning"), indicator="orange")
@@ -419,7 +419,7 @@ class PaymentEntry(AccountsController):
def set_unallocated_amount(self):
self.unallocated_amount = 0
if self.party:
- total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
+ total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
if self.payment_type == "Receive" \
and self.base_total_allocated_amount < self.base_received_amount + total_deductions \
and self.total_allocated_amount < self.paid_amount + (total_deductions / self.source_exchange_rate):
@@ -444,7 +444,7 @@ class PaymentEntry(AccountsController):
else:
self.difference_amount = self.base_paid_amount - flt(self.base_received_amount)
- total_deductions = sum([flt(d.amount) for d in self.get("deductions")])
+ total_deductions = sum(flt(d.amount) for d in self.get("deductions"))
self.difference_amount = flt(self.difference_amount - total_deductions,
self.precision("difference_amount"))
@@ -460,8 +460,8 @@ class PaymentEntry(AccountsController):
if ((self.payment_type=="Pay" and self.party_type=="Customer")
or (self.payment_type=="Receive" and self.party_type=="Supplier")):
- total_negative_outstanding = sum([abs(flt(d.outstanding_amount))
- for d in self.get("references") if flt(d.outstanding_amount) < 0])
+ total_negative_outstanding = sum(abs(flt(d.outstanding_amount))
+ for d in self.get("references") if flt(d.outstanding_amount) < 0)
paid_amount = self.paid_amount if self.payment_type=="Receive" else self.received_amount
additional_charges = sum([flt(d.amount) for d in self.deductions])
diff --git a/erpnext/accounts/doctype/payment_request/payment_request.py b/erpnext/accounts/doctype/payment_request/payment_request.py
index 53ac996290..520e87a6ce 100644
--- a/erpnext/accounts/doctype/payment_request/payment_request.py
+++ b/erpnext/accounts/doctype/payment_request/payment_request.py
@@ -112,7 +112,7 @@ class PaymentRequest(Document):
if not data_of_completed_requests:
return self.grand_total
- request_amounts = sum([json.loads(d).get('request_amount') for d in data_of_completed_requests])
+ request_amounts = sum(json.loads(d).get('request_amount') for d in data_of_completed_requests)
return request_amounts
def on_cancel(self):
diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py
index d23b952bdc..b54d0e73a8 100644
--- a/erpnext/accounts/doctype/pricing_rule/utils.py
+++ b/erpnext/accounts/doctype/pricing_rule/utils.py
@@ -20,9 +20,9 @@ from frappe.utils import cint, flt, get_link_to_form, getdate, today, fmt_money
class MultiplePricingRuleConflict(frappe.ValidationError): pass
apply_on_table = {
- 'Item Code': 'items',
- 'Item Group': 'item_groups',
- 'Brand': 'brands'
+ 'Item Code': 'items',
+ 'Item Group': 'item_groups',
+ 'Brand': 'brands'
}
def get_pricing_rules(args, doc=None):
@@ -183,7 +183,7 @@ def _get_tree_conditions(args, parenttype, table, allow_blank=True):
condition = "ifnull({table}.{field}, '') in ({parent_groups})".format(
table=table,
field=field,
- parent_groups=", ".join([frappe.db.escape(d) for d in parent_groups])
+ parent_groups=", ".join(frappe.db.escape(d) for d in parent_groups)
)
frappe.flags.tree_conditions[key] = condition
@@ -264,7 +264,7 @@ def filter_pricing_rules(args, pricing_rules, doc=None):
# find pricing rule with highest priority
if pricing_rules:
- max_priority = max([cint(p.priority) for p in pricing_rules])
+ max_priority = max(cint(p.priority) for p in pricing_rules)
if max_priority:
pricing_rules = list(filter(lambda x: cint(x.priority)==max_priority, pricing_rules))
@@ -272,14 +272,14 @@ def filter_pricing_rules(args, pricing_rules, doc=None):
pricing_rules = list(pricing_rules)
if len(pricing_rules) > 1:
- rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules]))
+ rate_or_discount = list(set(d.rate_or_discount for d in pricing_rules))
if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage":
pricing_rules = list(filter(lambda x: x.for_price_list==args.price_list, pricing_rules)) \
or pricing_rules
if len(pricing_rules) > 1 and not args.for_shopping_cart:
frappe.throw(_("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: {0}")
- .format("\n".join([d.name for d in pricing_rules])), MultiplePricingRuleConflict)
+ .format("\n".join(d.name for d in pricing_rules)), MultiplePricingRuleConflict)
elif pricing_rules:
return pricing_rules[0]
@@ -541,7 +541,7 @@ def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
def apply_pricing_rule_for_free_items(doc, pricing_rule_args, set_missing_values=False):
if pricing_rule_args:
- items = tuple([(d.item_code, d.pricing_rules) for d in doc.items if d.is_free_item])
+ items = tuple((d.item_code, d.pricing_rules) for d in doc.items if d.is_free_item)
for args in pricing_rule_args:
if not items or (args.get('item_code'), args.get('pricing_rules')) not in items:
@@ -589,4 +589,4 @@ def update_coupon_code_count(coupon_name,transaction_type):
elif transaction_type=='cancelled':
if coupon.used>0:
coupon.used=coupon.used-1
- coupon.save(ignore_permissions=True)
\ No newline at end of file
+ coupon.save(ignore_permissions=True)
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 53db689c84..6dc0f56148 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -631,7 +631,7 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(len(pi.get("supplied_items")), 2)
- rm_supp_cost = sum([d.amount for d in pi.get("supplied_items")])
+ rm_supp_cost = sum(d.amount for d in pi.get("supplied_items"))
self.assertEqual(flt(pi.get("items")[0].rm_supp_cost, 2), flt(rm_supp_cost, 2))
def test_rejected_serial_no(self):
diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
index 0cea7612dd..dd26be7c99 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
@@ -112,7 +112,7 @@ class TestTaxWithholdingCategory(unittest.TestCase):
si = create_sales_invoice(customer = "Test TCS Customer", rate=5000)
si.submit()
- tcs_charged = sum([d.base_tax_amount for d in si.taxes if d.account_head == 'TCS - _TC'])
+ tcs_charged = sum(d.base_tax_amount for d in si.taxes if d.account_head == 'TCS - _TC')
self.assertEqual(tcs_charged, 500)
invoices.append(si)
diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py
index f1717c50d8..968ab49b31 100644
--- a/erpnext/accounts/general_ledger.py
+++ b/erpnext/accounts/general_ledger.py
@@ -143,7 +143,7 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
validate_expense_against_budget(args)
def validate_cwip_accounts(gl_map):
- cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")])
+ cwip_enabled = any(cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting"))
if cwip_enabled and gl_map[0].voucher_type == "Journal Entry":
cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
diff --git a/erpnext/accounts/report/cash_flow/custom_cash_flow.py b/erpnext/accounts/report/cash_flow/custom_cash_flow.py
index ff87276a87..c11c15390b 100644
--- a/erpnext/accounts/report/cash_flow/custom_cash_flow.py
+++ b/erpnext/accounts/report/cash_flow/custom_cash_flow.py
@@ -32,7 +32,7 @@ def get_accounts_in_mappers(mapping_names):
join `tabCash Flow Mapping` cfm on cfma.parent=cfm.name
where cfma.parent in (%s)
order by cfm.is_working_capital
- ''', (', '.join(['"%s"' % d for d in mapping_names])))
+ ''', (', '.join('"%s"' % d for d in mapping_names)))
def setup_mappers(mappers):
@@ -83,8 +83,8 @@ def setup_mappers(mappers):
account_types_labels = sorted(
set(
- [(d['label'], d['is_working_capital'], d['is_income_tax_liability'], d['is_income_tax_expense'])
- for d in account_types]
+ (d['label'], d['is_working_capital'], d['is_income_tax_liability'], d['is_income_tax_expense'])
+ for d in account_types
),
key=lambda x: x[1]
)
@@ -375,7 +375,7 @@ def _get_account_type_based_data(filters, account_names, period_list, accumulate
total = 0
for period in period_list:
start_date = get_start_date(period, accumulated_values, company)
- accounts = ', '.join(['"%s"' % d for d in account_names])
+ accounts = ', '.join('"%s"' % d for d in account_names)
if opening_balances:
date_info = dict(date=start_date)
diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
index 10b32fea56..c79d7401e6 100644
--- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
+++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
@@ -145,7 +145,7 @@ class PartyLedgerSummaryReport(object):
out = []
for party, row in iteritems(self.party_data):
if row.opening_balance or row.invoiced_amount or row.paid_amount or row.return_amount or row.closing_amount:
- total_party_adjustment = sum([amount for amount in itervalues(self.party_adjustment_details.get(party, {}))])
+ total_party_adjustment = sum(amount for amount in itervalues(self.party_adjustment_details.get(party, {})))
row.paid_amount -= total_party_adjustment
adjustments = self.party_adjustment_details.get(party, {})
diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py
index d20ddbde5c..39ff804518 100644
--- a/erpnext/accounts/report/financial_statements.py
+++ b/erpnext/accounts/report/financial_statements.py
@@ -369,7 +369,7 @@ def set_gl_entries_by_account(
if accounts:
additional_conditions += " and account in ({})"\
- .format(", ".join([frappe.db.escape(d) for d in accounts]))
+ .format(", ".join(frappe.db.escape(d) for d in accounts))
gl_filters = {
"company": company,
diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
index cb4d9b43db..685419a17e 100644
--- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
+++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py
@@ -334,7 +334,7 @@ def get_aii_accounts():
def get_purchase_receipts_against_purchase_order(item_list):
po_pr_map = frappe._dict()
- po_item_rows = list(set([d.po_detail for d in item_list]))
+ po_item_rows = list(set(d.po_detail for d in item_list))
if po_item_rows:
purchase_receipts = frappe.db.sql("""
diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
index 928b373eff..2e794da842 100644
--- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
+++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
@@ -23,7 +23,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if item_list:
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
- mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list]))
+ mode_of_payments = get_mode_of_payments(set(d.parent for d in item_list))
so_dn_map = get_delivery_notes_against_sales_order(item_list)
data = []
diff --git a/erpnext/accounts/report/pos_register/pos_register.py b/erpnext/accounts/report/pos_register/pos_register.py
index cfbd7fd0c8..6a42bb4fb6 100644
--- a/erpnext/accounts/report/pos_register/pos_register.py
+++ b/erpnext/accounts/report/pos_register/pos_register.py
@@ -77,14 +77,14 @@ def get_pos_entries(filters, group_by_field):
), filters, as_dict=1)
def concat_mode_of_payments(pos_entries):
- mode_of_payments = get_mode_of_payments(set([d.pos_invoice for d in pos_entries]))
+ mode_of_payments = get_mode_of_payments(set(d.pos_invoice for d in pos_entries))
for entry in pos_entries:
if mode_of_payments.get(entry.pos_invoice):
entry.mode_of_payment = ", ".join(mode_of_payments.get(entry.pos_invoice, []))
def add_subtotal_row(data, group_invoices, group_by_field, group_by_value):
- grand_total = sum([d.grand_total for d in group_invoices])
- paid_amount = sum([d.paid_amount for d in group_invoices])
+ grand_total = sum(d.grand_total for d in group_invoices)
+ paid_amount = sum(d.paid_amount for d in group_invoices)
data.append({
group_by_field: group_by_value,
"grand_total": grand_total,
diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py
index 8ac749d629..10edd41aa8 100644
--- a/erpnext/accounts/report/purchase_register/purchase_register.py
+++ b/erpnext/accounts/report/purchase_register/purchase_register.py
@@ -26,7 +26,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list,
invoice_expense_map, expense_accounts)
invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
- suppliers = list(set([d.supplier for d in invoice_list]))
+ suppliers = list(set(d.supplier for d in invoice_list))
supplier_details = get_supplier_details(suppliers)
company_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
@@ -120,13 +120,13 @@ def get_columns(invoice_list, additional_table_columns):
and docstatus = 1 and (account_head is not null and account_head != '')
and category in ('Total', 'Valuation and Total')
and parent in (%s) order by account_head""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list))
unrealized_profit_loss_accounts = frappe.db.sql_list("""SELECT distinct unrealized_profit_loss_account
from `tabPurchase Invoice` where docstatus = 1 and name in (%s)
and ifnull(unrealized_profit_loss_account, '') != ''
order by unrealized_profit_loss_account""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list))
expense_columns = [(account + ":Currency/currency:120") for account in expense_accounts]
unrealized_profit_loss_account_columns = [(account + ":Currency/currency:120") for account in unrealized_profit_loss_accounts]
@@ -208,7 +208,7 @@ def get_invoice_expense_map(invoice_list):
from `tabPurchase Invoice Item`
where parent in (%s)
group by parent, expense_account
- """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ """ % ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
invoice_expense_map = {}
for d in expense_details:
@@ -221,7 +221,7 @@ def get_internal_invoice_map(invoice_list):
unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account,
base_net_total as amount from `tabPurchase Invoice` where name in (%s)
and is_internal_supplier = 1 and company = represents_company""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
internal_invoice_map = {}
for d in unrealized_amount_details:
@@ -238,7 +238,7 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
where parent in (%s) and category in ('Total', 'Valuation and Total')
and base_tax_amount_after_discount_amount != 0
group by parent, account_head, add_deduct_tax
- """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ """ % ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
invoice_tax_map = {}
for d in tax_details:
@@ -258,7 +258,7 @@ def get_invoice_po_pr_map(invoice_list):
select parent, purchase_order, purchase_receipt, po_detail, project
from `tabPurchase Invoice Item`
where parent in (%s)
- """ % ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ """ % ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
invoice_po_pr_map = {}
for d in pi_items:
diff --git a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py
index c234da0fe3..ff774681a2 100644
--- a/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py
+++ b/erpnext/accounts/report/sales_payment_summary/sales_payment_summary.py
@@ -158,7 +158,7 @@ def get_sales_invoice_data(filters):
def get_mode_of_payments(filters):
mode_of_payments = {}
invoice_list = get_invoices(filters)
- invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
+ invoice_list_names = ",".join('"' + invoice['name'] + '"' for invoice in invoice_list)
if invoice_list:
inv_mop = frappe.db.sql("""select a.owner,a.posting_date, ifnull(b.mode_of_payment, '') as mode_of_payment
from `tabSales Invoice` a, `tabSales Invoice Payment` b
@@ -197,7 +197,7 @@ def get_invoices(filters):
def get_mode_of_payment_details(filters):
mode_of_payment_details = {}
invoice_list = get_invoices(filters)
- invoice_list_names = ",".join(['"' + invoice['name'] + '"' for invoice in invoice_list])
+ invoice_list_names = ",".join('"' + invoice['name'] + '"' for invoice in invoice_list)
if invoice_list:
inv_mop_detail = frappe.db.sql("""select a.owner, a.posting_date,
ifnull(b.mode_of_payment, '') as mode_of_payment, sum(b.base_amount) as paid_amount
diff --git a/erpnext/accounts/report/sales_register/sales_register.py b/erpnext/accounts/report/sales_register/sales_register.py
index cb2c98b64a..909959323f 100644
--- a/erpnext/accounts/report/sales_register/sales_register.py
+++ b/erpnext/accounts/report/sales_register/sales_register.py
@@ -248,19 +248,19 @@ def get_columns(invoice_list, additional_table_columns):
income_accounts = frappe.db.sql_list("""select distinct income_account
from `tabSales Invoice Item` where docstatus = 1 and parent in (%s)
order by income_account""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list))
tax_accounts = frappe.db.sql_list("""select distinct account_head
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
and docstatus = 1 and base_tax_amount_after_discount_amount != 0
and parent in (%s) order by account_head""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list))
unrealized_profit_loss_accounts = frappe.db.sql_list("""SELECT distinct unrealized_profit_loss_account
from `tabSales Invoice` where docstatus = 1 and name in (%s)
and ifnull(unrealized_profit_loss_account, '') != ''
order by unrealized_profit_loss_account""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list))
for account in income_accounts:
income_columns.append({
@@ -406,7 +406,7 @@ def get_invoices(filters, additional_query_columns):
def get_invoice_income_map(invoice_list):
income_details = frappe.db.sql("""select parent, income_account, sum(base_net_amount) as amount
from `tabSales Invoice Item` where parent in (%s) group by parent, income_account""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
invoice_income_map = {}
for d in income_details:
@@ -419,7 +419,7 @@ def get_internal_invoice_map(invoice_list):
unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account,
base_net_total as amount from `tabSales Invoice` where name in (%s)
and is_internal_customer = 1 and company = represents_company""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
internal_invoice_map = {}
for d in unrealized_amount_details:
@@ -432,7 +432,7 @@ def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts):
tax_details = frappe.db.sql("""select parent, account_head,
sum(base_tax_amount_after_discount_amount) as tax_amount
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
invoice_tax_map = {}
for d in tax_details:
@@ -451,7 +451,7 @@ def get_invoice_so_dn_map(invoice_list):
si_items = frappe.db.sql("""select parent, sales_order, delivery_note, so_detail
from `tabSales Invoice Item` where parent in (%s)
and (ifnull(sales_order, '') != '' or ifnull(delivery_note, '') != '')""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
invoice_so_dn_map = {}
for d in si_items:
@@ -475,7 +475,7 @@ def get_invoice_cc_wh_map(invoice_list):
si_items = frappe.db.sql("""select parent, cost_center, warehouse
from `tabSales Invoice Item` where parent in (%s)
and (ifnull(cost_center, '') != '' or ifnull(warehouse, '') != '')""" %
- ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
+ ', '.join(['%s']*len(invoice_list)), tuple(inv.name for inv in invoice_list), as_dict=1)
invoice_cc_wh_map = {}
for d in si_items:
diff --git a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
index a8280c1b18..e15715dccd 100644
--- a/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
+++ b/erpnext/accounts/report/tds_computation_summary/tds_computation_summary.py
@@ -78,7 +78,7 @@ def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date, f
and company=%s and posting_date between %s and %s
""", (supplier, company, from_date, to_date), as_dict=1)
- supplier_credit_amount = flt(sum([d.credit for d in entries]))
+ supplier_credit_amount = flt(sum(d.credit for d in entries))
vouchers = [d.voucher_no for d in entries]
vouchers += get_advance_vouchers([supplier], company=company,
@@ -91,7 +91,7 @@ def get_invoice_and_tds_amount(supplier, account, company, from_date, to_date, f
from `tabGL Entry`
where account=%s and posting_date between %s and %s
and company=%s and credit > 0 and voucher_no in ({0})
- """.format(', '.join(["'%s'" % d for d in vouchers])),
+ """.format(', '.join("'%s'" % d for d in vouchers)),
(account, from_date, to_date, company))[0][0])
date_range_filter = [fiscal_year, from_date, to_date]
diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py
index b020d0a506..ba461edaf8 100644
--- a/erpnext/accounts/report/utils.py
+++ b/erpnext/accounts/report/utils.py
@@ -139,6 +139,6 @@ def get_invoiced_item_gross_margin(sales_invoice=None, item_code=None, company=N
gross_profit_data = GrossProfitGenerator(filters)
result = gross_profit_data.grouped_data
if not with_item_data:
- result = sum([d.gross_profit for d in result])
+ result = sum(d.gross_profit for d in result)
return result
diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py
index 5a64e27ccb..66a9b60125 100644
--- a/erpnext/accounts/utils.py
+++ b/erpnext/accounts/utils.py
@@ -635,7 +635,7 @@ def get_held_invoices(party_type, party):
'select name from `tabPurchase Invoice` where release_date IS NOT NULL and release_date > CURDATE()',
as_dict=1
)
- held_invoices = set([d['name'] for d in held_invoices])
+ held_invoices = set(d['name'] for d in held_invoices)
return held_invoices
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 3cd4b802c1..8845f24d10 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -470,7 +470,7 @@ class TestAsset(unittest.TestCase):
})
asset.insert()
accumulated_depreciation_after_full_schedule = \
- max([d.accumulated_depreciation_amount for d in asset.get("schedules")])
+ max(d.accumulated_depreciation_amount for d in asset.get("schedules"))
asset_value_after_full_schedule = (flt(asset.gross_purchase_amount) -
flt(accumulated_depreciation_after_full_schedule))
diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
index 14308277c1..2f6b5ee2dc 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
+++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
@@ -92,7 +92,7 @@ class AssetValueAdjustment(Document):
d.value_after_depreciation = asset_value
if d.depreciation_method in ("Straight Line", "Manual"):
- end_date = max([s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx])
+ end_date = max(s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx)
total_days = date_diff(end_date, self.date)
rate_per_day = flt(d.value_after_depreciation) / flt(total_days)
from_date = self.date
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index ef9372eeb6..c023accbfc 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -104,7 +104,7 @@ class PurchaseOrder(BuyingController):
def validate_minimum_order_qty(self):
if not self.get("items"): return
- items = list(set([d.item_code for d in self.get("items")]))
+ items = list(set(d.item_code for d in self.get("items")))
itemwise_min_order_qty = frappe._dict(frappe.db.sql("""select name, min_order_qty
from tabItem where name in ({0})""".format(", ".join(["%s"] * len(items))), items))
@@ -291,10 +291,10 @@ class PurchaseOrder(BuyingController):
so.notify_update()
def has_drop_ship_item(self):
- return any([d.delivered_by_supplier for d in self.items])
+ return any(d.delivered_by_supplier for d in self.items)
def is_against_so(self):
- return any([d.sales_order for d in self.items if d.sales_order])
+ return any(d.sales_order for d in self.items if d.sales_order)
def set_received_qty_for_drop_ship_items(self):
for item in self.items:
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index aaa98f2f1f..565fc920b8 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -359,7 +359,7 @@ class TestPurchaseOrder(unittest.TestCase):
update_child_qty_rate('Purchase Order', trans_item, po.name)
po.reload()
- total_reqd_qty_after_change = sum([d.get("required_qty") for d in po.as_dict().get("supplied_items")])
+ total_reqd_qty_after_change = sum(d.get("required_qty") for d in po.as_dict().get("supplied_items"))
self.assertEqual(total_reqd_qty_after_change, 2 * total_reqd_qty)
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index 180ba93666..0127eb8163 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -391,7 +391,7 @@ def get_item_from_material_requests_based_on_supplier(source_name, target_doc =
def get_supplier_tag():
if not frappe.cache().hget("Supplier", "Tags"):
filters = {"document_type": "Supplier"}
- tags = list(set([tag.tag for tag in frappe.get_all("Tag Link", filters=filters, fields=["tag"]) if tag]))
+ tags = list(set(tag.tag for tag in frappe.get_all("Tag Link", filters=filters, fields=["tag"]) if tag))
frappe.cache().hset("Supplier", "Tags", tags)
return frappe.cache().hget("Supplier", "Tags")
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index f88e8df728..2fdc19e315 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -608,8 +608,8 @@ class AccountsController(TransactionBase):
order_field = "purchase_order"
order_doctype = "Purchase Order"
- order_list = list(set([d.get(order_field)
- for d in self.get("items") if d.get(order_field)]))
+ order_list = list(set(d.get(order_field)
+ for d in self.get("items") if d.get(order_field)))
journal_entries = get_advance_journal_entries(party_type, party, party_account,
amount_field, order_doctype, order_list, include_unallocated)
@@ -633,8 +633,8 @@ class AccountsController(TransactionBase):
def validate_advance_entries(self):
order_field = "sales_order" if self.doctype == "Sales Invoice" else "purchase_order"
- order_list = list(set([d.get(order_field)
- for d in self.get("items") if d.get(order_field)]))
+ order_list = list(set(d.get(order_field)
+ for d in self.get("items") if d.get(order_field)))
if not order_list: return
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 3f2d3390c0..da819119b1 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -181,8 +181,8 @@ class BuyingController(StockController):
stock_and_asset_items_amount += flt(d.base_net_amount)
last_item_idx = d.idx
- total_valuation_amount = sum([flt(d.base_tax_amount_after_discount_amount) for d in self.get("taxes")
- if d.category in ["Valuation", "Valuation and Total"]])
+ total_valuation_amount = sum(flt(d.base_tax_amount_after_discount_amount) for d in self.get("taxes")
+ if d.category in ["Valuation", "Valuation and Total"])
valuation_amount_adjustment = total_valuation_amount
for i, item in enumerate(self.get("items")):
@@ -325,7 +325,7 @@ class BuyingController(StockController):
def update_raw_materials_supplied_based_on_stock_entries(self):
self.set('supplied_items', [])
- purchase_orders = set([d.purchase_order for d in self.items])
+ purchase_orders = set(d.purchase_order for d in self.items)
# qty of raw materials backflushed (for each item per purchase order)
backflushed_raw_materials_map = get_backflushed_subcontracted_raw_materials(purchase_orders)
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 81ac234e70..7bd739a6ad 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -88,7 +88,7 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
fields = get_fields("Customer", fields)
searchfields = frappe.get_meta("Customer").get_search_fields()
- searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
+ searchfields = " or ".join(field + " like %(txt)s" for field in searchfields)
return frappe.db.sql("""select {fields} from `tabCustomer`
where docstatus < 2
diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py
index 54156f379c..7f28289760 100644
--- a/erpnext/controllers/selling_controller.py
+++ b/erpnext/controllers/selling_controller.py
@@ -428,7 +428,7 @@ class SellingController(StockController):
self.po_no = ', '.join(list(set(x.strip() for x in ','.join(po_nos).split(','))))
def get_po_nos(self, ref_doctype, ref_fieldname, po_nos):
- doc_list = list(set([d.get(ref_fieldname) for d in self.items if d.get(ref_fieldname)]))
+ doc_list = list(set(d.get(ref_fieldname) for d in self.items if d.get(ref_fieldname)))
if doc_list:
po_nos += [d.po_no for d in frappe.get_all(ref_doctype, 'po_no', filters = {'name': ('in', doc_list)}) if d.get('po_no')]
diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py
index 83d4c33140..943f7aaeb1 100644
--- a/erpnext/controllers/status_updater.py
+++ b/erpnext/controllers/status_updater.py
@@ -299,8 +299,8 @@ class StatusUpdater(Document):
args['name'] = self.get(args['percent_join_field_parent'])
self._update_percent_field(args, update_modified)
else:
- distinct_transactions = set([d.get(args['percent_join_field'])
- for d in self.get_all_children(args['source_dt'])])
+ distinct_transactions = set(d.get(args['percent_join_field'])
+ for d in self.get_all_children(args['source_dt']))
for name in distinct_transactions:
if name:
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 41ca404d9b..71bde7fad7 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -310,7 +310,7 @@ class StockController(AccountsController):
def get_serialized_items(self):
serialized_items = []
- item_codes = list(set([d.item_code for d in self.get("items")]))
+ item_codes = list(set(d.item_code for d in self.get("items")))
if item_codes:
serialized_items = frappe.db.sql_list("""select name from `tabItem`
where has_serial_no=1 and name in ({})""".format(", ".join(["%s"]*len(item_codes))),
@@ -321,8 +321,8 @@ class StockController(AccountsController):
def validate_warehouse(self):
from erpnext.stock.utils import validate_warehouse_company, validate_disabled_warehouse
- warehouses = list(set([d.warehouse for d in
- self.get("items") if getattr(d, "warehouse", None)]))
+ warehouses = list(set(d.warehouse for d in
+ self.get("items") if getattr(d, "warehouse", None)))
target_warehouses = list(set([d.target_warehouse for d in
self.get("items") if getattr(d, "target_warehouse", None)]))
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 9fae49482d..dda642a532 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -375,10 +375,10 @@ class calculate_taxes_and_totals(object):
def manipulate_grand_total_for_inclusive_tax(self):
# if fully inclusive taxes and diff
- if self.doc.get("taxes") and any([cint(t.included_in_print_rate) for t in self.doc.get("taxes")]):
+ if self.doc.get("taxes") and any(cint(t.included_in_print_rate) for t in self.doc.get("taxes")):
last_tax = self.doc.get("taxes")[-1]
- non_inclusive_tax_amount = sum([flt(d.tax_amount_after_discount_amount)
- for d in self.doc.get("taxes") if not d.included_in_print_rate])
+ non_inclusive_tax_amount = sum(flt(d.tax_amount_after_discount_amount)
+ for d in self.doc.get("taxes") if not d.included_in_print_rate)
diff = self.doc.total + non_inclusive_tax_amount \
- flt(last_tax.total, last_tax.precision("total"))
@@ -518,8 +518,8 @@ class calculate_taxes_and_totals(object):
def calculate_total_advance(self):
if self.doc.docstatus < 2:
- total_allocated_amount = sum([flt(adv.allocated_amount, adv.precision("allocated_amount"))
- for adv in self.doc.get("advances")])
+ total_allocated_amount = sum(flt(adv.allocated_amount, adv.precision("allocated_amount"))
+ for adv in self.doc.get("advances"))
self.doc.total_advance = flt(total_allocated_amount, self.doc.precision("total_advance"))
@@ -619,7 +619,7 @@ class calculate_taxes_and_totals(object):
if self.doc.doctype == "Sales Invoice" \
and self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \
- and any([d.type == "Cash" for d in self.doc.payments]):
+ and any(d.type == "Cash" for d in self.doc.payments):
grand_total = self.doc.rounded_total or self.doc.grand_total
base_grand_total = self.doc.base_rounded_total or self.doc.base_grand_total
diff --git a/erpnext/controllers/tests/test_mapper.py b/erpnext/controllers/tests/test_mapper.py
index 66459fdbf8..7a4b2d3614 100644
--- a/erpnext/controllers/tests/test_mapper.py
+++ b/erpnext/controllers/tests/test_mapper.py
@@ -26,8 +26,8 @@ class TestMapper(unittest.TestCase):
# Assert that all inserted items are present in updated sales order
src_items = item_list_1 + item_list_2 + item_list_3
- self.assertEqual(set([d for d in src_items]),
- set([d.item_code for d in updated_so.items]))
+ self.assertEqual(set(d for d in src_items),
+ set(d.item_code for d in updated_so.items))
def make_quotation(self, item_list, customer):
diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py
index ecf041efd1..7c072e4fad 100644
--- a/erpnext/controllers/website_list_for_contact.py
+++ b/erpnext/controllers/website_list_for_contact.py
@@ -113,7 +113,7 @@ def post_process(doctype, data):
doc.set_indicator()
doc.status_display = ", ".join(doc.status_display)
- doc.items_preview = ", ".join([d.item_name for d in doc.items if d.item_name])
+ doc.items_preview = ", ".join(d.item_name for d in doc.items if d.item_name)
result.append(doc)
return result
diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py
index d764db33f8..cdc4518894 100644
--- a/erpnext/manufacturing/doctype/job_card/job_card.py
+++ b/erpnext/manufacturing/doctype/job_card/job_card.py
@@ -317,7 +317,7 @@ class JobCard(Document):
'docstatus': ('!=', 2)}, fields = 'sum(transferred_qty) as qty', group_by='operation_id')
if job_cards:
- qty = min([d.qty for d in job_cards])
+ qty = min(d.qty for d in job_cards)
doc.db_set('material_transferred_for_manufacturing', qty)
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index d1583f1473..39a6024e2c 100755
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -232,7 +232,7 @@ def get_project(doctype, txt, searchfield, start, page_len, filters):
meta = frappe.get_meta(doctype)
searchfields = meta.get_search_fields()
search_columns = ", " + ", ".join(searchfields) if searchfields else ''
- search_cond = " or " + " or ".join([field + " like %(txt)s" for field in searchfields])
+ search_cond = " or " + " or ".join(field + " like %(txt)s" for field in searchfields)
return frappe.db.sql(""" select name {search_columns} from `tabProject`
where %(key)s like %(txt)s
diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py
index a3e4577f90..c8bd80fca0 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.py
+++ b/erpnext/projects/doctype/timesheet/timesheet.py
@@ -87,8 +87,8 @@ class Timesheet(Document):
def set_dates(self):
if self.docstatus < 2 and self.time_logs:
- start_date = min([getdate(d.from_time) for d in self.time_logs])
- end_date = max([getdate(d.to_time) for d in self.time_logs])
+ start_date = min(getdate(d.from_time) for d in self.time_logs)
+ end_date = max(getdate(d.to_time) for d in self.time_logs)
if start_date and end_date:
self.start_date = getdate(start_date)
diff --git a/erpnext/projects/report/project_summary/project_summary.py b/erpnext/projects/report/project_summary/project_summary.py
index 2c7bb49cfb..98dd617f9b 100644
--- a/erpnext/projects/report/project_summary/project_summary.py
+++ b/erpnext/projects/report/project_summary/project_summary.py
@@ -122,7 +122,7 @@ def get_report_summary(data):
if not data:
return None
- avg_completion = sum([project.percent_complete for project in data]) / len(data)
+ avg_completion = sum(project.percent_complete for project in data) / len(data)
total = sum([project.total_tasks for project in data])
total_overdue = sum([project.overdue_tasks for project in data])
completed = sum([project.completed_tasks for project in data])
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index 51d86ff0bf..818888c0c1 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -75,7 +75,7 @@ class Customer(TransactionBase):
self.loyalty_program_tier = customer.loyalty_program_tier
if self.sales_team:
- if sum([member.allocated_percentage or 0 for member in self.sales_team]) != 100:
+ if sum(member.allocated_percentage or 0 for member in self.sales_team) != 100:
frappe.throw(_("Total contribution percentage should be equal to 100"))
def check_customer_group_change(self):
diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py
index 246f9234a4..e4f8a47581 100644
--- a/erpnext/selling/doctype/quotation/quotation.py
+++ b/erpnext/selling/doctype/quotation/quotation.py
@@ -50,7 +50,7 @@ class Quotation(SellingController):
self.customer_name = company_name or lead_name
def update_opportunity(self, status):
- for opportunity in list(set([d.prevdoc_docname for d in self.get("items")])):
+ for opportunity in set(d.prevdoc_docname for d in self.get("items")):
if opportunity:
self.update_opportunity_status(status, opportunity)
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index d9e52e1d69..551f715bd5 100755
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -151,7 +151,7 @@ class SalesOrder(SellingController):
frappe.db.sql("update `tabOpportunity` set status = %s where name=%s",(flag,enq[0][0]))
def update_prevdoc_status(self, flag=None):
- for quotation in list(set([d.prevdoc_docname for d in self.get("items")])):
+ for quotation in set(d.prevdoc_docname for d in self.get("items")):
if quotation:
doc = frappe.get_doc("Quotation", quotation)
if doc.docstatus==2:
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index 077538d479..27e023c1e5 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -54,7 +54,7 @@ class Company(NestedSet):
def validate_abbr(self):
if not self.abbr:
- self.abbr = ''.join([c[0] for c in self.company_name.split()]).upper()
+ self.abbr = ''.join(c[0] for c in self.company_name.split()).upper()
self.abbr = self.abbr.strip()
@@ -335,7 +335,7 @@ class Company(NestedSet):
clear_defaults_cache()
def abbreviate(self):
- self.abbr = ''.join([c[0].upper() for c in self.company_name.split()])
+ self.abbr = ''.join(c[0].upper() for c in self.company_name.split())
def on_trash(self):
"""
diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py
index bff806d547..db31d6d699 100644
--- a/erpnext/setup/doctype/item_group/item_group.py
+++ b/erpnext/setup/doctype/item_group/item_group.py
@@ -139,7 +139,7 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non
# return child item groups if the type is of "Is Group"
return get_child_groups_for_list_in_html(item_group, start, limit, search)
- child_groups = ", ".join([frappe.db.escape(i[0]) for i in get_child_groups(product_group)])
+ child_groups = ", ".join(frappe.db.escape(i[0]) for i in get_child_groups(product_group))
# base query
query = """select I.name, I.item_name, I.item_code, I.route, I.image, I.website_image, I.thumbnail, I.item_group,
@@ -239,7 +239,7 @@ def get_item_for_list_in_html(context):
return frappe.get_template(products_template).render(context)
def get_group_item_count(item_group):
- child_groups = ", ".join(['"' + i[0] + '"' for i in get_child_groups(item_group)])
+ child_groups = ", ".join('"' + i[0] + '"' for i in get_child_groups(item_group))
return frappe.db.sql("""select count(*) from `tabItem`
where docstatus = 0 and show_in_website = 1
and (item_group in (%s)
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index 8fdda565d2..508e17c340 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -304,7 +304,7 @@ def validate_serial_no_with_batch(serial_nos, item_code):
frappe.throw(_("The serial no {0} does not belong to item {1}")
.format(get_link_to_form("Serial No", serial_nos[0]), get_link_to_form("Item", item_code)))
- serial_no_link = ','.join([get_link_to_form("Serial No", sn) for sn in serial_nos])
+ serial_no_link = ','.join(get_link_to_form("Serial No", sn) for sn in serial_nos)
message = "Serial Nos" if len(serial_nos) > 1 else "Serial No"
frappe.throw(_("There is no batch found against the {0}: {1}")
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index cce51cb9b1..dd31965fac 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -264,7 +264,7 @@ class DeliveryNote(SellingController):
"""
Validate that if packed qty exists, it should be equal to qty
"""
- if not any([flt(d.get('packed_qty')) for d in self.get("items")]):
+ if not any(flt(d.get('packed_qty')) for d in self.get("items")):
return
has_error = False
for d in self.get("items"):
diff --git a/erpnext/stock/doctype/delivery_trip/delivery_trip.py b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
index 81e730126e..9ec28d8981 100644
--- a/erpnext/stock/doctype/delivery_trip/delivery_trip.py
+++ b/erpnext/stock/doctype/delivery_trip/delivery_trip.py
@@ -68,7 +68,7 @@ class DeliveryTrip(Document):
delete (bool, optional): Defaults to `False`. `True` if driver details need to be emptied, else `False`.
"""
- delivery_notes = list(set([stop.delivery_note for stop in self.delivery_stops if stop.delivery_note]))
+ delivery_notes = list(set(stop.delivery_note for stop in self.delivery_stops if stop.delivery_note))
update_fields = {
"driver": self.driver,
@@ -136,8 +136,8 @@ class DeliveryTrip(Document):
# Include last leg in the final distance calculation
self.uom = self.default_distance_uom
- total_distance = sum([leg.get("distance", {}).get("value", 0.0)
- for leg in directions.get("legs")]) # in meters
+ total_distance = sum(leg.get("distance", {}).get("value", 0.0)
+ for leg in directions.get("legs")) # in meters
self.total_distance = total_distance * self.uom_conversion_factor
else:
idx += len(route) - 1
diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
index 83109469fc..5df4d8743f 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -78,7 +78,7 @@ class LandedCostVoucher(Document):
.format(item.idx, item.item_code))
def set_total_taxes_and_charges(self):
- self.total_taxes_and_charges = sum([flt(d.base_amount) for d in self.get("taxes")])
+ self.total_taxes_and_charges = sum(flt(d.base_amount) for d in self.get("taxes"))
def set_applicable_charges_on_item(self):
if self.get('taxes') and self.distribute_charges_based_on != 'Distribute Manually':
@@ -104,15 +104,15 @@ class LandedCostVoucher(Document):
based_on = self.distribute_charges_based_on.lower()
if based_on != 'distribute manually':
- total = sum([flt(d.get(based_on)) for d in self.get("items")])
+ total = sum(flt(d.get(based_on)) for d in self.get("items"))
else:
# consider for proportion while distributing manually
- total = sum([flt(d.get('applicable_charges')) for d in self.get("items")])
+ total = sum(flt(d.get('applicable_charges')) for d in self.get("items"))
if not total:
frappe.throw(_("Total {0} for all items is zero, may be you should change 'Distribute Charges Based On'").format(based_on))
- total_applicable_charges = sum([flt(d.applicable_charges) for d in self.get("items")])
+ total_applicable_charges = sum(flt(d.applicable_charges) for d in self.get("items"))
precision = get_field_precision(frappe.get_meta("Landed Cost Item").get_field("applicable_charges"),
currency=frappe.get_cached_value('Company', self.company, "default_currency"))
diff --git a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
index 984ae46c66..32b08f60c4 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
@@ -311,7 +311,7 @@ def create_landed_cost_voucher(receipt_document_type, receipt_document, company,
def distribute_landed_cost_on_items(lcv):
based_on = lcv.distribute_charges_based_on.lower()
- total = sum([flt(d.get(based_on)) for d in lcv.get("items")])
+ total = sum(flt(d.get(based_on)) for d in lcv.get("items"))
for item in lcv.get("items"):
item.applicable_charges = flt(item.get(based_on)) * flt(lcv.total_taxes_and_charges) / flt(total)
diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py
index 2008bffcd3..4a843e0fde 100644
--- a/erpnext/stock/doctype/packing_slip/packing_slip.py
+++ b/erpnext/stock/doctype/packing_slip/packing_slip.py
@@ -88,9 +88,9 @@ class PackingSlip(Document):
rows = [d.item_code for d in self.get("items")]
# also pick custom fields from delivery note
- custom_fields = ', '.join(['dni.`{0}`'.format(d.fieldname)
+ custom_fields = ', '.join('dni.`{0}`'.format(d.fieldname)
for d in frappe.get_meta("Delivery Note Item").get_custom_fields()
- if d.fieldtype not in no_value_fields])
+ if d.fieldtype not in no_value_fields)
if custom_fields:
custom_fields = ', ' + custom_fields
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 5095a80214..8d9b675bed 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -246,7 +246,7 @@ class TestPurchaseReceipt(unittest.TestCase):
pr = make_purchase_receipt(item_code="_Test FG Item", qty=10, rate=500, is_subcontracted="Yes")
self.assertEqual(len(pr.get("supplied_items")), 2)
- rm_supp_cost = sum([d.amount for d in pr.get("supplied_items")])
+ rm_supp_cost = sum(d.amount for d in pr.get("supplied_items"))
self.assertEqual(pr.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))
pr.cancel()
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index 5ecc9f8140..b236f6a999 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -613,7 +613,7 @@ def fetch_serial_numbers(filters, qty, do_not_include=[]):
batch_nos = filters.get("batch_no")
expiry_date = filters.get("expiry_date")
if batch_nos:
- batch_no_condition = """and sr.batch_no in ({}) """.format(', '.join(["'%s'" % d for d in batch_nos]))
+ batch_no_condition = """and sr.batch_no in ({}) """.format(', '.join("'%s'" % d for d in batch_nos))
if expiry_date:
batch_join_selection = "LEFT JOIN `tabBatch` batch on sr.batch_no = batch.name "
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 2f76bc7d56..560ceaa917 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -465,7 +465,7 @@ class StockEntry(StockController):
"""
# Set rate for outgoing items
outgoing_items_cost = self.set_rate_for_outgoing_items(reset_outgoing_rate, raise_error_if_no_rate)
- finished_item_qty = sum([d.transfer_qty for d in self.items if d.is_finished_item])
+ finished_item_qty = sum(d.transfer_qty for d in self.items if d.is_finished_item)
# Set basic rate for incoming items
for d in self.get('items'):
diff --git a/erpnext/stock/report/item_price_stock/item_price_stock.py b/erpnext/stock/report/item_price_stock/item_price_stock.py
index 5296211fae..db7498bb21 100644
--- a/erpnext/stock/report/item_price_stock/item_price_stock.py
+++ b/erpnext/stock/report/item_price_stock/item_price_stock.py
@@ -89,7 +89,7 @@ def get_item_price_qty_data(filters):
{conditions}"""
.format(conditions=conditions), filters, as_dict=1)
- price_list_names = list(set([item.price_list_name for item in item_results]))
+ price_list_names = list(set(item.price_list_name for item in item_results))
buying_price_map = get_price_map(price_list_names, buying=1)
selling_price_map = get_price_map(price_list_names, selling=1)
diff --git a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
index 2f70523264..2e13aa0b04 100644
--- a/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
+++ b/erpnext/stock/report/itemwise_recommended_reorder_level/itemwise_recommended_reorder_level.py
@@ -66,7 +66,7 @@ def get_consumed_items(condition):
purpose is NULL
or purpose not in ({})
)
- """.format(', '.join([f"'{p}'" for p in purpose_to_exclude]))
+ """.format(', '.join(f"'{p}'" for p in purpose_to_exclude))
condition = condition.replace("posting_date", "sle.posting_date")
consumed_items = frappe.db.sql("""
diff --git a/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py b/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py
index 276e42ee43..8fffbccab3 100644
--- a/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py
+++ b/erpnext/stock/report/product_bundle_balance/product_bundle_balance.py
@@ -141,7 +141,7 @@ def get_stock_ledger_entries(filters, items):
return []
item_conditions_sql = ' and sle.item_code in ({})' \
- .format(', '.join([frappe.db.escape(i) for i in items]))
+ .format(', '.join(frappe.db.escape(i) for i in items))
conditions = get_sle_conditions(filters)
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index bbd73e9112..b6a8063189 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -157,7 +157,7 @@ def get_stock_ledger_entries(filters, items):
item_conditions_sql = ''
if items:
item_conditions_sql = ' and sle.item_code in ({})'\
- .format(', '.join([frappe.db.escape(i, percent=False) for i in items]))
+ .format(', '.join(frappe.db.escape(i, percent=False) for i in items))
conditions = get_conditions(filters)
@@ -253,7 +253,7 @@ def get_items(filters):
def get_item_details(items, sle, filters):
item_details = {}
if not items:
- items = list(set([d.item_code for d in sle]))
+ items = list(set(d.item_code for d in sle))
if not items:
return item_details
@@ -291,7 +291,7 @@ def get_item_reorder_details(items):
select parent, warehouse, warehouse_reorder_qty, warehouse_reorder_level
from `tabItem Reorder`
where parent in ({0})
- """.format(', '.join([frappe.db.escape(i, percent=False) for i in items])), as_dict=1)
+ """.format(', '.join(frappe.db.escape(i, percent=False) for i in items)), as_dict=1)
return dict((d.parent + d.warehouse, d) for d in item_reorder_details)
diff --git a/erpnext/stock/report/stock_ledger/stock_ledger.py b/erpnext/stock/report/stock_ledger/stock_ledger.py
index 36996e9674..8909f217f4 100644
--- a/erpnext/stock/report/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/report/stock_ledger/stock_ledger.py
@@ -115,7 +115,7 @@ def get_stock_ledger_entries(filters, items):
item_conditions_sql = ''
if items:
item_conditions_sql = 'and sle.item_code in ({})'\
- .format(', '.join([frappe.db.escape(i) for i in items]))
+ .format(', '.join(frappe.db.escape(i) for i in items))
sl_entries = frappe.db.sql("""
SELECT
@@ -169,7 +169,7 @@ def get_items(filters):
def get_item_details(items, sl_entries, include_uom):
item_details = {}
if not items:
- items = list(set([d.item_code for d in sl_entries]))
+ items = list(set(d.item_code for d in sl_entries))
if not items:
return item_details
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index b2825fc26f..fc82c789cc 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -521,7 +521,7 @@ class update_entries_after(object):
fields=["purchase_rate", "name", "company"],
filters = {'name': ('in', serial_nos)})
- incoming_values = sum([flt(d.purchase_rate) for d in all_serial_nos if d.company==sle.company])
+ incoming_values = sum(flt(d.purchase_rate) for d in all_serial_nos if d.company==sle.company)
# Get rate for serial nos which has been transferred to other company
invalid_serial_nos = [d.name for d in all_serial_nos if d.company!=sle.company]
diff --git a/erpnext/support/doctype/warranty_claim/warranty_claim.py b/erpnext/support/doctype/warranty_claim/warranty_claim.py
index a3428a25af..a20e7a801b 100644
--- a/erpnext/support/doctype/warranty_claim/warranty_claim.py
+++ b/erpnext/support/doctype/warranty_claim/warranty_claim.py
@@ -29,7 +29,7 @@ class WarrantyClaim(TransactionBase):
where t2.parent = t1.name and t2.prevdoc_docname = %s and t1.docstatus!=2""",
(self.name))
if lst:
- lst1 = ','.join([x[0] for x in lst])
+ lst1 = ','.join(x[0] for x in lst)
frappe.throw(_("Cancel Material Visit {0} before cancelling this Warranty Claim").format(lst1))
else:
frappe.db.set(self, 'status', 'Cancelled')
diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py
index 66d6cd3888..70b41767d6 100644
--- a/erpnext/utilities/product.py
+++ b/erpnext/utilities/product.py
@@ -131,6 +131,6 @@ def get_non_stock_item_status(item_code, item_warehouse_field):
if frappe.db.exists("Product Bundle", item_code):
items = frappe.get_doc("Product Bundle", item_code).get_all_children()
bundle_warehouse = frappe.db.get_value('Item', item_code, item_warehouse_field)
- return all([ get_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items ])
+ return all(get_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items)
else:
return 1
diff --git a/erpnext/utilities/transaction_base.py b/erpnext/utilities/transaction_base.py
index f99da58e46..db997263c1 100644
--- a/erpnext/utilities/transaction_base.py
+++ b/erpnext/utilities/transaction_base.py
@@ -147,7 +147,7 @@ class TransactionBase(StatusUpdater):
if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype):
fieldname = self.prev_link_mapper[for_doctype]["fieldname"]
- values = filter(None, tuple([item.as_dict()[fieldname] for item in self.items]))
+ values = filter(None, tuple(item.as_dict()[fieldname] for item in self.items))
if values:
ret = {
@@ -180,7 +180,7 @@ def validate_uom_is_integer(doc, uom_field, qty_fields, child_dt=None):
if isinstance(qty_fields, string_types):
qty_fields = [qty_fields]
- distinct_uoms = list(set([d.get(uom_field) for d in doc.get_all_children()]))
+ distinct_uoms = list(set(d.get(uom_field) for d in doc.get_all_children()))
integer_uoms = list(filter(lambda uom: frappe.db.get_value("UOM", uom,
"must_be_whole_number", cache=True) or None, distinct_uoms))
From 348f04ca82635373935df6b28e3203e85f7d1e1a Mon Sep 17 00:00:00 2001
From: Ankush Menat
Date: Fri, 11 Jun 2021 21:01:30 +0530
Subject: [PATCH 222/262] fix: syntax error in serial/batch selector (#26024)
---
erpnext/public/js/utils/serial_no_batch_selector.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js
index 02b5ef3930..597d77c6e9 100644
--- a/erpnext/public/js/utils/serial_no_batch_selector.js
+++ b/erpnext/public/js/utils/serial_no_batch_selector.js
@@ -324,7 +324,7 @@ erpnext.SerialNoBatchSelector = class SerialNoBatchSelector {
qty_field.set_input(total_qty);
}
- update_pending_qtys: function() {
+ update_pending_qtys() {
const pending_qty_field = this.dialog.fields_dict.pending_qty;
const total_selected_qty_field = this.dialog.fields_dict.total_selected_qty;
@@ -340,7 +340,7 @@ erpnext.SerialNoBatchSelector = class SerialNoBatchSelector {
total_selected_qty_field.set_input(total_selected_qty);
}
- get_batch_fields: function() {
+ get_batch_fields() {
var me = this;
return [
@@ -537,7 +537,7 @@ erpnext.SerialNoBatchSelector = class SerialNoBatchSelector {
}
];
}
-});
+};
function get_pending_qty_fields(me) {
if (!check_can_calculate_pending_qty(me)) return [];
From a38147a8bafd639620e6ba8508ee676a164df229 Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Sat, 12 Jun 2021 13:33:21 +0530
Subject: [PATCH 223/262] feat: add Inactive status to Employee
---
erpnext/accounts/party.py | 2 +-
erpnext/hr/doctype/employee/employee.json | 4 ++--
erpnext/hr/doctype/employee/employee.py | 4 ++--
erpnext/hr/doctype/employee/employee_list.js | 2 +-
erpnext/hr/doctype/employee_promotion/employee_promotion.py | 6 +++---
erpnext/hr/doctype/employee_transfer/employee_transfer.py | 6 +++---
erpnext/payroll/doctype/retention_bonus/retention_bonus.py | 4 ++--
7 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index e01cb6e151..e025fc6905 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -457,7 +457,7 @@ def validate_party_frozen_disabled(party_type, party_name):
frappe.throw(_("{0} {1} is frozen").format(party_type, party_name), PartyFrozen)
elif party_type == "Employee":
- if frappe.db.get_value("Employee", party_name, "status") == "Left":
+ if frappe.db.get_value("Employee", party_name, "status") != "Active":
frappe.msgprint(_("{0} {1} is not active").format(party_type, party_name), alert=True)
def get_timeline_data(doctype, name):
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index 5123d6a5a7..5442ed56c3 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -207,7 +207,7 @@
"label": "Status",
"oldfieldname": "status",
"oldfieldtype": "Select",
- "options": "Active\nLeft",
+ "options": "Active\nInactive\nLeft",
"reqd": 1,
"search_index": 1
},
@@ -813,7 +813,7 @@
"idx": 24,
"image_field": "image",
"links": [],
- "modified": "2021-01-02 16:54:33.477439",
+ "modified": "2021-06-12 11:31:37.730760",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee",
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index ed7d588434..bc5694226a 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -37,7 +37,7 @@ class Employee(NestedSet):
def validate(self):
from erpnext.controllers.status_updater import validate_status
- validate_status(self.status, ["Active", "Temporary Leave", "Left"])
+ validate_status(self.status, ["Active", "Inactive", "Left"])
self.employee = self.name
self.set_employee_name()
@@ -478,7 +478,7 @@ def get_employee_emails(employee_list):
@frappe.whitelist()
def get_children(doctype, parent=None, company=None, is_root=False, is_tree=False):
- filters = [['status', '!=', 'Left']]
+ filters = [['status', '=', 'Active']]
if company and company != 'All Companies':
filters.append(['company', '=', company])
diff --git a/erpnext/hr/doctype/employee/employee_list.js b/erpnext/hr/doctype/employee/employee_list.js
index 44837030be..6679e318c2 100644
--- a/erpnext/hr/doctype/employee/employee_list.js
+++ b/erpnext/hr/doctype/employee/employee_list.js
@@ -3,7 +3,7 @@ frappe.listview_settings['Employee'] = {
filters: [["status","=", "Active"]],
get_indicator: function(doc) {
var indicator = [__(doc.status), frappe.utils.guess_colour(doc.status), "status,=," + doc.status];
- indicator[1] = {"Active": "green", "Temporary Leave": "red", "Left": "gray"}[doc.status];
+ indicator[1] = {"Active": "green", "Inactive": "red", "Left": "gray"}[doc.status];
return indicator;
}
};
diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.py b/erpnext/hr/doctype/employee_promotion/employee_promotion.py
index 4994921268..83fb235f92 100644
--- a/erpnext/hr/doctype/employee_promotion/employee_promotion.py
+++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.py
@@ -11,12 +11,12 @@ from erpnext.hr.utils import update_employee
class EmployeePromotion(Document):
def validate(self):
- if frappe.get_value("Employee", self.employee, "status") == "Left":
- frappe.throw(_("Cannot promote Employee with status Left"))
+ if frappe.get_value("Employee", self.employee, "status") != "Active":
+ frappe.throw(_("Cannot promote Employee with status Left or Inactive"))
def before_submit(self):
if getdate(self.promotion_date) > getdate():
- frappe.throw(_("Employee Promotion cannot be submitted before Promotion Date "),
+ frappe.throw(_("Employee Promotion cannot be submitted before Promotion Date"),
frappe.DocstatusTransitionError)
def on_submit(self):
diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.py b/erpnext/hr/doctype/employee_transfer/employee_transfer.py
index 3539970a32..6eec9fa12a 100644
--- a/erpnext/hr/doctype/employee_transfer/employee_transfer.py
+++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.py
@@ -11,12 +11,12 @@ from erpnext.hr.utils import update_employee
class EmployeeTransfer(Document):
def validate(self):
- if frappe.get_value("Employee", self.employee, "status") == "Left":
- frappe.throw(_("Cannot transfer Employee with status Left"))
+ if frappe.get_value("Employee", self.employee, "status") != "Active":
+ frappe.throw(_("Cannot transfer Employee with status Left or Inactive"))
def before_submit(self):
if getdate(self.transfer_date) > getdate():
- frappe.throw(_("Employee Transfer cannot be submitted before Transfer Date "),
+ frappe.throw(_("Employee Transfer cannot be submitted before Transfer Date"),
frappe.DocstatusTransitionError)
def on_submit(self):
diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
index b8e56ae42a..049ea265cc 100644
--- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
+++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
@@ -10,8 +10,8 @@ from frappe.utils import getdate
class RetentionBonus(Document):
def validate(self):
- if frappe.get_value('Employee', self.employee, 'status') == 'Left':
- frappe.throw(_('Cannot create Retention Bonus for left Employees'))
+ if frappe.get_value('Employee', self.employee, 'status') != 'Active':
+ frappe.throw(_('Cannot create Retention Bonus for Left or Inactive Employees'))
if getdate(self.bonus_payment_date) < getdate():
frappe.throw(_('Bonus Payment Date cannot be a past date'))
From efd7d584b2a50ddc4f95aaf34515e95ab683838b Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Sat, 12 Jun 2021 13:33:21 +0530
Subject: [PATCH 224/262] feat: add Inactive status to Employee
---
erpnext/accounts/party.py | 2 +-
erpnext/hr/doctype/employee/employee.json | 4 ++--
erpnext/hr/doctype/employee/employee.py | 4 ++--
erpnext/hr/doctype/employee/employee_list.js | 2 +-
erpnext/hr/doctype/employee_promotion/employee_promotion.py | 6 +++---
erpnext/hr/doctype/employee_transfer/employee_transfer.py | 6 +++---
erpnext/payroll/doctype/retention_bonus/retention_bonus.py | 4 ++--
7 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index e01cb6e151..e025fc6905 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -457,7 +457,7 @@ def validate_party_frozen_disabled(party_type, party_name):
frappe.throw(_("{0} {1} is frozen").format(party_type, party_name), PartyFrozen)
elif party_type == "Employee":
- if frappe.db.get_value("Employee", party_name, "status") == "Left":
+ if frappe.db.get_value("Employee", party_name, "status") != "Active":
frappe.msgprint(_("{0} {1} is not active").format(party_type, party_name), alert=True)
def get_timeline_data(doctype, name):
diff --git a/erpnext/hr/doctype/employee/employee.json b/erpnext/hr/doctype/employee/employee.json
index 5123d6a5a7..5442ed56c3 100644
--- a/erpnext/hr/doctype/employee/employee.json
+++ b/erpnext/hr/doctype/employee/employee.json
@@ -207,7 +207,7 @@
"label": "Status",
"oldfieldname": "status",
"oldfieldtype": "Select",
- "options": "Active\nLeft",
+ "options": "Active\nInactive\nLeft",
"reqd": 1,
"search_index": 1
},
@@ -813,7 +813,7 @@
"idx": 24,
"image_field": "image",
"links": [],
- "modified": "2021-01-02 16:54:33.477439",
+ "modified": "2021-06-12 11:31:37.730760",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee",
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index ed7d588434..bc5694226a 100755
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -37,7 +37,7 @@ class Employee(NestedSet):
def validate(self):
from erpnext.controllers.status_updater import validate_status
- validate_status(self.status, ["Active", "Temporary Leave", "Left"])
+ validate_status(self.status, ["Active", "Inactive", "Left"])
self.employee = self.name
self.set_employee_name()
@@ -478,7 +478,7 @@ def get_employee_emails(employee_list):
@frappe.whitelist()
def get_children(doctype, parent=None, company=None, is_root=False, is_tree=False):
- filters = [['status', '!=', 'Left']]
+ filters = [['status', '=', 'Active']]
if company and company != 'All Companies':
filters.append(['company', '=', company])
diff --git a/erpnext/hr/doctype/employee/employee_list.js b/erpnext/hr/doctype/employee/employee_list.js
index 44837030be..6679e318c2 100644
--- a/erpnext/hr/doctype/employee/employee_list.js
+++ b/erpnext/hr/doctype/employee/employee_list.js
@@ -3,7 +3,7 @@ frappe.listview_settings['Employee'] = {
filters: [["status","=", "Active"]],
get_indicator: function(doc) {
var indicator = [__(doc.status), frappe.utils.guess_colour(doc.status), "status,=," + doc.status];
- indicator[1] = {"Active": "green", "Temporary Leave": "red", "Left": "gray"}[doc.status];
+ indicator[1] = {"Active": "green", "Inactive": "red", "Left": "gray"}[doc.status];
return indicator;
}
};
diff --git a/erpnext/hr/doctype/employee_promotion/employee_promotion.py b/erpnext/hr/doctype/employee_promotion/employee_promotion.py
index 4994921268..83fb235f92 100644
--- a/erpnext/hr/doctype/employee_promotion/employee_promotion.py
+++ b/erpnext/hr/doctype/employee_promotion/employee_promotion.py
@@ -11,12 +11,12 @@ from erpnext.hr.utils import update_employee
class EmployeePromotion(Document):
def validate(self):
- if frappe.get_value("Employee", self.employee, "status") == "Left":
- frappe.throw(_("Cannot promote Employee with status Left"))
+ if frappe.get_value("Employee", self.employee, "status") != "Active":
+ frappe.throw(_("Cannot promote Employee with status Left or Inactive"))
def before_submit(self):
if getdate(self.promotion_date) > getdate():
- frappe.throw(_("Employee Promotion cannot be submitted before Promotion Date "),
+ frappe.throw(_("Employee Promotion cannot be submitted before Promotion Date"),
frappe.DocstatusTransitionError)
def on_submit(self):
diff --git a/erpnext/hr/doctype/employee_transfer/employee_transfer.py b/erpnext/hr/doctype/employee_transfer/employee_transfer.py
index 3539970a32..6eec9fa12a 100644
--- a/erpnext/hr/doctype/employee_transfer/employee_transfer.py
+++ b/erpnext/hr/doctype/employee_transfer/employee_transfer.py
@@ -11,12 +11,12 @@ from erpnext.hr.utils import update_employee
class EmployeeTransfer(Document):
def validate(self):
- if frappe.get_value("Employee", self.employee, "status") == "Left":
- frappe.throw(_("Cannot transfer Employee with status Left"))
+ if frappe.get_value("Employee", self.employee, "status") != "Active":
+ frappe.throw(_("Cannot transfer Employee with status Left or Inactive"))
def before_submit(self):
if getdate(self.transfer_date) > getdate():
- frappe.throw(_("Employee Transfer cannot be submitted before Transfer Date "),
+ frappe.throw(_("Employee Transfer cannot be submitted before Transfer Date"),
frappe.DocstatusTransitionError)
def on_submit(self):
diff --git a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
index b8e56ae42a..049ea265cc 100644
--- a/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
+++ b/erpnext/payroll/doctype/retention_bonus/retention_bonus.py
@@ -10,8 +10,8 @@ from frappe.utils import getdate
class RetentionBonus(Document):
def validate(self):
- if frappe.get_value('Employee', self.employee, 'status') == 'Left':
- frappe.throw(_('Cannot create Retention Bonus for left Employees'))
+ if frappe.get_value('Employee', self.employee, 'status') != 'Active':
+ frappe.throw(_('Cannot create Retention Bonus for Left or Inactive Employees'))
if getdate(self.bonus_payment_date) < getdate():
frappe.throw(_('Bonus Payment Date cannot be a past date'))
From 0ed33aa4e8fa3efc98e66bd061755dcca8715d2e Mon Sep 17 00:00:00 2001
From: Rucha Mahabal
Date: Sat, 12 Jun 2021 13:40:58 +0530
Subject: [PATCH 225/262] fix: unable to enter score in Assessment Result
details grid (#25945)
---
.../education/doctype/assessment_result/assessment_result.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/education/doctype/assessment_result/assessment_result.js b/erpnext/education/doctype/assessment_result/assessment_result.js
index 617a873b82..c35f607a99 100644
--- a/erpnext/education/doctype/assessment_result/assessment_result.js
+++ b/erpnext/education/doctype/assessment_result/assessment_result.js
@@ -6,7 +6,8 @@ frappe.ui.form.on('Assessment Result', {
if (!frm.doc.__islocal) {
frm.trigger('setup_chart');
}
- frm.set_df_property('details', 'read_only', 1);
+
+ frm.get_field('details').grid.cannot_add_rows = true;
frm.set_query('course', function() {
return {
From 5d082b05a909f8c1761769962db525423075e3cd Mon Sep 17 00:00:00 2001
From: marination
Date: Mon, 14 Jun 2021 14:51:33 +0530
Subject: [PATCH 226/262] fix: Flaky test for Report Subcontracted Raw
materials to be transferred
---
...tracted_raw_materials_to_be_transferred.py | 46 ++++++++++++-------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
index 11ec7669b0..2448e17c50 100644
--- a/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
+++ b/erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
@@ -30,42 +30,54 @@ class TestSubcontractedItemToBeTransferred(unittest.TestCase):
po.reload()
po_data = [row for row in data if row.get('purchase_order') == po.name]
+ # Alphabetically sort to be certain of order
+ po_data = sorted(po_data, key = lambda i: i['rm_item_code'])
self.assertEqual(len(po_data), 2)
- self.assertIn(po_data[0]['rm_item_code'], ['_Test Item', '_Test Item Home Desktop 100'])
- self.assertIn(po_data[0]['p_qty'], [9, 18])
- self.assertIn(po_data[0]['transferred_qty'], [1, 2])
+ self.assertEqual(po_data[0]['purchase_order'], po.name)
- self.assertEqual(data[1]['purchase_order'], po.name)
- self.assertIn(data[1]['rm_item_code'], ['_Test Item', '_Test Item Home Desktop 100'])
- self.assertIn(data[1]['p_qty'], [9, 18])
- self.assertIn(data[1]['transferred_qty'], [1, 2])
+ self.assertEqual(po_data[0]['rm_item_code'], '_Test Item')
+ self.assertEqual(po_data[0]['p_qty'], 8)
+ self.assertEqual(po_data[0]['transferred_qty'], 2)
+
+ self.assertEqual(po_data[1]['rm_item_code'], '_Test Item Home Desktop 100')
+ self.assertEqual(po_data[1]['p_qty'], 19)
+ self.assertEqual(po_data[1]['transferred_qty'], 1)
se.cancel()
po.cancel()
def transfer_subcontracted_raw_materials(po):
+ # Order of supplied items fetched in PO is flaky
+ transfer_qty_map = {
+ '_Test Item': 2,
+ '_Test Item Home Desktop 100': 1
+ }
+
+ item_1 = po.supplied_items[0].rm_item_code
+ item_2 = po.supplied_items[1].rm_item_code
+
rm_item = [
{
'name': po.supplied_items[0].name,
- 'item_code': '_Test Item Home Desktop 100',
- 'rm_item_code': '_Test Item Home Desktop 100',
- 'item_name': '_Test Item Home Desktop 100',
- 'qty': 2,
+ 'item_code': item_1,
+ 'rm_item_code': item_1,
+ 'item_name': item_1,
+ 'qty': transfer_qty_map[item_1],
'warehouse': '_Test Warehouse - _TC',
'rate': 100,
- 'amount': 200,
+ 'amount': 100 * transfer_qty_map[item_1],
'stock_uom': 'Nos'
},
{
'name': po.supplied_items[1].name,
- 'item_code': '_Test Item',
- 'rm_item_code': '_Test Item',
- 'item_name': '_Test Item',
- 'qty': 1,
+ 'item_code': item_2,
+ 'rm_item_code': item_2,
+ 'item_name': item_2,
+ 'qty': transfer_qty_map[item_2],
'warehouse': '_Test Warehouse - _TC',
'rate': 100,
- 'amount': 100,
+ 'amount': 100 * transfer_qty_map[item_2],
'stock_uom': 'Nos'
}
]
From ec25d5938b2170e557a08991f891e945925943f3 Mon Sep 17 00:00:00 2001
From: Himanshu
Date: Mon, 14 Jun 2021 19:05:52 +0530
Subject: [PATCH 227/262] feat(SLA): Apply SLA to any document (#22449)
---
erpnext/hooks.py | 8 +-
erpnext/patches.txt | 1 +
erpnext/patches/v13_0/add_doctype_to_sla.py | 20 +
erpnext/public/js/utils.js | 145 ++++
erpnext/support/doctype/issue/issue.js | 137 +--
erpnext/support/doctype/issue/issue.py | 314 +------
erpnext/support/doctype/issue/test_issue.py | 2 +-
.../doctype/service_day/service_day.json | 13 +-
.../service_level_agreement.js | 89 +-
.../service_level_agreement.json | 90 +-
.../service_level_agreement.py | 805 ++++++++++++++++--
.../test_service_level_agreement.py | 285 ++++++-
.../service_level_priority.json | 13 +-
.../sla_fulfilled_on_status/__init__.py | 0
.../sla_fulfilled_on_status.json | 31 +
.../sla_fulfilled_on_status.py | 8 +
16 files changed, 1358 insertions(+), 603 deletions(-)
create mode 100644 erpnext/patches/v13_0/add_doctype_to_sla.py
create mode 100644 erpnext/support/doctype/sla_fulfilled_on_status/__init__.py
create mode 100644 erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.json
create mode 100644 erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 22ce4df97c..3da606b68b 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -228,6 +228,7 @@ standard_queries = {
doc_events = {
"*": {
+ "validate": "erpnext.support.doctype.service_level_agreement.service_level_agreement.apply",
"on_submit": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.create_medical_record",
"on_update_after_submit": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.update_medical_record",
"on_cancel": "erpnext.healthcare.doctype.patient_history_settings.patient_history_settings.delete_medical_record"
@@ -242,6 +243,9 @@ doc_events = {
"on_update": ["erpnext.hr.doctype.employee.employee.update_user_permissions",
"erpnext.portal.utils.set_default_role"]
},
+ "Communication": {
+ "on_update": "erpnext.support.doctype.service_level_agreement.service_level_agreement.update_hold_time"
+ },
("Sales Taxes and Charges Template", 'Price List'): {
"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings"
},
@@ -332,8 +336,8 @@ scheduler_events = {
"erpnext.projects.doctype.project.project.hourly_reminder",
"erpnext.projects.doctype.project.project.collect_project_status",
"erpnext.hr.doctype.shift_type.shift_type.process_auto_attendance_for_all_shifts",
- "erpnext.support.doctype.issue.issue.set_service_level_agreement_variance",
- "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders"
+ "erpnext.erpnext_integrations.connectors.shopify_connection.sync_old_orders",
+ "erpnext.support.doctype.service_level_agreement.service_level_agreement.set_service_level_agreement_variance"
],
"hourly_long": [
"erpnext.stock.doctype.repost_item_valuation.repost_item_valuation.repost_entries"
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 770bef353f..161241e9bb 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -285,4 +285,5 @@ erpnext.patches.v13_0.germany_make_custom_fields
erpnext.patches.v13_0.germany_fill_debtor_creditor_number
erpnext.patches.v13_0.set_pos_closing_as_failed
erpnext.patches.v13_0.update_timesheet_changes
+erpnext.patches.v13_0.add_doctype_to_sla
erpnext.patches.v13_0.set_training_event_attendance
diff --git a/erpnext/patches/v13_0/add_doctype_to_sla.py b/erpnext/patches/v13_0/add_doctype_to_sla.py
new file mode 100644
index 0000000000..35407785ca
--- /dev/null
+++ b/erpnext/patches/v13_0/add_doctype_to_sla.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2020, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+from frappe.model.utils.rename_field import rename_field
+
+def execute():
+ frappe.reload_doc('support', 'doctype', 'service_level_agreement')
+ if frappe.db.has_column('Service Level Agreement', 'enable'):
+ rename_field('Service Level Agreement', 'enable', 'enabled')
+
+ for sla in frappe.get_all('Service Level Agreement'):
+ agreement = frappe.get_doc('Service Level Agreement', sla.name)
+ agreement.document_type = 'Issue'
+ agreement.apply_sla_for_resolution = 1
+ agreement.append('sla_fulfilled_on', {'status': 'Resolved'})
+ agreement.append('sla_fulfilled_on', {'status': 'Closed'})
+ agreement.save()
\ No newline at end of file
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index ce40ced11f..db7c034596 100755
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -749,6 +749,151 @@ $(document).on('app_ready', function() {
}
});
+// Show SLA dashboard
+$(document).on('app_ready', function() {
+ frappe.call({
+ method: 'erpnext.support.doctype.service_level_agreement.service_level_agreement.get_sla_doctypes',
+ callback: function(r) {
+ if (!r.message)
+ return;
+
+ $.each(r.message, function(_i, d) {
+ frappe.ui.form.on(d, {
+ onload: function(frm) {
+ if (!frm.doc.service_level_agreement)
+ return;
+
+ frappe.call({
+ method: 'erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters',
+ args: {
+ doctype: frm.doc.doctype,
+ name: frm.doc.service_level_agreement,
+ customer: frm.doc.customer
+ },
+ callback: function (r) {
+ if (r && r.message) {
+ frm.set_query('priority', function() {
+ return {
+ filters: {
+ 'name': ['in', r.message.priority],
+ }
+ };
+ });
+ frm.set_query('service_level_agreement', function() {
+ return {
+ filters: {
+ 'name': ['in', r.message.service_level_agreements],
+ }
+ };
+ });
+ }
+ }
+ });
+ },
+
+ refresh: function(frm) {
+ if (frm.doc.status !== 'Closed' && frm.doc.service_level_agreement
+ && frm.doc.agreement_status === 'Ongoing') {
+ frappe.call({
+ 'method': 'frappe.client.get',
+ args: {
+ doctype: 'Service Level Agreement',
+ name: frm.doc.service_level_agreement
+ },
+ callback: function(data) {
+ let statuses = data.message.pause_sla_on;
+ const hold_statuses = [];
+ $.each(statuses, (_i, entry) => {
+ hold_statuses.push(entry.status);
+ });
+ if (hold_statuses.includes(frm.doc.status)) {
+ frm.dashboard.clear_headline();
+ let message = {'indicator': 'orange', 'msg': __('SLA is on hold since {0}', [moment(frm.doc.on_hold_since).fromNow(true)])};
+ frm.dashboard.set_headline_alert(
+ '' +
+ '
' +
+ ''+ message.msg +' ' +
+ '
' +
+ '
'
+ );
+ } else {
+ set_time_to_resolve_and_response(frm, data.message.apply_sla_for_resolution);
+ }
+ }
+ });
+ } else if (frm.doc.service_level_agreement) {
+ frm.dashboard.clear_headline();
+
+ let agreement_status = (frm.doc.agreement_status == 'Fulfilled') ?
+ {'indicator': 'green', 'msg': 'Service Level Agreement has been fulfilled'} :
+ {'indicator': 'red', 'msg': 'Service Level Agreement Failed'};
+
+ frm.dashboard.set_headline_alert(
+ '' +
+ '
' +
+ ''+ agreement_status.msg +' ' +
+ '
' +
+ '
'
+ );
+ }
+ },
+ });
+ });
+ }
+ });
+});
+
+function set_time_to_resolve_and_response(frm, apply_sla_for_resolution) {
+ frm.dashboard.clear_headline();
+
+ let time_to_respond = get_status(frm.doc.response_by_variance);
+ if (!frm.doc.first_responded_on && frm.doc.agreement_status === 'Ongoing') {
+ time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status);
+ }
+
+ let alert = `
+
+
+
+ Time to Respond: ${time_to_respond.diff_display}
+
+
`;
+
+
+ if (apply_sla_for_resolution) {
+ let time_to_resolve = get_status(frm.doc.resolution_by_variance);
+ if (!frm.doc.resolution_date && frm.doc.agreement_status === 'Ongoing') {
+ time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status);
+ }
+
+ alert += `
+
+
+ Time to Resolve: ${time_to_resolve.diff_display}
+
+
`;
+ }
+
+ alert += '
';
+
+ frm.dashboard.set_headline_alert(alert);
+}
+
+function get_time_left(timestamp, agreement_status) {
+ const diff = moment(timestamp).diff(moment());
+ const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : 'Failed';
+ let indicator = (diff_display == 'Failed' && agreement_status != 'Fulfilled') ? 'red' : 'green';
+ return {'diff_display': diff_display, 'indicator': indicator};
+}
+
+function get_status(variance) {
+ if (variance > 0) {
+ return {'diff_display': 'Fulfilled', 'indicator': 'green'};
+ } else {
+ return {'diff_display': 'Failed', 'indicator': 'red'};
+ }
+}
+
function attach_selector_button(inner_text, append_loction, context, grid_row) {
let $btn_div = $("").css({"margin-bottom": "10px", "margin-top": "10px"})
.appendTo(append_loction);
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
index 99a4e04b7d..9ac1efa268 100644
--- a/erpnext/support/doctype/issue/issue.js
+++ b/erpnext/support/doctype/issue/issue.js
@@ -9,94 +9,15 @@ frappe.ui.form.on("Issue", {
};
});
- if (frappe.model.can_read("Support Settings")) {
- frappe.db.get_value("Support Settings", {name: "Support Settings"},
- ["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
- if (r && r.track_service_level_agreement == "0") {
- frm.set_df_property("service_level_section", "hidden", 1);
- }
- if (r && r.allow_resetting_service_level_agreement == "0") {
- frm.set_df_property("reset_service_level_agreement", "hidden", 1);
- }
- });
- }
-
- if (frm.doc.service_level_agreement) {
- frappe.call({
- method: "erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters",
- args: {
- name: frm.doc.service_level_agreement,
- customer: frm.doc.customer
- },
- callback: function (r) {
- if (r && r.message) {
- frm.set_query("priority", function() {
- return {
- filters: {
- "name": ["in", r.message.priority],
- }
- };
- });
- frm.set_query("service_level_agreement", function() {
- return {
- filters: {
- "name": ["in", r.message.service_level_agreements],
- }
- };
- });
- }
+ frappe.db.get_value("Support Settings", {name: "Support Settings"},
+ ["allow_resetting_service_level_agreement", "track_service_level_agreement"], (r) => {
+ if (r && r.track_service_level_agreement == "0") {
+ frm.set_df_property("service_level_section", "hidden", 1);
+ }
+ if (r && r.allow_resetting_service_level_agreement == "0") {
+ frm.set_df_property("reset_service_level_agreement", "hidden", 1);
}
});
- }
- },
-
- refresh: function(frm) {
-
- // alert messages
- if (frm.doc.status !== "Closed" && frm.doc.service_level_agreement
- && frm.doc.agreement_status === "Ongoing") {
- frappe.call({
- "method": "frappe.client.get",
- args: {
- doctype: "Service Level Agreement",
- name: frm.doc.service_level_agreement
- },
- callback: function(data) {
- let statuses = data.message.pause_sla_on;
- const hold_statuses = [];
- $.each(statuses, (_i, entry) => {
- hold_statuses.push(entry.status);
- });
- if (hold_statuses.includes(frm.doc.status)) {
- frm.dashboard.clear_headline();
- let message = { "indicator": "orange", "msg": __("SLA is on hold since {0}", [moment(frm.doc.on_hold_since).fromNow(true)]) };
- frm.dashboard.set_headline_alert(
- '
' +
- '
' +
- '' + message.msg + ' ' +
- '
' +
- '
'
- );
- } else {
- set_time_to_resolve_and_response(frm);
- }
- }
- });
- } else if (frm.doc.service_level_agreement) {
- frm.dashboard.clear_headline();
-
- let agreement_status = (frm.doc.agreement_status == "Fulfilled") ?
- { "indicator": "green", "msg": "Service Level Agreement has been fulfilled" } :
- { "indicator": "red", "msg": "Service Level Agreement Failed" };
-
- frm.dashboard.set_headline_alert(
- '
' +
- '
' +
- '' + agreement_status.msg + ' ' +
- '
' +
- '
'
- );
- }
// buttons
if (frm.doc.status !== "Closed") {
@@ -142,7 +63,7 @@ frappe.ui.form.on("Issue", {
message: __("Resetting Service Level Agreement.")
});
- frm.call("reset_service_level_agreement", {
+ frappe.call("erpnext.support.doctype.service_level_agreement.service_level_agreement.reset_service_level_agreement", {
reason: values.reason,
user: frappe.session.user_email
}, () => {
@@ -224,44 +145,4 @@ frappe.ui.form.on("Issue", {
// frm.timeline.wrapper.data("help-article-event-attached", true);
// }
},
-});
-
-function set_time_to_resolve_and_response(frm) {
- frm.dashboard.clear_headline();
-
- var time_to_respond = get_status(frm.doc.response_by_variance);
- if (!frm.doc.first_responded_on && frm.doc.agreement_status === "Ongoing") {
- time_to_respond = get_time_left(frm.doc.response_by, frm.doc.agreement_status);
- }
-
- var time_to_resolve = get_status(frm.doc.resolution_by_variance);
- if (!frm.doc.resolution_date && frm.doc.agreement_status === "Ongoing") {
- time_to_resolve = get_time_left(frm.doc.resolution_by, frm.doc.agreement_status);
- }
-
- frm.dashboard.set_headline_alert(
- '
' +
- '
' +
- 'Time to Respond: '+ time_to_respond.diff_display +' ' +
- '
' +
- '
' +
- 'Time to Resolve: '+ time_to_resolve.diff_display +' ' +
- '
' +
- '
'
- );
-}
-
-function get_time_left(timestamp, agreement_status) {
- const diff = moment(timestamp).diff(moment());
- const diff_display = diff >= 44500 ? moment.duration(diff).humanize() : "Failed";
- let indicator = (diff_display == "Failed" && agreement_status != "Fulfilled") ? "red" : "green";
- return {"diff_display": diff_display, "indicator": indicator};
-}
-
-function get_status(variance) {
- if (variance > 0) {
- return {"diff_display": "Fulfilled", "indicator": "green"};
- } else {
- return {"diff_display": "Failed", "indicator": "red"};
- }
-}
+});
\ No newline at end of file
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index b068363f06..dd6d647abc 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -7,11 +7,10 @@ import json
from frappe import _
from frappe import utils
from frappe.model.document import Document
-from frappe.utils import cint, now_datetime, getdate, get_weekdays, add_to_date, get_time, get_datetime, time_diff_in_seconds
+from frappe.utils import now_datetime
from datetime import datetime, timedelta
from frappe.model.mapper import get_mapped_doc
from frappe.utils.user import is_website_user
-from erpnext.support.doctype.service_level_agreement.service_level_agreement import get_active_service_level_agreement_for
from frappe.email.inbox import link_communication_to_document
class Issue(Document):
@@ -25,8 +24,6 @@ class Issue(Document):
if not self.raised_by:
self.raised_by = frappe.session.user
- self.change_service_level_agreement_and_priority()
- self.update_status()
self.set_lead_contact(self.raised_by)
def on_update(self):
@@ -54,99 +51,6 @@ class Issue(Document):
self.company = frappe.db.get_value("Lead", self.lead, "company") or \
frappe.db.get_default("Company")
- def update_status(self):
- status = frappe.db.get_value("Issue", self.name, "status")
- if self.status != "Open" and status == "Open" and not self.first_responded_on:
- self.first_responded_on = frappe.flags.current_time or now_datetime()
-
- if self.status in ["Closed", "Resolved"] and status not in ["Resolved", "Closed"]:
- self.resolution_date = frappe.flags.current_time or now_datetime()
- if frappe.db.get_value("Issue", self.name, "agreement_status") == "Ongoing":
- set_service_level_agreement_variance(issue=self.name)
- self.update_agreement_status()
- set_resolution_time(issue=self)
- set_user_resolution_time(issue=self)
-
- if self.status == "Open" and status != "Open":
- # if no date, it should be set as None and not a blank string "", as per mysql strict config
- self.resolution_date = None
- self.reset_issue_metrics()
- # enable SLA and variance on Reopen
- self.agreement_status = "Ongoing"
- set_service_level_agreement_variance(issue=self.name)
-
- self.handle_hold_time(status)
-
- def handle_hold_time(self, status):
- if self.service_level_agreement:
- # set response and resolution variance as None as the issue is on Hold
- pause_sla_on = frappe.db.get_all("Pause SLA On Status", fields=["status"],
- filters={"parent": self.service_level_agreement})
- hold_statuses = [entry.status for entry in pause_sla_on]
- update_values = {}
-
- if hold_statuses:
- if self.status in hold_statuses and status not in hold_statuses:
- update_values['on_hold_since'] = frappe.flags.current_time or now_datetime()
- if not self.first_responded_on:
- update_values['response_by'] = None
- update_values['response_by_variance'] = 0
- update_values['resolution_by'] = None
- update_values['resolution_by_variance'] = 0
-
- # calculate hold time when status is changed from any hold status to any non-hold status
- if self.status not in hold_statuses and status in hold_statuses:
- hold_time = self.total_hold_time if self.total_hold_time else 0
- now_time = frappe.flags.current_time or now_datetime()
- last_hold_time = 0
- if self.on_hold_since:
- # last_hold_time will be added to the sla variables
- last_hold_time = time_diff_in_seconds(now_time, self.on_hold_since)
- update_values['total_hold_time'] = hold_time + last_hold_time
-
- # re-calculate SLA variables after issue changes from any hold status to any non-hold status
- # add hold time to SLA variables
- start_date_time = get_datetime(self.service_level_agreement_creation)
- priority = get_priority(self)
- now_time = frappe.flags.current_time or now_datetime()
-
- if not self.first_responded_on:
- response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
- response_by = add_to_date(response_by, seconds=round(last_hold_time))
- response_by_variance = round(time_diff_in_seconds(response_by, now_time))
- update_values['response_by'] = response_by
- update_values['response_by_variance'] = response_by_variance + last_hold_time
-
- resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
- resolution_by = add_to_date(resolution_by, seconds=round(last_hold_time))
- resolution_by_variance = round(time_diff_in_seconds(resolution_by, now_time))
- update_values['resolution_by'] = resolution_by
- update_values['resolution_by_variance'] = resolution_by_variance + last_hold_time
- update_values['on_hold_since'] = None
-
- self.db_set(update_values)
-
- def update_agreement_status(self):
- if self.service_level_agreement and self.agreement_status == "Ongoing":
- if cint(frappe.db.get_value("Issue", self.name, "response_by_variance")) < 0 or \
- cint(frappe.db.get_value("Issue", self.name, "resolution_by_variance")) < 0:
-
- self.agreement_status = "Failed"
- else:
- self.agreement_status = "Fulfilled"
-
- def update_agreement_status_on_custom_status(self):
- """
- Update Agreement Fulfilled status using Custom Scripts for Custom Issue Status
- """
- if not self.first_responded_on: # first_responded_on set when first reply is sent to customer
- self.response_by_variance = round(time_diff_in_seconds(self.response_by, now_datetime()), 2)
-
- if not self.resolution_date: # resolution_date set when issue has been closed
- self.resolution_by_variance = round(time_diff_in_seconds(self.resolution_by, now_datetime()), 2)
-
- self.agreement_status = "Fulfilled" if self.response_by_variance > 0 and self.resolution_by_variance > 0 else "Failed"
-
def create_communication(self):
communication = frappe.new_doc("Communication")
communication.update({
@@ -213,194 +117,6 @@ class Issue(Document):
return replicated_issue.name
- def before_insert(self):
- if frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
- if frappe.flags.in_test:
- self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
- else:
- self.set_response_and_resolution_time()
-
- def set_response_and_resolution_time(self, priority=None, service_level_agreement=None):
- service_level_agreement = get_active_service_level_agreement_for(priority=priority,
- customer=self.customer, service_level_agreement=service_level_agreement)
-
- if not service_level_agreement:
- if frappe.db.get_value("Issue", self.name, "service_level_agreement"):
- frappe.throw(_("Couldn't Set Service Level Agreement {0}.").format(self.service_level_agreement))
- return
-
- if (service_level_agreement.customer and self.customer) and not (service_level_agreement.customer == self.customer):
- frappe.throw(_("This Service Level Agreement is specific to Customer {0}").format(service_level_agreement.customer))
-
- self.service_level_agreement = service_level_agreement.name
- self.priority = service_level_agreement.default_priority if not priority else priority
-
- priority = get_priority(self)
-
- if not self.creation:
- self.creation = now_datetime()
- self.service_level_agreement_creation = now_datetime()
-
- start_date_time = get_datetime(self.service_level_agreement_creation)
- self.response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
- self.resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
-
- self.response_by_variance = round(time_diff_in_seconds(self.response_by, now_datetime()))
- self.resolution_by_variance = round(time_diff_in_seconds(self.resolution_by, now_datetime()))
-
- def change_service_level_agreement_and_priority(self):
- if self.service_level_agreement and frappe.db.exists("Issue", self.name) and \
- frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
-
- if not self.priority == frappe.db.get_value("Issue", self.name, "priority"):
- self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
- frappe.msgprint(_("Priority has been changed to {0}.").format(self.priority))
-
- if not self.service_level_agreement == frappe.db.get_value("Issue", self.name, "service_level_agreement"):
- self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
- frappe.msgprint(_("Service Level Agreement has been changed to {0}.").format(self.service_level_agreement))
-
- @frappe.whitelist()
- def reset_service_level_agreement(self, reason, user):
- if not frappe.db.get_single_value("Support Settings", "allow_resetting_service_level_agreement"):
- frappe.throw(_("Allow Resetting Service Level Agreement from Support Settings."))
-
- frappe.get_doc({
- "doctype": "Comment",
- "comment_type": "Info",
- "reference_doctype": self.doctype,
- "reference_name": self.name,
- "comment_email": user,
- "content": " resetted Service Level Agreement - {0}".format(_(reason)),
- }).insert(ignore_permissions=True)
-
- self.service_level_agreement_creation = now_datetime()
- self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
- self.agreement_status = "Ongoing"
- self.save()
-
- def reset_issue_metrics(self):
- self.db_set("resolution_time", None)
- self.db_set("user_resolution_time", None)
-
-
-def get_priority(issue):
- service_level_agreement = frappe.get_doc("Service Level Agreement", issue.service_level_agreement)
- priority = service_level_agreement.get_service_level_agreement_priority(issue.priority)
- priority.update({
- "support_and_resolution": service_level_agreement.support_and_resolution,
- "holiday_list": service_level_agreement.holiday_list
- })
- return priority
-
-
-def get_expected_time_for(parameter, service_level, start_date_time):
- current_date_time = start_date_time
- expected_time = current_date_time
- start_time = None
- end_time = None
-
- if parameter == "response":
- allotted_seconds = service_level.get("response_time")
- elif parameter == "resolution":
- allotted_seconds = service_level.get("resolution_time")
- else:
- frappe.throw(_("{0} parameter is invalid").format(parameter))
-
- expected_time_is_set = 0
-
- support_days = {}
- for service in service_level.get("support_and_resolution"):
- support_days[service.workday] = frappe._dict({
- "start_time": service.start_time,
- "end_time": service.end_time,
- })
-
- holidays = get_holidays(service_level.get("holiday_list"))
- weekdays = get_weekdays()
-
- while not expected_time_is_set:
- current_weekday = weekdays[current_date_time.weekday()]
-
- if not is_holiday(current_date_time, holidays) and current_weekday in support_days:
- start_time = current_date_time - datetime(current_date_time.year, current_date_time.month, current_date_time.day) \
- if getdate(current_date_time) == getdate(start_date_time) and get_time_in_timedelta(current_date_time.time()) > support_days[current_weekday].start_time \
- else support_days[current_weekday].start_time
- end_time = support_days[current_weekday].end_time
- time_left_today = time_diff_in_seconds(end_time, start_time)
-
- # no time left for support today
- if time_left_today <= 0: pass
- elif allotted_seconds:
- if time_left_today >= allotted_seconds:
- expected_time = datetime.combine(getdate(current_date_time), get_time(start_time))
- expected_time = add_to_date(expected_time, seconds=allotted_seconds)
- expected_time_is_set = 1
- else:
- allotted_seconds = allotted_seconds - time_left_today
-
- if not expected_time_is_set:
- current_date_time = add_to_date(current_date_time, days=1)
-
- if end_time and allotted_seconds >= 86400:
- current_date_time = datetime.combine(getdate(current_date_time), get_time(end_time))
- else:
- current_date_time = expected_time
-
- return current_date_time
-
-def set_service_level_agreement_variance(issue=None):
- current_time = frappe.flags.current_time or now_datetime()
-
- filters = {"status": "Open", "agreement_status": "Ongoing"}
- if issue:
- filters = {"name": issue}
-
- for issue in frappe.get_list("Issue", filters=filters):
- doc = frappe.get_doc("Issue", issue.name)
-
- if not doc.first_responded_on: # first_responded_on set when first reply is sent to customer
- variance = round(time_diff_in_seconds(doc.response_by, current_time), 2)
- frappe.db.set_value(dt="Issue", dn=doc.name, field="response_by_variance", val=variance, update_modified=False)
- if variance < 0:
- frappe.db.set_value(dt="Issue", dn=doc.name, field="agreement_status", val="Failed", update_modified=False)
-
- if not doc.resolution_date: # resolution_date set when issue has been closed
- variance = round(time_diff_in_seconds(doc.resolution_by, current_time), 2)
- frappe.db.set_value(dt="Issue", dn=doc.name, field="resolution_by_variance", val=variance, update_modified=False)
- if variance < 0:
- frappe.db.set_value(dt="Issue", dn=doc.name, field="agreement_status", val="Failed", update_modified=False)
-
-
-def set_resolution_time(issue):
- # total time taken from issue creation to closing
- resolution_time = time_diff_in_seconds(issue.resolution_date, issue.creation)
- issue.db_set("resolution_time", resolution_time)
-
-
-def set_user_resolution_time(issue):
- # total time taken by a user to close the issue apart from wait_time
- communications = frappe.get_list("Communication", filters={
- "reference_doctype": issue.doctype,
- "reference_name": issue.name
- },
- fields=["sent_or_received", "name", "creation"],
- order_by="creation"
- )
-
- pending_time = []
- for i in range(len(communications)):
- if communications[i].sent_or_received == "Received" and communications[i-1].sent_or_received == "Sent":
- wait_time = time_diff_in_seconds(communications[i].creation, communications[i-1].creation)
- if wait_time > 0:
- pending_time.append(wait_time)
-
- total_pending_time = sum(pending_time)
- resolution_time_in_secs = time_diff_in_seconds(issue.resolution_date, issue.creation)
- user_resolution_time = resolution_time_in_secs - total_pending_time
- issue.db_set("user_resolution_time", user_resolution_time)
-
-
def get_list_context(context=None):
return {
"title": _("Issues"),
@@ -439,15 +155,13 @@ def get_issue_list(doctype, txt, filters, limit_start, limit_page_length=20, ord
@frappe.whitelist()
def set_multiple_status(names, status):
- names = json.loads(names)
- for name in names:
- set_status(name, status)
+
+ for name in json.loads(names):
+ frappe.db.set_value("Issue", name, "status", status)
@frappe.whitelist()
def set_status(name, status):
- st = frappe.get_doc("Issue", name)
- st.status = status
- st.save()
+ frappe.db.set_value("Issue", name, "status", status)
def auto_close_tickets():
"""Auto-close replied support tickets after 7 days"""
@@ -473,14 +187,6 @@ def update_issue(contact, method):
"""Called when Contact is deleted"""
frappe.db.sql("""UPDATE `tabIssue` set contact='' where contact=%s""", contact.name)
-def get_holidays(holiday_list_name):
- holiday_list = frappe.get_cached_doc("Holiday List", holiday_list_name)
- holidays = [holiday.holiday_date for holiday in holiday_list.holidays]
- return holidays
-
-def is_holiday(date, holidays):
- return getdate(date) in holidays
-
@frappe.whitelist()
def make_task(source_name, target_doc=None):
return get_mapped_doc("Issue", source_name, {
@@ -506,9 +212,7 @@ def make_issue_from_communication(communication, ignore_communication_links=Fals
return issue.name
-def get_time_in_timedelta(time):
- """
- Converts datetime.time(10, 36, 55, 961454) to datetime.timedelta(seconds=38215)
- """
- import datetime
- return datetime.timedelta(hours=time.hour, minutes=time.minute, seconds=time.second)
\ No newline at end of file
+def get_holidays(holiday_list_name):
+ holiday_list = frappe.get_cached_doc("Holiday List", holiday_list_name)
+ holidays = [holiday.holiday_date for holiday in holiday_list.holidays]
+ return holidays
\ No newline at end of file
diff --git a/erpnext/support/doctype/issue/test_issue.py b/erpnext/support/doctype/issue/test_issue.py
index 7da5d7f0ed..7b9b1446d4 100644
--- a/erpnext/support/doctype/issue/test_issue.py
+++ b/erpnext/support/doctype/issue/test_issue.py
@@ -68,7 +68,7 @@ class TestIssue(unittest.TestCase):
self.assertEqual(issue.resolution_by, datetime.datetime(2019, 3, 6, 12, 0))
frappe.flags.current_time = datetime.datetime(2019, 3, 4, 15, 0)
-
+ issue.reload()
issue.status = 'Closed'
issue.save()
diff --git a/erpnext/support/doctype/service_day/service_day.json b/erpnext/support/doctype/service_day/service_day.json
index 68614b1807..966213099b 100644
--- a/erpnext/support/doctype/service_day/service_day.json
+++ b/erpnext/support/doctype/service_day/service_day.json
@@ -1,4 +1,5 @@
{
+ "actions": [],
"creation": "2019-03-04 12:55:36.403035",
"doctype": "DocType",
"editable_grid": 1,
@@ -16,7 +17,8 @@
"fieldtype": "Select",
"in_list_view": 1,
"label": "Workday",
- "options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday"
+ "options": "Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\nSunday",
+ "reqd": 1
},
{
"fieldname": "section_break_2",
@@ -26,7 +28,8 @@
"fieldname": "start_time",
"fieldtype": "Time",
"in_list_view": 1,
- "label": "Start Time"
+ "label": "Start Time",
+ "reqd": 1
},
{
"fieldname": "column_break_3",
@@ -36,11 +39,13 @@
"fieldname": "end_time",
"fieldtype": "Time",
"in_list_view": 1,
- "label": "End Time"
+ "label": "End Time",
+ "reqd": 1
}
],
"istable": 1,
- "modified": "2019-05-05 19:15:08.999579",
+ "links": [],
+ "modified": "2020-07-06 13:28:47.303873",
"modified_by": "Administrator",
"module": "Support",
"name": "Service Day",
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js
index 00060b9530..308bce48df 100644
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.js
+++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.js
@@ -3,16 +3,87 @@
frappe.ui.form.on('Service Level Agreement', {
setup: function(frm) {
- let allow_statuses = [];
- const exclude_statuses = ['Open', 'Closed', 'Resolved'];
+ if (cint(frm.doc.apply_sla_for_resolution) === 1) {
+ frm.get_field('priorities').grid.editable_fields = [
+ {fieldname: 'priority', columns: 1},
+ {fieldname: 'default_priority', columns: 1},
+ {fieldname: 'response_time', columns: 2},
+ {fieldname: 'resolution_time', columns: 2}
+ ];
+ } else {
+ frm.get_field('priorities').grid.editable_fields = [
+ {fieldname: 'priority', columns: 1},
+ {fieldname: 'default_priority', columns: 1},
+ {fieldname: 'response_time', columns: 3},
+ ];
+ }
+ },
- frappe.model.with_doctype('Issue', () => {
- let statuses = frappe.meta.get_docfield('Issue', 'status', frm.doc.name).options;
- statuses = statuses.split('\n');
- allow_statuses = statuses.filter((status) => !exclude_statuses.includes(status));
- frm.fields_dict.pause_sla_on.grid.update_docfield_property(
- 'status', 'options', [''].concat(allow_statuses)
- );
+ refresh: function(frm) {
+ frm.trigger('fetch_status_fields');
+ frm.trigger('toggle_resolution_fields');
+ },
+
+ document_type: function(frm) {
+ frm.trigger('fetch_status_fields');
+ },
+
+ fetch_status_fields: function(frm) {
+ let allow_statuses = [];
+ let exclude_statuses = [];
+
+ if (frm.doc.document_type) {
+ frappe.model.with_doctype(frm.doc.document_type, () => {
+ let statuses = frappe.meta.get_docfield(frm.doc.document_type, 'status', frm.doc.name).options;
+ statuses = statuses.split('\n');
+
+ exclude_statuses = ['Open', 'Closed'];
+ allow_statuses = statuses.filter((status) => !exclude_statuses.includes(status));
+
+ frm.fields_dict.pause_sla_on.grid.update_docfield_property(
+ 'status', 'options', [''].concat(allow_statuses)
+ );
+
+ exclude_statuses = ['Open'];
+ allow_statuses = statuses.filter((status) => !exclude_statuses.includes(status));
+ frm.fields_dict.sla_fulfilled_on.grid.update_docfield_property(
+ 'status', 'options', [''].concat(allow_statuses)
+ );
+ });
+ }
+
+ frm.refresh_field('pause_sla_on');
+ },
+
+ apply_sla_for_resolution: function(frm) {
+ frm.trigger('toggle_resolution_fields');
+ },
+
+ toggle_resolution_fields: function(frm) {
+ if (cint(frm.doc.apply_sla_for_resolution) === 1) {
+ frm.fields_dict.priorities.grid.update_docfield_property('resolution_time', 'hidden', 0);
+ frm.fields_dict.priorities.grid.update_docfield_property('resolution_time', 'reqd', 1);
+ } else {
+ frm.fields_dict.priorities.grid.update_docfield_property('resolution_time', 'hidden', 1);
+ frm.fields_dict.priorities.grid.update_docfield_property('resolution_time', 'reqd', 0);
+ }
+
+ frm.refresh_field('priorities');
+ },
+
+ onload: function(frm) {
+ frm.set_query("document_type", function() {
+ let invalid_doctypes = frappe.model.core_doctypes_list;
+ invalid_doctypes.push(frm.doc.doctype, 'Cost Center', 'Company');
+
+ return {
+ filters: [
+ ['DocType', 'issingle', '=', 0],
+ ['DocType', 'istable', '=', 0],
+ ['DocType', 'name', 'not in', invalid_doctypes],
+ ['DocType', 'module', 'not in', ["Email", "Core", "Custom", "Event Streaming", "Social", "Data Migration", "Geo", "Desk"]]
+ ]
+ };
});
}
});
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json
index 939c199982..61ca3a334e 100644
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.json
+++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.json
@@ -1,18 +1,18 @@
{
"actions": [],
- "autoname": "format:SLA-{service_level}-{####}",
+ "autoname": "format:SLA-{document_type}-{service_level}-{####}",
"creation": "2018-12-26 21:08:15.448812",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
- "enable",
+ "enabled",
"section_break_2",
- "service_level",
- "default_priority",
+ "document_type",
"default_service_level_agreement",
+ "default_priority",
"column_break_2",
- "employee_group",
+ "service_level",
"holiday_list",
"entity_section",
"entity_type",
@@ -20,13 +20,14 @@
"entity",
"agreement_details_section",
"start_date",
- "active",
"column_break_7",
"end_date",
- "section_break_18",
- "pause_sla_on",
"response_and_resolution_time_section",
+ "apply_sla_for_resolution",
"priorities",
+ "status_details",
+ "sla_fulfilled_on",
+ "pause_sla_on",
"support_and_resolution_section_break",
"support_and_resolution"
],
@@ -36,7 +37,7 @@
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
- "label": "Service Level",
+ "label": "Service Level Name",
"reqd": 1
},
{
@@ -51,20 +52,12 @@
"fieldtype": "Column Break"
},
{
- "fieldname": "employee_group",
- "fieldtype": "Link",
- "in_list_view": 1,
- "in_standard_filter": 1,
- "label": "Employee Group",
- "options": "Employee Group"
- },
- {
+ "depends_on": "eval: !doc.default_service_level_agreement",
"fieldname": "agreement_details_section",
"fieldtype": "Section Break",
"label": "Agreement Details"
},
{
- "depends_on": "eval: !doc.default_service_level_agreement",
"fieldname": "start_date",
"fieldtype": "Date",
"label": "Start Date"
@@ -81,21 +74,18 @@
"label": "End Date"
},
{
- "collapsible": 1,
"fieldname": "response_and_resolution_time_section",
"fieldtype": "Section Break",
"label": "Response and Resolution Time"
},
{
- "collapsible": 1,
"fieldname": "support_and_resolution_section_break",
"fieldtype": "Section Break",
- "label": "Support Hours"
+ "label": "Working Hours"
},
{
"fieldname": "support_and_resolution",
"fieldtype": "Table",
- "label": "Support and Resolution",
"options": "Service Day",
"reqd": 1
},
@@ -106,13 +96,6 @@
"options": "Service Level Priority",
"reqd": 1
},
- {
- "default": "1",
- "fieldname": "active",
- "fieldtype": "Check",
- "label": "Active",
- "read_only": 1
- },
{
"fieldname": "column_break_10",
"fieldtype": "Column Break"
@@ -138,15 +121,10 @@
"label": "Entity Type",
"options": "\nCustomer\nCustomer Group\nTerritory"
},
- {
- "default": "1",
- "fieldname": "enable",
- "fieldtype": "Check",
- "label": "Enable"
- },
{
"fieldname": "section_break_2",
- "fieldtype": "Section Break"
+ "fieldtype": "Section Break",
+ "hide_border": 1
},
{
"default": "0",
@@ -161,20 +139,46 @@
"options": "Issue Priority",
"read_only": 1
},
- {
- "fieldname": "section_break_18",
- "fieldtype": "Section Break",
- "hide_border": 1
- },
{
"fieldname": "pause_sla_on",
"fieldtype": "Table",
- "label": "Pause SLA On",
+ "label": "SLA Paused On",
"options": "Pause SLA On Status"
+ },
+ {
+ "fieldname": "document_type",
+ "fieldtype": "Link",
+ "label": "Document Type",
+ "options": "DocType",
+ "reqd": 1
+ },
+ {
+ "default": "1",
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "label": "Enabled"
+ },
+ {
+ "fieldname": "status_details",
+ "fieldtype": "Section Break",
+ "label": "Status Details"
+ },
+ {
+ "fieldname": "sla_fulfilled_on",
+ "fieldtype": "Table",
+ "label": "SLA Fulfilled On",
+ "options": "SLA Fulfilled On Status",
+ "reqd": 1
+ },
+ {
+ "default": "1",
+ "fieldname": "apply_sla_for_resolution",
+ "fieldtype": "Check",
+ "label": "Apply SLA for Resolution Time"
}
],
"links": [],
- "modified": "2020-06-10 12:30:15.050785",
+ "modified": "2021-05-29 13:35:41.956849",
"modified_by": "Administrator",
"module": "Support",
"name": "Service Level Agreement",
diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
index 70c469663b..60e5fbe80e 100644
--- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
+++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py
@@ -6,44 +6,43 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
-from frappe.utils import getdate, get_weekdays, get_link_to_form
+from frappe.core.utils import get_parent_doc
+from frappe.utils import time_diff_in_seconds, getdate, get_weekdays, add_to_date, get_time, get_datetime, \
+ get_time_zone, to_timedelta, get_datetime_str, get_link_to_form, cint
+from datetime import datetime
+from erpnext.support.doctype.issue.issue import get_holidays
class ServiceLevelAgreement(Document):
-
def validate(self):
self.validate_doc()
+ self.validate_status_field()
self.check_priorities()
self.check_support_and_resolution()
def check_priorities(self):
- default_priority = []
priorities = []
for priority in self.priorities:
# Check if response and resolution time is set for every priority
- if not priority.response_time or not priority.resolution_time:
- frappe.throw(_("Set Response Time and Resolution Time for Priority {0} in row {1}.").format(priority.priority, priority.idx))
+ if not priority.response_time:
+ frappe.throw(_("Set Response Time for Priority {0} in row {1}.").format(priority.priority, priority.idx))
+
+ if self.apply_sla_for_resolution:
+ if not priority.resolution_time:
+ frappe.throw(_("Set Response Time for Priority {0} in row {1}.").format(priority.priority, priority.idx))
+
+ response = priority.response_time
+ resolution = priority.resolution_time
+ if response > resolution:
+ frappe.throw(_("Response Time for {0} priority in row {1} can't be greater than Resolution Time.").format(priority.priority, priority.idx))
priorities.append(priority.priority)
- if priority.default_priority:
- default_priority.append(priority.default_priority)
-
- response = priority.response_time
- resolution = priority.resolution_time
-
- if response > resolution:
- frappe.throw(_("Response Time for {0} priority in row {1} can't be greater than Resolution Time.").format(priority.priority, priority.idx))
-
# Check if repeated priority
if not len(set(priorities)) == len(priorities):
repeated_priority = get_repeated(priorities)
frappe.throw(_("Priority {0} has been repeated.").format(repeated_priority))
- # Check if repeated default priority
- if not len(set(default_priority)) == len(default_priority):
- frappe.throw(_("Select only one Priority as Default."))
-
# set default priority from priorities
try:
self.default_priority = next(d.priority for d in self.priorities if d.default_priority)
@@ -55,17 +54,12 @@ class ServiceLevelAgreement(Document):
support_days = []
for support_and_resolution in self.support_and_resolution:
- # Check if start and end time is set for every support day
- if not (support_and_resolution.start_time or support_and_resolution.end_time):
- frappe.throw(_("Set Start Time and End Time for \
- Support Day {0} at index {1}.".format(support_and_resolution.workday, support_and_resolution.idx)))
-
support_days.append(support_and_resolution.workday)
support_and_resolution.idx = week.index(support_and_resolution.workday) + 1
- if support_and_resolution.start_time >= support_and_resolution.end_time:
- frappe.throw(_("Start Time can't be greater than or equal to End Time \
- for {0}.".format(support_and_resolution.workday)))
+ if to_timedelta(support_and_resolution.start_time) >= to_timedelta(support_and_resolution.end_time):
+ frappe.throw(_("Start Time can't be greater than or equal to End Time for {0}.").format(
+ support_and_resolution.workday))
# Check for repeated workday
if not len(set(support_days)) == len(support_days):
@@ -73,24 +67,34 @@ class ServiceLevelAgreement(Document):
frappe.throw(_("Workday {0} has been repeated.").format(repeated_days))
def validate_doc(self):
- if not frappe.db.get_single_value("Support Settings", "track_service_level_agreement") and self.enable:
+ if self.enabled and self.document_type == "Issue" \
+ and not frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
frappe.throw(_("{0} is not enabled in {1}").format(frappe.bold("Track Service Level Agreement"),
get_link_to_form("Support Settings", "Support Settings")))
- if self.default_service_level_agreement:
- if frappe.db.exists("Service Level Agreement", {"default_service_level_agreement": "1", "name": ["!=", self.name]}):
- frappe.throw(_("A Default Service Level Agreement already exists."))
- else:
- if self.start_date and self.end_date:
- if getdate(self.start_date) >= getdate(self.end_date):
- frappe.throw(_("Start Date of Agreement can't be greater than or equal to End Date."))
+ if self.default_service_level_agreement and frappe.db.exists("Service Level Agreement", {
+ "document_type": self.document_type,
+ "default_service_level_agreement": "1",
+ "name": ["!=", self.name]
+ }):
+ frappe.throw(_("Default Service Level Agreement for {0} already exists.").format(self.document_type))
- if getdate(self.end_date) < getdate(frappe.utils.getdate()):
- frappe.throw(_("End Date of Agreement can't be less than today."))
+ if self.start_date and self.end_date:
+ self.validate_from_to_dates(self.start_date, self.end_date)
- if self.entity_type and self.entity:
- if frappe.db.exists("Service Level Agreement", {"entity_type": self.entity_type, "entity": self.entity, "name": ["!=", self.name]}):
- frappe.throw(_("Service Level Agreement with Entity Type {0} and Entity {1} already exists.").format(self.entity_type, self.entity))
+ if self.entity_type and self.entity and frappe.db.exists("Service Level Agreement", {
+ "entity_type": self.entity_type,
+ "entity": self.entity,
+ "name": ["!=", self.name]
+ }):
+ frappe.throw(_("Service Level Agreement for {0} {1} already exists.").format(
+ frappe.bold(self.entity_type), frappe.bold(self.entity)))
+
+ def validate_status_field(self):
+ meta = frappe.get_meta(self.document_type)
+ if not meta.get_field("status"):
+ frappe.throw(_("The Document Type {0} must have a Status field to configure Service Level Agreement").format(
+ frappe.bold(self.document_type)))
def get_service_level_agreement_priority(self, priority):
priority = frappe.get_doc("Service Level Priority", {"priority": priority, "parent": self.name})
@@ -101,78 +105,169 @@ class ServiceLevelAgreement(Document):
"resolution_time": priority.resolution_time
})
+ def before_insert(self):
+ # no need to set up SLA fields for Issue dt as they are standard fields in Issue
+ if self.document_type == "Issue":
+ return
+
+ service_level_agreement_fields = get_service_level_agreement_fields()
+ meta = frappe.get_meta(self.document_type, cached=False)
+
+ if meta.custom:
+ self.create_docfields(meta, service_level_agreement_fields)
+ else:
+ self.create_custom_fields(meta, service_level_agreement_fields)
+
+ def on_trash(self):
+ set_documents_with_active_service_level_agreement()
+
+ def after_insert(self):
+ set_documents_with_active_service_level_agreement()
+
+ def on_update(self):
+ set_documents_with_active_service_level_agreement()
+
+ def create_docfields(self, meta, service_level_agreement_fields):
+ last_index = len(meta.fields)
+
+ for field in service_level_agreement_fields:
+ if not meta.has_field(field.get("fieldname")):
+ last_index += 1
+
+ frappe.get_doc({
+ "doctype": "DocField",
+ "idx": last_index,
+ "parenttype": "DocType",
+ "parentfield": "fields",
+ "parent": self.document_type,
+ "label": field.get("label"),
+ "fieldname": field.get("fieldname"),
+ "fieldtype": field.get("fieldtype"),
+ "collapsible": field.get("collapsible"),
+ "options": field.get("options"),
+ "read_only": field.get("read_only"),
+ "hidden": field.get("hidden"),
+ "description": field.get("description"),
+ "default": field.get("default"),
+ }).insert(ignore_permissions=True)
+ else:
+ existing_field = meta.get_field(field.get("fieldname"))
+ self.reset_field_properties(existing_field, "DocField", field)
+
+ # to update meta and modified timestamp
+ frappe.get_doc('DocType', self.document_type).save(ignore_permissions=True)
+
+ def create_custom_fields(self, meta, service_level_agreement_fields):
+ for field in service_level_agreement_fields:
+ if not meta.has_field(field.get("fieldname")):
+ frappe.get_doc({
+ "doctype": "Custom Field",
+ "dt": self.document_type,
+ "label": field.get("label"),
+ "fieldname": field.get("fieldname"),
+ "fieldtype": field.get("fieldtype"),
+ "insert_after": "append",
+ "collapsible": field.get("collapsible"),
+ "options": field.get("options"),
+ "read_only": field.get("read_only"),
+ "hidden": field.get("hidden"),
+ "description": field.get("description"),
+ "default": field.get("default"),
+ }).insert(ignore_permissions=True)
+ else:
+ existing_field = meta.get_field(field.get("fieldname"))
+ self.reset_field_properties(existing_field, "Custom Field", field)
+
+ def reset_field_properties(self, field, field_dt, sla_field):
+ field = frappe.get_doc(field_dt, {"fieldname": field.fieldname})
+ field.label = sla_field.get("label")
+ field.fieldname = sla_field.get("fieldname")
+ field.fieldtype = sla_field.get("fieldtype")
+ field.collapsible = sla_field.get("collapsible")
+ field.hidden = sla_field.get("hidden")
+ field.options = sla_field.get("options")
+ field.read_only = sla_field.get("read_only")
+ field.hidden = sla_field.get("hidden")
+ field.description = sla_field.get("description")
+ field.default = sla_field.get("default")
+ field.save(ignore_permissions=True)
+
+
def check_agreement_status():
- service_level_agreements = frappe.get_list("Service Level Agreement", filters=[
- {"active": 1},
+ service_level_agreements = frappe.get_all("Service Level Agreement", filters=[
+ {"enabled": 1},
{"default_service_level_agreement": 0}
], fields=["name"])
for service_level_agreement in service_level_agreements:
doc = frappe.get_doc("Service Level Agreement", service_level_agreement.name)
if doc.end_date and getdate(doc.end_date) < getdate(frappe.utils.getdate()):
- frappe.db.set_value("Service Level Agreement", service_level_agreement.name, "active", 0)
+ frappe.db.set_value("Service Level Agreement", service_level_agreement.name, "enabled", 0)
-def get_active_service_level_agreement_for(priority, customer=None, service_level_agreement=None):
- if not frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
+
+def get_active_service_level_agreement_for(doctype, priority, customer=None, service_level_agreement=None):
+ if doctype == "Issue" and not frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
return
filters = [
- ["Service Level Agreement", "active", "=", 1],
- ["Service Level Agreement", "enable", "=", 1]
+ ["Service Level Agreement", "document_type", "=", doctype],
+ ["Service Level Agreement", "enabled", "=", 1]
]
-
if priority:
filters.append(["Service Level Priority", "priority", "=", priority])
- or_filters = [
- ["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer)]]
- ]
+ or_filters = []
if service_level_agreement:
or_filters = [
["Service Level Agreement", "name", "=", service_level_agreement],
]
+ if customer:
+ or_filters.append(
+ ["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer)]]
+ )
or_filters.append(["Service Level Agreement", "default_service_level_agreement", "=", 1])
- agreement = frappe.get_list("Service Level Agreement", filters=filters, or_filters=or_filters,
- fields=["name", "default_priority"])
+ agreement = frappe.get_all("Service Level Agreement", filters=filters, or_filters=or_filters,
+ fields=["name", "default_priority", "apply_sla_for_resolution"])
return agreement[0] if agreement else None
+
def get_customer_group(customer):
- if customer:
- return frappe.db.get_value("Customer", customer, "customer_group")
+ return frappe.db.get_value("Customer", customer, "customer_group") if customer else None
+
def get_customer_territory(customer):
- if customer:
- return frappe.db.get_value("Customer", customer, "territory")
+ return frappe.db.get_value("Customer", customer, "territory") if customer else None
+
@frappe.whitelist()
-def get_service_level_agreement_filters(name, customer=None):
+def get_service_level_agreement_filters(doctype, name, customer=None):
if not frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
return
filters = [
- ["Service Level Agreement", "active", "=", 1],
- ["Service Level Agreement", "enable", "=", 1]
+ ["Service Level Agreement", "document_type", "=", doctype],
+ ["Service Level Agreement", "enabled", "=", 1]
]
- if not customer:
- or_filters = [
- ["Service Level Agreement", "default_service_level_agreement", "=", 1]
- ]
- else:
+ or_filters = [
+ ["Service Level Agreement", "default_service_level_agreement", "=", 1]
+ ]
+
+ if customer:
# Include SLA with No Entity and Entity Type
- or_filters = [
- ["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer), ""]],
- ["Service Level Agreement", "default_service_level_agreement", "=", 1]
- ]
+ or_filters.append(
+ ["Service Level Agreement", "entity", "in", [customer, get_customer_group(customer), get_customer_territory(customer), ""]]
+ )
return {
- "priority": [priority.priority for priority in frappe.get_list("Service Level Priority", filters={"parent": name}, fields=["priority"])],
- "service_level_agreements": [d.name for d in frappe.get_list("Service Level Agreement", filters=filters, or_filters=or_filters)]
+ "priority": [priority.priority for priority in frappe.get_all("Service Level Priority", filters={"parent": name}, fields=["priority"])],
+ "service_level_agreements": [d.name for d in frappe.get_all("Service Level Agreement", filters=filters, or_filters=or_filters)]
}
+
def get_repeated(values):
unique_list = []
diff = []
@@ -183,3 +278,573 @@ def get_repeated(values):
if value not in diff:
diff.append(str(value))
return " ".join(diff)
+
+
+def get_documents_with_active_service_level_agreement():
+ if not frappe.cache().hget("service_level_agreement", "active"):
+ set_documents_with_active_service_level_agreement()
+
+ return frappe.cache().hget("service_level_agreement", "active")
+
+
+def set_documents_with_active_service_level_agreement():
+ active = [sla.document_type for sla in frappe.get_all("Service Level Agreement", fields=["document_type"])]
+ frappe.cache().hset("service_level_agreement", "active", active)
+
+
+def apply(doc, method=None):
+ # Applies SLA to document on validate
+ if frappe.flags.in_patch or frappe.flags.in_install or frappe.flags.in_setup_wizard or \
+ doc.doctype not in get_documents_with_active_service_level_agreement():
+ return
+
+ service_level_agreement = get_active_service_level_agreement_for(doctype=doc.get("doctype"), priority=doc.get("priority"),
+ customer=doc.get("customer"), service_level_agreement=doc.get("service_level_agreement"))
+
+ if not service_level_agreement:
+ return
+
+ set_sla_properties(doc, service_level_agreement)
+
+
+def set_sla_properties(doc, service_level_agreement):
+ if frappe.db.exists(doc.doctype, doc.name):
+ from_db = frappe.get_doc(doc.doctype, doc.name)
+ else:
+ from_db = frappe._dict({})
+
+ meta = frappe.get_meta(doc.doctype)
+
+ if meta.has_field("customer") and service_level_agreement.customer and doc.get("customer") and \
+ not service_level_agreement.customer == doc.get("customer"):
+ frappe.throw(_("Service Level Agreement {0} is specific to Customer {1}").format(service_level_agreement.name,
+ service_level_agreement.customer))
+
+ doc.service_level_agreement = service_level_agreement.name
+ doc.priority = doc.get("priority") or service_level_agreement.default_priority
+ priority = get_priority(doc)
+
+ if not doc.creation:
+ doc.creation = now_datetime(doc.get("owner"))
+
+ if meta.has_field("service_level_agreement_creation"):
+ doc.service_level_agreement_creation = now_datetime(doc.get("owner"))
+
+ start_date_time = get_datetime(doc.get("service_level_agreement_creation") or doc.creation)
+
+ set_response_by_and_variance(doc, meta, start_date_time, priority)
+ if service_level_agreement.apply_sla_for_resolution:
+ set_resolution_by_and_variance(doc, meta, start_date_time, priority)
+
+ update_status(doc, from_db, meta)
+
+
+def update_status(doc, from_db, meta):
+ if meta.has_field("status"):
+ if meta.has_field("first_responded_on") and doc.status != "Open" and \
+ from_db.status == "Open" and not doc.first_responded_on:
+ doc.first_responded_on = frappe.flags.current_time or now_datetime(doc.get("owner"))
+
+ if meta.has_field("service_level_agreement") and doc.service_level_agreement:
+ # mark sla status as fulfilled based on the configuration
+ fulfillment_statuses = [entry.status for entry in frappe.db.get_all("SLA Fulfilled On Status", filters={
+ "parent": doc.service_level_agreement
+ }, fields=["status"])]
+
+ if doc.status in fulfillment_statuses and from_db.status not in fulfillment_statuses:
+ apply_sla_for_resolution = frappe.db.get_value("Service Level Agreement", doc.service_level_agreement,
+ "apply_sla_for_resolution")
+
+ if apply_sla_for_resolution and meta.has_field("resolution_date"):
+ doc.resolution_date = frappe.flags.current_time or now_datetime(doc.get("owner"))
+
+ if meta.has_field("agreement_status") and from_db.agreement_status == "Ongoing":
+ set_service_level_agreement_variance(doc.doctype, doc.name)
+ update_agreement_status(doc, meta)
+
+ if apply_sla_for_resolution:
+ set_resolution_time(doc, meta)
+ set_user_resolution_time(doc, meta)
+
+ if doc.status == "Open" and from_db.status != "Open":
+ # if no date, it should be set as None and not a blank string "", as per mysql strict config
+ # enable SLA and variance on Reopen
+ reset_metrics(doc, meta)
+ set_service_level_agreement_variance(doc.doctype, doc.name)
+
+ handle_hold_time(doc, meta, from_db.status)
+
+
+def get_expected_time_for(parameter, service_level, start_date_time):
+ current_date_time = start_date_time
+ expected_time = current_date_time
+ start_time = end_time = None
+ expected_time_is_set = 0
+
+ allotted_seconds = get_allotted_seconds(parameter, service_level)
+ support_days = get_support_days(service_level)
+ holidays = get_holidays(service_level.get("holiday_list"))
+ weekdays = get_weekdays()
+
+ while not expected_time_is_set:
+ current_weekday = weekdays[current_date_time.weekday()]
+
+ if not is_holiday(current_date_time, holidays) and current_weekday in support_days:
+ if getdate(current_date_time) == getdate(start_date_time) \
+ and get_time_in_timedelta(current_date_time.time()) > support_days[current_weekday].start_time:
+ start_time = current_date_time - datetime(current_date_time.year, current_date_time.month, current_date_time.day)
+ else:
+ start_time = support_days[current_weekday].start_time
+
+ end_time = support_days[current_weekday].end_time
+ time_left_today = time_diff_in_seconds(end_time, start_time)
+ # no time left for support today
+ if time_left_today <= 0:
+ pass
+
+ elif allotted_seconds:
+ if time_left_today >= allotted_seconds:
+ expected_time = datetime.combine(getdate(current_date_time), get_time(start_time))
+ expected_time = add_to_date(expected_time, seconds=allotted_seconds)
+ expected_time_is_set = 1
+ else:
+ allotted_seconds = allotted_seconds - time_left_today
+
+ if not expected_time_is_set:
+ current_date_time = add_to_date(current_date_time, days=1)
+
+ if end_time and allotted_seconds >= 86400:
+ current_date_time = datetime.combine(getdate(current_date_time), get_time(end_time))
+ else:
+ current_date_time = expected_time
+
+ return current_date_time
+
+
+def get_allotted_seconds(parameter, service_level):
+ allotted_seconds = 0
+ if parameter == "response":
+ allotted_seconds = service_level.get("response_time")
+ elif parameter == "resolution":
+ allotted_seconds = service_level.get("resolution_time")
+ else:
+ frappe.throw(_("{0} parameter is invalid").format(parameter))
+
+ return allotted_seconds
+
+
+def get_support_days(service_level):
+ support_days = {}
+ for service in service_level.get("support_and_resolution"):
+ support_days[service.workday] = frappe._dict({
+ "start_time": service.start_time,
+ "end_time": service.end_time,
+ })
+ return support_days
+
+
+def set_service_level_agreement_variance(doctype, doc=None):
+
+ filters = {"status": "Open", "agreement_status": "Ongoing"}
+
+ if doc:
+ filters = {"name": doc}
+
+ for entry in frappe.get_all(doctype, filters=filters):
+ current_doc = frappe.get_doc(doctype, entry.name)
+ current_time = frappe.flags.current_time or now_datetime(current_doc.get("owner"))
+ apply_sla_for_resolution = frappe.db.get_value("Service Level Agreement", current_doc.service_level_agreement,
+ "apply_sla_for_resolution")
+
+ if not current_doc.first_responded_on: # first_responded_on set when first reply is sent to customer
+ variance = round(time_diff_in_seconds(current_doc.response_by, current_time), 2)
+ frappe.db.set_value(current_doc.doctype, current_doc.name, "response_by_variance", variance, update_modified=False)
+
+ if variance < 0:
+ frappe.db.set_value(current_doc.doctype, current_doc.name, "agreement_status", "Failed", update_modified=False)
+
+ if apply_sla_for_resolution and not current_doc.get("resolution_date"): # resolution_date set when issue has been closed
+ variance = round(time_diff_in_seconds(current_doc.resolution_by, current_time), 2)
+ frappe.db.set_value(current_doc.doctype, current_doc.name, "resolution_by_variance", variance, update_modified=False)
+
+ if variance < 0:
+ frappe.db.set_value(current_doc.doctype, current_doc.name, "agreement_status", "Failed", update_modified=False)
+
+
+def set_user_resolution_time(doc, meta):
+ # total time taken by a user to close the issue apart from wait_time
+ if not meta.has_field("user_resolution_time"):
+ return
+
+ communications = frappe.get_all("Communication", filters={
+ "reference_doctype": doc.doctype,
+ "reference_name": doc.name
+ }, fields=["sent_or_received", "name", "creation"], order_by="creation")
+
+ pending_time = []
+ for i in range(len(communications)):
+ if communications[i].sent_or_received == "Received" and communications[i-1].sent_or_received == "Sent":
+ wait_time = time_diff_in_seconds(communications[i].creation, communications[i-1].creation)
+ if wait_time > 0:
+ pending_time.append(wait_time)
+
+ total_pending_time = sum(pending_time)
+ resolution_time_in_secs = time_diff_in_seconds(doc.resolution_date, doc.creation)
+ doc.user_resolution_time = resolution_time_in_secs - total_pending_time
+
+
+def change_service_level_agreement_and_priority(self):
+ if self.service_level_agreement and frappe.db.exists("Issue", self.name) and \
+ frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):
+
+ if not self.priority == frappe.db.get_value("Issue", self.name, "priority"):
+ self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
+ frappe.msgprint(_("Priority has been changed to {0}.").format(self.priority))
+
+ if not self.service_level_agreement == frappe.db.get_value("Issue", self.name, "service_level_agreement"):
+ self.set_response_and_resolution_time(priority=self.priority, service_level_agreement=self.service_level_agreement)
+ frappe.msgprint(_("Service Level Agreement has been changed to {0}.").format(self.service_level_agreement))
+
+
+def get_priority(doc):
+ service_level_agreement = frappe.get_doc("Service Level Agreement", doc.service_level_agreement)
+ priority = service_level_agreement.get_service_level_agreement_priority(doc.priority)
+ priority.update({
+ "support_and_resolution": service_level_agreement.support_and_resolution,
+ "holiday_list": service_level_agreement.holiday_list
+ })
+ return priority
+
+
+def reset_service_level_agreement(doc, reason, user):
+ if not frappe.db.get_single_value("Support Settings", "allow_resetting_service_level_agreement"):
+ frappe.throw(_("Allow Resetting Service Level Agreement from Support Settings."))
+
+ frappe.get_doc({
+ "doctype": "Comment",
+ "comment_type": "Info",
+ "reference_doctype": doc.doctype,
+ "reference_name": doc.name,
+ "comment_email": user,
+ "content": " resetted Service Level Agreement - {0}".format(_(reason)),
+ }).insert(ignore_permissions=True)
+
+ doc.service_level_agreement_creation = now_datetime(doc.get("owner"))
+ doc.set_response_and_resolution_time(priority=doc.priority, service_level_agreement=doc.service_level_agreement)
+ doc.agreement_status = "Ongoing"
+ doc.save()
+
+
+def reset_metrics(doc, meta):
+ if meta.has_field("resolution_date"):
+ doc.resolution_date = None
+
+ if not meta.has_field("resolution_time"):
+ doc.resolution_time = None
+
+ if not meta.has_field("user_resolution_time"):
+ doc.user_resolution_time = None
+
+ if meta.has_field("agreement_status"):
+ doc.agreement_status = "Ongoing"
+
+
+def set_resolution_time(doc, meta):
+ # total time taken from issue creation to closing
+ if not meta.has_field("resolution_time"):
+ return
+
+ doc.resolution_time = time_diff_in_seconds(doc.resolution_date, doc.creation)
+
+
+# called via hooks on communication update
+def update_hold_time(doc, status):
+ parent = get_parent_doc(doc)
+ if not parent:
+ return
+
+ if doc.communication_type == "Comment":
+ return
+
+ status_field = parent.meta.get_field("status")
+ if status_field:
+ options = (status_field.options or "").splitlines()
+
+ # if status has a "Replied" option, then handle hold time
+ if ("Replied" in options) and doc.sent_or_received == "Received":
+ meta = frappe.get_meta(parent.doctype)
+ handle_hold_time(parent, meta, 'Replied')
+
+
+def handle_hold_time(doc, meta, status):
+ if meta.has_field("service_level_agreement") and doc.service_level_agreement:
+ # set response and resolution variance as None as the issue is on Hold for status as Replied
+ hold_statuses = [entry.status for entry in frappe.db.get_all("Pause SLA On Status", filters={
+ "parent": doc.service_level_agreement
+ }, fields=["status"])]
+
+ if not hold_statuses:
+ return
+
+ if meta.has_field("status") and doc.status in hold_statuses and status not in hold_statuses:
+ apply_hold_status(doc, meta)
+
+ # calculate hold time when status is changed from any hold status to any non-hold status
+ if meta.has_field("status") and doc.status not in hold_statuses and status in hold_statuses:
+ reset_hold_status_and_update_hold_time(doc, meta)
+
+
+def apply_hold_status(doc, meta):
+ update_values = {'on_hold_since': frappe.flags.current_time or now_datetime(doc.get("owner"))}
+
+ if meta.has_field("first_responded_on") and not doc.first_responded_on:
+ update_values['response_by'] = None
+ update_values['response_by_variance'] = 0
+
+ update_values['resolution_by'] = None
+ update_values['resolution_by_variance'] = 0
+
+ doc.db_set(update_values)
+
+
+def reset_hold_status_and_update_hold_time(doc, meta):
+ hold_time = doc.total_hold_time if meta.has_field("total_hold_time") and doc.total_hold_time else 0
+ now_time = frappe.flags.current_time or now_datetime(doc.get("owner"))
+ last_hold_time = 0
+ update_values = {}
+
+ if meta.has_field("on_hold_since") and doc.on_hold_since:
+ # last_hold_time will be added to the sla variables
+ last_hold_time = time_diff_in_seconds(now_time, doc.on_hold_since)
+ update_values['total_hold_time'] = hold_time + last_hold_time
+
+ # re-calculate SLA variables after issue changes from any hold status to any non-hold status
+ start_date_time = get_datetime(doc.get("service_level_agreement_creation") or doc.creation)
+ priority = get_priority(doc)
+ now_time = frappe.flags.current_time or now_datetime(doc.get("owner"))
+
+ # add hold time to response by variance
+ if meta.has_field("first_responded_on") and not doc.first_responded_on:
+ response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
+ response_by = add_to_date(response_by, seconds=round(last_hold_time))
+ response_by_variance = round(time_diff_in_seconds(response_by, now_time))
+
+ update_values['response_by'] = response_by
+ update_values['response_by_variance'] = response_by_variance + last_hold_time
+
+ # add hold time to resolution by variance
+ if frappe.db.get_value("Service Level Agreement", doc.service_level_agreement, "apply_sla_for_resolution"):
+ resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
+ resolution_by = add_to_date(resolution_by, seconds=round(last_hold_time))
+ resolution_by_variance = round(time_diff_in_seconds(resolution_by, now_time))
+
+ update_values['resolution_by'] = resolution_by
+ update_values['resolution_by_variance'] = resolution_by_variance + last_hold_time
+
+ update_values['on_hold_since'] = None
+
+ doc.db_set(update_values)
+
+
+def get_service_level_agreement_fields():
+ return [
+ {
+ "collapsible": 1,
+ "fieldname": "service_level_section",
+ "fieldtype": "Section Break",
+ "label": "Service Level"
+ },
+ {
+ "fieldname": "service_level_agreement",
+ "fieldtype": "Link",
+ "label": "Service Level Agreement",
+ "options": "Service Level Agreement"
+ },
+ {
+ "fieldname": "priority",
+ "fieldtype": "Link",
+ "label": "Priority",
+ "options": "Issue Priority"
+ },
+ {
+ "fieldname": "response_by",
+ "fieldtype": "Datetime",
+ "label": "Response By",
+ "read_only": 1
+ },
+ {
+ "fieldname": "response_by_variance",
+ "fieldtype": "Duration",
+ "hide_seconds": 1,
+ "label": "Response By Variance",
+ "read_only": 1
+ },
+ {
+ "fieldname": "first_responded_on",
+ "fieldtype": "Datetime",
+ "label": "First Responded On",
+ "read_only": 1
+ },
+ {
+ "fieldname": "on_hold_since",
+ "fieldtype": "Datetime",
+ "hidden": 1,
+ "label": "On Hold Since",
+ "read_only": 1
+ },
+ {
+ "fieldname": "total_hold_time",
+ "fieldtype": "Duration",
+ "label": "Total Hold Time",
+ "read_only": 1
+ },
+ {
+ "fieldname": "cb",
+ "fieldtype": "Column Break",
+ "read_only": 1
+ },
+ {
+ "default": "Ongoing",
+ "fieldname": "agreement_status",
+ "fieldtype": "Select",
+ "label": "Service Level Agreement Status",
+ "options": "Ongoing\nFulfilled\nFailed",
+ "read_only": 1
+ },
+ {
+ "fieldname": "resolution_by",
+ "fieldtype": "Datetime",
+ "label": "Resolution By",
+ "read_only": 1
+ },
+ {
+ "fieldname": "resolution_by_variance",
+ "fieldtype": "Duration",
+ "hide_seconds": 1,
+ "label": "Resolution By Variance",
+ "read_only": 1
+ },
+ {
+ "fieldname": "service_level_agreement_creation",
+ "fieldtype": "Datetime",
+ "hidden": 1,
+ "label": "Service Level Agreement Creation",
+ "read_only": 1
+ },
+ {
+ "depends_on": "eval:!doc.__islocal",
+ "fieldname": "resolution_date",
+ "fieldtype": "Datetime",
+ "label": "Resolution Date",
+ "no_copy": 1,
+ "read_only": 1
+ }
+ ]
+
+
+def update_agreement_status_on_custom_status(doc):
+ # Update Agreement Fulfilled status using Custom Scripts for Custom Status
+
+ meta = frappe.get_meta(doc.doctype)
+ now_time = frappe.flags.current_time or now_datetime(doc.get("owner"))
+ if meta.has_field("first_responded_on") and not doc.first_responded_on:
+ # first_responded_on set when first reply is sent to customer
+ doc.response_by_variance = round(time_diff_in_seconds(doc.response_by, now_time), 2)
+
+ if meta.has_field("resolution_date") and not doc.resolution_date:
+ # resolution_date set when issue has been closed
+ doc.resolution_by_variance = round(time_diff_in_seconds(doc.resolution_by, now_time), 2)
+
+ if meta.has_field("agreement_status"):
+ doc.agreement_status = "Fulfilled" if doc.response_by_variance > 0 and doc.resolution_by_variance > 0 else "Failed"
+
+
+def update_agreement_status(doc, meta):
+ if meta.has_field("service_level_agreement") and meta.has_field("agreement_status") and \
+ doc.service_level_agreement and doc.agreement_status == "Ongoing":
+
+ apply_sla_for_resolution = frappe.db.get_value("Service Level Agreement", doc.service_level_agreement,
+ "apply_sla_for_resolution")
+
+ # if SLA is applied for resolution check for response and resolution, else only response
+ if apply_sla_for_resolution:
+ if meta.has_field("response_by_variance") and meta.has_field("resolution_by_variance"):
+ if cint(frappe.db.get_value(doc.doctype, doc.name, "response_by_variance")) < 0 or \
+ cint(frappe.db.get_value(doc.doctype, doc.name, "resolution_by_variance")) < 0:
+
+ doc.agreement_status = "Failed"
+ else:
+ doc.agreement_status = "Fulfilled"
+ else:
+ if meta.has_field("response_by_variance") and \
+ cint(frappe.db.get_value(doc.doctype, doc.name, "response_by_variance")) < 0:
+ doc.agreement_status = "Failed"
+ else:
+ doc.agreement_status = "Fulfilled"
+
+
+def is_holiday(date, holidays):
+ return getdate(date) in holidays
+
+
+def get_time_in_timedelta(time):
+ """Converts datetime.time(10, 36, 55, 961454) to datetime.timedelta(seconds=38215)."""
+ import datetime
+ return datetime.timedelta(hours=time.hour, minutes=time.minute, seconds=time.second)
+
+
+def set_response_by_and_variance(doc, meta, start_date_time, priority):
+ if meta.has_field("response_by"):
+ doc.response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
+
+ if meta.has_field("response_by_variance"):
+ now_time = frappe.flags.current_time or now_datetime(doc.get("owner"))
+ doc.response_by_variance = round(time_diff_in_seconds(doc.response_by, now_time), 2)
+
+def set_resolution_by_and_variance(doc, meta, start_date_time, priority):
+ if meta.has_field("resolution_by"):
+ doc.resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
+
+ if meta.has_field("resolution_by_variance"):
+ now_time = frappe.flags.current_time or now_datetime(doc.get("owner"))
+ doc.resolution_by_variance = round(time_diff_in_seconds(doc.resolution_by, now_time), 2)
+
+
+def now_datetime(user):
+ dt = convert_utc_to_user_timezone(datetime.utcnow(), user)
+ return dt.replace(tzinfo=None)
+
+
+def convert_utc_to_user_timezone(utc_timestamp, user):
+ from pytz import timezone, UnknownTimeZoneError
+
+ user_tz = get_tz(user)
+ utcnow = timezone('UTC').localize(utc_timestamp)
+ try:
+ return utcnow.astimezone(timezone(user_tz))
+ except UnknownTimeZoneError:
+ return utcnow
+
+
+def get_tz(user):
+ return frappe.db.get_value("User", user, "time_zone") or get_time_zone()
+
+
+@frappe.whitelist()
+def get_user_time(user, to_string=False):
+ return get_datetime_str(now_datetime(user)) if to_string else now_datetime(user)
+
+
+@frappe.whitelist()
+def get_sla_doctypes():
+ doctypes = []
+ data = frappe.get_list('Service Level Agreement',
+ {'enabled': 1},
+ ['document_type'],
+ distinct=1
+ )
+
+ for entry in data:
+ doctypes.append(entry.document_type)
+
+ return doctypes
diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
index 07ef368cbe..2a8446d29f 100644
--- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
+++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
@@ -5,19 +5,20 @@ from __future__ import unicode_literals
import frappe
import unittest
-from erpnext.hr.doctype.employee_group.test_employee_group import make_employee_group
+import datetime
+from frappe.utils import flt
from erpnext.support.doctype.issue_priority.test_issue_priority import make_priorities
+from erpnext.support.doctype.service_level_agreement.service_level_agreement import get_service_level_agreement_fields
class TestServiceLevelAgreement(unittest.TestCase):
def setUp(self):
- frappe.db.sql("delete from `tabService Level Agreement`")
frappe.db.set_value("Support Settings", None, "track_service_level_agreement", 1)
+ frappe.db.sql("delete from `tabLead`")
def test_service_level_agreement(self):
# Default Service Level Agreement
create_default_service_level_agreement = create_service_level_agreement(default_service_level_agreement=1,
- holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
- entity_type=None, entity=None, response_time=14400, resolution_time=21600)
+ holiday_list="__Test Holiday List", entity_type=None, entity=None, response_time=14400, resolution_time=21600)
get_default_service_level_agreement = get_service_level_agreement(default_service_level_agreement=1)
@@ -29,8 +30,8 @@ class TestServiceLevelAgreement(unittest.TestCase):
# Service Level Agreement for Customer
customer = create_customer()
create_customer_service_level_agreement = create_service_level_agreement(default_service_level_agreement=0,
- holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
- entity_type="Customer", entity=customer, response_time=7200, resolution_time=10800)
+ holiday_list="__Test Holiday List", entity_type="Customer", entity=customer,
+ response_time=7200, resolution_time=10800)
get_customer_service_level_agreement = get_service_level_agreement(entity_type="Customer", entity=customer)
self.assertEqual(create_customer_service_level_agreement.name, get_customer_service_level_agreement.name)
@@ -41,8 +42,8 @@ class TestServiceLevelAgreement(unittest.TestCase):
# Service Level Agreement for Customer Group
customer_group = create_customer_group()
create_customer_group_service_level_agreement = create_service_level_agreement(default_service_level_agreement=0,
- holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
- entity_type="Customer Group", entity=customer_group, response_time=7200, resolution_time=10800)
+ holiday_list="__Test Holiday List", entity_type="Customer Group", entity=customer_group,
+ response_time=7200, resolution_time=10800)
get_customer_group_service_level_agreement = get_service_level_agreement(entity_type="Customer Group", entity=customer_group)
self.assertEqual(create_customer_group_service_level_agreement.name, get_customer_group_service_level_agreement.name)
@@ -53,7 +54,7 @@ class TestServiceLevelAgreement(unittest.TestCase):
# Service Level Agreement for Territory
territory = create_territory()
create_territory_service_level_agreement = create_service_level_agreement(default_service_level_agreement=0,
- holiday_list="__Test Holiday List", employee_group="_Test Employee Group",
+ holiday_list="__Test Holiday List",
entity_type="Territory", entity=territory, response_time=7200, resolution_time=10800)
get_territory_service_level_agreement = get_service_level_agreement(entity_type="Territory", entity=territory)
@@ -62,64 +63,223 @@ class TestServiceLevelAgreement(unittest.TestCase):
self.assertEqual(create_territory_service_level_agreement.entity, get_territory_service_level_agreement.entity)
self.assertEqual(create_territory_service_level_agreement.default_service_level_agreement, get_territory_service_level_agreement.default_service_level_agreement)
+ def test_custom_field_creation_for_sla_on_standard_dt(self):
+ # Default Service Level Agreement
+ doctype = "Lead"
+ lead_sla = create_service_level_agreement(
+ default_service_level_agreement=1,
+ holiday_list="__Test Holiday List",
+ entity_type=None, entity=None,
+ response_time=14400, resolution_time=21600,
+ doctype=doctype,
+ sla_fulfilled_on=[{"status": "Converted"}]
+ )
-def get_service_level_agreement(default_service_level_agreement=None, entity_type=None, entity=None):
+ # check default SLA for lead
+ default_sla = get_service_level_agreement(default_service_level_agreement=1, doctype=doctype)
+ self.assertEqual(lead_sla.name, default_sla.name)
+
+ # check SLA custom fields created for leads
+ sla_fields = get_service_level_agreement_fields()
+ meta = frappe.get_meta(doctype, cached=False)
+
+ for field in sla_fields:
+ self.assertTrue(meta.has_field(field.get("fieldname")))
+
+ def test_docfield_creation_for_sla_on_custom_dt(self):
+ doctype = create_custom_doctype()
+ sla = create_service_level_agreement(
+ default_service_level_agreement=1,
+ holiday_list="__Test Holiday List",
+ entity_type=None, entity=None,
+ response_time=14400, resolution_time=21600,
+ doctype=doctype.name
+ )
+
+ # check default SLA for custom dt
+ default_sla = get_service_level_agreement(default_service_level_agreement=1, doctype=doctype.name)
+ self.assertEqual(sla.name, default_sla.name)
+
+ # check SLA docfields created
+ sla_fields = get_service_level_agreement_fields()
+ meta = frappe.get_meta(doctype.name, cached=False)
+
+ for field in sla_fields:
+ self.assertTrue(meta.has_field(field.get("fieldname")))
+
+ def test_sla_application(self):
+ # Default Service Level Agreement
+ doctype = "Lead"
+ lead_sla = create_service_level_agreement(
+ default_service_level_agreement=1,
+ holiday_list="__Test Holiday List",
+ entity_type=None, entity=None,
+ response_time=14400, resolution_time=21600,
+ doctype=doctype,
+ sla_fulfilled_on=[{"status": "Converted"}]
+ )
+
+ # make lead with default SLA
+ creation = datetime.datetime(2019, 3, 4, 12, 0)
+ lead = make_lead(creation=creation, index=1)
+
+ self.assertEqual(lead.service_level_agreement, lead_sla.name)
+ self.assertEqual(lead.response_by, datetime.datetime(2019, 3, 4, 16, 0))
+ self.assertEqual(lead.resolution_by, datetime.datetime(2019, 3, 4, 18, 0))
+
+ frappe.flags.current_time = datetime.datetime(2019, 3, 4, 15, 0)
+ lead.reload()
+ lead.status = 'Converted'
+ lead.save()
+
+ self.assertEqual(lead.agreement_status, 'Fulfilled')
+
+ def test_hold_time(self):
+ doctype = "Lead"
+ create_service_level_agreement(
+ default_service_level_agreement=1,
+ holiday_list="__Test Holiday List",
+ entity_type=None, entity=None,
+ response_time=14400, resolution_time=21600,
+ doctype=doctype,
+ sla_fulfilled_on=[{"status": "Converted"}],
+ pause_sla_on=[{"status": "Replied"}]
+ )
+
+ creation = datetime.datetime(2020, 3, 4, 4, 0)
+ lead = make_lead(creation, index=2)
+
+ frappe.flags.current_time = datetime.datetime(2020, 3, 4, 4, 15)
+ lead.reload()
+ lead.status = 'Replied'
+ lead.save()
+
+ lead.reload()
+ self.assertEqual(lead.on_hold_since, frappe.flags.current_time)
+
+ frappe.flags.current_time = datetime.datetime(2020, 3, 4, 5, 5)
+ lead.reload()
+ lead.status = 'Converted'
+ lead.save()
+
+ lead.reload()
+ self.assertEqual(flt(lead.total_hold_time, 2), 3000)
+ self.assertEqual(lead.resolution_by, datetime.datetime(2020, 3, 4, 16, 50))
+
+ def test_failed_sla_for_response_only(self):
+ doctype = "Lead"
+ create_service_level_agreement(
+ default_service_level_agreement=1,
+ holiday_list="__Test Holiday List",
+ entity_type=None, entity=None,
+ response_time=14400,
+ doctype=doctype,
+ sla_fulfilled_on=[{"status": "Replied"}],
+ pause_sla_on=[],
+ apply_sla_for_resolution=0
+ )
+
+ creation = datetime.datetime(2019, 3, 4, 12, 0)
+ lead = make_lead(creation=creation, index=1)
+ self.assertEqual(lead.response_by, datetime.datetime(2019, 3, 4, 16, 0))
+
+ # failed with response time only
+ frappe.flags.current_time = datetime.datetime(2019, 3, 4, 16, 5)
+ lead.reload()
+ lead.status = 'Replied'
+ lead.save()
+
+ lead.reload()
+ self.assertEqual(lead.agreement_status, 'Failed')
+
+ def test_fulfilled_sla_for_response_only(self):
+ doctype = "Lead"
+ lead_sla = create_service_level_agreement(
+ default_service_level_agreement=1,
+ holiday_list="__Test Holiday List",
+ entity_type=None, entity=None,
+ response_time=14400,
+ doctype=doctype,
+ sla_fulfilled_on=[{"status": "Replied"}],
+ apply_sla_for_resolution=0
+ )
+
+ # fulfilled with response time only
+ creation = datetime.datetime(2019, 3, 4, 12, 0)
+ lead = make_lead(creation=creation, index=2)
+
+ self.assertEqual(lead.service_level_agreement, lead_sla.name)
+ self.assertEqual(lead.response_by, datetime.datetime(2019, 3, 4, 16, 0))
+
+ frappe.flags.current_time = datetime.datetime(2019, 3, 4, 15, 30)
+ lead.reload()
+ lead.status = 'Replied'
+ lead.save()
+
+ lead.reload()
+ self.assertEqual(lead.agreement_status, 'Fulfilled')
+
+ def tearDown(self):
+ for d in frappe.get_all("Service Level Agreement"):
+ frappe.delete_doc("Service Level Agreement", d.name, force=1)
+
+
+def get_service_level_agreement(default_service_level_agreement=None, entity_type=None, entity=None, doctype="Issue"):
if default_service_level_agreement:
- filters = {"default_service_level_agreement": default_service_level_agreement}
+ filters = {"default_service_level_agreement": default_service_level_agreement, "document_type": doctype}
else:
filters = {"entity_type": entity_type, "entity": entity}
service_level_agreement = frappe.get_doc("Service Level Agreement", filters)
return service_level_agreement
-def create_service_level_agreement(default_service_level_agreement, holiday_list, employee_group,
- response_time, entity_type, entity, resolution_time):
+def create_service_level_agreement(default_service_level_agreement, holiday_list, response_time, entity_type,
+ entity, resolution_time=0, doctype="Issue", sla_fulfilled_on=[], pause_sla_on=[], apply_sla_for_resolution=1):
- employee_group = make_employee_group()
make_holiday_list()
make_priorities()
- service_level_agreement = frappe.get_doc({
+ if not sla_fulfilled_on:
+ sla_fulfilled_on = [
+ {"status": "Resolved"},
+ {"status": "Closed"}
+ ]
+
+ pause_sla_on = [{"status": "Replied"}] if doctype == "Issue" else pause_sla_on
+
+ service_level_agreement = frappe._dict({
"doctype": "Service Level Agreement",
- "enable": 1,
+ "enabled": 1,
+ "document_type": doctype,
"service_level": "__Test Service Level",
"default_service_level_agreement": default_service_level_agreement,
"default_priority": "Medium",
"holiday_list": holiday_list,
- "employee_group": employee_group,
"entity_type": entity_type,
"entity": entity,
"start_date": frappe.utils.getdate(),
"end_date": frappe.utils.add_to_date(frappe.utils.getdate(), days=100),
+ "apply_sla_for_resolution": apply_sla_for_resolution,
"priorities": [
{
"priority": "Low",
"response_time": response_time,
- "response_time_period": "Hour",
"resolution_time": resolution_time,
- "resolution_time_period": "Hour",
},
{
"priority": "Medium",
"response_time": response_time,
"default_priority": 1,
- "response_time_period": "Hour",
"resolution_time": resolution_time,
- "resolution_time_period": "Hour",
},
{
"priority": "High",
"response_time": response_time,
- "response_time_period": "Hour",
"resolution_time": resolution_time,
- "resolution_time_period": "Hour",
- }
- ],
- "pause_sla_on": [
- {
- "status": "Replied"
}
],
+ "sla_fulfilled_on": sla_fulfilled_on,
+ "pause_sla_on": pause_sla_on,
"support_and_resolution": [
{
"workday": "Monday",
@@ -173,10 +333,13 @@ def create_service_level_agreement(default_service_level_agreement, holiday_list
service_level_agreement_exists = frappe.db.exists("Service Level Agreement", filters)
if not service_level_agreement_exists:
- service_level_agreement.insert(ignore_permissions=True)
- return service_level_agreement
+ doc = frappe.get_doc(service_level_agreement).insert(ignore_permissions=True)
else:
- return frappe.get_doc("Service Level Agreement", service_level_agreement_exists)
+ doc = frappe.get_doc("Service Level Agreement", service_level_agreement_exists)
+ doc.update(service_level_agreement)
+ doc.save()
+
+ return doc
def create_customer():
@@ -219,19 +382,19 @@ def create_territory():
def create_service_level_agreements_for_issues():
create_service_level_agreement(default_service_level_agreement=1, holiday_list="__Test Holiday List",
- employee_group="_Test Employee Group", entity_type=None, entity=None, response_time=14400, resolution_time=21600)
+ entity_type=None, entity=None, response_time=14400, resolution_time=21600)
create_customer()
create_service_level_agreement(default_service_level_agreement=0, holiday_list="__Test Holiday List",
- employee_group="_Test Employee Group", entity_type="Customer", entity="_Test Customer", response_time=7200, resolution_time=10800)
+ entity_type="Customer", entity="_Test Customer", response_time=7200, resolution_time=10800)
create_customer_group()
create_service_level_agreement(default_service_level_agreement=0, holiday_list="__Test Holiday List",
- employee_group="_Test Employee Group", entity_type="Customer Group", entity="_Test SLA Customer Group", response_time=7200, resolution_time=10800)
+ entity_type="Customer Group", entity="_Test SLA Customer Group", response_time=7200, resolution_time=10800)
create_territory()
create_service_level_agreement(default_service_level_agreement=0, holiday_list="__Test Holiday List",
- employee_group="_Test Employee Group", entity_type="Territory", entity="_Test SLA Territory", response_time=7200, resolution_time=10800)
+ entity_type="Territory", entity="_Test SLA Territory", response_time=7200, resolution_time=10800)
def make_holiday_list():
holiday_list = frappe.db.exists("Holiday List", "__Test Holiday List")
@@ -256,3 +419,55 @@ def make_holiday_list():
},
]
}).insert()
+
+def create_custom_doctype():
+ if not frappe.db.exists("DocType", "Test SLA on Custom Dt"):
+ doc = frappe.get_doc({
+ "doctype": "DocType",
+ "module": "Support",
+ "custom": 1,
+ "fields": [
+ {
+ "label": "Date",
+ "fieldname": "date",
+ "fieldtype": "Date"
+ },
+ {
+ "label": "Description",
+ "fieldname": "desc",
+ "fieldtype": "Long Text"
+ },
+ {
+ "label": "Email ID",
+ "fieldname": "email_id",
+ "fieldtype": "Link",
+ "options": "Customer"
+ },
+ {
+ "label": "Status",
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "options": "Open\nReplied\nClosed"
+ }
+ ],
+ "permissions": [{
+ "role": "System Manager",
+ "read": 1,
+ "write": 1
+ }],
+ "name": "Test SLA on Custom Dt",
+ })
+ doc.insert()
+ return doc
+ else:
+ return frappe.get_doc("DocType", "Test SLA on Custom Dt")
+
+def make_lead(creation=None, index=0):
+ return frappe.get_doc({
+ "doctype": "Lead",
+ "email_id": "test_lead1@example{0}.com".format(index),
+ "lead_name": "_Test Lead {0}".format(index),
+ "status": "Open",
+ "creation": creation,
+ "service_level_agreement_creation": creation
+ }).insert(ignore_permissions=True)
\ No newline at end of file
diff --git a/erpnext/support/doctype/service_level_priority/service_level_priority.json b/erpnext/support/doctype/service_level_priority/service_level_priority.json
index 65d51694cc..0367fc6d88 100644
--- a/erpnext/support/doctype/service_level_priority/service_level_priority.json
+++ b/erpnext/support/doctype/service_level_priority/service_level_priority.json
@@ -15,12 +15,13 @@
],
"fields": [
{
- "columns": 2,
+ "columns": 1,
"fieldname": "priority",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Priority",
- "options": "Issue Priority"
+ "options": "Issue Priority",
+ "reqd": 1
},
{
"fieldname": "sb_00",
@@ -32,7 +33,6 @@
"fieldtype": "Duration",
"hide_days": 1,
"hide_seconds": 1,
- "in_list_view": 1,
"label": "Resolution Time"
},
{
@@ -58,12 +58,13 @@
"hide_days": 1,
"hide_seconds": 1,
"in_list_view": 1,
- "label": "First Response Time"
+ "label": "First Response Time",
+ "reqd": 1
}
],
"istable": 1,
"links": [],
- "modified": "2020-06-10 12:45:47.545915",
+ "modified": "2021-05-29 19:52:51.733248",
"modified_by": "Administrator",
"module": "Support",
"name": "Service Level Priority",
@@ -73,4 +74,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
-}
+}
\ No newline at end of file
diff --git a/erpnext/support/doctype/sla_fulfilled_on_status/__init__.py b/erpnext/support/doctype/sla_fulfilled_on_status/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.json b/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.json
new file mode 100644
index 0000000000..87124deaf8
--- /dev/null
+++ b/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.json
@@ -0,0 +1,31 @@
+{
+ "actions": [],
+ "creation": "2021-05-26 21:11:29.176369",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+ "status"
+ ],
+ "fields": [
+ {
+ "fieldname": "status",
+ "fieldtype": "Select",
+ "in_list_view": 1,
+ "label": "Status",
+ "reqd": 1
+ }
+ ],
+ "istable": 1,
+ "links": [],
+ "modified": "2021-05-26 21:11:29.176369",
+ "modified_by": "Administrator",
+ "module": "Support",
+ "name": "SLA Fulfilled On Status",
+ "owner": "Administrator",
+ "permissions": [],
+ "quick_entry": 1,
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py b/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py
new file mode 100644
index 0000000000..b0b5ffc816
--- /dev/null
+++ b/erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+# import frappe
+from frappe.model.document import Document
+
+class SLAFulfilledOnStatus(Document):
+ pass
From 80077d215fa9754e8401cf5ff3207a5da5c8424a Mon Sep 17 00:00:00 2001
From: Saqib
Date: Mon, 14 Jun 2021 19:34:25 +0530
Subject: [PATCH 228/262] fix: patch for adding doctype to sla (#26053)
---
erpnext/patches.txt | 2 +-
erpnext/patches/v13_0/add_doctype_to_sla.py | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 161241e9bb..c42fcf605e 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -285,5 +285,5 @@ erpnext.patches.v13_0.germany_make_custom_fields
erpnext.patches.v13_0.germany_fill_debtor_creditor_number
erpnext.patches.v13_0.set_pos_closing_as_failed
erpnext.patches.v13_0.update_timesheet_changes
-erpnext.patches.v13_0.add_doctype_to_sla
+erpnext.patches.v13_0.add_doctype_to_sla #14-06-2021
erpnext.patches.v13_0.set_training_event_attendance
diff --git a/erpnext/patches/v13_0/add_doctype_to_sla.py b/erpnext/patches/v13_0/add_doctype_to_sla.py
index 35407785ca..e2c7fd268a 100644
--- a/erpnext/patches/v13_0/add_doctype_to_sla.py
+++ b/erpnext/patches/v13_0/add_doctype_to_sla.py
@@ -7,6 +7,7 @@ import frappe
from frappe.model.utils.rename_field import rename_field
def execute():
+ frappe.reload_doc('support', 'doctype', 'sla_fulfilled_on_status')
frappe.reload_doc('support', 'doctype', 'service_level_agreement')
if frappe.db.has_column('Service Level Agreement', 'enable'):
rename_field('Service Level Agreement', 'enable', 'enabled')
From 302855e160e60dc7b6de7120380f5f7e4643efb5 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 14 Jun 2021 11:16:39 +0530
Subject: [PATCH 229/262] fix: Auto tax calculations in Payment Entry
---
.../doctype/payment_entry/payment_entry.js | 86 +++++++++++++++++--
.../doctype/payment_entry/payment_entry.py | 44 +++++-----
.../purchase_taxes_and_charges.json | 3 +-
.../sales_taxes_and_charges.json | 3 +-
erpnext/controllers/accounts_controller.py | 34 ++++----
5 files changed, 118 insertions(+), 52 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js
index 939f3546ff..d3ac3a6676 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.js
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js
@@ -1087,6 +1087,8 @@ frappe.ui.form.on('Payment Entry', {
initialize_taxes: function(frm) {
$.each(frm.doc["taxes"] || [], function(i, tax) {
+ frm.events.validate_taxes_and_charges(tax);
+ frm.events.validate_inclusive_tax(tax);
tax.item_wise_tax_detail = {};
let tax_fields = ["total", "tax_fraction_for_current_item",
"grand_total_fraction_for_current_item"];
@@ -1101,6 +1103,73 @@ frappe.ui.form.on('Payment Entry', {
});
},
+ validate_taxes_and_charges: function(d) {
+ let msg = "";
+
+ if (d.account_head && !d.description) {
+ // set description from account head
+ d.description = d.account_head.split(' - ').slice(0, -1).join(' - ');
+ }
+
+ if (!d.charge_type && (d.row_id || d.rate || d.tax_amount)) {
+ msg = __("Please select Charge Type first");
+ d.row_id = "";
+ d.rate = d.tax_amount = 0.0;
+ } else if ((d.charge_type == 'Actual' || d.charge_type == 'On Net Total' || d.charge_type == 'On Paid Amount') && d.row_id) {
+ msg = __("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'");
+ d.row_id = "";
+ } else if ((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) {
+ if (d.idx == 1) {
+ msg = __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row");
+ d.charge_type = '';
+ } else if (!d.row_id) {
+ msg = __("Please specify a valid Row ID for row {0} in table {1}", [d.idx, __(d.doctype)]);
+ d.row_id = "";
+ } else if (d.row_id && d.row_id >= d.idx) {
+ msg = __("Cannot refer row number greater than or equal to current row number for this Charge type");
+ d.row_id = "";
+ }
+ }
+ if (msg) {
+ frappe.validated = false;
+ refresh_field("taxes");
+ frappe.throw(msg);
+ }
+
+ },
+
+ validate_inclusive_tax: function(tax) {
+ let actual_type_error = function() {
+ let msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx])
+ frappe.throw(msg);
+ };
+
+ let on_previous_row_error = function(row_range) {
+ let msg = __("For row {0} in {1}. To include {2} in Item rate, rows {3} must also be included",
+ [tax.idx, __(tax.doctype), tax.charge_type, row_range])
+ frappe.throw(msg);
+ };
+
+ if(cint(tax.included_in_paid_amount)) {
+ if(tax.charge_type == "Actual") {
+ // inclusive tax cannot be of type Actual
+ actual_type_error();
+ } else if(tax.charge_type == "On Previous Row Amount" &&
+ !cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_paid_amount)
+ ) {
+ // referred row should also be an inclusive tax
+ on_previous_row_error(tax.row_id);
+ } else if(tax.charge_type == "On Previous Row Total") {
+ let taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id),
+ function(t) { return cint(t.included_in_paid_amount) ? null : t; });
+ if(taxes_not_included.length > 0) {
+ // all rows above this tax should be inclusive
+ on_previous_row_error(tax.row_id == 1 ? "1" : "1 - " + tax.row_id);
+ }
+ }
+ }
+ },
+
determine_exclusive_rate: function(frm) {
let has_inclusive_tax = false;
$.each(frm.doc["taxes"] || [], function(i, row) {
@@ -1110,8 +1179,7 @@ frappe.ui.form.on('Payment Entry', {
let cumulated_tax_fraction = 0.0;
$.each(frm.doc["taxes"] || [], function(i, tax) {
- let current_tax_fraction = frm.events.get_current_tax_fraction(frm, tax);
- tax.tax_fraction_for_current_item = current_tax_fraction[0];
+ tax.tax_fraction_for_current_item = frm.events.get_current_tax_fraction(frm, tax);
if(i==0) {
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item;
@@ -1132,9 +1200,7 @@ frappe.ui.form.on('Payment Entry', {
if(cint(tax.included_in_paid_amount)) {
let tax_rate = tax.rate;
- if (tax.charge_type == "Actual") {
- current_tax_fraction = tax.tax_amount/(frm.doc.paid_amount_after_tax + frm.doc.tax_amount);
- } else if(tax.charge_type == "On Paid Amount") {
+ if(tax.charge_type == "On Paid Amount") {
current_tax_fraction = (tax_rate / 100.0);
} else if(tax.charge_type == "On Previous Row Amount") {
current_tax_fraction = (tax_rate / 100.0) *
@@ -1147,7 +1213,6 @@ frappe.ui.form.on('Payment Entry', {
if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") {
current_tax_fraction *= -1;
- inclusive_tax_amount_per_qty *= -1;
}
return current_tax_fraction;
},
@@ -1207,10 +1272,8 @@ frappe.ui.form.on('Payment Entry', {
frappe.throw(
__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"));
}
- if (!tax.row_id) {
- tax.row_id = tax.idx - 1;
- }
}
+
if(tax.charge_type == "Actual") {
current_tax_amount = flt(tax.tax_amount, precision("tax_amount", tax))
} else if(tax.charge_type == "On Paid Amount") {
@@ -1296,6 +1359,11 @@ frappe.ui.form.on('Advance Taxes and Charges', {
included_in_paid_amount: function(frm) {
frm.events.apply_taxes(frm);
frm.events.set_unallocated_amount(frm);
+ },
+
+ charge_type: function(frm) {
+ frm.events.apply_taxes(frm);
+ frm.events.set_unallocated_amount(frm);
}
})
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index edca210142..bd6f84cd75 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -16,9 +16,11 @@ from erpnext.accounts.doctype.bank_account.bank_account import get_party_bank_ac
from erpnext.controllers.accounts_controller import AccountsController, get_supplier_block_status
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
-
from six import string_types, iteritems
+from erpnext.controllers.accounts_controller import validate_conversion_rate, \
+ validate_taxes_and_charges, validate_inclusive_tax
+
class InvalidPaymentEntry(ValidationError):
pass
@@ -407,20 +409,6 @@ class PaymentEntry(AccountsController):
net_total = self.paid_amount
included_in_paid_amount = 0
- if self.get('references'):
- for doc in self.get('references'):
- if doc.reference_doctype == 'Purchase Order':
- reference_doclist.append(doc.reference_name)
-
- if reference_doclist:
- order_amount = frappe.db.get_all('Purchase Order', fields=['sum(net_total)'],
- filters = {'name': ('in', reference_doclist), 'docstatus': 1,
- 'apply_tds': 1}, as_list=1)
-
- if order_amount:
- net_total = order_amount[0][0]
- included_in_paid_amount = 1
-
# Adding args as purchase invoice to get TDS amount
args = frappe._dict({
'company': self.company,
@@ -719,9 +707,9 @@ class PaymentEntry(AccountsController):
if account_currency != self.company_currency:
frappe.throw(_("Currency for {0} must be {1}").format(d.account_head, self.company_currency))
- if (self.payment_type == 'Pay' and self.advance_tax_account) or self.payment_type == 'Receive':
+ if self.payment_type == 'Pay':
dr_or_cr = "debit" if d.add_deduct_tax == "Add" else "credit"
- elif (self.payment_type == 'Receive' and self.advance_tax_account) or self.payment_type == 'Pay':
+ elif self.payment_type == 'Receive':
dr_or_cr = "credit" if d.add_deduct_tax == "Add" else "debit"
payment_or_advance_account = self.get_party_account_for_taxes()
@@ -747,6 +735,8 @@ class PaymentEntry(AccountsController):
if account_currency==self.company_currency
else d.tax_amount,
"cost_center": self.cost_center,
+ "party_type": self.party_type,
+ "party": self.party
}, account_currency, item=d))
def add_deductions_gl_entries(self, gl_entries):
@@ -770,9 +760,9 @@ class PaymentEntry(AccountsController):
def get_party_account_for_taxes(self):
if self.advance_tax_account:
return self.advance_tax_account
- elif self.payment_type == 'Pay':
- return self.paid_from
elif self.payment_type == 'Receive':
+ return self.paid_from
+ elif self.payment_type == 'Pay':
return self.paid_to
def update_advance_paid(self):
@@ -823,6 +813,9 @@ class PaymentEntry(AccountsController):
def initialize_taxes(self):
for tax in self.get("taxes"):
+ validate_taxes_and_charges(tax)
+ validate_inclusive_tax(tax, self)
+
tax_fields = ["total", "tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
if tax.charge_type != "Actual":
@@ -918,15 +911,11 @@ class PaymentEntry(AccountsController):
if cint(tax.included_in_paid_amount):
tax_rate = tax.rate
- if tax.charge_type == 'Actual':
- current_tax_fraction = tax.tax_amount/ (self.paid_amount_after_tax + tax.tax_amount)
- elif tax.charge_type == "On Paid Amount":
+ if tax.charge_type == "On Paid Amount":
current_tax_fraction = tax_rate / 100.0
-
elif tax.charge_type == "On Previous Row Amount":
current_tax_fraction = (tax_rate / 100.0) * \
self.get("taxes")[cint(tax.row_id) - 1].tax_fraction_for_current_item
-
elif tax.charge_type == "On Previous Row Total":
current_tax_fraction = (tax_rate / 100.0) * \
self.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
@@ -1626,6 +1615,13 @@ def set_paid_amount_and_received_amount(dt, party_account_currency, bank, outsta
paid_amount = received_amount * doc.get('conversion_rate', 1)
if dt == "Employee Advance":
paid_amount = received_amount * doc.get('exchange_rate', 1)
+
+ if dt == "Purchase Order" and doc.apply_tds:
+ if party_account_currency == bank.account_currency:
+ paid_amount = received_amount = doc.base_net_total
+ else:
+ paid_amount = received_amount = doc.base_net_total * doc.get('exchange_rate', 1)
+
return paid_amount, received_amount
def apply_early_payment_discount(paid_amount, received_amount, doc):
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
index 9b07645ccc..1fa68e0a8a 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
@@ -218,6 +218,7 @@
},
{
"default": "0",
+ "depends_on": "eval:['Purchase Taxes and Charges Template', 'Payment Entry'].includes(parent.doctype)",
"description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
"fieldname": "included_in_paid_amount",
"fieldtype": "Check",
@@ -227,7 +228,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2021-06-09 11:48:25.335733",
+ "modified": "2021-06-14 01:43:50.750455",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
index 170d34e651..1b7a0fe562 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
@@ -195,6 +195,7 @@
},
{
"default": "0",
+ "depends_on": "eval:['Sales Taxes and Charges Template', 'Payment Entry'].includes(parent.doctype)",
"description": "If checked, the tax amount will be considered as already included in the Paid Amount in Payment Entry",
"fieldname": "included_in_paid_amount",
"fieldtype": "Check",
@@ -205,7 +206,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2021-06-09 11:48:04.691596",
+ "modified": "2021-06-14 01:44:36.899147",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 53ded33b6f..a86c8e5909 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1192,7 +1192,7 @@ def validate_conversion_rate(currency, conversion_rate, conversion_rate_label, c
def validate_taxes_and_charges(tax):
- if tax.charge_type in ['Actual', 'On Net Total'] and tax.row_id:
+ if tax.charge_type in ['Actual', 'On Net Total', 'On Paid Amount'] and tax.row_id:
frappe.throw(_("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'"))
elif tax.charge_type in ['On Previous Row Amount', 'On Previous Row Total']:
if cint(tax.idx) == 1:
@@ -1209,23 +1209,23 @@ def validate_taxes_and_charges(tax):
def validate_inclusive_tax(tax, doc):
def _on_previous_row_error(row_range):
- throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx,
- row_range))
+ throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx, row_range))
- if cint(getattr(tax, "included_in_print_rate", None)):
- if tax.charge_type == "Actual":
- # inclusive tax cannot be of type Actual
- throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate").format(tax.idx))
- elif tax.charge_type == "On Previous Row Amount" and \
- not cint(doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate):
- # referred row should also be inclusive
- _on_previous_row_error(tax.row_id)
- elif tax.charge_type == "On Previous Row Total" and \
- not all([cint(t.included_in_print_rate) for t in doc.get("taxes")[:cint(tax.row_id) - 1]]):
- # all rows about the reffered tax should be inclusive
- _on_previous_row_error("1 - %d" % (tax.row_id,))
- elif tax.get("category") == "Valuation":
- frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
+ for fieldname in ['included_in_print_rate', 'included_in_paid_amount']:
+ if cint(getattr(tax, fieldname, None)):
+ if tax.charge_type == "Actual":
+ # inclusive tax cannot be of type Actual
+ throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate or Paid Amount").format(tax.idx))
+ elif tax.charge_type == "On Previous Row Amount" and \
+ not cint(doc.get("taxes")[cint(tax.row_id) - 1].get(fieldname)):
+ # referred row should also be inclusive
+ _on_previous_row_error(tax.row_id)
+ elif tax.charge_type == "On Previous Row Total" and \
+ not all([cint(t.get(fieldname) for t in doc.get("taxes")[:cint(tax.row_id) - 1])]):
+ # all rows about the referred tax should be inclusive
+ _on_previous_row_error("1 - %d" % (cint(tax.row_id),))
+ elif tax.get("category") == "Valuation":
+ frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
From 5ef9a629175f4a5743b210fa5d7deabf703ef6a6 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 14 Jun 2021 14:34:44 +0530
Subject: [PATCH 230/262] fix: Add separate function to validate payment entry
taxes
---
.../doctype/payment_entry/payment_entry.py | 22 ++++++++++++--
erpnext/controllers/accounts_controller.py | 29 +++++++++----------
2 files changed, 34 insertions(+), 17 deletions(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index bd6f84cd75..bd95726035 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -18,8 +18,7 @@ from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
from six import string_types, iteritems
-from erpnext.controllers.accounts_controller import validate_conversion_rate, \
- validate_taxes_and_charges, validate_inclusive_tax
+from erpnext.controllers.accounts_controller import validate_taxes_and_charges
class InvalidPaymentEntry(ValidationError):
pass
@@ -925,6 +924,25 @@ class PaymentEntry(AccountsController):
return current_tax_fraction
+def validate_inclusive_tax(tax, doc):
+ def _on_previous_row_error(row_range):
+ throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx, row_range))
+
+ if cint(getattr(tax, "included_in_paid_amount", None)):
+ if tax.charge_type == "Actual":
+ # inclusive tax cannot be of type Actual
+ throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate or Paid Amount").format(tax.idx))
+ elif tax.charge_type == "On Previous Row Amount" and \
+ not cint(doc.get("taxes")[cint(tax.row_id) - 1].included_in_paid_amount):
+ # referred row should also be inclusive
+ _on_previous_row_error(tax.row_id)
+ elif tax.charge_type == "On Previous Row Total" and \
+ not all([cint(t.included_in_paid_amount for t in doc.get("taxes")[:cint(tax.row_id) - 1])]):
+ # all rows about the referred tax should be inclusive
+ _on_previous_row_error("1 - %d" % (cint(tax.row_id),))
+ elif tax.get("category") == "Valuation":
+ frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
+
@frappe.whitelist()
def get_outstanding_reference_documents(args):
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index a86c8e5909..02d1c7680b 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1211,21 +1211,20 @@ def validate_inclusive_tax(tax, doc):
def _on_previous_row_error(row_range):
throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx, row_range))
- for fieldname in ['included_in_print_rate', 'included_in_paid_amount']:
- if cint(getattr(tax, fieldname, None)):
- if tax.charge_type == "Actual":
- # inclusive tax cannot be of type Actual
- throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate or Paid Amount").format(tax.idx))
- elif tax.charge_type == "On Previous Row Amount" and \
- not cint(doc.get("taxes")[cint(tax.row_id) - 1].get(fieldname)):
- # referred row should also be inclusive
- _on_previous_row_error(tax.row_id)
- elif tax.charge_type == "On Previous Row Total" and \
- not all([cint(t.get(fieldname) for t in doc.get("taxes")[:cint(tax.row_id) - 1])]):
- # all rows about the referred tax should be inclusive
- _on_previous_row_error("1 - %d" % (cint(tax.row_id),))
- elif tax.get("category") == "Valuation":
- frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
+ if cint(getattr(tax, "included_in_print_rate", None)):
+ if tax.charge_type == "Actual":
+ # inclusive tax cannot be of type Actual
+ throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate or Paid Amount").format(tax.idx))
+ elif tax.charge_type == "On Previous Row Amount" and \
+ not cint(doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate):
+ # referred row should also be inclusive
+ _on_previous_row_error(tax.row_id)
+ elif tax.charge_type == "On Previous Row Total" and \
+ not all([cint(t.included_in_print_rate for t in doc.get("taxes")[:cint(tax.row_id) - 1])]):
+ # all rows about the referred tax should be inclusive
+ _on_previous_row_error("1 - %d" % (cint(tax.row_id),))
+ elif tax.get("category") == "Valuation":
+ frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
From ac52daa14f97d98670ece65444977b239686fe8c Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 14 Jun 2021 14:44:19 +0530
Subject: [PATCH 231/262] fix: Import throw
---
erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py
index bd95726035..b195332980 100644
--- a/erpnext/accounts/doctype/payment_entry/payment_entry.py
+++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext, json
-from frappe import _, scrub, ValidationError
+from frappe import _, scrub, ValidationError, throw
from frappe.utils import flt, comma_or, nowdate, getdate, cint
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
from erpnext.accounts.party import get_party_account
From bbf6121bb5f251917e1052e60f74ce170f591614 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Mon, 14 Jun 2021 20:01:04 +0530
Subject: [PATCH 232/262] fix: Revert unintended changes
---
erpnext/controllers/accounts_controller.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 02d1c7680b..e455982517 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -1220,9 +1220,9 @@ def validate_inclusive_tax(tax, doc):
# referred row should also be inclusive
_on_previous_row_error(tax.row_id)
elif tax.charge_type == "On Previous Row Total" and \
- not all([cint(t.included_in_print_rate for t in doc.get("taxes")[:cint(tax.row_id) - 1])]):
+ not all([cint(t.included_in_print_rate) for t in doc.get("taxes")[:cint(tax.row_id) - 1]]):
# all rows about the referred tax should be inclusive
- _on_previous_row_error("1 - %d" % (cint(tax.row_id),))
+ _on_previous_row_error("1 - %d" % (tax.row_id,))
elif tax.get("category") == "Valuation":
frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
From 4afda3c89c2fe06f0ab91604fd8e00c39f88101f Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Tue, 1 Jun 2021 13:13:04 +0530
Subject: [PATCH 233/262] fix(India): Taxable value for invoices with
additional discount
---
erpnext/regional/india/e_invoice/utils.py | 30 ++++++-----------------
erpnext/regional/india/utils.py | 8 ++----
2 files changed, 9 insertions(+), 29 deletions(-)
diff --git a/erpnext/regional/india/e_invoice/utils.py b/erpnext/regional/india/e_invoice/utils.py
index 0eaf790538..11ebef724c 100644
--- a/erpnext/regional/india/e_invoice/utils.py
+++ b/erpnext/regional/india/e_invoice/utils.py
@@ -38,7 +38,7 @@ def validate_eligibility(doc):
einvoicing_eligible_from = frappe.db.get_single_value('E Invoice Settings', 'applicable_from') or '2021-04-01'
if getdate(doc.get('posting_date')) < getdate(einvoicing_eligible_from):
return False
-
+
invalid_company = not frappe.db.get_value('E Invoice User', { 'company': doc.get('company') })
invalid_supply_type = doc.get('gst_category') not in ['Registered Regular', 'SEZ', 'Overseas', 'Deemed Export']
company_transaction = doc.get('billing_address_gstin') == doc.get('company_gstin')
@@ -135,7 +135,7 @@ def validate_address_fields(address, is_shipping_address):
def get_party_details(address_name, is_shipping_address=False):
addr = frappe.get_doc('Address', address_name)
-
+
validate_address_fields(addr, is_shipping_address)
if addr.gst_state_number == 97:
@@ -188,11 +188,6 @@ def get_item_list(invoice):
item.qty = abs(item.qty)
- if invoice.apply_discount_on == 'Net Total' and invoice.discount_amount:
- item.discount_amount = abs(item.base_amount - item.base_net_amount)
- else:
- item.discount_amount = 0
-
item.unit_rate = abs((abs(item.taxable_value) - item.discount_amount)/ item.qty)
item.gross_amount = abs(item.taxable_value) + item.discount_amount
item.taxable_value = abs(item.taxable_value)
@@ -254,18 +249,8 @@ def update_item_taxes(invoice, item):
def get_invoice_value_details(invoice):
invoice_value_details = frappe._dict(dict())
-
- if invoice.apply_discount_on == 'Net Total' and invoice.discount_amount:
- # Discount already applied on net total which means on items
- invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')]))
- invoice_value_details.invoice_discount_amt = 0
- elif invoice.apply_discount_on == 'Grand Total' and invoice.discount_amount:
- invoice_value_details.invoice_discount_amt = invoice.base_discount_amount
- invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')]))
- else:
- invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')]))
- # since tax already considers discount amount
- invoice_value_details.invoice_discount_amt = 0
+ invoice_value_details.base_total = abs(sum([i.taxable_value for i in invoice.get('items')]))
+ invoice_value_details.invoice_discount_amt = 0
invoice_value_details.round_off = invoice.base_rounding_adjustment
invoice_value_details.base_grand_total = abs(invoice.base_rounded_total) or abs(invoice.base_grand_total)
@@ -287,8 +272,7 @@ def update_invoice_taxes(invoice, invoice_value_details):
considered_rows = []
for t in invoice.taxes:
- tax_amount = t.base_tax_amount if (invoice.apply_discount_on == 'Grand Total' and invoice.discount_amount) \
- else t.base_tax_amount_after_discount_amount
+ tax_amount = t.base_tax_amount_after_discount_amount
if t.account_head in gst_accounts_list:
if t.account_head in gst_accounts.cess_account:
# using after discount amt since item also uses after discount amt for cess calc
@@ -995,7 +979,7 @@ class GSPConnector():
self.invoice.failure_description = self.get_failure_message(errors) if errors else ""
self.update_invoice()
frappe.db.commit()
-
+
def get_failure_message(self, errors):
if isinstance(errors, list):
errors = ', '.join(errors)
@@ -1052,7 +1036,7 @@ def generate_einvoices(docnames):
_('{} e-invoices generated successfully').format(success),
title=_('Bulk E-Invoice Generation Complete')
)
-
+
else:
enqueue_bulk_action(schedule_bulk_generate_irn, docnames=docnames)
diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py
index 075c698fea..a4466e78f2 100644
--- a/erpnext/regional/india/utils.py
+++ b/erpnext/regional/india/utils.py
@@ -817,12 +817,8 @@ def update_taxable_values(doc, method):
considered_rows.append(prev_row_id)
for item in doc.get('items'):
- if doc.apply_discount_on == 'Grand Total' and doc.discount_amount:
- proportionate_value = item.base_amount if doc.base_total else item.qty
- total_value = doc.base_total if doc.base_total else doc.total_qty
- else:
- proportionate_value = item.base_net_amount if doc.base_net_total else item.qty
- total_value = doc.base_net_total if doc.base_net_total else doc.total_qty
+ proportionate_value = item.base_net_amount if doc.base_net_total else item.qty
+ total_value = doc.base_net_total if doc.base_net_total else doc.total_qty
applicable_charges = flt(flt(proportionate_value * (flt(additional_taxes) / flt(total_value)),
item.precision('taxable_value')))
From 433815dabaf7b1c7219de663c180c1fa7bd384d8 Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Thu, 10 Jun 2021 12:04:30 +0530
Subject: [PATCH 234/262] fix: Update einvoice json test
---
.../sales_invoice/test_sales_invoice.py | 98 ++++++++-----------
1 file changed, 41 insertions(+), 57 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 5010fdc247..114b7d2d35 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -1937,69 +1937,53 @@ class TestSalesInvoice(unittest.TestCase):
frappe.flags.country = country
def test_einvoice_json(self):
- from erpnext.regional.india.e_invoice.utils import make_einvoice
+ from erpnext.regional.india.e_invoice.utils import make_einvoice, validate_totals
- si = make_sales_invoice_for_ewaybill()
- si.naming_series = 'INV-2020-.#####'
- si.items = []
- si.append("items", {
- "item_code": "_Test Item",
- "uom": "Nos",
- "warehouse": "_Test Warehouse - _TC",
- "qty": 2000,
- "rate": 12,
- "income_account": "Sales - _TC",
- "expense_account": "Cost of Goods Sold - _TC",
- "cost_center": "_Test Cost Center - _TC",
- })
- si.append("items", {
- "item_code": "_Test Item 2",
- "uom": "Nos",
- "warehouse": "_Test Warehouse - _TC",
- "qty": 420,
- "rate": 15,
- "income_account": "Sales - _TC",
- "expense_account": "Cost of Goods Sold - _TC",
- "cost_center": "_Test Cost Center - _TC",
- })
+ si = get_sales_invoice_for_e_invoice()
si.discount_amount = 100
si.save()
einvoice = make_einvoice(si)
-
- total_item_ass_value = 0
- total_item_cgst_value = 0
- total_item_sgst_value = 0
- total_item_igst_value = 0
- total_item_value = 0
-
- for item in einvoice['ItemList']:
- total_item_ass_value += item['AssAmt']
- total_item_cgst_value += item['CgstAmt']
- total_item_sgst_value += item['SgstAmt']
- total_item_igst_value += item['IgstAmt']
- total_item_value += item['TotItemVal']
-
- self.assertTrue(item['AssAmt'], item['TotAmt'] - item['Discount'])
- self.assertTrue(item['TotItemVal'], item['AssAmt'] + item['CgstAmt'] + item['SgstAmt'] + item['IgstAmt'])
-
- value_details = einvoice['ValDtls']
-
- self.assertEqual(einvoice['Version'], '1.1')
- self.assertEqual(value_details['AssVal'], total_item_ass_value)
- self.assertEqual(value_details['CgstVal'], total_item_cgst_value)
- self.assertEqual(value_details['SgstVal'], total_item_sgst_value)
- self.assertEqual(value_details['IgstVal'], total_item_igst_value)
-
- calculated_invoice_value = \
- value_details['AssVal'] + value_details['CgstVal'] \
- + value_details['SgstVal'] + value_details['IgstVal'] \
- + value_details['OthChrg'] - value_details['Discount']
-
- self.assertTrue(value_details['TotInvVal'] - calculated_invoice_value < 0.1)
-
- self.assertEqual(value_details['TotInvVal'], si.base_grand_total)
self.assertTrue(einvoice['EwbDtls'])
+ validate_totals(einvoice)
+
+ si.apply_discount_on = 'Net Total'
+ si.save()
+ einvoice = make_einvoice(si)
+ validate_totals(einvoice)
+
+ [d.set('included_in_print_rate', 1) for d in si.taxes]
+ si.save()
+ einvoice = make_einvoice(si)
+ validate_totals(einvoice)
+
+def get_sales_invoice_for_e_invoice():
+ si = make_sales_invoice_for_ewaybill()
+ si.naming_series = 'INV-2020-.#####'
+ si.items = []
+ si.append("items", {
+ "item_code": "_Test Item",
+ "uom": "Nos",
+ "warehouse": "_Test Warehouse - _TC",
+ "qty": 2000,
+ "rate": 12,
+ "income_account": "Sales - _TC",
+ "expense_account": "Cost of Goods Sold - _TC",
+ "cost_center": "_Test Cost Center - _TC",
+ })
+
+ si.append("items", {
+ "item_code": "_Test Item 2",
+ "uom": "Nos",
+ "warehouse": "_Test Warehouse - _TC",
+ "qty": 420,
+ "rate": 15,
+ "income_account": "Sales - _TC",
+ "expense_account": "Cost of Goods Sold - _TC",
+ "cost_center": "_Test Cost Center - _TC",
+ })
+
+ return si
def test_item_tax_net_range(self):
item = create_item("T Shirt")
From b2f2d0e749dfd5ba95f8e4119ef89e1b203f6dba Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Tue, 15 Jun 2021 19:43:54 +0530
Subject: [PATCH 235/262] chore: Added change log for v13.5.0
---
erpnext/change_log/v13/v13_5_0.md | 54 +++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 erpnext/change_log/v13/v13_5_0.md
diff --git a/erpnext/change_log/v13/v13_5_0.md b/erpnext/change_log/v13/v13_5_0.md
new file mode 100644
index 0000000000..64c323a23e
--- /dev/null
+++ b/erpnext/change_log/v13/v13_5_0.md
@@ -0,0 +1,54 @@
+# Version 13.5.0 Release Notes
+
+### Features & Enhancements
+
+- Tax deduction against advance payments ([#25831](https://github.com/frappe/erpnext/pull/25831))
+- Cost-center wise period closing entry ([#25766](https://github.com/frappe/erpnext/pull/25766))
+- Create Quality Inspections from account and stock documents ([#25221](https://github.com/frappe/erpnext/pull/25221))
+- Item Taxes based on net rate ([#25961](https://github.com/frappe/erpnext/pull/25961))
+- Enable/disable gl entry posting for change given in pos ([#25822](https://github.com/frappe/erpnext/pull/25822))
+- Add Inactive status to Employee ([#26029](https://github.com/frappe/erpnext/pull/26029))
+- Added check box to combine items with same BOM ([#25478](https://github.com/frappe/erpnext/pull/25478))
+- Item Tax Templates for Germany ([#25858](https://github.com/frappe/erpnext/pull/25858))
+- Refactored leave balance report ([#25771](https://github.com/frappe/erpnext/pull/25771))
+- Refactored Vehicle Expenses Report ([#25727](https://github.com/frappe/erpnext/pull/25727))
+- Refactored maintenance schedule and visit document ([#25358](https://github.com/frappe/erpnext/pull/25358))
+
+### Fixes
+
+- Cannot add same item with different rates ([#25849](https://github.com/frappe/erpnext/pull/25849))
+- Show only company addresses for ITC reversal entry ([#25866](https://github.com/frappe/erpnext/pull/25866))
+- Hiding Rounding Adjustment field ([#25380](https://github.com/frappe/erpnext/pull/25380))
+- Auto tax calculations in Payment Entry ([#26055](https://github.com/frappe/erpnext/pull/26055))
+- Not able to select the item code in work order ([#25915](https://github.com/frappe/erpnext/pull/25915))
+- Cannot reset plaid link for a bank account ([#25869](https://github.com/frappe/erpnext/pull/25869))
+- Student invalid password reset link ([#25826](https://github.com/frappe/erpnext/pull/25826))
+- Multiple pos issues ([#25928](https://github.com/frappe/erpnext/pull/25928))
+- Add Product Bundles to POS ([#25860](https://github.com/frappe/erpnext/pull/25860))
+- Enable Parallel tests ([#25862](https://github.com/frappe/erpnext/pull/25862))
+- Service item check on e-Invoicing ([#25986](https://github.com/frappe/erpnext/pull/25986))
+- Choose correct Salary Structure Assignment when getting data for formula eval ([#25981](https://github.com/frappe/erpnext/pull/25981))
+- Ignore internal transfer invoices from GST Reports ([#25969](https://github.com/frappe/erpnext/pull/25969))
+- Taxable value for invoices with additional discount ([#26056](https://github.com/frappe/erpnext/pull/26056))
+- Validate negative allocated amount in Payment Entry ([#25799](https://github.com/frappe/erpnext/pull/25799))
+- Allow all System Managers to delete company transactions ([#25834](https://github.com/frappe/erpnext/pull/25834))
+- Wrong round off gl entry posted in case of purchase invoice ([#25775](https://github.com/frappe/erpnext/pull/25775))
+- Use dictionary filter instead of list ([#25874](https://github.com/frappe/erpnext/pull/25874))
+- Ageing error in PSOA ([#25855](https://github.com/frappe/erpnext/pull/25855))
+- On click of duplicate button system has not copied the difference account ([#25988](https://github.com/frappe/erpnext/pull/25988))
+- Assign Product Bundle's conversion_factor to Pack… ([#25840](https://github.com/frappe/erpnext/pull/25840))
+- Rename Loan Management workspace to Loans ([#25856](https://github.com/frappe/erpnext/pull/25856))
+- Fix stock quantity calculation when negative_stock_allowe… ([#25859](https://github.com/frappe/erpnext/pull/25859))
+- Update cost center from pos profile ([#25971](https://github.com/frappe/erpnext/pull/25971))
+- Ensure website theme is applied correctly ([#25863](https://github.com/frappe/erpnext/pull/25863))
+- Only display GST card in Accounting Workspace if it's in India ([#26000](https://github.com/frappe/erpnext/pull/26000))
+- Incorrect gstin fetched incase of branch company address ([#25841](https://github.com/frappe/erpnext/pull/25841))
+- Sort account balances by account name ([#26009](https://github.com/frappe/erpnext/pull/26009))
+- Custom conversion factor field not mapped from job card to stock entry ([#25956](https://github.com/frappe/erpnext/pull/25956))
+- Chart of accounts importer always error ([#25882](https://github.com/frappe/erpnext/pull/25882))
+- Create POS Invoice for Product Bundles ([#25847](https://github.com/frappe/erpnext/pull/25847))
+- Wrap dates in getdate for leave application ([#25899](https://github.com/frappe/erpnext/pull/25899))
+- Closing entry shows incorrect expected amount ([#25868](https://github.com/frappe/erpnext/pull/25868))
+- Add Hold status column in the Issue Summary Report ([#25828](https://github.com/frappe/erpnext/pull/25828))
+- Rendering of broken image on pos ([#25872](https://github.com/frappe/erpnext/pull/25872))
+- Timeout error in the repost item valuation ([#25854](https://github.com/frappe/erpnext/pull/25854))
\ No newline at end of file
From 1e2df2c1093e5fa418933e6425cf97c23372ca6f Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Tue, 15 Jun 2021 19:53:57 +0530
Subject: [PATCH 236/262] fix(pos): 'NoneType' object is not iterable
---
erpnext/selling/page/point_of_sale/point_of_sale.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py
index 7742f24385..8d1f112dc2 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.py
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.py
@@ -9,7 +9,7 @@ from erpnext.accounts.doctype.pos_profile.pos_profile import get_item_groups
from erpnext.accounts.doctype.pos_invoice.pos_invoice import get_stock_availability
def search_by_term(search_term, warehouse, price_list):
- result = search_for_serial_or_batch_or_barcode_number(search_term)
+ result = search_for_serial_or_batch_or_barcode_number(search_term) or {}
item_code = result.get("item_code") or search_term
serial_no = result.get("serial_no") or ""
@@ -25,7 +25,7 @@ def search_by_term(search_term, warehouse, price_list):
price_list_rate, currency = frappe.db.get_value('Item Price', {
'price_list': price_list,
'item_code': item_code
- }, ["price_list_rate", "currency"])
+ }, ["price_list_rate", "currency"]) or [None, None]
item_info.update({
'serial_no': serial_no,
@@ -46,7 +46,7 @@ def get_items(start, page_length, price_list, item_group, pos_profile, search_te
result = []
if search_term:
- result = search_by_term(search_term, warehouse, price_list)
+ result = search_by_term(search_term, warehouse, price_list) or []
if result:
return result
From 24a88f6cf642603e2d5ee17e68853de4676979ed Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Tue, 15 Jun 2021 20:18:40 +0550
Subject: [PATCH 237/262] bumped to version 13.5.0
---
erpnext/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 5808090db3..76e8a514d5 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '13.4.1'
+__version__ = '13.5.0'
def get_default_company(user=None):
'''Get default company for user'''
From fd84847f2b263d0611a80387e90329e29c93c6d8 Mon Sep 17 00:00:00 2001
From: Ankush
Date: Wed, 16 Jun 2021 11:14:40 +0530
Subject: [PATCH 238/262] fix: syntax fixes for native class (#26064)
---
erpnext/public/js/controllers/taxes_and_totals.js | 8 ++++----
erpnext/public/js/controllers/transaction.js | 6 +++---
erpnext/public/js/payment/payments.js | 12 ++++++------
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 3f2436ddcb..cc33b8bc35 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -268,7 +268,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
frappe.model.round_floats_in(this.frm.doc, ["total", "base_total", "net_total", "base_net_total"]);
}
- update_item_tax_map: function() {
+ update_item_tax_map() {
let me = this;
let item_codes = [];
let item_rates = {};
@@ -305,9 +305,9 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
}
});
}
- },
+ }
- add_taxes_from_item_tax_template: function(item_tax_map) {
+ add_taxes_from_item_tax_template(item_tax_map) {
let me = this;
if (item_tax_map && cint(frappe.defaults.get_default("add_taxes_from_item_tax_template"))) {
@@ -325,7 +325,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
}
});
}
- },
+ }
calculate_taxes() {
var me = this;
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 40f9ae12b8..7e1ffa96a2 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -1918,7 +1918,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
});
}
- make_quality_inspection: function () {
+ make_quality_inspection() {
let data = [];
const fields = [
{
@@ -2040,9 +2040,9 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
} else {
dialog.show();
}
- },
+ }
- get_method_for_payment: function(){
+ 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)){
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index 0466cd62cd..4c23669dbb 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -22,7 +22,7 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
});
}
- set_payment_primary_action: function() {
+ set_payment_primary_action() {
var me = this;
this.dialog.set_primary_action(__("Submit"), function() {
@@ -107,7 +107,7 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
this.bind_numeric_keys_event();
}
- bind_form_control_event(){
+ bind_form_control_event() {
var me = this;
$(this.$body).find('.pos-payment-row').click(function() {
me.idx = $(this).attr("idx");
@@ -127,7 +127,7 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
$(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}));
@@ -135,9 +135,9 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
selected_row.addClass('selected-payment-mode');
$(this.$body).find('.amount').attr('disabled', true);
this.selected_mode.attr('disabled', false);
- },
+ }
- bind_numeric_keys_event: function() {
+ bind_numeric_keys_event() {
var me = this;
$(this.$body).find('.pos-keyboard-key').click(function(){
me.payment_val += $(this).text();
@@ -192,7 +192,7 @@ erpnext.payments = class payments extends erpnext.stock.StockController {
this.frm.doc.change_amount = flt(change_amount, precision("change_amount"));
this.calculate_write_off_amount();
this.show_amounts();
- },
+ }
update_paid_amount(update_write_off) {
var me = this;
From d5c172590ff3bc390acf34056396196de5b5c25d Mon Sep 17 00:00:00 2001
From: Afshan <33727827+AfshanKhan@users.noreply.github.com>
Date: Wed, 16 Jun 2021 14:28:03 +0530
Subject: [PATCH 239/262] fix(pos): pos loyalty card alignment (#26050)
---
erpnext/public/scss/point-of-sale.scss | 10 +++++++++-
erpnext/selling/page/point_of_sale/pos_payment.js | 4 ++--
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/erpnext/public/scss/point-of-sale.scss b/erpnext/public/scss/point-of-sale.scss
index 9bdaa8d1ee..c77b2ce3df 100644
--- a/erpnext/public/scss/point-of-sale.scss
+++ b/erpnext/public/scss/point-of-sale.scss
@@ -806,6 +806,9 @@
display: none;
float: right;
font-weight: 700;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
> .cash-shortcuts {
@@ -829,6 +832,11 @@
}
}
}
+
+ > .loyalty-card {
+ display: flex;
+ flex-direction: column;
+ }
}
}
@@ -1134,4 +1142,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js
index 156fb777fe..c484873d3e 100644
--- a/erpnext/selling/page/point_of_sale/pos_payment.js
+++ b/erpnext/selling/page/point_of_sale/pos_payment.js
@@ -481,7 +481,7 @@ erpnext.PointOfSale.Payment = class {
const amount = doc.loyalty_amount > 0 ? format_currency(doc.loyalty_amount, doc.currency) : '';
this.$payment_modes.append(
`
-
+
Redeem Loyalty Points
${amount}
${loyalty_program}
@@ -563,4 +563,4 @@ erpnext.PointOfSale.Payment = class {
toggle_component(show) {
show ? this.$component.css('display', 'flex') : this.$component.css('display', 'none');
}
-};
\ No newline at end of file
+};
From c03a947e986644db19c5dabfe3d2f23c9fc2ac30 Mon Sep 17 00:00:00 2001
From: Subin Tom
Date: Wed, 16 Jun 2021 19:47:55 +0530
Subject: [PATCH 240/262] fix: removed extra space from label rate
---
.../doctype/purchase_invoice_item/purchase_invoice_item.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
index 10e1c73ea9..29f72470b3 100644
--- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
+++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
@@ -272,7 +272,7 @@
"fieldname": "rate",
"fieldtype": "Currency",
"in_list_view": 1,
- "label": "Rate ",
+ "label": "Rate",
"oldfieldname": "import_rate",
"oldfieldtype": "Currency",
"options": "currency",
@@ -854,7 +854,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2021-03-30 09:02:39.256602",
+ "modified": "2021-06-16 19:33:51.099386",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
From e8e4841e5e778ebf35fd5548a530837d9d746a3d Mon Sep 17 00:00:00 2001
From: Suraj Shetty
Date: Thu, 17 Jun 2021 20:23:18 +0530
Subject: [PATCH 241/262] ci: Build frappe assets
- Build frappe assets since it is used for print views
---
.github/helper/install.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/helper/install.sh b/.github/helper/install.sh
index 7b0f944c66..f7a7122343 100644
--- a/.github/helper/install.sh
+++ b/.github/helper/install.sh
@@ -44,3 +44,4 @@ sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile
bench get-app erpnext "${GITHUB_WORKSPACE}"
bench start &
bench --site test_site reinstall --yes
+bench build --app frappe
From 7fc50ba46009beba91ad56064f0d487b6d7bc9e5 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Fri, 18 Jun 2021 10:11:53 +0530
Subject: [PATCH 242/262] fix: timeout while cancelling stock reconciliation
---
.../doctype/stock_reconciliation/stock_reconciliation.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index bcb40d850b..93ab40adba 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -473,6 +473,13 @@ class StockReconciliation(StockController):
else:
self._submit()
+ def cancel(self):
+ if len(self.items) > 100:
+ msgprint(_("The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Reconciliation and revert to the Submitted stage"))
+ self.queue_action('cancel', timeout=2000)
+ else:
+ self._cancel()
+
@frappe.whitelist()
def get_items(warehouse, posting_date, posting_time, company):
lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
From 584fe329000c56ee29e5a40c5d42980967c9c6c6 Mon Sep 17 00:00:00 2001
From: Ankush
Date: Fri, 18 Jun 2021 14:47:30 +0530
Subject: [PATCH 243/262] fix: escaped warehouse value for sql query (bp
#26049)
Co-authored-by: Noah Jacob
---
erpnext/controllers/stock_controller.py | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 9c29b0076b..6a7c9e3d0e 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -558,11 +558,8 @@ def future_sle_exists(args):
or_conditions = []
for warehouse, items in warehouse_items_map.items():
or_conditions.append(
- "warehouse = '{}' and item_code in ({})".format(
- warehouse,
- ", ".join(frappe.db.escape(item) for item in items)
- )
- )
+ f"""warehouse = {frappe.db.escape(warehouse)}
+ and item_code in ({', '.join(frappe.db.escape(item) for item in items)})""")
return frappe.db.sql("""
select name
From 4e88dcf956916e2f1a6f5223ad78a8b7afa0bc4c Mon Sep 17 00:00:00 2001
From: Ankush
Date: Fri, 18 Jun 2021 14:48:30 +0530
Subject: [PATCH 244/262] fix: auto unlink warehouse from item on delete
(#26073) (#26101)
* fix: auto unlink warehouse from item on delete
* fix: sider
* refactor: use delete_doc
* test: add test for unlinking warehouse from item
* refactor: add msgprint to inform user of unlink
* refactor: cleanup and reuse extant functions
* fix: don't delete row, update table
Co-authored-by: Alan <2.alan.tom@gmail.com>
---
.../stock/doctype/warehouse/test_warehouse.py | 34 +++++++++++++++++++
erpnext/stock/doctype/warehouse/warehouse.py | 7 ++++
2 files changed, 41 insertions(+)
diff --git a/erpnext/stock/doctype/warehouse/test_warehouse.py b/erpnext/stock/doctype/warehouse/test_warehouse.py
index 95478f61f0..e3981c913e 100644
--- a/erpnext/stock/doctype/warehouse/test_warehouse.py
+++ b/erpnext/stock/doctype/warehouse/test_warehouse.py
@@ -11,6 +11,7 @@ from frappe.test_runner import make_test_records
import erpnext
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
+from erpnext.stock.doctype.item.test_item import create_item
test_records = frappe.get_test_records('Warehouse')
@@ -92,6 +93,39 @@ class TestWarehouse(unittest.TestCase):
self.assertTrue(frappe.db.get_value("Warehouse",
filters={"account": "Test Warehouse for Merging 2 - TCP1"}))
+ def test_unlinking_warehouse_from_item_defaults(self):
+ company = "_Test Company"
+
+ warehouse_names = [f'_Test Warehouse {i} for Unlinking' for i in range(2)]
+ warehouse_ids = []
+ for warehouse in warehouse_names:
+ warehouse_id = create_warehouse(warehouse, company=company)
+ warehouse_ids.append(warehouse_id)
+
+ item_names = [f'_Test Item {i} for Unlinking' for i in range(2)]
+ for item, warehouse in zip(item_names, warehouse_ids):
+ create_item(item, warehouse=warehouse, company=company)
+
+ # Delete warehouses
+ for warehouse in warehouse_ids:
+ frappe.delete_doc("Warehouse", warehouse)
+
+ # Check Item existance
+ for item in item_names:
+ self.assertTrue(
+ bool(frappe.db.exists("Item", item)),
+ f"{item} doesn't exist"
+ )
+
+ item_doc = frappe.get_doc("Item", item)
+ for item_default in item_doc.item_defaults:
+ self.assertNotIn(
+ item_default.default_warehouse,
+ warehouse_ids,
+ f"{item} linked to {item_default.default_warehouse} in {warehouse_ids}."
+ )
+
+
def create_warehouse(warehouse_name, properties=None, company=None):
if not company:
company = "_Test Company"
diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py
index 2062bddc7c..3abc13907c 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.py
+++ b/erpnext/stock/doctype/warehouse/warehouse.py
@@ -54,6 +54,7 @@ class Warehouse(NestedSet):
throw(_("Child warehouse exists for this warehouse. You can not delete this warehouse."))
self.update_nsm_model()
+ self.unlink_from_items()
def check_if_sle_exists(self):
return frappe.db.sql("""select name from `tabStock Ledger Entry`
@@ -138,6 +139,12 @@ class Warehouse(NestedSet):
self.save()
return 1
+ def unlink_from_items(self):
+ frappe.db.sql("""
+ update `tabItem Default`
+ set default_warehouse=NULL
+ where default_warehouse=%s""", self.name)
+
@frappe.whitelist()
def get_children(doctype, parent=None, company=None, is_root=False):
if is_root:
From 22e75725ea808fff21d3f4d0178d136d1a836d4a Mon Sep 17 00:00:00 2001
From: Deepesh Garg
Date: Fri, 18 Jun 2021 17:25:37 +0530
Subject: [PATCH 245/262] fix: Sanctioned loan amount limit check
---
erpnext/loan_management/doctype/loan/loan.py | 29 +++++-
.../loan_management/doctype/loan/test_loan.py | 45 ++++++++-
.../loan_application/loan_application.py | 4 +-
.../doctype/loan_repayment/loan_repayment.py | 91 ++++++++++---------
4 files changed, 116 insertions(+), 53 deletions(-)
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index 230475f2d1..5252e0dbcb 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -60,8 +60,9 @@ class Loan(AccountsController):
self.monthly_repayment_amount = get_monthly_repayment_amount(self.repayment_method, self.loan_amount, self.rate_of_interest, self.repayment_periods)
def check_sanctioned_amount_limit(self):
- total_loan_amount = get_total_loan_amount(self.applicant_type, self.applicant, self.company)
sanctioned_amount_limit = get_sanctioned_amount_limit(self.applicant_type, self.applicant, self.company)
+ if sanctioned_amount_limit:
+ total_loan_amount = get_total_loan_amount(self.applicant_type, self.applicant, self.company)
if sanctioned_amount_limit and flt(self.loan_amount) + flt(total_loan_amount) > flt(sanctioned_amount_limit):
frappe.throw(_("Sanctioned Amount limit crossed for {0} {1}").format(self.applicant_type, frappe.bold(self.applicant)))
@@ -155,9 +156,29 @@ def update_total_amount_paid(doc):
frappe.db.set_value("Loan", doc.name, "total_amount_paid", total_amount_paid)
def get_total_loan_amount(applicant_type, applicant, company):
- return frappe.db.get_value('Loan',
- {'applicant_type': applicant_type, 'company': company, 'applicant': applicant, 'docstatus': 1},
- 'sum(loan_amount)')
+ pending_amount = 0
+ loan_details = frappe.db.get_all("Loan",
+ filters={"applicant_type": applicant_type, "company": company, "applicant": applicant, "docstatus": 1,
+ "status": ("!=", "Closed")},
+ fields=["status", "total_payment", "disbursed_amount", "total_interest_payable", "total_principal_paid",
+ "written_off_amount"])
+
+ interest_amount = flt(frappe.db.get_value("Loan Interest Accrual", {"applicant_type": applicant_type,
+ "company": company, "applicant": applicant, "docstatus": 1}, "sum(interest_amount - paid_interest_amount)"))
+
+ for loan in loan_details:
+ if loan.status in ("Disbursed", "Loan Closure Requested"):
+ pending_amount += flt(loan.total_payment) - flt(loan.total_interest_payable) \
+ - flt(loan.total_principal_paid) - flt(loan.written_off_amount)
+ elif loan.status == "Partially Disbursed":
+ pending_amount += flt(loan.disbursed_amount) - flt(loan.total_interest_payable) \
+ - flt(loan.total_principal_paid) - flt(loan.written_off_amount)
+ elif loan.status == "Sanctioned":
+ pending_amount += flt(loan.total_payment)
+
+ pending_amount += interest_amount
+
+ return pending_amount
def get_sanctioned_amount_limit(applicant_type, applicant, company):
return frappe.db.get_value('Sanctioned Loan Amount',
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index fae6f860b6..838660f7cf 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -49,7 +49,11 @@ class TestLoan(unittest.TestCase):
if not frappe.db.exists("Customer", "_Test Loan Customer"):
frappe.get_doc(get_customer_dict('_Test Loan Customer')).insert(ignore_permissions=True)
- self.applicant2 = frappe.db.get_value("Customer", {'name': '_Test Loan Customer'}, 'name')
+ if not frappe.db.exists("Customer", "_Test Loan Customer 1"):
+ frappe.get_doc(get_customer_dict("_Test Loan Customer 1")).insert(ignore_permissions=True)
+
+ self.applicant2 = frappe.db.get_value("Customer", {"name": "_Test Loan Customer"}, "name")
+ self.applicant3 = frappe.db.get_value("Customer", {"name": "_Test Loan Customer 1"}, "name")
create_loan(self.applicant1, "Personal Loan", 280000, "Repay Over Number of Periods", 20)
@@ -125,6 +129,38 @@ class TestLoan(unittest.TestCase):
self.assertTrue(gl_entries1)
self.assertTrue(gl_entries2)
+ def test_sanctioned_amount_limit(self):
+ # Clear loan docs before checking
+ frappe.db.sql("DELETE FROM `tabLoan` where applicant = '_Test Loan Customer 1'")
+ frappe.db.sql("DELETE FROM `tabLoan Application` where applicant = '_Test Loan Customer 1'")
+ frappe.db.sql("DELETE FROM `tabLoan Security Pledge` where applicant = '_Test Loan Customer 1'")
+
+ if not frappe.db.get_value("Sanctioned Loan Amount", filters={"applicant_type": "Customer",
+ "applicant": "_Test Loan Customer 1", "company": "_Test Company"}):
+ frappe.get_doc({
+ "doctype": "Sanctioned Loan Amount",
+ "applicant_type": "Customer",
+ "applicant": "_Test Loan Customer 1",
+ "sanctioned_amount_limit": 1500000,
+ "company": "_Test Company"
+ }).insert(ignore_permissions=True)
+
+ # Make First Loan
+ pledge = [{
+ "loan_security": "Test Security 1",
+ "qty": 4000.00
+ }]
+
+ loan_application = create_loan_application('_Test Company', self.applicant3, 'Demand Loan', pledge)
+ create_pledge(loan_application)
+ loan = create_demand_loan(self.applicant3, "Demand Loan", loan_application, posting_date='2019-10-01')
+ loan.submit()
+
+ # Make second loan greater than the sanctioned amount
+ loan_application = create_loan_application('_Test Company', self.applicant3, 'Demand Loan', pledge,
+ do_not_save=True)
+ self.assertRaises(frappe.ValidationError, loan_application.save)
+
def test_regular_loan_repayment(self):
pledge = [{
"loan_security": "Test Security 1",
@@ -367,7 +403,7 @@ class TestLoan(unittest.TestCase):
unpledge_request.load_from_db()
self.assertEqual(unpledge_request.docstatus, 1)
- def test_santined_loan_security_unpledge(self):
+ def test_sanctioned_loan_security_unpledge(self):
pledge = [{
"loan_security": "Test Security 1",
"qty": 4000.00
@@ -858,7 +894,7 @@ def create_repayment_entry(loan, applicant, posting_date, paid_amount):
return lr
def create_loan_application(company, applicant, loan_type, proposed_pledges, repayment_method=None,
- repayment_periods=None, posting_date=None):
+ repayment_periods=None, posting_date=None, do_not_save=False):
loan_application = frappe.new_doc('Loan Application')
loan_application.applicant_type = 'Customer'
loan_application.company = company
@@ -874,6 +910,9 @@ def create_loan_application(company, applicant, loan_type, proposed_pledges, rep
for pledge in proposed_pledges:
loan_application.append('proposed_pledges', pledge)
+ if do_not_save:
+ return loan_application
+
loan_application.save()
loan_application.submit()
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.py b/erpnext/loan_management/doctype/loan_application/loan_application.py
index 9c0147e55b..d8f3577b2c 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.py
@@ -46,9 +46,11 @@ class LoanApplication(Document):
frappe.throw(_("Loan Amount exceeds maximum loan amount of {0} as per proposed securities").format(self.maximum_loan_amount))
def check_sanctioned_amount_limit(self):
- total_loan_amount = get_total_loan_amount(self.applicant_type, self.applicant, self.company)
sanctioned_amount_limit = get_sanctioned_amount_limit(self.applicant_type, self.applicant, self.company)
+ if sanctioned_amount_limit:
+ total_loan_amount = get_total_loan_amount(self.applicant_type, self.applicant, self.company)
+
if sanctioned_amount_limit and flt(self.loan_amount) + flt(total_loan_amount) > flt(sanctioned_amount_limit):
frappe.throw(_("Sanctioned Amount limit crossed for {0} {1}").format(self.applicant_type, frappe.bold(self.applicant)))
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 3d99b1f304..b8b1a40b5f 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -235,70 +235,71 @@ class LoanRepayment(AccountsController):
else:
remarks = _("Repayment against Loan: ") + self.against_loan
- if self.total_penalty_paid:
+ if not loan_details.repay_from_salary:
+ if self.total_penalty_paid:
+ gle_map.append(
+ self.get_gl_dict({
+ "account": loan_details.loan_account,
+ "against": loan_details.payment_account,
+ "debit": self.total_penalty_paid,
+ "debit_in_account_currency": self.total_penalty_paid,
+ "against_voucher_type": "Loan",
+ "against_voucher": self.against_loan,
+ "remarks": _("Penalty against loan:") + self.against_loan,
+ "cost_center": self.cost_center,
+ "party_type": self.applicant_type,
+ "party": self.applicant,
+ "posting_date": getdate(self.posting_date)
+ })
+ )
+
+ gle_map.append(
+ self.get_gl_dict({
+ "account": loan_details.penalty_income_account,
+ "against": loan_details.payment_account,
+ "credit": self.total_penalty_paid,
+ "credit_in_account_currency": self.total_penalty_paid,
+ "against_voucher_type": "Loan",
+ "against_voucher": self.against_loan,
+ "remarks": _("Penalty against loan:") + self.against_loan,
+ "cost_center": self.cost_center,
+ "posting_date": getdate(self.posting_date)
+ })
+ )
+
gle_map.append(
self.get_gl_dict({
- "account": loan_details.loan_account,
- "against": loan_details.payment_account,
- "debit": self.total_penalty_paid,
- "debit_in_account_currency": self.total_penalty_paid,
+ "account": loan_details.payment_account,
+ "against": loan_details.loan_account + ", " + loan_details.interest_income_account
+ + ", " + loan_details.penalty_income_account,
+ "debit": self.amount_paid,
+ "debit_in_account_currency": self.amount_paid,
"against_voucher_type": "Loan",
"against_voucher": self.against_loan,
- "remarks": _("Penalty against loan:") + self.against_loan,
+ "remarks": remarks,
"cost_center": self.cost_center,
- "party_type": self.applicant_type,
- "party": self.applicant,
"posting_date": getdate(self.posting_date)
})
)
gle_map.append(
self.get_gl_dict({
- "account": loan_details.penalty_income_account,
+ "account": loan_details.loan_account,
+ "party_type": loan_details.applicant_type,
+ "party": loan_details.applicant,
"against": loan_details.payment_account,
- "credit": self.total_penalty_paid,
- "credit_in_account_currency": self.total_penalty_paid,
+ "credit": self.amount_paid,
+ "credit_in_account_currency": self.amount_paid,
"against_voucher_type": "Loan",
"against_voucher": self.against_loan,
- "remarks": _("Penalty against loan:") + self.against_loan,
+ "remarks": remarks,
"cost_center": self.cost_center,
"posting_date": getdate(self.posting_date)
})
)
- gle_map.append(
- self.get_gl_dict({
- "account": loan_details.payment_account,
- "against": loan_details.loan_account + ", " + loan_details.interest_income_account
- + ", " + loan_details.penalty_income_account,
- "debit": self.amount_paid,
- "debit_in_account_currency": self.amount_paid,
- "against_voucher_type": "Loan",
- "against_voucher": self.against_loan,
- "remarks": remarks,
- "cost_center": self.cost_center,
- "posting_date": getdate(self.posting_date)
- })
- )
-
- gle_map.append(
- self.get_gl_dict({
- "account": loan_details.loan_account,
- "party_type": loan_details.applicant_type,
- "party": loan_details.applicant,
- "against": loan_details.payment_account,
- "credit": self.amount_paid,
- "credit_in_account_currency": self.amount_paid,
- "against_voucher_type": "Loan",
- "against_voucher": self.against_loan,
- "remarks": remarks,
- "cost_center": self.cost_center,
- "posting_date": getdate(self.posting_date)
- })
- )
-
- if gle_map:
- make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj, merge_entries=False)
+ if gle_map:
+ make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj, merge_entries=False)
def create_repayment_entry(loan, applicant, company, posting_date, loan_type,
payment_type, interest_payable, payable_principal_amount, amount_paid, penalty_amount=None):
From 4d81d45a0ecbd2825f7e69d460b070e4f97243e6 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Tue, 15 Jun 2021 10:21:44 +0530
Subject: [PATCH 246/262] fix: time out while submitting the stock transactions
with more than 50 items
---
erpnext/controllers/buying_controller.py | 10 ++-
erpnext/controllers/stock_controller.py | 79 ++++++++++++++-----
.../stock_ledger_entry/stock_ledger_entry.py | 19 ++---
erpnext/stock/stock_ledger.py | 16 +++-
erpnext/stock/utils.py | 2 +-
5 files changed, 93 insertions(+), 33 deletions(-)
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index da819119b1..20f5445725 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -171,12 +171,13 @@ class BuyingController(StockController):
TODO: rename item_tax_amount to valuation_tax_amount
"""
+ stock_and_asset_items = []
stock_and_asset_items = self.get_stock_items() + self.get_asset_items()
stock_and_asset_items_qty, stock_and_asset_items_amount = 0, 0
last_item_idx = 1
for d in self.get("items"):
- if d.item_code and d.item_code in stock_and_asset_items:
+ if (d.item_code and d.item_code in stock_and_asset_items):
stock_and_asset_items_qty += flt(d.qty)
stock_and_asset_items_amount += flt(d.base_net_amount)
last_item_idx = d.idx
@@ -683,7 +684,8 @@ class BuyingController(StockController):
self.process_fixed_asset()
self.update_fixed_asset(field)
- update_last_purchase_rate(self, is_submit = 1)
+ if self.doctype in ['Purchase Order', 'Purchase Receipt']:
+ update_last_purchase_rate(self, is_submit = 1)
def on_cancel(self):
super(BuyingController, self).on_cancel()
@@ -691,7 +693,9 @@ class BuyingController(StockController):
if self.get('is_return'):
return
- update_last_purchase_rate(self, is_submit = 0)
+ if self.doctype in ['Purchase Order', 'Purchase Receipt']:
+ update_last_purchase_rate(self, is_submit = 0)
+
if self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
field = 'purchase_invoice' if self.doctype == 'Purchase Invoice' else 'purchase_receipt'
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 9c29b0076b..801c6b48d1 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -501,7 +501,6 @@ class StockController(AccountsController):
check_if_stock_and_account_balance_synced(self.posting_date,
self.company, self.doctype, self.name)
-
@frappe.whitelist()
def make_quality_inspections(doctype, docname, items):
if isinstance(items, str):
@@ -533,21 +532,75 @@ def make_quality_inspections(doctype, docname, items):
return inspections
-
def is_reposting_pending():
return frappe.db.exists("Repost Item Valuation",
{'docstatus': 1, 'status': ['in', ['Queued','In Progress']]})
+def future_sle_exists(args, sl_entries=None):
+ key = (args.voucher_type, args.voucher_no)
-def future_sle_exists(args):
- sl_entries = frappe.get_all("Stock Ledger Entry",
+ if validate_future_sle_not_exists(args, key, sl_entries):
+ return False
+ elif get_cached_data(args, key):
+ return True
+
+ if not sl_entries:
+ sl_entries = get_sle_entries_against_voucher(args)
+ if not sl_entries:
+ return
+
+ or_conditions = get_conditions_to_validate_future_sle(sl_entries)
+
+ data = frappe.db.sql("""
+ select item_code, warehouse, count(name) as total_row
+ from `tabStock Ledger Entry`
+ where
+ ({})
+ and timestamp(posting_date, posting_time)
+ >= timestamp(%(posting_date)s, %(posting_time)s)
+ and voucher_no != %(voucher_no)s
+ and is_cancelled = 0
+ GROUP BY
+ item_code, warehouse
+ """.format(" or ".join(or_conditions)), args, as_dict=1)
+
+ for d in data:
+ frappe.local.future_sle[key][(d.item_code, d.warehouse)] = d.total_row
+
+ return len(data)
+
+def validate_future_sle_not_exists(args, key, sl_entries=None):
+ item_key = ''
+ if args.get('item_code'):
+ item_key = (args.get('item_code'), args.get('warehouse'))
+
+ if not sl_entries and hasattr(frappe.local, 'future_sle'):
+ if (not frappe.local.future_sle.get(key) or
+ (item_key and item_key not in frappe.local.future_sle.get(key))):
+ return True
+
+def get_cached_data(args, key):
+ if not hasattr(frappe.local, 'future_sle'):
+ frappe.local.future_sle = {}
+
+ if key not in frappe.local.future_sle:
+ frappe.local.future_sle[key] = frappe._dict({})
+
+ if args.get('item_code'):
+ item_key = (args.get('item_code'), args.get('warehouse'))
+ count = frappe.local.future_sle[key].get(item_key)
+
+ return True if (count or count == 0) else False
+ else:
+ return frappe.local.future_sle[key]
+
+def get_sle_entries_against_voucher(args):
+ return frappe.get_all("Stock Ledger Entry",
filters={"voucher_type": args.voucher_type, "voucher_no": args.voucher_no},
fields=["item_code", "warehouse"],
order_by="creation asc")
- if not sl_entries:
- return
-
+def get_conditions_to_validate_future_sle(sl_entries):
warehouse_items_map = {}
for entry in sl_entries:
if entry.warehouse not in warehouse_items_map:
@@ -564,17 +617,7 @@ def future_sle_exists(args):
)
)
- return frappe.db.sql("""
- select name
- from `tabStock Ledger Entry`
- where
- ({})
- and timestamp(posting_date, posting_time)
- >= timestamp(%(posting_date)s, %(posting_time)s)
- and voucher_no != %(voucher_no)s
- and is_cancelled = 0
- limit 1
- """.format(" or ".join(or_conditions)), args)
+ return or_conditions
def create_repost_item_valuation_entry(args):
args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index b0e7440e6c..0febcb6891 100644
--- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
-from frappe.utils import flt, getdate, add_days, formatdate, get_datetime, date_diff
+from frappe.utils import flt, getdate, add_days, formatdate, get_datetime, cint
from frappe.model.document import Document
from datetime import date
from erpnext.controllers.item_variant import ItemTemplateCannotHaveStock
@@ -108,17 +108,18 @@ class StockLedgerEntry(Document):
self.stock_uom = item_det.stock_uom
def check_stock_frozen_date(self):
- stock_frozen_upto = frappe.db.get_value('Stock Settings', None, 'stock_frozen_upto') or ''
- if stock_frozen_upto:
- stock_auth_role = frappe.db.get_value('Stock Settings', None,'stock_auth_role')
- if getdate(self.posting_date) <= getdate(stock_frozen_upto) and not stock_auth_role in frappe.get_roles():
- frappe.throw(_("Stock transactions before {0} are frozen").format(formatdate(stock_frozen_upto)), StockFreezeError)
+ stock_settings = frappe.get_doc('Stock Settings', 'Stock Settings')
- stock_frozen_upto_days = int(frappe.db.get_value('Stock Settings', None, 'stock_frozen_upto_days') or 0)
+ if stock_settings.stock_frozen_upto:
+ if (getdate(self.posting_date) <= getdate(stock_settings.stock_frozen_upto)
+ and stock_settings.stock_auth_role not in frappe.get_roles()):
+ frappe.throw(_("Stock transactions before {0} are frozen")
+ .format(formatdate(stock_settings.stock_frozen_upto)), StockFreezeError)
+
+ stock_frozen_upto_days = cint(stock_settings.stock_frozen_upto_days)
if stock_frozen_upto_days:
- stock_auth_role = frappe.db.get_value('Stock Settings', None,'stock_auth_role')
older_than_x_days_ago = (add_days(getdate(self.posting_date), stock_frozen_upto_days) <= date.today())
- if older_than_x_days_ago and not stock_auth_role in frappe.get_roles():
+ if older_than_x_days_ago and stock_settings.stock_auth_role not in frappe.get_roles():
frappe.throw(_("Not allowed to update stock transactions older than {0}").format(stock_frozen_upto_days), StockFreezeError)
def scrub_posting_time(self):
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index fc82c789cc..fb2ecab249 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -22,6 +22,7 @@ _exceptions = frappe.local('stockledger_exceptions')
# _exceptions = []
def make_sl_entries(sl_entries, allow_negative_stock=False, via_landed_cost_voucher=False):
+ from erpnext.controllers.stock_controller import future_sle_exists
if sl_entries:
from erpnext.stock.utils import update_bin
@@ -30,6 +31,9 @@ def make_sl_entries(sl_entries, allow_negative_stock=False, via_landed_cost_vouc
validate_cancellation(sl_entries)
set_as_cancel(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no'))
+ args = get_args_for_future_sle(sl_entries[0])
+ future_sle_exists(args, sl_entries)
+
for sle in sl_entries:
if sle.serial_no:
validate_serial_no(sle)
@@ -53,6 +57,14 @@ def make_sl_entries(sl_entries, allow_negative_stock=False, via_landed_cost_vouc
args = sle_doc.as_dict()
update_bin(args, allow_negative_stock, via_landed_cost_voucher)
+def get_args_for_future_sle(row):
+ return frappe._dict({
+ 'voucher_type': row.get('voucher_type'),
+ 'voucher_no': row.get('voucher_no'),
+ 'posting_date': row.get('posting_date'),
+ 'posting_time': row.get('posting_time')
+ })
+
def validate_serial_no(sle):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
for sn in get_serial_nos(sle.serial_no):
@@ -472,8 +484,8 @@ class update_entries_after(object):
frappe.db.set_value("Purchase Receipt Item Supplied", sle.voucher_detail_no, "rate", outgoing_rate)
# Recalculate subcontracted item's rate in case of subcontracted purchase receipt/invoice
- if frappe.db.get_value(sle.voucher_type, sle.voucher_no, "is_subcontracted"):
- doc = frappe.get_doc(sle.voucher_type, sle.voucher_no)
+ if frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_subcontracted") == 'Yes':
+ doc = frappe.get_cached_doc(sle.voucher_type, sle.voucher_no)
doc.update_valuation_rate(reset_outgoing_rate=False)
for d in (doc.items + doc.supplied_items):
d.db_update()
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 034d3ebbb5..8a6a3a3e4a 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -177,7 +177,7 @@ def get_bin(item_code, warehouse):
return bin_obj
def update_bin(args, allow_negative_stock=False, via_landed_cost_voucher=False):
- is_stock_item = frappe.db.get_value('Item', args.get("item_code"), 'is_stock_item')
+ is_stock_item = frappe.get_cached_value('Item', args.get("item_code"), 'is_stock_item')
if is_stock_item:
bin = get_bin(args.get("item_code"), args.get("warehouse"))
bin.update_stock(args, allow_negative_stock, via_landed_cost_voucher)
From 9e616b09a2b40ae4c365b7cedcbb809ab587bf71 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Fri, 11 Jun 2021 17:27:08 +0530
Subject: [PATCH 247/262] fix: material request and supplier quotation not
linked if sq created from supplier portal against rfq
---
.../request_for_quotation.py | 22 ++++++++++---------
.../templates/includes/transaction_row.html | 8 ++++---
2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index 0127eb8163..a4ce84e1cf 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -317,19 +317,21 @@ def add_items(sq_doc, supplier, items):
create_rfq_items(sq_doc, supplier, data)
def create_rfq_items(sq_doc, supplier, data):
- sq_doc.append('items', {
- "item_code": data.item_code,
- "item_name": data.item_name,
- "description": data.description,
- "qty": data.qty,
- "rate": data.rate,
- "conversion_factor": data.conversion_factor if data.conversion_factor else None,
- "supplier_part_no": frappe.db.get_value("Item Supplier", {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no"),
- "warehouse": data.warehouse or '',
+ args = {}
+
+ for field in ['item_code', 'item_name', 'description', 'qty', 'rate', 'conversion_factor',
+ 'warehouse', 'material_request', 'material_request_item', 'stock_qty']:
+ args[field] = data.get(field)
+
+ args.update({
"request_for_quotation_item": data.name,
- "request_for_quotation": data.parent
+ "request_for_quotation": data.parent,
+ "supplier_part_no": frappe.db.get_value("Item Supplier",
+ {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no")
})
+ sq_doc.append('items', args)
+
@frappe.whitelist()
def get_pdf(doctype, name, supplier):
doc = get_rfq_doc(doctype, name, supplier)
diff --git a/erpnext/templates/includes/transaction_row.html b/erpnext/templates/includes/transaction_row.html
index 383413103e..3cfb8d8440 100644
--- a/erpnext/templates/includes/transaction_row.html
+++ b/erpnext/templates/includes/transaction_row.html
@@ -13,9 +13,11 @@
{{ doc.items_preview }}
-
- {{ doc.get_formatted("grand_total") }}
-
+ {% if doc.get('grand_total') %}
+
+ {{ doc.get_formatted("grand_total") }}
+
+ {% endif %}
Link
From 7b7ceaadd9143673d80caffdcac35b00503fac90 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Mon, 24 May 2021 20:11:15 +0530
Subject: [PATCH 248/262] feat: subcontract code refactor and enhancement
---
.../purchase_invoice/test_purchase_invoice.py | 2 +
.../doctype/purchase_order/purchase_order.js | 38 +-
.../purchase_order/purchase_order.json | 3 +-
.../doctype/purchase_order/purchase_order.py | 59 +-
.../purchase_order/test_purchase_order.py | 100 +--
.../purchase_order_item_supplied.json | 45 +-
.../purchase_receipt_item_supplied.json | 17 +-
.../subcontract_order_summary/__init__.py | 0
.../subcontract_order_summary.js | 45 ++
.../subcontract_order_summary.json | 32 +
.../subcontract_order_summary.py | 158 +++++
erpnext/controllers/buying_controller.py | 427 +------------
erpnext/controllers/subcontracting.py | 342 ++++++++++
erpnext/manufacturing/doctype/bom/test_bom.py | 2 +
erpnext/stock/doctype/bin/bin.py | 4 +-
.../item_alternative/test_item_alternative.py | 5 +
.../purchase_receipt/purchase_receipt.js | 2 +
.../purchase_receipt/purchase_receipt.json | 5 +-
.../purchase_receipt/purchase_receipt.py | 2 +
.../purchase_receipt/test_purchase_receipt.py | 4 +
.../stock/doctype/stock_entry/stock_entry.js | 4 +
.../doctype/stock_entry/stock_entry.json | 15 +-
.../stock/doctype/stock_entry/stock_entry.py | 79 ++-
erpnext/tests/test_subcontracting.py | 583 ++++++++++++++++++
24 files changed, 1418 insertions(+), 555 deletions(-)
create mode 100644 erpnext/buying/report/subcontract_order_summary/__init__.py
create mode 100644 erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
create mode 100644 erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.json
create mode 100644 erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
create mode 100644 erpnext/controllers/subcontracting.py
create mode 100644 erpnext/tests/test_subcontracting.py
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index 503dda7728..ff433b962f 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -621,8 +621,10 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(actual_qty_0, get_qty_after_transaction())
def test_subcontracting_via_purchase_invoice(self):
+ from erpnext.buying.doctype.purchase_order.test_purchase_order import update_backflush_based_on
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+ update_backflush_based_on('BOM')
make_stock_entry(item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100)
make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC",
qty=100, basic_rate=100)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index b5ebc568bc..88799f309c 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -53,6 +53,38 @@ frappe.ui.form.on("Purchase Order", {
} else {
frm.set_value("tax_withholding_category", frm.supplier_tds);
}
+ },
+
+ refresh: function(frm) {
+ frm.trigger('get_materials_from_supplier');
+ },
+
+ get_materials_from_supplier: function(frm) {
+ let po_details = [];
+
+ if (frm.doc.supplied_items && (frm.doc.per_received == 100 || frm.doc.status === 'Closed')) {
+ frm.doc.supplied_items.forEach(d => {
+ if (d.total_supplied_qty && d.total_supplied_qty != d.consumed_qty) {
+ po_details.push(d.name)
+ }
+ });
+ }
+
+ if (po_details && po_details.length) {
+ frm.add_custom_button(__('Return of Components'), () => {
+ frm.call({
+ method: 'erpnext.buying.doctype.purchase_order.purchase_order.get_materials_from_supplier',
+ freeze_message: __('Creating Stock Entry'),
+ args: { purchase_order: frm.doc.name, po_details: po_details },
+ callback: function(r) {
+ if (r && r.message) {
+ const doc = frappe.model.sync(r.message);
+ frappe.set_route("Form", doc[0].doctype, doc[0].name);
+ }
+ }
+ });
+ }, __('Create'));
+ }
}
});
@@ -217,7 +249,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e
}
has_unsupplied_items() {
- return this.frm.doc['supplied_items'].some(item => item.required_qty != item.supplied_qty)
+ return this.frm.doc['supplied_items'].some(item => item.required_qty > item.supplied_qty);
}
make_stock_entry() {
@@ -513,12 +545,14 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e
],
primary_action: function() {
var data = d.get_values();
+ var content_msg = 'Reason for hold: ' + data.reason_for_hold;
+
frappe.call({
method: "frappe.desk.form.utils.add_comment",
args: {
reference_doctype: me.frm.doctype,
reference_name: me.frm.docname,
- content: __('Reason for hold:') + " " +data.reason_for_hold,
+ content: __(content_msg),
comment_email: frappe.session.user,
comment_by: frappe.session.user_fullname
},
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 41668c6291..bb0ad60cab 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -609,6 +609,7 @@
"fieldname": "supplied_items",
"fieldtype": "Table",
"label": "Supplied Items",
+ "no_copy": 1,
"oldfieldname": "po_raw_material_details",
"oldfieldtype": "Table",
"options": "Purchase Order Item Supplied",
@@ -1377,7 +1378,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-19 00:55:30.781375",
+ "modified": "2021-05-30 15:17:53.663648",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 2629ba7d61..724f863e0f 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -503,9 +503,10 @@ def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions
@frappe.whitelist()
def make_rm_stock_entry(purchase_order, rm_items):
+ rm_items_list = rm_items
if isinstance(rm_items, string_types):
rm_items_list = json.loads(rm_items)
- else:
+ elif not rm_items:
frappe.throw(_("No Items available for transfer"))
if rm_items_list:
@@ -543,6 +544,8 @@ def make_rm_stock_entry(purchase_order, rm_items):
'qty': rm_item_data["qty"],
'from_warehouse': rm_item_data["warehouse"],
'stock_uom': rm_item_data["stock_uom"],
+ 'serial_no': rm_item_data.get('serial_no'),
+ 'batch_no': rm_item_data.get('batch_no'),
'main_item_code': rm_item_data["item_code"],
'allow_alternative_item': item_wh.get(rm_item_code, {}).get('allow_alternative_item')
}
@@ -582,3 +585,57 @@ def update_status(status, name):
def make_inter_company_sales_order(source_name, target_doc=None):
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_inter_company_transaction
return make_inter_company_transaction("Purchase Order", source_name, target_doc)
+
+@frappe.whitelist()
+def get_materials_from_supplier(purchase_order, po_details):
+ if isinstance(po_details, string_types):
+ po_details = json.loads(po_details)
+
+ doc = frappe.get_cached_doc('Purchase Order', purchase_order)
+ doc.initialized_fields()
+ doc.purchase_orders = [doc.name]
+ doc.get_available_materials()
+
+ if not doc.available_materials:
+ frappe.throw(_('Materials are already received against the purchase order {0}')
+ .format(purchase_order))
+
+ return make_return_stock_entry_for_subcontract(doc.available_materials, doc, po_details)
+
+def make_return_stock_entry_for_subcontract(available_materials, po_doc, po_details):
+ ste_doc = frappe.new_doc('Stock Entry')
+ ste_doc.purpose = 'Material Transfer'
+ ste_doc.purchase_order = po_doc.name
+ ste_doc.company = po_doc.company
+ ste_doc.is_return = 1
+
+ for key, value in available_materials.items():
+ if not value.qty:
+ continue
+
+ if value.batch_no:
+ for batch_no, qty in value.batch_no.items():
+ add_items_in_ste(ste_doc, value, value.qty, po_details, batch_no)
+ else:
+ add_items_in_ste(ste_doc, value, value.qty, po_details)
+
+ ste_doc.set_stock_entry_type()
+ ste_doc.calculate_rate_and_amount()
+
+ return ste_doc
+
+def add_items_in_ste(ste_doc, row, qty, po_details, batch_no=None):
+ item = ste_doc.append('items', row.item_details)
+
+ po_detail = list(set(row.po_details).intersection(po_details))
+ item.update({
+ 'qty': qty,
+ 'batch_no': batch_no,
+ 'basic_rate': row.item_details['rate'],
+ 'po_detail': po_detail[0] if po_detail else '',
+ 's_warehouse': row.item_details['t_warehouse'],
+ 't_warehouse': row.item_details['s_warehouse'],
+ 'item_code': row.item_details['rm_item_code'],
+ 'subcontracted_item': row.item_details['main_item_code'],
+ 'serial_no': '\n'.join(row.serial_no) if row.serial_no else ''
+ })
\ No newline at end of file
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 3b9f8e9775..33d1971451 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -20,7 +20,6 @@ from erpnext.controllers.status_updater import OverAllowanceError
from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
from erpnext.stock.doctype.batch.test_batch import make_new_batch
-from erpnext.controllers.buying_controller import get_backflushed_subcontracted_raw_materials
class TestPurchaseOrder(unittest.TestCase):
def test_make_purchase_receipt(self):
@@ -771,7 +770,7 @@ class TestPurchaseOrder(unittest.TestCase):
self.assertEqual(bin11.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
def test_exploded_items_in_subcontracted(self):
- item_code = "_Test Subcontracted FG Item 1"
+ item_code = "_Test Subcontracted FG Item 11"
make_subcontracted_item(item_code=item_code)
po = create_purchase_order(item_code=item_code, qty=1,
@@ -853,76 +852,6 @@ class TestPurchaseOrder(unittest.TestCase):
update_backflush_based_on("BOM")
- def test_backflushed_based_on_for_multiple_batches(self):
- item_code = "_Test Subcontracted FG Item 2"
- make_item('Sub Contracted Raw Material 2', {
- 'is_stock_item': 1,
- 'is_sub_contracted_item': 1
- })
-
- make_subcontracted_item(item_code=item_code, has_batch_no=1, create_new_batch=1,
- raw_materials=["Sub Contracted Raw Material 2"])
-
- update_backflush_based_on("Material Transferred for Subcontract")
-
- order_qty = 500
- po = create_purchase_order(item_code=item_code, qty=order_qty,
- is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
-
- make_stock_entry(target="_Test Warehouse - _TC",
- item_code = "Sub Contracted Raw Material 2", qty=552, basic_rate=100)
-
- rm_items = [
- {"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 2","item_name":"_Test Item",
- "qty":552,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"}]
-
- rm_item_string = json.dumps(rm_items)
- se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
- se.submit()
-
- for batch in ["ABCD1", "ABCD2", "ABCD3", "ABCD4"]:
- make_new_batch(batch_id=batch, item_code=item_code)
-
- pr = make_purchase_receipt(po.name)
-
- # partial receipt
- pr.get('items')[0].qty = 30
- pr.get('items')[0].batch_no = "ABCD1"
-
- purchase_order = po.name
- purchase_order_item = po.items[0].name
-
- for batch_no, qty in {"ABCD2": 60, "ABCD3": 70, "ABCD4":40}.items():
- pr.append("items", {
- "item_code": pr.get('items')[0].item_code,
- "item_name": pr.get('items')[0].item_name,
- "uom": pr.get('items')[0].uom,
- "stock_uom": pr.get('items')[0].stock_uom,
- "warehouse": pr.get('items')[0].warehouse,
- "conversion_factor": pr.get('items')[0].conversion_factor,
- "cost_center": pr.get('items')[0].cost_center,
- "rate": pr.get('items')[0].rate,
- "qty": qty,
- "batch_no": batch_no,
- "purchase_order": purchase_order,
- "purchase_order_item": purchase_order_item
- })
-
- pr.submit()
-
- pr1 = make_purchase_receipt(po.name)
- pr1.get('items')[0].qty = 300
- pr1.get('items')[0].batch_no = "ABCD1"
- pr1.save()
-
- pr_key = ("Sub Contracted Raw Material 2", po.name)
- consumed_qty = get_backflushed_subcontracted_raw_materials([po.name]).get(pr_key)
-
- self.assertTrue(pr1.supplied_items[0].consumed_qty > 0)
- self.assertTrue(pr1.supplied_items[0].consumed_qty, flt(552.0) - flt(consumed_qty))
-
- update_backflush_based_on("BOM")
-
def test_supplied_qty_against_subcontracted_po(self):
item_code = "_Test Subcontracted FG Item 5"
make_item('Sub Contracted Raw Material 4', {
@@ -1117,22 +1046,29 @@ def create_purchase_order(**args):
po.conversion_factor = args.conversion_factor or 1
po.supplier_warehouse = args.supplier_warehouse or None
- po.append("items", {
- "item_code": args.item or args.item_code or "_Test Item",
- "warehouse": args.warehouse or "_Test Warehouse - _TC",
- "qty": args.qty or 10,
- "rate": args.rate or 500,
- "schedule_date": add_days(nowdate(), 1),
- "include_exploded_items": args.get('include_exploded_items', 1),
- "against_blanket_order": args.against_blanket_order
- })
+ if args.rm_items:
+ for row in args.rm_items:
+ po.append("items", row)
+ else:
+ po.append("items", {
+ "item_code": args.item or args.item_code or "_Test Item",
+ "warehouse": args.warehouse or "_Test Warehouse - _TC",
+ "qty": args.qty or 10,
+ "rate": args.rate or 500,
+ "schedule_date": add_days(nowdate(), 1),
+ "include_exploded_items": args.get('include_exploded_items', 1),
+ "against_blanket_order": args.against_blanket_order
+ })
+
+ po.set_missing_values()
if not args.do_not_save:
po.insert()
if not args.do_not_submit:
if po.is_subcontracted == "Yes":
supp_items = po.get("supplied_items")
for d in supp_items:
- d.reserve_warehouse = args.warehouse or "_Test Warehouse - _TC"
+ if not d.reserve_warehouse:
+ d.reserve_warehouse = args.warehouse or "_Test Warehouse - _TC"
po.submit()
return po
diff --git a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
index d7ea9c1ccc..505ecd84c5 100644
--- a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
+++ b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
@@ -6,21 +6,25 @@
"engine": "InnoDB",
"field_order": [
"main_item_code",
- "bom_detail_no",
+ "rm_item_code",
+ "column_break_3",
"stock_uom",
+ "reserve_warehouse",
"conversion_factor",
"column_break_6",
- "rm_item_code",
+ "bom_detail_no",
"reference_name",
- "reserve_warehouse",
"section_break2",
"rate",
"col_break2",
"amount",
"section_break1",
"required_qty",
+ "supplied_qty",
"col_break1",
- "supplied_qty"
+ "returned_qty",
+ "total_supplied_qty",
+ "consumed_qty"
],
"fields": [
{
@@ -125,6 +129,8 @@
"fieldtype": "Float",
"in_list_view": 1,
"label": "Supplied Qty",
+ "no_copy": 1,
+ "print_hide": 1,
"read_only": 1
},
{
@@ -142,13 +148,42 @@
{
"fieldname": "col_break2",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "consumed_qty",
+ "fieldtype": "Float",
+ "label": "Consumed Qty",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "returned_qty",
+ "fieldtype": "Float",
+ "label": "Returned Qty",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "total_supplied_qty",
+ "fieldtype": "Float",
+ "hidden": 1,
+ "label": "Total Supplied Qty",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "fieldname": "column_break_3",
+ "fieldtype": "Column Break"
}
],
"hide_toolbar": 1,
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-09-18 17:26:09.703215",
+ "modified": "2021-06-01 00:41:54.123436",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item Supplied",
diff --git a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json
index dc00bca5cc..d8c37f5881 100644
--- a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json
+++ b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json
@@ -6,10 +6,11 @@
"engine": "InnoDB",
"field_order": [
"main_item_code",
- "description",
+ "rm_item_code",
+ "item_name",
"bom_detail_no",
"col_break1",
- "rm_item_code",
+ "description",
"stock_uom",
"conversion_factor",
"reference_name",
@@ -52,7 +53,6 @@
"fieldname": "description",
"fieldtype": "Text Editor",
"in_global_search": 1,
- "in_list_view": 1,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Data",
@@ -87,12 +87,13 @@
"read_only": 1
},
{
+ "columns": 2,
"fieldname": "consumed_qty",
"fieldtype": "Float",
+ "in_list_view": 1,
"label": "Consumed Qty",
"oldfieldname": "consumed_qty",
"oldfieldtype": "Currency",
- "read_only": 1,
"reqd": 1
},
{
@@ -183,12 +184,18 @@
{
"fieldname": "col_break4",
"fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2020-09-18 17:26:09.703215",
+ "modified": "2021-05-29 17:22:14.977117",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Receipt Item Supplied",
diff --git a/erpnext/buying/report/subcontract_order_summary/__init__.py b/erpnext/buying/report/subcontract_order_summary/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
new file mode 100644
index 0000000000..5ba52f1b21
--- /dev/null
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.js
@@ -0,0 +1,45 @@
+// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Subcontract Order Summary"] = {
+ "filters": [
+ {
+ label: __("Company"),
+ fieldname: "company",
+ fieldtype: "Link",
+ options: "Company",
+ default: frappe.defaults.get_user_default("Company"),
+ reqd: 1
+ },
+ {
+ label: __("From Date"),
+ fieldname:"from_date",
+ fieldtype: "Date",
+ default: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
+ reqd: 1
+ },
+ {
+ label: __("To Date"),
+ fieldname:"to_date",
+ fieldtype: "Date",
+ default: frappe.datetime.get_today(),
+ reqd: 1
+ },
+ {
+ label: __("Purchase Order"),
+ fieldname: "name",
+ fieldtype: "Link",
+ options: "Purchase Order",
+ get_query: function() {
+ return {
+ filters: {
+ docstatus: 1,
+ is_subcontracted: 'Yes',
+ company: frappe.query_report.get_filter_value('company')
+ }
+ }
+ }
+ }
+ ]
+};
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.json b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.json
new file mode 100644
index 0000000000..526a8d8ad0
--- /dev/null
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.json
@@ -0,0 +1,32 @@
+{
+ "add_total_row": 0,
+ "columns": [],
+ "creation": "2021-05-31 14:43:32.417694",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "modified": "2021-05-31 14:43:32.417694",
+ "modified_by": "Administrator",
+ "module": "Buying",
+ "name": "Subcontract Order Summary",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Purchase Order",
+ "report_name": "Subcontract Order Summary",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "Stock User"
+ },
+ {
+ "role": "Purchase Manager"
+ },
+ {
+ "role": "Purchase User"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
new file mode 100644
index 0000000000..8b08d2a284
--- /dev/null
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
@@ -0,0 +1,158 @@
+# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe import _
+
+def execute(filters=None):
+ columns, data = [], []
+ columns = get_columns()
+ data = get_data(filters)
+
+ return columns, data
+
+def get_data(report_filters):
+ data = []
+ orders = get_subcontracted_orders(report_filters)
+
+ if orders:
+ supplied_items = get_supplied_items(orders, report_filters)
+ po_details = prepare_subcontracted_data(orders, supplied_items)
+ get_subcontracted_data(po_details, data)
+
+ return data
+
+def get_subcontracted_orders(report_filters):
+ fields = ['`tabPurchase Order Item`.`parent` as po_id', '`tabPurchase Order Item`.`item_code`',
+ '`tabPurchase Order Item`.`item_name`', '`tabPurchase Order Item`.`qty`', '`tabPurchase Order Item`.`name`',
+ '`tabPurchase Order Item`.`received_qty`', '`tabPurchase Order`.`status`']
+
+ filters = get_filters(report_filters)
+
+ return frappe.get_all('Purchase Order', fields = fields, filters=filters) or []
+
+def get_filters(report_filters):
+ filters = [['Purchase Order', 'docstatus', '=', 1], ['Purchase Order', 'is_subcontracted', '=', 'Yes'],
+ ['Purchase Order', 'transaction_date', 'between', (report_filters.from_date, report_filters.to_date)]]
+
+ for field in ['name', 'company']:
+ if report_filters.get(field):
+ filters.append(['Purchase Order', field, '=', report_filters.get(field)])
+
+ return filters
+
+def get_supplied_items(orders, report_filters):
+ if not orders:
+ return []
+
+ fields = ['parent', 'main_item_code', 'rm_item_code', 'required_qty',
+ 'supplied_qty', 'returned_qty', 'total_supplied_qty', 'consumed_qty', 'reference_name']
+
+ filters = {'parent': ('in', [d.po_id for d in orders]), 'docstatus': 1}
+
+ supplied_items = {}
+ for row in frappe.get_all('Purchase Order Item Supplied', fields = fields, filters=filters):
+ new_key = (row.parent, row.reference_name, row.main_item_code)
+
+ supplied_items.setdefault(new_key, []).append(row)
+
+ return supplied_items
+
+def prepare_subcontracted_data(orders, supplied_items):
+ po_details = {}
+ for row in orders:
+ key = (row.po_id, row.name, row.item_code)
+ if key not in po_details:
+ po_details.setdefault(key, frappe._dict({'po_item': row, 'supplied_items': []}))
+
+ details = po_details[key]
+
+ if supplied_items.get(key):
+ for supplied_item in supplied_items[key]:
+ details['supplied_items'].append(supplied_item)
+
+ return po_details
+
+def get_subcontracted_data(po_details, data):
+ for key, details in po_details.items():
+ res = details.po_item
+ for index, row in enumerate(details.supplied_items):
+ if index != 0:
+ res = {}
+
+ res.update(row)
+ data.append(res)
+
+def get_columns():
+ return [
+ {
+ "label": _("Id"),
+ "fieldname": "po_id",
+ "fieldtype": "Link",
+ "options": "Purchase Order",
+ "width": 100
+ },
+ {
+ "label": _("Status"),
+ "fieldname": "status",
+ "fieldtype": "Data",
+ "width": 80
+ },
+ {
+ "label": _("Subcontracted Item"),
+ "fieldname": "item_code",
+ "fieldtype": "Link",
+ "options": "Item",
+ "width": 140
+ },
+ {
+ "label": _("Qty"),
+ "fieldname": "qty",
+ "fieldtype": "Float",
+ "width": 70
+ },
+ {
+ "label": _("Received"),
+ "fieldname": "received_qty",
+ "fieldtype": "Float",
+ "width": 80
+ },
+ {
+ "label": _("Supplied Item"),
+ "fieldname": "rm_item_code",
+ "fieldtype": "Link",
+ "options": "Item",
+ "width": 140
+ },
+ {
+ "label": _("Required Qty"),
+ "fieldname": "required_qty",
+ "fieldtype": "Float",
+ "width": 110
+ },
+ {
+ "label": _("Supplied Qty"),
+ "fieldname": "supplied_qty",
+ "fieldtype": "Float",
+ "width": 110
+ },
+ {
+ "label": _("Returned Qty"),
+ "fieldname": "returned_qty",
+ "fieldtype": "Float",
+ "width": 110
+ },
+ {
+ "label": _("Total Supplied"),
+ "fieldname": "total_supplied_qty",
+ "fieldtype": "Float",
+ "width": 120
+ },
+ {
+ "label": _("Consumed Qty"),
+ "fieldname": "consumed_qty",
+ "fieldtype": "Float",
+ "width": 110
+ },
+ ]
\ No newline at end of file
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 20f5445725..1907885717 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -11,16 +11,17 @@ from erpnext.accounts.party import get_party_details
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
from erpnext.stock.stock_ledger import get_valuation_rate
-from erpnext.stock.doctype.stock_entry.stock_entry import get_used_alternative_items
from erpnext.stock.doctype.serial_no.serial_no import get_auto_serial_nos, auto_make_serial_nos, get_serial_nos
from frappe.contacts.doctype.address.address import get_address_display
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
-from erpnext.controllers.stock_controller import StockController
from erpnext.controllers.sales_and_purchase_return import get_rate_for_return
from erpnext.stock.utils import get_incoming_rate
-class BuyingController(StockController):
+from erpnext.controllers.stock_controller import StockController
+from erpnext.controllers.subcontracting import Subcontracting
+
+class BuyingController(StockController, Subcontracting):
def get_feed(self):
if self.get("supplier_name"):
@@ -256,7 +257,7 @@ class BuyingController(StockController):
supplied_items_cost = 0.0
for d in self.get("supplied_items"):
if d.reference_name == item_row_id:
- if reset_outgoing_rate and frappe.db.get_value('Item', d.rm_item_code, 'is_stock_item'):
+ if reset_outgoing_rate and frappe.get_cached_value('Item', d.rm_item_code, 'is_stock_item'):
rate = get_incoming_rate({
"item_code": d.rm_item_code,
"warehouse": self.supplier_warehouse,
@@ -298,23 +299,7 @@ class BuyingController(StockController):
def create_raw_materials_supplied(self, raw_material_table):
if self.is_subcontracted=="Yes":
- parent_items = []
- backflush_raw_materials_based_on = frappe.db.get_single_value("Buying Settings",
- "backflush_raw_materials_of_subcontract_based_on")
- if (self.doctype == 'Purchase Receipt' and
- backflush_raw_materials_based_on != 'BOM'):
- self.update_raw_materials_supplied_based_on_stock_entries()
- else:
- for item in self.get("items"):
- if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
- item.rm_supp_cost = 0.0
- if item.bom and item.item_code in self.sub_contracted_items:
- self.update_raw_materials_supplied_based_on_bom(item, raw_material_table)
-
- if [item.item_code, item.name] not in parent_items:
- parent_items.append([item.item_code, item.name])
-
- self.cleanup_raw_materials_supplied(parent_items, raw_material_table)
+ self.set_materials_for_subcontracted_items(raw_material_table)
elif self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
for item in self.get("items"):
@@ -323,176 +308,6 @@ class BuyingController(StockController):
if self.is_subcontracted == "No" and self.get("supplied_items"):
self.set('supplied_items', [])
- def update_raw_materials_supplied_based_on_stock_entries(self):
- self.set('supplied_items', [])
-
- purchase_orders = set(d.purchase_order for d in self.items)
-
- # qty of raw materials backflushed (for each item per purchase order)
- backflushed_raw_materials_map = get_backflushed_subcontracted_raw_materials(purchase_orders)
-
- # qty of "finished good" item yet to be received
- qty_to_be_received_map = get_qty_to_be_received(purchase_orders)
-
- for item in self.get('items'):
- if not item.purchase_order:
- continue
-
- # reset raw_material cost
- item.rm_supp_cost = 0
-
- # qty of raw materials transferred to the supplier
- transferred_raw_materials = get_subcontracted_raw_materials_from_se(item.purchase_order, item.item_code)
-
- non_stock_items = get_non_stock_items(item.purchase_order, item.item_code)
-
- item_key = '{}{}'.format(item.item_code, item.purchase_order)
-
- fg_yet_to_be_received = qty_to_be_received_map.get(item_key)
-
- if not fg_yet_to_be_received:
- frappe.throw(_("Row #{0}: Item {1} is already fully received in Purchase Order {2}")
- .format(item.idx, frappe.bold(item.item_code),
- frappe.utils.get_link_to_form("Purchase Order", item.purchase_order)),
- title=_("Limit Crossed"))
-
- transferred_batch_qty_map = get_transferred_batch_qty_map(item.purchase_order, item.item_code)
- # backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
-
- for raw_material in transferred_raw_materials + non_stock_items:
- rm_item_key = (raw_material.rm_item_code, item.item_code, item.purchase_order)
- raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {})
-
- consumed_qty = raw_material_data.get('qty', 0)
- consumed_serial_nos = raw_material_data.get('serial_no', '')
- consumed_batch_nos = raw_material_data.get('batch_nos', '')
-
- transferred_qty = raw_material.qty
-
- rm_qty_to_be_consumed = transferred_qty - consumed_qty
-
- # backflush all remaining transferred qty in the last Purchase Receipt
- if fg_yet_to_be_received == item.qty:
- qty = rm_qty_to_be_consumed
- else:
- qty = (rm_qty_to_be_consumed / fg_yet_to_be_received) * item.qty
-
- if frappe.get_cached_value('UOM', raw_material.stock_uom, 'must_be_whole_number'):
- qty = frappe.utils.ceil(qty)
-
- if qty > rm_qty_to_be_consumed:
- qty = rm_qty_to_be_consumed
-
- if not qty: continue
-
- if raw_material.serial_nos:
- set_serial_nos(raw_material, consumed_serial_nos, qty)
-
- if raw_material.batch_nos:
- backflushed_batch_qty_map = raw_material_data.get('consumed_batch', {})
-
- batches_qty = get_batches_with_qty(raw_material.rm_item_code, raw_material.main_item_code,
- qty, transferred_batch_qty_map, backflushed_batch_qty_map, item.purchase_order)
-
- for batch_data in batches_qty:
- qty = batch_data['qty']
- raw_material.batch_no = batch_data['batch']
- if qty > 0:
- self.append_raw_material_to_be_backflushed(item, raw_material, qty)
- else:
- self.append_raw_material_to_be_backflushed(item, raw_material, qty)
-
- def append_raw_material_to_be_backflushed(self, fg_item_row, raw_material_data, qty):
- rm = self.append('supplied_items', {})
- rm.update(raw_material_data)
-
- if not rm.main_item_code:
- rm.main_item_code = fg_item_row.item_code
-
- rm.reference_name = fg_item_row.name
- rm.required_qty = qty
- rm.consumed_qty = qty
-
- def update_raw_materials_supplied_based_on_bom(self, item, raw_material_table):
- exploded_item = 1
- if hasattr(item, 'include_exploded_items'):
- exploded_item = item.get('include_exploded_items')
-
- bom_items = get_items_from_bom(item.item_code, item.bom, exploded_item)
-
- used_alternative_items = []
- if self.doctype in ["Purchase Receipt", "Purchase Invoice"] and item.purchase_order:
- used_alternative_items = get_used_alternative_items(purchase_order = item.purchase_order)
-
- raw_materials_cost = 0
- items = list(set([d.item_code for d in bom_items]))
- item_wh = frappe._dict(frappe.db.sql("""select i.item_code, id.default_warehouse
- from `tabItem` i, `tabItem Default` id
- where id.parent=i.name and id.company=%s and i.name in ({0})"""
- .format(", ".join(["%s"] * len(items))), [self.company] + items))
-
- for bom_item in bom_items:
- if self.doctype == "Purchase Order":
- reserve_warehouse = bom_item.source_warehouse or item_wh.get(bom_item.item_code)
- if frappe.db.get_value("Warehouse", reserve_warehouse, "company") != self.company:
- reserve_warehouse = None
-
- conversion_factor = item.conversion_factor
- if (self.doctype in ["Purchase Receipt", "Purchase Invoice"] and item.purchase_order and
- bom_item.item_code in used_alternative_items):
- alternative_item_data = used_alternative_items.get(bom_item.item_code)
- bom_item.item_code = alternative_item_data.item_code
- bom_item.item_name = alternative_item_data.item_name
- bom_item.stock_uom = alternative_item_data.stock_uom
- conversion_factor = alternative_item_data.conversion_factor
- bom_item.description = alternative_item_data.description
-
- # check if exists
- exists = 0
- for d in self.get(raw_material_table):
- if d.main_item_code == item.item_code and d.rm_item_code == bom_item.item_code \
- and d.reference_name == item.name:
- rm, exists = d, 1
- break
-
- if not exists:
- rm = self.append(raw_material_table, {})
-
- required_qty = flt(flt(bom_item.qty_consumed_per_unit) * (flt(item.qty) + getattr(item, 'rejected_qty', 0)) *
- flt(conversion_factor), rm.precision("required_qty"))
- rm.reference_name = item.name
- rm.bom_detail_no = bom_item.name
- rm.main_item_code = item.item_code
- rm.rm_item_code = bom_item.item_code
- rm.stock_uom = bom_item.stock_uom
- rm.required_qty = required_qty
- rm.rate = bom_item.rate
- rm.conversion_factor = conversion_factor
-
- if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
- rm.consumed_qty = required_qty
- rm.description = bom_item.description
- if item.batch_no and frappe.db.get_value("Item", rm.rm_item_code, "has_batch_no") and not rm.batch_no:
- rm.batch_no = item.batch_no
- elif not rm.reserve_warehouse:
- rm.reserve_warehouse = reserve_warehouse
-
- def cleanup_raw_materials_supplied(self, parent_items, raw_material_table):
- """Remove all those child items which are no longer present in main item table"""
- delete_list = []
- for d in self.get(raw_material_table):
- if [d.main_item_code, d.reference_name] not in parent_items:
- # mark for deletion from doclist
- delete_list.append(d)
-
- # delete from doclist
- if delete_list:
- rm_supplied_details = self.get(raw_material_table)
- self.set(raw_material_table, [])
- for d in rm_supplied_details:
- if d not in delete_list:
- self.append(raw_material_table, d)
-
@property
def sub_contracted_items(self):
if not hasattr(self, "_sub_contracted_items"):
@@ -867,104 +682,6 @@ class BuyingController(StockController):
else:
validate_item_type(self, "is_purchase_item", "purchase")
-
-def get_items_from_bom(item_code, bom, exploded_item=1):
- doctype = "BOM Item" if not exploded_item else "BOM Explosion Item"
-
- bom_items = frappe.db.sql("""select t2.item_code, t2.name,
- t2.rate, t2.stock_uom, t2.source_warehouse, t2.description,
- t2.stock_qty / ifnull(t1.quantity, 1) as qty_consumed_per_unit
- from
- `tabBOM` t1, `tab{0}` t2, tabItem t3
- where
- t2.parent = t1.name and t1.item = %s
- and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
- and t2.sourced_by_supplier = 0
- and t2.item_code = t3.name""".format(doctype),
- (item_code, bom), as_dict=1)
-
- if not bom_items:
- msgprint(_("Specified BOM {0} does not exist for Item {1}").format(bom, item_code), raise_exception=1)
-
- return bom_items
-
-def get_subcontracted_raw_materials_from_se(purchase_order, fg_item):
- common_query = """
- SELECT
- sed.item_code AS rm_item_code,
- SUM(sed.qty) AS qty,
- sed.description,
- sed.stock_uom,
- sed.subcontracted_item AS main_item_code,
- {serial_no_concat_syntax} AS serial_nos,
- {batch_no_concat_syntax} AS batch_nos
- FROM `tabStock Entry` se,`tabStock Entry Detail` sed
- WHERE
- se.name = sed.parent
- AND se.docstatus=1
- AND se.purpose='Send to Subcontractor'
- AND se.purchase_order = %s
- AND IFNULL(sed.t_warehouse, '') != ''
- AND IFNULL(sed.subcontracted_item, '') in ('', %s)
- GROUP BY sed.item_code, sed.subcontracted_item
- """
- raw_materials = frappe.db.multisql({
- 'mariadb': common_query.format(
- serial_no_concat_syntax="GROUP_CONCAT(sed.serial_no)",
- batch_no_concat_syntax="GROUP_CONCAT(sed.batch_no)"
- ),
- 'postgres': common_query.format(
- serial_no_concat_syntax="STRING_AGG(sed.serial_no, ',')",
- batch_no_concat_syntax="STRING_AGG(sed.batch_no, ',')"
- )
- }, (purchase_order, fg_item), as_dict=1)
-
- return raw_materials
-
-def get_backflushed_subcontracted_raw_materials(purchase_orders):
- purchase_receipts = frappe.get_all("Purchase Receipt Item",
- fields = ["purchase_order", "item_code", "name", "parent"],
- filters={"docstatus": 1, "purchase_order": ("in", list(purchase_orders))})
-
- distinct_purchase_receipts = {}
- for pr in purchase_receipts:
- key = (pr.purchase_order, pr.item_code, pr.parent)
- distinct_purchase_receipts.setdefault(key, []).append(pr.name)
-
- backflushed_raw_materials_map = frappe._dict()
- for args, references in iteritems(distinct_purchase_receipts):
- purchase_receipt_supplied_items = get_supplied_items(args[1], args[2], references)
-
- for data in purchase_receipt_supplied_items:
- pr_key = (data.rm_item_code, data.main_item_code, args[0])
- if pr_key not in backflushed_raw_materials_map:
- backflushed_raw_materials_map.setdefault(pr_key, frappe._dict({
- "qty": 0.0,
- "serial_no": [],
- "batch_no": [],
- "consumed_batch": {}
- }))
-
- row = backflushed_raw_materials_map.get(pr_key)
- row.qty += data.consumed_qty
-
- for field in ["serial_no", "batch_no"]:
- if data.get(field):
- row[field].append(data.get(field))
-
- if data.get("batch_no"):
- if data.get("batch_no") in row.consumed_batch:
- row.consumed_batch[data.get("batch_no")] += data.consumed_qty
- else:
- row.consumed_batch[data.get("batch_no")] = data.consumed_qty
-
- return backflushed_raw_materials_map
-
-def get_supplied_items(item_code, purchase_receipt, references):
- return frappe.get_all("Purchase Receipt Item Supplied",
- fields=["rm_item_code", "main_item_code", "consumed_qty", "serial_no", "batch_no"],
- filters={"main_item_code": item_code, "parent": purchase_receipt, "reference_name": ("in", references)})
-
def get_asset_item_details(asset_items):
asset_items_data = {}
for d in frappe.get_all('Item', fields = ["name", "auto_create_assets", "asset_naming_series"],
@@ -996,135 +713,3 @@ def validate_item_type(doc, fieldname, message):
error_message = _("Following item {0} is not marked as {1} item. You can enable them as {1} item from its Item master").format(items, message)
frappe.throw(error_message)
-
-def get_qty_to_be_received(purchase_orders):
- return frappe._dict(frappe.db.sql("""
- SELECT CONCAT(poi.`item_code`, poi.`parent`) AS item_key,
- SUM(poi.`qty`) - SUM(poi.`received_qty`) AS qty_to_be_received
- FROM `tabPurchase Order Item` poi
- WHERE
- poi.`parent` in %s
- GROUP BY poi.`item_code`, poi.`parent`
- HAVING SUM(poi.`qty`) > SUM(poi.`received_qty`)
- """, (purchase_orders)))
-
-def get_non_stock_items(purchase_order, fg_item_code):
- return frappe.db.sql("""
- SELECT
- pois.main_item_code,
- pois.rm_item_code,
- item.description,
- pois.required_qty AS qty,
- pois.rate,
- 1 as non_stock_item,
- pois.stock_uom
- FROM `tabPurchase Order Item Supplied` pois, `tabItem` item
- WHERE
- pois.`rm_item_code` = item.`name`
- AND item.is_stock_item = 0
- AND pois.`parent` = %s
- AND pois.`main_item_code` = %s
- """, (purchase_order, fg_item_code), as_dict=1)
-
-
-def set_serial_nos(raw_material, consumed_serial_nos, qty):
- serial_nos = set(get_serial_nos(raw_material.serial_nos)) - \
- set(get_serial_nos(consumed_serial_nos))
- if serial_nos and qty <= len(serial_nos):
- raw_material.serial_no = '\n'.join(list(serial_nos)[0:frappe.utils.cint(qty)])
-
-def get_transferred_batch_qty_map(purchase_order, fg_item):
- # returns
- # {
- # (item_code, fg_code): {
- # batch1: 10, # qty
- # batch2: 16
- # },
- # }
- transferred_batch_qty_map = {}
- transferred_batches = frappe.db.sql("""
- SELECT
- sed.batch_no,
- SUM(sed.qty) AS qty,
- sed.item_code,
- sed.subcontracted_item
- FROM `tabStock Entry` se,`tabStock Entry Detail` sed
- WHERE
- se.name = sed.parent
- AND se.docstatus=1
- AND se.purpose='Send to Subcontractor'
- AND se.purchase_order = %s
- AND ifnull(sed.subcontracted_item, '') in ('', %s)
- AND sed.batch_no IS NOT NULL
- GROUP BY
- sed.batch_no,
- sed.item_code
- """, (purchase_order, fg_item), as_dict=1)
-
- for batch_data in transferred_batches:
- key = ((batch_data.item_code, fg_item)
- if batch_data.subcontracted_item else (batch_data.item_code, purchase_order))
- transferred_batch_qty_map.setdefault(key, OrderedDict())
- transferred_batch_qty_map[key][batch_data.batch_no] = batch_data.qty
-
- return transferred_batch_qty_map
-
-def get_backflushed_batch_qty_map(purchase_order, fg_item):
- # returns
- # {
- # (item_code, fg_code): {
- # batch1: 10, # qty
- # batch2: 16
- # },
- # }
- backflushed_batch_qty_map = {}
- backflushed_batches = frappe.db.sql("""
- SELECT
- pris.batch_no,
- SUM(pris.consumed_qty) AS qty,
- pris.rm_item_code AS item_code
- FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` pris
- WHERE
- pr.name = pri.parent
- AND pri.parent = pris.parent
- AND pri.purchase_order = %s
- AND pri.item_code = pris.main_item_code
- AND pr.docstatus = 1
- AND pris.main_item_code = %s
- AND pris.batch_no IS NOT NULL
- GROUP BY
- pris.rm_item_code, pris.batch_no
- """, (purchase_order, fg_item), as_dict=1)
-
- for batch_data in backflushed_batches:
- backflushed_batch_qty_map.setdefault((batch_data.item_code, fg_item), {})
- backflushed_batch_qty_map[(batch_data.item_code, fg_item)][batch_data.batch_no] = batch_data.qty
-
- return backflushed_batch_qty_map
-
-def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty_map, backflushed_batches, po):
- # Returns available batches to be backflushed based on requirements
- transferred_batches = transferred_batch_qty_map.get((item_code, fg_item), {})
- if not transferred_batches:
- transferred_batches = transferred_batch_qty_map.get((item_code, po), {})
-
- available_batches = []
-
- for (batch, transferred_qty) in transferred_batches.items():
- backflushed_qty = backflushed_batches.get(batch, 0)
- available_qty = transferred_qty - backflushed_qty
-
- if available_qty >= required_qty:
- available_batches.append({'batch': batch, 'qty': required_qty})
- break
- elif available_qty != 0:
- available_batches.append({'batch': batch, 'qty': available_qty})
- required_qty -= available_qty
-
- for row in available_batches:
- if backflushed_batches.get(row.get('batch'), 0) > 0:
- backflushed_batches[row.get('batch')] += row.get('qty')
- else:
- backflushed_batches[row.get('batch')] = row.get('qty')
-
- return available_batches
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
new file mode 100644
index 0000000000..fe775766da
--- /dev/null
+++ b/erpnext/controllers/subcontracting.py
@@ -0,0 +1,342 @@
+from __future__ import unicode_literals
+
+import frappe
+from frappe import _
+from frappe.utils import flt, cint
+from collections import defaultdict
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+
+class Subcontracting(object):
+ def set_materials_for_subcontracted_items(self, raw_material_table):
+ if self.doctype == 'Purchase Invoice' and not self.update_stock:
+ return
+
+ self.raw_material_table = raw_material_table
+ self.identify_change_in_item_table()
+ self.prepare_supplied_items()
+ self.validate_consumed_qty()
+
+ def prepare_supplied_items(self):
+ self.initialized_fields()
+ self.get_purchase_orders()
+ self.get_pending_qty_to_receive()
+ self.get_available_materials()
+ self.remove_changed_rows()
+ self.set_supplied_items()
+
+ def initialized_fields(self):
+ self.available_materials = frappe._dict()
+ self.alternative_item_details = frappe._dict()
+ self.get_backflush_based_on()
+
+ def get_backflush_based_on(self):
+ self.backflush_based_on = frappe.db.get_single_value("Buying Settings",
+ "backflush_raw_materials_of_subcontract_based_on")
+
+ def get_purchase_orders(self):
+ self.purchase_orders = []
+
+ if self.doctype == 'Purchase Order':
+ return
+
+ self.purchase_orders = [d.purchase_order for d in self.items if d.purchase_order]
+
+ def identify_change_in_item_table(self):
+ self.changed_name = []
+
+ if self.doctype == 'Purchase Order' or not self.get(self.raw_material_table):
+ self.set(self.raw_material_table, [])
+ return
+
+ item_dict = self.get_data_before_save()
+ if not item_dict:
+ return True
+
+ for n_row in self.items:
+ if (n_row.name not in item_dict) or (n_row.item_code, n_row.qty) != item_dict[n_row.name]:
+ self.changed_name.append(n_row.name)
+
+ if item_dict.get(n_row.name):
+ del item_dict[n_row.name]
+
+ self.changed_name.extend(item_dict.keys())
+
+ def get_data_before_save(self):
+ item_dict = {}
+ if self.doctype == 'Purchase Receipt' and self._doc_before_save:
+ for row in self._doc_before_save.get('items'):
+ item_dict[row.name] = (row.item_code, row.qty)
+
+ return item_dict
+
+ def get_available_materials(self):
+ ''' Get the available raw materials which has been transferred to the supplier.
+ available_materials = {
+ (item_code, subcontracted_item, purchase_order): {
+ 'qty': 1, 'serial_no': [ABC], 'batch_no': {'batch1': 1}, 'data': item_details
+ }
+ }
+ '''
+ if not self.purchase_orders:
+ return
+
+ for row in self.get_transferred_items():
+ key = (row.rm_item_code, row.main_item_code, row.purchase_order)
+
+ if key not in self.available_materials:
+ self.available_materials.setdefault(key, frappe._dict({'qty': 0, 'serial_no': [],
+ 'batch_no': defaultdict(float), 'item_details': row, 'po_details': []})
+ )
+
+ details = self.available_materials[key]
+ details.qty += row.qty
+ details.po_details.append(row.po_detail)
+
+ if row.serial_no:
+ details.serial_no.extend(get_serial_nos(row.serial_no))
+
+ if row.batch_no:
+ details.batch_no[row.batch_no] += row.qty
+
+ self.set_alternative_item_details(row)
+
+ for doctype in ['Purchase Receipt', 'Purchase Invoice']:
+ self.remove_consumed_materials(doctype)
+
+ def remove_consumed_materials(self, doctype, return_consumed_items=False):
+ '''Deduct the consumed materials from the available materials.'''
+
+ pr_items = self.get_received_items(doctype)
+ if not pr_items:
+ return ([], {}) if return_consumed_items else None
+
+ pr_items = {d.name: d.get(self.get('po_field') or 'purchase_order') for d in pr_items}
+ consumed_materials = self.get_consumed_items(doctype, pr_items.keys())
+
+ if return_consumed_items:
+ return (consumed_materials, pr_items)
+
+ for row in consumed_materials:
+ key = (row.rm_item_code, row.main_item_code, pr_items.get(row.reference_name))
+ if not self.available_materials.get(key):
+ continue
+
+ self.available_materials[key]['qty'] -= row.consumed_qty
+ if row.serial_no:
+ self.available_materials[key]['serial_no'] = list(
+ set(self.available_materials[key]['serial_no']) - set(get_serial_nos(row.serial_no))
+ )
+
+ if row.batch_no:
+ self.available_materials[key]['batch_no'][row.batch_no] -= row.consumed_qty
+
+ def get_transferred_items(self):
+ fields = ['`tabStock Entry`.`purchase_order`']
+ alias_dict = {'item_code': 'rm_item_code', 'subcontracted_item': 'main_item_code', 'basic_rate': 'rate'}
+
+ child_table_fields = ['item_code', 'item_name', 'description', 'qty', 'basic_rate', 'amount',
+ 'serial_no', 'uom', 'subcontracted_item', 'stock_uom', 'batch_no', 'conversion_factor',
+ 's_warehouse', 't_warehouse', 'item_group', 'po_detail']
+
+ if self.backflush_based_on == 'BOM':
+ child_table_fields.append('original_item')
+
+ for field in child_table_fields:
+ fields.append(f'`tabStock Entry Detail`.`{field}` As {alias_dict.get(field, field)}')
+
+ filters = [['Stock Entry', 'docstatus', '=', 1], ['Stock Entry', 'purpose', '=', 'Send to Subcontractor'],
+ ['Stock Entry', 'purchase_order', 'in', self.purchase_orders]]
+
+ return frappe.get_all('Stock Entry', fields = fields, filters=filters)
+
+ def get_received_items(self, doctype):
+ fields = []
+ self.po_field = 'purchase_order' if doctype == 'Purchase Receipt' else 'po_detail'
+
+ for field in ['name', self.po_field, 'parent']:
+ fields.append(f'`tab{doctype} Item`.`{field}`')
+
+ filters = [[doctype, 'docstatus', '=', 1], [f'{doctype} Item', self.po_field, 'in', self.purchase_orders]]
+ if doctype == 'Purchase Invoice':
+ filters.append(['Purchase Invoice', 'update_stock', "=", 1])
+
+ return frappe.get_all(f'{doctype}', fields = fields, filters = filters)
+
+ def get_consumed_items(self, doctype, pr_items):
+ return frappe.get_all(f'{doctype} Item Supplied',
+ fields = ['serial_no', 'rm_item_code', 'reference_name', 'batch_no', 'consumed_qty', 'main_item_code'],
+ filters = {'docstatus': 1, 'reference_name': ('in', list(pr_items))})
+
+ def set_alternative_item_details(self, row):
+ if row.get('original_item'):
+ self.alternative_item_details[row.get('original_item')] = row
+
+ def get_pending_qty_to_receive(self):
+ '''Get qty to be received against the purchase order.'''
+
+ self.qty_to_be_received = defaultdict(float)
+
+ if self.doctype != 'Purchase Order' and self.backflush_based_on != 'BOM' and self.purchase_orders:
+ for row in frappe.get_all('Purchase Order Item',
+ fields = ['item_code', '(qty - received_qty) as qty', 'parent', 'name'],
+ filters = {'docstatus': 1, 'parent': ('in', self.purchase_orders)}):
+
+ self.qty_to_be_received[(row.item_code, row.parent)] += row.qty
+
+ def get_materials_from_bom(self, item_code, bom_no, exploded_item=0):
+ doctype = 'BOM Item' if not exploded_item else 'BOM Explosion Item'
+ fields = [f'`tab{doctype}`.`stock_qty` / `tabBOM`.`quantity` as qty_consumed_per_unit']
+
+ alias_dict = {'item_code': 'rm_item_code', 'name': 'bom_detail_no', 'source_warehouse': 'reserve_warehouse'}
+ for field in ['item_code', 'name', 'rate', 'stock_uom',
+ 'source_warehouse', 'description', 'item_name', 'stock_uom']:
+ fields.append(f'`tab{doctype}`.`{field}` As {alias_dict.get(field, field)}')
+
+ filters = [[doctype, 'parent', '=', bom_no], [doctype, 'docstatus', '=', 1],
+ ['BOM', 'item', '=', item_code], [doctype, 'sourced_by_supplier', '=', 0]]
+
+ return frappe.get_all('BOM', fields = fields, filters=filters, order_by = f'`tab{doctype}`.`idx`') or []
+
+ def remove_changed_rows(self):
+ if not self.changed_name:
+ return
+
+ i=1
+ self.set(self.raw_material_table, [])
+ for d in self._doc_before_save.supplied_items:
+ if d.reference_name in self.changed_name:
+ continue
+
+ d.idx = i
+ self.append('supplied_items', d)
+
+ i += 1
+
+ def set_supplied_items(self):
+ self.bom_items = {}
+
+ has_supplied_items = True if self.get(self.raw_material_table) else False
+ for row in self.items:
+ if (self.doctype != 'Purchase Order' and ((self.changed_name and row.name not in self.changed_name)
+ or (has_supplied_items and not self.changed_name))):
+ continue
+
+ if self.doctype == 'Purchase Order' or self.backflush_based_on == 'BOM':
+ for bom_item in self.get_materials_from_bom(row.item_code, row.bom, row.get('include_exploded_items')):
+ qty = (flt(bom_item.qty_consumed_per_unit) * flt(row.qty) * row.conversion_factor)
+ bom_item.main_item_code = row.item_code
+ self.update_reserve_warehouse(bom_item, row)
+ self.set_alternative_item(bom_item)
+ self.add_supplied_item(row, bom_item, qty)
+
+ elif self.backflush_based_on != 'BOM':
+ for key, transfer_item in self.available_materials.items():
+ if (key[1], key[2]) == (row.item_code, row.purchase_order) and transfer_item.qty > 0:
+ qty = self.get_qty_based_on_material_transfer(row, transfer_item) or 0
+ transfer_item.qty -= qty
+ self.add_supplied_item(row, transfer_item.get('item_details'), qty)
+
+ if self.qty_to_be_received:
+ self.qty_to_be_received[(row.item_code, row.purchase_order)] -= row.qty
+
+ def update_reserve_warehouse(self, row, item):
+ if self.doctype == 'Purchase Order':
+ row.reserve_warehouse = (self.set_reserve_warehouse or item.warehouse)
+
+ def get_qty_based_on_material_transfer(self, item_row, transfer_item):
+ key = (item_row.item_code, item_row.purchase_order)
+
+ if self.qty_to_be_received == item_row.qty:
+ return transfer_item.qty
+
+ if self.qty_to_be_received:
+ qty = (flt(item_row.qty) * flt(transfer_item.qty)) / flt(self.qty_to_be_received.get(key, 0))
+ if (transfer_item.serial_no or frappe.get_cached_value('UOM',
+ transfer_item.item_details.stock_uom, 'must_be_whole_number')):
+ return frappe.utils.ceil(qty)
+
+ return qty
+
+ def set_alternative_item(self, bom_item):
+ if self.alternative_item_details.get(bom_item.rm_item_code):
+ bom_item.update(self.alternative_item_details[bom_item.rm_item_code])
+
+ def add_supplied_item(self, item_row, bom_item, qty):
+ bom_item.conversion_factor = item_row.conversion_factor
+ rm_obj = self.append(self.raw_material_table, bom_item)
+ rm_obj.reference_name = item_row.name
+
+ if self.doctype == 'Purchase Order':
+ rm_obj.required_qty = qty
+ else:
+ self.set_batch_nos(bom_item, item_row, rm_obj, qty)
+
+ def set_batch_nos(self, bom_item, item_row, rm_obj, qty):
+ key = (rm_obj.rm_item_code, item_row.item_code, item_row.purchase_order)
+
+ if (self.available_materials.get(key) and self.available_materials[key]['batch_no']):
+ for batch_no, batch_qty in self.available_materials[key]['batch_no'].items():
+ if batch_qty >= qty:
+ self.set_batch_no_as_per_qty(item_row, rm_obj, batch_no, qty)
+ self.available_materials[key]['batch_no'][batch_no] -= qty
+ return
+
+ elif qty > 0 and batch_qty > 0:
+ qty -= batch_qty
+ new_rm_obj = self.append(self.raw_material_table, bom_item)
+ new_rm_obj.reference_name = item_row.name
+ self.set_batch_no_as_per_qty(item_row, new_rm_obj, batch_no, batch_qty)
+ self.available_materials[key]['batch_no'][batch_no] = 0
+ else:
+ rm_obj.required_qty = qty
+ rm_obj.consumed_qty = qty
+ self.set_serial_nos(item_row, rm_obj)
+
+ def set_batch_no_as_per_qty(self, item_row, rm_obj, batch_no, qty):
+ rm_obj.update({'consumed_qty': qty, 'batch_no': batch_no, 'required_qty': qty})
+ self.set_serial_nos(item_row, rm_obj)
+
+ def set_serial_nos(self, item_row, rm_obj):
+ key = (rm_obj.rm_item_code, item_row.item_code, item_row.purchase_order)
+ if (self.available_materials.get(key) and self.available_materials[key]['serial_no']):
+ used_serial_nos = self.available_materials[key]['serial_no'][0: cint(rm_obj.consumed_qty)]
+ rm_obj.serial_no = '\n'.join(used_serial_nos)
+
+ # Removed the used serial nos from the list
+ for sn in used_serial_nos:
+ self.available_materials[key]['serial_no'].remove(sn)
+
+ def set_consumed_qty_in_po(self):
+ if self.is_subcontracted != 'Yes':
+ return
+
+ self.get_purchase_orders()
+ consumed_items, pr_items = self.remove_consumed_materials(self.doctype, return_consumed_items=True)
+
+ itemwise_consumed_qty = defaultdict(float)
+ for row in consumed_items:
+ key = (row.rm_item_code, row.main_item_code, pr_items.get(row.reference_name))
+ itemwise_consumed_qty[key] += row.consumed_qty
+
+ self.update_consumed_qty_in_po(itemwise_consumed_qty)
+
+ def update_consumed_qty_in_po(self, itemwise_consumed_qty):
+ fields = ['main_item_code', 'rm_item_code', 'parent', 'supplied_qty', 'name']
+ filters = {'docstatus': 1, 'parent': ('in', self.purchase_orders)}
+
+ for row in frappe.get_all('Purchase Order Item Supplied', fields = fields, filters=filters, order_by='idx'):
+ key = (row.rm_item_code, row.main_item_code, row.parent)
+ consumed_qty = itemwise_consumed_qty.get(key, 0)
+
+ if row.supplied_qty < consumed_qty:
+ consumed_qty = row.supplied_qty
+
+ itemwise_consumed_qty[key] -= consumed_qty
+ frappe.db.set_value('Purchase Order Item Supplied', row.name, 'consumed_qty', consumed_qty)
+
+ def validate_consumed_qty(self):
+ for row in self.get(self.raw_material_table):
+ if flt(row.consumed_qty) == 0.0 and row.get('serial_no'):
+ msg = f'Row {row.idx}: the consumed qty cannot be zero for the item {frappe.bold(row.rm_item_code)}'
+
+ frappe.throw(_(msg),title=_('Consumed Items Qty Check'))
\ No newline at end of file
diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py
index e1cca9e3ef..42b23f223d 100644
--- a/erpnext/manufacturing/doctype/bom/test_bom.py
+++ b/erpnext/manufacturing/doctype/bom/test_bom.py
@@ -12,6 +12,7 @@ from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update
from six import string_types
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
+from erpnext.tests.test_subcontracting import set_backflush_based_on
test_records = frappe.get_test_records('BOM')
@@ -160,6 +161,7 @@ class TestBOM(unittest.TestCase):
def test_subcontractor_sourced_item(self):
item_code = "_Test Subcontracted FG Item 1"
+ set_backflush_based_on('Material Transferred for Subcontract')
if not frappe.db.exists('Item', item_code):
make_item(item_code, {
diff --git a/erpnext/stock/doctype/bin/bin.py b/erpnext/stock/doctype/bin/bin.py
index 0514bd2394..43642013ce 100644
--- a/erpnext/stock/doctype/bin/bin.py
+++ b/erpnext/stock/doctype/bin/bin.py
@@ -54,7 +54,7 @@ class Bin(Document):
self.reserved_qty = flt(self.reserved_qty) + flt(args.get("reserved_qty"))
self.indented_qty = flt(self.indented_qty) + flt(args.get("indented_qty"))
self.planned_qty = flt(self.planned_qty) + flt(args.get("planned_qty"))
-
+
self.set_projected_qty()
self.db_update()
@@ -115,7 +115,7 @@ class Bin(Document):
#Get Transferred Entries
materials_transferred = frappe.db.sql("""
select
- ifnull(sum(transfer_qty),0)
+ ifnull(sum(CASE WHEN se.is_return = 1 THEN (transfer_qty * -1) ELSE transfer_qty END),0)
from
`tabStock Entry` se, `tabStock Entry Detail` sed, `tabPurchase Order` po
where
diff --git a/erpnext/stock/doctype/item_alternative/test_item_alternative.py b/erpnext/stock/doctype/item_alternative/test_item_alternative.py
index d5700fe514..8f76844bde 100644
--- a/erpnext/stock/doctype/item_alternative/test_item_alternative.py
+++ b/erpnext/stock/doctype/item_alternative/test_item_alternative.py
@@ -18,6 +18,9 @@ class TestItemAlternative(unittest.TestCase):
make_items()
def test_alternative_item_for_subcontract_rm(self):
+ frappe.db.set_value('Buying Settings', None,
+ 'backflush_raw_materials_of_subcontract_based_on', 'BOM')
+
create_stock_reconciliation(item_code='Alternate Item For A RW 1', warehouse='_Test Warehouse - _TC',
qty=5, rate=2000)
create_stock_reconciliation(item_code='Test FG A RW 2', warehouse='_Test Warehouse - _TC',
@@ -65,6 +68,8 @@ class TestItemAlternative(unittest.TestCase):
status = True
self.assertEqual(status, True)
+ frappe.db.set_value('Buying Settings', None,
+ 'backflush_raw_materials_of_subcontract_based_on', 'Material Transferred for Subcontract')
def test_alternative_item_for_production_rm(self):
create_stock_reconciliation(item_code='Alternate Item For A RW 1',
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 0182ed55a1..692f3a6e57 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -41,6 +41,8 @@ frappe.ui.form.on("Purchase Receipt", {
}
});
+ frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
+
},
onload: function(frm) {
erpnext.queries.setup_queries(frm, "Warehouse", function() {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
index ad350d344f..44fb736304 100755
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
@@ -514,8 +514,7 @@
"oldfieldname": "pr_raw_material_details",
"oldfieldtype": "Table",
"options": "Purchase Receipt Item Supplied",
- "print_hide": 1,
- "read_only": 1
+ "print_hide": 1
},
{
"fieldname": "section_break0",
@@ -1149,7 +1148,7 @@
"idx": 261,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-19 01:01:00.754119",
+ "modified": "2021-05-25 00:15:12.239017",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 83ba324495..b8580f95a3 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -202,6 +202,7 @@ class PurchaseReceipt(BuyingController):
self.make_gl_entries()
self.repost_future_sle_and_gle()
+ self.set_consumed_qty_in_po()
def check_next_docstatus(self):
submit_rv = frappe.db.sql("""select t1.name
@@ -233,6 +234,7 @@ class PurchaseReceipt(BuyingController):
self.repost_future_sle_and_gle()
self.ignore_linked_doctypes = ('GL Entry', 'Stock Ledger Entry', 'Repost Item Valuation')
self.delete_auto_created_batches()
+ self.set_consumed_qty_in_po()
@frappe.whitelist()
def get_current_stock(self):
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index 8d9b675bed..95096d77d7 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -335,6 +335,10 @@ class TestPurchaseReceipt(unittest.TestCase):
se2.cancel()
se3.cancel()
po.reload()
+ pr2.load_from_db()
+ pr2.cancel()
+
+ po.load_from_db()
po.cancel()
def test_serial_no_supplier(self):
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index b6ae564408..908020d02b 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1079,6 +1079,10 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => {
}
function attach_bom_items(bom_no) {
+ if (!bom_no) {
+ return
+ }
+
if (check_should_not_attach_bom_items(bom_no)) return
frappe.db.get_doc("BOM",bom_no).then(bom => {
const {name, items} = bom
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json
index a0b5457dd7..523d332b8f 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.json
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.json
@@ -74,7 +74,8 @@
"total_amount",
"job_card",
"amended_from",
- "credit_note"
+ "credit_note",
+ "is_return"
],
"fields": [
{
@@ -611,6 +612,16 @@
"fieldname": "apply_putaway_rule",
"fieldtype": "Check",
"label": "Apply Putaway Rule"
+ },
+ {
+ "default": "0",
+ "fieldname": "is_return",
+ "fieldtype": "Check",
+ "hidden": 1,
+ "label": "Is Return",
+ "no_copy": 1,
+ "print_hide": 1,
+ "read_only": 1
}
],
"icon": "fa fa-file-text",
@@ -618,7 +629,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-05-24 11:32:23.904307",
+ "modified": "2021-05-26 17:07:58.015737",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry",
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 560ceaa917..213280870a 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -97,8 +97,7 @@ class StockEntry(StockController):
update_serial_nos_after_submit(self, "items")
self.update_work_order()
self.validate_purchase_order()
- if self.purchase_order and self.purpose == "Send to Subcontractor":
- self.update_purchase_order_supplied_items()
+ self.update_purchase_order_supplied_items()
self.make_gl_entries()
@@ -117,9 +116,7 @@ class StockEntry(StockController):
self.set_material_request_transfer_status('Completed')
def on_cancel(self):
-
- if self.purchase_order and self.purpose == "Send to Subcontractor":
- self.update_purchase_order_supplied_items()
+ self.update_purchase_order_supplied_items()
if self.work_order and self.purpose == "Material Consumption for Manufacture":
self.validate_work_order_status()
@@ -1347,7 +1344,7 @@ class StockEntry(StockController):
se_child.is_scrap_item = item_dict[d].get("is_scrap_item", 0)
for field in ["idx", "po_detail", "original_item",
- "expense_account", "description", "item_name"]:
+ "expense_account", "description", "item_name", "serial_no", "batch_no"]:
if item_dict[d].get(field):
se_child.set(field, item_dict[d].get(field))
@@ -1400,33 +1397,26 @@ class StockEntry(StockController):
.format(item.batch_no, item.item_code))
def update_purchase_order_supplied_items(self):
- #Get PO Supplied Items Details
- item_wh = frappe._dict(frappe.db.sql("""
- select rm_item_code, reserve_warehouse
- from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
- where po.name = poitemsup.parent
- and po.name = %s""", self.purchase_order))
+ if (self.purchase_order and
+ (self.purpose in ['Send to Subcontractor', 'Material Transfer'] or self.is_return)):
- #Update Supplied Qty in PO Supplied Items
+ #Get PO Supplied Items Details
+ item_wh = frappe._dict(frappe.db.sql("""
+ select rm_item_code, reserve_warehouse
+ from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
+ where po.name = poitemsup.parent
+ and po.name = %s""", self.purchase_order))
- frappe.db.sql("""UPDATE `tabPurchase Order Item Supplied` pos
- SET
- pos.supplied_qty = IFNULL((SELECT ifnull(sum(transfer_qty), 0)
- FROM
- `tabStock Entry Detail` sed, `tabStock Entry` se
- WHERE
- pos.name = sed.po_detail AND pos.rm_item_code = sed.item_code
- AND pos.parent = se.purchase_order AND sed.docstatus = 1
- AND se.name = sed.parent and se.purchase_order = %(po)s
- ), 0)
- WHERE pos.docstatus = 1 and pos.parent = %(po)s""", {"po": self.purchase_order})
+ supplied_items = get_supplied_items(self.purchase_order)
+ for name, item in supplied_items.items():
+ frappe.db.set_value('Purchase Order Item Supplied', name, item)
- #Update reserved sub contracted quantity in bin based on Supplied Item Details and
- for d in self.get("items"):
- item_code = d.get('original_item') or d.get('item_code')
- reserve_warehouse = item_wh.get(item_code)
- stock_bin = get_bin(item_code, reserve_warehouse)
- stock_bin.update_reserved_qty_for_sub_contracting()
+ #Update reserved sub contracted quantity in bin based on Supplied Item Details and
+ for d in self.get("items"):
+ item_code = d.get('original_item') or d.get('item_code')
+ reserve_warehouse = item_wh.get(item_code)
+ stock_bin = get_bin(item_code, reserve_warehouse)
+ stock_bin.update_reserved_qty_for_sub_contracting()
def update_so_in_serial_number(self):
so_name, item_code = frappe.db.get_value("Work Order", self.work_order, ["sales_order", "production_item"])
@@ -1480,7 +1470,7 @@ class StockEntry(StockController):
cond += """ WHEN (parent = %s and name = %s) THEN %s
""" %(frappe.db.escape(data[0]), frappe.db.escape(data[1]), transferred_qty)
- if cond and stock_entries_child_list:
+ if stock_entries_child_list:
frappe.db.sql(""" UPDATE `tabStock Entry Detail`
SET
transferred_qty = CASE {cond} END
@@ -1751,3 +1741,30 @@ def validate_sample_quantity(item_code, sample_quantity, qty, batch_no = None):
format(max_retain_qty, batch_no, item_code), alert=True)
sample_quantity = qty_diff
return sample_quantity
+
+def get_supplied_items(purchase_order):
+ fields = ['`tabStock Entry Detail`.`transfer_qty`', '`tabStock Entry`.`is_return`',
+ '`tabStock Entry Detail`.`po_detail`', '`tabStock Entry Detail`.`item_code`']
+
+ filters = [['Stock Entry', 'docstatus', '=', 1], ['Stock Entry', 'purchase_order', '=', purchase_order]]
+
+ supplied_item_details = {}
+ for row in frappe.get_all('Stock Entry', fields = fields, filters = filters):
+ if not row.po_detail:
+ continue
+
+ key = row.po_detail
+ if key not in supplied_item_details:
+ supplied_item_details.setdefault(key,
+ frappe._dict({'supplied_qty': 0, 'returned_qty':0, 'total_supplied_qty':0}))
+
+ supplied_item = supplied_item_details[key]
+
+ if row.is_return:
+ supplied_item.returned_qty += row.transfer_qty
+ else:
+ supplied_item.supplied_qty += row.transfer_qty
+
+ supplied_item.total_supplied_qty = flt(supplied_item.supplied_qty) - flt(supplied_item.returned_qty)
+
+ return supplied_item_details
\ No newline at end of file
diff --git a/erpnext/tests/test_subcontracting.py b/erpnext/tests/test_subcontracting.py
new file mode 100644
index 0000000000..c1a458a6dd
--- /dev/null
+++ b/erpnext/tests/test_subcontracting.py
@@ -0,0 +1,583 @@
+from __future__ import unicode_literals
+import frappe
+import unittest
+import copy
+from frappe.utils import cint
+from collections import defaultdict
+from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
+from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
+from erpnext.stock.doctype.item.test_item import make_item
+from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
+from erpnext.buying.doctype.purchase_order.purchase_order import (make_rm_stock_entry,
+ make_purchase_receipt, get_materials_from_supplier)
+
+class TestSubcontracting(unittest.TestCase):
+ def setUp(self):
+ make_subcontract_items()
+ make_raw_materials()
+ make_bom_for_subcontracted_items()
+
+ def test_po_with_bom(self):
+ '''
+ - Set backflush based on BOM
+ - Create subcontracted PO for the item Subcontracted Item SA1 and add same item two times.
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Create purchase receipt against the PO and check serial nos and batch no.
+ '''
+
+ set_backflush_based_on('BOM')
+ item_code = 'Subcontracted Item SA1'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 5, 'rate': 100},
+ {'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 6, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 5},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 5},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 5},
+ {'item_code': 'Subcontracted SRM Item 1', 'qty': 6},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 6},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 6}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name if d.get('qty') == 5 else po.items[1].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ transferred_detais = itemwise_details.get(key)
+
+ for field in ['qty', 'serial_no', 'batch_no']:
+ if value.get(field):
+ transfer, consumed = (transferred_detais.get(field), value.get(field))
+ if field == 'serial_no':
+ transfer, consumed = (sorted(transfer), sorted(consumed))
+
+ self.assertEqual(transfer, consumed)
+
+ def test_po_with_material_transfer(self):
+ '''
+ - Set backflush based on Material Transfer
+ - Create subcontracted PO for the item Subcontracted Item SA1 and Subcontracted Item SA5.
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Transfer extra item Subcontracted SRM Item 4 for the subcontract item Subcontracted Item SA5.
+ - Create partial purchase receipt against the PO and check serial nos and batch no.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': 'Subcontracted Item SA1', 'qty': 5, 'rate': 100},
+ {'warehouse': '_Test Warehouse - _TC', 'item_code': 'Subcontracted Item SA5', 'qty': 6, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 5, 'main_item_code': 'Subcontracted Item SA1'},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 5, 'main_item_code': 'Subcontracted Item SA1'},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 5, 'main_item_code': 'Subcontracted Item SA1'},
+ {'item_code': 'Subcontracted SRM Item 5', 'qty': 6, 'main_item_code': 'Subcontracted Item SA5'},
+ {'item_code': 'Subcontracted SRM Item 4', 'qty': 6, 'main_item_code': 'Subcontracted Item SA5'}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name if d.get('qty') == 5 else po.items[1].name
+
+ make_stock_transfer_entry(po_no = po.name,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.remove(pr1.items[1])
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ transferred_detais = itemwise_details.get(key)
+
+ for field in ['qty', 'serial_no', 'batch_no']:
+ if value.get(field):
+ self.assertEqual(value.get(field), transferred_detais.get(field))
+
+ pr2 = make_purchase_receipt(po.name)
+ pr2.submit()
+
+ for key, value in get_supplied_items(pr2).items():
+ transferred_detais = itemwise_details.get(key)
+
+ for field in ['qty', 'serial_no', 'batch_no']:
+ if value.get(field):
+ self.assertEqual(value.get(field), transferred_detais.get(field))
+
+ def test_subcontract_with_same_components_different_fg(self):
+ '''
+ - Set backflush based on Material Transfer
+ - Create subcontracted PO for the item Subcontracted Item SA2 and Subcontracted Item SA3.
+ - Transfer the components from Stores to Supplier warehouse with serial nos.
+ - Transfer extra qty of components for the item Subcontracted Item SA2.
+ - Create partial purchase receipt against the PO and check serial nos and batch no.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': 'Subcontracted Item SA2', 'qty': 5, 'rate': 100},
+ {'warehouse': '_Test Warehouse - _TC', 'item_code': 'Subcontracted Item SA3', 'qty': 6, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 2', 'qty': 6, 'main_item_code': 'Subcontracted Item SA2'},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 6, 'main_item_code': 'Subcontracted Item SA3'}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name if d.get('qty') == 5 else po.items[1].name
+
+ make_stock_transfer_entry(po_no = po.name,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 3
+ pr1.remove(pr1.items[1])
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ transferred_detais = itemwise_details.get(key)
+ self.assertEqual(value.qty, 4)
+ self.assertEqual(sorted(value.serial_no), sorted(transferred_detais.get('serial_no')[0:4]))
+
+ pr2 = make_purchase_receipt(po.name)
+ pr2.items[0].qty = 2
+ pr2.remove(pr2.items[1])
+ pr2.submit()
+
+ for key, value in get_supplied_items(pr2).items():
+ transferred_detais = itemwise_details.get(key)
+
+ self.assertEqual(value.qty, 2)
+ self.assertEqual(sorted(value.serial_no), sorted(transferred_detais.get('serial_no')[4:6]))
+
+ pr3 = make_purchase_receipt(po.name)
+ pr3.submit()
+ for key, value in get_supplied_items(pr3).items():
+ transferred_detais = itemwise_details.get(key)
+
+ self.assertEqual(value.qty, 6)
+ self.assertEqual(sorted(value.serial_no), sorted(transferred_detais.get('serial_no')[6:12]))
+
+ def test_return_non_consumed_materials(self):
+ '''
+ - Set backflush based on Material Transfer
+ - Create subcontracted PO for the item Subcontracted Item SA2.
+ - Transfer the components from Stores to Supplier warehouse with serial nos.
+ - Transfer extra qty of component for the subcontracted item Subcontracted Item SA2.
+ - Create purchase receipt for full qty against the PO and change the qty of raw material.
+ - After that return the non consumed material back to the store from supplier's warehouse.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': 'Subcontracted Item SA2', 'qty': 5, 'rate': 100}]
+ rm_items = [{'item_code': 'Subcontracted SRM Item 2', 'qty': 6, 'main_item_code': 'Subcontracted Item SA2'}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.save()
+ pr1.supplied_items[0].consumed_qty = 5
+ pr1.supplied_items[0].serial_no = '\n'.join(sorted(
+ itemwise_details.get('Subcontracted SRM Item 2').get('serial_no')[0:5]
+ ))
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ transferred_detais = itemwise_details.get(key)
+ self.assertEqual(value.qty, 5)
+ self.assertEqual(sorted(value.serial_no), sorted(transferred_detais.get('serial_no')[0:5]))
+
+ po.load_from_db()
+ self.assertEqual(po.supplied_items[0].consumed_qty, 5)
+ doc = get_materials_from_supplier(po.name, [d.name for d in po.supplied_items])
+ self.assertEqual(doc.items[0].qty, 1)
+ self.assertEqual(doc.items[0].s_warehouse, '_Test Warehouse 1 - _TC')
+ self.assertEqual(doc.items[0].t_warehouse, '_Test Warehouse - _TC')
+ self.assertEqual(get_serial_nos(doc.items[0].serial_no),
+ itemwise_details.get(doc.items[0].item_code)['serial_no'][5:6])
+
+ def test_item_with_batch_based_on_bom(self):
+ '''
+ - Set backflush based on BOM
+ - Create subcontracted PO for the item Subcontracted Item SA4 (has batch no).
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Transfer the components in multiple batches.
+ - Create the 3 purchase receipt against the PO and split Subcontracted Items into two batches.
+ - Keep the qty as 2 for Subcontracted Item in the purchase receipt.
+ '''
+
+ set_backflush_based_on('BOM')
+ item_code = 'Subcontracted Item SA4'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 1}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 2
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 2
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 2
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 2)
+
+ def test_item_with_batch_based_on_material_transfer(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA4 (has batch no).
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Transfer the components in multiple batches with extra 2 qty for the batched item.
+ - Create the 3 purchase receipt against the PO and split Subcontracted Items into two batches.
+ - Keep the qty as 2 for Subcontracted Item in the purchase receipt.
+ - In the first purchase receipt the batched raw materials will be consumed 2 extra qty.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA4'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 2
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ qty = 4 if key != 'Subcontracted SRM Item 3' else 6
+ self.assertEqual(value.qty, qty)
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 2
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 2
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 2)
+
+ def test_partial_transfer_serial_no_components_based_on_material_transfer(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA2.
+ - Transfer the partial components from Stores to Supplier warehouse with serial nos.
+ - Create partial purchase receipt against the PO and change the qty manually.
+ - Transfer the remaining components from Stores to Supplier warehouse with serial nos.
+ - Create purchase receipt for remaining qty against the PO and change the qty manually.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA2'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 2', 'qty': 5}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 5
+ pr1.save()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, 3)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no[0:3]))
+
+ pr1.load_from_db()
+ pr1.supplied_items[0].consumed_qty = 5
+ pr1.supplied_items[0].serial_no = '\n'.join(itemwise_details[pr1.supplied_items[0].rm_item_code]['serial_no'])
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no))
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no))
+
+ def test_partial_transfer_batch_based_on_material_transfer(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA6.
+ - Transfer the partial components from Stores to Supplier warehouse with batch.
+ - Create partial purchase receipt against the PO and change the qty manually.
+ - Transfer the remaining components from Stores to Supplier warehouse with batch.
+ - Create purchase receipt for remaining qty against the PO and change the qty manually.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA6'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 3', 'qty': 5}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.items[0].qty = 5
+ pr1.save()
+
+ transferred_batch_no = ''
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, 3)
+ transferred_batch_no = details.batch_no
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ pr1.load_from_db()
+ pr1.supplied_items[0].consumed_qty = 5
+ pr1.supplied_items[0].batch_no = list(transferred_batch_no.keys())[0]
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(value.batch_no, details.batch_no)
+
+def add_second_row_in_pr(pr):
+ item_dict = {}
+ for column in ['item_code', 'item_name', 'qty', 'uom', 'warehouse', 'stock_uom',
+ 'purchase_order', 'purchase_order_item', 'conversion_factor', 'rate']:
+ item_dict[column] = pr.items[0].get(column)
+
+ pr.append('items', item_dict)
+ pr.set_missing_values()
+
+def get_supplied_items(pr_doc):
+ supplied_items = {}
+ for row in pr_doc.get('supplied_items'):
+ if row.rm_item_code not in supplied_items:
+ supplied_items.setdefault(row.rm_item_code,
+ frappe._dict({'qty': 0, 'serial_no': [], 'batch_no': defaultdict(float)}))
+
+ details = supplied_items[row.rm_item_code]
+ update_item_details(row, details)
+
+ return supplied_items
+
+def make_stock_in_entry(**args):
+ args = frappe._dict(args)
+
+ items = {}
+ for row in args.rm_items:
+ row = frappe._dict(row)
+
+ doc = make_stock_entry(target=row.warehouse or '_Test Warehouse - _TC',
+ item_code=row.item_code, qty=row.qty or 1, basic_rate=row.rate or 100)
+
+ if row.item_code not in items:
+ items.setdefault(row.item_code, frappe._dict({'qty': 0, 'serial_no': [], 'batch_no': defaultdict(float)}))
+
+ child_row = doc.items[0]
+ details = items[child_row.item_code]
+ update_item_details(child_row, details)
+
+ return items
+
+def update_item_details(child_row, details):
+ details.qty += (child_row.get('qty') if child_row.doctype == 'Stock Entry Detail'
+ else child_row.get('consumed_qty'))
+
+ if child_row.serial_no:
+ details.serial_no.extend(get_serial_nos(child_row.serial_no))
+
+ if child_row.batch_no:
+ details.batch_no[child_row.batch_no] += (child_row.get('qty') or child_row.get('consumed_qty'))
+
+def make_stock_transfer_entry(**args):
+ args = frappe._dict(args)
+
+ items = []
+ for row in args.rm_items:
+ row = frappe._dict(row)
+
+ item = {'item_code': row.main_item_code or args.main_item_code, 'rm_item_code': row.item_code,
+ 'qty': row.qty or 1, 'item_name': row.item_code, 'rate': row.rate or 100,
+ 'stock_uom': row.stock_uom or 'Nos', 'warehouse': row.warehuose or '_Test Warehouse - _TC'}
+
+ item_details = args.itemwise_details.get(row.item_code)
+
+ if item_details and item_details.serial_no:
+ serial_nos = item_details.serial_no[0:cint(row.qty)]
+ item['serial_no'] = '\n'.join(serial_nos)
+ item_details.serial_no = list(set(item_details.serial_no) - set(serial_nos))
+
+ if item_details and item_details.batch_no:
+ for batch_no, batch_qty in item_details.batch_no.items():
+ if batch_qty >= row.qty:
+ item['batch_no'] = batch_no
+ item_details.batch_no[batch_no] -= row.qty
+ break
+
+ items.append(item)
+
+ ste_dict = make_rm_stock_entry(args.po_no, items)
+ doc = frappe.get_doc(ste_dict)
+ doc.insert()
+ doc.submit()
+
+ return doc
+
+def make_subcontract_items():
+ sub_contracted_items = {'Subcontracted Item SA1': {}, 'Subcontracted Item SA2': {}, 'Subcontracted Item SA3': {},
+ 'Subcontracted Item SA4': {'has_batch_no': 1, 'create_new_batch': 1, 'batch_number_series': 'SBAT.####'},
+ 'Subcontracted Item SA5': {}, 'Subcontracted Item SA6': {}}
+
+ for item, properties in sub_contracted_items.items():
+ if not frappe.db.exists('Item', item):
+ properties.update({'is_stock_item': 1, 'is_sub_contracted_item': 1})
+ make_item(item, properties)
+
+def make_raw_materials():
+ raw_materials = {'Subcontracted SRM Item 1': {},
+ 'Subcontracted SRM Item 2': {'has_serial_no': 1, 'serial_no_series': 'SRI.####'},
+ 'Subcontracted SRM Item 3': {'has_batch_no': 1, 'create_new_batch': 1, 'batch_number_series': 'BAT.####'},
+ 'Subcontracted SRM Item 4': {'has_serial_no': 1, 'serial_no_series': 'SRII.####'},
+ 'Subcontracted SRM Item 5': {'has_serial_no': 1, 'serial_no_series': 'SRII.####'}}
+
+ for item, properties in raw_materials.items():
+ if not frappe.db.exists('Item', item):
+ properties.update({'is_stock_item': 1})
+ make_item(item, properties)
+
+def make_bom_for_subcontracted_items():
+ boms = {
+ 'Subcontracted Item SA1': ['Subcontracted SRM Item 1', 'Subcontracted SRM Item 2', 'Subcontracted SRM Item 3'],
+ 'Subcontracted Item SA2': ['Subcontracted SRM Item 2'],
+ 'Subcontracted Item SA3': ['Subcontracted SRM Item 2'],
+ 'Subcontracted Item SA4': ['Subcontracted SRM Item 1', 'Subcontracted SRM Item 2', 'Subcontracted SRM Item 3'],
+ 'Subcontracted Item SA5': ['Subcontracted SRM Item 5'],
+ 'Subcontracted Item SA6': ['Subcontracted SRM Item 3']
+ }
+
+ for item_code, raw_materials in boms.items():
+ if not frappe.db.exists('BOM', {'item': item_code}):
+ make_bom(item=item_code, raw_materials=raw_materials, rate=100)
+
+def set_backflush_based_on(based_on):
+ frappe.db.set_value('Buying Settings', None,
+ 'backflush_raw_materials_of_subcontract_based_on', based_on)
\ No newline at end of file
From 21b58ef045cc60f3ad8d321308d7095ab8b4d7b4 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Tue, 1 Jun 2021 11:24:01 +0530
Subject: [PATCH 249/262] fix: semgrep error
---
.../subcontract_order_summary.py | 28 ++++++++-----------
erpnext/controllers/subcontracting.py | 6 ++--
.../stock/doctype/stock_entry/stock_entry.py | 3 +-
3 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
index 8b08d2a284..0b14e119ab 100644
--- a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
@@ -104,26 +104,26 @@ def get_columns():
"fieldname": "item_code",
"fieldtype": "Link",
"options": "Item",
- "width": 140
+ "width": 160
},
{
- "label": _("Qty"),
+ "label": _("Order Qty"),
"fieldname": "qty",
"fieldtype": "Float",
- "width": 70
+ "width": 90
},
{
- "label": _("Received"),
+ "label": _("Received Qty"),
"fieldname": "received_qty",
"fieldtype": "Float",
- "width": 80
+ "width": 110
},
{
"label": _("Supplied Item"),
"fieldname": "rm_item_code",
"fieldtype": "Link",
"options": "Item",
- "width": 140
+ "width": 160
},
{
"label": _("Required Qty"),
@@ -138,21 +138,15 @@ def get_columns():
"width": 110
},
{
- "label": _("Returned Qty"),
- "fieldname": "returned_qty",
- "fieldtype": "Float",
- "width": 110
- },
- {
- "label": _("Total Supplied"),
- "fieldname": "total_supplied_qty",
+ "label": _("Consumed Qty"),
+ "fieldname": "consumed_qty",
"fieldtype": "Float",
"width": 120
},
{
- "label": _("Consumed Qty"),
- "fieldname": "consumed_qty",
+ "label": _("Returned Qty"),
+ "fieldname": "returned_qty",
"fieldtype": "Float",
"width": 110
- },
+ }
]
\ No newline at end of file
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
index fe775766da..a9a38bd02d 100644
--- a/erpnext/controllers/subcontracting.py
+++ b/erpnext/controllers/subcontracting.py
@@ -101,9 +101,9 @@ class Subcontracting(object):
self.set_alternative_item_details(row)
for doctype in ['Purchase Receipt', 'Purchase Invoice']:
- self.remove_consumed_materials(doctype)
+ self.update_consumed_materials(doctype)
- def remove_consumed_materials(self, doctype, return_consumed_items=False):
+ def update_consumed_materials(self, doctype, return_consumed_items=False):
'''Deduct the consumed materials from the available materials.'''
pr_items = self.get_received_items(doctype)
@@ -311,7 +311,7 @@ class Subcontracting(object):
return
self.get_purchase_orders()
- consumed_items, pr_items = self.remove_consumed_materials(self.doctype, return_consumed_items=True)
+ consumed_items, pr_items = self.update_consumed_materials(self.doctype, return_consumed_items=True)
itemwise_consumed_qty = defaultdict(float)
for row in consumed_items:
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 213280870a..0009926f5d 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -1291,7 +1291,8 @@ class StockEntry(StockController):
item_dict[item]["qty"] = 0
# delete items with 0 qty
- for item in item_dict.keys():
+ list_of_items = item_dict.keys()
+ for item in list_of_items:
if not item_dict[item]["qty"]:
del item_dict[item]
From d755b2994396d87357ae1d2ff39c25dcdb85e4b6 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Mon, 7 Jun 2021 21:20:33 +0530
Subject: [PATCH 250/262] fix: toggle consumed qty field based on condition
---
.../doctype/purchase_receipt/purchase_receipt.js | 11 +++++++++--
.../doctype/purchase_receipt/purchase_receipt.py | 5 +++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 692f3a6e57..4f756170f6 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -41,8 +41,6 @@ frappe.ui.form.on("Purchase Receipt", {
}
});
- frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
-
},
onload: function(frm) {
erpnext.queries.setup_queries(frm, "Warehouse", function() {
@@ -77,6 +75,15 @@ frappe.ui.form.on("Purchase Receipt", {
}
frm.events.add_custom_buttons(frm);
+ frm.trigger('toggle_subcontracting_fields');
+ },
+
+ toggle_subcontracting_fields: function(frm) {
+ frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty',
+ 'read_only', frm.doc.__onload && frm.doc.__onload.backflush_based_on === 'BOM');
+
+ frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
+ frm.set_df_property('supplied_items', 'cannot_delete_rows', 1);
},
add_custom_buttons: function(frm) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index b8580f95a3..264561f376 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -102,6 +102,11 @@ class PurchaseReceipt(BuyingController):
if self.get("items") and self.apply_putaway_rule and not self.get("is_return"):
apply_putaway_rule(self.doctype, self.get("items"), self.company)
+ def onload(self):
+ super(PurchaseReceipt, self).onload()
+ self.set_onload("backflush_based_on", frappe.db.get_single_value('Buying Settings',
+ 'backflush_raw_materials_of_subcontract_based_on'))
+
def validate(self):
self.validate_posting_time()
super(PurchaseReceipt, self).validate()
From 6bbc8ec3e8ba06faca44f8d4da4bdc8aa7641e04 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Tue, 8 Jun 2021 10:36:39 +0530
Subject: [PATCH 251/262] fix: code cleanup and convert public method to
private for subcontracting class
---
.../doctype/purchase_order/purchase_order.js | 5 +-
.../doctype/purchase_order/purchase_order.py | 13 ++-
.../purchase_order_item_supplied.json | 6 +-
.../subcontract_order_summary.py | 2 +-
erpnext/controllers/subcontracting.py | 106 +++++++++---------
erpnext/public/js/controllers/transaction.js | 4 +
.../stock/doctype/stock_entry/stock_entry.py | 10 +-
7 files changed, 76 insertions(+), 70 deletions(-)
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 88799f309c..521432d296 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -74,6 +74,7 @@ frappe.ui.form.on("Purchase Order", {
frm.add_custom_button(__('Return of Components'), () => {
frm.call({
method: 'erpnext.buying.doctype.purchase_order.purchase_order.get_materials_from_supplier',
+ freeze: true,
freeze_message: __('Creating Stock Entry'),
args: { purchase_order: frm.doc.name, po_details: po_details },
callback: function(r) {
@@ -545,14 +546,14 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e
],
primary_action: function() {
var data = d.get_values();
- var content_msg = 'Reason for hold: ' + data.reason_for_hold;
+ let reason_for_hold = 'Reason for hold: ' + data.reason_for_hold;
frappe.call({
method: "frappe.desk.form.utils.add_comment",
args: {
reference_doctype: me.frm.doctype,
reference_name: me.frm.docname,
- content: __(content_msg),
+ content: __(reason_for_hold),
comment_email: frappe.session.user,
comment_by: frappe.session.user_fullname
},
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 724f863e0f..eaa502ff7f 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -14,12 +14,11 @@ from frappe.desk.notifications import clear_doctype_notifications
from erpnext.buying.utils import validate_for_items, check_on_hold_or_closed_status
from erpnext.stock.utils import get_bin
from erpnext.accounts.party import get_party_account_currency
-from six import string_types
from erpnext.stock.doctype.item.item import get_item_defaults
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details
-from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\
- unlink_inter_company_doc
+from erpnext.accounts.doctype.sales_invoice.sales_invoice import (validate_inter_company_party,
+ update_linked_doc, unlink_inter_company_doc)
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -504,7 +503,8 @@ def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions
@frappe.whitelist()
def make_rm_stock_entry(purchase_order, rm_items):
rm_items_list = rm_items
- if isinstance(rm_items, string_types):
+
+ if isinstance(rm_items, str):
rm_items_list = json.loads(rm_items)
elif not rm_items:
frappe.throw(_("No Items available for transfer"))
@@ -588,7 +588,7 @@ def make_inter_company_sales_order(source_name, target_doc=None):
@frappe.whitelist()
def get_materials_from_supplier(purchase_order, po_details):
- if isinstance(po_details, string_types):
+ if isinstance(po_details, str):
po_details = json.loads(po_details)
doc = frappe.get_cached_doc('Purchase Order', purchase_order)
@@ -615,7 +615,8 @@ def make_return_stock_entry_for_subcontract(available_materials, po_doc, po_deta
if value.batch_no:
for batch_no, qty in value.batch_no.items():
- add_items_in_ste(ste_doc, value, value.qty, po_details, batch_no)
+ if qty > 0:
+ add_items_in_ste(ste_doc, value, value.qty, po_details, batch_no)
else:
add_items_in_ste(ste_doc, value, value.qty, po_details)
diff --git a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
index 505ecd84c5..60247bd90b 100644
--- a/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
+++ b/erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
@@ -22,9 +22,9 @@
"required_qty",
"supplied_qty",
"col_break1",
+ "consumed_qty",
"returned_qty",
- "total_supplied_qty",
- "consumed_qty"
+ "total_supplied_qty"
],
"fields": [
{
@@ -183,7 +183,7 @@
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2021-06-01 00:41:54.123436",
+ "modified": "2021-06-09 15:17:58.128242",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item Supplied",
diff --git a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
index 0b14e119ab..0c0d4f0531 100644
--- a/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
+++ b/erpnext/buying/report/subcontract_order_summary/subcontract_order_summary.py
@@ -87,7 +87,7 @@ def get_subcontracted_data(po_details, data):
def get_columns():
return [
{
- "label": _("Id"),
+ "label": _("Purchase Order"),
"fieldname": "po_id",
"fieldtype": "Link",
"options": "Purchase Order",
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
index a9a38bd02d..e81c0f5732 100644
--- a/erpnext/controllers/subcontracting.py
+++ b/erpnext/controllers/subcontracting.py
@@ -1,39 +1,37 @@
-from __future__ import unicode_literals
-
import frappe
from frappe import _
from frappe.utils import flt, cint
from collections import defaultdict
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
-class Subcontracting(object):
+class Subcontracting():
def set_materials_for_subcontracted_items(self, raw_material_table):
if self.doctype == 'Purchase Invoice' and not self.update_stock:
return
self.raw_material_table = raw_material_table
- self.identify_change_in_item_table()
- self.prepare_supplied_items()
- self.validate_consumed_qty()
+ self.__identify_change_in_item_table()
+ self.__prepare_supplied_items()
+ self.__validate_consumed_qty()
- def prepare_supplied_items(self):
+ def __prepare_supplied_items(self):
self.initialized_fields()
- self.get_purchase_orders()
- self.get_pending_qty_to_receive()
+ self.__get_purchase_orders()
+ self.__get_pending_qty_to_receive()
self.get_available_materials()
- self.remove_changed_rows()
- self.set_supplied_items()
+ self.__remove_changed_rows()
+ self.__set_supplied_items()
def initialized_fields(self):
self.available_materials = frappe._dict()
self.alternative_item_details = frappe._dict()
- self.get_backflush_based_on()
+ self.__get_backflush_based_on()
- def get_backflush_based_on(self):
+ def __get_backflush_based_on(self):
self.backflush_based_on = frappe.db.get_single_value("Buying Settings",
"backflush_raw_materials_of_subcontract_based_on")
- def get_purchase_orders(self):
+ def __get_purchase_orders(self):
self.purchase_orders = []
if self.doctype == 'Purchase Order':
@@ -41,14 +39,14 @@ class Subcontracting(object):
self.purchase_orders = [d.purchase_order for d in self.items if d.purchase_order]
- def identify_change_in_item_table(self):
+ def __identify_change_in_item_table(self):
self.changed_name = []
if self.doctype == 'Purchase Order' or not self.get(self.raw_material_table):
self.set(self.raw_material_table, [])
return
- item_dict = self.get_data_before_save()
+ item_dict = self.__get_data_before_save()
if not item_dict:
return True
@@ -61,7 +59,7 @@ class Subcontracting(object):
self.changed_name.extend(item_dict.keys())
- def get_data_before_save(self):
+ def __get_data_before_save(self):
item_dict = {}
if self.doctype == 'Purchase Receipt' and self._doc_before_save:
for row in self._doc_before_save.get('items'):
@@ -80,7 +78,7 @@ class Subcontracting(object):
if not self.purchase_orders:
return
- for row in self.get_transferred_items():
+ for row in self.__get_transferred_items():
key = (row.rm_item_code, row.main_item_code, row.purchase_order)
if key not in self.available_materials:
@@ -98,20 +96,20 @@ class Subcontracting(object):
if row.batch_no:
details.batch_no[row.batch_no] += row.qty
- self.set_alternative_item_details(row)
+ self.__set_alternative_item_details(row)
for doctype in ['Purchase Receipt', 'Purchase Invoice']:
- self.update_consumed_materials(doctype)
+ self.__update_consumed_materials(doctype)
- def update_consumed_materials(self, doctype, return_consumed_items=False):
+ def __update_consumed_materials(self, doctype, return_consumed_items=False):
'''Deduct the consumed materials from the available materials.'''
- pr_items = self.get_received_items(doctype)
+ pr_items = self.__get_received_items(doctype)
if not pr_items:
return ([], {}) if return_consumed_items else None
pr_items = {d.name: d.get(self.get('po_field') or 'purchase_order') for d in pr_items}
- consumed_materials = self.get_consumed_items(doctype, pr_items.keys())
+ consumed_materials = self.__get_consumed_items(doctype, pr_items.keys())
if return_consumed_items:
return (consumed_materials, pr_items)
@@ -130,7 +128,7 @@ class Subcontracting(object):
if row.batch_no:
self.available_materials[key]['batch_no'][row.batch_no] -= row.consumed_qty
- def get_transferred_items(self):
+ def __get_transferred_items(self):
fields = ['`tabStock Entry`.`purchase_order`']
alias_dict = {'item_code': 'rm_item_code', 'subcontracted_item': 'main_item_code', 'basic_rate': 'rate'}
@@ -149,7 +147,7 @@ class Subcontracting(object):
return frappe.get_all('Stock Entry', fields = fields, filters=filters)
- def get_received_items(self, doctype):
+ def __get_received_items(self, doctype):
fields = []
self.po_field = 'purchase_order' if doctype == 'Purchase Receipt' else 'po_detail'
@@ -162,16 +160,16 @@ class Subcontracting(object):
return frappe.get_all(f'{doctype}', fields = fields, filters = filters)
- def get_consumed_items(self, doctype, pr_items):
+ def __get_consumed_items(self, doctype, pr_items):
return frappe.get_all(f'{doctype} Item Supplied',
fields = ['serial_no', 'rm_item_code', 'reference_name', 'batch_no', 'consumed_qty', 'main_item_code'],
filters = {'docstatus': 1, 'reference_name': ('in', list(pr_items))})
- def set_alternative_item_details(self, row):
+ def __set_alternative_item_details(self, row):
if row.get('original_item'):
self.alternative_item_details[row.get('original_item')] = row
- def get_pending_qty_to_receive(self):
+ def __get_pending_qty_to_receive(self):
'''Get qty to be received against the purchase order.'''
self.qty_to_be_received = defaultdict(float)
@@ -183,7 +181,7 @@ class Subcontracting(object):
self.qty_to_be_received[(row.item_code, row.parent)] += row.qty
- def get_materials_from_bom(self, item_code, bom_no, exploded_item=0):
+ def __get_materials_from_bom(self, item_code, bom_no, exploded_item=0):
doctype = 'BOM Item' if not exploded_item else 'BOM Explosion Item'
fields = [f'`tab{doctype}`.`stock_qty` / `tabBOM`.`quantity` as qty_consumed_per_unit']
@@ -197,7 +195,7 @@ class Subcontracting(object):
return frappe.get_all('BOM', fields = fields, filters=filters, order_by = f'`tab{doctype}`.`idx`') or []
- def remove_changed_rows(self):
+ def __remove_changed_rows(self):
if not self.changed_name:
return
@@ -212,7 +210,7 @@ class Subcontracting(object):
i += 1
- def set_supplied_items(self):
+ def __set_supplied_items(self):
self.bom_items = {}
has_supplied_items = True if self.get(self.raw_material_table) else False
@@ -222,28 +220,28 @@ class Subcontracting(object):
continue
if self.doctype == 'Purchase Order' or self.backflush_based_on == 'BOM':
- for bom_item in self.get_materials_from_bom(row.item_code, row.bom, row.get('include_exploded_items')):
+ for bom_item in self.__get_materials_from_bom(row.item_code, row.bom, row.get('include_exploded_items')):
qty = (flt(bom_item.qty_consumed_per_unit) * flt(row.qty) * row.conversion_factor)
bom_item.main_item_code = row.item_code
- self.update_reserve_warehouse(bom_item, row)
- self.set_alternative_item(bom_item)
- self.add_supplied_item(row, bom_item, qty)
+ self.__update_reserve_warehouse(bom_item, row)
+ self.__set_alternative_item(bom_item)
+ self.__add_supplied_item(row, bom_item, qty)
elif self.backflush_based_on != 'BOM':
for key, transfer_item in self.available_materials.items():
if (key[1], key[2]) == (row.item_code, row.purchase_order) and transfer_item.qty > 0:
- qty = self.get_qty_based_on_material_transfer(row, transfer_item) or 0
+ qty = self.__get_qty_based_on_material_transfer(row, transfer_item) or 0
transfer_item.qty -= qty
- self.add_supplied_item(row, transfer_item.get('item_details'), qty)
+ self.__add_supplied_item(row, transfer_item.get('item_details'), qty)
if self.qty_to_be_received:
self.qty_to_be_received[(row.item_code, row.purchase_order)] -= row.qty
- def update_reserve_warehouse(self, row, item):
+ def __update_reserve_warehouse(self, row, item):
if self.doctype == 'Purchase Order':
row.reserve_warehouse = (self.set_reserve_warehouse or item.warehouse)
- def get_qty_based_on_material_transfer(self, item_row, transfer_item):
+ def __get_qty_based_on_material_transfer(self, item_row, transfer_item):
key = (item_row.item_code, item_row.purchase_order)
if self.qty_to_be_received == item_row.qty:
@@ -257,11 +255,11 @@ class Subcontracting(object):
return qty
- def set_alternative_item(self, bom_item):
+ def __set_alternative_item(self, bom_item):
if self.alternative_item_details.get(bom_item.rm_item_code):
bom_item.update(self.alternative_item_details[bom_item.rm_item_code])
- def add_supplied_item(self, item_row, bom_item, qty):
+ def __add_supplied_item(self, item_row, bom_item, qty):
bom_item.conversion_factor = item_row.conversion_factor
rm_obj = self.append(self.raw_material_table, bom_item)
rm_obj.reference_name = item_row.name
@@ -269,15 +267,15 @@ class Subcontracting(object):
if self.doctype == 'Purchase Order':
rm_obj.required_qty = qty
else:
- self.set_batch_nos(bom_item, item_row, rm_obj, qty)
+ self.__set_batch_nos(bom_item, item_row, rm_obj, qty)
- def set_batch_nos(self, bom_item, item_row, rm_obj, qty):
+ def __set_batch_nos(self, bom_item, item_row, rm_obj, qty):
key = (rm_obj.rm_item_code, item_row.item_code, item_row.purchase_order)
if (self.available_materials.get(key) and self.available_materials[key]['batch_no']):
for batch_no, batch_qty in self.available_materials[key]['batch_no'].items():
if batch_qty >= qty:
- self.set_batch_no_as_per_qty(item_row, rm_obj, batch_no, qty)
+ self.__set_batch_no_as_per_qty(item_row, rm_obj, batch_no, qty)
self.available_materials[key]['batch_no'][batch_no] -= qty
return
@@ -285,18 +283,18 @@ class Subcontracting(object):
qty -= batch_qty
new_rm_obj = self.append(self.raw_material_table, bom_item)
new_rm_obj.reference_name = item_row.name
- self.set_batch_no_as_per_qty(item_row, new_rm_obj, batch_no, batch_qty)
+ self.__set_batch_no_as_per_qty(item_row, new_rm_obj, batch_no, batch_qty)
self.available_materials[key]['batch_no'][batch_no] = 0
else:
rm_obj.required_qty = qty
rm_obj.consumed_qty = qty
- self.set_serial_nos(item_row, rm_obj)
+ self.__set_serial_nos(item_row, rm_obj)
- def set_batch_no_as_per_qty(self, item_row, rm_obj, batch_no, qty):
+ def __set_batch_no_as_per_qty(self, item_row, rm_obj, batch_no, qty):
rm_obj.update({'consumed_qty': qty, 'batch_no': batch_no, 'required_qty': qty})
- self.set_serial_nos(item_row, rm_obj)
+ self.__set_serial_nos(item_row, rm_obj)
- def set_serial_nos(self, item_row, rm_obj):
+ def __set_serial_nos(self, item_row, rm_obj):
key = (rm_obj.rm_item_code, item_row.item_code, item_row.purchase_order)
if (self.available_materials.get(key) and self.available_materials[key]['serial_no']):
used_serial_nos = self.available_materials[key]['serial_no'][0: cint(rm_obj.consumed_qty)]
@@ -310,17 +308,17 @@ class Subcontracting(object):
if self.is_subcontracted != 'Yes':
return
- self.get_purchase_orders()
- consumed_items, pr_items = self.update_consumed_materials(self.doctype, return_consumed_items=True)
+ self.__get_purchase_orders()
+ consumed_items, pr_items = self.__update_consumed_materials(self.doctype, return_consumed_items=True)
itemwise_consumed_qty = defaultdict(float)
for row in consumed_items:
key = (row.rm_item_code, row.main_item_code, pr_items.get(row.reference_name))
itemwise_consumed_qty[key] += row.consumed_qty
- self.update_consumed_qty_in_po(itemwise_consumed_qty)
+ self.__update_consumed_qty_in_po(itemwise_consumed_qty)
- def update_consumed_qty_in_po(self, itemwise_consumed_qty):
+ def __update_consumed_qty_in_po(self, itemwise_consumed_qty):
fields = ['main_item_code', 'rm_item_code', 'parent', 'supplied_qty', 'name']
filters = {'docstatus': 1, 'parent': ('in', self.purchase_orders)}
@@ -334,7 +332,7 @@ class Subcontracting(object):
itemwise_consumed_qty[key] -= consumed_qty
frappe.db.set_value('Purchase Order Item Supplied', row.name, 'consumed_qty', consumed_qty)
- def validate_consumed_qty(self):
+ def __validate_consumed_qty(self):
for row in self.get(self.raw_material_table):
if flt(row.consumed_qty) == 0.0 and row.get('serial_no'):
msg = f'Row {row.idx}: the consumed qty cannot be zero for the item {frappe.bold(row.rm_item_code)}'
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 7e1ffa96a2..a29f118ef8 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -743,6 +743,10 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
var me = this;
var item = frappe.get_doc(cdt, cdn);
+ if (item && item.doctype === 'Purchase Receipt Item Supplied') {
+ return;
+ }
+
if (item && item.serial_no) {
if (!item.item_code) {
this.frm.trigger("item_code", cdt, cdn);
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 0009926f5d..66f8b63cb9 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -1005,10 +1005,12 @@ class StockEntry(StockController):
if self.purchase_order and self.purpose == "Send to Subcontractor":
#Get PO Supplied Items Details
item_wh = frappe._dict(frappe.db.sql("""
- select rm_item_code, reserve_warehouse
- from `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
- where po.name = poitemsup.parent
- and po.name = %s""",self.purchase_order))
+ SELECT
+ rm_item_code, reserve_warehouse
+ FROM
+ `tabPurchase Order` po, `tabPurchase Order Item Supplied` poitemsup
+ WHERE
+ po.name = poitemsup.parent and po.name = %s """,self.purchase_order))
for item in itervalues(item_dict):
if self.pro_doc and cint(self.pro_doc.from_wip_warehouse):
From 110e152fa3b67f09ee939e70f825efaed88b9595 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Tue, 15 Jun 2021 17:29:52 +0530
Subject: [PATCH 252/262] fix: purchase invoice qty change not recalculate the
consumed qty and added test cases for purchase invoice
---
.../purchase_invoice/purchase_invoice.json | 617 +++++-------------
.../purchase_invoice/purchase_invoice.py | 2 +
erpnext/controllers/buying_controller.py | 5 +
erpnext/controllers/subcontracting.py | 41 +-
erpnext/public/js/controllers/buying.js | 15 +-
.../purchase_receipt/purchase_receipt.js | 9 -
.../purchase_receipt/purchase_receipt.py | 5 -
erpnext/tests/test_subcontracting.py | 267 +++++++-
8 files changed, 463 insertions(+), 498 deletions(-)
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index a714ac7827..00ef7d5c18 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -175,9 +175,7 @@
"hidden": 1,
"label": "Title",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "naming_series",
@@ -189,9 +187,7 @@
"options": "ACC-PINV-.YYYY.-\nACC-PINV-RET-.YYYY.-",
"print_hide": 1,
"reqd": 1,
- "set_only_once": 1,
- "show_days": 1,
- "show_seconds": 1
+ "set_only_once": 1
},
{
"fieldname": "supplier",
@@ -203,9 +199,7 @@
"options": "Supplier",
"print_hide": 1,
"reqd": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"bold": 1,
@@ -217,9 +211,7 @@
"label": "Supplier Name",
"oldfieldname": "supplier_name",
"oldfieldtype": "Data",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fetch_from": "supplier.tax_id",
@@ -227,27 +219,21 @@
"fieldtype": "Read Only",
"label": "Tax Id",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "due_date",
"fieldtype": "Date",
"label": "Due Date",
"oldfieldname": "due_date",
- "oldfieldtype": "Date",
- "show_days": 1,
- "show_seconds": 1
+ "oldfieldtype": "Date"
},
{
"default": "0",
"fieldname": "is_paid",
"fieldtype": "Check",
"label": "Is Paid",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
@@ -255,25 +241,19 @@
"fieldtype": "Check",
"label": "Is Return (Debit Note)",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
"fieldname": "apply_tds",
"fieldtype": "Check",
"label": "Apply Tax Withholding Amount",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1,
"width": "50%"
},
{
@@ -283,17 +263,13 @@
"label": "Company",
"options": "Company",
"print_hide": 1,
- "remember_last_selected_value": 1,
- "show_days": 1,
- "show_seconds": 1
+ "remember_last_selected_value": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
- "options": "Cost Center",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Cost Center"
},
{
"default": "Today",
@@ -305,9 +281,7 @@
"oldfieldtype": "Date",
"print_hide": 1,
"reqd": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"fieldname": "posting_time",
@@ -316,8 +290,6 @@
"no_copy": 1,
"print_hide": 1,
"print_width": "100px",
- "show_days": 1,
- "show_seconds": 1,
"width": "100px"
},
{
@@ -326,9 +298,7 @@
"fieldname": "set_posting_time",
"fieldtype": "Check",
"label": "Edit Posting Date and Time",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "amended_from",
@@ -340,58 +310,44 @@
"oldfieldtype": "Link",
"options": "Purchase Invoice",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.on_hold",
"fieldname": "sb_14",
"fieldtype": "Section Break",
- "label": "Hold Invoice",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Hold Invoice"
},
{
"default": "0",
"fieldname": "on_hold",
"fieldtype": "Check",
- "label": "Hold Invoice",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Hold Invoice"
},
{
"depends_on": "eval:doc.on_hold",
"description": "Once set, this invoice will be on hold till the set date",
"fieldname": "release_date",
"fieldtype": "Date",
- "label": "Release Date",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Release Date"
},
{
"fieldname": "cb_17",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "eval:doc.on_hold",
"fieldname": "hold_comment",
"fieldtype": "Small Text",
- "label": "Reason For Putting On Hold",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Reason For Putting On Hold"
},
{
"collapsible": 1,
"collapsible_depends_on": "bill_no",
"fieldname": "supplier_invoice_details",
"fieldtype": "Section Break",
- "label": "Supplier Invoice Details",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Supplier Invoice Details"
},
{
"fieldname": "bill_no",
@@ -399,15 +355,11 @@
"label": "Supplier Invoice No",
"oldfieldname": "bill_no",
"oldfieldtype": "Data",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_15",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "bill_date",
@@ -416,17 +368,13 @@
"no_copy": 1,
"oldfieldname": "bill_date",
"oldfieldtype": "Date",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"depends_on": "return_against",
"fieldname": "returns",
"fieldtype": "Section Break",
- "label": "Returns",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Returns"
},
{
"depends_on": "return_against",
@@ -436,34 +384,26 @@
"no_copy": 1,
"options": "Purchase Invoice",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"fieldname": "section_addresses",
"fieldtype": "Section Break",
- "label": "Address and Contact",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Address and Contact"
},
{
"fieldname": "supplier_address",
"fieldtype": "Link",
"label": "Select Supplier Address",
"options": "Address",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "address_display",
"fieldtype": "Small Text",
"label": "Address",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "contact_person",
@@ -471,67 +411,51 @@
"in_global_search": 1,
"label": "Contact Person",
"options": "Contact",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "contact_display",
"fieldtype": "Small Text",
"label": "Contact",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"label": "Mobile No",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "contact_email",
"fieldtype": "Small Text",
"label": "Contact Email",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "col_break_address",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "shipping_address",
"fieldtype": "Link",
"label": "Select Shipping Address",
"options": "Address",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "shipping_address_display",
"fieldtype": "Small Text",
"label": "Shipping Address",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"fieldname": "currency_and_price_list",
"fieldtype": "Section Break",
"label": "Currency and Price List",
- "options": "fa fa-tag",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-tag"
},
{
"fieldname": "currency",
@@ -540,9 +464,7 @@
"oldfieldname": "currency",
"oldfieldtype": "Select",
"options": "Currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "conversion_rate",
@@ -551,24 +473,18 @@
"oldfieldname": "conversion_rate",
"oldfieldtype": "Currency",
"precision": "9",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break2",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "buying_price_list",
"fieldtype": "Link",
"label": "Price List",
"options": "Price List",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "price_list_currency",
@@ -576,18 +492,14 @@
"label": "Price List Currency",
"options": "Currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "plc_conversion_rate",
"fieldtype": "Float",
"label": "Price List Exchange Rate",
"precision": "9",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
@@ -596,15 +508,11 @@
"label": "Ignore Pricing Rule",
"no_copy": 1,
"permlevel": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "sec_warehouse",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"depends_on": "update_stock",
@@ -613,9 +521,7 @@
"fieldtype": "Link",
"label": "Set Accepted Warehouse",
"options": "Warehouse",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"depends_on": "update_stock",
@@ -625,15 +531,11 @@
"label": "Rejected Warehouse",
"no_copy": 1,
"options": "Warehouse",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "col_break_warehouse",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"default": "No",
@@ -641,33 +543,25 @@
"fieldtype": "Select",
"label": "Raw Materials Supplied",
"options": "No\nYes",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "items_section",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-shopping-cart",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-shopping-cart"
},
{
"default": "0",
"fieldname": "update_stock",
"fieldtype": "Check",
"label": "Update Stock",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "scan_barcode",
"fieldtype": "Data",
- "label": "Scan Barcode",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Scan Barcode"
},
{
"allow_bulk_edit": 1,
@@ -677,56 +571,43 @@
"oldfieldname": "entries",
"oldfieldtype": "Table",
"options": "Purchase Invoice Item",
- "reqd": 1,
- "show_days": 1,
- "show_seconds": 1
+ "reqd": 1
},
{
"fieldname": "pricing_rule_details",
"fieldtype": "Section Break",
- "label": "Pricing Rules",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Pricing Rules"
},
{
"fieldname": "pricing_rules",
"fieldtype": "Table",
"label": "Pricing Rule Detail",
"options": "Pricing Rule Detail",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible_depends_on": "supplied_items",
"fieldname": "raw_materials_supplied",
"fieldtype": "Section Break",
- "label": "Raw Materials Supplied",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Raw Materials Supplied"
},
{
+ "depends_on": "update_stock",
"fieldname": "supplied_items",
"fieldtype": "Table",
"label": "Supplied Items",
- "options": "Purchase Receipt Item Supplied",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "no_copy": 1,
+ "options": "Purchase Receipt Item Supplied"
},
{
"fieldname": "section_break_26",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"fieldname": "total_qty",
"fieldtype": "Float",
"label": "Total Quantity",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_total",
@@ -734,9 +615,7 @@
"label": "Total (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_net_total",
@@ -746,24 +625,18 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_28",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "total",
"fieldtype": "Currency",
"label": "Total",
"options": "currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "net_total",
@@ -773,56 +646,42 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "total_net_weight",
"fieldtype": "Float",
"label": "Total Net Weight",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "taxes_section",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-money"
},
{
"fieldname": "tax_category",
"fieldtype": "Link",
"label": "Tax Category",
"options": "Tax Category",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_49",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "shipping_rule",
"fieldtype": "Link",
"label": "Shipping Rule",
"options": "Shipping Rule",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "section_break_51",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"fieldname": "taxes_and_charges",
@@ -831,9 +690,7 @@
"oldfieldname": "purchase_other_charges",
"oldfieldtype": "Link",
"options": "Purchase Taxes and Charges Template",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "taxes",
@@ -841,17 +698,13 @@
"label": "Purchase Taxes and Charges",
"oldfieldname": "purchase_tax_details",
"oldfieldtype": "Table",
- "options": "Purchase Taxes and Charges",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Purchase Taxes and Charges"
},
{
"collapsible": 1,
"fieldname": "sec_tax_breakup",
"fieldtype": "Section Break",
- "label": "Tax Breakup",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Tax Breakup"
},
{
"fieldname": "other_charges_calculation",
@@ -860,17 +713,13 @@
"no_copy": 1,
"oldfieldtype": "HTML",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "totals",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
- "options": "fa fa-money",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-money"
},
{
"fieldname": "base_taxes_and_charges_added",
@@ -880,9 +729,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_taxes_and_charges_deducted",
@@ -892,9 +739,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_total_taxes_and_charges",
@@ -904,15 +749,11 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_40",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "taxes_and_charges_added",
@@ -922,9 +763,7 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "taxes_and_charges_deducted",
@@ -934,9 +773,7 @@
"oldfieldtype": "Currency",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "total_taxes_and_charges",
@@ -944,18 +781,14 @@
"label": "Total Taxes and Charges",
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "discount_amount",
"fieldname": "section_break_44",
"fieldtype": "Section Break",
- "label": "Additional Discount",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Additional Discount"
},
{
"default": "Grand Total",
@@ -963,9 +796,7 @@
"fieldtype": "Select",
"label": "Apply Additional Discount On",
"options": "\nGrand Total\nNet Total",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "base_discount_amount",
@@ -973,38 +804,28 @@
"label": "Additional Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_46",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "additional_discount_percentage",
"fieldtype": "Float",
"label": "Additional Discount Percentage",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Additional Discount Amount",
"options": "currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "section_break_49",
- "fieldtype": "Section Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Section Break"
},
{
"fieldname": "base_grand_total",
@@ -1014,9 +835,7 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1026,9 +845,7 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1038,9 +855,7 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "base_in_words",
@@ -1050,17 +865,13 @@
"oldfieldname": "in_words",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break8",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"print_hide": 1,
- "show_days": 1,
- "show_seconds": 1,
"width": "50%"
},
{
@@ -1071,9 +882,7 @@
"oldfieldname": "grand_total_import",
"oldfieldtype": "Currency",
"options": "currency",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1083,9 +892,7 @@
"no_copy": 1,
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"depends_on": "eval:!doc.disable_rounded_total",
@@ -1095,9 +902,7 @@
"no_copy": 1,
"options": "currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "in_words",
@@ -1107,9 +912,7 @@
"oldfieldname": "in_words_import",
"oldfieldtype": "Data",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "total_advance",
@@ -1120,9 +923,7 @@
"oldfieldtype": "Currency",
"options": "party_account_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "outstanding_amount",
@@ -1133,18 +934,14 @@
"oldfieldtype": "Currency",
"options": "party_account_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"default": "0",
"depends_on": "grand_total",
"fieldname": "disable_rounded_total",
"fieldtype": "Check",
- "label": "Disable Rounded Total",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Disable Rounded Total"
},
{
"collapsible": 1,
@@ -1152,26 +949,20 @@
"depends_on": "eval:doc.is_paid===1||(doc.advances && doc.advances.length>0)",
"fieldname": "payments_section",
"fieldtype": "Section Break",
- "label": "Payments",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Payments"
},
{
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"label": "Mode of Payment",
"options": "Mode of Payment",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "cash_bank_account",
"fieldtype": "Link",
"label": "Cash/Bank Account",
- "options": "Account",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Account"
},
{
"fieldname": "clearance_date",
@@ -1179,15 +970,11 @@
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "col_br_payments",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "is_paid",
@@ -1196,9 +983,7 @@
"label": "Paid Amount",
"no_copy": 1,
"options": "currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "base_paid_amount",
@@ -1207,9 +992,7 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
@@ -1217,9 +1000,7 @@
"depends_on": "grand_total",
"fieldname": "write_off",
"fieldtype": "Section Break",
- "label": "Write Off",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Write Off"
},
{
"fieldname": "write_off_amount",
@@ -1227,9 +1008,7 @@
"label": "Write Off Amount",
"no_copy": 1,
"options": "currency",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "base_write_off_amount",
@@ -1238,15 +1017,11 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "column_break_61",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1254,9 +1029,7 @@
"fieldtype": "Link",
"label": "Write Off Account",
"options": "Account",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"depends_on": "eval:flt(doc.write_off_amount)!=0",
@@ -1264,9 +1037,7 @@
"fieldtype": "Link",
"label": "Write Off Cost Center",
"options": "Cost Center",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
@@ -1276,17 +1047,13 @@
"label": "Advance Payments",
"oldfieldtype": "Section Break",
"options": "fa fa-money",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"default": "0",
"fieldname": "allocate_advances_automatically",
"fieldtype": "Check",
- "label": "Set Advances and Allocate (FIFO)",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Set Advances and Allocate (FIFO)"
},
{
"depends_on": "eval:!doc.allocate_advances_automatically",
@@ -1294,9 +1061,7 @@
"fieldtype": "Button",
"label": "Get Advances Paid",
"oldfieldtype": "Button",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "advances",
@@ -1306,26 +1071,20 @@
"oldfieldname": "advance_allocation_details",
"oldfieldtype": "Table",
"options": "Purchase Invoice Advance",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:(!doc.is_return)",
"fieldname": "payment_schedule_section",
"fieldtype": "Section Break",
- "label": "Payment Terms",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Payment Terms"
},
{
"fieldname": "payment_terms_template",
"fieldtype": "Link",
"label": "Payment Terms Template",
- "options": "Payment Terms Template",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Payment Terms Template"
},
{
"fieldname": "payment_schedule",
@@ -1333,9 +1092,7 @@
"label": "Payment Schedule",
"no_copy": 1,
"options": "Payment Schedule",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
@@ -1343,33 +1100,25 @@
"fieldname": "terms_section_break",
"fieldtype": "Section Break",
"label": "Terms and Conditions",
- "options": "fa fa-legal",
- "show_days": 1,
- "show_seconds": 1
+ "options": "fa fa-legal"
},
{
"fieldname": "tc_name",
"fieldtype": "Link",
"label": "Terms",
"options": "Terms and Conditions",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "terms",
"fieldtype": "Text Editor",
- "label": "Terms and Conditions1",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Terms and Conditions1"
},
{
"collapsible": 1,
"fieldname": "printing_settings",
"fieldtype": "Section Break",
- "label": "Printing Settings",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Printing Settings"
},
{
"allow_on_submit": 1,
@@ -1377,9 +1126,7 @@
"fieldtype": "Link",
"label": "Letter Head",
"options": "Letter Head",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"allow_on_submit": 1,
@@ -1387,15 +1134,11 @@
"fieldname": "group_same_items",
"fieldtype": "Check",
"label": "Group same items",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_112",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"allow_on_submit": 1,
@@ -1407,18 +1150,14 @@
"oldfieldtype": "Link",
"options": "Print Heading",
"print_hide": 1,
- "report_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "report_hide": 1
},
{
"fieldname": "language",
"fieldtype": "Data",
"label": "Print Language",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"collapsible": 1,
@@ -1427,9 +1166,7 @@
"label": "More Information",
"oldfieldtype": "Section Break",
"options": "fa fa-file-text",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "credit_to",
@@ -1440,9 +1177,7 @@
"options": "Account",
"print_hide": 1,
"reqd": 1,
- "search_index": 1,
- "show_days": 1,
- "show_seconds": 1
+ "search_index": 1
},
{
"fieldname": "party_account_currency",
@@ -1452,9 +1187,7 @@
"no_copy": 1,
"options": "Currency",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"default": "No",
@@ -1464,9 +1197,7 @@
"oldfieldname": "is_opening",
"oldfieldtype": "Select",
"options": "No\nYes",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "against_expense_account",
@@ -1476,15 +1207,11 @@
"no_copy": 1,
"oldfieldname": "against_expense_account",
"oldfieldtype": "Small Text",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_63",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"default": "Draft",
@@ -1493,9 +1220,7 @@
"in_standard_filter": 1,
"label": "Status",
"options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled\nInternal Transfer",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "inter_company_invoice_reference",
@@ -1504,9 +1229,7 @@
"no_copy": 1,
"options": "Sales Invoice",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "remarks",
@@ -1515,18 +1238,14 @@
"no_copy": 1,
"oldfieldname": "remarks",
"oldfieldtype": "Text",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"collapsible": 1,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"label": "Subscription Section",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"allow_on_submit": 1,
@@ -1535,9 +1254,7 @@
"fieldtype": "Date",
"label": "From Date",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"allow_on_submit": 1,
@@ -1546,15 +1263,11 @@
"fieldtype": "Date",
"label": "To Date",
"no_copy": 1,
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "column_break_114",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"fieldname": "auto_repeat",
@@ -1563,32 +1276,24 @@
"no_copy": 1,
"options": "Auto Repeat",
"print_hide": 1,
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"allow_on_submit": 1,
"depends_on": "eval: doc.auto_repeat",
"fieldname": "update_auto_repeat_reference",
"fieldtype": "Button",
- "label": "Update Auto Repeat Reference",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Update Auto Repeat Reference"
},
{
"collapsible": 1,
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions ",
- "show_days": 1,
- "show_seconds": 1
+ "label": "Accounting Dimensions "
},
{
"fieldname": "dimension_col_break",
- "fieldtype": "Column Break",
- "show_days": 1,
- "show_seconds": 1
+ "fieldtype": "Column Break"
},
{
"default": "0",
@@ -1596,9 +1301,7 @@
"fieldname": "is_internal_supplier",
"fieldtype": "Check",
"label": "Is Internal Supplier",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "tax_withholding_category",
@@ -1606,25 +1309,19 @@
"hidden": 1,
"label": "Tax Withholding Category",
"options": "Tax Withholding Category",
- "print_hide": 1,
- "show_days": 1,
- "show_seconds": 1
+ "print_hide": 1
},
{
"fieldname": "billing_address",
"fieldtype": "Link",
"label": "Select Billing Address",
- "options": "Address",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Address"
},
{
"fieldname": "billing_address_display",
"fieldtype": "Small Text",
"label": "Billing Address",
- "read_only": 1,
- "show_days": 1,
- "show_seconds": 1
+ "read_only": 1
},
{
"fieldname": "project",
@@ -1638,9 +1335,7 @@
"fieldname": "unrealized_profit_loss_account",
"fieldtype": "Link",
"label": "Unrealized Profit / Loss Account",
- "options": "Account",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Account"
},
{
"depends_on": "eval:doc.is_internal_supplier",
@@ -1649,9 +1344,7 @@
"fieldname": "represents_company",
"fieldtype": "Link",
"label": "Represents Company",
- "options": "Company",
- "show_days": 1,
- "show_seconds": 1
+ "options": "Company"
},
{
"depends_on": "eval:doc.update_stock && doc.is_internal_supplier",
@@ -1663,8 +1356,6 @@
"options": "Warehouse",
"print_hide": 1,
"print_width": "50px",
- "show_days": 1,
- "show_seconds": 1,
"width": "50px"
},
{
@@ -1692,7 +1383,7 @@
"idx": 204,
"is_submittable": 1,
"links": [],
- "modified": "2021-06-09 12:30:25.632109",
+ "modified": "2021-06-15 18:20:56.806195",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 0ee0bc7e11..45d89ad1c8 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -400,6 +400,7 @@ class PurchaseInvoice(BuyingController):
# because updating ordered qty in bin depends upon updated ordered qty in PO
if self.update_stock == 1:
self.update_stock_ledger()
+ self.set_consumed_qty_in_po()
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
update_serial_nos_after_submit(self, "items")
@@ -998,6 +999,7 @@ class PurchaseInvoice(BuyingController):
if self.update_stock == 1:
self.update_stock_ledger()
self.delete_auto_created_batches()
+ self.set_consumed_qty_in_po()
self.make_gl_entries_on_cancel()
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 1907885717..0b0da5f413 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -58,6 +58,11 @@ class BuyingController(StockController, Subcontracting):
if self.doctype in ("Purchase Receipt", "Purchase Invoice"):
self.update_valuation_rate()
+ def onload(self):
+ super(BuyingController, self).onload()
+ self.set_onload("backflush_based_on", frappe.db.get_single_value('Buying Settings',
+ 'backflush_raw_materials_of_subcontract_based_on'))
+
def set_missing_values(self, for_validate=False):
super(BuyingController, self).set_missing_values(for_validate)
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
index e81c0f5732..db841626a5 100644
--- a/erpnext/controllers/subcontracting.py
+++ b/erpnext/controllers/subcontracting.py
@@ -40,9 +40,10 @@ class Subcontracting():
self.purchase_orders = [d.purchase_order for d in self.items if d.purchase_order]
def __identify_change_in_item_table(self):
- self.changed_name = []
+ self.__changed_name = []
+ self.__reference_name = []
- if self.doctype == 'Purchase Order' or not self.get(self.raw_material_table):
+ if self.doctype == 'Purchase Order' or self.is_new():
self.set(self.raw_material_table, [])
return
@@ -51,17 +52,18 @@ class Subcontracting():
return True
for n_row in self.items:
+ self.__reference_name.append(n_row.name)
if (n_row.name not in item_dict) or (n_row.item_code, n_row.qty) != item_dict[n_row.name]:
- self.changed_name.append(n_row.name)
+ self.__changed_name.append(n_row.name)
if item_dict.get(n_row.name):
del item_dict[n_row.name]
- self.changed_name.extend(item_dict.keys())
+ self.__changed_name.extend(item_dict.keys())
def __get_data_before_save(self):
item_dict = {}
- if self.doctype == 'Purchase Receipt' and self._doc_before_save:
+ if self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self._doc_before_save:
for row in self._doc_before_save.get('items'):
item_dict[row.name] = (row.item_code, row.qty)
@@ -149,7 +151,7 @@ class Subcontracting():
def __get_received_items(self, doctype):
fields = []
- self.po_field = 'purchase_order' if doctype == 'Purchase Receipt' else 'po_detail'
+ self.po_field = 'purchase_order'
for field in ['name', self.po_field, 'parent']:
fields.append(f'`tab{doctype} Item`.`{field}`')
@@ -161,9 +163,9 @@ class Subcontracting():
return frappe.get_all(f'{doctype}', fields = fields, filters = filters)
def __get_consumed_items(self, doctype, pr_items):
- return frappe.get_all(f'{doctype} Item Supplied',
+ return frappe.get_all('Purchase Receipt Item Supplied',
fields = ['serial_no', 'rm_item_code', 'reference_name', 'batch_no', 'consumed_qty', 'main_item_code'],
- filters = {'docstatus': 1, 'reference_name': ('in', list(pr_items))})
+ filters = {'docstatus': 1, 'reference_name': ('in', list(pr_items)), 'parenttype': doctype})
def __set_alternative_item_details(self, row):
if row.get('original_item'):
@@ -196,13 +198,16 @@ class Subcontracting():
return frappe.get_all('BOM', fields = fields, filters=filters, order_by = f'`tab{doctype}`.`idx`') or []
def __remove_changed_rows(self):
- if not self.changed_name:
+ if not self.__changed_name:
return
i=1
self.set(self.raw_material_table, [])
for d in self._doc_before_save.supplied_items:
- if d.reference_name in self.changed_name:
+ if d.reference_name in self.__changed_name:
+ continue
+
+ if (d.reference_name not in self.__reference_name):
continue
d.idx = i
@@ -215,8 +220,8 @@ class Subcontracting():
has_supplied_items = True if self.get(self.raw_material_table) else False
for row in self.items:
- if (self.doctype != 'Purchase Order' and ((self.changed_name and row.name not in self.changed_name)
- or (has_supplied_items and not self.changed_name))):
+ if (self.doctype != 'Purchase Order' and ((self.__changed_name and row.name not in self.__changed_name)
+ or (has_supplied_items and not self.__changed_name))):
continue
if self.doctype == 'Purchase Order' or self.backflush_based_on == 'BOM':
@@ -305,16 +310,18 @@ class Subcontracting():
self.available_materials[key]['serial_no'].remove(sn)
def set_consumed_qty_in_po(self):
+ # Update consumed qty back in the purchase order
if self.is_subcontracted != 'Yes':
return
self.__get_purchase_orders()
- consumed_items, pr_items = self.__update_consumed_materials(self.doctype, return_consumed_items=True)
-
itemwise_consumed_qty = defaultdict(float)
- for row in consumed_items:
- key = (row.rm_item_code, row.main_item_code, pr_items.get(row.reference_name))
- itemwise_consumed_qty[key] += row.consumed_qty
+ for doctype in ['Purchase Receipt', 'Purchase Invoice']:
+ consumed_items, pr_items = self.__update_consumed_materials(doctype, return_consumed_items=True)
+
+ for row in consumed_items:
+ key = (row.rm_item_code, row.main_item_code, pr_items.get(row.reference_name))
+ itemwise_consumed_qty[key] += row.consumed_qty
self.__update_consumed_qty_in_po(itemwise_consumed_qty)
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index 680bf04bfc..a657f59c91 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -122,10 +122,21 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
this.set_from_product_bundle();
}
+ this.toggle_subcontracting_fields();
super.refresh();
- }
+ },
- supplier() {
+ toggle_subcontracting_fields: function() {
+ if (in_list(['Purchase Receipt', 'Purchase Invoice'], 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');
+
+ this.frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
+ this.frm.set_df_property('supplied_items', 'cannot_delete_rows', 1);
+ }
+ },
+
+ supplier: function() {
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function(){
me.apply_price_list();
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 4f756170f6..0182ed55a1 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -75,15 +75,6 @@ frappe.ui.form.on("Purchase Receipt", {
}
frm.events.add_custom_buttons(frm);
- frm.trigger('toggle_subcontracting_fields');
- },
-
- toggle_subcontracting_fields: function(frm) {
- frm.fields_dict.supplied_items.grid.update_docfield_property('consumed_qty',
- 'read_only', frm.doc.__onload && frm.doc.__onload.backflush_based_on === 'BOM');
-
- frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
- frm.set_df_property('supplied_items', 'cannot_delete_rows', 1);
},
add_custom_buttons: function(frm) {
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 264561f376..b8580f95a3 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -102,11 +102,6 @@ class PurchaseReceipt(BuyingController):
if self.get("items") and self.apply_putaway_rule and not self.get("is_return"):
apply_putaway_rule(self.doctype, self.get("items"), self.company)
- def onload(self):
- super(PurchaseReceipt, self).onload()
- self.set_onload("backflush_based_on", frappe.db.get_single_value('Buying Settings',
- 'backflush_raw_materials_of_subcontract_based_on'))
-
def validate(self):
self.validate_posting_time()
super(PurchaseReceipt, self).validate()
diff --git a/erpnext/tests/test_subcontracting.py b/erpnext/tests/test_subcontracting.py
index c1a458a6dd..d2438f8c60 100644
--- a/erpnext/tests/test_subcontracting.py
+++ b/erpnext/tests/test_subcontracting.py
@@ -10,7 +10,7 @@ from erpnext.stock.doctype.item.test_item import make_item
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.buying.doctype.purchase_order.purchase_order import (make_rm_stock_entry,
- make_purchase_receipt, get_materials_from_supplier)
+ make_purchase_receipt, make_purchase_invoice, get_materials_from_supplier)
class TestSubcontracting(unittest.TestCase):
def setUp(self):
@@ -458,10 +458,273 @@ class TestSubcontracting(unittest.TestCase):
self.assertEqual(value.qty, details.qty)
self.assertEqual(value.batch_no, details.batch_no)
+
+ def test_item_with_batch_based_on_material_transfer_for_purchase_invoice(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA4 (has batch no).
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Transfer the components in multiple batches with extra 2 qty for the batched item.
+ - Create the 3 purchase receipt against the PO and split Subcontracted Items into two batches.
+ - Keep the qty as 2 for Subcontracted Item in the purchase receipt.
+ - In the first purchase receipt the batched raw materials will be consumed 2 extra qty.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA4'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ qty = 4 if key != 'Subcontracted SRM Item 3' else 6
+ self.assertEqual(value.qty, qty)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.items[0].qty = 2
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 2)
+
+ def test_partial_transfer_serial_no_components_based_on_material_transfer_for_purchase_invoice(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA2.
+ - Transfer the partial components from Stores to Supplier warehouse with serial nos.
+ - Create partial purchase receipt against the PO and change the qty manually.
+ - Transfer the remaining components from Stores to Supplier warehouse with serial nos.
+ - Create purchase receipt for remaining qty against the PO and change the qty manually.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA2'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 2', 'qty': 5}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 5
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, 3)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no[0:3]))
+
+ pr1.load_from_db()
+ pr1.supplied_items[0].consumed_qty = 5
+ pr1.supplied_items[0].serial_no = '\n'.join(itemwise_details[pr1.supplied_items[0].rm_item_code]['serial_no'])
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no))
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(sorted(value.serial_no), sorted(details.serial_no))
+
+ def test_partial_transfer_batch_based_on_material_transfer_for_purchase_invoice(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA6.
+ - Transfer the partial components from Stores to Supplier warehouse with batch.
+ - Create partial purchase receipt against the PO and change the qty manually.
+ - Transfer the remaining components from Stores to Supplier warehouse with batch.
+ - Create purchase receipt for remaining qty against the PO and change the qty manually.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA6'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 3', 'qty': 5}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 5
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+
+ transferred_batch_no = ''
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, 3)
+ transferred_batch_no = details.batch_no
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ pr1.load_from_db()
+ pr1.supplied_items[0].consumed_qty = 5
+ pr1.supplied_items[0].batch_no = list(transferred_batch_no.keys())[0]
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ details = itemwise_details.get(key)
+ self.assertEqual(value.qty, details.qty)
+ self.assertEqual(value.batch_no, details.batch_no)
+
+ def test_item_with_batch_based_on_bom_for_purchase_invoice(self):
+ '''
+ - Set backflush based on BOM
+ - Create subcontracted PO for the item Subcontracted Item SA4 (has batch no).
+ - Transfer the components from Stores to Supplier warehouse with batch no and serial nos.
+ - Transfer the components in multiple batches.
+ - Create the 3 purchase receipt against the PO and split Subcontracted Items into two batches.
+ - Keep the qty as 2 for Subcontracted Item in the purchase receipt.
+ '''
+
+ set_backflush_based_on('BOM')
+ item_code = 'Subcontracted Item SA4'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 1', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 2', 'qty': 10},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 3},
+ {'item_code': 'Subcontracted SRM Item 3', 'qty': 1}
+ ]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ add_second_row_in_pr(pr1)
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 4)
+
+ pr1 = make_purchase_invoice(po.name)
+ pr1.update_stock = 1
+ pr1.items[0].qty = 2
+ pr1.items[0].expense_account = 'Stock Adjustment - _TC'
+ pr1.save()
+ pr1.submit()
+
+ for key, value in get_supplied_items(pr1).items():
+ self.assertEqual(value.qty, 2)
+
def add_second_row_in_pr(pr):
item_dict = {}
for column in ['item_code', 'item_name', 'qty', 'uom', 'warehouse', 'stock_uom',
- 'purchase_order', 'purchase_order_item', 'conversion_factor', 'rate']:
+ 'purchase_order', 'purchase_order_item', 'conversion_factor', 'rate', 'expense_account', 'po_detail']:
item_dict[column] = pr.items[0].get(column)
pr.append('items', item_dict)
From e5fb23972ab1e482404bdb5f0a8c919aa209c265 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Fri, 18 Jun 2021 20:37:42 +0530
Subject: [PATCH 253/262] fix: available qty for consumption
---
.../purchase_order/test_purchase_order.py | 3 -
.../purchase_receipt_item_supplied.json | 20 ++++--
erpnext/controllers/buying_controller.py | 10 +--
erpnext/controllers/subcontracting.py | 66 ++++++++++++++++---
erpnext/stock/stock_ledger.py | 2 +-
erpnext/tests/test_subcontracting.py | 31 +++++++++
6 files changed, 110 insertions(+), 22 deletions(-)
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index 33d1971451..8563b97ab7 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -847,9 +847,6 @@ class TestPurchaseOrder(unittest.TestCase):
for item in rm_items:
transferred_rm_map[item.get('rm_item_code')] = item
- for item in pr.get('supplied_items'):
- self.assertEqual(item.get('required_qty'), (transferred_rm_map[item.get('rm_item_code')].get('qty') / order_qty) * received_qty)
-
update_backflush_based_on("BOM")
def test_supplied_qty_against_subcontracted_po(self):
diff --git a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json
index d8c37f5881..f9cd72015a 100644
--- a/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json
+++ b/erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json
@@ -26,7 +26,8 @@
"secbreak_3",
"batch_no",
"col_break4",
- "serial_no"
+ "serial_no",
+ "purchase_order"
],
"fields": [
{
@@ -81,9 +82,10 @@
"fieldname": "required_qty",
"fieldtype": "Float",
"in_list_view": 1,
- "label": "Required Qty",
+ "label": "Available Qty For Consumption",
"oldfieldname": "required_qty",
"oldfieldtype": "Currency",
+ "print_hide": 1,
"read_only": 1
},
{
@@ -91,7 +93,7 @@
"fieldname": "consumed_qty",
"fieldtype": "Float",
"in_list_view": 1,
- "label": "Consumed Qty",
+ "label": "Qty to Be Consumed",
"oldfieldname": "consumed_qty",
"oldfieldtype": "Currency",
"reqd": 1
@@ -190,12 +192,22 @@
"fieldtype": "Data",
"label": "Item Name",
"read_only": 1
+ },
+ {
+ "fieldname": "purchase_order",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Purchase Order",
+ "no_copy": 1,
+ "options": "Purchase Order",
+ "print_hide": 1,
+ "read_only": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
- "modified": "2021-05-29 17:22:14.977117",
+ "modified": "2021-06-19 19:33:04.431213",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Receipt Item Supplied",
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 0b0da5f413..6a550e0e97 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -292,11 +292,13 @@ class BuyingController(StockController, Subcontracting):
if item in self.sub_contracted_items and not item.bom:
frappe.throw(_("Please select BOM in BOM field for Item {0}").format(item.item_code))
- if self.doctype == "Purchase Order":
- for supplied_item in self.get("supplied_items"):
- if not supplied_item.reserve_warehouse:
- frappe.throw(_("Reserved Warehouse is mandatory for Item {0} in Raw Materials supplied").format(frappe.bold(supplied_item.rm_item_code)))
+ if self.doctype != "Purchase Order":
+ return
+ for row in self.get("supplied_items"):
+ if not row.reserve_warehouse:
+ msg = f"Reserved Warehouse is mandatory for the Item {frappe.bold(row.rm_item_code)} in Raw Materials supplied"
+ frappe.throw(_(msg))
else:
for item in self.get("items"):
if item.bom:
diff --git a/erpnext/controllers/subcontracting.py b/erpnext/controllers/subcontracting.py
index db841626a5..36ae110216 100644
--- a/erpnext/controllers/subcontracting.py
+++ b/erpnext/controllers/subcontracting.py
@@ -1,6 +1,7 @@
import frappe
+import copy
from frappe import _
-from frappe.utils import flt, cint
+from frappe.utils import flt, cint, get_link_to_form
from collections import defaultdict
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
@@ -12,7 +13,7 @@ class Subcontracting():
self.raw_material_table = raw_material_table
self.__identify_change_in_item_table()
self.__prepare_supplied_items()
- self.__validate_consumed_qty()
+ self.__validate_supplied_items()
def __prepare_supplied_items(self):
self.initialized_fields()
@@ -24,6 +25,7 @@ class Subcontracting():
def initialized_fields(self):
self.available_materials = frappe._dict()
+ self.__transferred_items = frappe._dict()
self.alternative_item_details = frappe._dict()
self.__get_backflush_based_on()
@@ -100,6 +102,7 @@ class Subcontracting():
self.__set_alternative_item_details(row)
+ self.__transferred_items = copy.deepcopy(self.available_materials)
for doctype in ['Purchase Receipt', 'Purchase Invoice']:
self.__update_consumed_materials(doctype)
@@ -254,6 +257,8 @@ class Subcontracting():
if self.qty_to_be_received:
qty = (flt(item_row.qty) * flt(transfer_item.qty)) / flt(self.qty_to_be_received.get(key, 0))
+ transfer_item.item_details.required_qty = transfer_item.qty
+
if (transfer_item.serial_no or frappe.get_cached_value('UOM',
transfer_item.item_details.stock_uom, 'must_be_whole_number')):
return frappe.utils.ceil(qty)
@@ -272,12 +277,15 @@ class Subcontracting():
if self.doctype == 'Purchase Order':
rm_obj.required_qty = qty
else:
+ rm_obj.consumed_qty = 0
+ rm_obj.purchase_order = item_row.purchase_order
self.__set_batch_nos(bom_item, item_row, rm_obj, qty)
def __set_batch_nos(self, bom_item, item_row, rm_obj, qty):
key = (rm_obj.rm_item_code, item_row.item_code, item_row.purchase_order)
if (self.available_materials.get(key) and self.available_materials[key]['batch_no']):
+ new_rm_obj = None
for batch_no, batch_qty in self.available_materials[key]['batch_no'].items():
if batch_qty >= qty:
self.__set_batch_no_as_per_qty(item_row, rm_obj, batch_no, qty)
@@ -290,13 +298,21 @@ class Subcontracting():
new_rm_obj.reference_name = item_row.name
self.__set_batch_no_as_per_qty(item_row, new_rm_obj, batch_no, batch_qty)
self.available_materials[key]['batch_no'][batch_no] = 0
+
+ if abs(qty) > 0 and not new_rm_obj:
+ self.__set_consumed_qty(rm_obj, qty)
else:
- rm_obj.required_qty = qty
- rm_obj.consumed_qty = qty
+ self.__set_consumed_qty(rm_obj, qty, bom_item.required_qty or qty)
self.__set_serial_nos(item_row, rm_obj)
+ def __set_consumed_qty(self, rm_obj, consumed_qty, required_qty=0):
+ rm_obj.required_qty = required_qty
+ rm_obj.consumed_qty = consumed_qty
+
def __set_batch_no_as_per_qty(self, item_row, rm_obj, batch_no, qty):
- rm_obj.update({'consumed_qty': qty, 'batch_no': batch_no, 'required_qty': qty})
+ rm_obj.update({'consumed_qty': qty, 'batch_no': batch_no,
+ 'required_qty': qty, 'purchase_order': item_row.purchase_order})
+
self.__set_serial_nos(item_row, rm_obj)
def __set_serial_nos(self, item_row, rm_obj):
@@ -339,9 +355,39 @@ class Subcontracting():
itemwise_consumed_qty[key] -= consumed_qty
frappe.db.set_value('Purchase Order Item Supplied', row.name, 'consumed_qty', consumed_qty)
- def __validate_consumed_qty(self):
- for row in self.get(self.raw_material_table):
- if flt(row.consumed_qty) == 0.0 and row.get('serial_no'):
- msg = f'Row {row.idx}: the consumed qty cannot be zero for the item {frappe.bold(row.rm_item_code)}'
+ def __validate_supplied_items(self):
+ if self.doctype not in ['Purchase Invoice', 'Purchase Receipt']:
+ return
- frappe.throw(_(msg),title=_('Consumed Items Qty Check'))
\ No newline at end of file
+ for row in self.get(self.raw_material_table):
+ self.__validate_consumed_qty(row)
+
+ key = (row.rm_item_code, row.main_item_code, row.purchase_order)
+ if not self.__transferred_items or not self.__transferred_items.get(key):
+ return
+
+ self.__validate_batch_no(row, key)
+ self.__validate_serial_no(row, key)
+
+ def __validate_consumed_qty(self, row):
+ if self.backflush_based_on != 'BOM' and flt(row.consumed_qty) == 0.0:
+ msg = f'Row {row.idx}: the consumed qty cannot be zero for the item {frappe.bold(row.rm_item_code)}'
+
+ frappe.throw(_(msg),title=_('Consumed Items Qty Check'))
+
+ def __validate_batch_no(self, row, key):
+ if row.get('batch_no') and row.get('batch_no') not in self.__transferred_items.get(key).get('batch_no'):
+ link = get_link_to_form('Purchase Order', row.purchase_order)
+ msg = f'The Batch No {frappe.bold(row.get("batch_no"))} has not supplied against the Purchase Order {link}'
+ frappe.throw(_(msg), title=_("Incorrect Batch Consumed"))
+
+ def __validate_serial_no(self, row, key):
+ if row.get('serial_no'):
+ serial_nos = get_serial_nos(row.get('serial_no'))
+ incorrect_sn = set(serial_nos).difference(self.__transferred_items.get(key).get('serial_no'))
+
+ if incorrect_sn:
+ incorrect_sn = "\n".join(incorrect_sn)
+ link = get_link_to_form('Purchase Order', row.purchase_order)
+ msg = f'The Serial Nos {incorrect_sn} has not supplied against the Purchase Order {link}'
+ frappe.throw(_(msg), title=_("Incorrect Serial Number Consumed"))
\ No newline at end of file
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index fb2ecab249..9fe89c3fa5 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -485,7 +485,7 @@ class update_entries_after(object):
# Recalculate subcontracted item's rate in case of subcontracted purchase receipt/invoice
if frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_subcontracted") == 'Yes':
- doc = frappe.get_cached_doc(sle.voucher_type, sle.voucher_no)
+ doc = frappe.get_doc(sle.voucher_type, sle.voucher_no)
doc.update_valuation_rate(reset_outgoing_rate=False)
for d in (doc.items + doc.supplied_items):
d.db_update()
diff --git a/erpnext/tests/test_subcontracting.py b/erpnext/tests/test_subcontracting.py
index d2438f8c60..8b0ce0957d 100644
--- a/erpnext/tests/test_subcontracting.py
+++ b/erpnext/tests/test_subcontracting.py
@@ -395,6 +395,37 @@ class TestSubcontracting(unittest.TestCase):
self.assertEqual(value.qty, details.qty)
self.assertEqual(sorted(value.serial_no), sorted(details.serial_no))
+ def test_incorrect_serial_no_components_based_on_material_transfer(self):
+ '''
+ - Set backflush based on Material Transferred for Subcontract
+ - Create subcontracted PO for the item Subcontracted Item SA2.
+ - Transfer the serialized componenets to the supplier.
+ - Create purchase receipt and change the serial no which is not transferred.
+ - System should throw the error and not allowed to save the purchase receipt.
+ '''
+
+ set_backflush_based_on('Material Transferred for Subcontract')
+ item_code = 'Subcontracted Item SA2'
+ items = [{'warehouse': '_Test Warehouse - _TC', 'item_code': item_code, 'qty': 10, 'rate': 100}]
+
+ rm_items = [{'item_code': 'Subcontracted SRM Item 2', 'qty': 10}]
+
+ itemwise_details = make_stock_in_entry(rm_items=rm_items)
+ po = create_purchase_order(rm_items = items, is_subcontracted="Yes",
+ supplier_warehouse="_Test Warehouse 1 - _TC")
+
+ for d in rm_items:
+ d['po_detail'] = po.items[0].name
+
+ make_stock_transfer_entry(po_no = po.name, main_item_code=item_code,
+ rm_items=rm_items, itemwise_details=copy.deepcopy(itemwise_details))
+
+ pr1 = make_purchase_receipt(po.name)
+ pr1.save()
+ pr1.supplied_items[0].serial_no = 'ABCD'
+ self.assertRaises(frappe.ValidationError, pr1.save)
+ pr1.delete()
+
def test_partial_transfer_batch_based_on_material_transfer(self):
'''
- Set backflush based on Material Transferred for Subcontract
From f0dfea1d4748e5203ebc32d8629ffe6b261b630b Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Sun, 20 Jun 2021 10:20:35 +0530
Subject: [PATCH 254/262] fix: test case for Project Profitability report
---
.../project_profitability/test_project_profitability.py | 9 +++++++--
erpnext/public/js/controllers/buying.js | 8 ++++----
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/erpnext/projects/report/project_profitability/test_project_profitability.py b/erpnext/projects/report/project_profitability/test_project_profitability.py
index ea6bdb54ca..180926fe25 100644
--- a/erpnext/projects/report/project_profitability/test_project_profitability.py
+++ b/erpnext/projects/report/project_profitability/test_project_profitability.py
@@ -1,7 +1,7 @@
from __future__ import unicode_literals
import unittest
import frappe
-from frappe.utils import getdate, nowdate
+from frappe.utils import getdate, nowdate, add_days
from erpnext.hr.doctype.employee.test_employee import make_employee
from erpnext.projects.doctype.timesheet.test_timesheet import make_salary_structure_for_timesheet, make_timesheet
from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
@@ -16,17 +16,22 @@ class TestProjectProfitability(unittest.TestCase):
make_salary_structure_for_timesheet(emp, company='_Test Company')
self.timesheet = make_timesheet(emp, simulate = True, is_billable=1)
self.salary_slip = make_salary_slip(self.timesheet.name)
+ holidays = self.salary_slip.get_holidays_for_employee(nowdate(), nowdate())
+ if holidays:
+ frappe.db.set_value('Payroll Settings', None, 'include_holidays_in_total_working_days', 1)
+
self.salary_slip.submit()
self.sales_invoice = make_sales_invoice(self.timesheet.name, '_Test Item', '_Test Customer')
self.sales_invoice.due_date = nowdate()
self.sales_invoice.submit()
frappe.db.set_value('HR Settings', None, 'standard_working_hours', 8)
+ frappe.db.set_value('Payroll Settings', None, 'include_holidays_in_total_working_days', 0)
def test_project_profitability(self):
filters = {
'company': '_Test Company',
- 'start_date': getdate(),
+ 'start_date': add_days(getdate(), -3),
'end_date': getdate()
}
diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js
index a657f59c91..86dadd36d6 100644
--- a/erpnext/public/js/controllers/buying.js
+++ b/erpnext/public/js/controllers/buying.js
@@ -124,9 +124,9 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
this.toggle_subcontracting_fields();
super.refresh();
- },
+ }
- toggle_subcontracting_fields: function() {
+ toggle_subcontracting_fields() {
if (in_list(['Purchase Receipt', 'Purchase Invoice'], 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');
@@ -134,9 +134,9 @@ erpnext.buying.BuyingController = class BuyingController extends erpnext.Transac
this.frm.set_df_property('supplied_items', 'cannot_add_rows', 1);
this.frm.set_df_property('supplied_items', 'cannot_delete_rows', 1);
}
- },
+ }
- supplier: function() {
+ supplier() {
var me = this;
erpnext.utils.get_party_details(this.frm, null, null, function(){
me.apply_price_list();
From 99531a35e00c53943a2f613530ff23d19dc6efeb Mon Sep 17 00:00:00 2001
From: Saqib Ansari
Date: Mon, 21 Jun 2021 10:47:23 +0530
Subject: [PATCH 255/262] fix(pos): unsupported operand type -= for 'float' and
'NoneType'
---
erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +-
erpnext/public/js/controllers/transaction.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index e14f305fc5..55a5b99907 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -989,7 +989,7 @@ class SalesInvoice(SellingController):
for payment_mode in self.payments:
if skip_change_gl_entries and payment_mode.account == self.account_for_change_amount:
- payment_mode.base_amount -= self.change_amount
+ payment_mode.base_amount -= flt(self.change_amount)
if payment_mode.amount:
# POS, make payment entries
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 89fed3bf0d..0f44ad71d8 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -387,7 +387,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(this.frm.doc.scan_barcode) {
frappe.call({
- method: "erpnext.selling.page.point_of_sale.point_of_sale.search_serial_or_batch_or_barcode_number",
+ method: "erpnext.selling.page.point_of_sale.point_of_sale.search_for_serial_or_batch_or_barcode_number",
args: { search_value: this.frm.doc.scan_barcode }
}).then(r => {
const data = r && r.message;
From 7ff19ebec844e57edef9982642aefb3660012386 Mon Sep 17 00:00:00 2001
From: Saqib
Date: Mon, 21 Jun 2021 10:48:50 +0530
Subject: [PATCH 256/262] fix(pos): unsupported operand type -= for 'float' and
'NoneType' (#26096)
---
.../doctype/accounts_settings/accounts_settings.json | 5 +++--
erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +-
erpnext/public/js/controllers/transaction.js | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
index 2735b1ccee..703e93c075 100644
--- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
+++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json
@@ -257,9 +257,10 @@
},
{
"default": "1",
+ "description": "If enabled, ledger entries will be posted for change amount in POS transactions",
"fieldname": "post_change_gl_entries",
"fieldtype": "Check",
- "label": "Post Ledger Entries for Given Change"
+ "label": "Create Ledger Entries for Change Amount"
}
],
"icon": "icon-cog",
@@ -267,7 +268,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
- "modified": "2021-05-25 12:34:05.858669",
+ "modified": "2021-06-17 20:26:03.721202",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index e14f305fc5..55a5b99907 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -989,7 +989,7 @@ class SalesInvoice(SellingController):
for payment_mode in self.payments:
if skip_change_gl_entries and payment_mode.account == self.account_for_change_amount:
- payment_mode.base_amount -= self.change_amount
+ payment_mode.base_amount -= flt(self.change_amount)
if payment_mode.amount:
# POS, make payment entries
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index a29f118ef8..210237fbde 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -387,7 +387,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
if(this.frm.doc.scan_barcode) {
frappe.call({
- method: "erpnext.selling.page.point_of_sale.point_of_sale.search_serial_or_batch_or_barcode_number",
+ method: "erpnext.selling.page.point_of_sale.point_of_sale.search_for_serial_or_batch_or_barcode_number",
args: { search_value: this.frm.doc.scan_barcode }
}).then(r => {
const data = r && r.message;
From 7dae0fbe9557d1733f9e475e7dab002b125d89b9 Mon Sep 17 00:00:00 2001
From: Ankush
Date: Mon, 21 Jun 2021 11:19:47 +0530
Subject: [PATCH 257/262] fix: status indicator for delivery notes (bp #26062)
On list view `per_returned` isn't fetched i.e. `undefined` which become
0 hence the list view indicator is false.
This "computation" is already done by status updater, so relying on
doc.status is better than redefining it.
---
erpnext/stock/doctype/delivery_note/delivery_note_list.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note_list.js b/erpnext/stock/doctype/delivery_note/delivery_note_list.js
index f08125b199..0402898047 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note_list.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note_list.js
@@ -6,8 +6,8 @@ frappe.listview_settings['Delivery Note'] = {
return [__("Return"), "gray", "is_return,=,Yes"];
} else if (doc.status === "Closed") {
return [__("Closed"), "green", "status,=,Closed"];
- } else if (flt(doc.per_returned, 2) === 100) {
- return [__("Return Issued"), "grey", "per_returned,=,100"];
+ } else if (doc.status === "Return Issued") {
+ return [__("Return Issued"), "grey", "status,=,Return Issued"];
} else if (flt(doc.per_billed, 2) < 100) {
return [__("To Bill"), "orange", "per_billed,<,100"];
} else if (flt(doc.per_billed, 2) === 100) {
From 127d637b3d04a7e8d1f5758ed502bd3664561463 Mon Sep 17 00:00:00 2001
From: Afshan <33727827+AfshanKhan@users.noreply.github.com>
Date: Mon, 21 Jun 2021 11:24:45 +0530
Subject: [PATCH 258/262] fix: check for duplicate payment terms in Payment
Term Template (#25999)
---
.../doctype/payment_terms_template/payment_terms_template.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
index 80e3348d81..39627eb376 100644
--- a/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
+++ b/erpnext/accounts/doctype/payment_terms_template/payment_terms_template.py
@@ -26,7 +26,7 @@ class PaymentTermsTemplate(Document):
def check_duplicate_terms(self):
terms = []
for term in self.terms:
- term_info = (term.credit_days, term.credit_months, term.due_date_based_on)
+ term_info = (term.payment_term, term.credit_days, term.credit_months, term.due_date_based_on)
if term_info in terms:
frappe.msgprint(
_('The Payment Term at row {0} is possibly a duplicate.').format(term.idx),
From 94484d7766d69a882cba5ee179f35505a5dc78e6 Mon Sep 17 00:00:00 2001
From: Nabin Hait
Date: Mon, 21 Jun 2021 11:48:57 +0550
Subject: [PATCH 259/262] bumped to version 13.5.1
---
erpnext/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index 76e8a514d5..60c614f6f5 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '13.5.0'
+__version__ = '13.5.1'
def get_default_company(user=None):
'''Get default company for user'''
From 01faa9ca116153fd8774fd245657f920f5fc8d28 Mon Sep 17 00:00:00 2001
From: Rohit Waghchaure
Date: Mon, 21 Jun 2021 00:59:02 +0530
Subject: [PATCH 260/262] fix: rate not able to change in purchase order
---
erpnext/controllers/taxes_and_totals.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 2bb83ea7f0..56da5b71da 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -658,7 +658,13 @@ class calculate_taxes_and_totals(object):
item.margin_type = None
item.margin_rate_or_amount = 0.0
- if item.margin_type and item.margin_rate_or_amount:
+ if not item.pricing_rules and flt(item.rate) > flt(item.price_list_rate):
+ item.margin_type = "Amount"
+ item.margin_rate_or_amount = flt(item.rate - item.price_list_rate,
+ item.precision("margin_rate_or_amount"))
+ item.rate_with_margin = item.rate
+
+ elif item.margin_type and item.margin_rate_or_amount:
margin_value = item.margin_rate_or_amount if item.margin_type == 'Amount' else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
rate_with_margin = flt(item.price_list_rate) + flt(margin_value)
base_rate_with_margin = flt(rate_with_margin) * flt(self.doc.conversion_rate)
From c212d7fafda778a53d464f4cd798ae92a580c7da Mon Sep 17 00:00:00 2001
From: marination
Date: Mon, 21 Jun 2021 19:38:37 +0530
Subject: [PATCH 261/262] fix: Sort website products by weightage mentioned in
Item master
---
erpnext/shopping_cart/product_query.py | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/erpnext/shopping_cart/product_query.py b/erpnext/shopping_cart/product_query.py
index 36d446ed0f..dd94c26bc6 100644
--- a/erpnext/shopping_cart/product_query.py
+++ b/erpnext/shopping_cart/product_query.py
@@ -61,7 +61,8 @@ class ProductQuery:
],
or_filters=self.or_filters,
start=start,
- limit=self.page_length
+ limit=self.page_length,
+ order_by="weightage desc"
)
items_dict = {item.name: item for item in items}
@@ -71,7 +72,15 @@ class ProductQuery:
result = [items_dict.get(item) for item in list(set.intersection(*all_items))]
else:
- result = frappe.get_all("Item", fields=self.fields, filters=self.filters, or_filters=self.or_filters, start=start, limit=self.page_length)
+ result = frappe.get_all(
+ "Item",
+ fields=self.fields,
+ filters=self.filters,
+ or_filters=self.or_filters,
+ start=start,
+ limit=self.page_length,
+ order_by="weightage desc"
+ )
for item in result:
product_info = get_product_info_for_website(item.item_code, skip_quotation_creation=True).get('product_info')
From 943b46a759b79fd4fae9a7ada0425d7947e3f746 Mon Sep 17 00:00:00 2001
From: Subin Tom <36098155+nemesis189@users.noreply.github.com>
Date: Tue, 22 Jun 2021 14:26:36 +0530
Subject: [PATCH 262/262] fix: sql syntax error in get_project_name method
(#26145)
---
erpnext/controllers/queries.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 7bd739a6ad..4ada834425 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -315,7 +315,7 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select {fields} from `tabProject`
where
`tabProject`.status not in ("Completed", "Cancelled")
- and {cond} {match_cond} {scond}
+ and {cond} {scond} {match_cond}
order by
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
idx desc,