Asset linked to purchase receipt and serial no

This commit is contained in:
Rohit Waghchaure 2018-04-26 19:18:29 +05:30
parent 17aec2d16c
commit ab84254188
23 changed files with 763 additions and 105 deletions

View File

@ -305,24 +305,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
@ -636,7 +620,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)

View File

@ -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",

View File

@ -181,7 +181,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) {

View File

@ -40,6 +40,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -71,6 +72,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -102,6 +104,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -133,6 +136,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -165,6 +169,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -196,6 +201,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -228,6 +234,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -260,6 +267,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -292,6 +300,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -322,6 +331,38 @@
"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": "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": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -351,6 +392,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -382,6 +424,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -413,6 +456,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -444,6 +488,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -474,6 +519,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": "purchase_receipt",
"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": "Purchase Receipt",
"length": 0,
"no_copy": 1,
"options": "Purchase Receipt",
"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
},
{
@ -505,6 +583,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -535,6 +614,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -565,6 +645,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -595,6 +676,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -626,6 +708,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -655,6 +738,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -686,6 +770,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -715,6 +800,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -747,6 +833,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -779,6 +866,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -808,6 +896,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -838,6 +927,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -869,6 +959,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -902,6 +993,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -933,6 +1025,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -963,6 +1056,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -992,6 +1086,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1023,6 +1118,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1053,6 +1149,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1084,6 +1181,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1115,6 +1213,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1146,6 +1245,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1176,6 +1276,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1207,6 +1308,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1237,6 +1339,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@ -1251,7 +1354,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-01-05 09:53:05.945328",
"modified": "2018-04-19 20:03:13.669957",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
@ -1260,7 +1363,6 @@
"permissions": [
{
"amend": 1,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
@ -1280,7 +1382,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
@ -1307,4 +1408,4 @@
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
}
}

View File

@ -10,6 +10,7 @@ from frappe.model.document import Document
from erpnext.accounts.doctype.purchase_invoice.purchase_invoice import get_fixed_asset_account
from erpnext.assets.doctype.asset.depreciation \
import get_disposal_account_and_cost_center, get_depreciation_accounts
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
class Asset(Document):
def validate(self):
@ -26,12 +27,16 @@ class Asset(Document):
def on_submit(self):
self.set_status()
self.update_stock_movement()
def on_cancel(self):
self.validate_cancellation()
self.delete_depreciation_entries()
self.set_status()
def on_update(self):
self.update_serial_nos()
def validate_item(self):
item = frappe.db.get_value("Item", self.item_code,
["is_fixed_asset", "is_stock_item", "disabled"], as_dict=1)
@ -219,6 +224,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:
@ -250,6 +258,20 @@ class Asset(Document):
status = "Cancelled"
return status
def update_serial_nos(self):
if self.serial_no:
serial_nos = get_serial_nos(self.serial_no)
frappe.db.sql(""" update `tabSerial No` set asset = '%s' where
name in(%s)"""%(self.name, ','.join(['%s'] * len(serial_nos))), tuple(serial_nos))
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 update_maintenance_status():
assets = frappe.get_all('Asset', filters = {'docstatus': 1, 'maintenance_required': 1})
@ -280,7 +302,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):
si = frappe.new_doc("Sales Invoice")
si.company = company
si.currency = frappe.db.get_value("Company", company, "default_currency")
@ -290,6 +312,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
})

View File

@ -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']
}
]
}

View File

@ -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,

View File

@ -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))

View File

@ -12,6 +12,39 @@
"document_type": "",
"editable_grid": 0,
"fields": [
{
"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": "Receipt\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": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@ -41,6 +74,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -71,6 +105,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -102,6 +137,38 @@
"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,
"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
},
{
@ -131,6 +198,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -162,6 +230,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -193,6 +262,102 @@
"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": "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,
"translatable": 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,
"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": "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": 0,
"in_standard_filter": 0,
"label": "Reference Name",
"length": 0,
"no_copy": 1,
"options": "reference_doctype",
"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
},
{
@ -223,6 +388,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@ -236,7 +402,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-10-19 16:08:17.389257",
"modified": "2018-04-20 15:45:54.156501",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Movement",
@ -245,7 +411,6 @@
"permissions": [
{
"amend": 1,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
@ -265,7 +430,6 @@
},
{
"amend": 1,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
@ -285,7 +449,6 @@
},
{
"amend": 1,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,

View File

@ -11,19 +11,22 @@ 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
def validate_warehouses(self):
if not self.source_warehouse:
if self.purpose == 'Transfer' and 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"))

View File

@ -600,40 +600,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

View File

@ -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
from erpnext.controllers.stock_controller import StockController
@ -439,6 +440,11 @@ class BuyingController(StockController):
if self.get('is_return'):
return
if self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
if self.doctype == 'Purchase Receipt':
self.process_fixed_asset()
self.update_fixed_asset()
update_last_purchase_rate(self, is_submit = 1)
def on_cancel(self):
@ -446,6 +452,118 @@ class BuyingController(StockController):
return
update_last_purchase_rate(self, is_submit = 0)
if self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
if self.doctype == 'Purchase Receipt':
self.delete_linked_asset()
self.update_fixed_asset()
def process_fixed_asset(self):
if not self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
return
asset_items = [d.item_code for d in self.items if d.is_fixed_asset]
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 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
})
d.db_set('serial_no', serial_nos)
if not d.asset:
asset = self.make_asset(d)
d.db_set('asset', asset)
if d.asset:
self.make_asset_movement(d)
def make_asset(self, row):
asset = frappe.get_doc({
'doctype': 'Asset',
'item_code': row.item_code,
'asset_name': '{0} - {1}'.format(self.name, row.item_code),
'warehouse': row.warehouse,
'serial_no': row.serial_no,
'company': self.company,
'purchase_date': self.posting_date,
'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.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,
'source_warehouse': '',
'target_warehouse': row.warehouse,
'purpose': 'Receipt',
'serial_no': 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 = 'purchase_invoice' if self.doctype == 'Purchase Invoice' else 'purchase_receipt'
for d in self.get("items"):
if d.is_fixed_asset and d.asset:
asset = frappe.get_doc("Asset", d.asset)
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
else:
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 not self.doctype in ['Purchase Receipt', 'Purchase Invoice']:
return
if self.doctype == 'Purchase Invoice' and 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 +598,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

View File

@ -5,6 +5,14 @@ frappe.provide("erpnext.company");
frappe.ui.form.on("Company", {
setup: function(frm) {
frm.fields_dict.fixed_asset_account.get_query = function() {
return {
filters: {
account_type: "Fixed Asset",
company: frm.doc.name
}
}
}
erpnext.company.setup_queries(frm);
},

View File

@ -1285,7 +1285,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 +1513,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",
@ -3725,7 +3725,6 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@ -3745,7 +3744,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -3765,7 +3763,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -3785,7 +3782,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -3805,7 +3801,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -3825,7 +3820,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -3845,7 +3839,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -3865,7 +3858,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,

View File

@ -444,7 +444,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:

View File

@ -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") {

View File

@ -393,6 +393,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

View File

@ -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'),

View File

@ -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")

View File

@ -1577,6 +1577,70 @@
"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,
@ -2395,7 +2459,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-02-22 15:15:38.793425",
"modified": "2018-04-23 14:07:48.438379",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",

View File

@ -41,6 +41,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -69,6 +70,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -100,6 +102,7 @@
"reqd": 1,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -132,6 +135,7 @@
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -165,6 +169,39 @@
"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": "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,
"translatable": 0,
"unique": 0
},
{
@ -193,6 +230,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -222,6 +260,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -253,6 +292,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "300px"
},
@ -287,6 +327,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -319,6 +360,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -348,6 +390,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,
"width": "50%"
},
@ -407,6 +451,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -437,6 +482,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -468,6 +514,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -497,6 +544,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -529,6 +577,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -557,6 +606,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "50%"
},
@ -588,6 +638,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -617,6 +668,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -647,6 +699,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -677,6 +730,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -707,6 +761,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -738,6 +793,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -767,6 +823,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -799,6 +856,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -827,6 +885,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "50%"
},
@ -860,6 +919,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -891,6 +951,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -921,6 +982,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -952,6 +1014,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -981,6 +1044,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1009,6 +1073,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "50%"
},
@ -1042,6 +1107,7 @@
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
@ -1074,6 +1140,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
@ -1103,6 +1170,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "50%"
},
@ -1135,6 +1203,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
@ -1167,6 +1236,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "150px"
},
@ -1197,6 +1267,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1226,6 +1297,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
@ -1256,6 +1328,7 @@
"reqd": 1,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
@ -1270,7 +1343,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-05-15 18:22:23.685286",
"modified": "2018-04-19 20:25:52.066995",
"modified_by": "Administrator",
"module": "Stock",
"name": "Serial No",
@ -1278,7 +1351,6 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@ -1298,7 +1370,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
@ -1318,7 +1389,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,

View File

@ -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,26 @@ 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.item_code = args.get('item_code')
sr.company = args.get('company')
sr.via_stock_ledger = args.get('via_stock_ledger') or True
sr.insert()
sr.warehouse = sle.warehouse
sr.save()
if args.get('purchase_document_type'):
sr.purchase_document_type = args.get('purchase_document_type')
sr.purchase_document_no = args.get('purchase_document_no')
if args.get('warehouse'):
sr.warehouse = args.get('warehouse')
sr.save()
frappe.msgprint(_("Serial No {0} created").format(sr.name))
return sr.name

View File

@ -287,6 +287,10 @@ def get_default_income_account(args, item):
or frappe.db.get_value("Item Group", item.item_group, "default_income_account"))
def get_default_expense_account(args, item):
if item and item.is_fixed_asset:
return frappe.db.get_value("Company", args.company, "fixed_asset_account")
if account: return account
return (item.expense_account
or args.expense_account
or frappe.db.get_value("Item Group", item.item_group, "default_expense_account"))