Fixed merge conflict
This commit is contained in:
commit
c43c95e0aa
@ -5,7 +5,7 @@ import frappe
|
|||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
__version__ = '10.1.4'
|
__version__ = '10.1.5'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
@ -145,13 +145,13 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.doc.paid_amount : frm.doc.received_amount;
|
frm.doc.paid_amount : frm.doc.received_amount;
|
||||||
|
|
||||||
frm.toggle_display("write_off_difference_amount", (frm.doc.difference_amount && frm.doc.party &&
|
frm.toggle_display("write_off_difference_amount", (frm.doc.difference_amount && frm.doc.party &&
|
||||||
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) &&
|
|
||||||
(frm.doc.total_allocated_amount > party_amount)));
|
(frm.doc.total_allocated_amount > party_amount)));
|
||||||
|
|
||||||
frm.toggle_display("set_exchange_gain_loss",
|
frm.toggle_display("set_exchange_gain_loss",
|
||||||
(frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount &&
|
(frm.doc.paid_amount && frm.doc.received_amount && frm.doc.difference_amount &&
|
||||||
(frm.doc.paid_from_account_currency != company_currency ||
|
((frm.doc.paid_from_account_currency != company_currency ||
|
||||||
frm.doc.paid_to_account_currency != company_currency)));
|
frm.doc.paid_to_account_currency != company_currency) &&
|
||||||
|
frm.doc.paid_from_account_currency != frm.doc.paid_to_account_currency)));
|
||||||
|
|
||||||
frm.refresh_fields();
|
frm.refresh_fields();
|
||||||
},
|
},
|
||||||
@ -300,7 +300,15 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.payment_type == "Pay") {
|
if(frm.doc.payment_type == "Pay") {
|
||||||
frm.events.get_outstanding_documents(frm);
|
frm.events.get_outstanding_documents(frm);
|
||||||
} else if (frm.doc.payment_type == "Receive") {
|
} else if (frm.doc.payment_type == "Receive") {
|
||||||
frm.events.received_amount(frm);
|
if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
|
||||||
|
if(frm.doc.source_exchange_rate) {
|
||||||
|
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
|
||||||
|
}
|
||||||
|
frm.set_value("received_amount", frm.doc.paid_amount);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
frm.events.received_amount(frm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -317,26 +325,31 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
},
|
},
|
||||||
callback: function(r, rt) {
|
callback: function(r, rt) {
|
||||||
if(r.message) {
|
if(r.message) {
|
||||||
frm.set_value(currency_field, r.message['account_currency']);
|
frappe.run_serially([
|
||||||
frm.set_value(balance_field, r.message['account_balance']);
|
() => frm.set_value(currency_field, r.message['account_currency']),
|
||||||
|
() => {
|
||||||
|
frm.set_value(balance_field, r.message['account_balance']);
|
||||||
|
|
||||||
if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") {
|
if(frm.doc.payment_type=="Receive" && currency_field=="paid_to_account_currency") {
|
||||||
frm.toggle_reqd(["reference_no", "reference_date"],
|
frm.toggle_reqd(["reference_no", "reference_date"],
|
||||||
(r.message['account_type'] == "Bank" ? 1 : 0));
|
(r.message['account_type'] == "Bank" ? 1 : 0));
|
||||||
if(!frm.doc.received_amount && frm.doc.paid_amount)
|
if(!frm.doc.received_amount && frm.doc.paid_amount)
|
||||||
frm.events.paid_amount(frm);
|
frm.events.paid_amount(frm);
|
||||||
} else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") {
|
} else if(frm.doc.payment_type=="Pay" && currency_field=="paid_from_account_currency") {
|
||||||
frm.toggle_reqd(["reference_no", "reference_date"],
|
frm.toggle_reqd(["reference_no", "reference_date"],
|
||||||
(r.message['account_type'] == "Bank" ? 1 : 0));
|
(r.message['account_type'] == "Bank" ? 1 : 0));
|
||||||
|
|
||||||
if(!frm.doc.paid_amount && frm.doc.received_amount)
|
if(!frm.doc.paid_amount && frm.doc.received_amount)
|
||||||
frm.events.received_amount(frm);
|
frm.events.received_amount(frm);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
if(callback_function) callback_function(frm);
|
||||||
|
|
||||||
if(callback_function) callback_function(frm);
|
frm.events.hide_unhide_fields(frm);
|
||||||
|
frm.events.set_dynamic_labels(frm);
|
||||||
frm.events.hide_unhide_fields(frm);
|
}
|
||||||
frm.events.set_dynamic_labels(frm);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -405,7 +418,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
|
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make read only if Accounts Settings doesn't allow stale rates
|
// Make read only if Accounts Settings doesn't allow stale rates
|
||||||
@ -425,7 +438,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
|
frm.set_value("base_paid_amount", frm.doc.base_received_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
}
|
}
|
||||||
frm.set_paid_amount_based_on_received_amount = false;
|
frm.set_paid_amount_based_on_received_amount = false;
|
||||||
|
|
||||||
@ -456,7 +469,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.payment_type == "Pay")
|
if(frm.doc.payment_type == "Pay")
|
||||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
||||||
else
|
else
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
|
||||||
frm.set_paid_amount_based_on_received_amount = false;
|
frm.set_paid_amount_based_on_received_amount = false;
|
||||||
},
|
},
|
||||||
@ -476,7 +489,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.payment_type == "Receive")
|
if(frm.doc.payment_type == "Receive")
|
||||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
|
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
|
||||||
else
|
else
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
get_outstanding_documents: function(frm) {
|
get_outstanding_documents: function(frm) {
|
||||||
@ -565,8 +578,11 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.references.length == 0){
|
if(frm.doc.references.length == 0){
|
||||||
frm.events.get_outstanding_documents(frm);
|
frm.events.get_outstanding_documents(frm);
|
||||||
}
|
}
|
||||||
|
if(frm.doc.payment_type == 'Internal Transfer') {
|
||||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.paid_amount);
|
||||||
|
} else {
|
||||||
|
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
allocate_party_amount_against_ref_docs: function(frm, paid_amount) {
|
allocate_party_amount_against_ref_docs: function(frm, paid_amount) {
|
||||||
@ -651,10 +667,10 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.set_value("total_allocated_amount", Math.abs(total_allocated_amount));
|
frm.set_value("total_allocated_amount", Math.abs(total_allocated_amount));
|
||||||
frm.set_value("base_total_allocated_amount", Math.abs(base_total_allocated_amount));
|
frm.set_value("base_total_allocated_amount", Math.abs(base_total_allocated_amount));
|
||||||
|
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
set_difference_amount: function(frm) {
|
set_unallocated_amount: function(frm) {
|
||||||
var unallocated_amount = 0;
|
var unallocated_amount = 0;
|
||||||
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
var total_deductions = frappe.utils.sum($.map(frm.doc.deductions || [],
|
||||||
function(d) { return flt(d.amount) }));
|
function(d) { return flt(d.amount) }));
|
||||||
@ -662,17 +678,34 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
if(frm.doc.party) {
|
if(frm.doc.party) {
|
||||||
var party_amount = frm.doc.payment_type=="Receive" ?
|
var party_amount = frm.doc.payment_type=="Receive" ?
|
||||||
frm.doc.paid_amount : frm.doc.received_amount;
|
frm.doc.paid_amount : frm.doc.received_amount;
|
||||||
|
var company_currency = frm.doc.company? frappe.get_doc(":Company", frm.doc.company).default_currency: "";
|
||||||
|
|
||||||
if(frm.doc.total_allocated_amount < party_amount) {
|
if (frm.doc.party_account_currency == company_currency) {
|
||||||
if(frm.doc.payment_type == "Receive") {
|
if(frm.doc.payment_type == "Receive" && frm.doc.total_allocated_amount <= party_amount + total_deductions) {
|
||||||
unallocated_amount = party_amount - (frm.doc.total_allocated_amount - total_deductions);
|
unallocated_amount = party_amount - (frm.doc.total_allocated_amount - total_deductions);
|
||||||
} else {
|
} else if (frm.doc.payment_type == "Pay" && frm.doc.total_allocated_amount <= party_amount - total_deductions) {
|
||||||
unallocated_amount = party_amount - (frm.doc.total_allocated_amount + total_deductions);
|
unallocated_amount = party_amount - (frm.doc.total_allocated_amount + total_deductions);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
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) {
|
||||||
|
unallocated_amount = (frm.doc.base_received_amount + total_deductions
|
||||||
|
- 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) {
|
||||||
|
unallocated_amount = (frm.doc.base_paid_amount - (total_deductions
|
||||||
|
+ frm.doc.base_total_allocated_amount)) / frm.doc.target_exchange_rate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
frm.set_value("unallocated_amount", unallocated_amount);
|
frm.set_value("unallocated_amount", unallocated_amount);
|
||||||
|
frm.trigger("set_difference_amount");
|
||||||
|
},
|
||||||
|
|
||||||
|
set_difference_amount: function(frm) {
|
||||||
var difference_amount = 0;
|
var difference_amount = 0;
|
||||||
var base_unallocated_amount = flt(frm.doc.unallocated_amount) *
|
var base_unallocated_amount = flt(frm.doc.unallocated_amount) *
|
||||||
(frm.doc.payment_type=="Receive" ? frm.doc.source_exchange_rate : frm.doc.target_exchange_rate);
|
(frm.doc.payment_type=="Receive" ? frm.doc.source_exchange_rate : frm.doc.target_exchange_rate);
|
||||||
@ -687,11 +720,18 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
difference_amount = flt(frm.doc.base_paid_amount) - flt(frm.doc.base_received_amount);
|
difference_amount = flt(frm.doc.base_paid_amount) - flt(frm.doc.base_received_amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.events.hide_unhide_fields(frm);
|
frm.events.hide_unhide_fields(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
unallocated_amount: function(frm) {
|
||||||
|
frm.trigger("set_difference_amount");
|
||||||
|
},
|
||||||
|
|
||||||
check_mandatory_to_fetch: function(frm) {
|
check_mandatory_to_fetch: function(frm) {
|
||||||
$.each(["Company", "Party Type", "Party", "payment_type"], function(i, field) {
|
$.each(["Company", "Party Type", "Party", "payment_type"], function(i, field) {
|
||||||
if(!frm.doc[frappe.model.scrub(field)]) {
|
if(!frm.doc[frappe.model.scrub(field)]) {
|
||||||
@ -771,7 +811,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
row.amount = flt(row.amount) + flt(frm.doc.difference_amount);
|
row.amount = flt(row.amount) + flt(frm.doc.difference_amount);
|
||||||
refresh_field("deductions");
|
refresh_field("deductions");
|
||||||
|
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -818,10 +858,10 @@ frappe.ui.form.on('Payment Entry Reference', {
|
|||||||
|
|
||||||
frappe.ui.form.on('Payment Entry Deduction', {
|
frappe.ui.form.on('Payment Entry Deduction', {
|
||||||
amount: function(frm) {
|
amount: function(frm) {
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
deductions_remove: function(frm) {
|
deductions_remove: function(frm) {
|
||||||
frm.events.set_difference_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -71,6 +72,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 1,
|
"set_only_once": 1,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -102,6 +104,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -131,6 +134,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -162,6 +166,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -193,6 +198,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -224,6 +230,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -255,6 +262,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -288,6 +296,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -320,6 +329,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -349,6 +359,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -381,6 +392,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -411,6 +423,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -442,6 +455,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -474,6 +488,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -506,6 +521,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -538,6 +554,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -567,6 +584,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -599,6 +617,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -631,6 +650,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -663,6 +683,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -695,6 +716,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -727,6 +749,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -758,6 +781,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -790,6 +814,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -819,6 +844,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -851,6 +877,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -882,6 +909,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -914,6 +942,7 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -946,6 +975,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -978,6 +1008,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1010,6 +1041,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1041,6 +1073,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1072,6 +1105,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1104,6 +1138,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1134,6 +1169,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1163,6 +1199,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1188,12 +1225,13 @@
|
|||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 0,
|
||||||
"remember_last_selected_value": 0,
|
"remember_last_selected_value": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1226,6 +1264,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1257,6 +1296,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1289,6 +1329,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1320,6 +1361,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1350,6 +1392,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1381,6 +1424,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1410,6 +1454,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1441,6 +1486,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1472,6 +1518,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1504,6 +1551,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1536,6 +1584,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1566,6 +1615,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1595,6 +1645,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1626,6 +1677,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1657,6 +1709,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1687,6 +1740,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1718,6 +1772,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1748,6 +1803,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1778,6 +1834,7 @@
|
|||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -1791,7 +1848,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-01-11 14:43:03.336327",
|
"modified": "2018-02-19 16:58:23.899015",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Entry",
|
"name": "Payment Entry",
|
||||||
|
@ -287,17 +287,30 @@ class PaymentEntry(AccountsController):
|
|||||||
self.base_total_allocated_amount = abs(base_total_allocated_amount)
|
self.base_total_allocated_amount = abs(base_total_allocated_amount)
|
||||||
|
|
||||||
def set_unallocated_amount(self):
|
def set_unallocated_amount(self):
|
||||||
self.unallocated_amount = 0;
|
self.unallocated_amount = 0
|
||||||
if self.party:
|
if self.party:
|
||||||
party_amount = self.paid_amount if self.payment_type=="Receive" else self.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")])
|
||||||
|
|
||||||
if self.total_allocated_amount < party_amount:
|
if self.party_account_currency == self.company_currency:
|
||||||
if self.payment_type == "Receive":
|
if self.payment_type == "Receive" \
|
||||||
self.unallocated_amount = party_amount - (self.total_allocated_amount - total_deductions)
|
and self.total_allocated_amount <= self.paid_amount + total_deductions:
|
||||||
else:
|
self.unallocated_amount = self.paid_amount - \
|
||||||
self.unallocated_amount = party_amount - (self.total_allocated_amount + total_deductions)
|
(self.total_allocated_amount - total_deductions)
|
||||||
|
elif self.payment_type == "Pay" \
|
||||||
|
and self.total_allocated_amount <= self.received_amount - total_deductions:
|
||||||
|
self.unallocated_amount = self.received_amount - \
|
||||||
|
(self.total_allocated_amount + total_deductions)
|
||||||
|
else:
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
self.unallocated_amount = (self.base_paid_amount - (total_deductions +
|
||||||
|
self.base_total_allocated_amount)) / self.target_exchange_rate
|
||||||
|
|
||||||
def set_difference_amount(self):
|
def set_difference_amount(self):
|
||||||
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
base_unallocated_amount = flt(self.unallocated_amount) * (flt(self.source_exchange_rate)
|
||||||
|
@ -141,7 +141,6 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
def test_payment_entry_retrieves_last_exchange_rate(self):
|
def test_payment_entry_retrieves_last_exchange_rate(self):
|
||||||
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records, save_new_records
|
from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records, save_new_records
|
||||||
|
|
||||||
test_records = test_records
|
|
||||||
save_new_records(test_records)
|
save_new_records(test_records)
|
||||||
|
|
||||||
pe = frappe.new_doc("Payment Entry")
|
pe = frappe.new_doc("Payment Entry")
|
||||||
@ -151,6 +150,7 @@ class TestPaymentEntry(unittest.TestCase):
|
|||||||
pe.paid_from = "_Test Bank USD - _TC"
|
pe.paid_from = "_Test Bank USD - _TC"
|
||||||
pe.paid_to = "_Test Bank - _TC"
|
pe.paid_to = "_Test Bank - _TC"
|
||||||
pe.paid_amount = 100
|
pe.paid_amount = 100
|
||||||
|
pe.received_amount = 100
|
||||||
pe.reference_no = "3"
|
pe.reference_no = "3"
|
||||||
pe.reference_date = "2016-01-10"
|
pe.reference_date = "2016-01-10"
|
||||||
pe.party_type = "Supplier"
|
pe.party_type = "Supplier"
|
||||||
|
@ -98,7 +98,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-11 03:28:03.420683",
|
"modified": "2018-02-21 03:28:03.420683",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Entry Deduction",
|
"name": "Payment Entry Deduction",
|
||||||
|
@ -63,10 +63,8 @@ class TestPaymentRequest(unittest.TestCase):
|
|||||||
def test_payment_entry(self):
|
def test_payment_entry(self):
|
||||||
frappe.db.set_value("Company", "_Test Company",
|
frappe.db.set_value("Company", "_Test Company",
|
||||||
"exchange_gain_loss_account", "_Test Exchange Gain/Loss - _TC")
|
"exchange_gain_loss_account", "_Test Exchange Gain/Loss - _TC")
|
||||||
frappe.db.set_value("Company", "_Test Company",
|
frappe.db.set_value("Company", "_Test Company", "write_off_account", "_Test Write Off - _TC")
|
||||||
"write_off_account", "_Test Write Off - _TC")
|
frappe.db.set_value("Company", "_Test Company", "cost_center", "_Test Cost Center - _TC")
|
||||||
frappe.db.set_value("Company", "_Test Company",
|
|
||||||
"cost_center", "_Test Cost Center - _TC")
|
|
||||||
|
|
||||||
so_inr = make_sales_order(currency="INR")
|
so_inr = make_sales_order(currency="INR")
|
||||||
pr = make_payment_request(dt="Sales Order", dn=so_inr.name, recipient_id="saurabh@erpnext.com",
|
pr = make_payment_request(dt="Sales Order", dn=so_inr.name, recipient_id="saurabh@erpnext.com",
|
||||||
|
@ -106,7 +106,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
on_submit: function(doc, dt, dn) {
|
on_submit: function(doc, dt, dn) {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
if (frappe.get_route()[0] != 'Sales Invoice') {
|
if (frappe.get_route()[0] != 'Form') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
'target_parent_field': 'per_ordered',
|
'target_parent_field': 'per_ordered',
|
||||||
'target_ref_field': 'stock_qty',
|
'target_ref_field': 'stock_qty',
|
||||||
'source_field': 'stock_qty',
|
'source_field': 'stock_qty',
|
||||||
'percent_join_field': 'material_request',
|
'percent_join_field': 'material_request'
|
||||||
'overflow_type': 'order'
|
|
||||||
}]
|
}]
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
@ -242,12 +241,16 @@ class PurchaseOrder(BuyingController):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def update_status_updater(self):
|
def update_status_updater(self):
|
||||||
self.status_updater[0].update({
|
self.status_updater.append({
|
||||||
"target_parent_dt": "Sales Order",
|
'source_dt': 'Purchase Order Item',
|
||||||
"target_dt": "Sales Order Item",
|
'target_dt': 'Sales Order Item',
|
||||||
'target_field': 'ordered_qty',
|
'target_field': 'ordered_qty',
|
||||||
"join_field": "sales_order_item",
|
'target_parent_dt': 'Sales Order',
|
||||||
"target_parent_field": ''
|
'target_parent_field': '',
|
||||||
|
'join_field': 'sales_order_item',
|
||||||
|
'source_dt': 'Purchase Order Item',
|
||||||
|
'target_ref_field': 'stock_qty',
|
||||||
|
'source_field': 'stock_qty'
|
||||||
})
|
})
|
||||||
|
|
||||||
def update_delivered_qty_in_sales_order(self):
|
def update_delivered_qty_in_sales_order(self):
|
||||||
|
@ -666,6 +666,8 @@ class AccountsController(TransactionBase):
|
|||||||
self.remove(item)
|
self.remove(item)
|
||||||
|
|
||||||
def set_payment_schedule(self):
|
def set_payment_schedule(self):
|
||||||
|
if self.doctype == 'Sales Invoice' and self.is_pos: return
|
||||||
|
|
||||||
posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date")
|
posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date")
|
||||||
date = self.get("due_date")
|
date = self.get("due_date")
|
||||||
due_date = date or posting_date
|
due_date = date or posting_date
|
||||||
@ -695,6 +697,8 @@ class AccountsController(TransactionBase):
|
|||||||
dates = []
|
dates = []
|
||||||
li = []
|
li = []
|
||||||
|
|
||||||
|
if self.doctype == 'Sales Invoice' and self.is_pos: return
|
||||||
|
|
||||||
for d in self.get("payment_schedule"):
|
for d in self.get("payment_schedule"):
|
||||||
if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date):
|
if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date):
|
||||||
frappe.throw(_("Row {0}: Due Date cannot be before posting date").format(d.idx))
|
frappe.throw(_("Row {0}: Due Date cannot be before posting date").format(d.idx))
|
||||||
@ -708,6 +712,8 @@ class AccountsController(TransactionBase):
|
|||||||
.format(list=duplicates))
|
.format(list=duplicates))
|
||||||
|
|
||||||
def validate_payment_schedule_amount(self):
|
def validate_payment_schedule_amount(self):
|
||||||
|
if self.doctype == 'Sales Invoice' and self.is_pos: return
|
||||||
|
|
||||||
if self.get("payment_schedule"):
|
if self.get("payment_schedule"):
|
||||||
total = 0
|
total = 0
|
||||||
for d in self.get("payment_schedule"):
|
for d in self.get("payment_schedule"):
|
||||||
|
@ -53,8 +53,9 @@ def validate_returned_items(doc):
|
|||||||
|
|
||||||
valid_items = frappe._dict()
|
valid_items = frappe._dict()
|
||||||
|
|
||||||
select_fields = "item_code, qty, rate, parenttype" if doc.doctype=="Purchase Invoice" \
|
select_fields = "item_code, qty, stock_qty, rate, parenttype, conversion_factor"
|
||||||
else "item_code, qty, rate, serial_no, batch_no, parenttype"
|
if doc.doctype != 'Purchase Invoice':
|
||||||
|
select_fields += ",serial_no, batch_no"
|
||||||
|
|
||||||
if doc.doctype in ['Purchase Invoice', 'Purchase Receipt']:
|
if doc.doctype in ['Purchase Invoice', 'Purchase Receipt']:
|
||||||
select_fields += ",rejected_qty, received_qty"
|
select_fields += ",rejected_qty, received_qty"
|
||||||
@ -111,7 +112,7 @@ def validate_returned_items(doc):
|
|||||||
frappe.throw(_("Atleast one item should be entered with negative quantity in return document"))
|
frappe.throw(_("Atleast one item should be entered with negative quantity in return document"))
|
||||||
|
|
||||||
def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||||
fields = ['qty']
|
fields = ['stock_qty']
|
||||||
if doc.doctype in ['Purchase Receipt', 'Purchase Invoice']:
|
if doc.doctype in ['Purchase Receipt', 'Purchase Invoice']:
|
||||||
fields.extend(['received_qty', 'rejected_qty'])
|
fields.extend(['received_qty', 'rejected_qty'])
|
||||||
|
|
||||||
@ -119,16 +120,19 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
|||||||
|
|
||||||
for column in fields:
|
for column in fields:
|
||||||
returned_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0
|
returned_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0
|
||||||
reference_qty = ref.get(column)
|
reference_qty = (ref.get(column) if column == 'stock_qty'
|
||||||
|
else ref.get(column) * ref.get("conversion_factor", 1.0))
|
||||||
|
|
||||||
max_returnable_qty = flt(reference_qty) - returned_qty
|
max_returnable_qty = flt(reference_qty) - returned_qty
|
||||||
label = column.replace('_', ' ').title()
|
label = column.replace('_', ' ').title()
|
||||||
|
|
||||||
if reference_qty:
|
if reference_qty:
|
||||||
if flt(args.get(column)) > 0:
|
if flt(args.get(column)) > 0:
|
||||||
frappe.throw(_("{0} must be negative in return document").format(label))
|
frappe.throw(_("{0} must be negative in return document").format(label))
|
||||||
elif returned_qty >= reference_qty and args.get(column):
|
elif returned_qty >= reference_qty and args.get(column):
|
||||||
frappe.throw(_("Item {0} has already been returned")
|
frappe.throw(_("Item {0} has already been returned")
|
||||||
.format(args.item_code), StockOverReturnError)
|
.format(args.item_code), StockOverReturnError)
|
||||||
elif abs(args.get(column)) > max_returnable_qty:
|
elif (abs(args.get(column)) * args.get("conversion_factor", 1.0)) > max_returnable_qty:
|
||||||
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
|
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
|
||||||
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
|
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
|
||||||
|
|
||||||
@ -138,6 +142,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
|
|||||||
valid_items.setdefault(ref_item_row.item_code, frappe._dict({
|
valid_items.setdefault(ref_item_row.item_code, frappe._dict({
|
||||||
"qty": 0,
|
"qty": 0,
|
||||||
"rate": 0,
|
"rate": 0,
|
||||||
|
"stock_qty": 0,
|
||||||
"rejected_qty": 0,
|
"rejected_qty": 0,
|
||||||
"received_qty": 0,
|
"received_qty": 0,
|
||||||
"serial_no": [],
|
"serial_no": [],
|
||||||
@ -145,6 +150,7 @@ def get_ref_item_dict(valid_items, ref_item_row):
|
|||||||
}))
|
}))
|
||||||
item_dict = valid_items[ref_item_row.item_code]
|
item_dict = valid_items[ref_item_row.item_code]
|
||||||
item_dict["qty"] += ref_item_row.qty
|
item_dict["qty"] += ref_item_row.qty
|
||||||
|
item_dict["stock_qty"] += ref_item_row.get('stock_qty', 0)
|
||||||
if ref_item_row.get("rate", 0) > item_dict["rate"]:
|
if ref_item_row.get("rate", 0) > item_dict["rate"]:
|
||||||
item_dict["rate"] = ref_item_row.get("rate", 0)
|
item_dict["rate"] = ref_item_row.get("rate", 0)
|
||||||
|
|
||||||
@ -161,9 +167,10 @@ def get_ref_item_dict(valid_items, ref_item_row):
|
|||||||
return valid_items
|
return valid_items
|
||||||
|
|
||||||
def get_already_returned_items(doc):
|
def get_already_returned_items(doc):
|
||||||
column = 'child.item_code, sum(abs(child.qty)) as qty'
|
column = 'child.item_code, sum(abs(child.qty)) as qty, sum(abs(child.stock_qty)) as stock_qty'
|
||||||
if doc.doctype in ['Purchase Invoice', 'Purchase Receipt']:
|
if doc.doctype in ['Purchase Invoice', 'Purchase Receipt']:
|
||||||
column += ', sum(abs(child.rejected_qty)) as rejected_qty, sum(abs(child.received_qty)) as received_qty'
|
column += """, sum(abs(child.rejected_qty) * child.conversion_factor) as rejected_qty,
|
||||||
|
sum(abs(child.received_qty) * child.conversion_factor) as received_qty"""
|
||||||
|
|
||||||
data = frappe.db.sql("""
|
data = frappe.db.sql("""
|
||||||
select {0}
|
select {0}
|
||||||
@ -180,6 +187,7 @@ def get_already_returned_items(doc):
|
|||||||
for d in data:
|
for d in data:
|
||||||
items.setdefault(d.item_code, frappe._dict({
|
items.setdefault(d.item_code, frappe._dict({
|
||||||
"qty": d.get("qty"),
|
"qty": d.get("qty"),
|
||||||
|
"stock_qty": d.get("stock_qty"),
|
||||||
"received_qty": d.get("received_qty"),
|
"received_qty": d.get("received_qty"),
|
||||||
"rejected_qty": d.get("rejected_qty")
|
"rejected_qty": d.get("rejected_qty")
|
||||||
}))
|
}))
|
||||||
|
@ -38,9 +38,6 @@ frappe.ui.form.on('Fee Schedule', {
|
|||||||
if (data.reload && data.reload === 1) {
|
if (data.reload && data.reload === 1) {
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
}
|
}
|
||||||
if (data.progress && data.progress === "0") {
|
|
||||||
frappe.msgprint(__("Fee records will be created in the background. In case of any error the error message will be updated in the Schedule."));
|
|
||||||
}
|
|
||||||
if (data.progress) {
|
if (data.progress) {
|
||||||
let progress_bar = $(cur_frm.dashboard.progress_area).find(".progress-bar");
|
let progress_bar = $(cur_frm.dashboard.progress_area).find(".progress-bar");
|
||||||
if (progress_bar) {
|
if (progress_bar) {
|
||||||
@ -74,6 +71,15 @@ frappe.ui.form.on('Fee Schedule', {
|
|||||||
});
|
});
|
||||||
}, "fa fa-play", "btn-success");
|
}, "fa fa-play", "btn-success");
|
||||||
}
|
}
|
||||||
|
if (frm.doc.fee_creation_status == "Successful") {
|
||||||
|
frm.add_custom_button(__("View Fees Records"), function() {
|
||||||
|
frappe.route_options = {
|
||||||
|
fee_schedule: frm.doc.name
|
||||||
|
};
|
||||||
|
frappe.set_route("List", "Fees");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
fee_structure: function(frm) {
|
fee_structure: function(frm) {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"beta": 1,
|
"beta": 0,
|
||||||
"creation": "2017-07-18 15:21:21.527136",
|
"creation": "2017-07-18 15:21:21.527136",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -1029,7 +1029,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-12-04 13:08:27.727709",
|
"modified": "2018-02-26 13:59:36.560780",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Education",
|
"module": "Education",
|
||||||
"name": "Fee Schedule",
|
"name": "Fee Schedule",
|
||||||
|
@ -56,8 +56,15 @@ class FeeSchedule(Document):
|
|||||||
self.db_set("fee_creation_status", "In Process")
|
self.db_set("fee_creation_status", "In Process")
|
||||||
frappe.publish_realtime("fee_schedule_progress",
|
frappe.publish_realtime("fee_schedule_progress",
|
||||||
{"progress": "0", "reload": 1}, user=frappe.session.user)
|
{"progress": "0", "reload": 1}, user=frappe.session.user)
|
||||||
enqueue(generate_fee, queue='default', timeout=6000, event='generate_fee',
|
|
||||||
fee_schedule=self.name)
|
total_records = sum([int(d.total_students) for d in self.student_groups])
|
||||||
|
if total_records > 10:
|
||||||
|
frappe.msgprint(_('''Fee records will be created in the background.
|
||||||
|
In case of any error the error message will be updated in the Schedule.'''))
|
||||||
|
enqueue(generate_fee, queue='default', timeout=6000, event='generate_fee',
|
||||||
|
fee_schedule=self.name)
|
||||||
|
else:
|
||||||
|
generate_fee(self.name)
|
||||||
|
|
||||||
def generate_fee(fee_schedule):
|
def generate_fee(fee_schedule):
|
||||||
doc = frappe.get_doc("Fee Schedule", fee_schedule)
|
doc = frappe.get_doc("Fee Schedule", fee_schedule)
|
||||||
@ -69,10 +76,7 @@ def generate_fee(fee_schedule):
|
|||||||
frappe.throw(_("Please setup Students under Student Groups"))
|
frappe.throw(_("Please setup Students under Student Groups"))
|
||||||
|
|
||||||
for d in doc.student_groups:
|
for d in doc.student_groups:
|
||||||
students = frappe.db.sql(""" select sg.program, sg.batch, sgs.student, sgs.student_name
|
students = get_students(d.student_group, doc.academic_year, doc.academic_term, doc.student_category)
|
||||||
from `tabStudent Group` sg, `tabStudent Group Student` sgs
|
|
||||||
where sg.name=%s and sg.name=sgs.parent and sgs.active=1""", d.student_group, as_dict=1)
|
|
||||||
|
|
||||||
for student in students:
|
for student in students:
|
||||||
try:
|
try:
|
||||||
fees_doc = get_mapped_doc("Fee Schedule", fee_schedule, {
|
fees_doc = get_mapped_doc("Fee Schedule", fee_schedule, {
|
||||||
@ -86,7 +90,7 @@ def generate_fee(fee_schedule):
|
|||||||
fees_doc.student = student.student
|
fees_doc.student = student.student
|
||||||
fees_doc.student_name = student.student_name
|
fees_doc.student_name = student.student_name
|
||||||
fees_doc.program = student.program
|
fees_doc.program = student.program
|
||||||
fees_doc.student_batch = student.batch
|
fees_doc.student_batch = student.student_batch_name
|
||||||
fees_doc.send_payment_request = doc.send_email
|
fees_doc.send_payment_request = doc.send_email
|
||||||
fees_doc.save()
|
fees_doc.save()
|
||||||
fees_doc.submit()
|
fees_doc.submit()
|
||||||
@ -110,6 +114,30 @@ def generate_fee(fee_schedule):
|
|||||||
{"progress": "100", "reload": 1}, user=frappe.session.user)
|
{"progress": "100", "reload": 1}, user=frappe.session.user)
|
||||||
|
|
||||||
|
|
||||||
|
def get_students(student_group, academic_year, academic_term=None, student_category=None):
|
||||||
|
conditions = ""
|
||||||
|
if student_category:
|
||||||
|
conditions = " and pe.student_category='{}'".format(frappe.db.escape(student_category))
|
||||||
|
if academic_term:
|
||||||
|
conditions = " and pe.academic_term='{}'".format(frappe.db.escape(academic_term))
|
||||||
|
|
||||||
|
students = frappe.db.sql("""
|
||||||
|
select pe.student, pe.student_name, pe.program, pe.student_batch_name
|
||||||
|
from `tabStudent Group Student` sgs, `tabProgram Enrollment` pe
|
||||||
|
where
|
||||||
|
pe.student = sgs.student and pe.academic_year = %s
|
||||||
|
and sgs.parent = %s and sgs.active = 1
|
||||||
|
{conditions}
|
||||||
|
""".format(conditions=conditions), (academic_year, student_group), as_dict=1)
|
||||||
|
return students
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_total_students(student_group, academic_year, academic_term=None, student_category=None):
|
||||||
|
total_students = get_students(student_group, academic_year, academic_term, student_category)
|
||||||
|
return len(total_students)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_fee_structure(source_name,target_doc=None):
|
def get_fee_structure(source_name,target_doc=None):
|
||||||
fee_request = get_mapped_doc("Fee Structure", source_name,
|
fee_request = get_mapped_doc("Fee Structure", source_name,
|
||||||
@ -117,23 +145,3 @@ def get_fee_structure(source_name,target_doc=None):
|
|||||||
"doctype": "Fee Schedule"
|
"doctype": "Fee Schedule"
|
||||||
}}, ignore_permissions=True)
|
}}, ignore_permissions=True)
|
||||||
return fee_request
|
return fee_request
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_total_students(student_group, academic_year, academic_term=None, student_category=None):
|
|
||||||
conditions = ""
|
|
||||||
if student_category:
|
|
||||||
conditions = " and pe.student_category='{}'".format(frappe.db.escape(student_category))
|
|
||||||
if academic_term:
|
|
||||||
conditions = " and pe.academic_term='{}'".format(frappe.db.escape(academic_term))
|
|
||||||
|
|
||||||
|
|
||||||
return frappe.db.sql("""
|
|
||||||
select count(pe.name)
|
|
||||||
from `tabStudent Group Student` sgs, `tabProgram Enrollment` pe
|
|
||||||
where
|
|
||||||
pe.student = sgs.student
|
|
||||||
and pe.academic_year = %s
|
|
||||||
and sgs.parent = %s
|
|
||||||
and sgs.active = 1
|
|
||||||
{conditions}
|
|
||||||
""".format(conditions=conditions), (academic_year, student_group))[0][0]
|
|
||||||
|
@ -81,7 +81,7 @@ frappe.ui.form.on('Employee',{
|
|||||||
}
|
}
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.hr.doctype.employee.employee.create_user",
|
method: "erpnext.hr.doctype.employee.employee.create_user",
|
||||||
args: { employee: cur_frm.doc.name },
|
args: { employee: frm.doc.name, email: frm.doc.prefered_email },
|
||||||
callback: function(r)
|
callback: function(r)
|
||||||
{
|
{
|
||||||
frm.set_value("user_id", r.message)
|
frm.set_value("user_id", r.message)
|
||||||
|
@ -263,7 +263,7 @@ def deactivate_sales_person(status = None, employee = None):
|
|||||||
frappe.db.set_value("Sales Person", sales_person, "enabled", 0)
|
frappe.db.set_value("Sales Person", sales_person, "enabled", 0)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_user(employee, user = None):
|
def create_user(employee, user = None, email=None):
|
||||||
emp = frappe.get_doc("Employee", employee)
|
emp = frappe.get_doc("Employee", employee)
|
||||||
|
|
||||||
employee_name = emp.employee_name.split(" ")
|
employee_name = emp.employee_name.split(" ")
|
||||||
@ -277,6 +277,9 @@ def create_user(employee, user = None):
|
|||||||
|
|
||||||
first_name = employee_name[0]
|
first_name = employee_name[0]
|
||||||
|
|
||||||
|
if email:
|
||||||
|
emp.prefered_email = email
|
||||||
|
|
||||||
user = frappe.new_doc("User")
|
user = frappe.new_doc("User")
|
||||||
user.update({
|
user.update({
|
||||||
"name": emp.employee_name,
|
"name": emp.employee_name,
|
||||||
|
@ -41,10 +41,12 @@ class ExpenseClaim(AccountsController):
|
|||||||
}[cstr(self.docstatus or 0)]
|
}[cstr(self.docstatus or 0)]
|
||||||
|
|
||||||
paid_amount = flt(self.total_amount_reimbursed) + flt(self.total_advance_amount)
|
paid_amount = flt(self.total_amount_reimbursed) + flt(self.total_advance_amount)
|
||||||
if self.total_sanctioned_amount > 0 and self.total_sanctioned_amount == paid_amount\
|
|
||||||
|
if (self.is_paid or (flt(self.total_sanctioned_amount) > 0
|
||||||
|
and flt(self.total_sanctioned_amount) == paid_amount)) \
|
||||||
and self.docstatus == 1:
|
and self.docstatus == 1:
|
||||||
self.status = "Paid"
|
self.status = "Paid"
|
||||||
elif self.total_sanctioned_amount > 0 and self.docstatus == 1:
|
elif flt(self.total_sanctioned_amount) > 0 and self.docstatus == 1:
|
||||||
self.status = "Unpaid"
|
self.status = "Unpaid"
|
||||||
|
|
||||||
def set_payable_account(self):
|
def set_payable_account(self):
|
||||||
|
@ -175,7 +175,7 @@ class PayrollEntry(Document):
|
|||||||
Get loan details from submitted salary slip based on selected criteria
|
Get loan details from submitted salary slip based on selected criteria
|
||||||
"""
|
"""
|
||||||
cond = self.get_filter_condition()
|
cond = self.get_filter_condition()
|
||||||
return frappe.db.sql(""" select eld.employee_loan_account,
|
return frappe.db.sql(""" select eld.employee_loan_account, eld.employee_loan,
|
||||||
eld.interest_income_account, eld.principal_amount, eld.interest_amount, eld.total_payment
|
eld.interest_income_account, eld.principal_amount, eld.interest_amount, eld.total_payment
|
||||||
from
|
from
|
||||||
`tabSalary Slip` t1, `tabSalary Slip Loan` eld
|
`tabSalary Slip` t1, `tabSalary Slip Loan` eld
|
||||||
@ -283,7 +283,12 @@ class PayrollEntry(Document):
|
|||||||
"account": data.employee_loan_account,
|
"account": data.employee_loan_account,
|
||||||
"credit_in_account_currency": data.principal_amount
|
"credit_in_account_currency": data.principal_amount
|
||||||
})
|
})
|
||||||
accounts.append({
|
|
||||||
|
if data.interest_amount and not data.interest_income_account:
|
||||||
|
frappe.throw(_("Select interest income account in employee loan {0}").format(data.employee_loan))
|
||||||
|
|
||||||
|
if data.interest_income_account and data.interest_amount:
|
||||||
|
accounts.append({
|
||||||
"account": data.interest_income_account,
|
"account": data.interest_income_account,
|
||||||
"credit_in_account_currency": data.interest_amount,
|
"credit_in_account_currency": data.interest_amount,
|
||||||
"cost_center": self.cost_center,
|
"cost_center": self.cost_center,
|
||||||
|
@ -156,9 +156,10 @@ class SalarySlip(TransactionBase):
|
|||||||
})
|
})
|
||||||
|
|
||||||
def get_date_details(self):
|
def get_date_details(self):
|
||||||
date_details = get_start_end_dates(self.payroll_frequency, self.start_date or self.posting_date)
|
if not self.end_date:
|
||||||
self.start_date = date_details.start_date
|
date_details = get_start_end_dates(self.payroll_frequency, self.start_date or self.posting_date)
|
||||||
self.end_date = date_details.end_date
|
self.start_date = date_details.start_date
|
||||||
|
self.end_date = date_details.end_date
|
||||||
|
|
||||||
def check_sal_struct(self, joining_date, relieving_date):
|
def check_sal_struct(self, joining_date, relieving_date):
|
||||||
cond = ''
|
cond = ''
|
||||||
|
@ -51,7 +51,6 @@ class BOM(WebsiteGenerator):
|
|||||||
self.validate_currency()
|
self.validate_currency()
|
||||||
self.set_conversion_rate()
|
self.set_conversion_rate()
|
||||||
self.validate_uom_is_interger()
|
self.validate_uom_is_interger()
|
||||||
self.update_stock_qty()
|
|
||||||
self.set_bom_material_details()
|
self.set_bom_material_details()
|
||||||
self.validate_materials()
|
self.validate_materials()
|
||||||
self.validate_operations()
|
self.validate_operations()
|
||||||
@ -251,14 +250,12 @@ class BOM(WebsiteGenerator):
|
|||||||
set_default(self, "item")
|
set_default(self, "item")
|
||||||
item = frappe.get_doc("Item", self.item)
|
item = frappe.get_doc("Item", self.item)
|
||||||
if item.default_bom != self.name:
|
if item.default_bom != self.name:
|
||||||
item.default_bom = self.name
|
frappe.db.set_value('Item', self.item, 'default_bom', self.name)
|
||||||
item.save(ignore_permissions = True)
|
|
||||||
else:
|
else:
|
||||||
frappe.db.set(self, "is_default", 0)
|
frappe.db.set(self, "is_default", 0)
|
||||||
item = frappe.get_doc("Item", self.item)
|
item = frappe.get_doc("Item", self.item)
|
||||||
if item.default_bom == self.name:
|
if item.default_bom == self.name:
|
||||||
item.default_bom = None
|
frappe.db.set_value('Item', self.item, 'default_bom', None)
|
||||||
item.save(ignore_permissions = True)
|
|
||||||
|
|
||||||
def clear_operations(self):
|
def clear_operations(self):
|
||||||
if not self.with_operations:
|
if not self.with_operations:
|
||||||
@ -295,6 +292,8 @@ class BOM(WebsiteGenerator):
|
|||||||
m.uom = m.stock_uom
|
m.uom = m.stock_uom
|
||||||
m.qty = m.stock_qty
|
m.qty = m.stock_qty
|
||||||
|
|
||||||
|
m.db_update()
|
||||||
|
|
||||||
def validate_uom_is_interger(self):
|
def validate_uom_is_interger(self):
|
||||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||||
validate_uom_is_integer(self, "uom", "qty", "BOM Item")
|
validate_uom_is_integer(self, "uom", "qty", "BOM Item")
|
||||||
@ -337,19 +336,23 @@ class BOM(WebsiteGenerator):
|
|||||||
|
|
||||||
def check_recursion(self):
|
def check_recursion(self):
|
||||||
""" Check whether recursion occurs in any bom"""
|
""" Check whether recursion occurs in any bom"""
|
||||||
|
bom_list = self.traverse_tree()
|
||||||
|
bom_nos = frappe.get_all('BOM Item', fields=["bom_no"],
|
||||||
|
filters={'parent': ('in', bom_list), 'parenttype': 'BOM'})
|
||||||
|
|
||||||
check_list = [['parent', 'bom_no', 'parent'], ['bom_no', 'parent', 'child']]
|
raise_exception = False
|
||||||
for d in check_list:
|
if bom_nos and self.name in [d.bom_no for d in bom_nos]:
|
||||||
bom_list, count = [self.name], 0
|
raise_exception = True
|
||||||
while (len(bom_list) > count ):
|
|
||||||
boms = frappe.db.sql(" select %s from `tabBOM Item` where %s = %s and parenttype='BOM'" %
|
if not raise_exception:
|
||||||
(d[0], d[1], '%s'), cstr(bom_list[count]))
|
bom_nos = frappe.get_all('BOM Item', fields=["parent"],
|
||||||
count = count + 1
|
filters={'bom_no': self.name, 'parenttype': 'BOM'})
|
||||||
for b in boms:
|
|
||||||
if b[0] == self.name:
|
if self.name in [d.parent for d in bom_nos]:
|
||||||
frappe.throw(_("BOM recursion: {0} cannot be parent or child of {2}").format(b[0], self.name))
|
raise_exception = True
|
||||||
if b[0]:
|
|
||||||
bom_list.append(b[0])
|
if raise_exception:
|
||||||
|
frappe.throw(_("BOM recursion: {0} cannot be parent or child of {2}").format(self.name, self.name))
|
||||||
|
|
||||||
def update_cost_and_exploded_items(self, bom_list=[]):
|
def update_cost_and_exploded_items(self, bom_list=[]):
|
||||||
bom_list = self.traverse_tree(bom_list)
|
bom_list = self.traverse_tree(bom_list)
|
||||||
|
@ -60,5 +60,14 @@ frappe.treeview_settings["BOM"] = {
|
|||||||
condition: 'frappe.boot.user.can_create.indexOf("BOM") !== -1'
|
condition: 'frappe.boot.user.can_create.indexOf("BOM") !== -1'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
onrender: function(node) {
|
||||||
|
if(node.is_root && node.data.value!="BOM") {
|
||||||
|
frappe.model.with_doc("BOM", node.data.value, function() {
|
||||||
|
var bom = frappe.model.get_doc("BOM", node.data.value);
|
||||||
|
node.data.image = bom.image || "";
|
||||||
|
node.data.description = bom.description || "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
view_template: 'bom_item_preview'
|
view_template: 'bom_item_preview'
|
||||||
}
|
}
|
@ -504,4 +504,7 @@ execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=
|
|||||||
erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_group
|
erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_group
|
||||||
erpnext.patches.v10_0.add_default_cash_flow_mappers
|
erpnext.patches.v10_0.add_default_cash_flow_mappers
|
||||||
erpnext.patches.v11_0.make_quality_inspection_template
|
erpnext.patches.v11_0.make_quality_inspection_template
|
||||||
# erpnext.patches.v10_0.update_territory_and_customer_group
|
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_detailss
|
@ -0,0 +1,56 @@
|
|||||||
|
# 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)
|
||||||
|
))
|
@ -0,0 +1,38 @@
|
|||||||
|
# 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 set sales_order_item = (select name from
|
||||||
|
`tabSales Order Item` soi where soi.parent=mri.sales_order and soi.item_code=mri.item_code) where docstatus = 1 and
|
||||||
|
ifnull(mri.sales_order, "")!=""
|
||||||
|
''')
|
||||||
|
|
||||||
|
# update the sales order item in the purchase order
|
||||||
|
frappe.db.sql('''update `tabPurchase Order Item` poi set sales_order_item = (select name from
|
||||||
|
`tabSales Order Item` soi where soi.parent=poi.sales_order and soi.item_code=poi.item_code) where docstatus = 1 and
|
||||||
|
ifnull(poi.sales_order, "")!=""
|
||||||
|
''')
|
||||||
|
|
||||||
|
# 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
|
@ -3,34 +3,26 @@ from frappe.model.rename_doc import get_fetch_fields
|
|||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"]
|
ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"]
|
||||||
customers = frappe.get_all('Customer', fields=["name", "territory", "customer_group"])
|
customers = frappe.get_all('Customer', fields=["name", "customer_group"])
|
||||||
|
|
||||||
territory_fetch = get_fetch_fields('Customer', 'Territory', ignore_doctypes)
|
|
||||||
customer_group_fetch = get_fetch_fields('Customer', 'Customer Group', ignore_doctypes)
|
customer_group_fetch = get_fetch_fields('Customer', 'Customer Group', ignore_doctypes)
|
||||||
|
|
||||||
batch_size = 1000
|
batch_size = 1000
|
||||||
for i in range(0, len(customers), batch_size):
|
for i in range(0, len(customers), batch_size):
|
||||||
batch_customers = customers[i:i + batch_size]
|
batch_customers = customers[i:i + batch_size]
|
||||||
for source_fieldname, linked_doctypes_info in [["customer_group", customer_group_fetch], ["territory", territory_fetch]]:
|
for d in customer_group_fetch:
|
||||||
for d in linked_doctypes_info:
|
when_then = []
|
||||||
when_then = []
|
for customer in batch_customers:
|
||||||
for customer in batch_customers:
|
value = frappe.db.escape(frappe.as_unicode(customer.get("customer_group")))
|
||||||
when_then.append('''
|
|
||||||
WHEN `{master_fieldname}` = "{docname}" and {linked_to_fieldname} != "{value}"
|
|
||||||
THEN "{value}"
|
|
||||||
'''.format(
|
|
||||||
master_fieldname=d["master_fieldname"],
|
|
||||||
linked_to_fieldname=d["linked_to_fieldname"],
|
|
||||||
docname=frappe.db.escape(customer.name).encode("utf-8"),
|
|
||||||
value=frappe.db.escape(customer.get(source_fieldname)).encode("utf-8")))
|
|
||||||
|
|
||||||
frappe.db.sql("""
|
when_then.append('''
|
||||||
update
|
WHEN `%s` = "%s" and %s != "%s"
|
||||||
`tab{doctype}`
|
THEN "%s"
|
||||||
set
|
'''%(d["master_fieldname"], frappe.db.escape(frappe.as_unicode(customer.name)),
|
||||||
{linked_to_fieldname} = CASE {when_then_cond} ELSE `{linked_to_fieldname}` END
|
d["linked_to_fieldname"], value, value))
|
||||||
""".format(
|
|
||||||
doctype = d['doctype'],
|
frappe.db.sql("""
|
||||||
when_then_cond=" ".join(when_then),
|
update
|
||||||
linked_to_fieldname=d.linked_to_fieldname
|
`tab%s`
|
||||||
))
|
set
|
||||||
|
%s = CASE %s ELSE `%s` END
|
||||||
|
"""%(d['doctype'], d.linked_to_fieldname, " ".join(when_then), d.linked_to_fieldname))
|
||||||
|
37
erpnext/patches/v10_0/update_warehouse_address_details.py
Normal file
37
erpnext/patches/v10_0/update_warehouse_address_details.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# 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
|
||||||
|
|
@ -54,16 +54,14 @@ class Customer(TransactionBase):
|
|||||||
self.flags.old_lead = self.lead_name
|
self.flags.old_lead = self.lead_name
|
||||||
validate_party_accounts(self)
|
validate_party_accounts(self)
|
||||||
self.validate_credit_limit_on_change()
|
self.validate_credit_limit_on_change()
|
||||||
self.check_customer_group_or_territory_change()
|
self.check_customer_group_change()
|
||||||
|
|
||||||
def check_customer_group_or_territory_change(self):
|
def check_customer_group_change(self):
|
||||||
frappe.flags.customer_group_changed, frappe.flags.territory_changed = False, False
|
frappe.flags.customer_group_changed = False
|
||||||
|
|
||||||
if not self.get('__islocal'):
|
if not self.get('__islocal'):
|
||||||
if self.customer_group != frappe.db.get_value('Customer', self.name, 'customer_group'):
|
if self.customer_group != frappe.db.get_value('Customer', self.name, 'customer_group'):
|
||||||
frappe.flags.customer_group_changed = True
|
frappe.flags.customer_group_changed = True
|
||||||
if self.territory != frappe.db.get_value('Customer', self.name, 'territory'):
|
|
||||||
frappe.flags.territory_changed = True
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.validate_name_with_customer_group()
|
self.validate_name_with_customer_group()
|
||||||
@ -76,12 +74,10 @@ class Customer(TransactionBase):
|
|||||||
if self.flags.is_new_doc:
|
if self.flags.is_new_doc:
|
||||||
self.create_lead_address_contact()
|
self.create_lead_address_contact()
|
||||||
|
|
||||||
self.update_territory_and_customer_groups()
|
self.update_customer_groups()
|
||||||
|
|
||||||
def update_territory_and_customer_groups(self):
|
def update_customer_groups(self):
|
||||||
ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"]
|
ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"]
|
||||||
if frappe.flags.territory_changed:
|
|
||||||
update_linked_doctypes('Customer', self.name, 'Territory', self.territory, ignore_doctypes)
|
|
||||||
if frappe.flags.customer_group_changed:
|
if frappe.flags.customer_group_changed:
|
||||||
update_linked_doctypes('Customer', self.name, 'Customer Group',
|
update_linked_doctypes('Customer', self.name, 'Customer Group',
|
||||||
self.customer_group, ignore_doctypes)
|
self.customer_group, ignore_doctypes)
|
||||||
|
@ -41,7 +41,7 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
|
|||||||
|
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
if (doc.__islocal) {
|
if (doc.__islocal && !doc.valid_till) {
|
||||||
if(frappe.boot.sysdefaults.quotation_valid_till){
|
if(frappe.boot.sysdefaults.quotation_valid_till){
|
||||||
this.frm.set_value('valid_till', frappe.datetime.add_days(doc.transaction_date, frappe.boot.sysdefaults.quotation_valid_till));
|
this.frm.set_value('valid_till', frappe.datetime.add_days(doc.transaction_date, frappe.boot.sysdefaults.quotation_valid_till));
|
||||||
} else {
|
} else {
|
||||||
|
@ -435,6 +435,7 @@ def make_material_request(source_name, target_doc=None):
|
|||||||
"Sales Order Item": {
|
"Sales Order Item": {
|
||||||
"doctype": "Material Request Item",
|
"doctype": "Material Request Item",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
|
"name": "sales_order_item",
|
||||||
"parent": "sales_order",
|
"parent": "sales_order",
|
||||||
"stock_uom": "uom",
|
"stock_uom": "uom",
|
||||||
"stock_qty": "qty"
|
"stock_qty": "qty"
|
||||||
|
@ -259,12 +259,16 @@ erpnext.pos.PointOfSale = class PointOfSale {
|
|||||||
frappe.msgprint(__("Quantity must be positive"));
|
frappe.msgprint(__("Quantity must be positive"));
|
||||||
value = item.qty;
|
value = item.qty;
|
||||||
} else {
|
} else {
|
||||||
item[field] = value;
|
if (in_list(["qty", "serial_no", "batch"], field)) {
|
||||||
if (field == "serial_no" && value) {
|
item[field] = value;
|
||||||
let serial_nos = value.split("\n");
|
if (field == "serial_no" && value) {
|
||||||
item["qty"] = serial_nos.filter(d => {
|
let serial_nos = value.split("\n");
|
||||||
return d!=="";
|
item["qty"] = serial_nos.filter(d => {
|
||||||
}).length;
|
return d!=="";
|
||||||
|
}).length;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return frappe.model.set_value(item.doctype, item.name, field, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1504,7 +1508,7 @@ class Payment {
|
|||||||
fieldname: p.mode_of_payment,
|
fieldname: p.mode_of_payment,
|
||||||
default: p.amount,
|
default: p.amount,
|
||||||
onchange: () => {
|
onchange: () => {
|
||||||
const value = this.dialog.get_value(this.fieldname);
|
const value = this.dialog.get_value(this.fieldname) || 0;
|
||||||
me.update_payment_value(this.fieldname, value);
|
me.update_payment_value(this.fieldname, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -102,7 +102,7 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non
|
|||||||
or I.name like %(search)s)"""
|
or I.name like %(search)s)"""
|
||||||
search = "%" + cstr(search) + "%"
|
search = "%" + cstr(search) + "%"
|
||||||
|
|
||||||
query += """order by I.weightage desc, in_stock desc, I.item_name limit %s, %s""" % (start, limit)
|
query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (start, limit)
|
||||||
|
|
||||||
data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1)
|
data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1)
|
||||||
|
|
||||||
|
@ -427,7 +427,8 @@ $.extend(erpnext.item, {
|
|||||||
["parent","=", attribute]
|
["parent","=", attribute]
|
||||||
],
|
],
|
||||||
fields: ["attribute_value"],
|
fields: ["attribute_value"],
|
||||||
limit_page_length: null
|
limit_start: 0,
|
||||||
|
limit_page_length: 500
|
||||||
}
|
}
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
if(r.message) {
|
if(r.message) {
|
||||||
|
@ -261,7 +261,8 @@ def make_purchase_order(source_name, target_doc=None):
|
|||||||
["parent", "material_request"],
|
["parent", "material_request"],
|
||||||
["uom", "stock_uom"],
|
["uom", "stock_uom"],
|
||||||
["uom", "uom"],
|
["uom", "uom"],
|
||||||
["sales_order", "sales_order"]
|
["sales_order", "sales_order"],
|
||||||
|
["sales_order_item", "sales_order_item"]
|
||||||
],
|
],
|
||||||
"postprocess": update_item,
|
"postprocess": update_item,
|
||||||
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
|
"condition": lambda doc: doc.ordered_qty < doc.stock_qty
|
||||||
|
@ -670,6 +670,36 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "sales_order_item",
|
||||||
|
"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": "Sales Order Item",
|
||||||
|
"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": 1,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -959,8 +989,8 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2017-12-20 16:29:18.902085",
|
"modified": "2018-02-12 05:51:39.954530",
|
||||||
"modified_by": "nabinhait@gmail.com",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Material Request Item",
|
"name": "Material Request Item",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
|
@ -11,7 +11,7 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchas
|
|||||||
from erpnext import set_perpetual_inventory
|
from erpnext import set_perpetual_inventory
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError
|
from erpnext.stock.doctype.serial_no.serial_no import SerialNoDuplicateError
|
||||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
|
||||||
class TestPurchaseReceipt(unittest.TestCase):
|
class TestPurchaseReceipt(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -203,6 +203,22 @@ class TestPurchaseReceipt(unittest.TestCase):
|
|||||||
"delivery_document_no": return_pr.name
|
"delivery_document_no": return_pr.name
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def test_purchase_return_for_multi_uom(self):
|
||||||
|
item_code = "_Test Purchase Return For Multi-UOM"
|
||||||
|
if not frappe.db.exists('Item', item_code):
|
||||||
|
item = make_item(item_code, {'stock_uom': 'Box'})
|
||||||
|
row = item.append('uoms', {
|
||||||
|
'uom': 'Unit',
|
||||||
|
'conversion_factor': 0.1
|
||||||
|
})
|
||||||
|
row.db_update()
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(item_code=item_code, qty=1, uom="Box", conversion_factor=1.0)
|
||||||
|
return_pr = make_purchase_receipt(item_code=item_code, qty=-10, uom="Unit",
|
||||||
|
stock_uom="Box", conversion_factor=0.1, is_return=1, return_against=pr.name)
|
||||||
|
|
||||||
|
self.assertEquals(abs(return_pr.items[0].stock_qty), 1.0)
|
||||||
|
|
||||||
def test_closed_purchase_receipt(self):
|
def test_closed_purchase_receipt(self):
|
||||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_purchase_receipt_status
|
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_purchase_receipt_status
|
||||||
|
|
||||||
@ -255,7 +271,6 @@ class TestPurchaseReceipt(unittest.TestCase):
|
|||||||
|
|
||||||
def test_not_accept_duplicate_serial_no(self):
|
def test_not_accept_duplicate_serial_no(self):
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
|
||||||
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
|
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
|
||||||
|
|
||||||
item_code = frappe.db.get_value('Item', {'has_serial_no': 1})
|
item_code = frappe.db.get_value('Item', {'has_serial_no': 1})
|
||||||
@ -307,9 +322,10 @@ def make_purchase_receipt(**args):
|
|||||||
"rejected_qty": rejected_qty,
|
"rejected_qty": rejected_qty,
|
||||||
"rejected_warehouse": args.rejected_warehouse or "_Test Rejected Warehouse - _TC" if rejected_qty != 0 else "",
|
"rejected_warehouse": args.rejected_warehouse or "_Test Rejected Warehouse - _TC" if rejected_qty != 0 else "",
|
||||||
"rate": args.rate or 50,
|
"rate": args.rate or 50,
|
||||||
"conversion_factor": 1.0,
|
"conversion_factor": args.conversion_factor or 1.0,
|
||||||
"serial_no": args.serial_no,
|
"serial_no": args.serial_no,
|
||||||
"stock_uom": "_Test UOM"
|
"stock_uom": args.stock_uom or "_Test UOM",
|
||||||
|
"uom": args.uom or "_Test UOM"
|
||||||
})
|
})
|
||||||
|
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
|
@ -191,7 +191,7 @@ def validate_serial_no(sle, item_det):
|
|||||||
if sle.serial_no:
|
if sle.serial_no:
|
||||||
frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
|
frappe.throw(_("Item {0} is not setup for Serial Nos. Column must be blank").format(sle.item_code),
|
||||||
SerialNoNotRequiredError)
|
SerialNoNotRequiredError)
|
||||||
else:
|
elif sle.is_cancelled == "No":
|
||||||
if sle.serial_no:
|
if sle.serial_no:
|
||||||
serial_nos = get_serial_nos(sle.serial_no)
|
serial_nos = get_serial_nos(sle.serial_no)
|
||||||
if cint(sle.actual_qty) != flt(sle.actual_qty):
|
if cint(sle.actual_qty) != flt(sle.actual_qty):
|
||||||
@ -326,11 +326,16 @@ def update_serial_nos_after_submit(controller, parentfield):
|
|||||||
update_rejected_serial_nos = True if (controller.doctype in ("Purchase Receipt", "Purchase Invoice")
|
update_rejected_serial_nos = True if (controller.doctype in ("Purchase Receipt", "Purchase Invoice")
|
||||||
and d.rejected_qty) else False
|
and d.rejected_qty) else False
|
||||||
accepted_serial_nos_updated = False
|
accepted_serial_nos_updated = False
|
||||||
warehouse = d.t_warehouse if controller.doctype == "Stock Entry" else d.warehouse
|
if controller.doctype == "Stock Entry":
|
||||||
|
warehouse = d.t_warehouse
|
||||||
|
qty = d.transfer_qty
|
||||||
|
else:
|
||||||
|
warehouse = d.warehouse
|
||||||
|
qty = d.stock_qty
|
||||||
|
|
||||||
for sle in stock_ledger_entries:
|
for sle in stock_ledger_entries:
|
||||||
if sle.voucher_detail_no==d.name:
|
if sle.voucher_detail_no==d.name:
|
||||||
if not accepted_serial_nos_updated and d.qty and abs(sle.actual_qty)==d.qty \
|
if not accepted_serial_nos_updated and qty and abs(sle.actual_qty)==qty \
|
||||||
and sle.warehouse == warehouse and sle.serial_no != d.serial_no:
|
and sle.warehouse == warehouse and sle.serial_no != d.serial_no:
|
||||||
d.serial_no = sle.serial_no
|
d.serial_no = sle.serial_no
|
||||||
frappe.db.set_value(d.doctype, d.name, "serial_no", sle.serial_no)
|
frappe.db.set_value(d.doctype, d.name, "serial_no", sle.serial_no)
|
||||||
|
@ -313,6 +313,14 @@ frappe.ui.form.on('Stock Entry', {
|
|||||||
frm.set_value("total_additional_costs",
|
frm.set_value("total_additional_costs",
|
||||||
flt(total_additional_costs, precision("total_additional_costs")));
|
flt(total_additional_costs, precision("total_additional_costs")));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
source_warehouse_address: function(frm) {
|
||||||
|
erpnext.utils.get_address_display(frm, 'source_warehouse_address', 'source_address_display', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
target_warehouse_address: function(frm) {
|
||||||
|
erpnext.utils.get_address_display(frm, 'target_warehouse_address', 'target_address_display', false);
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
frappe.ui.form.on('Stock Entry Detail', {
|
frappe.ui.form.on('Stock Entry Detail', {
|
||||||
|
@ -768,6 +768,68 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "from_warehouse",
|
||||||
|
"fieldname": "source_warehouse_address",
|
||||||
|
"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": "Source Warehouse Address",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Address",
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "source_address_display",
|
||||||
|
"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": "Source Warehouse Address",
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -828,6 +890,68 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"depends_on": "to_warehouse",
|
||||||
|
"fieldname": "target_warehouse_address",
|
||||||
|
"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": "Target Warehouse Name",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Address",
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "target_address_display",
|
||||||
|
"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": "Target Warehouse Address",
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -1770,7 +1894,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-02-17 10:32:24.111113",
|
"modified": "2018-03-01 12:27:12.884611",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry",
|
"name": "Stock Entry",
|
||||||
|
@ -5,6 +5,15 @@
|
|||||||
frappe.ui.form.on("Warehouse", {
|
frappe.ui.form.on("Warehouse", {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
frm.toggle_display('warehouse_name', frm.doc.__islocal);
|
frm.toggle_display('warehouse_name', frm.doc.__islocal);
|
||||||
|
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
|
||||||
|
|
||||||
|
|
||||||
|
if(!frm.doc.__islocal) {
|
||||||
|
frappe.contacts.render_address_and_contact(frm);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
frappe.contacts.clear_address_and_contact(frm);
|
||||||
|
}
|
||||||
|
|
||||||
frm.add_custom_button(__("Stock Balance"), function() {
|
frm.add_custom_button(__("Stock Balance"), function() {
|
||||||
frappe.set_route("query-report", "Stock Balance", {"warehouse": frm.doc.name});
|
frappe.set_route("query-report", "Stock Balance", {"warehouse": frm.doc.name});
|
||||||
|
@ -226,6 +226,125 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "address_and_contact",
|
||||||
|
"fieldtype": "Section 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,
|
||||||
|
"label": "Address and Contact",
|
||||||
|
"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": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "address_html",
|
||||||
|
"fieldtype": "HTML",
|
||||||
|
"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": "Address HTML",
|
||||||
|
"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": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "column_break_10",
|
||||||
|
"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,
|
||||||
|
"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,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "contact_html",
|
||||||
|
"fieldtype": "HTML",
|
||||||
|
"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": "Contact HTML",
|
||||||
|
"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": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"allow_bulk_edit": 0,
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
@ -699,7 +818,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2018-01-23 16:45:45.546649",
|
"modified": "2018-02-28 09:15:33.463838",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Warehouse",
|
"name": "Warehouse",
|
||||||
|
@ -7,6 +7,7 @@ from frappe.utils import cint, validate_email_add
|
|||||||
from frappe import throw, _
|
from frappe import throw, _
|
||||||
from frappe.utils.nestedset import NestedSet
|
from frappe.utils.nestedset import NestedSet
|
||||||
from erpnext.stock import get_warehouse_account
|
from erpnext.stock import get_warehouse_account
|
||||||
|
from frappe.contacts.address_and_contact import load_address_and_contact
|
||||||
|
|
||||||
class Warehouse(NestedSet):
|
class Warehouse(NestedSet):
|
||||||
nsm_parent_field = 'parent_warehouse'
|
nsm_parent_field = 'parent_warehouse'
|
||||||
@ -25,10 +26,8 @@ class Warehouse(NestedSet):
|
|||||||
|
|
||||||
if account:
|
if account:
|
||||||
self.set_onload('account', account)
|
self.set_onload('account', account)
|
||||||
|
load_address_and_contact(self)
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
if self.email_id:
|
|
||||||
validate_email_add(self.email_id, True)
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.update_nsm_model()
|
self.update_nsm_model()
|
||||||
|
@ -24,9 +24,8 @@ def execute(filters=None):
|
|||||||
|
|
||||||
data = []
|
data = []
|
||||||
for item in items:
|
for item in items:
|
||||||
|
total_outgoing = consumed_item_map.get(item.name, 0) + delivered_item_map.get(item.name,0)
|
||||||
total_outgoing = consumed_item_map.get(item.name, 0)+delivered_item_map.get(item.name,0)
|
avg_daily_outgoing = flt(total_outgoing / diff, float_preceision)
|
||||||
avg_daily_outgoing = flt(total_outgoing/diff, float_preceision)
|
|
||||||
reorder_level = (avg_daily_outgoing * flt(item.lead_time_days)) + flt(item.safety_stock)
|
reorder_level = (avg_daily_outgoing * flt(item.lead_time_days)) + flt(item.safety_stock)
|
||||||
|
|
||||||
data.append([item.name, item.item_name, item.description, item.safety_stock, item.lead_time_days,
|
data.append([item.name, item.item_name, item.description, item.safety_stock, item.lead_time_days,
|
||||||
@ -45,12 +44,11 @@ def get_columns():
|
|||||||
|
|
||||||
def get_item_info():
|
def get_item_info():
|
||||||
return frappe.db.sql("""select name, item_name, description, safety_stock,
|
return frappe.db.sql("""select name, item_name, description, safety_stock,
|
||||||
lead_time_days from tabItem""", as_dict=1)
|
lead_time_days from tabItem""", as_dict=1)
|
||||||
|
|
||||||
def get_consumed_items(condition):
|
def get_consumed_items(condition):
|
||||||
|
|
||||||
cn_items = frappe.db.sql("""select se_item.item_code,
|
cn_items = frappe.db.sql("""select se_item.item_code,
|
||||||
sum(se_item.actual_qty) as 'consume_qty'
|
sum(se_item.transfer_qty) as 'consume_qty'
|
||||||
from `tabStock Entry` se, `tabStock Entry Detail` se_item
|
from `tabStock Entry` se, `tabStock Entry Detail` se_item
|
||||||
where se.name = se_item.parent and se.docstatus = 1
|
where se.name = se_item.parent and se.docstatus = 1
|
||||||
and ifnull(se_item.t_warehouse, '') = '' %s
|
and ifnull(se_item.t_warehouse, '') = '' %s
|
||||||
@ -63,17 +61,16 @@ def get_consumed_items(condition):
|
|||||||
return cn_items_map
|
return cn_items_map
|
||||||
|
|
||||||
def get_delivered_items(condition):
|
def get_delivered_items(condition):
|
||||||
|
dn_items = frappe.db.sql("""select dn_item.item_code, sum(dn_item.stock_qty) as dn_qty
|
||||||
dn_items = frappe.db.sql("""select dn_item.item_code, sum(dn_item.qty) as dn_qty
|
|
||||||
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
|
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
|
||||||
where dn.name = dn_item.parent and dn.docstatus = 1 %s
|
where dn.name = dn_item.parent and dn.docstatus = 1 %s
|
||||||
group by dn_item.item_code""" % (condition), as_dict=1)
|
group by dn_item.item_code""" % (condition), as_dict=1)
|
||||||
|
|
||||||
si_items = frappe.db.sql("""select si_item.item_name, sum(si_item.qty) as si_qty
|
si_items = frappe.db.sql("""select si_item.item_code, sum(si_item.stock_qty) as si_qty
|
||||||
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
|
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
|
||||||
where si.name = si_item.parent and si.docstatus = 1 and
|
where si.name = si_item.parent and si.docstatus = 1 and
|
||||||
si.update_stock = 1 and si.is_pos = 1 %s
|
si.update_stock = 1 %s
|
||||||
group by si_item.item_name""" % (condition), as_dict=1)
|
group by si_item.item_code""" % (condition), as_dict=1)
|
||||||
|
|
||||||
dn_item_map = {}
|
dn_item_map = {}
|
||||||
for item in dn_items:
|
for item in dn_items:
|
||||||
|
@ -96,6 +96,8 @@ def get_item_conditions(filters):
|
|||||||
def get_sle_conditions(filters):
|
def get_sle_conditions(filters):
|
||||||
conditions = []
|
conditions = []
|
||||||
if filters.get("warehouse"):
|
if filters.get("warehouse"):
|
||||||
conditions.append("warehouse=%(warehouse)s")
|
lft, rgt = frappe.db.get_value('Warehouse', filters.get("warehouse"), ['lft', 'rgt'])
|
||||||
|
conditions.append("""warehouse in (select wh.name from `tabWarehouse` wh
|
||||||
|
where wh.lft >= {0} and rgt <= {1})""".format(lft, rgt))
|
||||||
|
|
||||||
return "and {}".format(" and ".join(conditions)) if conditions else ""
|
return "and {}".format(" and ".join(conditions)) if conditions else ""
|
||||||
|
@ -454,22 +454,22 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no,
|
|||||||
where item_code = %s and valuation_rate > 0
|
where item_code = %s and valuation_rate > 0
|
||||||
order by posting_date desc, posting_time desc, name desc limit 1""", item_code)
|
order by posting_date desc, posting_time desc, name desc limit 1""", item_code)
|
||||||
|
|
||||||
valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
|
if last_valuation_rate:
|
||||||
|
return flt(last_valuation_rate[0][0]) # as there is previous records, it might come with zero rate
|
||||||
|
|
||||||
|
# If negative stock allowed, and item delivered without any incoming entry,
|
||||||
|
# system does not found any SLE, then take valuation rate from Item
|
||||||
|
valuation_rate = frappe.db.get_value("Item", item_code, "valuation_rate")
|
||||||
|
|
||||||
if not valuation_rate:
|
if not valuation_rate:
|
||||||
# If negative stock allowed, and item delivered without any incoming entry,
|
# try Item Standard rate
|
||||||
# syste does not found any SLE, then take valuation rate from Item
|
valuation_rate = frappe.db.get_value("Item", item_code, "standard_rate")
|
||||||
valuation_rate = frappe.db.get_value("Item", item_code, "valuation_rate")
|
|
||||||
|
|
||||||
if not valuation_rate:
|
if not valuation_rate:
|
||||||
# try Item Standard rate
|
# try in price list
|
||||||
valuation_rate = frappe.db.get_value("Item", item_code, "standard_rate")
|
valuation_rate = frappe.db.get_value('Item Price',
|
||||||
|
dict(item_code=item_code, buying=1, currency=currency),
|
||||||
if not valuation_rate:
|
'price_list_rate')
|
||||||
# try in price list
|
|
||||||
valuation_rate = frappe.db.get_value('Item Price',
|
|
||||||
dict(item_code=item_code, buying=1, currency=currency),
|
|
||||||
'price_list_rate')
|
|
||||||
|
|
||||||
if not allow_zero_rate and not valuation_rate and raise_error_if_no_rate \
|
if not allow_zero_rate and not valuation_rate and raise_error_if_no_rate \
|
||||||
and cint(erpnext.is_perpetual_inventory_enabled(company)):
|
and cint(erpnext.is_perpetual_inventory_enabled(company)):
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<th style="border: 1px solid #d1d8dd; width: 35%; text-align: left; padding: 5px;">{{ _("Warehouse") }}</th>
|
<th style="border: 1px solid #d1d8dd; width: 35%; text-align: left; padding: 5px;">{{ _("Warehouse") }}</th>
|
||||||
<th style="border: 1px solid #d1d8dd; width: 10%; text-align: right; padding: 5px;">{{ _("Quantity") }}</th>
|
<th style="border: 1px solid #d1d8dd; width: 10%; text-align: right; padding: 5px;">{{ _("Quantity") }}</th>
|
||||||
<th style="border: 1px solid #d1d8dd; width: 10%; text-align: left; padding: 5px;">{{ _("UOM") }}</th>
|
<th style="border: 1px solid #d1d8dd; width: 10%; text-align: left; padding: 5px;">{{ _("UOM") }}</th>
|
||||||
<th style="border: 1px solid #d1d8dd; width: 10%; text-align: left; padding: 5px;">{{ _("Balance Qty") }}</th>
|
<th style="border: 1px solid #d1d8dd; width: 10%; text-align: left; padding: 5px;">{{ _("Projected Qty") }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -22,7 +22,7 @@
|
|||||||
<td style="border: 1px solid #d1d8dd; text-align: left; padding: 5px;">{{ item.warehouse }}</td>
|
<td style="border: 1px solid #d1d8dd; text-align: left; padding: 5px;">{{ item.warehouse }}</td>
|
||||||
<td style="border: 1px solid #d1d8dd; text-align: right; padding: 5px;">{{ item.qty }}</td>
|
<td style="border: 1px solid #d1d8dd; text-align: right; padding: 5px;">{{ item.qty }}</td>
|
||||||
<td style="border: 1px solid #d1d8dd; text-align: left; padding: 5px;">{{ item.uom }}</td>
|
<td style="border: 1px solid #d1d8dd; text-align: left; padding: 5px;">{{ item.uom }}</td>
|
||||||
<td style="border: 1px solid #d1d8dd; text-align: left; padding: 5px;">{{ item.balance_qty }}</td>
|
<td style="border: 1px solid #d1d8dd; text-align: left; padding: 5px;">{{ frappe.utils.flt(item.projected_qty) + frappe.utils.flt(item.qty) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -35,7 +35,7 @@ def get_product_list(search=None, start=0, limit=12):
|
|||||||
search = "%" + cstr(search) + "%"
|
search = "%" + cstr(search) + "%"
|
||||||
|
|
||||||
# order by
|
# order by
|
||||||
query += """ order by I.weightage desc, in_stock desc, I.item_name limit %s, %s""" % (cint(start), cint(limit))
|
query += """ order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (cint(start), cint(limit))
|
||||||
|
|
||||||
data = frappe.db.sql(query, {
|
data = frappe.db.sql(query, {
|
||||||
"search": search,
|
"search": search,
|
||||||
|
@ -45,7 +45,7 @@ class TransactionBase(StatusUpdater):
|
|||||||
events = frappe.db.sql_list("""select name from `tabEvent`
|
events = frappe.db.sql_list("""select name from `tabEvent`
|
||||||
where ref_type=%s and ref_name=%s""", (self.doctype, self.name))
|
where ref_type=%s and ref_name=%s""", (self.doctype, self.name))
|
||||||
if events:
|
if events:
|
||||||
frappe.db.sql("delete from `tabEvent` where name in (%s)"
|
frappe.db.sql("delete from `tabEvent` where name in ({0})"
|
||||||
.format(", ".join(['%s']*len(events))), tuple(events))
|
.format(", ".join(['%s']*len(events))), tuple(events))
|
||||||
|
|
||||||
def _add_calendar_event(self, opts):
|
def _add_calendar_event(self, opts):
|
||||||
@ -73,6 +73,8 @@ class TransactionBase(StatusUpdater):
|
|||||||
validate_uom_is_integer(self, uom_field, qty_fields)
|
validate_uom_is_integer(self, uom_field, qty_fields)
|
||||||
|
|
||||||
def validate_with_previous_doc(self, ref):
|
def validate_with_previous_doc(self, ref):
|
||||||
|
self.exclude_fields = ["conversion_factor", "uom"] if self.get('is_return') else []
|
||||||
|
|
||||||
for key, val in ref.items():
|
for key, val in ref.items():
|
||||||
is_child = val.get("is_child_table")
|
is_child = val.get("is_child_table")
|
||||||
ref_doc = {}
|
ref_doc = {}
|
||||||
@ -103,7 +105,7 @@ class TransactionBase(StatusUpdater):
|
|||||||
frappe.throw(_("Invalid reference {0} {1}").format(reference_doctype, reference_name))
|
frappe.throw(_("Invalid reference {0} {1}").format(reference_doctype, reference_name))
|
||||||
|
|
||||||
for field, condition in fields:
|
for field, condition in fields:
|
||||||
if prevdoc_values[field] is not None:
|
if prevdoc_values[field] is not None and field not in self.exclude_fields:
|
||||||
self.validate_value(field, condition, prevdoc_values[field], doc)
|
self.validate_value(field, condition, prevdoc_values[field], doc)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user