Merge branch 'schools' of https://github.com/neilLasrado/erpnext into neilLasrado-schools
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 20d39a8..5be0b69 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -35,25 +35,6 @@
'percent_join_field': 'purchase_order',
'overflow_type': 'billing'
}]
-
- self.prev_link_mapper = {
- "Purchase Order": {
- "fieldname": "purchase_order",
- "doctype": "Purchase Invoice Item",
- "filters": [
- ["Purchase Invoice Item", "parent", "=", self.name],
- ["Purchase Invoice Item", "purchase_order", "!=", ""]
- ]
- },
- "Purchase Receipt": {
- "fieldname": "purchase_receipt",
- "doctype": "Purchase Invoice Item",
- "filters": [
- ["Purchase Invoice Item", "parent", "=", self.name],
- ["Purchase Invoice Item", "purchase_receipt", "!=", ""]
- ]
- }
- }
def validate(self):
if not self.is_opening:
@@ -65,7 +46,7 @@
self.po_required()
self.pr_required()
self.validate_supplier_invoice()
-
+
# validate cash purchase
if (self.is_paid == 1):
@@ -96,7 +77,7 @@
def create_remarks(self):
if not self.remarks:
if self.bill_no and self.bill_date:
- self.remarks = _("Against Supplier Invoice {0} dated {1}").format(self.bill_no,
+ self.remarks = _("Against Supplier Invoice {0} dated {1}").format(self.bill_no,
formatdate(self.bill_date))
else:
self.remarks = _("No Remarks")
@@ -165,32 +146,32 @@
["Purchase Order", "purchase_order", "po_detail"],
["Purchase Receipt", "purchase_receipt", "pr_detail"]
])
-
+
def set_expense_account(self):
auto_accounting_for_stock = cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
if auto_accounting_for_stock:
stock_not_billed_account = self.get_company_default("stock_received_but_not_billed")
stock_items = self.get_stock_items()
-
+
if self.update_stock:
warehouse_account = get_warehouse_account()
-
+
for item in self.get("items"):
# in case of auto inventory accounting,
- # expense account is always "Stock Received But Not Billed" for a stock item
+ # expense account is always "Stock Received But Not Billed" for a stock item
# except epening entry, drop-ship entry and fixed asset items
-
+
if auto_accounting_for_stock and item.item_code in stock_items \
and self.is_opening == 'No' and not item.is_fixed_asset \
- and (not item.po_detail or
+ and (not item.po_detail or
not frappe.db.get_value("Purchase Order Item", item.po_detail, "delivered_by_supplier")):
if self.update_stock:
item.expense_account = warehouse_account[item.warehouse]["name"]
else:
item.expense_account = stock_not_billed_account
-
+
elif not item.expense_account:
throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name))
@@ -262,7 +243,7 @@
where name=`tabPurchase Invoice Item`.parent and update_stock=1 and is_return=1)"""
}
])
-
+
def validate_purchase_receipt_if_update_stock(self):
if self.update_stock:
for item in self.get("items"):
@@ -273,30 +254,30 @@
def on_submit(self):
self.check_prev_docstatus()
self.update_status_updater_args()
-
+
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
self.company, self.base_grand_total)
-
+
if not self.is_return:
self.update_against_document_in_jv()
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
self.update_billing_status_in_pr()
- # Updating stock ledger should always be called after updating prevdoc status,
+ # Updating stock ledger should always be called after updating prevdoc status,
# because updating ordered qty in bin depends upon updated ordered qty in PO
if self.update_stock == 1:
self.update_stock_ledger()
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
update_serial_nos_after_submit(self, "items")
-
+
# this sequence because outstanding may get -negative
self.make_gl_entries()
self.update_project()
self.update_fixed_asset()
-
- def update_fixed_asset(self):
+
+ def update_fixed_asset(self):
for d in self.get("items"):
if d.is_fixed_asset:
asset = frappe.get_doc("Asset", d.asset)
@@ -307,10 +288,10 @@
else:
asset.purchase_invoice = None
asset.supplier = None
-
+
asset.flags.ignore_validate_update_after_submit = True
asset.save()
-
+
def make_gl_entries(self, repost_future_gle=False):
self.auto_accounting_for_stock = \
cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
@@ -319,24 +300,24 @@
self.expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
self.negative_expense_to_be_booked = 0.0
gl_entries = []
-
-
+
+
self.make_supplier_gl_entry(gl_entries)
self.make_item_gl_entries(gl_entries)
self.make_tax_gl_entries(gl_entries)
-
+
gl_entries = merge_similar_entries(gl_entries)
-
+
self.make_payment_gl_entries(gl_entries)
self.make_write_off_gl_entry(gl_entries)
-
+
if gl_entries:
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
-
+
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
update_outstanding=update_outstanding, merge_entries=False)
-
+
if update_outstanding == "No":
update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
self.doctype, self.return_against if cint(self.is_return) else self.name)
@@ -345,10 +326,10 @@
from erpnext.controllers.stock_controller import update_gl_entries_after
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
-
+
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
-
+
def make_supplier_gl_entry(self, gl_entries):
if self.grand_total:
@@ -374,18 +355,18 @@
stock_items = self.get_stock_items()
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
warehouse_account = get_warehouse_account()
-
+
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = get_account_currency(item.expense_account)
-
+
if self.update_stock and self.auto_accounting_for_stock:
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
# warehouse account
- warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
+ warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
* flt(item.qty) * flt(item.conversion_factor), item.precision("base_net_amount"))
-
+
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account,
@@ -396,7 +377,7 @@
"project": item.project
}, account_currency)
)
-
+
# Amount added through landed-cost-voucher
if flt(item.landed_cost_voucher_amount):
gl_entries.append(self.get_gl_dict({
@@ -424,14 +405,14 @@
"account": item.expense_account,
"against": self.supplier,
"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
- "debit_in_account_currency": (flt(item.base_net_amount,
- item.precision("base_net_amount")) if account_currency==self.company_currency
+ "debit_in_account_currency": (flt(item.base_net_amount,
+ item.precision("base_net_amount")) if account_currency==self.company_currency
else flt(item.net_amount, item.precision("net_amount"))),
"cost_center": item.cost_center,
"project": item.project
}, account_currency)
)
-
+
if self.auto_accounting_for_stock and self.is_opening == "No" and \
item.item_code in stock_items and item.item_tax_amount:
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
@@ -480,7 +461,7 @@
valuation_tax.setdefault(tax.cost_center, 0)
valuation_tax[tax.cost_center] += \
(tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.base_tax_amount_after_discount_amount)
-
+
if self.is_opening == "No" and self.negative_expense_to_be_booked and valuation_tax:
# credit valuation tax amount in "Expenses Included In Valuation"
# this will balance out valuation amount included in cost of goods sold
@@ -525,7 +506,7 @@
"against_voucher_type": self.doctype,
}, self.party_account_currency)
)
-
+
gl_entries.append(
self.get_gl_dict({
"account": self.cash_bank_account,
@@ -568,9 +549,9 @@
def on_cancel(self):
self.check_for_closed_status()
-
+
self.update_status_updater_args()
-
+
if not self.is_return:
from erpnext.accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doctype, self.name)
@@ -579,11 +560,11 @@
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
self.update_billing_status_in_pr()
- # Updating stock ledger should always be called after updating prevdoc status,
+ # Updating stock ledger should always be called after updating prevdoc status,
# because updating ordered qty in bin depends upon updated ordered qty in PO
if self.update_stock == 1:
self.update_stock_ledger()
-
+
self.make_gl_entries_on_cancel()
self.update_project()
self.update_fixed_asset()
@@ -637,7 +618,7 @@
for pr in set(updated_pr):
frappe.get_doc("Purchase Receipt", pr).update_billing_percentage(update_modified=update_modified)
-
+
def validate_fixed_asset_account(self):
for d in self.get('items'):
if d.is_fixed_asset:
@@ -658,12 +639,11 @@
if account:
if frappe.db.get_value("Account", account, "account_type") != "Fixed Asset":
account=None
-
+
if not account:
asset_category, company = frappe.db.get_value("Asset", asset, ["asset_category", "company"])
-
+
account = frappe.db.get_value("Asset Category Account",
filters={"parent": asset_category, "company_name": company}, fieldname="fixed_asset_account")
-
+
return account
-
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py
new file mode 100644
index 0000000..9b950db
--- /dev/null
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice_dashboard.py
@@ -0,0 +1,31 @@
+from frappe import _
+
+data = {
+ 'fieldname': 'purchase_invoice',
+ 'non_standard_fieldnames': {
+ 'Delivery Note': 'against_sales_invoice',
+ 'Journal Entry': 'reference_name',
+ 'Payment Entry': 'reference_name',
+ 'Payment Request': 'reference_name',
+ 'Landed Cost Voucher': 'receipt_document',
+ 'Purchase Invoice': 'return_against'
+ },
+ 'internal_links': {
+ 'Purchase Order': ['items', 'sales_order'],
+ 'Purchase Receipt': ['items', 'delivery_note'],
+ },
+ 'transactions': [
+ {
+ 'label': _('Payment'),
+ 'items': ['Payment Entry', 'Payment Request', 'Journal Entry']
+ },
+ {
+ 'label': _('Reference'),
+ 'items': ['Purchase Order', 'Purchase Receipt', 'Asset', 'Landed Cost Voucher']
+ },
+ {
+ 'label': _('Returns'),
+ 'items': ['Purchase Invoice']
+ },
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
index bb489e7..4ea18ac 100644
--- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
@@ -50,9 +50,9 @@
pi = frappe.copy_doc(test_records[1])
pi.insert()
pi.submit()
-
+
self.check_gle_for_pi(pi.name)
-
+
set_perpetual_inventory(0)
def test_gl_entries_with_auto_accounting_for_stock_against_pr(self):
@@ -316,59 +316,59 @@
where voucher_type='Sales Invoice' and voucher_no=%s""", pi.name)
self.assertFalse(gle)
-
+
def test_purchase_invoice_update_stock_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
-
- pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
+
+ pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime())
-
+
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
-
+
expected_gl_entries = dict((d[0], d) for d in [
[pi.credit_to, 0.0, 250.0],
[pi.items[0].warehouse, 250.0, 0.0]
])
-
+
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_gl_entries[gle.account][0], gle.account)
self.assertEquals(expected_gl_entries[gle.account][1], gle.debit)
self.assertEquals(expected_gl_entries[gle.account][2], gle.credit)
-
+
def test_purchase_invoice_for_is_paid_and_update_stock_gl_entry_with_perpetual_inventory(self):
set_perpetual_inventory()
- pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
+ pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime(), cash_bank_account="Cash - _TC", is_paid=1)
- gl_entries = frappe.db.sql("""select account, account_currency, sum(debit) as debit,
- sum(credit) as credit, debit_in_account_currency, credit_in_account_currency
- from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
+ gl_entries = frappe.db.sql("""select account, account_currency, sum(debit) as debit,
+ sum(credit) as credit, debit_in_account_currency, credit_in_account_currency
+ from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
group by account, voucher_no order by account asc;""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
-
+
expected_gl_entries = dict((d[0], d) for d in [
[pi.credit_to, 250.0, 250.0],
[pi.items[0].warehouse, 250.0, 0.0],
["Cash - _TC", 0.0, 250.0]
])
-
+
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_gl_entries[gle.account][0], gle.account)
self.assertEquals(expected_gl_entries[gle.account][1], gle.debit)
self.assertEquals(expected_gl_entries[gle.account][2], gle.credit)
-
+
def test_update_stock_and_purchase_return(self):
actual_qty_0 = get_qty_after_transaction()
-
+
pi = make_purchase_invoice(update_stock=1, posting_date=frappe.utils.nowdate(),
posting_time=frappe.utils.nowtime())
-
+
actual_qty_1 = get_qty_after_transaction()
self.assertEquals(actual_qty_0 + 5, actual_qty_1)
@@ -377,37 +377,38 @@
actual_qty_2 = get_qty_after_transaction()
self.assertEquals(actual_qty_1 - 2, actual_qty_2)
-
+
pi1.cancel()
self.assertEquals(actual_qty_1, get_qty_after_transaction())
-
+
+ pi.reload()
pi.cancel()
self.assertEquals(actual_qty_0, get_qty_after_transaction())
-
+
def test_subcontracting_via_purchase_invoice(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
-
+
make_stock_entry(item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100)
- make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC",
+ make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC",
qty=100, basic_rate=100)
-
- pi = make_purchase_invoice(item_code="_Test FG Item", qty=10, rate=500,
+
+ pi = make_purchase_invoice(item_code="_Test FG Item", qty=10, rate=500,
update_stock=1, is_subcontracted="Yes")
-
+
self.assertEquals(len(pi.get("supplied_items")), 2)
-
+
rm_supp_cost = sum([d.amount for d in pi.get("supplied_items")])
self.assertEquals(pi.get("items")[0].rm_supp_cost, flt(rm_supp_cost, 2))
-
+
def test_rejected_serial_no(self):
pi = make_purchase_invoice(item_code="_Test Serialized Item With Series", received_qty=2, qty=1,
rejected_qty=1, rate=500, update_stock=1,
rejected_warehouse = "_Test Rejected Warehouse - _TC")
-
+
self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].serial_no, "warehouse"),
pi.get("items")[0].warehouse)
-
- self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no,
+
+ self.assertEquals(frappe.db.get_value("Serial No", pi.get("items")[0].rejected_serial_no,
"warehouse"), pi.get("items")[0].rejected_warehouse)
def make_purchase_invoice(**args):
@@ -420,10 +421,10 @@
pi.update_stock = 1
if args.is_paid:
pi.is_paid = 1
-
+
if args.cash_bank_account:
pi.cash_bank_account=args.cash_bank_account
-
+
pi.company = args.company or "_Test Company"
pi.supplier = args.supplier or "_Test Supplier"
pi.currency = args.currency or "INR"
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 1b68a83..1df86aa 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -39,25 +39,6 @@
'keyword': 'Billed',
'overflow_type': 'billing'
}]
-
- self.prev_link_mapper = {
- "Sales Order": {
- "fieldname": "sales_order",
- "doctype": "Sales Invoice Item",
- "filters": [
- ["Sales Invoice Item", "parent", "=", self.name],
- ["Sales Invoice Item", "sales_order", "!=", ""]
- ]
- },
- "Delivery Note": {
- "fieldname": "delivery_note",
- "doctype": "Sales Invoice Item",
- "filters": [
- ["Sales Invoice Item", "parent", "=", self.name],
- ["Sales Invoice Item", "delivery_note", "!=", ""]
- ]
- }
- }
def set_indicator(self):
"""Set indicator for portal"""
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
new file mode 100644
index 0000000..f494303
--- /dev/null
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice_dashboard.py
@@ -0,0 +1,30 @@
+from frappe import _
+
+data = {
+ 'fieldname': 'sales_invoice',
+ 'non_standard_fieldnames': {
+ 'Delivery Note': 'against_sales_invoice',
+ 'Journal Entry': 'reference_name',
+ 'Payment Entry': 'reference_name',
+ 'Payment Request': 'reference_name',
+ 'Sales Invoice': 'return_against'
+ },
+ 'internal_links': {
+ 'Sales Order': ['items', 'sales_order'],
+ 'Delivery Note': ['items', 'delivery_note'],
+ },
+ 'transactions': [
+ {
+ 'label': _('Payment'),
+ 'items': ['Payment Entry', 'Payment Request', 'Journal Entry']
+ },
+ {
+ 'label': _('Reference'),
+ 'items': ['Timesheet', 'Delivery Note', 'Sales Order']
+ },
+ {
+ 'label': _('Returns'),
+ 'items': ['Sales Invoice']
+ },
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index bc07aca..af46dc0 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -683,7 +683,7 @@
me.validate()
me.create_invoice();
me.make_payment();
- });
+ }, "octicon octicon-credit-card");
}else if(this.frm.doc.docstatus == 0 && this.frm.doc.items.length){
this.page.set_primary_action(__("Submit"), function() {
me.validate()
@@ -702,7 +702,7 @@
this.page.set_secondary_action(__("New"), function() {
me.save_previous_entry();
me.create_new();
- }).addClass("btn-primary");
+ }, "octicon octicon-plus").addClass("btn-primary");
},
print_document: function(html){
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 3885736..79b22ae 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -32,17 +32,6 @@
'percent_join_field': 'material_request',
'overflow_type': 'order'
}]
-
- self.prev_link_mapper = {
- "Supplier Quotation": {
- "fieldname": "supplier_quotation",
- "doctype": "Purchase Order Item",
- "filters": [
- ["Purchase Order Item", "parent", "=", self.name],
- ["Purchase Order Item", "supplier_quotation", "!=", ""]
- ]
- }
- }
def validate(self):
super(PurchaseOrder, self).validate()
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation_dashboard.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation_dashboard.py
new file mode 100644
index 0000000..6c8ae7c
--- /dev/null
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation_dashboard.py
@@ -0,0 +1,20 @@
+from frappe import _
+
+data = {
+ 'fieldname': 'supplier_quotation',
+ 'internal_links': {
+ 'Material Request': ['items', 'material_request'],
+ 'Request for Quotation': ['items', 'request_for_quotation'],
+ 'Project': ['items', 'project'],
+ },
+ 'transactions': [
+ {
+ 'label': _('Related'),
+ 'items': ['Purchase Order']
+ },
+ {
+ 'label': _('Reference'),
+ 'items': ['Material Request', 'Request for Quotation', 'Project']
+ },
+ ]
+}
diff --git a/erpnext/portal/doctype/homepage/homepage.py b/erpnext/portal/doctype/homepage/homepage.py
index a817230..20ce767 100644
--- a/erpnext/portal/doctype/homepage/homepage.py
+++ b/erpnext/portal/doctype/homepage/homepage.py
@@ -17,9 +17,10 @@
for d in frappe.get_all('Item', fields=['name', 'item_name', 'description', 'image'],
filters={'show_in_website': 1}, limit=3):
- # set missing routes (?)
doc = frappe.get_doc('Item', d.name)
- doc.save()
+ if not doc.route:
+ # set missing route
+ doc.save()
self.append('products', dict(item_code=d.name,
item_name=d.item_name, description=d.description, image=d.image))
diff --git a/erpnext/public/build.json b/erpnext/public/build.json
index cf412e1..340ebdb 100644
--- a/erpnext/public/build.json
+++ b/erpnext/public/build.json
@@ -26,8 +26,7 @@
"public/js/payment/pos_payment.html",
"public/js/payment/payment_details.html",
"public/js/templates/item_selector.html",
- "public/js/utils/item_selector.js",
- "public/js/utils/document_flow.js"
+ "public/js/utils/item_selector.js"
],
"js/item-dashboard.min.js": [
"stock/dashboard/item_dashboard.html",
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 0b6b0a6..ece8284 100644
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -33,7 +33,7 @@
setup_serial_no: function() {
var grid_row = cur_frm.open_grid_row();
- if(!grid_row.fields_dict.serial_no ||
+ if(!grid_row || !grid_row.fields_dict.serial_no ||
grid_row.fields_dict.serial_no.get_status()!=="Write") return;
var $btn = $('<button class="btn btn-sm btn-default">'+__("Add Serial No")+'</button>')
diff --git a/erpnext/public/js/utils/document_flow.js b/erpnext/public/js/utils/document_flow.js
deleted file mode 100644
index 0bc0b44..0000000
--- a/erpnext/public/js/utils/document_flow.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
-// MIT License. See license.txt
-
-// for module flow
-
-$.extend(frappe.document_flow, {
- "Selling": {
- "Sales Order": ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "Payment Entry"],
- "Quotation": ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "Payment Entry"]
- },
- "Accounts": {
- "Sales Invoice": ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "Payment Entry"],
- "Purchase Invoice": ["Supplier Quotation", "Purchase Order", "Purchase Receipt",
- "Purchase Invoice", "Payment Entry"]
- },
- "Buying": {
- // "Purchase Order": ["Supplier Quotation", "Purchase Order", "Purchase Receipt",
- // "Purchase Invoice", "Payment Entry"],
- "Supplier Quotation": ["Supplier Quotation", "Purchase Order", "Purchase Receipt",
- "Purchase Invoice", "Payment Entry"]
- },
- "Stock": {
- "Delivery Note": ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "Payment Entry"],
- "Purchase Receipt": ["Supplier Quotation", "Purchase Order", "Purchase Receipt",
- "Purchase Invoice", "Payment Entry"]
- }
-});
diff --git a/erpnext/selling/doctype/quotation/quotation_dashboard.py b/erpnext/selling/doctype/quotation/quotation_dashboard.py
new file mode 100644
index 0000000..80dc6aa
--- /dev/null
+++ b/erpnext/selling/doctype/quotation/quotation_dashboard.py
@@ -0,0 +1,11 @@
+from frappe import _
+
+data = {
+ 'fieldname': 'prevdoc_docname',
+ 'transactions': [
+ {
+ 'label': _('Related'),
+ 'items': ['Sales Order']
+ },
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index e4a1aab..ced3679 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -24,17 +24,6 @@
def __init__(self, arg1, arg2=None):
super(SalesOrder, self).__init__(arg1, arg2)
- self.prev_link_mapper = {
- "Quotation": {
- "fieldname": "prevdoc_docname",
- "doctype": "Sales Order Item",
- "filters": [
- ["Sales Order Item", "parent", "=", self.name],
- ["Sales Order Item", "prevdoc_docname", "!=", ""]
- ]
- }
- }
-
def validate(self):
super(SalesOrder, self).validate()
diff --git a/erpnext/selling/doctype/sales_order/sales_order_dashboard.py b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
new file mode 100644
index 0000000..feda39d
--- /dev/null
+++ b/erpnext/selling/doctype/sales_order/sales_order_dashboard.py
@@ -0,0 +1,33 @@
+from frappe import _
+
+data = {
+ 'fieldname': 'sales_order',
+ 'non_standard_fieldnames': {
+ 'Delivery Note': 'against_sales_order',
+ },
+ 'internal_links': {
+ 'Quotation': ['items', 'prevdoc_docname']
+ },
+ 'transactions': [
+ {
+ 'label': _('Fulfillment'),
+ 'items': ['Sales Invoice', 'Delivery Note']
+ },
+ {
+ 'label': _('Purchasing'),
+ 'items': ['Material Request', 'Purchase Order']
+ },
+ {
+ 'label': _('Projects'),
+ 'items': ['Project']
+ },
+ {
+ 'label': _('Manufacturing'),
+ 'items': ['Production Order']
+ },
+ {
+ 'label': _('Reference'),
+ 'items': ['Quotation']
+ },
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index d8defc0..5e31ac3 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -60,19 +60,7 @@
'source_field': '-1 * qty',
'extra_cond': """ and exists (select name from `tabDelivery Note` where name=`tabDelivery Note Item`.parent and is_return=1)"""
}]
-
- self.prev_link_mapper = {
- "Sales Order": {
- "fieldname": "against_sales_order",
- "doctype": "Delivery Note Item",
- "filters": [
- ["Delivery Note Item", "parent", "=", self.name],
- ["Delivery Note Item", "against_sales_order", "!=", ""]
- ]
- }
- }
-
def before_print(self):
def toggle_print_hide(meta, fieldname):
df = meta.get_field(fieldname)
@@ -203,7 +191,7 @@
if not self.is_return:
self.check_credit_limit()
- # Updating stock ledger should always be called after updating prevdoc status,
+ # Updating stock ledger should always be called after updating prevdoc status,
# because updating reserved qty in bin depends upon updated delivered qty in SO
self.update_stock_ledger()
self.make_gl_entries()
@@ -215,7 +203,7 @@
self.update_prevdoc_status()
self.update_billing_status()
- # Updating stock ledger should always be called after updating prevdoc status,
+ # Updating stock ledger should always be called after updating prevdoc status,
# because updating reserved qty in bin depends upon updated delivered qty in SO
self.update_stock_ledger()
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note_dashboard.py b/erpnext/stock/doctype/delivery_note/delivery_note_dashboard.py
new file mode 100644
index 0000000..c2b54f8
--- /dev/null
+++ b/erpnext/stock/doctype/delivery_note/delivery_note_dashboard.py
@@ -0,0 +1,26 @@
+from frappe import _
+
+data = {
+ 'fieldname': 'delivery_note_no',
+ 'non_standard_fieldnames': {
+ 'Sales Invoice': 'delivery_note',
+ 'Packing Slip': 'delivery_note',
+ },
+ 'internal_links': {
+ 'Sales Order': ['items', 'against_sales_order'],
+ },
+ 'transactions': [
+ {
+ 'label': _('Related'),
+ 'items': ['Sales Invoice', 'Packing Slip']
+ },
+ {
+ 'label': _('Reference'),
+ 'items': ['Sales Order', 'Quality Inspection']
+ },
+ {
+ 'label': _('Returns'),
+ 'items': ['Stock Entry']
+ },
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 5faefde..258331c 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -44,17 +44,6 @@
# 'overflow_type': 'receipt',
'extra_cond': """ and exists (select name from `tabPurchase Receipt` where name=`tabPurchase Receipt Item`.parent and is_return=1)"""
}]
-
- self.prev_link_mapper = {
- "Purchase Order": {
- "fieldname": "purchase_order",
- "doctype": "Purchase Receipt Item",
- "filters": [
- ["Purchase Receipt Item", "parent", "=", self.name],
- ["Purchase Receipt Item", "purchase_order", "!=", ""]
- ]
- }
- }
def validate(self):
super(PurchaseReceipt, self).validate()
@@ -123,7 +112,7 @@
purchase_controller = frappe.get_doc("Purchase Common")
# Check for Approving Authority
- frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
+ frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
self.company, self.base_grand_total)
# Set status as Submitted
@@ -135,7 +124,7 @@
if not self.is_return:
purchase_controller.update_last_purchase_rate(self, 1)
- # Updating stock ledger should always be called after updating prevdoc status,
+ # Updating stock ledger should always be called after updating prevdoc status,
# because updating ordered qty in bin depends upon updated ordered qty in PO
self.update_stock_ledger()
@@ -166,13 +155,13 @@
frappe.db.set(self,'status','Cancelled')
- self.update_prevdoc_status()
+ self.update_prevdoc_status()
self.update_billing_status()
if not self.is_return:
pc_obj.update_last_purchase_rate(self, 0)
-
- # Updating stock ledger should always be called after updating prevdoc status,
+
+ # Updating stock ledger should always be called after updating prevdoc status,
# because updating ordered qty in bin depends upon updated ordered qty in PO
self.update_stock_ledger()
self.make_gl_entries_on_cancel()
@@ -199,8 +188,8 @@
for d in self.get("items"):
if d.item_code in stock_items and flt(d.valuation_rate) and flt(d.qty):
if warehouse_account.get(d.warehouse):
- stock_value_diff = frappe.db.get_value("Stock Ledger Entry",
- {"voucher_type": "Purchase Receipt", "voucher_no": self.name,
+ stock_value_diff = frappe.db.get_value("Stock Ledger Entry",
+ {"voucher_type": "Purchase Receipt", "voucher_no": self.name,
"voucher_detail_no": d.name}, "stock_value_difference")
if not stock_value_diff:
continue
@@ -251,15 +240,15 @@
valuation_amount_as_per_doc = flt(d.base_net_amount, d.precision("base_net_amount")) + \
flt(d.landed_cost_voucher_amount) + flt(d.rm_supp_cost) + flt(d.item_tax_amount)
- divisional_loss = flt(valuation_amount_as_per_doc - stock_value_diff,
+ divisional_loss = flt(valuation_amount_as_per_doc - stock_value_diff,
d.precision("base_net_amount"))
-
+
if divisional_loss:
if self.is_return or flt(d.item_tax_amount):
loss_account = expenses_included_in_valuation
else:
loss_account = stock_rbnb
-
+
gl_entries.append(self.get_gl_dict({
"account": loss_account,
"against": warehouse_account[d.warehouse]["name"],
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
new file mode 100644
index 0000000..3278032
--- /dev/null
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt_dashboard.py
@@ -0,0 +1,28 @@
+from frappe import _
+
+data = {
+ 'fieldname': 'purchase_receipt_no',
+ 'non_standard_fieldnames': {
+ 'Purchase Invoice': 'purchase_receipt',
+ 'Landed Cost Voucher': 'receipt_document'
+ },
+ 'internal_links': {
+ 'Purchase Order': ['items', 'purchase_order'],
+ 'Project': ['items', 'project'],
+ 'Quality Inspection': ['items', 'qa_no'],
+ },
+ 'transactions': [
+ {
+ 'label': _('Related'),
+ 'items': ['Purchase Invoice', 'Landed Cost Voucher']
+ },
+ {
+ 'label': _('Reference'),
+ 'items': ['Purchase Order', 'Quality Inspection', 'Project']
+ },
+ {
+ 'label': _('Returns'),
+ 'items': ['Stock Entry']
+ },
+ ]
+}
\ No newline at end of file
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 8d17a1e..fa6dd3c 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -346,9 +346,8 @@
- if (frappe.local.flags.currently_saving
- and frappe.local.flags.currently_saving.doctype==self.exceptions[0]["voucher_type"]
- and frappe.local.flags.currently_saving.name==self.exceptions[0]["voucher_no"]):
+ if ((self.exceptions[0]["voucher_type"], self.exceptions[0]["voucher_no"]) in
+ frappe.local.flags.currently_saving):
msg = _("{0} units of {1} needed in {2} to complete this transaction.").format(
abs(deficiency), frappe.get_desk_link('Item', self.item_code),
frappe.get_desk_link('Warehouse', self.warehouse))