Merge pull request #13750 from rohitwaghchaure/asset_purchase_link
Asset linked to purchase and serial no
This commit is contained in:
commit
48199842aa
@ -412,7 +412,7 @@
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "account_type",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "\nAccumulated Depreciation\nBank\nCash\nChargeable\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nTax\nTemporary",
|
||||
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nTax\nTemporary",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
@ -625,7 +625,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-02 11:00:34.108490",
|
||||
"modified": "2018-05-07 15:37:25.962506",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Account",
|
||||
|
@ -63,7 +63,10 @@ def get():
|
||||
},
|
||||
_("Accumulated Depreciation"): {
|
||||
"account_type": "Accumulated Depreciation"
|
||||
}
|
||||
},
|
||||
_("CWIP Account"): {
|
||||
"account_type": "Capital Work in Progress",
|
||||
}
|
||||
},
|
||||
_("Investments"): {
|
||||
"is_group": 1
|
||||
@ -81,6 +84,9 @@ def get():
|
||||
_("Cost of Goods Sold"): {
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
_("Expenses Included In Asset Valuation"): {
|
||||
"account_type": "Expenses Included In Asset Valuation"
|
||||
},
|
||||
_("Expenses Included In Valuation"): {
|
||||
"account_type": "Expenses Included In Valuation"
|
||||
},
|
||||
@ -146,6 +152,9 @@ def get():
|
||||
_("Stock Received But Not Billed"): {
|
||||
"account_type": "Stock Received But Not Billed"
|
||||
},
|
||||
_("Asset Received But Not Billed"): {
|
||||
"account_type": "Asset Received But Not Billed"
|
||||
}
|
||||
},
|
||||
_("Duties and Taxes"): {
|
||||
"account_type": "Tax",
|
||||
|
@ -85,6 +85,10 @@ def get():
|
||||
"account_type": "Accumulated Depreciation",
|
||||
"account_number": "1780"
|
||||
},
|
||||
_("CWIP Account"): {
|
||||
"account_type": "Capital Work in Progress",
|
||||
"account_number": "1790"
|
||||
},
|
||||
"account_number": "1700"
|
||||
},
|
||||
_("Investments"): {
|
||||
@ -108,6 +112,10 @@ def get():
|
||||
"account_type": "Cost of Goods Sold",
|
||||
"account_number": "5111"
|
||||
},
|
||||
_("Expenses Included In Asset Valuation"): {
|
||||
"account_type": "Expenses Included In Asset Valuation",
|
||||
"account_number": "5112"
|
||||
},
|
||||
_("Expenses Included In Valuation"): {
|
||||
"account_type": "Expenses Included In Valuation",
|
||||
"account_number": "5118"
|
||||
@ -228,6 +236,10 @@ def get():
|
||||
"account_type": "Stock Received But Not Billed",
|
||||
"account_number": "2210"
|
||||
},
|
||||
_("Asset Received But Not Billed"): {
|
||||
"account_type": "Asset Received But Not Billed",
|
||||
"account_number": "2211"
|
||||
},
|
||||
"account_number": "2200"
|
||||
},
|
||||
_("Duties and Taxes"): {
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, erpnext, json
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, nowdate
|
||||
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, nowdate, cint
|
||||
from frappe import msgprint, _, scrub
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
from erpnext.accounts.utils import get_balance_on, get_account_currency
|
||||
@ -92,6 +92,7 @@ class JournalEntry(AccountsController):
|
||||
self.unlink_advance_entry_reference()
|
||||
self.unlink_asset_reference()
|
||||
self.unlink_inter_company_jv()
|
||||
self.unlink_asset_adjustment_entry()
|
||||
|
||||
def unlink_advance_entry_reference(self):
|
||||
for d in self.get("accounts"):
|
||||
@ -109,9 +110,12 @@ class JournalEntry(AccountsController):
|
||||
for s in asset.get("schedules"):
|
||||
if s.journal_entry == self.name:
|
||||
s.db_set("journal_entry", None)
|
||||
asset.value_after_depreciation += s.depreciation_amount
|
||||
|
||||
asset.db_set("value_after_depreciation", asset.value_after_depreciation)
|
||||
idx = cint(s.finance_book_id) or 1
|
||||
finance_books = asset.get('finance_books')[idx - 1]
|
||||
finance_books.value_after_depreciation += s.depreciation_amount
|
||||
finance_books.db_update()
|
||||
|
||||
asset.set_status()
|
||||
|
||||
def unlink_inter_company_jv(self):
|
||||
@ -121,6 +125,10 @@ class JournalEntry(AccountsController):
|
||||
frappe.db.set_value("Journal Entry", self.name,\
|
||||
"inter_company_journal_entry_reference", "")
|
||||
|
||||
def unlink_asset_adjustment_entry(self):
|
||||
frappe.db.sql(""" update `tabAsset Adjustment`
|
||||
set journal_entry = null where journal_entry = %s""", self.name)
|
||||
|
||||
def validate_party(self):
|
||||
for d in self.get("accounts"):
|
||||
account_type = frappe.db.get_value("Account", d.account, "account_type")
|
||||
|
@ -205,9 +205,10 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
||||
var row = locals[cdt][cdn];
|
||||
if(row.asset) {
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.get_fixed_asset_account",
|
||||
method: "erpnext.assets.doctype.asset_category.asset_category.get_asset_category_account",
|
||||
args: {
|
||||
"asset": row.asset,
|
||||
"fieldname": "fixed_asset_account",
|
||||
"account": row.expense_account
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
|
@ -19,6 +19,7 @@ from erpnext.accounts.general_ledger import get_round_off_account_and_cost_cente
|
||||
from frappe.model.mapper import get_mapped_doc
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\
|
||||
unlink_inter_company_invoice
|
||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||
|
||||
form_grid_templates = {
|
||||
"items": "templates/form_grid/item_grid.html"
|
||||
@ -305,24 +306,8 @@ class PurchaseInvoice(BuyingController):
|
||||
self.make_gl_entries()
|
||||
|
||||
self.update_project()
|
||||
self.update_fixed_asset()
|
||||
update_linked_invoice(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||
|
||||
def update_fixed_asset(self):
|
||||
for d in self.get("items"):
|
||||
if d.is_fixed_asset:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
if self.docstatus==1:
|
||||
asset.purchase_invoice = self.name
|
||||
asset.purchase_date = self.posting_date
|
||||
asset.supplier = self.supplier
|
||||
else:
|
||||
asset.purchase_invoice = None
|
||||
asset.supplier = None
|
||||
|
||||
asset.flags.ignore_validate_update_after_submit = True
|
||||
asset.save()
|
||||
|
||||
def make_gl_entries(self, gl_entries=None, repost_future_gle=True, from_repost=False):
|
||||
if not self.grand_total:
|
||||
return
|
||||
@ -438,6 +423,50 @@ class PurchaseInvoice(BuyingController):
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||
"credit": flt(item.rm_supp_cost)
|
||||
}, warehouse_account[self.supplier_warehouse]["account_currency"]))
|
||||
|
||||
elif item.is_fixed_asset:
|
||||
asset_accounts = self.get_company_default(["asset_received_but_not_billed",
|
||||
"expenses_included_in_asset_valuation", "capital_work_in_progress_account"])
|
||||
|
||||
asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate)
|
||||
base_asset_amount = flt(item.base_net_amount + item.item_tax_amount)
|
||||
|
||||
if not self.update_stock:
|
||||
asset_rbnb_currency = get_account_currency(asset_accounts[0])
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": asset_accounts[0],
|
||||
"against": self.supplier,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"debit": base_asset_amount,
|
||||
"debit_in_account_currency": (base_asset_amount
|
||||
if asset_rbnb_currency == self.company_currency else asset_amount)
|
||||
}))
|
||||
else:
|
||||
cwip_account = get_asset_category_account(item.asset,
|
||||
'capital_work_in_progress_account') or asset_accounts[2]
|
||||
|
||||
cwip_account_currency = get_account_currency(cwip_account)
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": cwip_account,
|
||||
"against": self.supplier,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"debit": base_asset_amount,
|
||||
"debit_in_account_currency": (base_asset_amount
|
||||
if cwip_account_currency == self.company_currency else asset_amount)
|
||||
}))
|
||||
|
||||
if item.item_tax_amount:
|
||||
asset_eiiav_currency = get_account_currency(asset_accounts[0])
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": asset_accounts[1],
|
||||
"against": self.supplier,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"cost_center": item.cost_center,
|
||||
"credit": item.item_tax_amount,
|
||||
"credit_in_account_currency": (item.item_tax_amount
|
||||
if asset_eiiav_currency == self.company_currency else
|
||||
item.item_tax_amount / self.conversion_rate)
|
||||
}))
|
||||
else:
|
||||
gl_entries.append(
|
||||
self.get_gl_dict({
|
||||
@ -636,7 +665,6 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
self.make_gl_entries_on_cancel()
|
||||
self.update_project()
|
||||
self.update_fixed_asset()
|
||||
frappe.db.set(self, 'status', 'Cancelled')
|
||||
|
||||
unlink_inter_company_invoice(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||
@ -708,20 +736,6 @@ def make_debit_note(source_name, target_doc=None):
|
||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||
return make_return_doc("Purchase Invoice", source_name, target_doc)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_fixed_asset_account(asset, account=None):
|
||||
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
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_stock_entry(source_name, target_doc=None):
|
||||
doc = get_mapped_doc("Purchase Invoice", source_name, {
|
||||
|
@ -2258,7 +2258,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-02-22 15:15:25.297672",
|
||||
"modified": "2018-04-23 14:07:33.576495",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
@ -57,6 +57,19 @@ frappe.ui.form.on('Asset', {
|
||||
erpnext.asset.restore_asset(frm);
|
||||
});
|
||||
}
|
||||
|
||||
if (frm.doc.purchase_receipt) {
|
||||
frm.add_custom_button("General Ledger", function() {
|
||||
frappe.route_options = {
|
||||
"voucher_no": frm.doc.name,
|
||||
"from_date": frm.doc.available_for_use_date,
|
||||
"to_date": frm.doc.available_for_use_date,
|
||||
"company": frm.doc.company
|
||||
};
|
||||
frappe.set_route("query-report", "General Ledger");
|
||||
});
|
||||
}
|
||||
|
||||
if (frm.doc.status=='Submitted' && !frm.doc.is_existing_asset && !frm.doc.purchase_invoice) {
|
||||
frm.add_custom_button(__("Purchase Invoice"), function() {
|
||||
frm.trigger("make_purchase_invoice");
|
||||
@ -67,6 +80,12 @@ frappe.ui.form.on('Asset', {
|
||||
frm.trigger("create_asset_maintenance");
|
||||
}, __("Make"));
|
||||
}
|
||||
if (frm.doc.status != 'Fully Depreciated') {
|
||||
frm.add_custom_button(__("Asset Adjustment"), function() {
|
||||
frm.trigger("create_asset_maintenance");
|
||||
}, __("Make"));
|
||||
}
|
||||
|
||||
frm.page.set_inner_btn_group_as_primary(__("Make"));
|
||||
frm.trigger("setup_chart");
|
||||
}
|
||||
@ -131,9 +150,7 @@ frappe.ui.form.on('Asset', {
|
||||
},
|
||||
callback: function(r, rt) {
|
||||
if(r.message) {
|
||||
$.each(r.message, function(field, value) {
|
||||
frm.set_value(field, value);
|
||||
})
|
||||
frm.set_value('finance_books', r.message);
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -141,7 +158,7 @@ frappe.ui.form.on('Asset', {
|
||||
},
|
||||
|
||||
is_existing_asset: function(frm) {
|
||||
frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
|
||||
// frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
|
||||
},
|
||||
|
||||
opening_accumulated_depreciation: function(frm) {
|
||||
@ -181,7 +198,8 @@ frappe.ui.form.on('Asset', {
|
||||
args: {
|
||||
"asset": frm.doc.name,
|
||||
"item_code": frm.doc.item_code,
|
||||
"company": frm.doc.company
|
||||
"company": frm.doc.company,
|
||||
"serial_no": frm.doc.serial_no
|
||||
},
|
||||
method: "erpnext.assets.doctype.asset.asset.make_sales_invoice",
|
||||
callback: function(r) {
|
||||
@ -290,15 +308,14 @@ erpnext.asset.transfer_asset = function(frm) {
|
||||
title: __("Transfer Asset"),
|
||||
fields: [
|
||||
{
|
||||
"label": __("Target Warehouse"),
|
||||
"fieldname": "target_warehouse",
|
||||
"label": __("Target Location"),
|
||||
"fieldname": "target_location",
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"options": "Location",
|
||||
"get_query": function () {
|
||||
return {
|
||||
filters: [
|
||||
["Warehouse", "company", "in", ["", cstr(frm.doc.company)]],
|
||||
["Warehouse", "is_group", "=", 0]
|
||||
["Location", "is_group", "=", 0]
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -325,8 +342,8 @@ erpnext.asset.transfer_asset = function(frm) {
|
||||
args: {
|
||||
"asset": frm.doc.name,
|
||||
"transaction_date": args.transfer_date,
|
||||
"source_warehouse": frm.doc.warehouse,
|
||||
"target_warehouse": args.target_warehouse,
|
||||
"source_warehouse": frm.doc.location,
|
||||
"target_warehouse": args.target_location,
|
||||
"company": frm.doc.company
|
||||
}
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,11 +7,14 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff
|
||||
from frappe.model.document import Document
|
||||
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_fixed_asset_account
|
||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||
from erpnext.assets.doctype.asset.depreciation \
|
||||
import get_disposal_account_and_cost_center, get_depreciation_accounts
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
from erpnext.controllers.accounts_controller import AccountsController
|
||||
|
||||
class Asset(Document):
|
||||
class Asset(AccountsController):
|
||||
def validate(self):
|
||||
self.status = self.get_status()
|
||||
self.validate_item()
|
||||
@ -26,6 +29,7 @@ class Asset(Document):
|
||||
|
||||
def on_submit(self):
|
||||
self.set_status()
|
||||
self.update_stock_movement()
|
||||
|
||||
def on_cancel(self):
|
||||
self.validate_cancellation()
|
||||
@ -45,11 +49,12 @@ class Asset(Document):
|
||||
frappe.throw(_("Item {0} must be a non-stock item").format(self.item_code))
|
||||
|
||||
def set_missing_values(self):
|
||||
if self.item_code:
|
||||
item_details = get_item_details(self.item_code)
|
||||
for field, value in item_details.items():
|
||||
if not self.get(field):
|
||||
self.set(field, value)
|
||||
if not self.asset_category:
|
||||
self.asset_category = frappe.db.get_value("Item", self.item_code, "asset_category")
|
||||
|
||||
if self.item_code and not self.get('finance_books'):
|
||||
finance_books = get_item_details(self.item_code, self.asset_category)
|
||||
self.set('finance_books', finance_books)
|
||||
|
||||
def validate_asset_values(self):
|
||||
if not flt(self.gross_purchase_amount):
|
||||
@ -58,16 +63,105 @@ class Asset(Document):
|
||||
if not self.calculate_depreciation:
|
||||
return
|
||||
|
||||
if flt(self.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
|
||||
frappe.throw(_("Expected Value After Useful Life must be less than Gross Purchase Amount"))
|
||||
if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(nowdate()):
|
||||
frappe.throw(_("Available-for-use Date is entered as past date"))
|
||||
|
||||
def make_depreciation_schedule(self):
|
||||
if self.depreciation_method != 'Manual':
|
||||
self.schedules = []
|
||||
|
||||
if not self.get("schedules") and self.available_for_use_date:
|
||||
total_depreciations = sum([d.total_number_of_depreciations for d in self.get('finance_books')])
|
||||
|
||||
for d in self.get('finance_books'):
|
||||
self.validate_asset_finance_books(d)
|
||||
|
||||
value_after_depreciation = (flt(self.gross_purchase_amount) -
|
||||
flt(self.opening_accumulated_depreciation))
|
||||
|
||||
d.value_after_depreciation = value_after_depreciation
|
||||
|
||||
no_of_depreciations = cint(d.total_number_of_depreciations - 1) - cint(self.number_of_depreciations_booked)
|
||||
end_date = add_months(d.depreciation_start_date,
|
||||
no_of_depreciations * cint(d.frequency_of_depreciation))
|
||||
|
||||
total_days = date_diff(end_date, self.available_for_use_date)
|
||||
rate_per_day = value_after_depreciation / total_days
|
||||
|
||||
number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
|
||||
cint(self.number_of_depreciations_booked)
|
||||
|
||||
from_date = self.available_for_use_date
|
||||
if number_of_pending_depreciations:
|
||||
next_depr_date = getdate(add_months(self.available_for_use_date,
|
||||
number_of_pending_depreciations * 12))
|
||||
if (cint(frappe.db.get_value("Asset Settings", None, "schedule_based_on_fiscal_year")) == 1
|
||||
and getdate(d.depreciation_start_date) < next_depr_date):
|
||||
|
||||
number_of_pending_depreciations += 1
|
||||
for n in range(number_of_pending_depreciations):
|
||||
if n == range(number_of_pending_depreciations)[-1]:
|
||||
schedule_date = add_months(self.available_for_use_date, n * 12)
|
||||
previous_scheduled_date = add_months(d.depreciation_start_date, (n-1) * 12)
|
||||
depreciation_amount = \
|
||||
self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
|
||||
d, previous_scheduled_date, schedule_date)
|
||||
|
||||
elif n == range(number_of_pending_depreciations)[0]:
|
||||
schedule_date = d.depreciation_start_date
|
||||
depreciation_amount = \
|
||||
self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
|
||||
d, self.available_for_use_date, schedule_date)
|
||||
|
||||
else:
|
||||
schedule_date = add_months(d.depreciation_start_date, n * 12)
|
||||
depreciation_amount = \
|
||||
self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d)
|
||||
|
||||
if value_after_depreciation != 0:
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
|
||||
self.append("schedules", {
|
||||
"schedule_date": schedule_date,
|
||||
"depreciation_amount": depreciation_amount,
|
||||
"depreciation_method": d.depreciation_method,
|
||||
"finance_book": d.finance_book,
|
||||
"finance_book_id": d.idx
|
||||
})
|
||||
else:
|
||||
for n in range(number_of_pending_depreciations):
|
||||
schedule_date = add_months(d.depreciation_start_date,
|
||||
n * cint(d.frequency_of_depreciation))
|
||||
|
||||
if d.depreciation_method in ("Straight Line", "Manual"):
|
||||
days = date_diff(schedule_date, from_date)
|
||||
depreciation_amount = days * rate_per_day
|
||||
from_date = schedule_date
|
||||
else:
|
||||
depreciation_amount = self.get_depreciation_amount(value_after_depreciation,
|
||||
d.total_number_of_depreciations, d)
|
||||
|
||||
if depreciation_amount:
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
|
||||
self.append("schedules", {
|
||||
"schedule_date": schedule_date,
|
||||
"depreciation_amount": depreciation_amount,
|
||||
"depreciation_method": d.depreciation_method,
|
||||
"finance_book": d.finance_book,
|
||||
"finance_book_id": d.idx
|
||||
})
|
||||
|
||||
def validate_asset_finance_books(self, row):
|
||||
if flt(row.expected_value_after_useful_life) >= flt(self.gross_purchase_amount):
|
||||
frappe.throw(_("Row {0}: Expected Value After Useful Life must be less than Gross Purchase Amount")
|
||||
.format(row.idx))
|
||||
|
||||
if not self.is_existing_asset:
|
||||
self.opening_accumulated_depreciation = 0
|
||||
self.number_of_depreciations_booked = 0
|
||||
if not self.next_depreciation_date:
|
||||
frappe.throw(_("Next Depreciation Date is mandatory for new asset"))
|
||||
else:
|
||||
depreciable_amount = flt(self.gross_purchase_amount) - flt(self.expected_value_after_useful_life)
|
||||
depreciable_amount = flt(self.gross_purchase_amount) - flt(row.expected_value_after_useful_life)
|
||||
if flt(self.opening_accumulated_depreciation) > depreciable_amount:
|
||||
frappe.throw(_("Opening Accumulated Depreciation must be less than equal to {0}")
|
||||
.format(depreciable_amount))
|
||||
@ -78,139 +172,89 @@ class Asset(Document):
|
||||
else:
|
||||
self.number_of_depreciations_booked = 0
|
||||
|
||||
if cint(self.number_of_depreciations_booked) > cint(self.total_number_of_depreciations):
|
||||
if cint(self.number_of_depreciations_booked) > cint(row.total_number_of_depreciations):
|
||||
frappe.throw(_("Number of Depreciations Booked cannot be greater than Total Number of Depreciations"))
|
||||
|
||||
self.value_after_depreciation = (flt(self.gross_purchase_amount) -
|
||||
flt(self.opening_accumulated_depreciation))
|
||||
if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(nowdate()):
|
||||
frappe.msgprint(_("Depreciation Row {0}: Depreciation Start Date is entered as past date")
|
||||
.format(row.idx), title=_('Warning'), indicator='red')
|
||||
|
||||
if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(nowdate()):
|
||||
frappe.msgprint(_("Next Depreciation Date is entered as past date"), title=_('Warning'), indicator='red')
|
||||
if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(self.purchase_date):
|
||||
frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Purchase Date")
|
||||
.format(row.idx))
|
||||
|
||||
if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(self.purchase_date):
|
||||
frappe.throw(_("Next Depreciation Date cannot be before Purchase Date"))
|
||||
if row.depreciation_start_date and getdate(row.depreciation_start_date) < getdate(self.available_for_use_date):
|
||||
frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date")
|
||||
.format(row.idx))
|
||||
|
||||
if self.next_depreciation_date and getdate(self.next_depreciation_date) < getdate(self.available_for_use_date):
|
||||
frappe.throw(_("Next Depreciation Date cannot be before Available-for-use Date"))
|
||||
def set_accumulated_depreciation(self, ignore_booked_entry = False):
|
||||
straight_line_idx = [d.idx for d in self.get("schedules") if d.depreciation_method == 'Straight Line']
|
||||
finance_books = []
|
||||
|
||||
if (flt(self.value_after_depreciation) > flt(self.expected_value_after_useful_life)
|
||||
and not self.next_depreciation_date and self.calculate_depreciation):
|
||||
frappe.throw(_("Please set Next Depreciation Date"))
|
||||
|
||||
def make_depreciation_schedule(self):
|
||||
|
||||
if self.depreciation_method != 'Manual':
|
||||
self.schedules = []
|
||||
|
||||
if not self.get("schedules") and self.next_depreciation_date:
|
||||
value_after_depreciation = flt(self.value_after_depreciation)
|
||||
|
||||
number_of_pending_depreciations = cint(self.total_number_of_depreciations) - \
|
||||
cint(self.number_of_depreciations_booked)
|
||||
if number_of_pending_depreciations:
|
||||
next_depr_date = getdate(add_months(self.available_for_use_date,
|
||||
number_of_pending_depreciations * 12))
|
||||
if (cint(frappe.db.get_value("Asset Settings", None, "schedule_based_on_fiscal_year")) == 1
|
||||
and getdate(self.next_depreciation_date) < next_depr_date):
|
||||
|
||||
number_of_pending_depreciations += 1
|
||||
for n in range(number_of_pending_depreciations):
|
||||
if n == range(number_of_pending_depreciations)[-1]:
|
||||
schedule_date = add_months(self.available_for_use_date, n * 12)
|
||||
previous_scheduled_date = add_months(self.next_depreciation_date, (n-1) * 12)
|
||||
depreciation_amount = \
|
||||
self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
|
||||
previous_scheduled_date, schedule_date)
|
||||
|
||||
elif n == range(number_of_pending_depreciations)[0]:
|
||||
schedule_date = self.next_depreciation_date
|
||||
depreciation_amount = \
|
||||
self.get_depreciation_amount_prorata_temporis(value_after_depreciation,
|
||||
self.available_for_use_date, schedule_date)
|
||||
|
||||
else:
|
||||
schedule_date = add_months(self.next_depreciation_date, n * 12)
|
||||
depreciation_amount = \
|
||||
self.get_depreciation_amount_prorata_temporis(value_after_depreciation)
|
||||
|
||||
if value_after_depreciation != 0:
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
|
||||
self.append("schedules", {
|
||||
"schedule_date": schedule_date,
|
||||
"depreciation_amount": depreciation_amount
|
||||
})
|
||||
else:
|
||||
for n in range(number_of_pending_depreciations):
|
||||
schedule_date = add_months(self.next_depreciation_date,
|
||||
n * cint(self.frequency_of_depreciation))
|
||||
|
||||
depreciation_amount = self.get_depreciation_amount(value_after_depreciation)
|
||||
if depreciation_amount:
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
|
||||
self.append("schedules", {
|
||||
"schedule_date": schedule_date,
|
||||
"depreciation_amount": depreciation_amount
|
||||
})
|
||||
|
||||
def set_accumulated_depreciation(self):
|
||||
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
||||
value_after_depreciation = flt(self.value_after_depreciation)
|
||||
for i, d in enumerate(self.get("schedules")):
|
||||
if ignore_booked_entry and d.journal_entry:
|
||||
continue
|
||||
|
||||
if d.finance_book_id not in finance_books:
|
||||
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
||||
value_after_depreciation = flt(self.get_value_after_depreciation(d.finance_book_id))
|
||||
finance_books.append(d.finance_book_id)
|
||||
|
||||
depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
|
||||
if i==len(self.get("schedules"))-1 and self.depreciation_method == "Straight Line":
|
||||
if straight_line_idx and i == max(straight_line_idx) - 1:
|
||||
book = self.get('finance_books')[cint(d.finance_book_id) - 1]
|
||||
depreciation_amount += flt(value_after_depreciation -
|
||||
flt(self.expected_value_after_useful_life), d.precision("depreciation_amount"))
|
||||
flt(book.expected_value_after_useful_life), d.precision("depreciation_amount"))
|
||||
|
||||
d.depreciation_amount = depreciation_amount
|
||||
accumulated_depreciation += d.depreciation_amount
|
||||
d.accumulated_depreciation_amount = flt(accumulated_depreciation,
|
||||
d.precision("accumulated_depreciation_amount"))
|
||||
|
||||
def get_depreciation_amount(self, depreciable_value):
|
||||
if self.depreciation_method in ("Straight Line", "Manual"):
|
||||
depreciation_amount = (flt(self.value_after_depreciation) -
|
||||
flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) -
|
||||
cint(self.number_of_depreciations_booked))
|
||||
else:
|
||||
factor = 200.0 / self.total_number_of_depreciations
|
||||
depreciation_amount = flt(depreciable_value * factor / 100, 0)
|
||||
def get_value_after_depreciation(self, idx):
|
||||
return flt(self.get('finance_books')[cint(idx)-1].value_after_depreciation)
|
||||
|
||||
value_after_depreciation = flt(depreciable_value) - depreciation_amount
|
||||
if value_after_depreciation < flt(self.expected_value_after_useful_life):
|
||||
depreciation_amount = flt(depreciable_value) - flt(self.expected_value_after_useful_life)
|
||||
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
|
||||
percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
|
||||
|
||||
factor = percentage_value / total_number_of_depreciations
|
||||
depreciation_amount = flt(depreciable_value * factor / 100, 0)
|
||||
|
||||
value_after_depreciation = flt(depreciable_value) - depreciation_amount
|
||||
if value_after_depreciation < flt(row.expected_value_after_useful_life):
|
||||
depreciation_amount = flt(depreciable_value) - flt(row.expected_value_after_useful_life)
|
||||
|
||||
return depreciation_amount
|
||||
|
||||
def get_depreciation_amount_prorata_temporis(self, depreciable_value, start_date=None, end_date=None):
|
||||
def get_depreciation_amount_prorata_temporis(self, depreciable_value, row, start_date=None, end_date=None):
|
||||
if start_date and end_date:
|
||||
prorata_temporis = min(abs(flt(date_diff(str(end_date), str(start_date)))) / flt(frappe.db.get_value("Asset Settings", None, "number_of_days_in_fiscal_year")), 1)
|
||||
else:
|
||||
prorata_temporis = 1
|
||||
|
||||
if self.depreciation_method in ("Straight Line", "Manual"):
|
||||
depreciation_amount = (flt(self.value_after_depreciation) -
|
||||
flt(self.expected_value_after_useful_life)) / (cint(self.total_number_of_depreciations) -
|
||||
if row.depreciation_method in ("Straight Line", "Manual"):
|
||||
depreciation_amount = (flt(row.value_after_depreciation) -
|
||||
flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
|
||||
cint(self.number_of_depreciations_booked)) * prorata_temporis
|
||||
|
||||
return depreciation_amount
|
||||
else:
|
||||
self.get_depreciation_amount(depreciable_value)
|
||||
depreciation_amount = self.get_depreciation_amount(depreciable_value, row)
|
||||
|
||||
return depreciation_amount
|
||||
|
||||
def validate_expected_value_after_useful_life(self):
|
||||
accumulated_depreciation_after_full_schedule = \
|
||||
max([d.accumulated_depreciation_amount for d in self.get("schedules")])
|
||||
for row in self.get('finance_books'):
|
||||
accumulated_depreciation_after_full_schedule = \
|
||||
max([d.accumulated_depreciation_amount for d in self.get("schedules") if d.finance_book_id == row.idx])
|
||||
|
||||
asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
|
||||
flt(accumulated_depreciation_after_full_schedule),
|
||||
self.precision('expected_value_after_useful_life'))
|
||||
asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
|
||||
flt(accumulated_depreciation_after_full_schedule),
|
||||
self.precision('gross_purchase_amount'))
|
||||
|
||||
if self.expected_value_after_useful_life < asset_value_after_full_schedule:
|
||||
frappe.throw(_("Expected value after useful life must be greater than or equal to {0}")
|
||||
.format(asset_value_after_full_schedule))
|
||||
if row.expected_value_after_useful_life < asset_value_after_full_schedule:
|
||||
frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
|
||||
.format(row.idx, asset_value_after_full_schedule))
|
||||
|
||||
def validate_cancellation(self):
|
||||
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
|
||||
@ -219,6 +263,9 @@ class Asset(Document):
|
||||
if self.purchase_invoice:
|
||||
frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
|
||||
|
||||
if self.purchase_receipt:
|
||||
frappe.throw(_("Please cancel Purchase Receipt {0} first").format(self.purchase_receipt))
|
||||
|
||||
def delete_depreciation_entries(self):
|
||||
for d in self.get("schedules"):
|
||||
if d.journal_entry:
|
||||
@ -240,9 +287,15 @@ class Asset(Document):
|
||||
status = "Draft"
|
||||
elif self.docstatus == 1:
|
||||
status = "Submitted"
|
||||
expected_value_after_useful_life = flt(sum([d.expected_value_after_useful_life
|
||||
for d in self.get('finance_books')]))
|
||||
|
||||
value_after_depreciation = flt(sum([d.value_after_depreciation
|
||||
for d in self.get('finance_books')]))
|
||||
|
||||
if self.journal_entry_for_scrap:
|
||||
status = "Scrapped"
|
||||
elif flt(self.value_after_depreciation) <= flt(self.expected_value_after_useful_life):
|
||||
elif flt(value_after_depreciation) <= expected_value_after_useful_life:
|
||||
status = "Fully Depreciated"
|
||||
elif flt(self.value_after_depreciation) < flt(self.gross_purchase_amount):
|
||||
status = 'Partially Depreciated'
|
||||
@ -250,6 +303,45 @@ class Asset(Document):
|
||||
status = "Cancelled"
|
||||
return status
|
||||
|
||||
def update_stock_movement(self):
|
||||
asset_movement = frappe.db.get_value('Asset Movement',
|
||||
{'asset': self.name, 'reference_name': self.purchase_receipt, 'docstatus': 0}, 'name')
|
||||
|
||||
if asset_movement:
|
||||
doc = frappe.get_doc('Asset Movement', asset_movement)
|
||||
doc.submit()
|
||||
|
||||
def make_gl_entries(self):
|
||||
if self.purchase_receipt and self.purchase_receipt_amount:
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
|
||||
gl_entries = []
|
||||
|
||||
cwip_account = get_cwip_account(self.name, self.asset_category, self.company)
|
||||
fixed_aseet_account = get_asset_category_account(self.name, 'fixed_asset_account',
|
||||
asset_category = self.asset_category, company = self.company)
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": cwip_account,
|
||||
"against": fixed_aseet_account,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"posting_date": self.available_for_use_date,
|
||||
"credit": self.purchase_receipt_amount,
|
||||
"credit_in_account_currency": self.purchase_receipt_amount
|
||||
}))
|
||||
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": fixed_aseet_account,
|
||||
"against": cwip_account,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"posting_date": self.available_for_use_date,
|
||||
"debit": self.purchase_receipt_amount,
|
||||
"debit_in_account_currency": self.purchase_receipt_amount
|
||||
}))
|
||||
|
||||
make_gl_entries(gl_entries)
|
||||
self.db_set('booked_fixed_asset', 1)
|
||||
|
||||
def update_maintenance_status():
|
||||
assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
|
||||
|
||||
@ -260,6 +352,18 @@ def update_maintenance_status():
|
||||
if frappe.db.exists('Asset Repair', {'asset_name': asset.name, 'repair_status': 'Pending'}):
|
||||
asset.set_status('Out of Order')
|
||||
|
||||
def make_post_gl_entry():
|
||||
assets = frappe.db.sql_list(""" select name from `tabAsset`
|
||||
where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
|
||||
|
||||
for asset in assets:
|
||||
doc = frappe.get_doc('Asset', asset)
|
||||
doc.make_gl_entries()
|
||||
|
||||
def get_asset_naming_series():
|
||||
meta = frappe.get_meta('Asset')
|
||||
return meta.get_field("naming_series").options
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, posting_date):
|
||||
pi = frappe.new_doc("Purchase Invoice")
|
||||
@ -271,7 +375,7 @@ def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, post
|
||||
"item_code": item_code,
|
||||
"is_fixed_asset": 1,
|
||||
"asset": asset,
|
||||
"expense_account": get_fixed_asset_account(asset),
|
||||
"expense_account": get_asset_category_account(asset, 'fixed_asset_account'),
|
||||
"qty": 1,
|
||||
"price_list_rate": gross_purchase_amount,
|
||||
"rate": gross_purchase_amount
|
||||
@ -280,7 +384,7 @@ def make_purchase_invoice(asset, item_code, gross_purchase_amount, company, post
|
||||
return pi
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_sales_invoice(asset, item_code, company):
|
||||
def make_sales_invoice(asset, item_code, company, serial_no=None):
|
||||
si = frappe.new_doc("Sales Invoice")
|
||||
si.company = company
|
||||
si.currency = frappe.db.get_value("Company", company, "default_currency")
|
||||
@ -290,6 +394,7 @@ def make_sales_invoice(asset, item_code, company):
|
||||
"is_fixed_asset": 1,
|
||||
"asset": asset,
|
||||
"income_account": disposal_account,
|
||||
"serial_no": serial_no,
|
||||
"cost_center": depreciation_cost_center,
|
||||
"qty": 1
|
||||
})
|
||||
@ -322,17 +427,32 @@ def transfer_asset(args):
|
||||
frappe.msgprint(_("Asset Movement record {0} created").format("<a href='#Form/Asset Movement/{0}'>{0}</a>".format(movement_entry.name)))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_item_details(item_code):
|
||||
asset_category = frappe.db.get_value("Item", item_code, "asset_category")
|
||||
|
||||
def get_item_details(item_code, asset_category=None):
|
||||
if not asset_category:
|
||||
frappe.throw(_("Please enter Asset Category in Item {0}").format(item_code))
|
||||
|
||||
ret = frappe.db.get_value("Asset Category", asset_category,
|
||||
["depreciation_method", "total_number_of_depreciations", "frequency_of_depreciation"], as_dict=1)
|
||||
asset_category_doc = frappe.get_doc('Asset Category', asset_category)
|
||||
books = []
|
||||
for d in asset_category_doc.finance_books:
|
||||
books.append({
|
||||
'finance_book': d.finance_book,
|
||||
'depreciation_method': d.depreciation_method,
|
||||
'total_number_of_depreciations': d.total_number_of_depreciations,
|
||||
'frequency_of_depreciation': d.frequency_of_depreciation,
|
||||
'start_date': nowdate()
|
||||
})
|
||||
|
||||
ret.update({
|
||||
"asset_category": asset_category
|
||||
})
|
||||
return books
|
||||
|
||||
return ret
|
||||
def get_cwip_account(asset, asset_category=None, company=None):
|
||||
cwip_account = get_asset_category_account(asset, 'capital_work_in_progress_account',
|
||||
asset_category = asset_category, company = company)
|
||||
|
||||
if not cwip_account:
|
||||
cwip_account = frappe.db.get_value('Company', company, 'capital_work_in_progress_account')
|
||||
|
||||
if not cwip_account:
|
||||
frappe.throw(_("Set Capital Work In Progress Account in asset category {0} or company {1}")
|
||||
.format(asset_category, company))
|
||||
|
||||
return cwip_account
|
||||
|
@ -1,6 +1,9 @@
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'asset_name',
|
||||
'non_standard_fieldnames': {
|
||||
'Asset Movement': 'asset'
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': ['Maintenance'],
|
||||
@ -9,6 +12,10 @@ def get_data():
|
||||
{
|
||||
'label': ['Repair'],
|
||||
'items': ['Asset Repair']
|
||||
},
|
||||
{
|
||||
'label': ['Movement'],
|
||||
'items': ['Asset Movement']
|
||||
}
|
||||
]
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, today, getdate
|
||||
from frappe.utils import flt, today, getdate, cint
|
||||
|
||||
def post_depreciation_entries(date=None):
|
||||
# Return if automatic booking of asset depreciation is disabled
|
||||
@ -47,6 +47,7 @@ def make_depreciation_entry(asset_name, date=None):
|
||||
je.naming_series = depreciation_series
|
||||
je.posting_date = d.schedule_date
|
||||
je.company = asset.company
|
||||
je.finance_book = d.finance_book
|
||||
je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount)
|
||||
|
||||
je.append("accounts", {
|
||||
@ -68,9 +69,12 @@ def make_depreciation_entry(asset_name, date=None):
|
||||
je.submit()
|
||||
|
||||
d.db_set("journal_entry", je.name)
|
||||
asset.value_after_depreciation -= d.depreciation_amount
|
||||
|
||||
idx = cint(d.finance_book_id)
|
||||
finance_books = asset.get('finance_books')[idx - 1]
|
||||
finance_books.value_after_depreciation -= d.depreciation_amount
|
||||
finance_books.db_update()
|
||||
|
||||
asset.db_set("value_after_depreciation", asset.value_after_depreciation)
|
||||
asset.set_status()
|
||||
|
||||
return asset
|
||||
|
0
erpnext/assets/doctype/asset_adjustment/__init__.py
Normal file
0
erpnext/assets/doctype/asset_adjustment/__init__.py
Normal file
30
erpnext/assets/doctype/asset_adjustment/asset_adjustment.js
Normal file
30
erpnext/assets/doctype/asset_adjustment/asset_adjustment.js
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Asset Adjustment', {
|
||||
asset: function(frm) {
|
||||
frm.trigger("set_current_asset_value");
|
||||
},
|
||||
|
||||
finance_book: function(frm) {
|
||||
frm.trigger("set_current_asset_value");
|
||||
},
|
||||
|
||||
set_current_asset_value: function(frm) {
|
||||
debugger
|
||||
if (frm.doc.finance_book && frm.doc.asset) {
|
||||
frm.call({
|
||||
method: "erpnext.assets.doctype.asset_adjustment.asset_adjustment.get_current_asset_value",
|
||||
args: {
|
||||
asset: frm.doc.asset,
|
||||
finance_book: frm.doc.finance_book
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
frm.set_value('current_asset_value', r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
437
erpnext/assets/doctype/asset_adjustment/asset_adjustment.json
Normal file
437
erpnext/assets/doctype/asset_adjustment/asset_adjustment.json
Normal file
@ -0,0 +1,437 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-05-11 00:22:43.695151",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "asset",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Asset",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "asset_category",
|
||||
"fieldtype": "Read Only",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset Category",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "asset.asset_category",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "finance_book",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Finance Book",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Finance Book",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "journal_entry",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Journal Entry",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Journal Entry",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Datetime",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "current_asset_value",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Current Asset Value",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "new_asset_value",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "New Asset Value",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "difference_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Difference Amount",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Amended From",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Asset Adjustment",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-11 21:45:03.459696",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Adjustment",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "asset",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
103
erpnext/assets/doctype/asset_adjustment/asset_adjustment.py
Normal file
103
erpnext/assets/doctype/asset_adjustment/asset_adjustment.py
Normal file
@ -0,0 +1,103 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, getdate, cint, date_diff
|
||||
from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
|
||||
from frappe.model.document import Document
|
||||
|
||||
class AssetAdjustment(Document):
|
||||
def validate(self):
|
||||
self.set_difference_amount()
|
||||
self.set_current_asset_value()
|
||||
|
||||
def on_submit(self):
|
||||
self.make_depreciation_entry()
|
||||
self.reschedule_depreciations()
|
||||
|
||||
def on_cancel(self):
|
||||
if self.journal_entry:
|
||||
frappe.throw(_("Cancel the journal entry {0} first").format(self.journal_entry))
|
||||
|
||||
def set_difference_amount(self):
|
||||
self.difference_amount = flt(self.current_asset_value - self.new_asset_value)
|
||||
|
||||
def set_current_asset_value(self):
|
||||
if not self.current_asset_value and self.asset and self.finance_book:
|
||||
self.current_asset_value = get_current_asset_value(self.asset, self.finance_book)
|
||||
|
||||
def make_depreciation_entry(self):
|
||||
asset = frappe.get_doc("Asset", self.asset)
|
||||
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
|
||||
get_depreciation_accounts(asset)
|
||||
|
||||
depreciation_cost_center, depreciation_series = frappe.db.get_value("Company", asset.company,
|
||||
["depreciation_cost_center", "series_for_depreciation_entry"])
|
||||
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.voucher_type = "Depreciation Entry"
|
||||
je.naming_series = depreciation_series
|
||||
je.posting_date = self.date
|
||||
je.company = self.company
|
||||
je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount)
|
||||
|
||||
je.append("accounts", {
|
||||
"account": accumulated_depreciation_account,
|
||||
"credit_in_account_currency": self.difference_amount,
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": depreciation_expense_account,
|
||||
"debit_in_account_currency": self.difference_amount,
|
||||
"cost_center": depreciation_cost_center
|
||||
})
|
||||
|
||||
je.flags.ignore_permissions = True
|
||||
je.submit()
|
||||
|
||||
self.db_set("journal_entry", je.name)
|
||||
|
||||
def reschedule_depreciations(self):
|
||||
asset = frappe.get_doc('Asset', self.asset)
|
||||
|
||||
for d in asset.finance_books:
|
||||
d.value_after_depreciation = self.new_asset_value
|
||||
|
||||
if d.depreciation_method in ("Straight Line", "Manual"):
|
||||
end_date = max([s.schedule_date for s in asset.schedules if cint(s.finance_book_id) == d.idx])
|
||||
total_days = date_diff(end_date, self.date)
|
||||
rate_per_day = flt(d.value_after_depreciation) / flt(total_days)
|
||||
from_date = self.date
|
||||
else:
|
||||
no_of_depreciations = len([e.name for e in asset.schedules
|
||||
if (cint(s.finance_book_id) == d.idx and not e.journal_entry)])
|
||||
|
||||
value_after_depreciation = d.value_after_depreciation
|
||||
for data in asset.schedules:
|
||||
if cint(data.finance_book_id) == d.idx and not data.journal_entry:
|
||||
if d.depreciation_method in ("Straight Line", "Manual"):
|
||||
days = date_diff(data.schedule_date, from_date)
|
||||
depreciation_amount = days * rate_per_day
|
||||
from_date = data.schedule_date
|
||||
else:
|
||||
depreciation_amount = asset.get_depreciation_amount(value_after_depreciation,
|
||||
no_of_depreciations, d)
|
||||
|
||||
if depreciation_amount:
|
||||
value_after_depreciation -= flt(depreciation_amount)
|
||||
data.depreciation_amount = depreciation_amount
|
||||
|
||||
d.db_update()
|
||||
|
||||
asset.set_accumulated_depreciation(ignore_booked_entry=True)
|
||||
for asset_data in asset.schedules:
|
||||
if not asset_data.journal_entry:
|
||||
asset_data.db_update()
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_current_asset_value(asset, finance_book):
|
||||
return frappe.db.get_value('Asset Finance Book',
|
||||
{'parent': asset, 'parenttype': 'Asset', 'finance_book': finance_book}, 'value_after_depreciation', debug=1)
|
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Asset Adjustment", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Asset Adjustment
|
||||
() => frappe.tests.make('Asset Adjustment', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestAssetAdjustment(unittest.TestCase):
|
||||
pass
|
@ -40,5 +40,16 @@ frappe.ui.form.on('Asset Category', {
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query('capital_work_in_progress_account', 'accounts', function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
"filters": {
|
||||
"account_type": "Capital Work in Progress",
|
||||
"is_group": 0,
|
||||
"company": d.company_name
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
});
|
@ -43,38 +43,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Straight Line",
|
||||
"fieldname": "depreciation_method",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Depreciation Method",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nStraight Line\nDouble Declining Balance\nManual",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -110,16 +78,16 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_number_of_depreciations",
|
||||
"fieldtype": "Int",
|
||||
"fieldname": "finance_book_detail",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Number of Depreciations",
|
||||
"label": "Finance Book Detail",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -129,7 +97,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -140,18 +108,19 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "frequency_of_depreciation",
|
||||
"fieldtype": "Int",
|
||||
"fieldname": "finance_books",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Frequency of Depreciation (Months)",
|
||||
"label": "Finance Books",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Asset Finance Book",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -159,7 +128,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -236,7 +205,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-01 15:14:25.645077",
|
||||
"modified": "2018-05-12 14:56:04.116425",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Category",
|
||||
@ -312,4 +281,4 @@
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
}
|
@ -10,6 +10,22 @@ from frappe.model.document import Document
|
||||
|
||||
class AssetCategory(Document):
|
||||
def validate(self):
|
||||
for field in ("total_number_of_depreciations", "frequency_of_depreciation"):
|
||||
if cint(self.get(field))<1:
|
||||
frappe.throw(_("{0} must be greater than 0").format(self.meta.get_label(field)), frappe.MandatoryError)
|
||||
for d in self.finance_books:
|
||||
for field in ("Total Number of Depreciations", "Frequency of Depreciation"):
|
||||
if cint(d.get(frappe.scrub(field)))<1:
|
||||
frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_asset_category_account(asset, fieldname, account=None, asset_category = None, company = None):
|
||||
if not asset_category and company:
|
||||
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=fieldname)
|
||||
|
||||
return account
|
@ -17,7 +17,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 3,
|
||||
"columns": 2,
|
||||
"fieldname": "company_name",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -48,7 +48,7 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 3,
|
||||
"columns": 2,
|
||||
"fieldname": "fixed_asset_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@ -135,6 +135,37 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "capital_work_in_progress_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Capital Work In Progress Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
@ -147,7 +178,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-28 16:54:12.252271",
|
||||
"modified": "2018-05-10 17:06:48.839347",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Category Account",
|
||||
|
@ -0,0 +1,289 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-05-08 14:44:37.095570",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fieldname": "finance_book",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Finance Book",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Finance Book",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "depreciation_method",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Depreciation Method",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_number_of_depreciations",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Number of Depreciations",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "frequency_of_depreciation",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Frequency of Depreciation (Months)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:parent.doctype == 'Asset'",
|
||||
"fieldname": "depreciation_start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Depreciation Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.doctype == 'Asset'",
|
||||
"fieldname": "expected_value_after_useful_life",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Expected Value After Useful Life",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "value_after_depreciation",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Value After Depreciation",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-12 14:56:44.800046",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Finance Book",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class AssetFinanceBook(Document):
|
||||
pass
|
@ -42,6 +42,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -73,6 +74,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -104,6 +106,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -135,6 +138,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -164,6 +168,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -195,6 +200,39 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Serial No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "asset_name.serial_no",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -224,6 +262,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -255,6 +294,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -284,6 +324,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -315,6 +356,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -346,6 +388,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -376,6 +419,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
@ -407,6 +451,7 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@ -420,7 +465,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-12-01 15:13:29.816396",
|
||||
"modified": "2018-04-20 08:39:27.072622",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Maintenance",
|
||||
@ -429,7 +474,6 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@ -449,7 +493,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
|
@ -11,6 +11,9 @@ from frappe.utils import add_days, add_months, add_years, getdate, nowdate
|
||||
|
||||
class AssetMaintenance(Document):
|
||||
def validate(self):
|
||||
if not self.serial_no:
|
||||
self.serial_no = frappe.db.get_value("Asset", self.asset_name, 'serial_no')
|
||||
|
||||
for task in self.get('asset_maintenance_tasks'):
|
||||
if task.end_date and (getdate(task.start_date) >= getdate(task.end_date)):
|
||||
throw(_("Start date should be less than end date for task {0}").format(task.maintenance_task))
|
||||
|
@ -12,6 +12,69 @@
|
||||
"document_type": "",
|
||||
"editable_grid": 0,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Transfer",
|
||||
"fieldname": "purpose",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Purpose",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nIssue\nReceipt\nTransfer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -73,37 +136,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -139,7 +171,96 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "source_warehouse",
|
||||
"fieldname": "quantity",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Quantity",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Serial No",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "source_location",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -147,11 +268,194 @@
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Source Warehouse",
|
||||
"in_standard_filter": 0,
|
||||
"label": "Source Location",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"options": "Location",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "target_location",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Target Location",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Location",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "from_employee",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "From Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "to_employee",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "To Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reference",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Reference",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reference_doctype",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Reference DocType",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "DocType",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@ -170,27 +474,27 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "target_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "reference_name",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Target Warehouse",
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Reference Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"no_copy": 1,
|
||||
"options": "reference_doctype",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -236,7 +540,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-10-19 16:08:17.389257",
|
||||
"modified": "2018-05-10 23:16:20.791672",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Movement",
|
||||
|
@ -5,44 +5,60 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
from frappe.model.document import Document
|
||||
|
||||
class AssetMovement(Document):
|
||||
def validate(self):
|
||||
self.validate_asset()
|
||||
self.validate_warehouses()
|
||||
|
||||
|
||||
def validate_asset(self):
|
||||
status, company = frappe.db.get_value("Asset", self.asset, ["status", "company"])
|
||||
if status in ("Draft", "Scrapped", "Sold"):
|
||||
status, company, serial_no = frappe.db.get_value("Asset", self.asset, ["status", "company", "serial_no"])
|
||||
if self.purpose == 'Transfer' and status in ("Draft", "Scrapped", "Sold"):
|
||||
frappe.throw(_("{0} asset cannot be transferred").format(status))
|
||||
|
||||
|
||||
if company != self.company:
|
||||
frappe.throw(_("Asset {0} does not belong to company {1}").format(self.asset, self.company))
|
||||
|
||||
|
||||
if serial_no and not self.serial_no:
|
||||
self.serial_no = serial_no
|
||||
|
||||
if self.serial_no and len(get_serial_nos(self.serial_no)) != self.quantity:
|
||||
frappe.throw(_("Number of serial nos and quantity must be the same"))
|
||||
|
||||
if not(self.source_location or self.target_location or self.from_employee or self.to_employee):
|
||||
frappe.throw(_("Either location or employee must be required"))
|
||||
|
||||
def validate_warehouses(self):
|
||||
if not self.source_warehouse:
|
||||
self.source_warehouse = frappe.db.get_value("Asset", self.asset, "warehouse")
|
||||
|
||||
if self.source_warehouse == self.target_warehouse:
|
||||
frappe.throw(_("Source and Target Warehouse cannot be same"))
|
||||
if self.purpose in ['Transfer', 'Issue']:
|
||||
self.source_location = frappe.db.get_value("Asset", self.asset, "location")
|
||||
|
||||
if self.source_location == self.target_location:
|
||||
frappe.throw(_("Source and Target Location cannot be same"))
|
||||
|
||||
def on_submit(self):
|
||||
self.set_latest_warehouse_in_asset()
|
||||
self.set_latest_location_in_asset()
|
||||
|
||||
def on_cancel(self):
|
||||
self.set_latest_warehouse_in_asset()
|
||||
|
||||
def set_latest_warehouse_in_asset(self):
|
||||
latest_movement_entry = frappe.db.sql("""select target_warehouse from `tabAsset Movement`
|
||||
self.set_latest_location_in_asset()
|
||||
|
||||
def set_latest_location_in_asset(self):
|
||||
latest_movement_entry = frappe.db.sql("""select target_location from `tabAsset Movement`
|
||||
where asset=%s and docstatus=1 and company=%s
|
||||
order by transaction_date desc limit 1""", (self.asset, self.company))
|
||||
|
||||
if latest_movement_entry:
|
||||
warehouse = latest_movement_entry[0][0]
|
||||
location = latest_movement_entry[0][0]
|
||||
else:
|
||||
warehouse = frappe.db.sql("""select source_warehouse from `tabAsset Movement`
|
||||
location = frappe.db.sql("""select source_location from `tabAsset Movement`
|
||||
where asset=%s and docstatus=2 and company=%s
|
||||
order by transaction_date asc limit 1""", (self.asset, self.company))[0][0]
|
||||
|
||||
frappe.db.set_value("Asset", self.asset, "warehouse", warehouse)
|
||||
|
||||
frappe.db.set_value("Asset", self.asset, "location", location)
|
||||
|
||||
if self.serial_no:
|
||||
serial_nos = get_serial_nos(self.serial_no)
|
||||
|
||||
frappe.db.sql(""" update `tabSerial No` set location = %s where name in (%s)"""
|
||||
%('%s', ','.join(['%s'] * len(serial_nos))), (location, tuple(serial_nos)))
|
||||
|
@ -13,6 +13,37 @@
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "finance_book",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Finance Book",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Finance Book",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -196,6 +227,67 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "finance_book_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Finance Book Id",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "depreciation_method",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Depreciation Method",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
@ -208,7 +300,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-10-19 16:30:13.738170",
|
||||
"modified": "2018-05-10 15:12:41.679436",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Depreciation Schedule",
|
||||
|
0
erpnext/assets/doctype/location/__init__.py
Normal file
0
erpnext/assets/doctype/location/__init__.py
Normal file
8
erpnext/assets/doctype/location/location.js
Normal file
8
erpnext/assets/doctype/location/location.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Location', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
306
erpnext/assets/doctype/location/location.json
Normal file
306
erpnext/assets/doctype/location/location.json
Normal file
@ -0,0 +1,306 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:location_name",
|
||||
"beta": 0,
|
||||
"creation": "2018-05-07 12:49:22.595974",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "location_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Location Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_group",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Is Group",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "parent_location",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Parent Location",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Location",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "lft",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "lft",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "rgt",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "old_parent",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Old Parent",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-05-07 19:21:06.051414",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Location",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Stock User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Stock Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
47
erpnext/assets/doctype/location/location.py
Normal file
47
erpnext/assets/doctype/location/location.py
Normal file
@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
|
||||
class Location(NestedSet):
|
||||
def on_update(self):
|
||||
self.update_nsm_model()
|
||||
|
||||
def on_trash(self):
|
||||
self.update_nsm_model()
|
||||
|
||||
def update_nsm_model(self):
|
||||
frappe.utils.nestedset.update_nsm(self)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, location=None, is_root=False):
|
||||
if parent == None or parent == "All Locations":
|
||||
parent = ""
|
||||
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
name as value,
|
||||
is_group as expandable
|
||||
from
|
||||
`tab{doctype}` comp
|
||||
where
|
||||
ifnull(parent_location, "")="{parent}"
|
||||
""".format(
|
||||
doctype = frappe.db.escape(doctype),
|
||||
parent=frappe.db.escape(parent)
|
||||
), as_dict=1)
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_node():
|
||||
from frappe.desk.treeview import make_tree_args
|
||||
args = frappe.form_dict
|
||||
args = make_tree_args(**args)
|
||||
|
||||
if args.parent_location == 'All Locations':
|
||||
args.parent_location = None
|
||||
|
||||
frappe.get_doc(args).insert()
|
28
erpnext/assets/doctype/location/location_tree.js
Normal file
28
erpnext/assets/doctype/location/location_tree.js
Normal file
@ -0,0 +1,28 @@
|
||||
frappe.treeview_settings["Location"] = {
|
||||
ignore_fields:["parent_location"],
|
||||
get_tree_nodes: 'erpnext.assets.doctype.location.location.get_children',
|
||||
add_tree_node: 'erpnext.assets.doctype.location.location.add_node',
|
||||
filters: [
|
||||
{
|
||||
fieldname: "location",
|
||||
fieldtype:"Link",
|
||||
options: "Location",
|
||||
label: __("Location")
|
||||
},
|
||||
],
|
||||
breadcrumb: "Assets",
|
||||
root_label: "All Locations",
|
||||
get_tree_root: false,
|
||||
menu_items: [
|
||||
{
|
||||
label: __("New Location"),
|
||||
action: function() {
|
||||
frappe.new_doc("Location", true);
|
||||
},
|
||||
condition: 'frappe.boot.user.can_create.indexOf("Location") !== -1'
|
||||
}
|
||||
],
|
||||
onload: function(treeview) {
|
||||
treeview.make_tree();
|
||||
}
|
||||
};
|
23
erpnext/assets/doctype/location/test_location.js
Normal file
23
erpnext/assets/doctype/location/test_location.js
Normal file
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Location", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Location
|
||||
() => frappe.tests.make('Location', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
10
erpnext/assets/doctype/location/test_location.py
Normal file
10
erpnext/assets/doctype/location/test_location.py
Normal file
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestLocation(unittest.TestCase):
|
||||
pass
|
@ -10,6 +10,10 @@ def get_data():
|
||||
"type": "doctype",
|
||||
"name": "Asset",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Location",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Asset Category",
|
||||
@ -39,6 +43,10 @@ def get_data():
|
||||
"type": "doctype",
|
||||
"name": "Asset Maintenance Log",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Asset Adjustment",
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Asset Repair",
|
||||
|
@ -273,15 +273,16 @@ class AccountsController(TransactionBase):
|
||||
def get_gl_dict(self, args, account_currency=None):
|
||||
"""this method populates the common properties of a gl entry record"""
|
||||
|
||||
fiscal_years = get_fiscal_years(self.posting_date, company=self.company)
|
||||
posting_date = args.get('posting_date') or self.get('posting_date')
|
||||
fiscal_years = get_fiscal_years(posting_date, company=self.company)
|
||||
if len(fiscal_years) > 1:
|
||||
frappe.throw(_("Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year").format(formatdate(self.posting_date)))
|
||||
frappe.throw(_("Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year").format(formatdate(posting_date)))
|
||||
else:
|
||||
fiscal_year = fiscal_years[0][0]
|
||||
|
||||
gl_dict = frappe._dict({
|
||||
'company': self.company,
|
||||
'posting_date': self.posting_date,
|
||||
'posting_date': posting_date,
|
||||
'fiscal_year': fiscal_year,
|
||||
'voucher_type': self.doctype,
|
||||
'voucher_no': self.name,
|
||||
@ -600,40 +601,36 @@ class AccountsController(TransactionBase):
|
||||
if d.qty > 1:
|
||||
frappe.throw(_("Row #{0}: Qty must be 1, as item is a fixed asset. Please use separate row for multiple qty.").format(d.idx))
|
||||
|
||||
if d.meta.get_field("asset"):
|
||||
if not d.asset:
|
||||
frappe.throw(_("Row #{0}: Asset is mandatory for fixed asset purchase/sale")
|
||||
.format(d.idx))
|
||||
else:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
if d.meta.get_field("asset") and d.asset:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
|
||||
if asset.company != self.company:
|
||||
frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}")
|
||||
.format(d.idx, d.asset, self.company))
|
||||
if asset.company != self.company:
|
||||
frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}")
|
||||
.format(d.idx, d.asset, self.company))
|
||||
|
||||
elif asset.item_code != d.item_code:
|
||||
frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}")
|
||||
.format(d.idx, d.asset, d.item_code))
|
||||
elif asset.item_code != d.item_code:
|
||||
frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}")
|
||||
.format(d.idx, d.asset, d.item_code))
|
||||
|
||||
elif asset.docstatus != 1:
|
||||
frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(d.idx, d.asset))
|
||||
elif asset.docstatus != 1:
|
||||
frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(d.idx, d.asset))
|
||||
|
||||
elif self.doctype == "Purchase Invoice":
|
||||
if asset.status != "Submitted":
|
||||
frappe.throw(_("Row #{0}: Asset {1} is already {2}")
|
||||
.format(d.idx, d.asset, asset.status))
|
||||
elif getdate(asset.purchase_date) != getdate(self.posting_date):
|
||||
frappe.throw(_("Row #{0}: Posting Date must be same as purchase date {1} of asset {2}").format(d.idx, asset.purchase_date, d.asset))
|
||||
elif asset.is_existing_asset:
|
||||
frappe.throw(_("Row #{0}: Purchase Invoice cannot be made against an existing asset {1}").format(d.idx, d.asset))
|
||||
elif self.doctype == "Purchase Invoice":
|
||||
if asset.status != "Submitted":
|
||||
frappe.throw(_("Row #{0}: Asset {1} is already {2}")
|
||||
.format(d.idx, d.asset, asset.status))
|
||||
elif getdate(asset.purchase_date) != getdate(self.posting_date):
|
||||
frappe.throw(_("Row #{0}: Posting Date must be same as purchase date {1} of asset {2}").format(d.idx, asset.purchase_date, d.asset))
|
||||
elif asset.is_existing_asset:
|
||||
frappe.throw(_("Row #{0}: Purchase Invoice cannot be made against an existing asset {1}").format(d.idx, d.asset))
|
||||
|
||||
elif self.docstatus=="Sales Invoice" and self.docstatus == 1:
|
||||
if self.update_stock:
|
||||
frappe.throw(_("'Update Stock' cannot be checked for fixed asset sale"))
|
||||
elif self.docstatus=="Sales Invoice" and self.docstatus == 1:
|
||||
if self.update_stock:
|
||||
frappe.throw(_("'Update Stock' cannot be checked for fixed asset sale"))
|
||||
|
||||
elif asset.status in ("Scrapped", "Cancelled", "Sold"):
|
||||
frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}")
|
||||
.format(d.idx, d.asset, asset.status))
|
||||
elif asset.status in ("Scrapped", "Cancelled", "Sold"):
|
||||
frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}")
|
||||
.format(d.idx, d.asset, asset.status))
|
||||
|
||||
def delink_advance_entries(self, linked_doc_name):
|
||||
total_allocated_amount = 0
|
||||
|
@ -11,6 +11,7 @@ from erpnext.stock.get_item_details import get_conversion_factor
|
||||
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
|
||||
from erpnext.stock.stock_ledger import get_valuation_rate
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import get_used_alternative_items
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_auto_serial_nos, auto_make_serial_nos, get_serial_nos
|
||||
|
||||
from erpnext.controllers.stock_controller import StockController
|
||||
|
||||
@ -78,7 +79,7 @@ class BuyingController(StockController):
|
||||
break
|
||||
|
||||
def validate_stock_or_nonstock_items(self):
|
||||
if self.meta.get_field("taxes") and not self.get_stock_items():
|
||||
if self.meta.get_field("taxes") and not self.get_stock_items() and not self.get_asset_items():
|
||||
tax_for_valuation = [d for d in self.get("taxes")
|
||||
if d.category in ["Valuation", "Valuation and Total"]]
|
||||
|
||||
@ -87,6 +88,12 @@ class BuyingController(StockController):
|
||||
d.category = 'Total'
|
||||
msgprint(_('Tax Category has been changed to "Total" because all the Items are non-stock items'))
|
||||
|
||||
def get_asset_items(self):
|
||||
if self.doctype not in ['Purchase Invoice', 'Purchase Receipt']:
|
||||
return []
|
||||
|
||||
return [d.item_code for d in self.items if d.is_fixed_asset]
|
||||
|
||||
def set_landed_cost_voucher_amount(self):
|
||||
for d in self.get("items"):
|
||||
lc_voucher_data = frappe.db.sql("""select sum(applicable_charges), cost_center
|
||||
@ -111,7 +118,7 @@ class BuyingController(StockController):
|
||||
|
||||
TODO: rename item_tax_amount to valuation_tax_amount
|
||||
"""
|
||||
stock_items = self.get_stock_items()
|
||||
stock_items = self.get_stock_items() + self.get_asset_items()
|
||||
|
||||
stock_items_qty, stock_items_amount = 0, 0
|
||||
last_stock_item_idx = 1
|
||||
@ -439,6 +446,12 @@ class BuyingController(StockController):
|
||||
if self.get('is_return'):
|
||||
return
|
||||
|
||||
if self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
|
||||
field = 'purchase_invoice' if self.doctype == 'Purchase Invoice' else 'purchase_receipt'
|
||||
|
||||
self.process_fixed_asset()
|
||||
self.update_fixed_asset(field)
|
||||
|
||||
update_last_purchase_rate(self, is_submit = 1)
|
||||
|
||||
def on_cancel(self):
|
||||
@ -446,6 +459,133 @@ class BuyingController(StockController):
|
||||
return
|
||||
|
||||
update_last_purchase_rate(self, is_submit = 0)
|
||||
if self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
|
||||
field = 'purchase_invoice' if self.doctype == 'Purchase Invoice' else 'purchase_receipt'
|
||||
|
||||
self.delete_linked_asset()
|
||||
self.update_fixed_asset(field, delete_asset=True)
|
||||
|
||||
def process_fixed_asset(self):
|
||||
if self.doctype == 'Purchase Invoice' and not self.update_stock:
|
||||
return
|
||||
|
||||
asset_items = self.get_asset_items()
|
||||
if asset_items:
|
||||
self.make_serial_nos_for_asset(asset_items)
|
||||
|
||||
def make_serial_nos_for_asset(self, asset_items):
|
||||
items_data = get_asset_item_details(asset_items)
|
||||
|
||||
for d in self.items:
|
||||
if d.is_fixed_asset:
|
||||
item_data = items_data.get(d.item_code)
|
||||
if not d.asset:
|
||||
asset = self.make_asset(d)
|
||||
d.db_set('asset', asset)
|
||||
|
||||
if item_data.get('has_serial_no'):
|
||||
# If item has serial no
|
||||
if item_data.get('serial_no_series') and not d.serial_no:
|
||||
serial_nos = get_auto_serial_nos(item_data.get('serial_no_series'), d.qty)
|
||||
elif d.serial_no:
|
||||
serial_nos = d.serial_no
|
||||
elif not d.serial_no:
|
||||
frappe.throw(_("Serial no is mandatory for the item {0}").format(d.item_code))
|
||||
|
||||
auto_make_serial_nos({
|
||||
'serial_no': serial_nos,
|
||||
'item_code': d.item_code,
|
||||
'via_stock_ledger': False,
|
||||
'company': self.company,
|
||||
'actual_qty': d.qty,
|
||||
'purchase_document_type': self.doctype,
|
||||
'purchase_document_no': self.name,
|
||||
'asset': d.asset
|
||||
})
|
||||
d.db_set('serial_no', serial_nos)
|
||||
|
||||
if d.asset:
|
||||
self.make_asset_movement(d)
|
||||
|
||||
def make_asset(self, row):
|
||||
if not row.asset_location:
|
||||
frappe.throw(_("Row {0}: Enter location for the asset item {1}").format(row.idx, row.item_code))
|
||||
|
||||
item_data = frappe.db.get_value('Item',
|
||||
row.item_code, ['asset_naming_series', 'asset_category'], as_dict=1)
|
||||
|
||||
purchase_amount = flt(row.base_net_amount + row.item_tax_amount)
|
||||
asset = frappe.get_doc({
|
||||
'doctype': 'Asset',
|
||||
'item_code': row.item_code,
|
||||
'asset_name': row.item_name,
|
||||
'status': 'Receipt',
|
||||
'naming_series': item_data.get('asset_naming_series') or 'AST',
|
||||
'asset_category': item_data.get('asset_category'),
|
||||
'location': row.asset_location,
|
||||
'company': self.company,
|
||||
'purchase_date': self.posting_date,
|
||||
'calculate_depreciation': 1,
|
||||
'purchase_receipt_amount': purchase_amount,
|
||||
'gross_purchase_amount': purchase_amount,
|
||||
'purchase_receipt': self.name if self.doctype == 'Purchase Receipt' else None,
|
||||
'purchase_invoice': self.name if self.doctype == 'Purchase Invoice' else None
|
||||
})
|
||||
|
||||
asset.flags.ignore_validate = True
|
||||
asset.flags.ignore_mandatory = True
|
||||
asset.set_missing_values()
|
||||
asset.insert()
|
||||
|
||||
frappe.msgprint(_("Asset {0} created").format(asset.name))
|
||||
return asset.name
|
||||
|
||||
def make_asset_movement(self, row):
|
||||
asset_movement = frappe.get_doc({
|
||||
'doctype': 'Asset Movement',
|
||||
'asset': row.asset,
|
||||
'target_location': row.asset_location,
|
||||
'purpose': 'Receipt',
|
||||
'serial_no': row.serial_no,
|
||||
'quantity': len(get_serial_nos(row.serial_no)),
|
||||
'company': self.company,
|
||||
'transaction_date': self.posting_date,
|
||||
'reference_doctype': self.doctype,
|
||||
'reference_name': self.name
|
||||
}).insert()
|
||||
|
||||
return asset_movement.name
|
||||
|
||||
def update_fixed_asset(self, field, delete_asset = False):
|
||||
for d in self.get("items"):
|
||||
if d.is_fixed_asset and d.asset:
|
||||
asset = frappe.get_doc("Asset", d.asset)
|
||||
|
||||
if delete_asset and asset.docstatus == 0:
|
||||
frappe.delete_doc("Asset", asset.name)
|
||||
d.db_set('asset', None)
|
||||
continue
|
||||
|
||||
if self.docstatus in [0, 1] and not asset.get(field):
|
||||
asset.set(field, self.name)
|
||||
asset.purchase_date = self.posting_date
|
||||
asset.supplier = self.supplier
|
||||
elif self.docstatus == 2:
|
||||
asset.set(field, None)
|
||||
asset.supplier = None
|
||||
|
||||
asset.flags.ignore_validate_update_after_submit = True
|
||||
if asset.docstatus == 0:
|
||||
asset.flags.ignore_validate = True
|
||||
|
||||
asset.save()
|
||||
|
||||
def delete_linked_asset(self):
|
||||
if self.doctype == 'Purchase Invoice' and not self.get('update_stock'):
|
||||
return
|
||||
|
||||
frappe.db.sql("delete from `tabAsset Movement` where reference_name=%s and docstatus = 0", self.name)
|
||||
frappe.db.sql("delete from `tabSerial No` where purchase_document_no=%s", self.name)
|
||||
|
||||
def validate_schedule_date(self):
|
||||
if not self.schedule_date:
|
||||
@ -480,3 +620,11 @@ def get_items_from_bom(item_code, bom, exploded_item=1):
|
||||
msgprint(_("Specified BOM {0} does not exist for Item {1}").format(bom, item_code), raise_exception=1)
|
||||
|
||||
return bom_items
|
||||
|
||||
def get_asset_item_details(asset_items):
|
||||
asset_items_data = {}
|
||||
for d in frappe.get_all('Item', fields = ["name", "has_serial_no", "serial_no_series"],
|
||||
filters = {'name': ('in', asset_items)}):
|
||||
asset_items_data.setdefault(d.name, d)
|
||||
|
||||
return asset_items_data
|
||||
|
@ -234,7 +234,8 @@ scheduler_events = {
|
||||
"erpnext.buying.doctype.supplier_scorecard.supplier_scorecard.refresh_scorecards",
|
||||
"erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history",
|
||||
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
|
||||
"erpnext.assets.doctype.asset.asset.update_maintenance_status"
|
||||
"erpnext.assets.doctype.asset.asset.update_maintenance_status",
|
||||
"erpnext.assets.doctype.asset.asset.make_post_gl_entry"
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -528,3 +528,5 @@ erpnext.patches.v11_0.create_salary_structure_assignments
|
||||
erpnext.patches.v11_0.rename_health_insurance
|
||||
erpnext.patches.v11_0.rebuild_tree_for_company
|
||||
erpnext.patches.v11_0.create_department_records_for_each_company
|
||||
erpnext.patches.v11_0.make_location_from_warehouse
|
||||
erpnext.patches.v11_0.make_asset_finance_book_against_old_entries
|
@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils.nestedset import rebuild_tree
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('assets', 'doctype', 'asset_finance_book')
|
||||
frappe.reload_doc('assets', 'doctype', 'depreciation_schedule')
|
||||
frappe.reload_doc('assets', 'doctype', 'asset_category')
|
||||
frappe.reload_doc('assets', 'doctype', 'asset')
|
||||
frappe.reload_doc('assets', 'doctype', 'asset_movement')
|
||||
|
||||
frappe.db.sql(""" update `tabAsset` ast, `tabWarehouse` wh
|
||||
set ast.location = wh.warehouse_name where ast.warehouse = wh.name""")
|
||||
|
||||
frappe.db.sql(""" update `tabAsset Movement` ast_mv
|
||||
set ast_mv.source_location = (select warehouse_name from `tabWarehouse` where name = ast_mv.source_warehouse),
|
||||
ast_mv.target_location = (select warehouse_name from `tabWarehouse` where name = ast_mv.target_warehouse)""")
|
||||
|
||||
for d in frappe.get_all('Asset'):
|
||||
doc = frappe.get_doc('Asset', d.name)
|
||||
if doc.calculate_depreciation:
|
||||
fb = doc.append('finance_books', {
|
||||
'depreciation_method': doc.depreciation_method,
|
||||
'total_number_of_depreciations': doc.total_number_of_depreciations,
|
||||
'frequency_of_depreciation': doc.frequency_of_depreciation,
|
||||
'depreciation_start_date': doc.next_depreciation_date,
|
||||
'expected_value_after_useful_life': doc.expected_value_after_useful_life,
|
||||
'value_after_depreciation': doc.value_after_depreciation
|
||||
})
|
||||
|
||||
fb.db_update()
|
||||
|
||||
frappe.db.sql(""" update `tabDepreciation Schedule` ds, `tabAsset` ast
|
||||
set ds.depreciation_method = ast.depreciation_method, ds.finance_book_id = 1 where ds.parent = ast.name """)
|
||||
|
||||
for catergory in frappe.get_all('Asset Category'):
|
||||
asset_category_doc = frappe.get_doc("Asset Category", catergory)
|
||||
row = asset_category_doc.append('finance_books', {
|
||||
'depreciation_method': asset_category_doc.depreciation_method,
|
||||
'total_number_of_depreciations': asset_category_doc.total_number_of_depreciations,
|
||||
'frequency_of_depreciation': asset_category_doc.frequency_of_depreciation
|
||||
})
|
||||
|
||||
row.db_update()
|
30
erpnext/patches/v11_0/make_location_from_warehouse.py
Normal file
30
erpnext/patches/v11_0/make_location_from_warehouse.py
Normal file
@ -0,0 +1,30 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils.nestedset import rebuild_tree
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('assets', 'doctype', 'location')
|
||||
frappe.reload_doc('stock', 'doctype', 'warehouse')
|
||||
|
||||
for d in frappe.get_all('Warehouse',
|
||||
fields = ['warehouse_name', 'is_group', 'parent_warehouse'], order_by="is_group desc"):
|
||||
try:
|
||||
loc = frappe.new_doc('Location')
|
||||
loc.location_name = d.warehouse_name
|
||||
loc.is_group = d.is_group
|
||||
loc.flags.ignore_mandatory = True
|
||||
if d.parent_warehouse:
|
||||
loc.parent_location = get_parent_warehouse_name(d.parent_warehouse)
|
||||
|
||||
loc.save(ignore_permissions=True)
|
||||
except frappe.DuplicateEntryError:
|
||||
continue
|
||||
|
||||
rebuild_tree("Location", "parent_location")
|
||||
|
||||
def get_parent_warehouse_name(warehouse):
|
||||
return frappe.db.get_value('Warehouse', warehouse, 'warehouse_name')
|
||||
|
@ -207,6 +207,9 @@ erpnext.company.setup_queries = function(frm) {
|
||||
["round_off_cost_center", {}],
|
||||
["depreciation_cost_center", {}],
|
||||
["default_employee_advance_account", {"root_type": "Asset"}],
|
||||
["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
|
||||
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
|
||||
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}]
|
||||
], function(i, v) {
|
||||
erpnext.company.set_custom_query(frm, v);
|
||||
});
|
||||
|
@ -1785,6 +1785,38 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "expenses_included_in_asset_valuation",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Expenses Included In Asset Valuation",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1879,6 +1911,70 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "capital_work_in_progress_account",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Capital Work In Progress Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "asset_received_but_not_billed",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset Received But Not Billed",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -2400,7 +2496,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2018-05-05 13:08:07.351655",
|
||||
"modified": "2018-05-07 15:35:06.736602",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Company",
|
||||
|
@ -168,6 +168,9 @@ class Company(NestedSet):
|
||||
self._set_default_account("round_off_account", "Round Off")
|
||||
self._set_default_account("accumulated_depreciation_account", "Accumulated Depreciation")
|
||||
self._set_default_account("depreciation_expense_account", "Depreciation")
|
||||
self._set_default_account("capital_work_in_progress_account", "Capital Work in Progress")
|
||||
self._set_default_account("asset_received_but_not_billed", "Asset Received But Not Billed")
|
||||
self._set_default_account("expenses_included_in_asset_valuation", "Expenses Included In Asset Valuation")
|
||||
|
||||
if self.enable_perpetual_inventory:
|
||||
self._set_default_account("stock_received_but_not_billed", "Stock Received But Not Billed")
|
||||
|
@ -19,7 +19,9 @@ frappe.ui.form.on("Item", {
|
||||
|
||||
// should never check Private
|
||||
frm.fields_dict["website_image"].df.is_private = 0;
|
||||
|
||||
if (frm.doc.is_fixed_asset) {
|
||||
frm.trigger("set_asset_naming_series");
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
@ -124,7 +126,20 @@ frappe.ui.form.on("Item", {
|
||||
},
|
||||
|
||||
is_fixed_asset: function(frm) {
|
||||
frm.set_value("is_stock_item", frm.doc.is_fixed_asset ? 0 : 1);
|
||||
frm.call({
|
||||
method: "set_asset_naming_series",
|
||||
doc: frm.doc,
|
||||
callback: function() {
|
||||
frm.set_value("is_stock_item", frm.doc.is_fixed_asset ? 0 : 1);
|
||||
frm.trigger("set_asset_naming_series");
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
set_asset_naming_series: function(frm) {
|
||||
if (frm.doc.__onload && frm.doc.__onload.asset_naming_series) {
|
||||
frm.set_df_property("asset_naming_series", "options", frm.doc.__onload.asset_naming_series);
|
||||
}
|
||||
},
|
||||
|
||||
page_name: frappe.utils.warn_page_name_change,
|
||||
|
@ -395,7 +395,7 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
@ -559,6 +559,38 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "is_fixed_asset",
|
||||
"fieldname": "asset_naming_series",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset Naming Series",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1285,7 +1317,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.has_batch_no || doc.has_serial_no",
|
||||
"columns": 0,
|
||||
"depends_on": "is_stock_item",
|
||||
"depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset",
|
||||
"fieldname": "serial_nos_and_batches",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@ -1513,7 +1545,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"depends_on": "eval:doc.is_stock_item",
|
||||
"depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset",
|
||||
"description": "",
|
||||
"fieldname": "has_serial_no",
|
||||
"fieldtype": "Check",
|
||||
@ -3717,7 +3749,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 1,
|
||||
"modified": "2018-04-30 12:21:48.715529",
|
||||
"modified": "2018-05-07 14:54:24.479267",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Item",
|
||||
@ -3725,7 +3757,6 @@
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
@ -3745,7 +3776,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -3765,7 +3795,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -3785,7 +3814,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -3805,7 +3833,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -3825,7 +3852,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -3845,7 +3871,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
@ -3865,7 +3890,6 @@
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
|
@ -16,6 +16,7 @@ from frappe.utils import (cint, cstr, flt, formatdate, get_timestamp, getdate,
|
||||
from frappe.utils.html_utils import clean_html
|
||||
from frappe.website.doctype.website_slideshow.website_slideshow import \
|
||||
get_slideshow
|
||||
|
||||
from frappe.website.render import clear_cache
|
||||
from frappe.website.website_generator import WebsiteGenerator
|
||||
|
||||
@ -42,10 +43,18 @@ class Item(WebsiteGenerator):
|
||||
super(Item, self).onload()
|
||||
|
||||
self.set_onload('stock_exists', self.stock_ledger_created())
|
||||
self.set_asset_naming_series()
|
||||
if self.is_fixed_asset:
|
||||
asset = frappe.db.get_all("Asset", filters={"item_code": self.name, "docstatus": 1}, limit=1)
|
||||
self.set_onload("asset_exists", True if asset else False)
|
||||
|
||||
def set_asset_naming_series(self):
|
||||
if not hasattr(self, '_asset_naming_series'):
|
||||
from erpnext.assets.doctype.asset.asset import get_asset_naming_series
|
||||
self._asset_naming_series = get_asset_naming_series()
|
||||
|
||||
self.set_onload('asset_naming_series', self._asset_naming_series)
|
||||
|
||||
def autoname(self):
|
||||
if frappe.db.get_default("item_naming_by") == "Naming Series":
|
||||
if self.variant_of:
|
||||
@ -444,7 +453,7 @@ class Item(WebsiteGenerator):
|
||||
_("Conversion factor for default Unit of Measure must be 1 in row {0}").format(d.idx))
|
||||
|
||||
def validate_item_type(self):
|
||||
if self.has_serial_no == 1 and self.is_stock_item == 0:
|
||||
if self.has_serial_no == 1 and self.is_stock_item == 0 and not self.is_fixed_asset:
|
||||
msgprint(_("'Has Serial No' can not be 'Yes' for non-stock item"), raise_exception=1)
|
||||
|
||||
if self.has_serial_no == 0 and self.serial_no_series:
|
||||
|
@ -65,6 +65,20 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
if (erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
|
||||
this.show_general_ledger();
|
||||
}
|
||||
|
||||
this.frm.add_custom_button(__('Asset'), function() {
|
||||
frappe.route_options = {
|
||||
purchase_receipt: me.frm.doc.name,
|
||||
};
|
||||
frappe.set_route("List", "Asset");
|
||||
}, __("View"));
|
||||
|
||||
this.frm.add_custom_button(__('Asset Movement'), function() {
|
||||
frappe.route_options = {
|
||||
reference_name: me.frm.doc.name,
|
||||
};
|
||||
frappe.set_route("List", "Asset Movement");
|
||||
}, __("View"));
|
||||
}
|
||||
|
||||
if(!this.frm.doc.is_return && this.frm.doc.status!="Closed") {
|
||||
|
@ -13,6 +13,7 @@ from erpnext.controllers.buying_controller import BuyingController
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
from frappe.desk.notifications import clear_doctype_notifications
|
||||
from erpnext.buying.utils import check_for_closed_status
|
||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||
|
||||
form_grid_templates = {
|
||||
"items": "templates/form_grid/item_grid.html"
|
||||
@ -253,6 +254,40 @@ class PurchaseReceipt(BuyingController):
|
||||
d.rejected_warehouse not in warehouse_with_no_account:
|
||||
warehouse_with_no_account.append(d.warehouse)
|
||||
|
||||
elif d.is_fixed_asset:
|
||||
asset_accounts = self.get_company_default(["capital_work_in_progress_account",
|
||||
"asset_received_but_not_billed"])
|
||||
|
||||
# CWIP entry
|
||||
cwip_account = get_asset_category_account(d.asset,
|
||||
'capital_work_in_progress_account') or asset_accounts[0]
|
||||
|
||||
asset_amount = flt(d.net_amount) + flt(d.item_tax_amount/self.conversion_rate)
|
||||
base_asset_amount = flt(d.base_net_amount + d.item_tax_amount)
|
||||
|
||||
cwip_account_currency = get_account_currency(cwip_account)
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": cwip_account,
|
||||
"against": asset_accounts[1],
|
||||
"cost_center": d.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"debit": base_asset_amount,
|
||||
"debit_in_account_currency": (base_asset_amount
|
||||
if cwip_account_currency == self.company_currency else asset_amount)
|
||||
}))
|
||||
|
||||
# Asset received but not billed
|
||||
asset_rbnb_currency = get_account_currency(asset_accounts[1])
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": asset_accounts[1],
|
||||
"against": asset_accounts[0],
|
||||
"cost_center": d.cost_center,
|
||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||
"credit": base_asset_amount,
|
||||
"credit_in_account_currency": (base_asset_amount
|
||||
if asset_rbnb_currency == self.company_currency else asset_amount)
|
||||
}))
|
||||
|
||||
# Cost center-wise amount breakup for other charges included for valuation
|
||||
valuation_tax = {}
|
||||
for tax in self.get("taxes"):
|
||||
@ -393,6 +428,8 @@ def make_purchase_invoice(source_name, target_doc=None):
|
||||
"parent": "purchase_receipt",
|
||||
"purchase_order_item": "po_detail",
|
||||
"purchase_order": "purchase_order",
|
||||
"is_fixed_asset": "is_fixed_asset",
|
||||
"asset": "asset",
|
||||
},
|
||||
"postprocess": update_item,
|
||||
"filter": lambda d: abs(d.qty) - abs(invoiced_qty_map.get(d.name, 0))<=0
|
||||
|
@ -5,6 +5,7 @@ def get_data():
|
||||
'fieldname': 'purchase_receipt_no',
|
||||
'non_standard_fieldnames': {
|
||||
'Purchase Invoice': 'purchase_receipt',
|
||||
'Asset': 'purchase_receipt',
|
||||
'Landed Cost Voucher': 'receipt_document',
|
||||
'Subscription': 'reference_document'
|
||||
},
|
||||
@ -16,7 +17,7 @@ def get_data():
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Related'),
|
||||
'items': ['Purchase Invoice', 'Landed Cost Voucher']
|
||||
'items': ['Purchase Invoice', 'Landed Cost Voucher', 'Asset']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
|
@ -289,13 +289,53 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
serial_no=serial_no, basic_rate=100, do_not_submit=True)
|
||||
self.assertRaises(SerialNoDuplicateError, se.submit)
|
||||
|
||||
def test_serialized_asset_item(self):
|
||||
asset_item = "Test Serialized Asset Item"
|
||||
|
||||
if not frappe.db.exists('Item', asset_item):
|
||||
asset_category = frappe.get_all('Asset Category')
|
||||
|
||||
if asset_category:
|
||||
asset_category = asset_category[0].name
|
||||
|
||||
if not asset_category:
|
||||
doc = frappe.get_doc({
|
||||
'doctype': 'Asset Category',
|
||||
'asset_category_name': 'Test Asset Category',
|
||||
'depreciation_method': 'Straight Line',
|
||||
'total_number_of_depreciations': 12,
|
||||
'frequency_of_depreciation': 1,
|
||||
'accounts': [{
|
||||
'company_name': '_Test Company',
|
||||
'fixed_asset_account': '_Test Fixed Asset - _TC',
|
||||
'accumulated_depreciation_account': 'Depreciation - _TC',
|
||||
'depreciation_expense_account': 'Depreciation - _TC'
|
||||
}]
|
||||
}).insert()
|
||||
|
||||
asset_category = doc.name
|
||||
|
||||
asset_item = make_item(asset_item, {'is_stock_item':0,
|
||||
'stock_uom': 'Box', 'is_fixed_asset': 1, 'has_serial_no': 1,
|
||||
'asset_category': asset_category, 'serial_no_series': 'ABC.###'})
|
||||
|
||||
pr = make_purchase_receipt(item_code=asset_item, qty=3)
|
||||
asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name}, 'name')
|
||||
asset_movement = frappe.db.get_value('Asset Movement', {'reference_name': pr.name}, 'name')
|
||||
serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name')
|
||||
|
||||
self.assertEquals(len(serial_nos), 3)
|
||||
pr.cancel()
|
||||
serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or []
|
||||
self.assertEquals(len(serial_nos), 0)
|
||||
frappe.db.sql("delete from `tabAsset Category`")
|
||||
frappe.db.sql("delete from `tabAsset`")
|
||||
|
||||
def get_gl_entries(voucher_type, voucher_no):
|
||||
return frappe.db.sql("""select account, debit, credit
|
||||
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
|
||||
order by account desc""", (voucher_type, voucher_no), as_dict=1)
|
||||
|
||||
|
||||
def make_purchase_receipt(**args):
|
||||
frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1)
|
||||
pr = frappe.new_doc("Purchase Receipt")
|
||||
|
@ -1577,6 +1577,103 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "is_fixed_asset",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Is Fixed Asset",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "is_fixed_asset",
|
||||
"fieldname": "asset",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Asset",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "is_fixed_asset",
|
||||
"fieldname": "asset_location",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset Location",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Location",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -2395,7 +2492,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-02-22 15:15:38.793425",
|
||||
"modified": "2018-05-07 13:42:05.061386",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt Item",
|
||||
|
@ -619,6 +619,190 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "asset_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset Details",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "asset",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"options": "Asset",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "asset",
|
||||
"fieldname": "asset_status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Asset Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nIssue\nReceipt\nTransfer",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_24",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "location",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Location",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Location",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "employee",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Employee",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1270,7 +1454,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-05-15 18:22:23.685286",
|
||||
"modified": "2018-05-10 23:38:20.646770",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Serial No",
|
||||
|
@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
from frappe.model.naming import make_autoname
|
||||
from frappe.utils import cint, cstr, flt, add_days, nowdate, getdate
|
||||
from frappe import _, ValidationError
|
||||
|
||||
@ -276,24 +277,31 @@ def allow_serial_nos_with_different_item(sle_serial_no, sle):
|
||||
def update_serial_nos(sle, item_det):
|
||||
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
|
||||
and item_det.has_serial_no == 1 and item_det.serial_no_series:
|
||||
from frappe.model.naming import make_autoname
|
||||
serial_nos = []
|
||||
for i in range(cint(sle.actual_qty)):
|
||||
serial_nos.append(make_autoname(item_det.serial_no_series, "Serial No"))
|
||||
frappe.db.set(sle, "serial_no", "\n".join(serial_nos))
|
||||
serial_nos = get_auto_serial_nos(item_det.serial_no_series, sle.actual_qty)
|
||||
frappe.db.set(sle, "serial_no", serial_nos)
|
||||
validate_serial_no(sle, item_det)
|
||||
|
||||
if sle.serial_no:
|
||||
serial_nos = get_serial_nos(sle.serial_no)
|
||||
for serial_no in serial_nos:
|
||||
if frappe.db.exists("Serial No", serial_no):
|
||||
sr = frappe.get_doc("Serial No", serial_no)
|
||||
sr.via_stock_ledger = True
|
||||
sr.item_code = sle.item_code
|
||||
sr.warehouse = sle.warehouse if sle.actual_qty > 0 else None
|
||||
sr.save(ignore_permissions=True)
|
||||
elif sle.actual_qty > 0:
|
||||
make_serial_no(serial_no, sle)
|
||||
auto_make_serial_nos(sle)
|
||||
|
||||
def get_auto_serial_nos(serial_no_series, qty):
|
||||
serial_nos = []
|
||||
for i in range(cint(qty)):
|
||||
serial_nos.append(make_autoname(serial_no_series, "Serial No"))
|
||||
|
||||
return "\n".join(serial_nos)
|
||||
|
||||
def auto_make_serial_nos(args):
|
||||
serial_nos = get_serial_nos(args.get('serial_no'))
|
||||
for serial_no in serial_nos:
|
||||
if frappe.db.exists("Serial No", serial_no):
|
||||
sr = frappe.get_doc("Serial No", serial_no)
|
||||
sr.via_stock_ledger = True
|
||||
sr.item_code = args.get('item_code')
|
||||
sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None
|
||||
sr.save(ignore_permissions=True)
|
||||
elif args.get('actual_qty', 0) > 0:
|
||||
make_serial_no(serial_no, args)
|
||||
|
||||
def get_item_details(item_code):
|
||||
return frappe.db.sql("""select name, has_batch_no, docstatus,
|
||||
@ -304,20 +312,27 @@ def get_serial_nos(serial_no):
|
||||
return [s.strip() for s in cstr(serial_no).strip().upper().replace(',', '\n').split('\n')
|
||||
if s.strip()]
|
||||
|
||||
def make_serial_no(serial_no, sle):
|
||||
def make_serial_no(serial_no, args):
|
||||
sr = frappe.new_doc("Serial No")
|
||||
sr.warehouse = None
|
||||
sr.dont_update_if_missing.append("warehouse")
|
||||
sr.flags.ignore_permissions = True
|
||||
|
||||
sr.serial_no = serial_no
|
||||
sr.item_code = sle.item_code
|
||||
sr.company = sle.company
|
||||
sr.via_stock_ledger = True
|
||||
sr.insert()
|
||||
sr.item_code = args.get('item_code')
|
||||
sr.company = args.get('company')
|
||||
sr.via_stock_ledger = args.get('via_stock_ledger') or True
|
||||
sr.asset = args.get('asset')
|
||||
|
||||
if args.get('purchase_document_type'):
|
||||
sr.purchase_document_type = args.get('purchase_document_type')
|
||||
sr.purchase_document_no = args.get('purchase_document_no')
|
||||
|
||||
sr.insert()
|
||||
if args.get('warehouse'):
|
||||
sr.warehouse = args.get('warehouse')
|
||||
sr.save()
|
||||
|
||||
sr.warehouse = sle.warehouse
|
||||
sr.save()
|
||||
frappe.msgprint(_("Serial No {0} created").format(sr.name))
|
||||
return sr.name
|
||||
|
||||
|
23
erpnext/stock/doctype/serial_no/test_serial_no.js
Normal file
23
erpnext/stock/doctype/serial_no/test_serial_no.js
Normal file
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Serial No", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Serial No
|
||||
() => frappe.tests.make('Serial No', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user