Merge branch 'develop'
This commit is contained in:
commit
a5e11d7195
@ -1,2 +1,2 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
__version__ = '5.3.1'
|
__version__ = '5.4.0'
|
||||||
|
|||||||
@ -4,11 +4,13 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
from frappe.utils import flt, fmt_money, getdate, formatdate, cstr, cint
|
from frappe.utils import flt, fmt_money, getdate, formatdate, cstr
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class CustomerFrozen(frappe.ValidationError): pass
|
||||||
|
|
||||||
class GLEntry(Document):
|
class GLEntry(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.flags.ignore_submit_comment = True
|
self.flags.ignore_submit_comment = True
|
||||||
@ -17,6 +19,7 @@ class GLEntry(Document):
|
|||||||
self.validate_posting_date()
|
self.validate_posting_date()
|
||||||
self.check_pl_account()
|
self.check_pl_account()
|
||||||
self.validate_cost_center()
|
self.validate_cost_center()
|
||||||
|
self.validate_party()
|
||||||
|
|
||||||
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
|
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
|
||||||
self.validate_account_details(adv_adj)
|
self.validate_account_details(adv_adj)
|
||||||
@ -88,6 +91,13 @@ class GLEntry(Document):
|
|||||||
|
|
||||||
if self.cost_center and _get_cost_center_company() != self.company:
|
if self.cost_center and _get_cost_center_company() != self.company:
|
||||||
frappe.throw(_("Cost Center {0} does not belong to Company {1}").format(self.cost_center, self.company))
|
frappe.throw(_("Cost Center {0} does not belong to Company {1}").format(self.cost_center, self.company))
|
||||||
|
|
||||||
|
def validate_party(self):
|
||||||
|
if self.party_type and self.party:
|
||||||
|
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
||||||
|
if not frozen_accounts_modifier in frappe.get_roles():
|
||||||
|
if frappe.db.get_value(self.party_type, self.party, "is_frozen"):
|
||||||
|
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
|
||||||
|
|
||||||
def validate_balance_type(account, adv_adj=False):
|
def validate_balance_type(account, adv_adj=False):
|
||||||
if not adv_adj and account:
|
if not adv_adj and account:
|
||||||
|
|||||||
@ -190,8 +190,9 @@ class PaymentReconciliation(Document):
|
|||||||
if flt(p.allocated_amount) > flt(p.amount):
|
if flt(p.allocated_amount) > flt(p.amount):
|
||||||
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to JV amount {2}")
|
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to JV amount {2}")
|
||||||
.format(p.idx, p.allocated_amount, p.amount))
|
.format(p.idx, p.allocated_amount, p.amount))
|
||||||
|
|
||||||
if flt(p.allocated_amount) > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
|
invoice_outstanding = unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)
|
||||||
|
if abs(flt(p.allocated_amount) - invoice_outstanding) > 0.009:
|
||||||
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
|
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
|
||||||
.format(p.idx, p.allocated_amount, unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)))
|
.format(p.idx, p.allocated_amount, unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)))
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
"options": "Territory",
|
"options": "Territory",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "naming_series",
|
"fieldname": "naming_series",
|
||||||
@ -167,7 +167,7 @@
|
|||||||
"options": "Account",
|
"options": "Account",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "income_account",
|
"fieldname": "income_account",
|
||||||
@ -178,7 +178,7 @@
|
|||||||
"options": "Account",
|
"options": "Account",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||||
@ -201,7 +201,7 @@
|
|||||||
"options": "Cost Center",
|
"options": "Cost Center",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "write_off_account",
|
"fieldname": "write_off_account",
|
||||||
@ -234,7 +234,7 @@
|
|||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2015-07-07 08:56:04.381471",
|
"modified": "2015-07-28 15:07:14.417200",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "POS Profile",
|
"name": "POS Profile",
|
||||||
|
|||||||
@ -20,27 +20,19 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
// Show / Hide button
|
// Show / Hide button
|
||||||
if(doc.docstatus==1 && doc.outstanding_amount > 0)
|
this.show_general_ledger();
|
||||||
this.frm.add_custom_button(__('Make Payment Entry'), this.make_bank_entry);
|
|
||||||
|
if(!doc.is_return) {
|
||||||
if(doc.docstatus==1) {
|
if(doc.docstatus==1) {
|
||||||
cur_frm.add_custom_button(__('Make Purchase Return'), this.make_purchase_return);
|
if(doc.outstanding_amount > 0) {
|
||||||
|
this.frm.add_custom_button(__('Make Payment Entry'), this.make_bank_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_frm.add_custom_button(__('Make Debit Note'), this.make_debit_note);
|
||||||
|
}
|
||||||
|
|
||||||
cur_frm.add_custom_button(__('View Ledger'), function() {
|
if(doc.docstatus===0) {
|
||||||
frappe.route_options = {
|
cur_frm.add_custom_button(__('From Purchase Order'), function() {
|
||||||
"voucher_no": doc.name,
|
|
||||||
"from_date": doc.posting_date,
|
|
||||||
"to_date": doc.posting_date,
|
|
||||||
"company": doc.company,
|
|
||||||
group_by_voucher: 0
|
|
||||||
};
|
|
||||||
frappe.set_route("query-report", "General Ledger");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(doc.docstatus===0) {
|
|
||||||
cur_frm.add_custom_button(__('From Purchase Order'),
|
|
||||||
function() {
|
|
||||||
frappe.model.map_current_doc({
|
frappe.model.map_current_doc({
|
||||||
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
|
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
|
||||||
source_doctype: "Purchase Order",
|
source_doctype: "Purchase Order",
|
||||||
@ -54,8 +46,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
cur_frm.add_custom_button(__('From Purchase Receipt'),
|
cur_frm.add_custom_button(__('From Purchase Receipt'), function() {
|
||||||
function() {
|
|
||||||
frappe.model.map_current_doc({
|
frappe.model.map_current_doc({
|
||||||
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
|
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
|
||||||
source_doctype: "Purchase Receipt",
|
source_doctype: "Purchase Receipt",
|
||||||
@ -66,10 +57,10 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
supplier: function() {
|
supplier: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
if(this.frm.updating_party_details)
|
if(this.frm.updating_party_details)
|
||||||
@ -112,9 +103,9 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
make_purchase_return: function() {
|
make_debit_note: function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_purchase_return",
|
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_debit_note",
|
||||||
frm: cur_frm
|
frm: cur_frm
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -152,7 +143,7 @@ cur_frm.fields_dict['items'].grid.get_field("item_code").get_query = function(do
|
|||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query",
|
||||||
filters:{
|
filters:{
|
||||||
'is_purchase_item': 'Yes'
|
'is_purchase_item': 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,4 +223,3 @@ cur_frm.cscript.select_print_heading = function(doc,cdt,cdn){
|
|||||||
else
|
else
|
||||||
cur_frm.pformat.print_heading = __("Purchase Invoice");
|
cur_frm.pformat.print_heading = __("Purchase Invoice");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
def check_active_purchase_items(self):
|
def check_active_purchase_items(self):
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.item_code: # extra condn coz item_code is not mandatory in PV
|
if d.item_code: # extra condn coz item_code is not mandatory in PV
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_purchase_item") != 'Yes':
|
if frappe.db.get_value("Item", d.item_code, "is_purchase_item") != 1:
|
||||||
msgprint(_("Item {0} is not Purchase Item").format(d.item_code), raise_exception=True)
|
msgprint(_("Item {0} is not Purchase Item").format(d.item_code), raise_exception=True)
|
||||||
|
|
||||||
def check_conversion_rate(self):
|
def check_conversion_rate(self):
|
||||||
@ -255,7 +255,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"against": self.against_expense_account,
|
"against": self.against_expense_account,
|
||||||
"credit": self.total_amount_to_pay,
|
"credit": self.total_amount_to_pay,
|
||||||
"remarks": self.remarks,
|
"remarks": self.remarks,
|
||||||
"against_voucher": self.name,
|
"against_voucher": self.return_against if cint(self.is_return) else self.name,
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -411,6 +411,6 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})
|
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_purchase_return(source_name, target_doc=None):
|
def make_debit_note(source_name, target_doc=None):
|
||||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||||
return make_return_doc("Purchase Invoice", source_name, target_doc)
|
return make_return_doc("Purchase Invoice", source_name, target_doc)
|
||||||
@ -4,9 +4,11 @@
|
|||||||
// render
|
// render
|
||||||
frappe.listview_settings['Purchase Invoice'] = {
|
frappe.listview_settings['Purchase Invoice'] = {
|
||||||
add_fields: ["supplier", "supplier_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
add_fields: ["supplier", "supplier_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
||||||
"currency"],
|
"currency", "is_return"],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(flt(doc.outstanding_amount) > 0 && doc.docstatus==1) {
|
if(cint(doc.is_return)==1) {
|
||||||
|
return [__("Return"), "darkgrey", "is_return,=,1"];
|
||||||
|
} else if(flt(doc.outstanding_amount) > 0 && doc.docstatus==1) {
|
||||||
if(frappe.datetime.get_diff(doc.due_date) < 0) {
|
if(frappe.datetime.get_diff(doc.due_date) < 0) {
|
||||||
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<,Today"];
|
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<,Today"];
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -11,9 +11,9 @@ def get_items(price_list, sales_or_purchase, item=None):
|
|||||||
args = {"price_list": price_list}
|
args = {"price_list": price_list}
|
||||||
|
|
||||||
if sales_or_purchase == "Sales":
|
if sales_or_purchase == "Sales":
|
||||||
condition = "i.is_sales_item='Yes'"
|
condition = "i.is_sales_item=1"
|
||||||
else:
|
else:
|
||||||
condition = "i.is_purchase_item='Yes'"
|
condition = "i.is_purchase_item=1"
|
||||||
|
|
||||||
if item:
|
if item:
|
||||||
# search serial no
|
# search serial no
|
||||||
|
|||||||
@ -43,18 +43,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
|
|
||||||
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
||||||
|
|
||||||
if(doc.docstatus==1) {
|
this.show_general_ledger();
|
||||||
cur_frm.add_custom_button('View Ledger', function() {
|
|
||||||
frappe.route_options = {
|
if(doc.update_stock) this.show_stock_ledger();
|
||||||
"voucher_no": doc.name,
|
|
||||||
"from_date": doc.posting_date,
|
if(doc.docstatus==1 && !doc.is_return) {
|
||||||
"to_date": doc.posting_date,
|
|
||||||
"company": doc.company,
|
|
||||||
group_by_voucher: 0
|
|
||||||
};
|
|
||||||
frappe.set_route("query-report", "General Ledger");
|
|
||||||
});
|
|
||||||
|
|
||||||
if(cint(doc.update_stock)!=1) {
|
if(cint(doc.update_stock)!=1) {
|
||||||
// show Make Delivery Note button only if Sales Invoice is not created from Delivery Note
|
// show Make Delivery Note button only if Sales Invoice is not created from Delivery Note
|
||||||
var from_delivery_note = false;
|
var from_delivery_note = false;
|
||||||
@ -72,11 +65,12 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
cur_frm.add_custom_button(__('Make Payment Entry'), cur_frm.cscript.make_bank_entry);
|
cur_frm.add_custom_button(__('Make Payment Entry'), cur_frm.cscript.make_bank_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.add_custom_button(__('Make Sales Return'), this.make_sales_return);
|
cur_frm.add_custom_button(doc.update_stock ? __('Make Sales Return') : __('Make Credit Note'),
|
||||||
|
this.make_sales_return);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show buttons only when pos view is active
|
// Show buttons only when pos view is active
|
||||||
if (cint(doc.docstatus==0) && cur_frm.page.current_view_name!=="pos") {
|
if (cint(doc.docstatus==0) && cur_frm.page.current_view_name!=="pos" && !doc.is_return) {
|
||||||
cur_frm.cscript.sales_order_btn();
|
cur_frm.cscript.sales_order_btn();
|
||||||
cur_frm.cscript.delivery_note_btn();
|
cur_frm.cscript.delivery_note_btn();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from frappe.utils import cint, cstr, flt
|
from frappe.utils import cint, flt
|
||||||
from frappe import _, msgprint, throw
|
from frappe import _, msgprint, throw
|
||||||
from erpnext.accounts.party import get_party_account, get_due_date
|
from erpnext.accounts.party import get_party_account, get_due_date
|
||||||
from erpnext.controllers.stock_controller import update_gl_entries_after
|
from erpnext.controllers.stock_controller import update_gl_entries_after
|
||||||
@ -66,6 +66,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.validate_c_form()
|
self.validate_c_form()
|
||||||
self.validate_time_logs_are_submitted()
|
self.validate_time_logs_are_submitted()
|
||||||
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
|
self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
|
||||||
|
self.update_packing_list()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
super(SalesInvoice, self).on_submit()
|
super(SalesInvoice, self).on_submit()
|
||||||
@ -85,7 +86,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||||
self.check_credit_limit()
|
self.check_credit_limit()
|
||||||
|
|
||||||
# this sequence because outstanding may get -ve
|
# this sequence because outstanding may get -ve
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
|
|
||||||
@ -102,15 +103,15 @@ class SalesInvoice(SellingController):
|
|||||||
self.update_stock_ledger()
|
self.update_stock_ledger()
|
||||||
|
|
||||||
self.check_stop_sales_order("sales_order")
|
self.check_stop_sales_order("sales_order")
|
||||||
|
|
||||||
from erpnext.accounts.utils import remove_against_link_from_jv
|
from erpnext.accounts.utils import remove_against_link_from_jv
|
||||||
remove_against_link_from_jv(self.doctype, self.name, "against_invoice")
|
remove_against_link_from_jv(self.doctype, self.name, "against_invoice")
|
||||||
|
|
||||||
if not self.is_return:
|
if not self.is_return:
|
||||||
self.update_status_updater_args()
|
self.update_status_updater_args()
|
||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
|
||||||
|
|
||||||
self.validate_c_form_on_cancel()
|
self.validate_c_form_on_cancel()
|
||||||
|
|
||||||
self.make_gl_entries_on_cancel()
|
self.make_gl_entries_on_cancel()
|
||||||
@ -248,12 +249,10 @@ class SalesInvoice(SellingController):
|
|||||||
def validate_fixed_asset_account(self):
|
def validate_fixed_asset_account(self):
|
||||||
"""Validate Fixed Asset and whether Income Account Entered Exists"""
|
"""Validate Fixed Asset and whether Income Account Entered Exists"""
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
item = frappe.db.sql("""select name,is_asset_item,is_sales_item from `tabItem`
|
is_asset_item = frappe.db.get_value("Item", d.item_code, "is_asset_item")
|
||||||
where name = %s""", d.item_code)
|
account_type = frappe.db.get_value("Account", d.income_account, "account_type")
|
||||||
acc = frappe.db.sql("""select account_type from `tabAccount`
|
if is_asset_item == 1 and account_type != 'Fixed Asset':
|
||||||
where name = %s and docstatus != 2""", d.income_account)
|
msgprint(_("Account {0} must be of type 'Fixed Asset' as Item {1} is an Asset Item").format(d.income_account, d.item_code), raise_exception=True)
|
||||||
if item and item[0][1] == 'Yes' and acc and acc[0][0] != 'Fixed Asset':
|
|
||||||
msgprint(_("Account {0} must be of type 'Fixed Asset' as Item {1} is an Asset Item").format(acc[0][0], d.item_code), raise_exception=True)
|
|
||||||
|
|
||||||
def validate_with_previous_doc(self):
|
def validate_with_previous_doc(self):
|
||||||
super(SalesInvoice, self).validate_with_previous_doc({
|
super(SalesInvoice, self).validate_with_previous_doc({
|
||||||
@ -271,7 +270,7 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')):
|
if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')):
|
||||||
self.validate_rate_with_reference_doc([
|
self.validate_rate_with_reference_doc([
|
||||||
["Sales Order", "sales_order", "so_detail"],
|
["Sales Order", "sales_order", "so_detail"],
|
||||||
["Delivery Note", "delivery_note", "dn_detail"]
|
["Delivery Note", "delivery_note", "dn_detail"]
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -296,7 +295,7 @@ class SalesInvoice(SellingController):
|
|||||||
for i in dic:
|
for i in dic:
|
||||||
if frappe.db.get_value('Selling Settings', None, dic[i]) == 'Yes':
|
if frappe.db.get_value('Selling Settings', None, dic[i]) == 'Yes':
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if frappe.db.get_value('Item', d.item_code, 'is_stock_item') == 'Yes' \
|
if frappe.db.get_value('Item', d.item_code, 'is_stock_item') == 1 \
|
||||||
and not d.get(i.lower().replace(' ','_')):
|
and not d.get(i.lower().replace(' ','_')):
|
||||||
msgprint(_("{0} is mandatory for Item {1}").format(i,d.item_code), raise_exception=1)
|
msgprint(_("{0} is mandatory for Item {1}").format(i,d.item_code), raise_exception=1)
|
||||||
|
|
||||||
@ -365,6 +364,13 @@ class SalesInvoice(SellingController):
|
|||||||
d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
|
d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
|
||||||
d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
|
d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
|
||||||
|
|
||||||
|
def update_packing_list(self):
|
||||||
|
if cint(self.update_stock) == 1:
|
||||||
|
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
|
||||||
|
make_packing_list(self, 'items')
|
||||||
|
else:
|
||||||
|
self.set('packed_items', [])
|
||||||
|
|
||||||
|
|
||||||
def get_warehouse(self):
|
def get_warehouse(self):
|
||||||
user_pos_profile = frappe.db.sql("""select name, warehouse from `tabPOS Profile`
|
user_pos_profile = frappe.db.sql("""select name, warehouse from `tabPOS Profile`
|
||||||
@ -383,20 +389,6 @@ class SalesInvoice(SellingController):
|
|||||||
return warehouse
|
return warehouse
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
if cint(self.update_stock) == 1:
|
|
||||||
# Set default warehouse from POS Profile
|
|
||||||
if cint(self.is_pos) == 1:
|
|
||||||
w = self.get_warehouse()
|
|
||||||
if w:
|
|
||||||
for d in self.get('items'):
|
|
||||||
if not d.warehouse:
|
|
||||||
d.warehouse = cstr(w)
|
|
||||||
|
|
||||||
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
|
|
||||||
make_packing_list(self, 'items')
|
|
||||||
else:
|
|
||||||
self.set('packed_items', [])
|
|
||||||
|
|
||||||
if cint(self.is_pos) == 1:
|
if cint(self.is_pos) == 1:
|
||||||
if flt(self.paid_amount) == 0:
|
if flt(self.paid_amount) == 0:
|
||||||
if self.cash_bank_account:
|
if self.cash_bank_account:
|
||||||
@ -426,11 +418,14 @@ class SalesInvoice(SellingController):
|
|||||||
def update_stock_ledger(self):
|
def update_stock_ledger(self):
|
||||||
sl_entries = []
|
sl_entries = []
|
||||||
for d in self.get_item_list():
|
for d in self.get_item_list():
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" and d.warehouse:
|
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and d.warehouse and flt(d['qty']):
|
||||||
|
self.update_reserved_qty(d)
|
||||||
|
|
||||||
incoming_rate = 0
|
incoming_rate = 0
|
||||||
if cint(self.is_return) and self.return_against and self.docstatus==1:
|
if cint(self.is_return) and self.return_against and self.docstatus==1:
|
||||||
incoming_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
|
incoming_rate = self.get_incoming_rate_for_sales_return(d.item_code,
|
||||||
|
self.return_against)
|
||||||
|
|
||||||
sl_entries.append(self.get_sl_entries(d, {
|
sl_entries.append(self.get_sl_entries(d, {
|
||||||
"actual_qty": -1*flt(d.qty),
|
"actual_qty": -1*flt(d.qty),
|
||||||
"stock_uom": frappe.db.get_value("Item", d.item_code, "stock_uom"),
|
"stock_uom": frappe.db.get_value("Item", d.item_code, "stock_uom"),
|
||||||
@ -664,4 +659,4 @@ def make_delivery_note(source_name, target_doc=None):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_sales_return(source_name, target_doc=None):
|
def make_sales_return(source_name, target_doc=None):
|
||||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||||
return make_return_doc("Sales Invoice", source_name, target_doc)
|
return make_return_doc("Sales Invoice", source_name, target_doc)
|
||||||
|
|||||||
@ -4,9 +4,11 @@
|
|||||||
// render
|
// render
|
||||||
frappe.listview_settings['Sales Invoice'] = {
|
frappe.listview_settings['Sales Invoice'] = {
|
||||||
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
||||||
"currency"],
|
"currency", "is_return"],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if(flt(doc.outstanding_amount)==0) {
|
if(cint(doc.is_return)==1) {
|
||||||
|
return [__("Return"), "darkgrey", "is_return,=,1"];
|
||||||
|
} else if(flt(doc.outstanding_amount)==0) {
|
||||||
return [__("Paid"), "green", "outstanding_amount,=,0"]
|
return [__("Paid"), "green", "outstanding_amount,=,0"]
|
||||||
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date > frappe.datetime.get_today()) {
|
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date > frappe.datetime.get_today()) {
|
||||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"]
|
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"]
|
||||||
|
|||||||
@ -5,10 +5,8 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import unittest, copy
|
import unittest, copy
|
||||||
from frappe.utils import nowdate, add_days, flt
|
from frappe.utils import nowdate, add_days, flt
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
|
||||||
from erpnext.projects.doctype.time_log_batch.test_time_log_batch import *
|
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||||
|
|
||||||
class TestSalesInvoice(unittest.TestCase):
|
class TestSalesInvoice(unittest.TestCase):
|
||||||
def make(self):
|
def make(self):
|
||||||
@ -402,32 +400,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
jv.cancel()
|
jv.cancel()
|
||||||
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8)
|
self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8)
|
||||||
|
|
||||||
def test_time_log_batch(self):
|
|
||||||
delete_time_log_and_batch()
|
|
||||||
time_log = create_time_log()
|
|
||||||
tlb = create_time_log_batch(time_log)
|
|
||||||
|
|
||||||
tlb = frappe.get_doc("Time Log Batch", tlb.name)
|
|
||||||
tlb.submit()
|
|
||||||
|
|
||||||
si = frappe.get_doc(frappe.copy_doc(test_records[0]))
|
|
||||||
si.get("items")[0].time_log_batch = tlb.name
|
|
||||||
si.insert()
|
|
||||||
si.submit()
|
|
||||||
|
|
||||||
self.assertEquals(frappe.db.get_value("Time Log Batch", tlb.name, "status"), "Billed")
|
|
||||||
|
|
||||||
self.assertEquals(frappe.db.get_value("Time Log", time_log, "status"), "Billed")
|
|
||||||
|
|
||||||
si.cancel()
|
|
||||||
|
|
||||||
self.assertEquals(frappe.db.get_value("Time Log Batch", tlb.name, "status"), "Submitted")
|
|
||||||
|
|
||||||
self.assertEquals(frappe.db.get_value("Time Log", time_log, "status"), "Batched for Billing")
|
|
||||||
|
|
||||||
frappe.delete_doc("Sales Invoice", si.name)
|
|
||||||
delete_time_log_and_batch()
|
|
||||||
|
|
||||||
def test_sales_invoice_gl_entry_without_aii(self):
|
def test_sales_invoice_gl_entry_without_aii(self):
|
||||||
set_perpetual_inventory(0)
|
set_perpetual_inventory(0)
|
||||||
si = frappe.copy_doc(test_records[1])
|
si = frappe.copy_doc(test_records[1])
|
||||||
|
|||||||
@ -215,7 +215,7 @@ class GrossProfitGenerator(object):
|
|||||||
if self.filters.to_date:
|
if self.filters.to_date:
|
||||||
conditions += " and posting_date <= %(to_date)s"
|
conditions += " and posting_date <= %(to_date)s"
|
||||||
|
|
||||||
self.si_list = frappe.db.sql("""select item.parenttype, item.parent,
|
self.si_list = frappe.db.sql("""select item.parenttype, item.parent,
|
||||||
si.posting_date, si.posting_time, si.project_name, si.update_stock,
|
si.posting_date, si.posting_time, si.project_name, si.update_stock,
|
||||||
si.customer, si.customer_group, si.territory,
|
si.customer, si.customer_group, si.territory,
|
||||||
item.item_code, item.item_name, item.description, item.warehouse,
|
item.item_code, item.item_name, item.description, item.warehouse,
|
||||||
@ -257,4 +257,4 @@ class GrossProfitGenerator(object):
|
|||||||
|
|
||||||
def load_non_stock_items(self):
|
def load_non_stock_items(self):
|
||||||
self.non_stock_items = frappe.db.sql_list("""select name from tabItem
|
self.non_stock_items = frappe.db.sql_list("""select name from tabItem
|
||||||
where ifnull(is_stock_item, 'No')='No'""")
|
where is_stock_item=0""")
|
||||||
|
|||||||
@ -44,12 +44,12 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
|
|||||||
if(me.frm.doc.is_subcontracted == "Yes") {
|
if(me.frm.doc.is_subcontracted == "Yes") {
|
||||||
return{
|
return{
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query",
|
||||||
filters:{ 'is_sub_contracted_item': 'Yes' }
|
filters:{ 'is_sub_contracted_item': 1 }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return{
|
return{
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query",
|
||||||
filters: { 'is_purchase_item': 'Yes' }
|
filters: { 'is_purchase_item': 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -56,24 +56,25 @@ class PurchaseCommon(BuyingController):
|
|||||||
d.set(x, f_lst[x])
|
d.set(x, f_lst[x])
|
||||||
|
|
||||||
item = frappe.db.sql("""select is_stock_item, is_purchase_item,
|
item = frappe.db.sql("""select is_stock_item, is_purchase_item,
|
||||||
is_sub_contracted_item, end_of_life from `tabItem` where name=%s""", d.item_code)
|
is_sub_contracted_item, end_of_life from `tabItem` where name=%s""",
|
||||||
|
d.item_code, as_dict=1)[0]
|
||||||
|
|
||||||
from erpnext.stock.doctype.item.item import validate_end_of_life
|
from erpnext.stock.doctype.item.item import validate_end_of_life
|
||||||
validate_end_of_life(d.item_code, item[0][3])
|
validate_end_of_life(d.item_code, item.end_of_life)
|
||||||
|
|
||||||
# validate stock item
|
# validate stock item
|
||||||
if item[0][0]=='Yes' and d.qty and not d.warehouse:
|
if item.is_stock_item==1 and d.qty and not d.warehouse:
|
||||||
frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))
|
frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))
|
||||||
|
|
||||||
# validate purchase item
|
# validate purchase item
|
||||||
if not (obj.doctype=="Material Request" and getattr(obj, "material_request_type", None)=="Material Transfer"):
|
if not (obj.doctype=="Material Request" and getattr(obj, "material_request_type", None)=="Material Transfer"):
|
||||||
if item[0][1] != 'Yes' and item[0][2] != 'Yes':
|
if item.is_purchase_item != 1 and item.is_sub_contracted_item != 1:
|
||||||
frappe.throw(_("{0} must be a Purchased or Sub-Contracted Item in row {1}").format(d.item_code, d.idx))
|
frappe.throw(_("{0} must be a Purchased or Sub-Contracted Item in row {1}").format(d.item_code, d.idx))
|
||||||
|
|
||||||
items.append(cstr(d.item_code))
|
items.append(cstr(d.item_code))
|
||||||
if items and len(items) != len(set(items)):
|
if items and len(items) != len(set(items)):
|
||||||
frappe.msgprint(_("Warning: Same item has been entered multiple times."))
|
frappe.msgprint(_("Warning: Same item has been entered multiple times."))
|
||||||
|
|
||||||
|
|
||||||
def check_for_stopped_status(self, doctype, docname):
|
def check_for_stopped_status(self, doctype, docname):
|
||||||
stopped = frappe.db.sql("""select name from `tab%s` where name = %s and
|
stopped = frappe.db.sql("""select name from `tab%s` where name = %s and
|
||||||
|
|||||||
@ -153,7 +153,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
item_wh_list = []
|
item_wh_list = []
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if (not po_item_rows or d.name in po_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
|
if (not po_item_rows or d.name in po_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
|
||||||
and frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" and d.warehouse:
|
and frappe.db.get_value("Item", d.item_code, "is_stock_item") and d.warehouse:
|
||||||
item_wh_list.append([d.item_code, d.warehouse])
|
item_wh_list.append([d.item_code, d.warehouse])
|
||||||
|
|
||||||
for item_code, warehouse in item_wh_list:
|
for item_code, warehouse in item_wh_list:
|
||||||
|
|||||||
@ -5,7 +5,13 @@ frappe.listview_settings['Purchase Order'] = {
|
|||||||
if(doc.status==="Stopped") {
|
if(doc.status==="Stopped") {
|
||||||
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
||||||
} else if(flt(doc.per_received) < 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_received) < 100 && doc.status!=="Stopped") {
|
||||||
return [__("Not Received"), "orange", "per_received,<,100|status,!=,Stopped"];
|
if(flt(doc.per_billed) < 100) {
|
||||||
|
return [__("To Receive and Bill"), "orange",
|
||||||
|
"per_received,<,100|per_billed,<,100|status,!=,Stopped"];
|
||||||
|
} else {
|
||||||
|
return [__("To Receive"), "orange",
|
||||||
|
"per_received,<,100|per_billed,=,100|status,!=,Stopped"];
|
||||||
|
}
|
||||||
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
|
||||||
return [__("To Bill"), "orange", "per_received,=,100|per_billed,<,100|status,!=,Stopped"];
|
return [__("To Bill"), "orange", "per_received,=,100|per_billed,<,100|status,!=,Stopped"];
|
||||||
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
|
||||||
|
|||||||
@ -54,6 +54,13 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "is_frozen",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Frozen",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:!doc.__islocal",
|
"depends_on": "eval:!doc.__islocal",
|
||||||
"fieldname": "address_contacts",
|
"fieldname": "address_contacts",
|
||||||
@ -172,7 +179,7 @@
|
|||||||
],
|
],
|
||||||
"icon": "icon-user",
|
"icon": "icon-user",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2015-07-13 05:28:29.121285",
|
"modified": "2015-07-17 09:39:05.318826",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Supplier",
|
"name": "Supplier",
|
||||||
|
|||||||
9
erpnext/change_log/v5/v5_4_0.md
Normal file
9
erpnext/change_log/v5/v5_4_0.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
- Sales / Purchase Return Enahancement - **Sponsored by [Strella Consulting Sdn Bhd](http://www.strellagroup.com)**
|
||||||
|
* Now you can make Return entry by creating Delivery Note, Purchase Receipt or Sales / Purchase Invoice with negative quantity
|
||||||
|
- **Item** form cleanups: "Yes" / "No" type fields changed to checkboxes.<br>
|
||||||
|
**Warning**: This could break your 3rd party integrations with Item, if any
|
||||||
|
- Leave Application: Consideration of **holidays** in calculation of 'Number of Days' is now optional. You can set it in Leave Type record.
|
||||||
|
- Customer / Supplier can be **freezed** now
|
||||||
|
- Fix: Reserved qty calculation while delivering Product Bundle via Sales Invoice
|
||||||
|
- Fix: Deleted stock ledger entries on cancellation of Sales Invoice while Product Bundle delivered
|
||||||
|
- Fix: Fetch default expense account and cost center from item based on selected company
|
||||||
@ -11,11 +11,14 @@ from erpnext.utilities.transaction_base import TransactionBase
|
|||||||
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
|
||||||
from erpnext.controllers.sales_and_purchase_return import validate_return
|
from erpnext.controllers.sales_and_purchase_return import validate_return
|
||||||
|
|
||||||
|
class CustomerFrozen(frappe.ValidationError): pass
|
||||||
|
|
||||||
class AccountsController(TransactionBase):
|
class AccountsController(TransactionBase):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.get("_action") and self._action != "update_after_submit":
|
if self.get("_action") and self._action != "update_after_submit":
|
||||||
self.set_missing_values(for_validate=True)
|
self.set_missing_values(for_validate=True)
|
||||||
self.validate_date_with_fiscal_year()
|
self.validate_date_with_fiscal_year()
|
||||||
|
|
||||||
if self.meta.get_field("currency"):
|
if self.meta.get_field("currency"):
|
||||||
self.calculate_taxes_and_totals()
|
self.calculate_taxes_and_totals()
|
||||||
if not self.meta.get_field("is_return") or not self.is_return:
|
if not self.meta.get_field("is_return") or not self.is_return:
|
||||||
@ -32,6 +35,8 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
if self.meta.get_field("taxes_and_charges"):
|
if self.meta.get_field("taxes_and_charges"):
|
||||||
self.validate_enabled_taxes_and_charges()
|
self.validate_enabled_taxes_and_charges()
|
||||||
|
|
||||||
|
self.validate_party()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if self.meta.get_field("is_recurring"):
|
if self.meta.get_field("is_recurring"):
|
||||||
@ -302,7 +307,7 @@ class AccountsController(TransactionBase):
|
|||||||
item_codes = list(set(item.item_code for item in self.get("items")))
|
item_codes = list(set(item.item_code for item in self.get("items")))
|
||||||
if item_codes:
|
if item_codes:
|
||||||
stock_items = [r[0] for r in frappe.db.sql("""select name
|
stock_items = [r[0] for r in frappe.db.sql("""select name
|
||||||
from `tabItem` where name in (%s) and is_stock_item='Yes'""" % \
|
from `tabItem` where name in (%s) and is_stock_item=1""" % \
|
||||||
(", ".join((["%s"]*len(item_codes))),), item_codes)]
|
(", ".join((["%s"]*len(item_codes))),), item_codes)]
|
||||||
|
|
||||||
return stock_items
|
return stock_items
|
||||||
@ -340,6 +345,23 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
return self._abbr
|
return self._abbr
|
||||||
|
|
||||||
|
def validate_party(self):
|
||||||
|
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
|
||||||
|
if frozen_accounts_modifier in frappe.get_roles():
|
||||||
|
return
|
||||||
|
|
||||||
|
party_type = None
|
||||||
|
if self.meta.get_field("customer"):
|
||||||
|
party_type = 'Customer'
|
||||||
|
|
||||||
|
elif self.meta.get_field("supplier"):
|
||||||
|
party_type = 'Supplier'
|
||||||
|
|
||||||
|
if party_type:
|
||||||
|
party = self.get(party_type.lower())
|
||||||
|
if frappe.db.get_value(party_type, party, "is_frozen"):
|
||||||
|
frappe.throw("{0} {1} is frozen".format(party_type, party), CustomerFrozen)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_tax_rate(account_head):
|
def get_tax_rate(account_head):
|
||||||
return frappe.db.get_value("Account", account_head, "tax_rate")
|
return frappe.db.get_value("Account", account_head, "tax_rate")
|
||||||
|
|||||||
@ -238,8 +238,8 @@ class BuyingController(StockController):
|
|||||||
t2.rate, t2.stock_uom, t2.name, t2.description
|
t2.rate, t2.stock_uom, t2.name, t2.description
|
||||||
from `tabBOM` t1, `tabBOM Item` t2, tabItem t3
|
from `tabBOM` t1, `tabBOM Item` t2, tabItem t3
|
||||||
where t2.parent = t1.name and t1.item = %s
|
where t2.parent = t1.name and t1.item = %s
|
||||||
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
|
and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s
|
||||||
and t2.item_code = t3.name and ifnull(t3.is_stock_item, 'No') = 'Yes'""", (item_code, bom), as_dict=1)
|
and t2.item_code = t3.name and t3.is_stock_item = 1""", (item_code, bom), as_dict=1)
|
||||||
|
|
||||||
if not bom_items:
|
if not bom_items:
|
||||||
msgprint(_("Specified BOM {0} does not exist for Item {1}").format(bom, item_code), raise_exception=1)
|
msgprint(_("Specified BOM {0} does not exist for Item {1}").format(bom, item_code), raise_exception=1)
|
||||||
@ -254,7 +254,7 @@ class BuyingController(StockController):
|
|||||||
self.get("items")))
|
self.get("items")))
|
||||||
if item_codes:
|
if item_codes:
|
||||||
self._sub_contracted_items = [r[0] for r in frappe.db.sql("""select name
|
self._sub_contracted_items = [r[0] for r in frappe.db.sql("""select name
|
||||||
from `tabItem` where name in (%s) and is_sub_contracted_item='Yes'""" % \
|
from `tabItem` where name in (%s) and is_sub_contracted_item=1""" % \
|
||||||
(", ".join((["%s"]*len(item_codes))),), item_codes)]
|
(", ".join((["%s"]*len(item_codes))),), item_codes)]
|
||||||
|
|
||||||
return self._sub_contracted_items
|
return self._sub_contracted_items
|
||||||
|
|||||||
@ -107,8 +107,15 @@ def make_return_doc(doctype, source_name, target_doc=None):
|
|||||||
doc.is_return = 1
|
doc.is_return = 1
|
||||||
doc.return_against = source.name
|
doc.return_against = source.name
|
||||||
doc.ignore_pricing_rule = 1
|
doc.ignore_pricing_rule = 1
|
||||||
|
if doctype == "Sales Invoice":
|
||||||
|
doc.is_pos = 0
|
||||||
|
|
||||||
|
for tax in doc.get("taxes"):
|
||||||
|
if tax.charge_type == "Actual":
|
||||||
|
tax.tax_amount = -1 * tax.tax_amount
|
||||||
|
|
||||||
doc.run_method("calculate_taxes_and_totals")
|
doc.run_method("calculate_taxes_and_totals")
|
||||||
|
|
||||||
def update_item(source_doc, target_doc, source_parent):
|
def update_item(source_doc, target_doc, source_parent):
|
||||||
target_doc.qty = -1* source_doc.qty
|
target_doc.qty = -1* source_doc.qty
|
||||||
if doctype == "Purchase Receipt":
|
if doctype == "Purchase Receipt":
|
||||||
|
|||||||
@ -174,12 +174,14 @@ class SellingController(StockController):
|
|||||||
if flt(d.qty) > flt(d.delivered_qty):
|
if flt(d.qty) > flt(d.delivered_qty):
|
||||||
reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
|
reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
|
||||||
|
|
||||||
elif self.doctype == "Delivery Note" and d.against_sales_order and not self.is_return:
|
elif (((self.doctype == "Delivery Note" and d.against_sales_order)
|
||||||
|
or (self.doctype == "Sales Invoice" and d.sales_order and self.update_stock))
|
||||||
|
and not self.is_return):
|
||||||
# if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12.
|
# if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12.
|
||||||
# But in this case reserved qty should only be reduced by 10 and not 12
|
# But in this case reserved qty should only be reduced by 10 and not 12
|
||||||
|
|
||||||
already_delivered_qty = self.get_already_delivered_qty(self.name,
|
already_delivered_qty = self.get_already_delivered_qty(self.name,
|
||||||
d.against_sales_order, d.so_detail)
|
d.against_sales_order if self.doctype=="Delivery Note" else d.sales_order, d.so_detail)
|
||||||
so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.so_detail)
|
so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.so_detail)
|
||||||
|
|
||||||
if already_delivered_qty + d.qty > so_qty:
|
if already_delivered_qty + d.qty > so_qty:
|
||||||
@ -221,12 +223,21 @@ class SellingController(StockController):
|
|||||||
return frappe.db.sql("""select name from `tabProduct Bundle`
|
return frappe.db.sql("""select name from `tabProduct Bundle`
|
||||||
where new_item_code=%s and docstatus != 2""", item_code)
|
where new_item_code=%s and docstatus != 2""", item_code)
|
||||||
|
|
||||||
def get_already_delivered_qty(self, dn, so, so_detail):
|
def get_already_delivered_qty(self, current_docname, so, so_detail):
|
||||||
qty = frappe.db.sql("""select sum(qty) from `tabDelivery Note Item`
|
delivered_via_dn = frappe.db.sql("""select sum(qty) from `tabDelivery Note Item`
|
||||||
where so_detail = %s and docstatus = 1
|
where so_detail = %s and docstatus = 1
|
||||||
and against_sales_order = %s
|
and against_sales_order = %s
|
||||||
and parent != %s""", (so_detail, so, dn))
|
and parent != %s""", (so_detail, so, current_docname))
|
||||||
return qty and flt(qty[0][0]) or 0.0
|
|
||||||
|
delivered_via_si = frappe.db.sql("""select sum(qty) from `tabSales Invoice Item`
|
||||||
|
where so_detail = %s and docstatus = 1
|
||||||
|
and sales_order = %s
|
||||||
|
and parent != %s""", (so_detail, so, current_docname))
|
||||||
|
|
||||||
|
total_delivered_qty = (flt(delivered_via_dn[0][0]) if delivered_via_dn else 0) \
|
||||||
|
+ (flt(delivered_via_si[0][0]) if delivered_via_si else 0)
|
||||||
|
|
||||||
|
return total_delivered_qty
|
||||||
|
|
||||||
def get_so_qty_and_warehouse(self, so_detail):
|
def get_so_qty_and_warehouse(self, so_detail):
|
||||||
so_item = frappe.db.sql("""select qty, warehouse from `tabSales Order Item`
|
so_item = frappe.db.sql("""select qty, warehouse from `tabSales Order Item`
|
||||||
@ -248,7 +259,7 @@ def check_active_sales_items(obj):
|
|||||||
item = frappe.db.sql("""select docstatus, is_sales_item,
|
item = frappe.db.sql("""select docstatus, is_sales_item,
|
||||||
is_service_item, income_account from tabItem where name = %s""",
|
is_service_item, income_account from tabItem where name = %s""",
|
||||||
d.item_code, as_dict=True)[0]
|
d.item_code, as_dict=True)[0]
|
||||||
if item.is_sales_item == 'No' and item.is_service_item == 'No':
|
if item.is_sales_item == 0 and item.is_service_item == 0:
|
||||||
frappe.throw(_("Item {0} must be Sales or Service Item in {1}").format(d.item_code, d.idx))
|
frappe.throw(_("Item {0} must be Sales or Service Item in {1}").format(d.item_code, d.idx))
|
||||||
if getattr(d, "income_account", None) and not item.income_account:
|
if getattr(d, "income_account", None) and not item.income_account:
|
||||||
frappe.db.set_value("Item", d.item_code, "income_account",
|
frappe.db.set_value("Item", d.item_code, "income_account",
|
||||||
|
|||||||
@ -9,6 +9,8 @@ import frappe.defaults
|
|||||||
|
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
|
from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
|
||||||
|
from erpnext.stock.utils import update_bin
|
||||||
|
|
||||||
|
|
||||||
class StockController(AccountsController):
|
class StockController(AccountsController):
|
||||||
def make_gl_entries(self, repost_future_gle=True):
|
def make_gl_entries(self, repost_future_gle=True):
|
||||||
@ -212,7 +214,7 @@ class StockController(AccountsController):
|
|||||||
item_codes = list(set([d.item_code for d in self.get("items")]))
|
item_codes = list(set([d.item_code for d in self.get("items")]))
|
||||||
if item_codes:
|
if item_codes:
|
||||||
serialized_items = frappe.db.sql_list("""select name from `tabItem`
|
serialized_items = frappe.db.sql_list("""select name from `tabItem`
|
||||||
where has_serial_no='Yes' and name in ({})""".format(", ".join(["%s"]*len(item_codes))),
|
where has_serial_no=1 and name in ({})""".format(", ".join(["%s"]*len(item_codes))),
|
||||||
tuple(item_codes))
|
tuple(item_codes))
|
||||||
|
|
||||||
return serialized_items
|
return serialized_items
|
||||||
@ -227,6 +229,23 @@ class StockController(AccountsController):
|
|||||||
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
|
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
|
||||||
|
|
||||||
return incoming_rate
|
return incoming_rate
|
||||||
|
|
||||||
|
def update_reserved_qty(self, d):
|
||||||
|
if d['reserved_qty'] < 0 :
|
||||||
|
# Reduce reserved qty from reserved warehouse mentioned in so
|
||||||
|
if not d["reserved_warehouse"]:
|
||||||
|
frappe.throw(_("Reserved Warehouse is missing in Sales Order"))
|
||||||
|
|
||||||
|
args = {
|
||||||
|
"item_code": d['item_code'],
|
||||||
|
"warehouse": d["reserved_warehouse"],
|
||||||
|
"voucher_type": self.doctype,
|
||||||
|
"voucher_no": self.name,
|
||||||
|
"reserved_qty": (self.docstatus==1 and 1 or -1)*flt(d['reserved_qty']),
|
||||||
|
"posting_date": self.posting_date,
|
||||||
|
"is_amended": self.amended_from and 'Yes' or 'No'
|
||||||
|
}
|
||||||
|
update_bin(args)
|
||||||
|
|
||||||
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
|
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
|
||||||
warehouse_account=None):
|
warehouse_account=None):
|
||||||
|
|||||||
@ -77,9 +77,6 @@ class calculate_taxes_and_totals(object):
|
|||||||
if not self.discount_amount_applied:
|
if not self.discount_amount_applied:
|
||||||
validate_taxes_and_charges(tax)
|
validate_taxes_and_charges(tax)
|
||||||
validate_inclusive_tax(tax, self.doc)
|
validate_inclusive_tax(tax, self.doc)
|
||||||
|
|
||||||
if self.doc.meta.get_field("is_return") and self.doc.is_return and tax.charge_type == "Actual":
|
|
||||||
tax.tax_amount = -1 * tax.tax_amount
|
|
||||||
|
|
||||||
tax.item_wise_tax_detail = {}
|
tax.item_wise_tax_detail = {}
|
||||||
tax_fields = ["total", "tax_amount_after_discount_amount",
|
tax_fields = ["total", "tax_amount_after_discount_amount",
|
||||||
|
|||||||
@ -48,7 +48,7 @@ erpnext.crm.Opportunity = frappe.ui.form.Controller.extend({
|
|||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query",
|
||||||
filters: me.frm.doc.enquiry_type === "Maintenance" ?
|
filters: me.frm.doc.enquiry_type === "Maintenance" ?
|
||||||
{"is_service_item": "Yes"} : {"is_sales_item": "Yes"}
|
{"is_service_item": 1} : {"is_sales_item":1}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ blogs.
|
|||||||
"""
|
"""
|
||||||
app_icon = "icon-th"
|
app_icon = "icon-th"
|
||||||
app_color = "#e74c3c"
|
app_color = "#e74c3c"
|
||||||
app_version = "5.3.1"
|
app_version = "5.4.0"
|
||||||
github_link = "https://github.com/frappe/erpnext"
|
github_link = "https://github.com/frappe/erpnext"
|
||||||
|
|
||||||
error_report_email = "support@erpnext.com"
|
error_report_email = "support@erpnext.com"
|
||||||
|
|||||||
@ -238,10 +238,15 @@ def get_total_leave_days(leave_app):
|
|||||||
ret = {'total_leave_days' : 0.5}
|
ret = {'total_leave_days' : 0.5}
|
||||||
if not leave_app.half_day:
|
if not leave_app.half_day:
|
||||||
tot_days = date_diff(leave_app.to_date, leave_app.from_date) + 1
|
tot_days = date_diff(leave_app.to_date, leave_app.from_date) + 1
|
||||||
holidays = leave_app.get_holidays()
|
if frappe.db.get_value("Leave Type", leave_app.leave_type, "include_holiday"):
|
||||||
ret = {
|
holidays = leave_app.get_holidays()
|
||||||
'total_leave_days' : flt(tot_days)-flt(holidays)
|
ret = {
|
||||||
}
|
'total_leave_days' : flt(tot_days)-flt(holidays)
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
ret = {
|
||||||
|
'total_leave_days' : flt(tot_days)
|
||||||
|
}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@ -246,4 +246,4 @@ class TestLeaveApplication(unittest.TestCase):
|
|||||||
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
|
frappe.db.sql("""delete from `tabEmployee Leave Approver` where parent=%s""",
|
||||||
"_T-Employee-0001")
|
"_T-Employee-0001")
|
||||||
|
|
||||||
frappe.db.set_value("Employee", "_T-Employee-0001", "department", original_department)
|
frappe.db.set_value("Employee", "_T-Employee-0001", "department", original_department)
|
||||||
@ -59,11 +59,17 @@
|
|||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Allow Negative Balance",
|
"label": "Allow Negative Balance",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "include_holiday",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Include holidays within leaves as leaves",
|
||||||
|
"permlevel": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-flag",
|
"icon": "icon-flag",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2015-05-08 05:15:24.194053",
|
"modified": "2015-07-29 05:15:24",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Leave Type",
|
"name": "Leave Type",
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"doctype": "Leave Type",
|
"doctype": "Leave Type",
|
||||||
"leave_type_name": "_Test Leave Type"
|
"leave_type_name": "_Test Leave Type",
|
||||||
|
"include_holiday": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Leave Type",
|
"doctype": "Leave Type",
|
||||||
"is_lwp": 1,
|
"is_lwp": 1,
|
||||||
"leave_type_name": "_Test Leave Type LWP"
|
"leave_type_name": "_Test Leave Type LWP",
|
||||||
|
"include_holiday": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -1,193 +1,193 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"allow_copy": 0,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 0,
|
"allow_rename": 0,
|
||||||
"autoname": "Offer-.#####",
|
"autoname": "Offer-.#####",
|
||||||
"creation": "2015-03-04 14:20:17.662207",
|
"creation": "2015-03-04 14:20:17.662207",
|
||||||
"custom": 0,
|
"custom": 0,
|
||||||
"default_print_format": "Offer Letter",
|
"default_print_format": "Offer Letter",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Transaction",
|
"document_type": "Transaction",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"fieldname": "job_applicant",
|
"fieldname": "job_applicant",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Job Applicant",
|
"label": "Job Applicant",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Job Applicant",
|
"options": "Job Applicant",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0
|
"set_only_once": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "applicant_name",
|
"fieldname": "applicant_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Applicant Name",
|
"label": "Applicant Name",
|
||||||
"options": "job_applicant.applicant_name",
|
"options": "job_applicant.applicant_name",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"options": "Awaiting Response\nAccepted\nRejected ",
|
"options": "Awaiting Response\nAccepted\nRejected",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "",
|
"default": "",
|
||||||
"fieldname": "offer_date",
|
"fieldname": "offer_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Offer Date",
|
"label": "Offer Date",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"fieldname": "designation",
|
"fieldname": "designation",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Designation",
|
"label": "Designation",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Designation",
|
"options": "Designation",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 0,
|
"report_hide": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"set_only_once": 0
|
"set_only_once": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_4",
|
"fieldname": "section_break_4",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "offer_terms",
|
"fieldname": "offer_terms",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Offer Letter Terms",
|
"label": "Offer Letter Terms",
|
||||||
"options": "Offer Letter Term",
|
"options": "Offer Letter Term",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_14",
|
"fieldname": "section_break_14",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"fieldname": "select_terms",
|
"fieldname": "select_terms",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"ignore_user_permissions": 0,
|
"ignore_user_permissions": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Select Terms and Conditions",
|
"label": "Select Terms and Conditions",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Terms and Conditions",
|
"options": "Terms and Conditions",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 0,
|
"read_only": 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
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "terms",
|
"fieldname": "terms",
|
||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Text Editor",
|
||||||
"label": "Terms and Conditions",
|
"label": "Terms and Conditions",
|
||||||
"options": "",
|
"options": "",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "amended_from",
|
"fieldname": "amended_from",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Amended From",
|
"label": "Amended From",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Offer Letter",
|
"options": "Offer Letter",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_heading": 0,
|
"hide_heading": 0,
|
||||||
"hide_toolbar": 0,
|
"hide_toolbar": 0,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"in_dialog": 0,
|
"in_dialog": 0,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-04-01 05:51:39.841591",
|
"modified": "2015-07-29 05:51:39.841591",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Offer Letter",
|
"name": "Offer Letter",
|
||||||
"name_case": "",
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 1,
|
"amend": 1,
|
||||||
"cancel": 1,
|
"cancel": 1,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"import": 1,
|
"import": 1,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "HR User",
|
"role": "HR User",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 1,
|
"submit": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"read_only_onload": 0,
|
"read_only_onload": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"title_field": "applicant_name"
|
"title_field": "applicant_name"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class HubSettings(Document):
|
|||||||
def publish_selling_items(self):
|
def publish_selling_items(self):
|
||||||
"""Set `publish_in_hub`=1 for all Sales Items"""
|
"""Set `publish_in_hub`=1 for all Sales Items"""
|
||||||
for item in frappe.get_all("Item", fields=["name"],
|
for item in frappe.get_all("Item", fields=["name"],
|
||||||
filters={"is_sales_item": "Yes", "publish_in_hub": "0"}):
|
filters={"is_sales_item": 1, "publish_in_hub": "0"}):
|
||||||
frappe.db.set_value("Item", item.name, "publish_in_hub", 1)
|
frappe.db.set_value("Item", item.name, "publish_in_hub", 1)
|
||||||
|
|
||||||
def register(self):
|
def register(self):
|
||||||
|
|||||||
@ -107,7 +107,7 @@ class BOM(Document):
|
|||||||
rate = 0
|
rate = 0
|
||||||
if arg['bom_no']:
|
if arg['bom_no']:
|
||||||
rate = self.get_bom_unitcost(arg['bom_no'])
|
rate = self.get_bom_unitcost(arg['bom_no'])
|
||||||
elif arg and (arg['is_purchase_item'] == 'Yes' or arg['is_sub_contracted_item'] == 'Yes'):
|
elif arg and (arg['is_purchase_item'] == 1 or arg['is_sub_contracted_item'] == 1):
|
||||||
if self.rm_cost_as_per == 'Valuation Rate':
|
if self.rm_cost_as_per == 'Valuation Rate':
|
||||||
rate = self.get_valuation_rate(arg)
|
rate = self.get_valuation_rate(arg)
|
||||||
elif self.rm_cost_as_per == 'Last Purchase Rate':
|
elif self.rm_cost_as_per == 'Last Purchase Rate':
|
||||||
@ -364,7 +364,7 @@ class BOM(Document):
|
|||||||
if self.with_operations and not self.get('operations'):
|
if self.with_operations and not self.get('operations'):
|
||||||
frappe.throw(_("Operations cannot be left blank."))
|
frappe.throw(_("Operations cannot be left blank."))
|
||||||
|
|
||||||
def get_bom_items_as_dict(bom, qty=1, fetch_exploded=1):
|
def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1):
|
||||||
item_dict = {}
|
item_dict = {}
|
||||||
|
|
||||||
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
|
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
|
||||||
@ -385,14 +385,14 @@ def get_bom_items_as_dict(bom, qty=1, fetch_exploded=1):
|
|||||||
and bom_item.docstatus < 2
|
and bom_item.docstatus < 2
|
||||||
and bom_item.parent = %(bom)s
|
and bom_item.parent = %(bom)s
|
||||||
and item.name = bom_item.item_code
|
and item.name = bom_item.item_code
|
||||||
and ifnull(item.is_stock_item, 'No') = 'Yes'
|
and is_stock_item = 1
|
||||||
{conditions}
|
{conditions}
|
||||||
group by item_code, stock_uom"""
|
group by item_code, stock_uom"""
|
||||||
|
|
||||||
if fetch_exploded:
|
if fetch_exploded:
|
||||||
query = query.format(table="BOM Explosion Item",
|
query = query.format(table="BOM Explosion Item",
|
||||||
conditions="""and ifnull(item.is_pro_applicable, 'No') = 'No'
|
conditions="""and item.is_pro_applicable = 0
|
||||||
and ifnull(item.is_sub_contracted_item, 'No') = 'No' """)
|
and item.is_sub_contracted_item = 0 """)
|
||||||
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
||||||
else:
|
else:
|
||||||
query = query.format(table="BOM Item", conditions="")
|
query = query.format(table="BOM Item", conditions="")
|
||||||
@ -405,11 +405,18 @@ def get_bom_items_as_dict(bom, qty=1, fetch_exploded=1):
|
|||||||
else:
|
else:
|
||||||
item_dict[item.item_code] = item
|
item_dict[item.item_code] = item
|
||||||
|
|
||||||
|
for item, item_details in item_dict.items():
|
||||||
|
for d in [["Account", "expense_account", "default_expense_account"],
|
||||||
|
["Cost Center", "cost_center", "cost_center"], ["Warehouse", "default_warehouse", ""]]:
|
||||||
|
company_in_record = frappe.db.get_value(d[0], item_details.get(d[1]), "company")
|
||||||
|
if not item_details.get(d[1]) or (company_in_record and company != company_in_record):
|
||||||
|
item_dict[item][d[1]] = frappe.db.get_value("Company", company, d[2]) if d[2] else None
|
||||||
|
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_bom_items(bom, qty=1, fetch_exploded=1):
|
def get_bom_items(bom, company, qty=1, fetch_exploded=1):
|
||||||
items = get_bom_items_as_dict(bom, qty, fetch_exploded).values()
|
items = get_bom_items_as_dict(bom, company, qty, fetch_exploded).values()
|
||||||
items.sort(lambda a, b: a.item_code > b.item_code and 1 or -1)
|
items.sort(lambda a, b: a.item_code > b.item_code and 1 or -1)
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|||||||
@ -12,14 +12,14 @@ test_records = frappe.get_test_records('BOM')
|
|||||||
class TestBOM(unittest.TestCase):
|
class TestBOM(unittest.TestCase):
|
||||||
def test_get_items(self):
|
def test_get_items(self):
|
||||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||||
items_dict = get_bom_items_as_dict(bom=get_default_bom(), qty=1, fetch_exploded=0)
|
items_dict = get_bom_items_as_dict(bom=get_default_bom(), company="_Test Company", qty=1, fetch_exploded=0)
|
||||||
self.assertTrue(test_records[2]["items"][0]["item_code"] in items_dict)
|
self.assertTrue(test_records[2]["items"][0]["item_code"] in items_dict)
|
||||||
self.assertTrue(test_records[2]["items"][1]["item_code"] in items_dict)
|
self.assertTrue(test_records[2]["items"][1]["item_code"] in items_dict)
|
||||||
self.assertEquals(len(items_dict.values()), 2)
|
self.assertEquals(len(items_dict.values()), 2)
|
||||||
|
|
||||||
def test_get_items_exploded(self):
|
def test_get_items_exploded(self):
|
||||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||||
items_dict = get_bom_items_as_dict(bom=get_default_bom(), qty=1, fetch_exploded=1)
|
items_dict = get_bom_items_as_dict(bom=get_default_bom(), company="_Test Company", qty=1, fetch_exploded=1)
|
||||||
self.assertTrue(test_records[2]["items"][0]["item_code"] in items_dict)
|
self.assertTrue(test_records[2]["items"][0]["item_code"] in items_dict)
|
||||||
self.assertFalse(test_records[2]["items"][1]["item_code"] in items_dict)
|
self.assertFalse(test_records[2]["items"][1]["item_code"] in items_dict)
|
||||||
self.assertTrue(test_records[0]["items"][0]["item_code"] in items_dict)
|
self.assertTrue(test_records[0]["items"][0]["item_code"] in items_dict)
|
||||||
@ -28,7 +28,7 @@ class TestBOM(unittest.TestCase):
|
|||||||
|
|
||||||
def test_get_items_list(self):
|
def test_get_items_list(self):
|
||||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items
|
from erpnext.manufacturing.doctype.bom.bom import get_bom_items
|
||||||
self.assertEquals(len(get_bom_items(bom=get_default_bom())), 3)
|
self.assertEquals(len(get_bom_items(bom=get_default_bom(), company="_Test Company")), 3)
|
||||||
|
|
||||||
def test_default_bom(self):
|
def test_default_bom(self):
|
||||||
def _get_default_bom_in_item():
|
def _get_default_bom_in_item():
|
||||||
|
|||||||
@ -191,11 +191,10 @@ $.extend(cur_frm.cscript, {
|
|||||||
method: "set_production_order_operations"
|
method: "set_production_order_operations"
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
qty: function() {
|
qty: function() {
|
||||||
frappe.ui.form.trigger("Production Order", 'bom_no')
|
frappe.ui.form.trigger("Production Order", 'bom_no')
|
||||||
},
|
},
|
||||||
|
|
||||||
show_time_logs: function(doc, cdt, cdn) {
|
show_time_logs: function(doc, cdt, cdn) {
|
||||||
var child = locals[cdt][cdn]
|
var child = locals[cdt][cdn]
|
||||||
frappe.route_options = {"operation_id": child.name};
|
frappe.route_options = {"operation_id": child.name};
|
||||||
@ -250,8 +249,8 @@ cur_frm.cscript['Update Finished Goods'] = function() {
|
|||||||
cur_frm.fields_dict['production_item'].get_query = function(doc) {
|
cur_frm.fields_dict['production_item'].get_query = function(doc) {
|
||||||
return {
|
return {
|
||||||
filters:[
|
filters:[
|
||||||
['Item', 'is_pro_applicable', '=', 'Yes'],
|
['Item', 'is_pro_applicable', '=', 1],
|
||||||
['Item', 'has_variants', '=', 'No'],
|
['Item', 'has_variants', '=', 0]
|
||||||
['Item', 'end_of_life', '>=', frappe.datetime.nowdate()]
|
['Item', 'end_of_life', '>=', frappe.datetime.nowdate()]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -264,7 +263,3 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -94,7 +94,7 @@ class ProductionOrder(Document):
|
|||||||
(self.sales_order, self.production_item))[0][0]
|
(self.sales_order, self.production_item))[0][0]
|
||||||
# total qty in SO
|
# total qty in SO
|
||||||
so_qty = flt(so_item_qty) + flt(dnpi_qty)
|
so_qty = flt(so_item_qty) + flt(dnpi_qty)
|
||||||
|
|
||||||
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "over_production_allowance_percentage"))
|
allowance_percentage = flt(frappe.db.get_single_value("Manufacturing Settings", "over_production_allowance_percentage"))
|
||||||
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
|
if total_qty > so_qty + (allowance_percentage/100 * so_qty):
|
||||||
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item,
|
frappe.throw(_("Cannot produce more Item {0} than Sales Order quantity {1}").format(self.production_item,
|
||||||
@ -320,14 +320,14 @@ class ProductionOrder(Document):
|
|||||||
def delete_time_logs(self):
|
def delete_time_logs(self):
|
||||||
for time_log in frappe.get_all("Time Log", ["name"], {"production_order": self.name}):
|
for time_log in frappe.get_all("Time Log", ["name"], {"production_order": self.name}):
|
||||||
frappe.delete_doc("Time Log", time_log.name)
|
frappe.delete_doc("Time Log", time_log.name)
|
||||||
|
|
||||||
def validate_production_item(self):
|
def validate_production_item(self):
|
||||||
if frappe.db.get_value("Item", self.production_item, "is_pro_applicable")=='No':
|
if not frappe.db.get_value("Item", self.production_item, "is_pro_applicable"):
|
||||||
frappe.throw(_("Item is not allowed to have Production Order."), ProductionNotApplicableError)
|
frappe.throw(_("Item is not allowed to have Production Order."), ProductionNotApplicableError)
|
||||||
|
|
||||||
if frappe.db.get_value("Item", self.production_item, "has_variants"):
|
if frappe.db.get_value("Item", self.production_item, "has_variants"):
|
||||||
frappe.throw(_("Production Order cannot be raised against a Item Template"), ItemHasVariantError)
|
frappe.throw(_("Production Order cannot be raised against a Item Template"), ItemHasVariantError)
|
||||||
|
|
||||||
validate_end_of_life(self.production_item)
|
validate_end_of_life(self.production_item)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import unittest
|
import unittest
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import flt, get_datetime, time_diff_in_hours
|
from frappe.utils import flt, time_diff_in_hours, now, add_days
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||||
from erpnext.manufacturing.doctype.production_order.production_order \
|
from erpnext.manufacturing.doctype.production_order.production_order \
|
||||||
import make_stock_entry, make_time_log, ProductionNotApplicableError,ItemHasVariantError
|
import make_stock_entry, ProductionNotApplicableError,ItemHasVariantError
|
||||||
from erpnext.stock.doctype.stock_entry import test_stock_entry
|
from erpnext.stock.doctype.stock_entry import test_stock_entry
|
||||||
from erpnext.projects.doctype.time_log.time_log import OverProductionLoggedError
|
from erpnext.projects.doctype.time_log.time_log import OverProductionLoggedError
|
||||||
|
|
||||||
@ -68,8 +68,9 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
self.assertRaises(StockOverProductionError, s.submit)
|
self.assertRaises(StockOverProductionError, s.submit)
|
||||||
|
|
||||||
def test_make_time_log(self):
|
def test_make_time_log(self):
|
||||||
|
from erpnext.projects.doctype.time_log.test_time_log import make_time_log_test_record
|
||||||
prod_order = make_prod_order_test_record(item="_Test FG Item 2",
|
prod_order = make_prod_order_test_record(item="_Test FG Item 2",
|
||||||
planned_start_date="2014-11-25 00:00:00", qty=1, do_not_save=True)
|
planned_start_date=now(), qty=1, do_not_save=True)
|
||||||
|
|
||||||
prod_order.set_production_order_operations()
|
prod_order.set_production_order_operations()
|
||||||
prod_order.insert()
|
prod_order.insert()
|
||||||
@ -79,17 +80,13 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
|
|
||||||
d.completed_qty = flt(d.completed_qty)
|
d.completed_qty = flt(d.completed_qty)
|
||||||
|
|
||||||
time_log = make_time_log(prod_order.name, d.operation, \
|
time_log = make_time_log_test_record(hours=1, production_order= prod_order.name, operation= d.operation,
|
||||||
d.planned_start_time, d.planned_end_time, prod_order.qty - d.completed_qty,
|
completed_qty= prod_order.qty - d.completed_qty, operation_id=d.name, for_manufacturing=1, simulate=True)
|
||||||
operation_id=d.name)
|
|
||||||
|
|
||||||
self.assertEqual(prod_order.name, time_log.production_order)
|
self.assertEqual(prod_order.name, time_log.production_order)
|
||||||
self.assertEqual((prod_order.qty - d.completed_qty), time_log.completed_qty)
|
self.assertEqual((prod_order.qty - d.completed_qty), time_log.completed_qty)
|
||||||
self.assertEqual(time_diff_in_hours(d.planned_end_time, d.planned_start_time),time_log.hours)
|
self.assertEqual(time_diff_in_hours(d.planned_end_time, d.planned_start_time),time_log.hours)
|
||||||
|
|
||||||
time_log.save()
|
|
||||||
time_log.submit()
|
|
||||||
|
|
||||||
manufacturing_settings = frappe.get_doc({
|
manufacturing_settings = frappe.get_doc({
|
||||||
"doctype": "Manufacturing Settings",
|
"doctype": "Manufacturing Settings",
|
||||||
"allow_production_on_holidays": 0
|
"allow_production_on_holidays": 0
|
||||||
@ -101,11 +98,6 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
self.assertEqual(prod_order.operations[0].status, "Completed")
|
self.assertEqual(prod_order.operations[0].status, "Completed")
|
||||||
self.assertEqual(prod_order.operations[0].completed_qty, prod_order.qty)
|
self.assertEqual(prod_order.operations[0].completed_qty, prod_order.qty)
|
||||||
|
|
||||||
self.assertEqual(get_datetime(prod_order.operations[0].actual_start_time),
|
|
||||||
get_datetime(time_log.from_time))
|
|
||||||
self.assertEqual(get_datetime(prod_order.operations[0].actual_end_time),
|
|
||||||
get_datetime(time_log.to_time))
|
|
||||||
|
|
||||||
self.assertEqual(prod_order.operations[0].actual_operation_time, 60)
|
self.assertEqual(prod_order.operations[0].actual_operation_time, 60)
|
||||||
self.assertEqual(prod_order.operations[0].actual_operating_cost, 100)
|
self.assertEqual(prod_order.operations[0].actual_operating_cost, 100)
|
||||||
|
|
||||||
@ -118,37 +110,33 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
self.assertEqual(flt(prod_order.operations[0].actual_operation_time), 0)
|
self.assertEqual(flt(prod_order.operations[0].actual_operation_time), 0)
|
||||||
self.assertEqual(flt(prod_order.operations[0].actual_operating_cost), 0)
|
self.assertEqual(flt(prod_order.operations[0].actual_operating_cost), 0)
|
||||||
|
|
||||||
time_log2 = frappe.copy_doc(time_log)
|
time_log2 = make_time_log_test_record(from_time= add_days(time_log.to_time, 1) ,production_order= prod_order.name, operation= d.operation,
|
||||||
time_log2.update({
|
completed_qty= 5, operation_id=d.name, for_manufacturing=1, do_not_save=True)
|
||||||
"completed_qty": 10,
|
|
||||||
"from_time": "2014-11-26 00:00:00",
|
|
||||||
"to_time": "2014-11-26 00:00:00",
|
|
||||||
"docstatus": 0
|
|
||||||
})
|
|
||||||
self.assertRaises(OverProductionLoggedError, time_log2.save)
|
self.assertRaises(OverProductionLoggedError, time_log2.save)
|
||||||
|
|
||||||
def test_planned_operating_cost(self):
|
def test_planned_operating_cost(self):
|
||||||
prod_order = make_prod_order_test_record(item="_Test FG Item 2",
|
prod_order = make_prod_order_test_record(item="_Test FG Item 2",
|
||||||
planned_start_date="2014-11-25 00:00:00", qty=1, do_not_save=True)
|
planned_start_date=now(), qty=1, do_not_save=True)
|
||||||
prod_order.set_production_order_operations()
|
prod_order.set_production_order_operations()
|
||||||
cost = prod_order.planned_operating_cost
|
cost = prod_order.planned_operating_cost
|
||||||
prod_order.qty = 2
|
prod_order.qty = 2
|
||||||
prod_order.set_production_order_operations()
|
prod_order.set_production_order_operations()
|
||||||
self.assertEqual(prod_order.planned_operating_cost, cost*2)
|
self.assertEqual(prod_order.planned_operating_cost, cost*2)
|
||||||
|
|
||||||
def test_production_item(self):
|
def test_production_item(self):
|
||||||
frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", "No")
|
frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", 0)
|
||||||
|
|
||||||
prod_order = make_prod_order_test_record(item="_Test FG Item", qty=1, do_not_save=True)
|
prod_order = make_prod_order_test_record(item="_Test FG Item", qty=1, do_not_save=True)
|
||||||
self.assertRaises(ProductionNotApplicableError, prod_order.save)
|
self.assertRaises(ProductionNotApplicableError, prod_order.save)
|
||||||
|
|
||||||
frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", "Yes")
|
frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", 1)
|
||||||
frappe.db.set_value("Item", "_Test FG Item", "end_of_life", "2000-1-1")
|
frappe.db.set_value("Item", "_Test FG Item", "end_of_life", "2000-1-1")
|
||||||
|
|
||||||
self.assertRaises(frappe.ValidationError, prod_order.save)
|
self.assertRaises(frappe.ValidationError, prod_order.save)
|
||||||
|
|
||||||
frappe.db.set_value("Item", "_Test FG Item", "end_of_life", None)
|
frappe.db.set_value("Item", "_Test FG Item", "end_of_life", None)
|
||||||
|
|
||||||
prod_order = make_prod_order_test_record(item="_Test Variant Item", qty=1, do_not_save=True)
|
prod_order = make_prod_order_test_record(item="_Test Variant Item", qty=1, do_not_save=True)
|
||||||
self.assertRaises(ItemHasVariantError, prod_order.save)
|
self.assertRaises(ItemHasVariantError, prod_order.save)
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ cur_frm.fields_dict['sales_orders'].grid.get_field('sales_order').get_query = fu
|
|||||||
|
|
||||||
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc) {
|
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc) {
|
||||||
return erpnext.queries.item({
|
return erpnext.queries.item({
|
||||||
'is_pro_applicable': 'Yes'
|
'is_pro_applicable': 1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -61,13 +61,13 @@ class ProductionPlanningTool(Document):
|
|||||||
and so.company = %s
|
and so.company = %s
|
||||||
and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) %s
|
and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) %s
|
||||||
and (exists (select name from `tabItem` item where item.name=so_item.item_code
|
and (exists (select name from `tabItem` item where item.name=so_item.item_code
|
||||||
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
|
and (item.is_pro_applicable = 1
|
||||||
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s)
|
or item.is_sub_contracted_item = 1 %s)
|
||||||
or exists (select name from `tabPacked Item` pi
|
or exists (select name from `tabPacked Item` pi
|
||||||
where pi.parent = so.name and pi.parent_item = so_item.item_code
|
where pi.parent = so.name and pi.parent_item = so_item.item_code
|
||||||
and exists (select name from `tabItem` item where item.name=pi.item_code
|
and exists (select name from `tabItem` item where item.name=pi.item_code
|
||||||
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
|
and (item.is_pro_applicable = 1
|
||||||
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s)))
|
or item.is_sub_contracted_item = 1) %s)))
|
||||||
""" % ('%s', so_filter, item_filter, item_filter), self.company, as_dict=1)
|
""" % ('%s', so_filter, item_filter, item_filter), self.company, as_dict=1)
|
||||||
|
|
||||||
self.add_so_in_table(open_so)
|
self.add_so_in_table(open_so)
|
||||||
@ -108,8 +108,8 @@ class ProductionPlanningTool(Document):
|
|||||||
from `tabSales Order Item` so_item
|
from `tabSales Order Item` so_item
|
||||||
where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0)
|
where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0)
|
||||||
and exists (select * from `tabItem` item where item.name=so_item.item_code
|
and exists (select * from `tabItem` item where item.name=so_item.item_code
|
||||||
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
|
and (item.is_pro_applicable = 1
|
||||||
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes')) %s""" % \
|
or item.is_sub_contracted_item = 1)) %s""" % \
|
||||||
(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)
|
(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)
|
||||||
|
|
||||||
if self.fg_item:
|
if self.fg_item:
|
||||||
@ -123,8 +123,8 @@ class ProductionPlanningTool(Document):
|
|||||||
and pi.parent_item = so_item.item_code
|
and pi.parent_item = so_item.item_code
|
||||||
and so_item.parent in (%s) and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0)
|
and so_item.parent in (%s) and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0)
|
||||||
and exists (select * from `tabItem` item where item.name=pi.item_code
|
and exists (select * from `tabItem` item where item.name=pi.item_code
|
||||||
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
|
and (item.is_pro_applicable = 1
|
||||||
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes')) %s""" % \
|
or item.is_sub_contracted_item = 1)) %s""" % \
|
||||||
(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)
|
(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)
|
||||||
|
|
||||||
return items + packed_items
|
return items + packed_items
|
||||||
@ -178,7 +178,7 @@ class ProductionPlanningTool(Document):
|
|||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.bom_no:
|
if d.bom_no:
|
||||||
bom_dict.setdefault(d.bom_no, []).append([d.sales_order, flt(d.planned_qty)])
|
bom_dict.setdefault(d.bom_no, []).append([d.sales_order, flt(d.planned_qty)])
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_pro_applicable") == "Yes":
|
if frappe.db.get_value("Item", d.item_code, "is_pro_applicable"):
|
||||||
item_dict[(d.item_code, d.sales_order, d.warehouse)] = {
|
item_dict[(d.item_code, d.sales_order, d.warehouse)] = {
|
||||||
"production_item" : d.item_code,
|
"production_item" : d.item_code,
|
||||||
"sales_order" : d.sales_order,
|
"sales_order" : d.sales_order,
|
||||||
@ -239,10 +239,10 @@ class ProductionPlanningTool(Document):
|
|||||||
ifnull(sum(ifnull(fb.qty, 0)/ifnull(bom.quantity, 1)), 0) as qty,
|
ifnull(sum(ifnull(fb.qty, 0)/ifnull(bom.quantity, 1)), 0) as qty,
|
||||||
fb.description, fb.stock_uom, it.min_order_qty
|
fb.description, fb.stock_uom, it.min_order_qty
|
||||||
from `tabBOM Explosion Item` fb, `tabBOM` bom, `tabItem` it
|
from `tabBOM Explosion Item` fb, `tabBOM` bom, `tabItem` it
|
||||||
where bom.name = fb.parent and it.name = fb.item_code
|
where bom.name = fb.parent and it.name = fb.item_code
|
||||||
and ifnull(it.is_pro_applicable, 'No') = 'No'
|
and is_pro_applicable = 0
|
||||||
and ifnull(it.is_sub_contracted_item, 'No') = 'No'
|
and is_sub_contracted_item = 0
|
||||||
and ifnull(it.is_stock_item, 'No') = 'Yes'
|
and is_stock_item = 1
|
||||||
and fb.docstatus<2 and bom.name=%s
|
and fb.docstatus<2 and bom.name=%s
|
||||||
group by item_code, stock_uom""", bom, as_dict=1):
|
group by item_code, stock_uom""", bom, as_dict=1):
|
||||||
bom_wise_item_details.setdefault(d.item_code, d)
|
bom_wise_item_details.setdefault(d.item_code, d)
|
||||||
@ -255,7 +255,7 @@ class ProductionPlanningTool(Document):
|
|||||||
from `tabBOM Item` bom_item, `tabBOM` bom, tabItem item
|
from `tabBOM Item` bom_item, `tabBOM` bom, tabItem item
|
||||||
where bom.name = bom_item.parent and bom.name = %s and bom_item.docstatus < 2
|
where bom.name = bom_item.parent and bom.name = %s and bom_item.docstatus < 2
|
||||||
and bom_item.item_code = item.name
|
and bom_item.item_code = item.name
|
||||||
and ifnull(item.is_stock_item, 'No') = 'Yes'
|
and item.is_stock_item = 1
|
||||||
group by item_code""", bom, as_dict=1):
|
group by item_code""", bom, as_dict=1):
|
||||||
bom_wise_item_details.setdefault(d.item_code, d)
|
bom_wise_item_details.setdefault(d.item_code, d)
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ class ProductionPlanningTool(Document):
|
|||||||
|
|
||||||
def insert_purchase_request(self):
|
def insert_purchase_request(self):
|
||||||
items_to_be_requested = self.get_requested_items()
|
items_to_be_requested = self.get_requested_items()
|
||||||
|
|
||||||
purchase_request_list = []
|
purchase_request_list = []
|
||||||
if items_to_be_requested:
|
if items_to_be_requested:
|
||||||
for item in items_to_be_requested:
|
for item in items_to_be_requested:
|
||||||
|
|||||||
@ -24,6 +24,9 @@ erpnext.patches.v4_0.map_charge_to_taxes_and_charges
|
|||||||
execute:frappe.reload_doc('support', 'doctype', 'newsletter') # 2014-01-31
|
execute:frappe.reload_doc('support', 'doctype', 'newsletter') # 2014-01-31
|
||||||
execute:frappe.reload_doc('hr', 'doctype', 'employee') # 2014-02-03
|
execute:frappe.reload_doc('hr', 'doctype', 'employee') # 2014-02-03
|
||||||
execute:frappe.db.sql("update tabPage set module='Core' where name='Setup'")
|
execute:frappe.db.sql("update tabPage set module='Core' where name='Setup'")
|
||||||
|
|
||||||
|
# inserted this patch here since Item types are being changed
|
||||||
|
erpnext.patches.v5_2.change_item_selects_to_checks
|
||||||
erpnext.patches.v4_0.fields_to_be_renamed
|
erpnext.patches.v4_0.fields_to_be_renamed
|
||||||
erpnext.patches.v4_0.rename_sitemap_to_route
|
erpnext.patches.v4_0.rename_sitemap_to_route
|
||||||
erpnext.patches.v4_0.fix_contact_address
|
erpnext.patches.v4_0.fix_contact_address
|
||||||
@ -176,4 +179,7 @@ erpnext.patches.v5_1.fix_credit_days_based_on
|
|||||||
execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
|
execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
|
||||||
erpnext.patches.v5_1.rename_roles
|
erpnext.patches.v5_1.rename_roles
|
||||||
erpnext.patches.v5_1.default_bom
|
erpnext.patches.v5_1.default_bom
|
||||||
execute:frappe.delete_doc("DocType", "Party Type")
|
execute:frappe.delete_doc("DocType", "Party Type")
|
||||||
|
erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items
|
||||||
|
execute:frappe.reload_doctype("Leave Type")
|
||||||
|
execute:frappe.db.sql("update `tabLeave Type` set include_holiday=1")
|
||||||
@ -5,61 +5,61 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
frappe.db.sql("update tabItem set has_batch_no = 'No' where ifnull(has_batch_no, '') = ''")
|
frappe.db.sql("update tabItem set has_batch_no = 0 where ifnull(has_batch_no, '') = ''")
|
||||||
frappe.db.sql("update tabItem set has_serial_no = 'No' where ifnull(has_serial_no, '') = ''")
|
frappe.db.sql("update tabItem set has_serial_no = 0 where ifnull(has_serial_no, '') = ''")
|
||||||
|
|
||||||
item_list = frappe.db.sql("""select name, has_batch_no, has_serial_no from tabItem
|
item_list = frappe.db.sql("""select name, has_batch_no, has_serial_no from tabItem
|
||||||
where ifnull(is_stock_item, 'No') = 'Yes'""", as_dict=1)
|
where is_stock_item = 1""", as_dict=1)
|
||||||
|
|
||||||
sle_count = get_sle_count()
|
sle_count = get_sle_count()
|
||||||
sle_with_batch = get_sle_with_batch()
|
sle_with_batch = get_sle_with_batch()
|
||||||
sle_with_serial = get_sle_with_serial()
|
sle_with_serial = get_sle_with_serial()
|
||||||
|
|
||||||
batch_items = get_items_with_batch()
|
batch_items = get_items_with_batch()
|
||||||
serialized_items = get_items_with_serial()
|
serialized_items = get_items_with_serial()
|
||||||
|
|
||||||
for d in item_list:
|
for d in item_list:
|
||||||
if d.has_batch_no == 'Yes':
|
if d.has_batch_no == 1:
|
||||||
if d.name not in batch_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_batch.get(d.name):
|
if d.name not in batch_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_batch.get(d.name):
|
||||||
frappe.db.set_value("Item", d.name, "has_batch_no", "No")
|
frappe.db.set_value("Item", d.name, "has_batch_no", 0)
|
||||||
else:
|
else:
|
||||||
if d.name in batch_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_batch.get(d.name)):
|
if d.name in batch_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_batch.get(d.name)):
|
||||||
frappe.db.set_value("Item", d.name, "has_batch_no", "Yes")
|
frappe.db.set_value("Item", d.name, "has_batch_no", 1)
|
||||||
|
|
||||||
if d.has_serial_no == 'Yes':
|
if d.has_serial_no == 1:
|
||||||
if d.name not in serialized_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_serial.get(d.name):
|
if d.name not in serialized_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_serial.get(d.name):
|
||||||
frappe.db.set_value("Item", d.name, "has_serial_no", "No")
|
frappe.db.set_value("Item", d.name, "has_serial_no", 0)
|
||||||
else:
|
else:
|
||||||
if d.name in serialized_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_serial.get(d.name)):
|
if d.name in serialized_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_serial.get(d.name)):
|
||||||
frappe.db.set_value("Item", d.name, "has_serial_no", "Yes")
|
frappe.db.set_value("Item", d.name, "has_serial_no", 1)
|
||||||
|
|
||||||
|
|
||||||
def get_sle_count():
|
def get_sle_count():
|
||||||
sle_count = {}
|
sle_count = {}
|
||||||
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` group by item_code""", as_dict=1):
|
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` group by item_code""", as_dict=1):
|
||||||
sle_count.setdefault(d.item_code, d.cnt)
|
sle_count.setdefault(d.item_code, d.cnt)
|
||||||
|
|
||||||
return sle_count
|
return sle_count
|
||||||
|
|
||||||
def get_sle_with_batch():
|
def get_sle_with_batch():
|
||||||
sle_with_batch = {}
|
sle_with_batch = {}
|
||||||
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
|
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
|
||||||
where ifnull(batch_no, '') != '' group by item_code""", as_dict=1):
|
where ifnull(batch_no, '') != '' group by item_code""", as_dict=1):
|
||||||
sle_with_batch.setdefault(d.item_code, d.cnt)
|
sle_with_batch.setdefault(d.item_code, d.cnt)
|
||||||
|
|
||||||
return sle_with_batch
|
return sle_with_batch
|
||||||
|
|
||||||
|
|
||||||
def get_sle_with_serial():
|
def get_sle_with_serial():
|
||||||
sle_with_serial = {}
|
sle_with_serial = {}
|
||||||
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
|
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
|
||||||
where ifnull(serial_no, '') != '' group by item_code""", as_dict=1):
|
where ifnull(serial_no, '') != '' group by item_code""", as_dict=1):
|
||||||
sle_with_serial.setdefault(d.item_code, d.cnt)
|
sle_with_serial.setdefault(d.item_code, d.cnt)
|
||||||
|
|
||||||
return sle_with_serial
|
return sle_with_serial
|
||||||
|
|
||||||
def get_items_with_batch():
|
def get_items_with_batch():
|
||||||
return frappe.db.sql_list("select item from tabBatch")
|
return frappe.db.sql_list("select item from tabBatch")
|
||||||
|
|
||||||
def get_items_with_serial():
|
def get_items_with_serial():
|
||||||
return frappe.db.sql_list("select item_code from `tabSerial No`")
|
return frappe.db.sql_list("select item_code from `tabSerial No`")
|
||||||
|
|||||||
1
erpnext/patches/v5_2/__init__.py
Normal file
1
erpnext/patches/v5_2/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
21
erpnext/patches/v5_2/change_item_selects_to_checks.py
Normal file
21
erpnext/patches/v5_2/change_item_selects_to_checks.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
fields = ("is_stock_item", "is_asset_item", "has_batch_no", "has_serial_no",
|
||||||
|
"is_purchase_item", "is_sales_item", "is_service_item", "inspection_required",
|
||||||
|
"is_pro_applicable", "is_sub_contracted_item")
|
||||||
|
|
||||||
|
|
||||||
|
# convert to 1 or 0
|
||||||
|
update_str = ", ".join(["`{0}`=if(`{0}`='Yes',1,0)".format(f) for f in fields])
|
||||||
|
frappe.db.sql("update tabItem set {0}".format(update_str))
|
||||||
|
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
# alter fields to int
|
||||||
|
for f in fields:
|
||||||
|
frappe.db.sql("alter table tabItem change {0} {0} int(1) default '0'".format(f, f))
|
||||||
|
|
||||||
|
frappe.reload_doctype("Item")
|
||||||
0
erpnext/patches/v5_4/__init__.py
Normal file
0
erpnext/patches/v5_4/__init__.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from erpnext.utilities.repost_stock import update_bin_qty, get_reserved_qty, repost_actual_qty
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice`
|
||||||
|
where docstatus = 2 and ifnull(update_stock, 0) = 1""")
|
||||||
|
|
||||||
|
if cancelled_invoices:
|
||||||
|
frappe.db.sql("""delete from `tabStock Ledger Entry`
|
||||||
|
where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
|
||||||
|
% (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
|
||||||
|
|
||||||
|
for item_code, warehouse in frappe.db.sql("select item_code, warehouse from tabBin where ifnull(reserved_qty, 0) < 0"):
|
||||||
|
|
||||||
|
repost_actual_qty(item_code, warehouse)
|
||||||
|
|
||||||
|
update_bin_qty(item_code, warehouse, {
|
||||||
|
"reserved_qty": get_reserved_qty(item_code, warehouse)
|
||||||
|
})
|
||||||
|
|
||||||
@ -15,10 +15,11 @@ class TestActivityCost(unittest.TestCase):
|
|||||||
activity_cost1.update({
|
activity_cost1.update({
|
||||||
"employee": "_T-Employee-0001",
|
"employee": "_T-Employee-0001",
|
||||||
"employee_name": "_Test Employee",
|
"employee_name": "_Test Employee",
|
||||||
"activity_type": "_Test Activity Type",
|
"activity_type": "_Test Activity Type 1",
|
||||||
"billing_rate": 100,
|
"billing_rate": 100,
|
||||||
"costing_rate": 50
|
"costing_rate": 50
|
||||||
})
|
})
|
||||||
activity_cost1.insert()
|
activity_cost1.insert()
|
||||||
activity_cost2 = frappe.copy_doc(activity_cost1)
|
activity_cost2 = frappe.copy_doc(activity_cost1)
|
||||||
self.assertRaises(DuplicationError, activity_cost2.insert )
|
self.assertRaises(DuplicationError, activity_cost2.insert )
|
||||||
|
frappe.db.sql("delete from `tabActivity Cost`")
|
||||||
@ -1,10 +1 @@
|
|||||||
[
|
[]
|
||||||
{
|
|
||||||
"activity_type": "_Test Activity Type",
|
|
||||||
"docstatus": 1,
|
|
||||||
"doctype": "Time Log",
|
|
||||||
"from_time": "2013-01-01 10:00:00.000000",
|
|
||||||
"note": "_Test Note",
|
|
||||||
"to_time": "2013-01-01 11:00:00.000000"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@ -5,63 +5,44 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from erpnext.projects.doctype.time_log.time_log import OverlapError
|
import datetime
|
||||||
from erpnext.projects.doctype.time_log.time_log import NotSubmittedError
|
from frappe.utils import now_datetime, now
|
||||||
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError
|
from erpnext.projects.doctype.time_log.time_log import OverlapError, NotSubmittedError, NegativeHoursError
|
||||||
from erpnext.manufacturing.doctype.workstation.workstation import NotInWorkingHoursError
|
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
|
||||||
from erpnext.manufacturing.doctype.production_order.test_production_order import make_prod_order_test_record
|
from erpnext.manufacturing.doctype.production_order.test_production_order import make_prod_order_test_record
|
||||||
|
|
||||||
|
|
||||||
class TestTimeLog(unittest.TestCase):
|
class TestTimeLog(unittest.TestCase):
|
||||||
def test_duplication(self):
|
def test_duplication(self):
|
||||||
frappe.db.sql("delete from `tabTime Log`")
|
tl1 = make_time_log_test_record(user= "test@example.com", employee= "_T-Employee-0002", simulate= True)
|
||||||
|
|
||||||
tl1 = frappe.get_doc(frappe.copy_doc(test_records[0]))
|
tl2 = make_time_log_test_record(user= "test@example.com", employee= "_T-Employee-0002",
|
||||||
tl1.user = "test@example.com"
|
from_time= tl1.from_time, to_time= tl1.to_time, do_not_save= 1)
|
||||||
tl1.insert()
|
|
||||||
|
|
||||||
tl2 = frappe.get_doc(frappe.copy_doc(test_records[0]))
|
|
||||||
tl2.user = "test@example.com"
|
|
||||||
|
|
||||||
self.assertRaises(OverlapError, tl2.insert)
|
self.assertRaises(OverlapError, tl2.insert)
|
||||||
|
|
||||||
frappe.db.sql("delete from `tabTime Log`")
|
|
||||||
|
|
||||||
def test_production_order_status(self):
|
def test_production_order_status(self):
|
||||||
prod_order = make_prod_order_test_record(item="_Test FG Item 2", qty=1, do_not_submit=True)
|
prod_order = make_prod_order_test_record(item= "_Test FG Item 2", qty= 1, do_not_submit= True)
|
||||||
prod_order.set_production_order_operations()
|
prod_order.set_production_order_operations()
|
||||||
prod_order.save()
|
prod_order.save()
|
||||||
|
|
||||||
time_log = frappe.get_doc({
|
time_log = make_time_log_test_record(for_manufacturing= 1, production_order= prod_order.name, qty= 1,
|
||||||
"doctype": "Time Log",
|
employee= "_T-Employee-0003", do_not_save= True, simulate=1)
|
||||||
"for_manufacturing": 1,
|
|
||||||
"production_order": prod_order.name,
|
|
||||||
"qty": 1,
|
|
||||||
"from_time": "2014-12-26 00:00:00",
|
|
||||||
"to_time": "2014-12-26 00:00:00"
|
|
||||||
})
|
|
||||||
|
|
||||||
self.assertRaises(NotSubmittedError, time_log.save)
|
self.assertRaises(NotSubmittedError, time_log.save)
|
||||||
|
|
||||||
def test_time_log_on_holiday(self):
|
def test_time_log_on_holiday(self):
|
||||||
prod_order = make_prod_order_test_record(item="_Test FG Item 2", qty=1,
|
prod_order = make_prod_order_test_record(item= "_Test FG Item 2", qty= 1,
|
||||||
planned_start_date="2014-11-25 00:00:00", do_not_save=True)
|
planned_start_date= now(), do_not_save= True)
|
||||||
prod_order.set_production_order_operations()
|
prod_order.set_production_order_operations()
|
||||||
prod_order.save()
|
prod_order.save()
|
||||||
prod_order.submit()
|
prod_order.submit()
|
||||||
|
|
||||||
time_log = frappe.get_doc({
|
time_log = make_time_log_test_record(from_time= "2013-02-01 10:00:00", to_time= "2013-02-01 20:00:00",
|
||||||
"doctype": "Time Log",
|
for_manufacturing= 1, production_order= prod_order.name, qty= 1,
|
||||||
"for_manufacturing": 1,
|
operation= prod_order.operations[0].operation, operation_id= prod_order.operations[0].name,
|
||||||
"production_order": prod_order.name,
|
workstation= "_Test Workstation 1", do_not_save= True)
|
||||||
"operation": prod_order.operations[0].operation,
|
|
||||||
"operation_id": prod_order.operations[0].name,
|
|
||||||
"qty": 1,
|
|
||||||
"activity_type": "_Test Activity Type",
|
|
||||||
"from_time": "2013-02-01 10:00:00",
|
|
||||||
"to_time": "2013-02-01 20:00:00",
|
|
||||||
"workstation": "_Test Workstation 1"
|
|
||||||
})
|
|
||||||
self.assertRaises(WorkstationHolidayError , time_log.save)
|
self.assertRaises(WorkstationHolidayError , time_log.save)
|
||||||
|
|
||||||
time_log.update({
|
time_log.update({
|
||||||
@ -76,28 +57,23 @@ class TestTimeLog(unittest.TestCase):
|
|||||||
time_log.cancel()
|
time_log.cancel()
|
||||||
|
|
||||||
def test_negative_hours(self):
|
def test_negative_hours(self):
|
||||||
frappe.db.sql("delete from `tabTime Log`")
|
time_log = make_time_log_test_record(to_time= now_datetime() + datetime.timedelta(minutes=-1),
|
||||||
test_time_log = frappe.new_doc("Time Log")
|
employee="_T-Employee-0006",do_not_save= True)
|
||||||
test_time_log.activity_type = "Communication"
|
self.assertRaises(NegativeHoursError, time_log.save)
|
||||||
test_time_log.from_time = "2013-01-01 11:00:00.000000"
|
|
||||||
test_time_log.to_time = "2013-01-01 10:00:00.000000"
|
|
||||||
self.assertRaises(frappe.ValidationError, test_time_log.save)
|
|
||||||
frappe.db.sql("delete from `tabTime Log`")
|
|
||||||
|
|
||||||
def test_total_activity_cost_for_project(self):
|
def test_total_activity_cost_for_project(self):
|
||||||
frappe.db.sql("""delete from `tabTask` where project = "_Test Project 1" """)
|
frappe.db.sql("""delete from `tabTask` where project = "_Test Project 1" """)
|
||||||
frappe.db.sql("""delete from `tabProject` where name = "_Test Project 1" """)
|
frappe.db.sql("""delete from `tabProject` where name = "_Test Project 1" """)
|
||||||
frappe.db.sql("""delete from `tabActivity Cost` where employee = "_T-Employee-0001" and activity_type = "_Test Activity Type" """)
|
|
||||||
|
|
||||||
activity_cost = frappe.new_doc('Activity Cost')
|
if not frappe.db.exists('Activity Cost', {"activity_type": "_Test Activity Type"}):
|
||||||
activity_cost.update({
|
activity_cost = frappe.get_doc({
|
||||||
"employee": "_T-Employee-0001",
|
"doctype": "Activity Cost",
|
||||||
"employee_name": "_Test Employee",
|
"employee": "",
|
||||||
"activity_type": "_Test Activity Type",
|
"activity_type": "_Test Activity Type",
|
||||||
"billing_rate": 100,
|
"billing_rate": 100,
|
||||||
"costing_rate": 50
|
"costing_rate": 50
|
||||||
})
|
})
|
||||||
activity_cost.insert()
|
activity_cost.insert()
|
||||||
|
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"project_name": "_Test Project 1",
|
"project_name": "_Test Project 1",
|
||||||
@ -108,40 +84,16 @@ class TestTimeLog(unittest.TestCase):
|
|||||||
|
|
||||||
task_name = frappe.db.get_value("Task",{"project": "_Test Project 1"})
|
task_name = frappe.db.get_value("Task",{"project": "_Test Project 1"})
|
||||||
|
|
||||||
time_log = frappe.get_doc({
|
time_log = make_time_log_test_record(employee="_T-Employee-0002", hours=2, task= task_name)
|
||||||
"activity_type": "_Test Activity Type",
|
|
||||||
"docstatus": 1,
|
|
||||||
"doctype": "Time Log",
|
|
||||||
"from_time": "2013-02-02 09:00:00.000000",
|
|
||||||
"to_time": "2013-02-02 11:00:00.000000",
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"project": "_Test Project 1",
|
|
||||||
"task": task_name,
|
|
||||||
"billable": 1
|
|
||||||
})
|
|
||||||
time_log.save()
|
|
||||||
self.assertEqual(time_log.costing_rate, 50)
|
self.assertEqual(time_log.costing_rate, 50)
|
||||||
self.assertEqual(time_log.costing_amount, 100)
|
self.assertEqual(time_log.costing_amount, 100)
|
||||||
self.assertEqual(time_log.billing_rate, 100)
|
self.assertEqual(time_log.billing_rate, 100)
|
||||||
self.assertEqual(time_log.billing_amount, 200)
|
self.assertEqual(time_log.billing_amount, 200)
|
||||||
time_log.submit()
|
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Task", task_name, "total_billing_amount"), 200)
|
self.assertEqual(frappe.db.get_value("Task", task_name, "total_billing_amount"), 200)
|
||||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_billing_amount"), 200)
|
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_billing_amount"), 200)
|
||||||
|
|
||||||
time_log2 = frappe.get_doc({
|
time_log2 = make_time_log_test_record(employee="_T-Employee-0003", hours=2, task= task_name)
|
||||||
"activity_type": "_Test Activity Type",
|
|
||||||
"docstatus": 1,
|
|
||||||
"doctype": "Time Log",
|
|
||||||
"from_time": "2013-02-03 09:00:00.000000",
|
|
||||||
"to_time": "2013-02-03 11:00:00.000000",
|
|
||||||
"employee": "_T-Employee-0001",
|
|
||||||
"project": "_Test Project 1",
|
|
||||||
"task": task_name,
|
|
||||||
"billable": 1
|
|
||||||
})
|
|
||||||
time_log2.save()
|
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Task", task_name, "total_billing_amount"), 400)
|
self.assertEqual(frappe.db.get_value("Task", task_name, "total_billing_amount"), 400)
|
||||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_billing_amount"), 400)
|
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_billing_amount"), 400)
|
||||||
|
|
||||||
@ -149,6 +101,44 @@ class TestTimeLog(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(frappe.db.get_value("Task", task_name, "total_billing_amount"), 200)
|
self.assertEqual(frappe.db.get_value("Task", task_name, "total_billing_amount"), 200)
|
||||||
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_billing_amount"), 200)
|
self.assertEqual(frappe.db.get_value("Project", "_Test Project 1", "total_billing_amount"), 200)
|
||||||
|
time_log.cancel()
|
||||||
|
|
||||||
test_records = frappe.get_test_records('Time Log')
|
|
||||||
test_ignore = ["Time Log Batch", "Sales Invoice"]
|
test_ignore = ["Time Log Batch", "Sales Invoice"]
|
||||||
|
|
||||||
|
def make_time_log_test_record(**args):
|
||||||
|
args = frappe._dict(args)
|
||||||
|
|
||||||
|
time_log = frappe.new_doc("Time Log")
|
||||||
|
|
||||||
|
time_log.from_time = args.from_time or now_datetime()
|
||||||
|
time_log.hours = args.hours or 1
|
||||||
|
time_log.to_time = args.to_time or time_log.from_time + datetime.timedelta(hours= time_log.hours)
|
||||||
|
|
||||||
|
time_log.project = args.project
|
||||||
|
time_log.task = args.task
|
||||||
|
time_log.for_manufacturing = args.for_manufacturing
|
||||||
|
time_log.production_order = args.production_order
|
||||||
|
time_log.operation = args.operation
|
||||||
|
time_log.operation_id = args.operation_id
|
||||||
|
time_log.workstation = args.workstation
|
||||||
|
time_log.completed_qty = args.completed_qty
|
||||||
|
time_log.activity_type = args.activity_type or "_Test Activity Type"
|
||||||
|
time_log.billable = args.billable or 1
|
||||||
|
time_log.employee = args.employee
|
||||||
|
time_log.user = args.user
|
||||||
|
|
||||||
|
if not args.do_not_save:
|
||||||
|
if args.simulate:
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
time_log.save()
|
||||||
|
break
|
||||||
|
except OverlapError:
|
||||||
|
time_log.from_time = time_log.from_time + datetime.timedelta(minutes=10)
|
||||||
|
time_log.to_time = time_log.from_time + datetime.timedelta(hours= time_log.hours)
|
||||||
|
else:
|
||||||
|
time_log.save()
|
||||||
|
if not args.do_not_submit:
|
||||||
|
time_log.submit()
|
||||||
|
|
||||||
|
return time_log
|
||||||
@ -10,6 +10,7 @@ from dateutil.relativedelta import relativedelta
|
|||||||
class OverlapError(frappe.ValidationError): pass
|
class OverlapError(frappe.ValidationError): pass
|
||||||
class OverProductionLoggedError(frappe.ValidationError): pass
|
class OverProductionLoggedError(frappe.ValidationError): pass
|
||||||
class NotSubmittedError(frappe.ValidationError): pass
|
class NotSubmittedError(frappe.ValidationError): pass
|
||||||
|
class NegativeHoursError(frappe.ValidationError): pass
|
||||||
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
@ -101,8 +102,8 @@ class TimeLog(Document):
|
|||||||
return existing[0] if existing else None
|
return existing[0] if existing else None
|
||||||
|
|
||||||
def validate_timings(self):
|
def validate_timings(self):
|
||||||
if self.to_time and self.from_time and get_datetime(self.to_time) < get_datetime(self.from_time):
|
if self.to_time and self.from_time and get_datetime(self.to_time) <= get_datetime(self.from_time):
|
||||||
frappe.throw(_("From Time cannot be greater than To Time"))
|
frappe.throw(_("To Time must be greater than From Time"), NegativeHoursError)
|
||||||
|
|
||||||
def calculate_total_hours(self):
|
def calculate_total_hours(self):
|
||||||
if self.to_time and self.from_time:
|
if self.to_time and self.from_time:
|
||||||
|
|||||||
@ -3,43 +3,19 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import frappe, unittest
|
import frappe, unittest
|
||||||
|
from erpnext.projects.doctype.time_log.test_time_log import make_time_log_test_record
|
||||||
|
|
||||||
class TimeLogBatchTest(unittest.TestCase):
|
class TimeLogBatchTest(unittest.TestCase):
|
||||||
def test_time_log_status(self):
|
def test_time_log_status(self):
|
||||||
delete_time_log_and_batch()
|
time_log = make_time_log_test_record(simulate=True)
|
||||||
time_log = create_time_log()
|
|
||||||
|
|
||||||
self.assertEquals(frappe.db.get_value("Time Log", time_log, "status"), "Submitted")
|
self.assertEquals(frappe.db.get_value("Time Log", time_log.name, "status"), "Submitted")
|
||||||
|
|
||||||
tlb = create_time_log_batch(time_log)
|
tlb = create_time_log_batch(time_log.name)
|
||||||
|
|
||||||
self.assertEquals(frappe.db.get_value("Time Log", time_log, "status"), "Batched for Billing")
|
self.assertEquals(frappe.db.get_value("Time Log", time_log.name, "status"), "Batched for Billing")
|
||||||
tlb.cancel()
|
tlb.cancel()
|
||||||
self.assertEquals(frappe.db.get_value("Time Log", time_log, "status"), "Submitted")
|
self.assertEquals(frappe.db.get_value("Time Log", time_log.name, "status"), "Submitted")
|
||||||
|
|
||||||
delete_time_log_and_batch()
|
|
||||||
|
|
||||||
def delete_time_log_and_batch():
|
|
||||||
for name in frappe.db.sql_list("select name from `tabTime Log Batch` where docstatus=1"):
|
|
||||||
frappe.get_doc("Time Log Batch", name).cancel()
|
|
||||||
frappe.delete_doc("Time Log Batch", name)
|
|
||||||
|
|
||||||
for name in frappe.db.sql_list("select name from `tabTime Log` where docstatus=1"):
|
|
||||||
frappe.get_doc("Time Log", name).cancel()
|
|
||||||
frappe.delete_doc("Time Log", name)
|
|
||||||
|
|
||||||
def create_time_log():
|
|
||||||
from erpnext.projects.doctype.time_log.test_time_log import test_records as time_log_records
|
|
||||||
time_log = frappe.copy_doc(time_log_records[0])
|
|
||||||
time_log.update({
|
|
||||||
"from_time": "2013-01-02 10:00:00.000000",
|
|
||||||
"to_time": "2013-01-02 11:00:00.000000",
|
|
||||||
"docstatus": 0,
|
|
||||||
"for_manufacturing": 0
|
|
||||||
})
|
|
||||||
time_log.insert()
|
|
||||||
time_log.submit()
|
|
||||||
return time_log.name
|
|
||||||
|
|
||||||
def create_time_log_batch(time_log):
|
def create_time_log_batch(time_log):
|
||||||
tlb = frappe.get_doc({
|
tlb = frappe.get_doc({
|
||||||
|
|||||||
@ -58,7 +58,7 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
|
|||||||
|
|
||||||
show_general_ledger: function() {
|
show_general_ledger: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
if(this.frm.doc.docstatus===1 && cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
|
if(this.frm.doc.docstatus===1) {
|
||||||
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
|
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
|
||||||
frappe.route_options = {
|
frappe.route_options = {
|
||||||
voucher_no: me.frm.doc.name,
|
voucher_no: me.frm.doc.name,
|
||||||
|
|||||||
@ -94,10 +94,6 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({
|
|||||||
tax_fields = ["total", "tax_amount_after_discount_amount",
|
tax_fields = ["total", "tax_amount_after_discount_amount",
|
||||||
"tax_amount_for_current_item", "grand_total_for_current_item",
|
"tax_amount_for_current_item", "grand_total_for_current_item",
|
||||||
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
|
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
|
||||||
|
|
||||||
if (frappe.meta.get_docfield(me.frm.doc.doctype, "is_return") && me.frm.doc.is_return
|
|
||||||
&& tax.charge_type == "Actual")
|
|
||||||
tax.tax_amount = -1 * tax.tax_amount;
|
|
||||||
|
|
||||||
if (cstr(tax.charge_type) != "Actual" &&
|
if (cstr(tax.charge_type) != "Actual" &&
|
||||||
!(me.discount_amount_applied && me.frm.doc.apply_discount_on=="Grand Total"))
|
!(me.discount_amount_applied && me.frm.doc.apply_discount_on=="Grand Total"))
|
||||||
|
|||||||
@ -101,6 +101,13 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "is_frozen",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Frozen",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:!doc.__islocal",
|
"depends_on": "eval:!doc.__islocal",
|
||||||
"fieldname": "address_contacts",
|
"fieldname": "address_contacts",
|
||||||
@ -278,7 +285,7 @@
|
|||||||
],
|
],
|
||||||
"icon": "icon-user",
|
"icon": "icon-user",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"modified": "2015-07-13 05:28:25.753684",
|
"modified": "2015-07-17 09:38:50.086978",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Customer",
|
"name": "Customer",
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import frappe
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from frappe.test_runner import make_test_records
|
from frappe.test_runner import make_test_records
|
||||||
|
from erpnext.controllers.accounts_controller import CustomerFrozen
|
||||||
|
|
||||||
test_ignore = ["Price List"]
|
test_ignore = ["Price List"]
|
||||||
|
|
||||||
@ -65,5 +66,15 @@ class TestCustomer(unittest.TestCase):
|
|||||||
{"comment_doctype": "Customer", "comment_docname": "_Test Customer 1 Renamed"}), comment.name)
|
{"comment_doctype": "Customer", "comment_docname": "_Test Customer 1 Renamed"}), comment.name)
|
||||||
|
|
||||||
frappe.rename_doc("Customer", "_Test Customer 1 Renamed", "_Test Customer 1")
|
frappe.rename_doc("Customer", "_Test Customer 1 Renamed", "_Test Customer 1")
|
||||||
|
|
||||||
|
def test_freezed_customer(self):
|
||||||
|
frappe.db.set_value("Customer", "_Test Customer", "is_frozen", 1)
|
||||||
|
|
||||||
|
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||||
|
|
||||||
|
so = make_sales_order(do_not_save= True)
|
||||||
|
self.assertRaises(CustomerFrozen, so.save)
|
||||||
|
|
||||||
|
frappe.db.set_value("Customer", "_Test Customer", "is_frozen", 0)
|
||||||
|
|
||||||
|
so.save()
|
||||||
@ -39,10 +39,10 @@ class InstallationNote(TransactionBase):
|
|||||||
check_active_sales_items(self)
|
check_active_sales_items(self)
|
||||||
|
|
||||||
def is_serial_no_added(self, item_code, serial_no):
|
def is_serial_no_added(self, item_code, serial_no):
|
||||||
ar_required = frappe.db.get_value("Item", item_code, "has_serial_no")
|
has_serial_no = frappe.db.get_value("Item", item_code, "has_serial_no")
|
||||||
if ar_required == 'Yes' and not serial_no:
|
if has_serial_no == 1 and not serial_no:
|
||||||
frappe.throw(_("Serial No is mandatory for Item {0}").format(item_code))
|
frappe.throw(_("Serial No is mandatory for Item {0}").format(item_code))
|
||||||
elif ar_required != 'Yes' and cstr(serial_no).strip():
|
elif has_serial_no != 1 and cstr(serial_no).strip():
|
||||||
frappe.throw(_("Item {0} is not a serialized Item").format(item_code))
|
frappe.throw(_("Item {0} is not a serialized Item").format(item_code))
|
||||||
|
|
||||||
def is_serial_no_exist(self, item_code, serial_no):
|
def is_serial_no_exist(self, item_code, serial_no):
|
||||||
@ -69,7 +69,7 @@ class InstallationNote(TransactionBase):
|
|||||||
frappe.throw(_("Serial No {0} does not belong to Delivery Note {1}").format(sr, prevdoc_docname))
|
frappe.throw(_("Serial No {0} does not belong to Delivery Note {1}").format(sr, prevdoc_docname))
|
||||||
|
|
||||||
def validate_serial_no(self):
|
def validate_serial_no(self):
|
||||||
cur_s_no, prevdoc_s_no, sr_list = [], [], []
|
prevdoc_s_no, sr_list = [], []
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
self.is_serial_no_added(d.item_code, d.serial_no)
|
self.is_serial_no_added(d.item_code, d.serial_no)
|
||||||
if d.serial_no:
|
if d.serial_no:
|
||||||
|
|||||||
@ -21,7 +21,7 @@ class ProductBundle(Document):
|
|||||||
def validate_main_item(self):
|
def validate_main_item(self):
|
||||||
"""main item must have Is Stock Item as No and Is Sales Item as Yes"""
|
"""main item must have Is Stock Item as No and Is Sales Item as Yes"""
|
||||||
if not frappe.db.sql("""select name from tabItem where name=%s and
|
if not frappe.db.sql("""select name from tabItem where name=%s and
|
||||||
ifnull(is_stock_item,'')='No' and ifnull(is_sales_item,'')='Yes'""", self.new_item_code):
|
is_stock_item = 0 and is_sales_item = 1""", self.new_item_code):
|
||||||
frappe.throw(_("Parent Item {0} must be not Stock Item and must be a Sales Item").format(self.new_item_code))
|
frappe.throw(_("Parent Item {0} must be not Stock Item and must be a Sales Item").format(self.new_item_code))
|
||||||
|
|
||||||
def get_item_details(self, name):
|
def get_item_details(self, name):
|
||||||
@ -36,7 +36,7 @@ def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
from erpnext.controllers.queries import get_match_cond
|
from erpnext.controllers.queries import get_match_cond
|
||||||
|
|
||||||
return frappe.db.sql("""select name, item_name, description from tabItem
|
return frappe.db.sql("""select name, item_name, description from tabItem
|
||||||
where is_stock_item="No" and is_sales_item="Yes"
|
where is_stock_item=0 and is_sales_item=1
|
||||||
and name not in (select name from `tabProduct Bundle`) and %s like %s
|
and name not in (select name from `tabProduct Bundle`) and %s like %s
|
||||||
%s limit %s, %s""" % (searchfield, "%s",
|
%s limit %s, %s""" % (searchfield, "%s",
|
||||||
get_match_cond(doctype),"%s", "%s"),
|
get_match_cond(doctype),"%s", "%s"),
|
||||||
|
|||||||
@ -28,17 +28,11 @@ class Quotation(SellingController):
|
|||||||
|
|
||||||
if self.order_type in ['Maintenance', 'Service']:
|
if self.order_type in ['Maintenance', 'Service']:
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
is_service_item = frappe.db.sql("select is_service_item from `tabItem` where name=%s", d.item_code)
|
if not frappe.db.get_value("Item", d.item_code, "is_service_item"):
|
||||||
is_service_item = is_service_item and is_service_item[0][0] or 'No'
|
|
||||||
|
|
||||||
if is_service_item == 'No':
|
|
||||||
frappe.throw(_("Item {0} must be Service Item").format(d.item_code))
|
frappe.throw(_("Item {0} must be Service Item").format(d.item_code))
|
||||||
else:
|
else:
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
is_sales_item = frappe.db.sql("select is_sales_item from `tabItem` where name=%s", d.item_code)
|
if not frappe.db.get_value("Item", d.item_code, "is_sales_item"):
|
||||||
is_sales_item = is_sales_item and is_sales_item[0][0] or 'No'
|
|
||||||
|
|
||||||
if is_sales_item == 'No':
|
|
||||||
frappe.throw(_("Item {0} must be Sales Item").format(d.item_code))
|
frappe.throw(_("Item {0} must be Sales Item").format(d.item_code))
|
||||||
|
|
||||||
def validate_quotation_to(self):
|
def validate_quotation_to(self):
|
||||||
|
|||||||
@ -39,7 +39,7 @@ class SalesOrder(SellingController):
|
|||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
check_list.append(cstr(d.item_code))
|
check_list.append(cstr(d.item_code))
|
||||||
|
|
||||||
if (frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or
|
if (frappe.db.get_value("Item", d.item_code, "is_stock_item")==1 or
|
||||||
self.has_product_bundle(d.item_code)) and not d.warehouse:
|
self.has_product_bundle(d.item_code)) and not d.warehouse:
|
||||||
frappe.throw(_("Reserved warehouse required for stock item {0}").format(d.item_code))
|
frappe.throw(_("Reserved warehouse required for stock item {0}").format(d.item_code))
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ class SalesOrder(SellingController):
|
|||||||
def update_stock_ledger(self, update_stock):
|
def update_stock_ledger(self, update_stock):
|
||||||
from erpnext.stock.utils import update_bin
|
from erpnext.stock.utils import update_bin
|
||||||
for d in self.get_item_list():
|
for d in self.get_item_list():
|
||||||
if frappe.db.get_value("Item", d['item_code'], "is_stock_item") == "Yes":
|
if frappe.db.get_value("Item", d['item_code'], "is_stock_item")==1:
|
||||||
args = {
|
args = {
|
||||||
"item_code": d['item_code'],
|
"item_code": d['item_code'],
|
||||||
"warehouse": d['reserved_warehouse'],
|
"warehouse": d['reserved_warehouse'],
|
||||||
@ -258,14 +258,14 @@ def stop_or_unstop_sales_orders(names, status):
|
|||||||
|
|
||||||
def before_recurring(self):
|
def before_recurring(self):
|
||||||
super(SalesOrder, self).before_recurring()
|
super(SalesOrder, self).before_recurring()
|
||||||
|
|
||||||
for field in ("delivery_status", "per_delivered", "billing_status", "per_billed"):
|
for field in ("delivery_status", "per_delivered", "billing_status", "per_billed"):
|
||||||
self.set(field, None)
|
self.set(field, None)
|
||||||
|
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
for field in ("delivered_qty", "billed_amt", "planned_qty", "prevdoc_docname"):
|
for field in ("delivered_qty", "billed_amt", "planned_qty", "prevdoc_docname"):
|
||||||
d.set(field, None)
|
d.set(field, None)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_material_request(source_name, target_doc=None):
|
def make_material_request(source_name, target_doc=None):
|
||||||
@ -273,9 +273,9 @@ def make_material_request(source_name, target_doc=None):
|
|||||||
doc.material_request_type = "Purchase"
|
doc.material_request_type = "Purchase"
|
||||||
|
|
||||||
so = frappe.get_doc("Sales Order", source_name)
|
so = frappe.get_doc("Sales Order", source_name)
|
||||||
|
|
||||||
item_table = "Packed Item" if so.packed_items else "Sales Order Item"
|
item_table = "Packed Item" if so.packed_items else "Sales Order Item"
|
||||||
|
|
||||||
doc = get_mapped_doc("Sales Order", source_name, {
|
doc = get_mapped_doc("Sales Order", source_name, {
|
||||||
"Sales Order": {
|
"Sales Order": {
|
||||||
"doctype": "Material Request",
|
"doctype": "Material Request",
|
||||||
|
|||||||
@ -5,12 +5,30 @@ frappe.listview_settings['Sales Order'] = {
|
|||||||
if(doc.status==="Stopped") {
|
if(doc.status==="Stopped") {
|
||||||
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
|
||||||
} else if(flt(doc.per_delivered) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
} else if(flt(doc.per_delivered) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
||||||
|
// to bill & overdue
|
||||||
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Stopped"];
|
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Stopped"];
|
||||||
|
|
||||||
} else if(flt(doc.per_delivered) < 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_delivered) < 100 && doc.status!=="Stopped") {
|
||||||
return [__("Not Delivered"), "orange", "per_delivered,<,100|status,!=,Stopped"];
|
// not delivered
|
||||||
|
|
||||||
|
if(flt(doc.per_billed) < 100) {
|
||||||
|
// not delivered & not billed
|
||||||
|
|
||||||
|
return [__("To Deliver and Bill"), "orange",
|
||||||
|
"per_delivered,<,100|per_billed,<,100|status,!=,Stopped"];
|
||||||
|
} else {
|
||||||
|
// not billed
|
||||||
|
|
||||||
|
return [__("To Deliver"), "orange",
|
||||||
|
"per_delivered,<,100|per_billed,=,100|status,!=,Stopped"];
|
||||||
|
}
|
||||||
|
|
||||||
} else if(flt(doc.per_delivered) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_delivered) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
|
||||||
|
// to bill
|
||||||
return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Stopped"];
|
return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Stopped"];
|
||||||
|
|
||||||
} else if(flt(doc.per_delivered) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
|
} else if(flt(doc.per_delivered) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
|
||||||
|
|
||||||
return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Stopped"];
|
return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Stopped"];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,509 +1,509 @@
|
|||||||
{
|
{
|
||||||
"autoname": "hash",
|
"autoname": "hash",
|
||||||
"creation": "2013-03-07 11:42:58",
|
"creation": "2013-03-07 11:42:58",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Item Code",
|
"label": "Item Code",
|
||||||
"oldfieldname": "item_code",
|
"oldfieldname": "item_code",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 1,
|
"search_index": 1,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "customer_item_code",
|
"fieldname": "customer_item_code",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Customer's Item Code",
|
"label": "Customer's Item Code",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col_break1",
|
"fieldname": "col_break1",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "item_name",
|
"fieldname": "item_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Item Name",
|
"label": "Item Name",
|
||||||
"oldfieldname": "item_name",
|
"oldfieldname": "item_name",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "150",
|
"print_width": "150",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"width": "150"
|
"width": "150"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_5",
|
"fieldname": "section_break_5",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "description",
|
"fieldname": "description",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"in_list_view": 0,
|
"in_list_view": 1,
|
||||||
"label": "Description",
|
"label": "Description",
|
||||||
"oldfieldname": "description",
|
"oldfieldname": "description",
|
||||||
"oldfieldtype": "Small Text",
|
"oldfieldtype": "Small Text",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_width": "300px",
|
"print_width": "300px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"width": "300px"
|
"width": "300px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_7",
|
"fieldname": "column_break_7",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "image",
|
"fieldname": "image",
|
||||||
"fieldtype": "Attach",
|
"fieldtype": "Attach",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Image",
|
"label": "Image",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0
|
"print_hide": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "image_view",
|
"fieldname": "image_view",
|
||||||
"fieldtype": "Image",
|
"fieldtype": "Image",
|
||||||
"label": "Image View",
|
"label": "Image View",
|
||||||
"options": "image",
|
"options": "image",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "quantity_and_rate",
|
"fieldname": "quantity_and_rate",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Quantity and Rate",
|
"label": "Quantity and Rate",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "qty",
|
"fieldname": "qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Quantity",
|
"label": "Quantity",
|
||||||
"oldfieldname": "qty",
|
"oldfieldname": "qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "price_list_rate",
|
"fieldname": "price_list_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Price List Rate",
|
"label": "Price List Rate",
|
||||||
"oldfieldname": "ref_rate",
|
"oldfieldname": "ref_rate",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "70px",
|
"print_width": "70px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "70px"
|
"width": "70px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "price_list_rate",
|
"depends_on": "price_list_rate",
|
||||||
"fieldname": "discount_percentage",
|
"fieldname": "discount_percentage",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Discount on Price List Rate (%)",
|
"label": "Discount on Price List Rate (%)",
|
||||||
"oldfieldname": "adj_rate",
|
"oldfieldname": "adj_rate",
|
||||||
"oldfieldtype": "Float",
|
"oldfieldtype": "Float",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "70px",
|
"print_width": "70px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"width": "70px"
|
"width": "70px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col_break2",
|
"fieldname": "col_break2",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "stock_uom",
|
"fieldname": "stock_uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "UOM",
|
"label": "UOM",
|
||||||
"oldfieldname": "stock_uom",
|
"oldfieldname": "stock_uom",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"options": "UOM",
|
"options": "UOM",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_width": "70px",
|
"print_width": "70px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "70px"
|
"width": "70px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "base_price_list_rate",
|
"fieldname": "base_price_list_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Price List Rate (Company Currency)",
|
"label": "Price List Rate (Company Currency)",
|
||||||
"oldfieldname": "base_ref_rate",
|
"oldfieldname": "base_ref_rate",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_simple1",
|
"fieldname": "section_break_simple1",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "rate",
|
"fieldname": "rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Rate",
|
"label": "Rate",
|
||||||
"oldfieldname": "export_rate",
|
"oldfieldname": "export_rate",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "amount",
|
"fieldname": "amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Amount",
|
"label": "Amount",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"oldfieldname": "export_amount",
|
"oldfieldname": "export_amount",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col_break3",
|
"fieldname": "col_break3",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "base_rate",
|
"fieldname": "base_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Basic Rate (Company Currency)",
|
"label": "Basic Rate (Company Currency)",
|
||||||
"oldfieldname": "basic_rate",
|
"oldfieldname": "basic_rate",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "base_amount",
|
"fieldname": "base_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Amount (Company Currency)",
|
"label": "Amount (Company Currency)",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"oldfieldname": "amount",
|
"oldfieldname": "amount",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "pricing_rule",
|
"fieldname": "pricing_rule",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Pricing Rule",
|
"label": "Pricing Rule",
|
||||||
"options": "Pricing Rule",
|
"options": "Pricing Rule",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_24",
|
"fieldname": "section_break_24",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "net_rate",
|
"fieldname": "net_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Net Rate",
|
"label": "Net Rate",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "net_amount",
|
"fieldname": "net_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Net Amount",
|
"label": "Net Amount",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_27",
|
"fieldname": "column_break_27",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "base_net_rate",
|
"fieldname": "base_net_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Net Rate (Company Currency)",
|
"label": "Net Rate (Company Currency)",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "base_net_amount",
|
"fieldname": "base_net_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Net Amount (Company Currency)",
|
"label": "Net Amount (Company Currency)",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "warehouse_and_reference",
|
"fieldname": "warehouse_and_reference",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Warehouse and Reference",
|
"label": "Warehouse and Reference",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "warehouse",
|
"fieldname": "warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Delivery Warehouse",
|
"label": "Delivery Warehouse",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"oldfieldname": "reserved_warehouse",
|
"oldfieldname": "reserved_warehouse",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Warehouse",
|
"options": "Warehouse",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 0,
|
"reqd": 0,
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "prevdoc_docname",
|
"fieldname": "prevdoc_docname",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Quotation",
|
"label": "Quotation",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "prevdoc_docname",
|
"oldfieldname": "prevdoc_docname",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Quotation",
|
"options": "Quotation",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"search_index": 1
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "brand",
|
"fieldname": "brand",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Brand Name",
|
"label": "Brand Name",
|
||||||
"oldfieldname": "brand",
|
"oldfieldname": "brand",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Brand",
|
"options": "Brand",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"search_index": 1
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "",
|
"description": "",
|
||||||
"fieldname": "item_group",
|
"fieldname": "item_group",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Item Group",
|
"label": "Item Group",
|
||||||
"oldfieldname": "item_group",
|
"oldfieldname": "item_group",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
"options": "Item Group",
|
"options": "Item Group",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"search_index": 1
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "page_break",
|
"fieldname": "page_break",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Page Break",
|
"label": "Page Break",
|
||||||
"oldfieldname": "page_break",
|
"oldfieldname": "page_break",
|
||||||
"oldfieldtype": "Check",
|
"oldfieldtype": "Check",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"report_hide": 1
|
"report_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col_break4",
|
"fieldname": "col_break4",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "projected_qty",
|
"fieldname": "projected_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Projected Qty",
|
"label": "Projected Qty",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "projected_qty",
|
"oldfieldname": "projected_qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "70px",
|
"print_width": "70px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"width": "70px"
|
"width": "70px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "actual_qty",
|
"fieldname": "actual_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Actual Qty",
|
"label": "Actual Qty",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "70px",
|
"print_width": "70px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"width": "70px"
|
"width": "70px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "delivered_qty",
|
"fieldname": "delivered_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"label": "Delivered Qty",
|
"label": "Delivered Qty",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "delivered_qty",
|
"oldfieldname": "delivered_qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "100px",
|
"print_width": "100px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"search_index": 0,
|
"search_index": 0,
|
||||||
"width": "100px"
|
"width": "100px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "billed_amt",
|
"fieldname": "billed_amt",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Billed Amt",
|
"label": "Billed Amt",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "For Production",
|
"description": "For Production",
|
||||||
"fieldname": "planned_qty",
|
"fieldname": "planned_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Planned Quantity",
|
"label": "Planned Quantity",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "planned_qty",
|
"oldfieldname": "planned_qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "50px",
|
"print_width": "50px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
"width": "50px"
|
"width": "50px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "For Production",
|
"description": "For Production",
|
||||||
"fieldname": "produced_qty",
|
"fieldname": "produced_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Produced Quantity",
|
"label": "Produced Quantity",
|
||||||
"oldfieldname": "produced_qty",
|
"oldfieldname": "produced_qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "50px",
|
"print_width": "50px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
"width": "50px"
|
"width": "50px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "item_tax_rate",
|
"fieldname": "item_tax_rate",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Small Text",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"label": "Item Tax Rate",
|
"label": "Item Tax Rate",
|
||||||
"oldfieldname": "item_tax_rate",
|
"oldfieldname": "item_tax_rate",
|
||||||
"oldfieldtype": "Small Text",
|
"oldfieldtype": "Small Text",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 1
|
"report_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Used for Production Plan",
|
"description": "Used for Production Plan",
|
||||||
"fieldname": "transaction_date",
|
"fieldname": "transaction_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 1,
|
"hidden": 1,
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
"label": "Sales Order Date",
|
"label": "Sales Order Date",
|
||||||
"oldfieldname": "transaction_date",
|
"oldfieldname": "transaction_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
"search_index": 0
|
"search_index": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2015-07-02 05:37:29.289574",
|
"modified": "2015-07-28 05:37:29.289574",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order Item",
|
"name": "Sales Order Item",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,8 +57,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query",
|
||||||
filters: (me.frm.doc.order_type === "Maintenance" ?
|
filters: (me.frm.doc.order_type === "Maintenance" ?
|
||||||
{'is_service_item': 'Yes'}:
|
{'is_service_item': 1}:
|
||||||
{'is_sales_item': 'Yes' })
|
{'is_sales_item': 1 })
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
|
||||||
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
|
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
|
||||||
|
cur_frm.disable_save();
|
||||||
|
cur_frm.toolbar.print_icon.addClass("hide");
|
||||||
return cur_frm.call({
|
return cur_frm.call({
|
||||||
doc: cur_frm.doc,
|
doc: cur_frm.doc,
|
||||||
method: 'get_transactions',
|
method: 'get_transactions',
|
||||||
@ -18,7 +21,7 @@ cur_frm.cscript.update_selects = function(r) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.select_doc_for_series = function(doc, cdt, cdn) {
|
cur_frm.cscript.select_doc_for_series = function(doc, cdt, cdn) {
|
||||||
cur_frm.toggle_display(['help_html','set_options', 'user_must_always_select', 'update'],
|
cur_frm.toggle_display(['help_html','set_options', 'user_must_always_select', 'update'],
|
||||||
doc.select_doc_for_series);
|
doc.select_doc_for_series);
|
||||||
|
|
||||||
var callback = function(r, rt){
|
var callback = function(r, rt){
|
||||||
@ -40,4 +43,4 @@ cur_frm.cscript.prefix = function(doc, dt, dn) {
|
|||||||
return cur_frm.call_server('get_current', '', function(r) {
|
return cur_frm.call_server('get_current', '', function(r) {
|
||||||
refresh_field('current_value');
|
refresh_field('current_value');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,11 +41,16 @@ def install(country=None):
|
|||||||
{'doctype': 'Expense Claim Type', 'name': _('Travel'), 'expense_type': _('Travel')},
|
{'doctype': 'Expense Claim Type', 'name': _('Travel'), 'expense_type': _('Travel')},
|
||||||
|
|
||||||
# leave type
|
# leave type
|
||||||
{'doctype': 'Leave Type', 'leave_type_name': _('Casual Leave'), 'name': _('Casual Leave'), 'is_encash': 1, 'is_carry_forward': 1, 'max_days_allowed': '3', },
|
{'doctype': 'Leave Type', 'leave_type_name': _('Casual Leave'), 'name': _('Casual Leave'),
|
||||||
{'doctype': 'Leave Type', 'leave_type_name': _('Compensatory Off'), 'name': _('Compensatory Off'), 'is_encash': 0, 'is_carry_forward': 0, },
|
'is_encash': 1, 'is_carry_forward': 1, 'max_days_allowed': '3', 'include_holiday': 1},
|
||||||
{'doctype': 'Leave Type', 'leave_type_name': _('Sick Leave'), 'name': _('Sick Leave'), 'is_encash': 0, 'is_carry_forward': 0, },
|
{'doctype': 'Leave Type', 'leave_type_name': _('Compensatory Off'), 'name': _('Compensatory Off'),
|
||||||
{'doctype': 'Leave Type', 'leave_type_name': _('Privilege Leave'), 'name': _('Privilege Leave'), 'is_encash': 0, 'is_carry_forward': 0, },
|
'is_encash': 0, 'is_carry_forward': 0, 'include_holiday': 1},
|
||||||
{'doctype': 'Leave Type', 'leave_type_name': _('Leave Without Pay'), 'name': _('Leave Without Pay'), 'is_encash': 0, 'is_carry_forward': 0, 'is_lwp':1},
|
{'doctype': 'Leave Type', 'leave_type_name': _('Sick Leave'), 'name': _('Sick Leave'),
|
||||||
|
'is_encash': 0, 'is_carry_forward': 0, 'include_holiday': 1},
|
||||||
|
{'doctype': 'Leave Type', 'leave_type_name': _('Privilege Leave'), 'name': _('Privilege Leave'),
|
||||||
|
'is_encash': 0, 'is_carry_forward': 0, 'include_holiday': 1},
|
||||||
|
{'doctype': 'Leave Type', 'leave_type_name': _('Leave Without Pay'), 'name': _('Leave Without Pay'),
|
||||||
|
'is_encash': 0, 'is_carry_forward': 0, 'is_lwp':1, 'include_holiday': 1},
|
||||||
|
|
||||||
# Employment Type
|
# Employment Type
|
||||||
{'doctype': 'Employment Type', 'employee_type_name': _('Full-time')},
|
{'doctype': 'Employment Type', 'employee_type_name': _('Full-time')},
|
||||||
|
|||||||
@ -11,8 +11,8 @@ def make_sample_data():
|
|||||||
"""Create a few opportunities, quotes, material requests, issues, todos, projects
|
"""Create a few opportunities, quotes, material requests, issues, todos, projects
|
||||||
to help the user get started"""
|
to help the user get started"""
|
||||||
|
|
||||||
selling_items = frappe.get_all("Item", filters = {"is_sales_item": "Yes"})
|
selling_items = frappe.get_all("Item", filters = {"is_sales_item": 1})
|
||||||
buying_items = frappe.get_all("Item", filters = {"is_sales_item": "No"})
|
buying_items = frappe.get_all("Item", filters = {"is_sales_item": 0})
|
||||||
|
|
||||||
if selling_items:
|
if selling_items:
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
@ -37,7 +37,7 @@ def make_opportunity(selling_items):
|
|||||||
|
|
||||||
add_random_children(b, "items", rows=len(selling_items), randomize = {
|
add_random_children(b, "items", rows=len(selling_items), randomize = {
|
||||||
"qty": (1, 5),
|
"qty": (1, 5),
|
||||||
"item_code": ("Item", {"is_sales_item": "Yes"})
|
"item_code": ("Item", {"is_sales_item": 1})
|
||||||
}, unique="item_code")
|
}, unique="item_code")
|
||||||
|
|
||||||
b.insert(ignore_permissions=True)
|
b.insert(ignore_permissions=True)
|
||||||
@ -54,7 +54,7 @@ def make_quote(selling_items):
|
|||||||
|
|
||||||
add_random_children(qtn, "items", rows=len(selling_items), randomize = {
|
add_random_children(qtn, "items", rows=len(selling_items), randomize = {
|
||||||
"qty": (1, 5),
|
"qty": (1, 5),
|
||||||
"item_code": ("Item", {"is_sales_item": "Yes"})
|
"item_code": ("Item", {"is_sales_item": 1})
|
||||||
}, unique="item_code")
|
}, unique="item_code")
|
||||||
|
|
||||||
qtn.insert(ignore_permissions=True)
|
qtn.insert(ignore_permissions=True)
|
||||||
|
|||||||
@ -29,7 +29,7 @@ frappe.pages['setup-wizard'].on_page_load = function(wrapper) {
|
|||||||
erpnext.wiz.taxes.slide,
|
erpnext.wiz.taxes.slide,
|
||||||
erpnext.wiz.customers.slide,
|
erpnext.wiz.customers.slide,
|
||||||
erpnext.wiz.suppliers.slide,
|
erpnext.wiz.suppliers.slide,
|
||||||
erpnext.wiz.items.slide,
|
erpnext.wiz.items.slide
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +406,6 @@ $.extend(erpnext.wiz, {
|
|||||||
description: __('Your financial year begins on'), reqd:1},
|
description: __('Your financial year begins on'), reqd:1},
|
||||||
{fieldname:'fy_end_date', label:__('Financial Year End Date'), fieldtype:'Date',
|
{fieldname:'fy_end_date', label:__('Financial Year End Date'), fieldtype:'Date',
|
||||||
description: __('Your financial year ends on'), reqd:1},
|
description: __('Your financial year ends on'), reqd:1},
|
||||||
|
|
||||||
],
|
],
|
||||||
help: __('The name of your company for which you are setting up this system.'),
|
help: __('The name of your company for which you are setting up this system.'),
|
||||||
|
|
||||||
@ -510,7 +509,7 @@ $.extend(erpnext.wiz, {
|
|||||||
slide: {
|
slide: {
|
||||||
icon: "icon-money",
|
icon: "icon-money",
|
||||||
"title": __("Add Users"),
|
"title": __("Add Users"),
|
||||||
"help": __("Add users to your organization"),
|
"help": __("Add users to your organization, other than yourself"),
|
||||||
"fields": [],
|
"fields": [],
|
||||||
before_load: function(slide) {
|
before_load: function(slide) {
|
||||||
slide.fields = [];
|
slide.fields = [];
|
||||||
@ -635,6 +634,11 @@ $.extend(erpnext.wiz, {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
slide.fields[1].reqd = 1;
|
slide.fields[1].reqd = 1;
|
||||||
|
|
||||||
|
// dummy data
|
||||||
|
slide.fields.push({fieldtype: "Section Break"});
|
||||||
|
slide.fields.push({fieldtype: "Check", fieldname: "add_sample_data",
|
||||||
|
label: __("Add a few sample records"), "default": 1});
|
||||||
},
|
},
|
||||||
css_class: "two-column"
|
css_class: "two-column"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -14,6 +14,7 @@ from frappe.utils.nestedset import get_root_of
|
|||||||
from .default_website import website_maker
|
from .default_website import website_maker
|
||||||
import install_fixtures
|
import install_fixtures
|
||||||
from .sample_data import make_sample_data
|
from .sample_data import make_sample_data
|
||||||
|
from erpnext.accounts.utils import FiscalYearError
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def setup_account(args=None):
|
def setup_account(args=None):
|
||||||
@ -85,7 +86,11 @@ def setup_account(args=None):
|
|||||||
|
|
||||||
frappe.clear_cache()
|
frappe.clear_cache()
|
||||||
|
|
||||||
make_sample_data()
|
if args.get("add_sample_data"):
|
||||||
|
try:
|
||||||
|
make_sample_data()
|
||||||
|
except FiscalYearError:
|
||||||
|
pass
|
||||||
except:
|
except:
|
||||||
if args:
|
if args:
|
||||||
traceback = frappe.get_traceback()
|
traceback = frappe.get_traceback()
|
||||||
@ -363,10 +368,10 @@ def create_items(args):
|
|||||||
"item_code": item,
|
"item_code": item,
|
||||||
"item_name": item,
|
"item_name": item,
|
||||||
"description": item,
|
"description": item,
|
||||||
"is_sales_item": "Yes" if is_sales_item else "No",
|
"is_sales_item": 1 if is_sales_item else 0,
|
||||||
"is_purchase_item": "Yes" if is_purchase_item else "No",
|
"is_purchase_item": 1 if is_purchase_item else 0,
|
||||||
"show_in_website": 1,
|
"show_in_website": 1,
|
||||||
"is_stock_item": is_stock_item and "Yes" or "No",
|
"is_stock_item": is_stock_item and 1 or 0,
|
||||||
"item_group": item_group,
|
"item_group": item_group,
|
||||||
"stock_uom": args.get("item_uom_" + str(i)),
|
"stock_uom": args.get("item_uom_" + str(i)),
|
||||||
"default_warehouse": default_warehouse
|
"default_warehouse": default_warehouse
|
||||||
@ -542,18 +547,20 @@ def create_users(args):
|
|||||||
user.append_roles("Accounts Manager", "Accounts User")
|
user.append_roles("Accounts Manager", "Accounts User")
|
||||||
|
|
||||||
user.flags.delay_emails = True
|
user.flags.delay_emails = True
|
||||||
user.insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
# create employee
|
if not frappe.db.get_value("User", email):
|
||||||
emp = frappe.get_doc({
|
user.insert(ignore_permissions=True)
|
||||||
"doctype": "Employee",
|
|
||||||
"full_name": fullname,
|
# create employee
|
||||||
"user_id": user.name,
|
emp = frappe.get_doc({
|
||||||
"status": "Active",
|
"doctype": "Employee",
|
||||||
"company": args.get("company_name")
|
"full_name": fullname,
|
||||||
})
|
"user_id": email,
|
||||||
emp.flags.ignore_mandatory = True
|
"status": "Active",
|
||||||
emp.insert(ignore_permissions = True)
|
"company": args.get("company_name")
|
||||||
|
})
|
||||||
|
emp.flags.ignore_mandatory = True
|
||||||
|
emp.insert(ignore_permissions = True)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def load_messages(language):
|
def load_messages(language):
|
||||||
|
|||||||
@ -5,8 +5,8 @@ cur_frm.fields_dict['item'].get_query = function(doc, cdt, cdn) {
|
|||||||
return {
|
return {
|
||||||
query: "erpnext.controllers.queries.item_query",
|
query: "erpnext.controllers.queries.item_query",
|
||||||
filters:{
|
filters:{
|
||||||
'is_stock_item': 'Yes',
|
'is_stock_item': 1,
|
||||||
'has_batch_no': 'Yes'
|
'has_batch_no': 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,10 @@ from frappe import _
|
|||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class Batch(Document):
|
class Batch(Document):
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.item_has_batch_enabled()
|
self.item_has_batch_enabled()
|
||||||
|
|
||||||
def item_has_batch_enabled(self):
|
def item_has_batch_enabled(self):
|
||||||
if frappe.db.get_value("Item",self.item,"has_batch_no") =='No':
|
if frappe.db.get_value("Item",self.item,"has_batch_no") == 0:
|
||||||
frappe.throw(_("The selected item cannot have Batch"))
|
frappe.throw(_("The selected item cannot have Batch"))
|
||||||
|
|||||||
@ -8,57 +8,64 @@ frappe.provide("erpnext.stock.delivery_note");
|
|||||||
erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend({
|
erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend({
|
||||||
refresh: function(doc, dt, dn) {
|
refresh: function(doc, dt, dn) {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
|
if (!doc.is_return) {
|
||||||
|
if(doc.__onload && !doc.__onload.billing_complete && doc.docstatus==1) {
|
||||||
|
// show Make Invoice button only if Delivery Note is not created from Sales Invoice
|
||||||
|
var from_sales_invoice = false;
|
||||||
|
from_sales_invoice = cur_frm.doc.items.some(function(item) {
|
||||||
|
return item.against_sales_invoice ? true : false;
|
||||||
|
});
|
||||||
|
|
||||||
if(doc.__onload && !doc.__onload.billing_complete && doc.docstatus==1) {
|
if(!from_sales_invoice)
|
||||||
// show Make Invoice button only if Delivery Note is not created from Sales Invoice
|
cur_frm.add_custom_button(__('Make Invoice'), this.make_sales_invoice);
|
||||||
var from_sales_invoice = false;
|
}
|
||||||
from_sales_invoice = cur_frm.doc.items.some(function(item) {
|
|
||||||
return item.against_sales_invoice ? true : false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if(!from_sales_invoice)
|
if(flt(doc.per_installed, 2) < 100 && doc.docstatus==1)
|
||||||
cur_frm.add_custom_button(__('Make Invoice'), this.make_sales_invoice);
|
cur_frm.add_custom_button(__('Make Installation Note'), this.make_installation_note);
|
||||||
|
|
||||||
|
if (doc.docstatus==1) {
|
||||||
|
cur_frm.add_custom_button(__('Make Sales Return'), this.make_sales_return);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doc.docstatus==0 && !doc.__islocal) {
|
||||||
|
cur_frm.add_custom_button(__('Make Packing Slip'),
|
||||||
|
cur_frm.cscript['Make Packing Slip'], frappe.boot.doctype_icons["Packing Slip"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.frm.doc.docstatus===0) {
|
||||||
|
cur_frm.add_custom_button(__('From Sales Order'),
|
||||||
|
function() {
|
||||||
|
frappe.model.map_current_doc({
|
||||||
|
method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
|
||||||
|
source_doctype: "Sales Order",
|
||||||
|
get_query_filters: {
|
||||||
|
docstatus: 1,
|
||||||
|
status: ["!=", "Stopped"],
|
||||||
|
per_delivered: ["<", 99.99],
|
||||||
|
project_name: cur_frm.doc.project_name || undefined,
|
||||||
|
customer: cur_frm.doc.customer || undefined,
|
||||||
|
company: cur_frm.doc.company
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flt(doc.per_installed, 2) < 100 && doc.docstatus==1)
|
|
||||||
cur_frm.add_custom_button(__('Make Installation Note'), this.make_installation_note);
|
|
||||||
|
|
||||||
if (doc.docstatus==1) {
|
if (doc.docstatus==1) {
|
||||||
cur_frm.add_custom_button(__('Make Sales Return'), this.make_sales_return);
|
|
||||||
|
|
||||||
this.show_stock_ledger();
|
this.show_stock_ledger();
|
||||||
this.show_general_ledger();
|
if (cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
|
||||||
}
|
this.show_general_ledger();
|
||||||
|
}
|
||||||
if(doc.docstatus==0 && !doc.__islocal) {
|
|
||||||
cur_frm.add_custom_button(__('Make Packing Slip'),
|
|
||||||
cur_frm.cscript['Make Packing Slip'], frappe.boot.doctype_icons["Packing Slip"]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
erpnext.stock.delivery_note.set_print_hide(doc, dt, dn);
|
erpnext.stock.delivery_note.set_print_hide(doc, dt, dn);
|
||||||
|
|
||||||
// unhide expense_account and cost_center is auto_accounting_for_stock enabled
|
// unhide expense_account and cost_center is auto_accounting_for_stock enabled
|
||||||
var aii_enabled = cint(sys_defaults.auto_accounting_for_stock)
|
var aii_enabled = cint(sys_defaults.auto_accounting_for_stock)
|
||||||
cur_frm.fields_dict["items"].grid.set_column_disp(["expense_account", "cost_center"], aii_enabled);
|
cur_frm.fields_dict["items"].grid.set_column_disp(["expense_account", "cost_center"], aii_enabled);
|
||||||
|
|
||||||
if (this.frm.doc.docstatus===0) {
|
|
||||||
cur_frm.add_custom_button(__('From Sales Order'),
|
|
||||||
function() {
|
|
||||||
frappe.model.map_current_doc({
|
|
||||||
method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
|
|
||||||
source_doctype: "Sales Order",
|
|
||||||
get_query_filters: {
|
|
||||||
docstatus: 1,
|
|
||||||
status: ["!=", "Stopped"],
|
|
||||||
per_delivered: ["<", 99.99],
|
|
||||||
project_name: cur_frm.doc.project_name || undefined,
|
|
||||||
customer: cur_frm.doc.customer || undefined,
|
|
||||||
company: cur_frm.doc.company
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
make_sales_invoice: function() {
|
make_sales_invoice: function() {
|
||||||
|
|||||||
@ -9,7 +9,6 @@ from frappe.utils import flt, cint
|
|||||||
from frappe import msgprint, _
|
from frappe import msgprint, _
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
from erpnext.stock.utils import update_bin
|
|
||||||
from erpnext.controllers.selling_controller import SellingController
|
from erpnext.controllers.selling_controller import SellingController
|
||||||
|
|
||||||
form_grid_templates = {
|
form_grid_templates = {
|
||||||
@ -108,7 +107,7 @@ class DeliveryNote(SellingController):
|
|||||||
if not self.installation_status: self.installation_status = 'Not Installed'
|
if not self.installation_status: self.installation_status = 'Not Installed'
|
||||||
|
|
||||||
def validate_with_previous_doc(self):
|
def validate_with_previous_doc(self):
|
||||||
for fn in (("Sales Order", "against_sales_order", "so_detail"),
|
for fn in (("Sales Order", "against_sales_order", "so_detail"),
|
||||||
("Sales Invoice", "against_sales_invoice", "si_detail")):
|
("Sales Invoice", "against_sales_invoice", "si_detail")):
|
||||||
if filter(None, [getattr(d, fn[1], None) for d in self.get("items")]):
|
if filter(None, [getattr(d, fn[1], None) for d in self.get("items")]):
|
||||||
super(DeliveryNote, self).validate_with_previous_doc({
|
super(DeliveryNote, self).validate_with_previous_doc({
|
||||||
@ -118,9 +117,9 @@ class DeliveryNote(SellingController):
|
|||||||
["currency", "="]],
|
["currency", "="]],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')):
|
if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')):
|
||||||
self.validate_rate_with_reference_doc([["Sales Order", "sales_order", "so_detail"],
|
self.validate_rate_with_reference_doc([["Sales Order", "sales_order", "so_detail"],
|
||||||
["Sales Invoice", "sales_invoice", "si_detail"]])
|
["Sales Invoice", "sales_invoice", "si_detail"]])
|
||||||
|
|
||||||
def validate_proj_cust(self):
|
def validate_proj_cust(self):
|
||||||
@ -138,7 +137,7 @@ class DeliveryNote(SellingController):
|
|||||||
e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
|
e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
|
||||||
f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
|
f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
|
||||||
|
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes':
|
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
|
||||||
if e in check_list:
|
if e in check_list:
|
||||||
msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
|
msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
|
||||||
else:
|
else:
|
||||||
@ -151,7 +150,7 @@ class DeliveryNote(SellingController):
|
|||||||
|
|
||||||
def validate_warehouse(self):
|
def validate_warehouse(self):
|
||||||
for d in self.get_item_list():
|
for d in self.get_item_list():
|
||||||
if frappe.db.get_value("Item", d['item_code'], "is_stock_item") == "Yes":
|
if frappe.db.get_value("Item", d['item_code'], "is_stock_item") == 1:
|
||||||
if not d['warehouse']:
|
if not d['warehouse']:
|
||||||
frappe.throw(_("Warehouse required for stock Item {0}").format(d["item_code"]))
|
frappe.throw(_("Warehouse required for stock Item {0}").format(d["item_code"]))
|
||||||
|
|
||||||
@ -247,7 +246,7 @@ class DeliveryNote(SellingController):
|
|||||||
def update_stock_ledger(self):
|
def update_stock_ledger(self):
|
||||||
sl_entries = []
|
sl_entries = []
|
||||||
for d in self.get_item_list():
|
for d in self.get_item_list():
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" \
|
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 \
|
||||||
and d.warehouse and flt(d['qty']):
|
and d.warehouse and flt(d['qty']):
|
||||||
self.update_reserved_qty(d)
|
self.update_reserved_qty(d)
|
||||||
|
|
||||||
@ -262,23 +261,6 @@ class DeliveryNote(SellingController):
|
|||||||
|
|
||||||
self.make_sl_entries(sl_entries)
|
self.make_sl_entries(sl_entries)
|
||||||
|
|
||||||
def update_reserved_qty(self, d):
|
|
||||||
if d['reserved_qty'] < 0 :
|
|
||||||
# Reduce reserved qty from reserved warehouse mentioned in so
|
|
||||||
if not d["reserved_warehouse"]:
|
|
||||||
frappe.throw(_("Reserved Warehouse is missing in Sales Order"))
|
|
||||||
|
|
||||||
args = {
|
|
||||||
"item_code": d['item_code'],
|
|
||||||
"warehouse": d["reserved_warehouse"],
|
|
||||||
"voucher_type": self.doctype,
|
|
||||||
"voucher_no": self.name,
|
|
||||||
"reserved_qty": (self.docstatus==1 and 1 or -1)*flt(d['reserved_qty']),
|
|
||||||
"posting_date": self.posting_date,
|
|
||||||
"is_amended": self.amended_from and 'Yes' or 'No'
|
|
||||||
}
|
|
||||||
update_bin(args)
|
|
||||||
|
|
||||||
def get_list_context(context=None):
|
def get_list_context(context=None):
|
||||||
from erpnext.controllers.website_list_for_contact import get_list_context
|
from erpnext.controllers.website_list_for_contact import get_list_context
|
||||||
list_context = get_list_context(context)
|
list_context = get_list_context(context)
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
frappe.listview_settings['Delivery Note'] = {
|
frappe.listview_settings['Delivery Note'] = {
|
||||||
add_fields: ["customer", "customer_name", "base_grand_total", "per_installed",
|
add_fields: ["customer", "customer_name", "base_grand_total", "per_installed",
|
||||||
"transporter_name", "grand_total"]
|
"transporter_name", "grand_total", "is_return"],
|
||||||
|
get_indicator: function(doc) {
|
||||||
|
if(cint(doc.is_return)==1) {
|
||||||
|
return [__("Return"), "darkgrey", "is_return,=,1"];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -43,7 +43,7 @@ frappe.ui.form.on("Item", {
|
|||||||
|
|
||||||
erpnext.item.edit_prices_button(frm);
|
erpnext.item.edit_prices_button(frm);
|
||||||
|
|
||||||
if (!frm.doc.__islocal && frm.doc.is_stock_item == 'Yes') {
|
if (!frm.doc.__islocal && frm.doc.is_stock_item) {
|
||||||
frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method', 'has_batch_no'],
|
frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method', 'has_batch_no'],
|
||||||
(frm.doc.__onload && frm.doc.__onload.sle_exists=="exists") ? false : true);
|
(frm.doc.__onload && frm.doc.__onload.sle_exists=="exists") ? false : true);
|
||||||
}
|
}
|
||||||
@ -80,11 +80,11 @@ frappe.ui.form.on("Item", {
|
|||||||
method: "copy_specification_from_item_group"
|
method: "copy_specification_from_item_group"
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
is_stock_item: function(frm) {
|
is_stock_item: function(frm) {
|
||||||
erpnext.item.toggle_reqd(frm);
|
erpnext.item.toggle_reqd(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
manage_variants: function(frm) {
|
manage_variants: function(frm) {
|
||||||
if (cur_frm.doc.__unsaved==1) {
|
if (cur_frm.doc.__unsaved==1) {
|
||||||
frappe.throw(__("You have unsaved changes. Please save."))
|
frappe.throw(__("You have unsaved changes. Please save."))
|
||||||
@ -168,7 +168,7 @@ $.extend(erpnext.item, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
toggle_reqd: function(frm) {
|
toggle_reqd: function(frm) {
|
||||||
frm.toggle_reqd("default_warehouse", frm.doc.is_stock_item==="Yes");
|
frm.toggle_reqd("default_warehouse", frm.doc.is_stock_item);
|
||||||
},
|
},
|
||||||
|
|
||||||
make_dashboard: function(frm) {
|
make_dashboard: function(frm) {
|
||||||
|
|||||||
@ -28,7 +28,7 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Item will be saved by this name in the data base.",
|
"description": "",
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_filter": 0,
|
"in_filter": 0,
|
||||||
@ -80,7 +80,7 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Unit of measurement of this item (e.g. Kg, Unit, No, Pair).",
|
"description": "",
|
||||||
"fieldname": "stock_uom",
|
"fieldname": "stock_uom",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
@ -113,17 +113,6 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "2099-12-31",
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"fieldname": "end_of_life",
|
|
||||||
"fieldtype": "Date",
|
|
||||||
"label": "End of Life",
|
|
||||||
"oldfieldname": "end_of_life",
|
|
||||||
"oldfieldtype": "Date",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "column_break0",
|
"fieldname": "column_break0",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
@ -166,11 +155,233 @@
|
|||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0
|
"search_index": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "inventory",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Inventory",
|
||||||
|
"oldfieldtype": "Section Break",
|
||||||
|
"options": "icon-truck",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "1",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "is_stock_item",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Maintain Stock",
|
||||||
|
"oldfieldname": "is_stock_item",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"depends_on": "eval:doc.is_stock_item",
|
||||||
|
"fieldname": "has_batch_no",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Has Batch No",
|
||||||
|
"oldfieldname": "has_batch_no",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"depends_on": "eval:doc.is_stock_item",
|
||||||
|
"description": "Selecting \"Yes\" will give a unique identity to each entity of this item which can be viewed in the Serial No master.",
|
||||||
|
"fieldname": "has_serial_no",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"in_filter": 1,
|
||||||
|
"label": "Has Serial No",
|
||||||
|
"oldfieldname": "has_serial_no",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "has_serial_no",
|
||||||
|
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
|
||||||
|
"fieldname": "serial_no_series",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Serial Number Series",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"depends_on": "eval:doc.is_stock_item",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "is_asset_item",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Is Fixed Asset Item",
|
||||||
|
"oldfieldname": "is_asset_item",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "is_stock_item",
|
||||||
|
"fieldname": "column_break1",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"oldfieldtype": "Column Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"width": "50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "default_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
|
"label": "Default Warehouse",
|
||||||
|
"oldfieldname": "default_warehouse",
|
||||||
|
"oldfieldtype": "Link",
|
||||||
|
"options": "Warehouse",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "is_stock_item",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "tolerance",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Allow over delivery or receipt upto this percent",
|
||||||
|
"oldfieldname": "tolerance",
|
||||||
|
"oldfieldtype": "Currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "is_stock_item",
|
||||||
|
"fieldname": "valuation_method",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Valuation Method",
|
||||||
|
"options": "\nFIFO\nMoving Average",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0.00",
|
||||||
|
"depends_on": "is_stock_item",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "min_order_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Minimum Order Qty",
|
||||||
|
"oldfieldname": "min_order_qty",
|
||||||
|
"oldfieldtype": "Currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_stock_item",
|
||||||
|
"fieldname": "warranty_period",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Warranty Period (in days)",
|
||||||
|
"oldfieldname": "warranty_period",
|
||||||
|
"oldfieldtype": "Data",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "2099-12-31",
|
||||||
|
"depends_on": "is_stock_item",
|
||||||
|
"fieldname": "end_of_life",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "End of Life",
|
||||||
|
"oldfieldname": "end_of_life",
|
||||||
|
"oldfieldtype": "Date",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "is_stock_item",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "net_weight",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Net Weight",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_stock_item",
|
||||||
|
"fieldname": "weight_uom",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
|
"label": "Weight UOM",
|
||||||
|
"options": "UOM",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_stock_item",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "reorder_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Auto re-order",
|
||||||
|
"options": "icon-rss",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:(doc.is_stock_item && !doc.apply_warehouse_wise_reorder_level)",
|
||||||
|
"description": "Automatically create Material Request if quantity falls below this level",
|
||||||
|
"fieldname": "re_order_level",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Re-order Level",
|
||||||
|
"oldfieldname": "re_order_level",
|
||||||
|
"oldfieldtype": "Currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:(doc.is_stock_item && !doc.apply_warehouse_wise_reorder_level)",
|
||||||
|
"fieldname": "re_order_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Re-order Qty",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "is_stock_item",
|
||||||
|
"fieldname": "apply_warehouse_wise_reorder_level",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Apply Warehouse-wise Reorder Level",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:(doc.is_stock_item && doc.apply_warehouse_wise_reorder_level)",
|
||||||
|
"fieldname": "section_break_31",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:(doc.is_stock_item && doc.apply_warehouse_wise_reorder_level)",
|
||||||
|
"description": "Will also apply for variants unless overrridden",
|
||||||
|
"fieldname": "reorder_levels",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Warehouse-wise Reorder Levels",
|
||||||
|
"options": "Item Reorder",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:!doc.variant_of",
|
"depends_on": "eval:!doc.variant_of",
|
||||||
"fieldname": "variants_section",
|
"fieldname": "variants_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Variant",
|
"label": "Variants",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
@ -219,253 +430,34 @@
|
|||||||
"precision": "",
|
"precision": "",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "inventory",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Inventory",
|
|
||||||
"oldfieldtype": "Section Break",
|
|
||||||
"options": "icon-truck",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "Yes",
|
|
||||||
"description": "Select \"Yes\" if you are maintaining stock of this item in your Inventory.",
|
|
||||||
"fieldname": "is_stock_item",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Is Stock Item",
|
|
||||||
"oldfieldname": "is_stock_item",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "Yes\nNo",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "",
|
|
||||||
"description": "Mandatory if Stock Item is \"Yes\". Also the default warehouse where reserved quantity is set from Sales Order.",
|
|
||||||
"fieldname": "default_warehouse",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"ignore_user_permissions": 1,
|
|
||||||
"label": "Default Warehouse",
|
|
||||||
"oldfieldname": "default_warehouse",
|
|
||||||
"oldfieldtype": "Link",
|
|
||||||
"options": "Warehouse",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"description": "Percentage variation in quantity to be allowed while receiving or delivering this item.",
|
|
||||||
"fieldname": "tolerance",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Allowance Percent",
|
|
||||||
"oldfieldname": "tolerance",
|
|
||||||
"oldfieldtype": "Currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"fieldname": "valuation_method",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Valuation Method",
|
|
||||||
"options": "\nFIFO\nMoving Average",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0.00",
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"description": "You can enter the minimum quantity of this item to be ordered.",
|
|
||||||
"fieldname": "min_order_qty",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"hidden": 0,
|
|
||||||
"label": "Minimum Order Qty",
|
|
||||||
"oldfieldname": "min_order_qty",
|
|
||||||
"oldfieldtype": "Currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"fieldname": "column_break1",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"oldfieldtype": "Column Break",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"width": "50%"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "No",
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"description": "Select \"Yes\" if this item is used for some internal purpose in your company.",
|
|
||||||
"fieldname": "is_asset_item",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Is Fixed Asset Item",
|
|
||||||
"oldfieldname": "is_asset_item",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "Yes\nNo",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "No",
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"fieldname": "has_batch_no",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Has Batch No",
|
|
||||||
"oldfieldname": "has_batch_no",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "Yes\nNo",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "No",
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"description": "Selecting \"Yes\" will give a unique identity to each entity of this item which can be viewed in the Serial No master.",
|
|
||||||
"fieldname": "has_serial_no",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"in_filter": 1,
|
|
||||||
"label": "Has Serial No",
|
|
||||||
"oldfieldname": "has_serial_no",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "Yes\nNo",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval: doc.has_serial_no===\"Yes\"",
|
|
||||||
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
|
|
||||||
"fieldname": "serial_no_series",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Serial Number Series",
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"fieldname": "warranty_period",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Warranty Period (in days)",
|
|
||||||
"oldfieldname": "warranty_period",
|
|
||||||
"oldfieldtype": "Data",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"description": "Net Weight of each Item",
|
|
||||||
"fieldname": "net_weight",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Net Weight",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"fieldname": "weight_uom",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"ignore_user_permissions": 1,
|
|
||||||
"label": "Weight UOM",
|
|
||||||
"options": "UOM",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"description": "Auto-raise Material Request if quantity goes below re-order level in default warehouse",
|
|
||||||
"fieldname": "reorder_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Re-order",
|
|
||||||
"options": "icon-rss",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:(doc.is_stock_item==\"Yes\" && !doc.apply_warehouse_wise_reorder_level)",
|
|
||||||
"fieldname": "re_order_level",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Re-Order Level",
|
|
||||||
"oldfieldname": "re_order_level",
|
|
||||||
"oldfieldtype": "Currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:(doc.is_stock_item==\"Yes\" && !doc.apply_warehouse_wise_reorder_level)",
|
|
||||||
"fieldname": "re_order_qty",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Re-Order Qty",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
|
|
||||||
"fieldname": "apply_warehouse_wise_reorder_level",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Apply Warehouse-wise Reorder Level",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:(doc.is_stock_item==\"Yes\" && doc.apply_warehouse_wise_reorder_level)",
|
|
||||||
"fieldname": "section_break_31",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:(doc.is_stock_item==\"Yes\" && doc.apply_warehouse_wise_reorder_level)",
|
|
||||||
"description": "Will also apply for variants unless overrridden",
|
|
||||||
"fieldname": "reorder_levels",
|
|
||||||
"fieldtype": "Table",
|
|
||||||
"label": "Warehouse-wise Reorder Levels",
|
|
||||||
"options": "Item Reorder",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "purchase_details",
|
"fieldname": "purchase_details",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "",
|
"label": "Purchase Details",
|
||||||
"oldfieldtype": "Section Break",
|
"oldfieldtype": "Section Break",
|
||||||
"options": "icon-shopping-cart",
|
"options": "icon-shopping-cart",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "Yes",
|
"default": "1",
|
||||||
"description": "Selecting \"Yes\" will allow this item to appear in Purchase Order , Purchase Receipt.",
|
"description": "",
|
||||||
"fieldname": "is_purchase_item",
|
"fieldname": "is_purchase_item",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Check",
|
||||||
"label": "Is Purchase Item",
|
"label": "Is Purchase Item",
|
||||||
"oldfieldname": "is_purchase_item",
|
"oldfieldname": "is_purchase_item",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "Yes\nNo",
|
"options": "",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
"depends_on": "is_purchase_item",
|
||||||
"fieldname": "default_supplier",
|
"description": "Average time taken by the supplier to deliver",
|
||||||
"fieldtype": "Link",
|
|
||||||
"ignore_user_permissions": 1,
|
|
||||||
"label": "Default Supplier",
|
|
||||||
"options": "Supplier",
|
|
||||||
"permlevel": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
|
||||||
"description": "Lead Time days is number of days by which this item is expected in your warehouse. This days is fetched in Material Request when you select this item.",
|
|
||||||
"fieldname": "lead_time_days",
|
"fieldname": "lead_time_days",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Lead Time Days",
|
"label": "Lead Time in days",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"oldfieldname": "lead_time_days",
|
"oldfieldname": "lead_time_days",
|
||||||
"oldfieldtype": "Int",
|
"oldfieldtype": "Int",
|
||||||
@ -473,20 +465,7 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "",
|
"depends_on": "is_purchase_item",
|
||||||
"description": "Default Purchase Account in which cost of the item will be debited.",
|
|
||||||
"fieldname": "expense_account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"ignore_user_permissions": 1,
|
|
||||||
"label": "Default Expense Account",
|
|
||||||
"oldfieldname": "purchase_account",
|
|
||||||
"oldfieldtype": "Link",
|
|
||||||
"options": "Account",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "",
|
|
||||||
"description": "",
|
"description": "",
|
||||||
"fieldname": "buying_cost_center",
|
"fieldname": "buying_cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -499,27 +478,28 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
"depends_on": "is_purchase_item",
|
||||||
"fieldname": "last_purchase_rate",
|
"description": "",
|
||||||
"fieldtype": "Float",
|
"fieldname": "expense_account",
|
||||||
"label": "Last Purchase Rate",
|
"fieldtype": "Link",
|
||||||
"no_copy": 1,
|
"ignore_user_permissions": 1,
|
||||||
"oldfieldname": "last_purchase_rate",
|
"label": "Default Expense Account",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldname": "purchase_account",
|
||||||
|
"oldfieldtype": "Link",
|
||||||
|
"options": "Account",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
"depends_on": "is_purchase_item",
|
||||||
"fieldname": "column_break2",
|
"fieldname": "unit_of_measure_conversion",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"oldfieldtype": "Column Break",
|
"label": "Unit of Measure Conversion",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"precision": ""
|
||||||
"width": "50%"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
"depends_on": "is_purchase_item",
|
||||||
"description": "Will also apply for variants",
|
"description": "Will also apply for variants",
|
||||||
"fieldname": "uoms",
|
"fieldname": "uoms",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
@ -532,7 +512,35 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
"depends_on": "is_purchase_item",
|
||||||
|
"fieldname": "last_purchase_rate",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Last Purchase Rate",
|
||||||
|
"no_copy": 1,
|
||||||
|
"oldfieldname": "last_purchase_rate",
|
||||||
|
"oldfieldtype": "Currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "is_purchase_item",
|
||||||
|
"fieldname": "supplier_details",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Supplier Details",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_purchase_item",
|
||||||
|
"fieldname": "default_supplier",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
|
"label": "Default Supplier",
|
||||||
|
"options": "Supplier",
|
||||||
|
"permlevel": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_purchase_item",
|
||||||
"fieldname": "manufacturer",
|
"fieldname": "manufacturer",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Manufacturer",
|
"label": "Manufacturer",
|
||||||
@ -540,7 +548,7 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
"depends_on": "eval:doc.is_purchase_item",
|
||||||
"fieldname": "manufacturer_part_no",
|
"fieldname": "manufacturer_part_no",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Manufacturer Part Number",
|
"label": "Manufacturer Part Number",
|
||||||
@ -548,7 +556,17 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
|
"depends_on": "is_purchase_item",
|
||||||
|
"fieldname": "column_break2",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"label": "Item Code for Suppliers",
|
||||||
|
"oldfieldtype": "Column Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"width": "50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "is_purchase_item",
|
||||||
"fieldname": "supplier_items",
|
"fieldname": "supplier_items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Supplier Items",
|
"label": "Supplier Items",
|
||||||
@ -566,30 +584,30 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "Yes",
|
"default": "1",
|
||||||
"description": "Selecting \"Yes\" will allow this item to figure in Sales Order, Delivery Note",
|
"description": "",
|
||||||
"fieldname": "is_sales_item",
|
"fieldname": "is_sales_item",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Check",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Is Sales Item",
|
"label": "Is Sales Item",
|
||||||
"oldfieldname": "is_sales_item",
|
"oldfieldname": "is_sales_item",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "Yes\nNo",
|
"options": "",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "No",
|
"default": "",
|
||||||
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
|
"depends_on": "eval:doc.is_sales_item",
|
||||||
"description": "Select \"Yes\" if this item represents some work like training, designing, consulting etc.",
|
"description": "Allow in Sales Order of type \"Service\"",
|
||||||
"fieldname": "is_service_item",
|
"fieldname": "is_service_item",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Check",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Is Service Item",
|
"label": "Is Service Item",
|
||||||
"oldfieldname": "is_service_item",
|
"oldfieldname": "is_service_item",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "Yes\nNo",
|
"options": "",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
@ -614,17 +632,7 @@
|
|||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
|
"depends_on": "is_sales_item",
|
||||||
"fieldname": "max_discount",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Max Discount (%)",
|
|
||||||
"oldfieldname": "max_discount",
|
|
||||||
"oldfieldtype": "Currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
|
|
||||||
"fieldname": "income_account",
|
"fieldname": "income_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
@ -634,7 +642,7 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
|
"depends_on": "is_sales_item",
|
||||||
"fieldname": "selling_cost_center",
|
"fieldname": "selling_cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
@ -644,17 +652,18 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
|
"depends_on": "is_sales_item",
|
||||||
"fieldname": "column_break3",
|
"fieldname": "column_break3",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
|
"label": "Customer Item Codes",
|
||||||
"oldfieldtype": "Column Break",
|
"oldfieldtype": "Column Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
|
"depends_on": "is_sales_item",
|
||||||
"description": "For the convenience of customers, these codes can be used in print formats like Invoices and Delivery Notes",
|
"description": "",
|
||||||
"fieldname": "customer_items",
|
"fieldname": "customer_items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Customer Items",
|
"label": "Customer Items",
|
||||||
@ -662,6 +671,16 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_sales_item",
|
||||||
|
"fieldname": "max_discount",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Max Discount (%)",
|
||||||
|
"oldfieldname": "max_discount",
|
||||||
|
"oldfieldtype": "Currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "item_tax_section_break",
|
"fieldname": "item_tax_section_break",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@ -692,20 +711,20 @@
|
|||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "No",
|
"default": "",
|
||||||
"fieldname": "inspection_required",
|
"fieldname": "inspection_required",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Check",
|
||||||
"label": "Inspection Required",
|
"label": "Inspection Required",
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"oldfieldname": "inspection_required",
|
"oldfieldname": "inspection_required",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "\nYes\nNo",
|
"options": "",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.inspection_required==\"Yes\"",
|
"depends_on": "inspection_required",
|
||||||
"description": "Will also apply to variants",
|
"description": "Will also apply to variants",
|
||||||
"fieldname": "quality_parameters",
|
"fieldname": "quality_parameters",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
@ -725,6 +744,39 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"depends_on": "",
|
||||||
|
"description": "",
|
||||||
|
"fieldname": "is_pro_applicable",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Allow Production Order",
|
||||||
|
"oldfieldname": "is_pro_applicable",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "",
|
||||||
|
"description": "If subcontracted to a vendor",
|
||||||
|
"fieldname": "is_sub_contracted_item",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Supply Raw Materials for Purchase",
|
||||||
|
"oldfieldname": "is_sub_contracted_item",
|
||||||
|
"oldfieldtype": "Select",
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_74",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "",
|
"depends_on": "",
|
||||||
"fieldname": "default_bom",
|
"fieldname": "default_bom",
|
||||||
@ -738,33 +790,6 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"default": "No",
|
|
||||||
"depends_on": "",
|
|
||||||
"description": "Selecting \"Yes\" will allow you to make a Production Order for this item.",
|
|
||||||
"fieldname": "is_pro_applicable",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Allow Production Order",
|
|
||||||
"oldfieldname": "is_pro_applicable",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "Yes\nNo",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "No",
|
|
||||||
"description": "",
|
|
||||||
"fieldname": "is_sub_contracted_item",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Supply Raw Materials for Purchase",
|
|
||||||
"oldfieldname": "is_sub_contracted_item",
|
|
||||||
"oldfieldtype": "Select",
|
|
||||||
"options": "Yes\nNo",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "customer_code",
|
"fieldname": "customer_code",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
@ -803,7 +828,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "show_in_website",
|
"depends_on": "show_in_website",
|
||||||
"description": "Products will be sorted by weight-age in default searches. More the weight-age, higher the product will appear in the list.",
|
"description": "Items with higher weightage will be shown higher",
|
||||||
"fieldname": "weightage",
|
"fieldname": "weightage",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Weightage",
|
"label": "Weightage",
|
||||||
@ -865,6 +890,13 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "website_specifications_cb",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"label": "Website Specifications",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "show_in_website",
|
"depends_on": "show_in_website",
|
||||||
"fieldname": "copy_from_item_group",
|
"fieldname": "copy_from_item_group",
|
||||||
@ -903,7 +935,7 @@
|
|||||||
"icon": "icon-tag",
|
"icon": "icon-tag",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2015-07-13 05:28:28.698107",
|
"modified": "2015-07-24 06:04:28.448050",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item",
|
"name": "Item",
|
||||||
|
|||||||
@ -87,7 +87,7 @@ class Item(WebsiteGenerator):
|
|||||||
return context
|
return context
|
||||||
|
|
||||||
def check_warehouse_is_set_for_stock_item(self):
|
def check_warehouse_is_set_for_stock_item(self):
|
||||||
if self.is_stock_item=="Yes" and not self.default_warehouse and frappe.get_all("Warehouse"):
|
if self.is_stock_item==1 and not self.default_warehouse and frappe.get_all("Warehouse"):
|
||||||
frappe.msgprint(_("Default Warehouse is mandatory for stock Item."),
|
frappe.msgprint(_("Default Warehouse is mandatory for stock Item."),
|
||||||
raise_exception=WarehouseNotSet)
|
raise_exception=WarehouseNotSet)
|
||||||
|
|
||||||
@ -158,13 +158,13 @@ class Item(WebsiteGenerator):
|
|||||||
frappe.throw(_("Conversion factor for default Unit of Measure must be 1 in row {0}").format(d.idx))
|
frappe.throw(_("Conversion factor for default Unit of Measure must be 1 in row {0}").format(d.idx))
|
||||||
|
|
||||||
def validate_item_type(self):
|
def validate_item_type(self):
|
||||||
if self.is_pro_applicable == 'Yes' and self.is_stock_item == 'No':
|
if self.is_pro_applicable == 1 and self.is_stock_item==0:
|
||||||
frappe.throw(_("As Production Order can be made for this item, it must be a stock item."))
|
frappe.throw(_("As Production Order can be made for this item, it must be a stock item."))
|
||||||
|
|
||||||
if self.has_serial_no == 'Yes' and self.is_stock_item == 'No':
|
if self.has_serial_no == 1 and self.is_stock_item == 0:
|
||||||
msgprint(_("'Has Serial No' can not be 'Yes' for non-stock item"), raise_exception=1)
|
msgprint(_("'Has Serial No' can not be 'Yes' for non-stock item"), raise_exception=1)
|
||||||
|
|
||||||
if self.has_serial_no == "No" and self.serial_no_series:
|
if self.has_serial_no == 0 and self.serial_no_series:
|
||||||
self.serial_no_series = None
|
self.serial_no_series = None
|
||||||
|
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ class Item(WebsiteGenerator):
|
|||||||
vals = frappe.db.get_value("Item", self.name,
|
vals = frappe.db.get_value("Item", self.name,
|
||||||
["has_serial_no", "is_stock_item", "valuation_method", "has_batch_no"], as_dict=True)
|
["has_serial_no", "is_stock_item", "valuation_method", "has_batch_no"], as_dict=True)
|
||||||
|
|
||||||
if vals and ((self.is_stock_item == "No" and vals.is_stock_item == "Yes") or
|
if vals and ((self.is_stock_item == 0 and vals.is_stock_item == 1) or
|
||||||
vals.has_serial_no != self.has_serial_no or
|
vals.has_serial_no != self.has_serial_no or
|
||||||
vals.has_batch_no != self.has_batch_no or
|
vals.has_batch_no != self.has_batch_no or
|
||||||
cstr(vals.valuation_method) != cstr(self.valuation_method)):
|
cstr(vals.valuation_method) != cstr(self.valuation_method)):
|
||||||
@ -313,11 +313,11 @@ class Item(WebsiteGenerator):
|
|||||||
def update_item_desc(self):
|
def update_item_desc(self):
|
||||||
if frappe.db.get_value('BOM',self.name, 'description') != self.description:
|
if frappe.db.get_value('BOM',self.name, 'description') != self.description:
|
||||||
frappe.db.sql("""update `tabBOM` set description = %s where item = %s and docstatus < 2""",(self.description, self.name))
|
frappe.db.sql("""update `tabBOM` set description = %s where item = %s and docstatus < 2""",(self.description, self.name))
|
||||||
frappe.db.sql("""update `tabBOM Item` set description = %s where
|
frappe.db.sql("""update `tabBOM Item` set description = %s where
|
||||||
item_code = %s and docstatus < 2""",(self.description, self.name))
|
item_code = %s and docstatus < 2""",(self.description, self.name))
|
||||||
frappe.db.sql("""update `tabBOM Explosion Item` set description = %s where
|
frappe.db.sql("""update `tabBOM Explosion Item` set description = %s where
|
||||||
item_code = %s and docstatus < 2""",(self.description, self.name))
|
item_code = %s and docstatus < 2""",(self.description, self.name))
|
||||||
|
|
||||||
def update_variants(self):
|
def update_variants(self):
|
||||||
if self.has_variants:
|
if self.has_variants:
|
||||||
updated = []
|
updated = []
|
||||||
@ -327,7 +327,7 @@ class Item(WebsiteGenerator):
|
|||||||
updated.append(d.item_code)
|
updated.append(d.item_code)
|
||||||
if updated:
|
if updated:
|
||||||
frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
|
frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
|
||||||
|
|
||||||
def validate_has_variants(self):
|
def validate_has_variants(self):
|
||||||
if not self.has_variants and frappe.db.get_value("Item", self.name, "has_variants"):
|
if not self.has_variants and frappe.db.get_value("Item", self.name, "has_variants"):
|
||||||
if frappe.db.exists("Item", {"variant_of": self.name}):
|
if frappe.db.exists("Item", {"variant_of": self.name}):
|
||||||
@ -336,11 +336,11 @@ class Item(WebsiteGenerator):
|
|||||||
def validate_stock_for_template_must_be_zero(self):
|
def validate_stock_for_template_must_be_zero(self):
|
||||||
if self.has_variants:
|
if self.has_variants:
|
||||||
stock_in = frappe.db.sql_list("""select warehouse from tabBin
|
stock_in = frappe.db.sql_list("""select warehouse from tabBin
|
||||||
where item_code=%s and (ifnull(actual_qty, 0) > 0 or ifnull(ordered_qty, 0) > 0
|
where item_code=%s and (ifnull(actual_qty, 0) > 0 or ifnull(ordered_qty, 0) > 0
|
||||||
or ifnull(reserved_qty, 0) > 0 or ifnull(indented_qty, 0) > 0 or ifnull(planned_qty, 0) > 0)""", self.name)
|
or ifnull(reserved_qty, 0) > 0 or ifnull(indented_qty, 0) > 0 or ifnull(planned_qty, 0) > 0)""", self.name)
|
||||||
if stock_in:
|
if stock_in:
|
||||||
frappe.throw(_("Item Template cannot have stock or Open Sales/Purchase/Production Orders."), ItemTemplateCannotHaveStock)
|
frappe.throw(_("Item Template cannot have stock or Open Sales/Purchase/Production Orders."), ItemTemplateCannotHaveStock)
|
||||||
|
|
||||||
def validate_end_of_life(item_code, end_of_life=None, verbose=1):
|
def validate_end_of_life(item_code, end_of_life=None, verbose=1):
|
||||||
if not end_of_life:
|
if not end_of_life:
|
||||||
end_of_life = frappe.db.get_value("Item", item_code, "end_of_life")
|
end_of_life = frappe.db.get_value("Item", item_code, "end_of_life")
|
||||||
@ -353,7 +353,7 @@ def validate_is_stock_item(item_code, is_stock_item=None, verbose=1):
|
|||||||
if not is_stock_item:
|
if not is_stock_item:
|
||||||
is_stock_item = frappe.db.get_value("Item", item_code, "is_stock_item")
|
is_stock_item = frappe.db.get_value("Item", item_code, "is_stock_item")
|
||||||
|
|
||||||
if is_stock_item != "Yes":
|
if is_stock_item != 1:
|
||||||
msg = _("Item {0} is not a stock Item").format(item_code)
|
msg = _("Item {0} is not a stock Item").format(item_code)
|
||||||
|
|
||||||
_msgprint(msg, verbose)
|
_msgprint(msg, verbose)
|
||||||
@ -445,4 +445,3 @@ def invalidate_cache_for_item(doc):
|
|||||||
|
|
||||||
if doc.get("old_item_group") and doc.get("old_item_group") != doc.item_group:
|
if doc.get("old_item_group") and doc.get("old_item_group") != doc.item_group:
|
||||||
invalidate_cache_for(doc, doc.old_item_group)
|
invalidate_cache_for(doc, doc.old_item_group)
|
||||||
|
|
||||||
|
|||||||
@ -21,16 +21,16 @@ class TestItem(unittest.TestCase):
|
|||||||
else:
|
else:
|
||||||
item = frappe.get_doc("Item", item_code)
|
item = frappe.get_doc("Item", item_code)
|
||||||
return item
|
return item
|
||||||
|
|
||||||
def test_template_cannot_have_stock(self):
|
def test_template_cannot_have_stock(self):
|
||||||
item = self.get_item(10)
|
item = self.get_item(10)
|
||||||
se = make_stock_entry(item_code=item.name, target="Stores - _TC", qty=1, incoming_rate=1)
|
make_stock_entry(item_code=item.name, target="Stores - _TC", qty=1, incoming_rate=1)
|
||||||
item.has_variants = 1
|
item.has_variants = 1
|
||||||
self.assertRaises(ItemTemplateCannotHaveStock, item.save)
|
self.assertRaises(ItemTemplateCannotHaveStock, item.save)
|
||||||
|
|
||||||
def test_default_warehouse(self):
|
def test_default_warehouse(self):
|
||||||
item = frappe.copy_doc(test_records[0])
|
item = frappe.copy_doc(test_records[0])
|
||||||
item.is_stock_item = "Yes"
|
item.is_stock_item = 1
|
||||||
item.default_warehouse = None
|
item.default_warehouse = None
|
||||||
self.assertRaises(WarehouseNotSet, item.insert)
|
self.assertRaises(WarehouseNotSet, item.insert)
|
||||||
|
|
||||||
|
|||||||
@ -5,17 +5,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Item",
|
"item_code": "_Test Item",
|
||||||
"item_group": "_Test Item Group",
|
"item_group": "_Test Item Group",
|
||||||
"item_name": "_Test Item",
|
"item_name": "_Test Item",
|
||||||
@ -38,17 +38,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Item 2",
|
"item_code": "_Test Item 2",
|
||||||
"item_group": "_Test Item Group",
|
"item_group": "_Test Item Group",
|
||||||
"item_name": "_Test Item 2",
|
"item_name": "_Test Item 2",
|
||||||
@ -62,17 +62,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Item Home Desktop 100",
|
"item_code": "_Test Item Home Desktop 100",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Item Home Desktop 100",
|
"item_name": "_Test Item Home Desktop 100",
|
||||||
@ -92,17 +92,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Item Home Desktop 200",
|
"item_code": "_Test Item Home Desktop 200",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Item Home Desktop 200",
|
"item_name": "_Test Item Home Desktop 200",
|
||||||
@ -113,17 +113,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "No",
|
"is_stock_item": 0,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Product Bundle Item",
|
"item_code": "_Test Product Bundle Item",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Product Bundle Item",
|
"item_name": "_Test Product Bundle Item",
|
||||||
@ -135,17 +135,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "Yes",
|
"is_pro_applicable": 1,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "Yes",
|
"is_sub_contracted_item": 1,
|
||||||
"item_code": "_Test FG Item",
|
"item_code": "_Test FG Item",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test FG Item",
|
"item_name": "_Test FG Item",
|
||||||
@ -154,16 +154,16 @@
|
|||||||
{
|
{
|
||||||
"description": "_Test Non Stock Item 7",
|
"description": "_Test Non Stock Item 7",
|
||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "No",
|
"is_stock_item": 0,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Non Stock Item",
|
"item_code": "_Test Non Stock Item",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Non Stock Item",
|
"item_name": "_Test Non Stock Item",
|
||||||
@ -173,16 +173,16 @@
|
|||||||
"default_warehouse": "_Test Warehouse - _TC",
|
"default_warehouse": "_Test Warehouse - _TC",
|
||||||
"description": "_Test Serialized Item 8",
|
"description": "_Test Serialized Item 8",
|
||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "Yes",
|
"has_serial_no": 1,
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Serialized Item",
|
"item_code": "_Test Serialized Item",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Serialized Item",
|
"item_name": "_Test Serialized Item",
|
||||||
@ -192,16 +192,16 @@
|
|||||||
"default_warehouse": "_Test Warehouse - _TC",
|
"default_warehouse": "_Test Warehouse - _TC",
|
||||||
"description": "_Test Serialized Item 9",
|
"description": "_Test Serialized Item 9",
|
||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "Yes",
|
"has_serial_no": 1,
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "No",
|
"is_pro_applicable": 0,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Serialized Item With Series",
|
"item_code": "_Test Serialized Item With Series",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Serialized Item With Series",
|
"item_name": "_Test Serialized Item With Series",
|
||||||
@ -214,16 +214,16 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "Yes",
|
"is_pro_applicable": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "No",
|
"is_sub_contracted_item": 0,
|
||||||
"item_code": "_Test Item Home Desktop Manufactured",
|
"item_code": "_Test Item Home Desktop Manufactured",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Item Home Desktop Manufactured",
|
"item_name": "_Test Item Home Desktop Manufactured",
|
||||||
@ -235,17 +235,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "Yes",
|
"is_pro_applicable": 1,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "Yes",
|
"is_sub_contracted_item": 1,
|
||||||
"item_code": "_Test FG Item 2",
|
"item_code": "_Test FG Item 2",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test FG Item 2",
|
"item_name": "_Test FG Item 2",
|
||||||
@ -257,17 +257,17 @@
|
|||||||
"doctype": "Item",
|
"doctype": "Item",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
||||||
"cost_center": "_Test Cost Center - _TC",
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
"has_batch_no": "No",
|
"has_batch_no": 0,
|
||||||
"has_serial_no": "No",
|
"has_serial_no": 0,
|
||||||
"income_account": "Sales - _TC",
|
"income_account": "Sales - _TC",
|
||||||
"inspection_required": "No",
|
"inspection_required": 0,
|
||||||
"is_asset_item": "No",
|
"is_asset_item": 0,
|
||||||
"is_pro_applicable": "Yes",
|
"is_pro_applicable": 1,
|
||||||
"is_purchase_item": "Yes",
|
"is_purchase_item": 1,
|
||||||
"is_sales_item": "Yes",
|
"is_sales_item": 1,
|
||||||
"is_service_item": "No",
|
"is_service_item": 0,
|
||||||
"is_stock_item": "Yes",
|
"is_stock_item": 1,
|
||||||
"is_sub_contracted_item": "Yes",
|
"is_sub_contracted_item": 1,
|
||||||
"item_code": "_Test Variant Item",
|
"item_code": "_Test Variant Item",
|
||||||
"item_group": "_Test Item Group Desktops",
|
"item_group": "_Test Item Group Desktops",
|
||||||
"item_name": "_Test Variant Item",
|
"item_name": "_Test Variant Item",
|
||||||
|
|||||||
@ -1,157 +1,158 @@
|
|||||||
{
|
{
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"autoname": "ITEM-PRICE-.#####",
|
"autoname": "ITEM-PRICE-.#####",
|
||||||
"creation": "2013-05-02 16:29:48",
|
"creation": "2013-05-02 16:29:48",
|
||||||
"description": "Multiple Item prices.",
|
"description": "Multiple Item prices.",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Master",
|
"document_type": "Master",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "price_list_details",
|
"fieldname": "price_list_details",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Price List",
|
"label": "Price List",
|
||||||
"options": "icon-tags",
|
"options": "icon-tags",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "price_list",
|
"fieldname": "price_list",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Price List",
|
"label": "Price List",
|
||||||
"options": "Price List",
|
"options": "Price List",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "buying",
|
"fieldname": "buying",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Buying",
|
"label": "Buying",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "selling",
|
"fieldname": "selling",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Selling",
|
"label": "Selling",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "item_details",
|
"fieldname": "item_details",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "",
|
"label": "",
|
||||||
"options": "icon-tag",
|
"options": "icon-tag",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "item_code",
|
"fieldname": "item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"in_list_view": 0,
|
"in_list_view": 0,
|
||||||
"label": "Item Code",
|
"label": "Item Code",
|
||||||
"oldfieldname": "price_list_name",
|
"oldfieldname": "price_list_name",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 1
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "price_list_rate",
|
"fieldname": "price_list_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Rate",
|
"label": "Rate",
|
||||||
"oldfieldname": "ref_rate",
|
"oldfieldname": "ref_rate",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "currency",
|
"options": "currency",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0
|
"search_index": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "currency",
|
"fieldname": "currency",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Currency",
|
"in_list_view": 1,
|
||||||
"options": "Currency",
|
"label": "Currency",
|
||||||
"permlevel": 0,
|
"options": "Currency",
|
||||||
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col_br_1",
|
"fieldname": "col_br_1",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "item_name",
|
"fieldname": "item_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Item Name",
|
"label": "Item Name",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "item_description",
|
"fieldname": "item_description",
|
||||||
"fieldtype": "Text",
|
"fieldtype": "Text",
|
||||||
"label": "Item Description",
|
"label": "Item Description",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "section_break_12",
|
"fieldname": "section_break_12",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "bulk_import_help",
|
"fieldname": "bulk_import_help",
|
||||||
"fieldtype": "HTML",
|
"fieldtype": "HTML",
|
||||||
"label": "Bulk Import Help",
|
"label": "Bulk Import Help",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-flag",
|
"icon": "icon-flag",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"in_create": 0,
|
"in_create": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"modified": "2015-05-26 03:15:02.324161",
|
"modified": "2015-07-29 14:53:58.851413",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item Price",
|
"name": "Item Price",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Sales Master Manager",
|
"role": "Sales Master Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cancel": 0,
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "Purchase Master Manager",
|
"role": "Purchase Master Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"title_field": "item_code"
|
"title_field": "item_code"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class LandedCostVoucher(Document):
|
|||||||
pr_items = frappe.db.sql("""select pr_item.item_code, pr_item.description,
|
pr_items = frappe.db.sql("""select pr_item.item_code, pr_item.description,
|
||||||
pr_item.qty, pr_item.base_rate, pr_item.base_amount, pr_item.name
|
pr_item.qty, pr_item.base_rate, pr_item.base_amount, pr_item.name
|
||||||
from `tabPurchase Receipt Item` pr_item where parent = %s
|
from `tabPurchase Receipt Item` pr_item where parent = %s
|
||||||
and exists(select name from tabItem where name = pr_item.item_code and is_stock_item = 'Yes')""",
|
and exists(select name from tabItem where name = pr_item.item_code and is_stock_item = 1)""",
|
||||||
pr.purchase_receipt, as_dict=True)
|
pr.purchase_receipt, as_dict=True)
|
||||||
|
|
||||||
for d in pr_items:
|
for d in pr_items:
|
||||||
@ -69,7 +69,7 @@ class LandedCostVoucher(Document):
|
|||||||
def set_applicable_charges_for_item(self):
|
def set_applicable_charges_for_item(self):
|
||||||
based_on = self.distribute_charges_based_on.lower()
|
based_on = self.distribute_charges_based_on.lower()
|
||||||
total = sum([flt(d.get(based_on)) for d in self.get("items")])
|
total = sum([flt(d.get(based_on)) for d in self.get("items")])
|
||||||
|
|
||||||
if not total:
|
if not total:
|
||||||
frappe.throw(_("Total {0} for all items is zero, may you should change 'Distribute Charges Based On'").format(based_on))
|
frappe.throw(_("Total {0} for all items is zero, may you should change 'Distribute Charges Based On'").format(based_on))
|
||||||
|
|
||||||
|
|||||||
@ -152,7 +152,7 @@ class MaterialRequest(BuyingController):
|
|||||||
item_wh_list = []
|
item_wh_list = []
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if (not mr_item_rows or d.name in mr_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
|
if (not mr_item_rows or d.name in mr_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
|
||||||
and frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" and d.warehouse:
|
and frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and d.warehouse:
|
||||||
item_wh_list.append([d.item_code, d.warehouse])
|
item_wh_list.append([d.item_code, d.warehouse])
|
||||||
|
|
||||||
for item_code, warehouse in item_wh_list:
|
for item_code, warehouse in item_wh_list:
|
||||||
|
|||||||
@ -29,32 +29,37 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
|||||||
refresh: function() {
|
refresh: function() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
if(this.frm.doc.docstatus == 1) {
|
this.show_stock_ledger();
|
||||||
if(this.frm.doc.__onload && !this.frm.doc.__onload.billing_complete) {
|
if (cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
|
||||||
cur_frm.add_custom_button(__('Make Purchase Invoice'), this.make_purchase_invoice);
|
this.show_general_ledger();
|
||||||
|
}
|
||||||
|
if(!this.frm.doc.is_return) {
|
||||||
|
if(this.frm.doc.docstatus==0) {
|
||||||
|
cur_frm.add_custom_button(__('From Purchase Order'),
|
||||||
|
function() {
|
||||||
|
frappe.model.map_current_doc({
|
||||||
|
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
|
||||||
|
source_doctype: "Purchase Order",
|
||||||
|
get_query_filters: {
|
||||||
|
supplier: cur_frm.doc.supplier || undefined,
|
||||||
|
docstatus: 1,
|
||||||
|
status: ["!=", "Stopped"],
|
||||||
|
per_received: ["<", 99.99],
|
||||||
|
company: cur_frm.doc.company
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.add_custom_button(__('Make Purchase Return'), this.make_purchase_return);
|
if(this.frm.doc.docstatus == 1) {
|
||||||
|
if(this.frm.doc.__onload && !this.frm.doc.__onload.billing_complete) {
|
||||||
this.show_stock_ledger();
|
cur_frm.add_custom_button(__('Make Purchase Invoice'), this.make_purchase_invoice);
|
||||||
this.show_general_ledger();
|
}
|
||||||
} else {
|
|
||||||
cur_frm.add_custom_button(__('From Purchase Order'),
|
cur_frm.add_custom_button(__('Make Purchase Return'), this.make_purchase_return);
|
||||||
function() {
|
}
|
||||||
frappe.model.map_current_doc({
|
|
||||||
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
|
|
||||||
source_doctype: "Purchase Order",
|
|
||||||
get_query_filters: {
|
|
||||||
supplier: cur_frm.doc.supplier || undefined,
|
|
||||||
docstatus: 1,
|
|
||||||
status: ["!=", "Stopped"],
|
|
||||||
per_received: ["<", 99.99],
|
|
||||||
company: cur_frm.doc.company
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
|
this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted==="Yes");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -198,10 +198,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
|
|
||||||
def validate_inspection(self):
|
def validate_inspection(self):
|
||||||
for d in self.get('items'): #Enter inspection date for all items that require inspection
|
for d in self.get('items'): #Enter inspection date for all items that require inspection
|
||||||
ins_reqd = frappe.db.sql("select inspection_required from `tabItem` where name = %s",
|
if frappe.db.get_value("Item", d.item_code, "inspection_required") and not d.qa_no:
|
||||||
(d.item_code,), as_dict = 1)
|
|
||||||
ins_reqd = ins_reqd and ins_reqd[0]['inspection_required'] or 'No'
|
|
||||||
if ins_reqd == 'Yes' and not d.qa_no:
|
|
||||||
frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code))
|
frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code))
|
||||||
if self.docstatus==1:
|
if self.docstatus==1:
|
||||||
raise frappe.ValidationError
|
raise frappe.ValidationError
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
frappe.listview_settings['Purchase Receipt'] = {
|
frappe.listview_settings['Purchase Receipt'] = {
|
||||||
add_fields: ["supplier", "supplier_name", "base_grand_total", "is_subcontracted",
|
add_fields: ["supplier", "supplier_name", "base_grand_total", "is_subcontracted",
|
||||||
"transporter_name"]
|
"transporter_name", "is_return"],
|
||||||
|
get_indicator: function(doc) {
|
||||||
|
if(cint(doc.is_return)==1) {
|
||||||
|
return [__("Return"), "darkgrey", "is_return,=,1"];
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,7 +11,7 @@ cur_frm.add_fetch("item_code", "brand", "brand")
|
|||||||
|
|
||||||
cur_frm.cscript.onload = function() {
|
cur_frm.cscript.onload = function() {
|
||||||
cur_frm.set_query("item_code", function() {
|
cur_frm.set_query("item_code", function() {
|
||||||
return erpnext.queries.item({"is_stock_item": "Yes", "has_serial_no": "Yes"})
|
return erpnext.queries.item({"is_stock_item": 1, "has_serial_no": 1})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,7 @@ class SerialNo(StockController):
|
|||||||
Validate whether serial no is required for this item
|
Validate whether serial no is required for this item
|
||||||
"""
|
"""
|
||||||
item = frappe.get_doc("Item", self.item_code)
|
item = frappe.get_doc("Item", self.item_code)
|
||||||
if item.has_serial_no!="Yes":
|
if item.has_serial_no!=1:
|
||||||
frappe.throw(_("Item {0} is not setup for Serial Nos. Check Item master").format(self.item_code))
|
frappe.throw(_("Item {0} is not setup for Serial Nos. Check Item master").format(self.item_code))
|
||||||
|
|
||||||
self.item_group = item.item_group
|
self.item_group = item.item_group
|
||||||
@ -198,7 +198,7 @@ def process_serial_no(sle):
|
|||||||
update_serial_nos(sle, item_det)
|
update_serial_nos(sle, item_det)
|
||||||
|
|
||||||
def validate_serial_no(sle, item_det):
|
def validate_serial_no(sle, item_det):
|
||||||
if item_det.has_serial_no=="No":
|
if item_det.has_serial_no==0:
|
||||||
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)
|
||||||
@ -246,7 +246,7 @@ def validate_serial_no(sle, item_det):
|
|||||||
|
|
||||||
def update_serial_nos(sle, item_det):
|
def update_serial_nos(sle, item_det):
|
||||||
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
|
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
|
||||||
and item_det.has_serial_no == "Yes" and item_det.serial_no_series:
|
and item_det.has_serial_no == 1 and item_det.serial_no_series:
|
||||||
from frappe.model.naming import make_autoname
|
from frappe.model.naming import make_autoname
|
||||||
serial_nos = []
|
serial_nos = []
|
||||||
for i in xrange(cint(sle.actual_qty)):
|
for i in xrange(cint(sle.actual_qty)):
|
||||||
|
|||||||
@ -7,7 +7,7 @@ frappe.provide("erpnext.stock");
|
|||||||
erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||||
setup: function() {
|
setup: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
this.frm.fields_dict.bom_no.get_query = function() {
|
this.frm.fields_dict.bom_no.get_query = function() {
|
||||||
return {
|
return {
|
||||||
filters:{ 'docstatus': 1 }
|
filters:{ 'docstatus': 1 }
|
||||||
@ -15,7 +15,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.frm.fields_dict.items.grid.get_field('item_code').get_query = function() {
|
this.frm.fields_dict.items.grid.get_field('item_code').get_query = function() {
|
||||||
return erpnext.queries.item({is_stock_item: "Yes"});
|
return erpnext.queries.item({is_stock_item: 1});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.frm.set_query("purchase_order", function() {
|
this.frm.set_query("purchase_order", function() {
|
||||||
@ -57,7 +57,9 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
|||||||
this.toggle_related_fields(this.frm.doc);
|
this.toggle_related_fields(this.frm.doc);
|
||||||
this.toggle_enable_bom();
|
this.toggle_enable_bom();
|
||||||
this.show_stock_ledger();
|
this.show_stock_ledger();
|
||||||
this.show_general_ledger();
|
if (cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
|
||||||
|
this.show_general_ledger();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
on_submit: function() {
|
on_submit: function() {
|
||||||
@ -252,13 +254,13 @@ cur_frm.fields_dict['items'].grid.get_field('batch_no').get_query = function(doc
|
|||||||
var filters = {
|
var filters = {
|
||||||
'item_code': item.item_code,
|
'item_code': item.item_code,
|
||||||
'posting_date': me.frm.doc.posting_date || nowdate()
|
'posting_date': me.frm.doc.posting_date || nowdate()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var filters = {
|
var filters = {
|
||||||
'item_code': item.item_code
|
'item_code': item.item_code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(item.s_warehouse) filters["warehouse"] = item.s_warehouse
|
if(item.s_warehouse) filters["warehouse"] = item.s_warehouse
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -5,10 +5,9 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import cstr, cint, flt, comma_or, get_datetime, getdate
|
from frappe.utils import cstr, cint, flt, comma_or, getdate
|
||||||
from erpnext.stock.utils import get_incoming_rate
|
from erpnext.stock.utils import get_incoming_rate
|
||||||
from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError
|
from erpnext.stock.stock_ledger import get_previous_sle, NegativeStockError
|
||||||
from erpnext.controllers.queries import get_match_cond
|
|
||||||
from erpnext.stock.get_item_details import get_available_qty, get_default_cost_center, get_conversion_factor
|
from erpnext.stock.get_item_details import get_available_qty, get_default_cost_center, get_conversion_factor
|
||||||
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
||||||
from erpnext.accounts.utils import validate_fiscal_year
|
from erpnext.accounts.utils import validate_fiscal_year
|
||||||
@ -354,12 +353,12 @@ class StockEntry(StockController):
|
|||||||
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty):
|
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty):
|
||||||
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
|
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
|
||||||
format(d.idx, d.transfer_qty, self.fg_completed_qty))
|
format(d.idx, d.transfer_qty, self.fg_completed_qty))
|
||||||
|
|
||||||
if self.production_order and self.purpose == "Manufacture" and d.t_warehouse:
|
if self.production_order and self.purpose == "Manufacture" and d.t_warehouse:
|
||||||
items_with_target_warehouse.append(d.item_code)
|
items_with_target_warehouse.append(d.item_code)
|
||||||
|
|
||||||
if self.production_order and self.purpose == "Manufacture":
|
if self.production_order and self.purpose == "Manufacture":
|
||||||
production_item = frappe.db.get_value("Production Order",
|
production_item = frappe.db.get_value("Production Order",
|
||||||
self.production_order, "production_item")
|
self.production_order, "production_item")
|
||||||
if production_item not in items_with_target_warehouse:
|
if production_item not in items_with_target_warehouse:
|
||||||
frappe.throw(_("Finished Item {0} must be entered for Manufacture type entry")
|
frappe.throw(_("Finished Item {0} must be entered for Manufacture type entry")
|
||||||
@ -427,7 +426,7 @@ class StockEntry(StockController):
|
|||||||
(args.get('item_code')), as_dict = 1)
|
(args.get('item_code')), as_dict = 1)
|
||||||
if not item:
|
if not item:
|
||||||
frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get("item_code")))
|
frappe.throw(_("Item {0} is not active or end of life has been reached").format(args.get("item_code")))
|
||||||
|
|
||||||
item = item[0]
|
item = item[0]
|
||||||
|
|
||||||
ret = {
|
ret = {
|
||||||
@ -436,8 +435,7 @@ class StockEntry(StockController):
|
|||||||
'description' : item.description,
|
'description' : item.description,
|
||||||
'image' : item.image,
|
'image' : item.image,
|
||||||
'item_name' : item.item_name,
|
'item_name' : item.item_name,
|
||||||
'expense_account' : args.get("expense_account") \
|
'expense_account' : args.get("expense_account"),
|
||||||
or frappe.db.get_value("Company", args.get("company"), "stock_adjustment_account"),
|
|
||||||
'cost_center' : get_default_cost_center(args, item),
|
'cost_center' : get_default_cost_center(args, item),
|
||||||
'qty' : 0,
|
'qty' : 0,
|
||||||
'transfer_qty' : 0,
|
'transfer_qty' : 0,
|
||||||
@ -446,6 +444,15 @@ class StockEntry(StockController):
|
|||||||
'actual_qty' : 0,
|
'actual_qty' : 0,
|
||||||
'incoming_rate' : 0
|
'incoming_rate' : 0
|
||||||
}
|
}
|
||||||
|
for d in [["Account", "expense_account", "default_expense_account"],
|
||||||
|
["Cost Center", "cost_center", "cost_center"]]:
|
||||||
|
company = frappe.db.get_value(d[0], ret.get(d[1]), "company")
|
||||||
|
if not ret[d[1]] or (company and self.company != company):
|
||||||
|
ret[d[1]] = frappe.db.get_value("Company", self.company, d[2]) if d[2] else None
|
||||||
|
|
||||||
|
if not ret["expense_account"]:
|
||||||
|
ret["expense_account"] = frappe.db.get_value("Company", self.company, "stock_adjustment_account")
|
||||||
|
|
||||||
stock_and_rate = args.get('warehouse') and self.get_warehouse_details(args) or {}
|
stock_and_rate = args.get('warehouse') and self.get_warehouse_details(args) or {}
|
||||||
ret.update(stock_and_rate)
|
ret.update(stock_and_rate)
|
||||||
return ret
|
return ret
|
||||||
@ -553,7 +560,7 @@ class StockEntry(StockController):
|
|||||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||||
|
|
||||||
# item dict = { item_code: {qty, description, stock_uom} }
|
# item dict = { item_code: {qty, description, stock_uom} }
|
||||||
item_dict = get_bom_items_as_dict(self.bom_no, qty=qty, fetch_exploded = self.use_multi_level_bom)
|
item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=qty, fetch_exploded = self.use_multi_level_bom)
|
||||||
|
|
||||||
for item in item_dict.values():
|
for item in item_dict.values():
|
||||||
item.from_warehouse = self.from_warehouse or item.default_warehouse
|
item.from_warehouse = self.from_warehouse or item.default_warehouse
|
||||||
@ -642,7 +649,7 @@ class StockEntry(StockController):
|
|||||||
mreq_item.warehouse != (item.s_warehouse if self.purpose== "Material Issue" else item.t_warehouse):
|
mreq_item.warehouse != (item.s_warehouse if self.purpose== "Material Issue" else item.t_warehouse):
|
||||||
frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx),
|
frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx),
|
||||||
frappe.MappingMismatchError)
|
frappe.MappingMismatchError)
|
||||||
|
|
||||||
def validate_batch(self):
|
def validate_batch(self):
|
||||||
if self.purpose in ["Material Transfer for Manufacture", "Manufacture", "Repack", "Subcontract"]:
|
if self.purpose in ["Material Transfer for Manufacture", "Manufacture", "Repack", "Subcontract"]:
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
|
|||||||
@ -64,18 +64,18 @@ class StockLedgerEntry(Document):
|
|||||||
|
|
||||||
item_det = item_det[0]
|
item_det = item_det[0]
|
||||||
|
|
||||||
if item_det.is_stock_item != 'Yes':
|
if item_det.is_stock_item != 1:
|
||||||
frappe.throw(_("Item {0} must be a stock Item").format(self.item_code))
|
frappe.throw(_("Item {0} must be a stock Item").format(self.item_code))
|
||||||
|
|
||||||
# check if batch number is required
|
# check if batch number is required
|
||||||
if self.voucher_type != 'Stock Reconciliation':
|
if self.voucher_type != 'Stock Reconciliation':
|
||||||
if item_det.has_batch_no =='Yes':
|
if item_det.has_batch_no ==1:
|
||||||
if not self.batch_no:
|
if not self.batch_no:
|
||||||
frappe.throw(_("Batch number is mandatory for Item {0}").format(self.item_code))
|
frappe.throw(_("Batch number is mandatory for Item {0}").format(self.item_code))
|
||||||
elif not frappe.db.get_value("Batch",{"item": self.item_code, "name": self.batch_no}):
|
elif not frappe.db.get_value("Batch",{"item": self.item_code, "name": self.batch_no}):
|
||||||
frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, self.item_code))
|
frappe.throw(_("{0} is not a valid Batch Number for Item {1}").format(self.batch_no, self.item_code))
|
||||||
|
|
||||||
elif item_det.has_batch_no =='No' and self.batch_no:
|
elif item_det.has_batch_no ==0 and self.batch_no:
|
||||||
frappe.throw(_("The Item {0} cannot have Batch").format(self.item_code))
|
frappe.throw(_("The Item {0} cannot have Batch").format(self.item_code))
|
||||||
|
|
||||||
if item_det.has_variants:
|
if item_det.has_variants:
|
||||||
|
|||||||
@ -83,7 +83,9 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
|||||||
refresh: function() {
|
refresh: function() {
|
||||||
if(this.frm.doc.docstatus==1) {
|
if(this.frm.doc.docstatus==1) {
|
||||||
this.show_stock_ledger();
|
this.show_stock_ledger();
|
||||||
this.show_general_ledger();
|
if (cint(frappe.defaults.get_default("auto_accounting_for_stock"))) {
|
||||||
|
this.show_general_ledger();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -134,12 +134,12 @@ class StockReconciliation(StockController):
|
|||||||
validate_is_stock_item(item_code, item.is_stock_item, verbose=0)
|
validate_is_stock_item(item_code, item.is_stock_item, verbose=0)
|
||||||
|
|
||||||
# item should not be serialized
|
# item should not be serialized
|
||||||
if item.has_serial_no == "Yes":
|
if item.has_serial_no == 1:
|
||||||
raise frappe.ValidationError, _("Serialized Item {0} cannot be updated \
|
raise frappe.ValidationError, _("Serialized Item {0} cannot be updated \
|
||||||
using Stock Reconciliation").format(item_code)
|
using Stock Reconciliation").format(item_code)
|
||||||
|
|
||||||
# item managed batch-wise not allowed
|
# item managed batch-wise not allowed
|
||||||
if item.has_batch_no == "Yes":
|
if item.has_batch_no == 1:
|
||||||
raise frappe.ValidationError, _("Item: {0} managed batch-wise, can not be reconciled using \
|
raise frappe.ValidationError, _("Item: {0} managed batch-wise, can not be reconciled using \
|
||||||
Stock Reconciliation, instead use Stock Entry").format(item_code)
|
Stock Reconciliation, instead use Stock Entry").format(item_code)
|
||||||
|
|
||||||
@ -163,16 +163,17 @@ class StockReconciliation(StockController):
|
|||||||
})
|
})
|
||||||
if previous_sle:
|
if previous_sle:
|
||||||
if row.qty in ("", None):
|
if row.qty in ("", None):
|
||||||
row.qty = previous_sle.get("qty_after_transaction")
|
row.qty = previous_sle.get("qty_after_transaction", 0)
|
||||||
|
|
||||||
if row.valuation_rate in ("", None):
|
if row.valuation_rate in ("", None):
|
||||||
row.valuation_rate = previous_sle.get("valuation_rate")
|
row.valuation_rate = previous_sle.get("valuation_rate", 0)
|
||||||
|
|
||||||
if row.qty and not row.valuation_rate:
|
if row.qty and not row.valuation_rate:
|
||||||
frappe.throw(_("Valuation Rate required for Item {0}").format(row.item_code))
|
frappe.throw(_("Valuation Rate required for Item {0}").format(row.item_code))
|
||||||
|
|
||||||
if previous_sle and row.qty == previous_sle.get("qty_after_transaction") \
|
if ((previous_sle and row.qty == previous_sle.get("qty_after_transaction")
|
||||||
and row.valuation_rate == previous_sle.get("valuation_rate"):
|
and row.valuation_rate == previous_sle.get("valuation_rate"))
|
||||||
|
or (not previous_sle and not row.qty)):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.insert_entries(row)
|
self.insert_entries(row)
|
||||||
@ -242,7 +243,7 @@ class StockReconciliation(StockController):
|
|||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_items(warehouse, posting_date, posting_time):
|
def get_items(warehouse, posting_date, posting_time):
|
||||||
items = frappe.get_list("Item", fields=["name"], filters=
|
items = frappe.get_list("Item", fields=["name"], filters=
|
||||||
{"is_stock_item": "Yes", "has_serial_no": "No", "has_batch_no": "No"})
|
{"is_stock_item": 1, "has_serial_no": 0, "has_batch_no": 0})
|
||||||
for item in items:
|
for item in items:
|
||||||
item.item_code = item.name
|
item.item_code = item.name
|
||||||
item.warehouse = warehouse
|
item.warehouse = warehouse
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
$.extend(cur_frm.cscript, {
|
$.extend(cur_frm.cscript, {
|
||||||
onload: function() {
|
onload: function() {
|
||||||
cur_frm.set_query("item_code", function() {
|
cur_frm.set_query("item_code", function() {
|
||||||
return erpnext.queries.item({"is_stock_item": "Yes"});
|
return erpnext.queries.item({"is_stock_item": 1});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -146,7 +146,7 @@ class Warehouse(Document):
|
|||||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
||||||
|
|
||||||
for item in frappe.db.sql("""select distinct item_code from (
|
for item in frappe.db.sql("""select distinct item_code from (
|
||||||
select name as item_code from `tabItem` where ifnull(is_stock_item, 'Yes')='Yes'
|
select name as item_code from `tabItem` where is_stock_item=1
|
||||||
union
|
union
|
||||||
select distinct item_code from tabBin) a"""):
|
select distinct item_code from tabBin) a"""):
|
||||||
repost_stock(item[0], newdn)
|
repost_stock(item[0], newdn)
|
||||||
|
|||||||
@ -37,7 +37,6 @@ def get_item_details(args):
|
|||||||
item_doc = frappe.get_doc("Item", args.item_code)
|
item_doc = frappe.get_doc("Item", args.item_code)
|
||||||
item = item_doc
|
item = item_doc
|
||||||
|
|
||||||
|
|
||||||
validate_item_details(args, item)
|
validate_item_details(args, item)
|
||||||
|
|
||||||
out = get_basic_details(args, item)
|
out = get_basic_details(args, item)
|
||||||
@ -61,7 +60,7 @@ def get_item_details(args):
|
|||||||
out.update(get_pricing_rule_for_item(args))
|
out.update(get_pricing_rule_for_item(args))
|
||||||
|
|
||||||
if args.get("parenttype") in ("Sales Invoice", "Delivery Note"):
|
if args.get("parenttype") in ("Sales Invoice", "Delivery Note"):
|
||||||
if item_doc.has_serial_no == "Yes" and not args.serial_no:
|
if item_doc.has_serial_no == 1 and not args.serial_no:
|
||||||
out.serial_no = get_serial_nos_by_fifo(args, item_doc)
|
out.serial_no = get_serial_nos_by_fifo(args, item_doc)
|
||||||
|
|
||||||
if args.transaction_date and item.lead_time_days:
|
if args.transaction_date and item.lead_time_days:
|
||||||
@ -119,10 +118,10 @@ def validate_item_details(args, item):
|
|||||||
if args.transaction_type == "selling":
|
if args.transaction_type == "selling":
|
||||||
# validate if sales item or service item
|
# validate if sales item or service item
|
||||||
if args.get("order_type") == "Maintenance":
|
if args.get("order_type") == "Maintenance":
|
||||||
if item.is_service_item != "Yes":
|
if item.is_service_item != 1:
|
||||||
throw(_("Item {0} must be a Service Item.").format(item.name))
|
throw(_("Item {0} must be a Service Item.").format(item.name))
|
||||||
|
|
||||||
elif item.is_sales_item != "Yes":
|
elif item.is_sales_item != 1:
|
||||||
throw(_("Item {0} must be a Sales Item").format(item.name))
|
throw(_("Item {0} must be a Sales Item").format(item.name))
|
||||||
|
|
||||||
if cint(item.has_variants):
|
if cint(item.has_variants):
|
||||||
@ -130,10 +129,10 @@ def validate_item_details(args, item):
|
|||||||
|
|
||||||
elif args.transaction_type == "buying" and args.parenttype != "Material Request":
|
elif args.transaction_type == "buying" and args.parenttype != "Material Request":
|
||||||
# validate if purchase item or subcontracted item
|
# validate if purchase item or subcontracted item
|
||||||
if item.is_purchase_item != "Yes":
|
if item.is_purchase_item != 1:
|
||||||
throw(_("Item {0} must be a Purchase Item").format(item.name))
|
throw(_("Item {0} must be a Purchase Item").format(item.name))
|
||||||
|
|
||||||
if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != "Yes":
|
if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != 1:
|
||||||
throw(_("Item {0} must be a Sub-contracted Item").format(item.name))
|
throw(_("Item {0} must be a Sub-contracted Item").format(item.name))
|
||||||
|
|
||||||
def get_basic_details(args, item):
|
def get_basic_details(args, item):
|
||||||
@ -301,7 +300,7 @@ def get_serial_nos_by_fifo(args, item_doc):
|
|||||||
order by timestamp(purchase_date, purchase_time) asc limit %(qty)s""", {
|
order by timestamp(purchase_date, purchase_time) asc limit %(qty)s""", {
|
||||||
"item_code": args.item_code,
|
"item_code": args.item_code,
|
||||||
"warehouse": args.warehouse,
|
"warehouse": args.warehouse,
|
||||||
"qty": cint(args.qty)
|
"qty": abs(cint(args.qty))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def get_actual_batch_qty(batch_no,warehouse,item_code):
|
def get_actual_batch_qty(batch_no,warehouse,item_code):
|
||||||
@ -338,7 +337,7 @@ def get_batch_qty(batch_no,warehouse,item_code):
|
|||||||
actual_batch_qty = get_actual_batch_qty(batch_no,warehouse,item_code)
|
actual_batch_qty = get_actual_batch_qty(batch_no,warehouse,item_code)
|
||||||
if batch_no:
|
if batch_no:
|
||||||
return {'actual_batch_qty': actual_batch_qty}
|
return {'actual_batch_qty': actual_batch_qty}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def apply_price_list(args):
|
def apply_price_list(args):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -69,7 +69,7 @@ def get_item_warehouse_projected_qty():
|
|||||||
from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != ''
|
from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != ''
|
||||||
and exists (select name from `tabItem`
|
and exists (select name from `tabItem`
|
||||||
where `tabItem`.name = `tabBin`.item_code and
|
where `tabItem`.name = `tabBin`.item_code and
|
||||||
is_stock_item='Yes' and (is_purchase_item='Yes' or is_sub_contracted_item='Yes') and
|
is_stock_item=1 and (is_purchase_item=1 or is_sub_contracted_item=1) and
|
||||||
(ifnull(end_of_life, '0000-00-00')='0000-00-00' or end_of_life > %s))
|
(ifnull(end_of_life, '0000-00-00')='0000-00-00' or end_of_life > %s))
|
||||||
and exists (select name from `tabWarehouse`
|
and exists (select name from `tabWarehouse`
|
||||||
where `tabWarehouse`.name = `tabBin`.warehouse
|
where `tabWarehouse`.name = `tabBin`.warehouse
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"apply_user_permissions": 1,
|
"apply_user_permissions": 1,
|
||||||
"creation": "2013-08-20 15:08:10",
|
"creation": "2013-08-20 15:08:10",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Report",
|
"doctype": "Report",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_standard": "Yes",
|
"is_standard": "Yes",
|
||||||
"modified": "2014-06-03 07:18:17.128918",
|
"modified": "2014-06-03 07:18:17.128918",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Items To Be Requested",
|
"name": "Items To Be Requested",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"query": "SELECT\n tabBin.item_code as \"Item:Link/Item:120\",\n tabBin.warehouse as \"Warehouse:Link/Warehouse:120\",\n tabBin.actual_qty as \"Actual:Float:90\",\n tabBin.indented_qty as \"Requested:Float:90\",\n tabBin.reserved_qty as \"Reserved:Float:90\",\n tabBin.ordered_qty as \"Ordered:Float:90\",\n tabBin.projected_qty as \"Projected:Float:90\"\nFROM\n tabBin, tabItem\nWHERE\n tabBin.item_code = tabItem.name\n AND tabItem.is_purchase_item = \"Yes\"\n AND tabBin.projected_qty < 0\nORDER BY\n tabBin.projected_qty ASC",
|
"query": "SELECT\n tabBin.item_code as \"Item:Link/Item:120\",\n tabBin.warehouse as \"Warehouse:Link/Warehouse:120\",\n tabBin.actual_qty as \"Actual:Float:90\",\n tabBin.indented_qty as \"Requested:Float:90\",\n tabBin.reserved_qty as \"Reserved:Float:90\",\n tabBin.ordered_qty as \"Ordered:Float:90\",\n tabBin.projected_qty as \"Projected:Float:90\"\nFROM\n tabBin, tabItem\nWHERE\n tabBin.item_code = tabItem.name\n AND tabItem.is_purchase_item = 1\n AND tabBin.projected_qty < 0\nORDER BY\n tabBin.projected_qty ASC",
|
||||||
"ref_doctype": "Item",
|
"ref_doctype": "Item",
|
||||||
"report_name": "Items To Be Requested",
|
"report_name": "Items To Be Requested",
|
||||||
"report_type": "Query Report"
|
"report_type": "Query Report"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ def execute(filters=None):
|
|||||||
total_qty = total_amount = 0.0
|
total_qty = total_amount = 0.0
|
||||||
if consumed_details.get(item_code):
|
if consumed_details.get(item_code):
|
||||||
for cd in consumed_details.get(item_code):
|
for cd in consumed_details.get(item_code):
|
||||||
|
|
||||||
if (cd.voucher_no not in material_transfer_vouchers):
|
if (cd.voucher_no not in material_transfer_vouchers):
|
||||||
if cd.voucher_type=="Delivery Note":
|
if cd.voucher_type=="Delivery Note":
|
||||||
delivered_qty += abs(flt(cd.actual_qty))
|
delivered_qty += abs(flt(cd.actual_qty))
|
||||||
@ -40,7 +40,7 @@ def execute(filters=None):
|
|||||||
|
|
||||||
def get_columns(filters):
|
def get_columns(filters):
|
||||||
"""return columns based on filters"""
|
"""return columns based on filters"""
|
||||||
|
|
||||||
columns = [_("Item") + ":Link/Item:100"] + [_("Item Name") + "::100"] + \
|
columns = [_("Item") + ":Link/Item:100"] + [_("Item Name") + "::100"] + \
|
||||||
[_("Description") + "::150"] + [_("UOM") + ":Link/UOM:90"] + \
|
[_("Description") + "::150"] + [_("UOM") + ":Link/UOM:90"] + \
|
||||||
[_("Consumed Qty") + ":Float:110"] + [_("Consumed Amount") + ":Currency:130"] + \
|
[_("Consumed Qty") + ":Float:110"] + [_("Consumed Amount") + ":Currency:130"] + \
|
||||||
@ -64,10 +64,10 @@ def get_consumed_details(filters):
|
|||||||
conditions, values = get_conditions(filters)
|
conditions, values = get_conditions(filters)
|
||||||
consumed_details = {}
|
consumed_details = {}
|
||||||
|
|
||||||
for d in frappe.db.sql("""select sle.item_code, i.item_name, i.description,
|
for d in frappe.db.sql("""select sle.item_code, i.item_name, i.description,
|
||||||
i.stock_uom, sle.actual_qty, sle.stock_value_difference,
|
i.stock_uom, sle.actual_qty, sle.stock_value_difference,
|
||||||
sle.voucher_no, sle.voucher_type
|
sle.voucher_no, sle.voucher_type
|
||||||
from `tabStock Ledger Entry` sle, `tabItem` i
|
from `tabStock Ledger Entry` sle, `tabItem` i
|
||||||
where sle.item_code=i.name and sle.actual_qty < 0 %s""" % conditions, values, as_dict=1):
|
where sle.item_code=i.name and sle.actual_qty < 0 %s""" % conditions, values, as_dict=1):
|
||||||
consumed_details.setdefault(d.item_code, []).append(d)
|
consumed_details.setdefault(d.item_code, []).append(d)
|
||||||
|
|
||||||
@ -77,20 +77,20 @@ def get_suppliers_details(filters):
|
|||||||
item_supplier_map = {}
|
item_supplier_map = {}
|
||||||
supplier = filters.get('supplier')
|
supplier = filters.get('supplier')
|
||||||
|
|
||||||
for d in frappe.db.sql("""select pr.supplier, pri.item_code from
|
for d in frappe.db.sql("""select pr.supplier, pri.item_code from
|
||||||
`tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri
|
`tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri
|
||||||
where pr.name=pri.parent and pr.docstatus=1 and
|
where pr.name=pri.parent and pr.docstatus=1 and
|
||||||
pri.item_code=(select name from `tabItem` where
|
pri.item_code=(select name from `tabItem` where
|
||||||
ifnull(is_stock_item, 'Yes')='Yes' and name=pri.item_code)""", as_dict=1):
|
is_stock_item=1 and name=pri.item_code)""", as_dict=1):
|
||||||
item_supplier_map.setdefault(d.item_code, []).append(d.supplier)
|
item_supplier_map.setdefault(d.item_code, []).append(d.supplier)
|
||||||
|
|
||||||
if supplier:
|
if supplier:
|
||||||
for item_code, suppliers in item_supplier_map.items():
|
for item_code, suppliers in item_supplier_map.items():
|
||||||
if supplier not in suppliers:
|
if supplier not in suppliers:
|
||||||
del item_supplier_map[item_code]
|
del item_supplier_map[item_code]
|
||||||
|
|
||||||
return item_supplier_map
|
return item_supplier_map
|
||||||
|
|
||||||
def get_material_transfer_vouchers():
|
def get_material_transfer_vouchers():
|
||||||
return frappe.db.sql_list("""select name from `tabStock Entry` where
|
return frappe.db.sql_list("""select name from `tabStock Entry` where
|
||||||
purpose='Material Transfer' and docstatus=1""")
|
purpose='Material Transfer' and docstatus=1""")
|
||||||
|
|||||||
@ -81,7 +81,7 @@ def get_bin(item_code, warehouse):
|
|||||||
|
|
||||||
def update_bin(args, allow_negative_stock=False, via_landed_cost_voucher=False):
|
def update_bin(args, allow_negative_stock=False, via_landed_cost_voucher=False):
|
||||||
is_stock_item = frappe.db.get_value('Item', args.get("item_code"), 'is_stock_item')
|
is_stock_item = frappe.db.get_value('Item', args.get("item_code"), 'is_stock_item')
|
||||||
if is_stock_item == 'Yes':
|
if is_stock_item:
|
||||||
bin = get_bin(args.get("item_code"), args.get("warehouse"))
|
bin = get_bin(args.get("item_code"), args.get("warehouse"))
|
||||||
bin.update_stock(args, allow_negative_stock, via_landed_cost_voucher)
|
bin.update_stock(args, allow_negative_stock, via_landed_cost_voucher)
|
||||||
return bin
|
return bin
|
||||||
@ -173,4 +173,3 @@ def validate_warehouse_company(warehouse, company):
|
|||||||
if warehouse_company and warehouse_company != company:
|
if warehouse_company and warehouse_company != company:
|
||||||
frappe.throw(_("Warehouse {0} does not belong to company {1}").format(warehouse, company),
|
frappe.throw(_("Warehouse {0} does not belong to company {1}").format(warehouse, company),
|
||||||
InvalidWarehouseCompany)
|
InvalidWarehouseCompany)
|
||||||
|
|
||||||
|
|||||||
@ -102,7 +102,7 @@ cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
|
|||||||
|
|
||||||
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
|
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
|
||||||
return {
|
return {
|
||||||
filters:{ 'is_service_item': "Yes" }
|
filters:{ 'is_service_item': 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -77,7 +77,7 @@ cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
|
|||||||
|
|
||||||
cur_frm.fields_dict['purposes'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
|
cur_frm.fields_dict['purposes'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
|
||||||
return{
|
return{
|
||||||
filters:{ 'is_service_item': "Yes"}
|
filters:{ 'is_service_item': 1}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -222,6 +222,7 @@
|
|||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "customer",
|
||||||
"fieldname": "contact_info",
|
"fieldname": "contact_info",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Contact Info",
|
"label": "Contact Info",
|
||||||
@ -396,7 +397,7 @@
|
|||||||
"icon": "icon-bug",
|
"icon": "icon-bug",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 0,
|
"is_submittable": 0,
|
||||||
"modified": "2015-02-21 04:11:40.653543",
|
"modified": "2015-07-28 11:59:38.762393",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Support",
|
"module": "Support",
|
||||||
"name": "Warranty Claim",
|
"name": "Warranty Claim",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user