Merge branch 'hotfix'
This commit is contained in:
commit
65652071ff
@ -5,7 +5,7 @@ import frappe
|
|||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
__version__ = '10.1.54'
|
__version__ = '10.1.55'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
|||||||
@ -388,16 +388,20 @@ class PurchaseInvoice(BuyingController):
|
|||||||
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
||||||
warehouse_account = get_warehouse_account_map()
|
warehouse_account = get_warehouse_account_map()
|
||||||
|
|
||||||
|
voucher_wise_stock_value = {}
|
||||||
|
if self.update_stock:
|
||||||
|
for d in frappe.get_all('Stock Ledger Entry',
|
||||||
|
fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
|
||||||
|
voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
|
||||||
|
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if flt(item.base_net_amount):
|
if flt(item.base_net_amount):
|
||||||
account_currency = get_account_currency(item.expense_account)
|
account_currency = get_account_currency(item.expense_account)
|
||||||
|
|
||||||
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
|
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
|
||||||
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
|
|
||||||
|
|
||||||
# warehouse account
|
# warehouse account
|
||||||
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
|
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
|
||||||
* flt(item.qty) * flt(item.conversion_factor), item.precision("base_net_amount"))
|
item, voucher_wise_stock_value, account_currency)
|
||||||
|
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
@ -469,6 +473,36 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
|
self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
|
||||||
item.precision("item_tax_amount"))
|
item.precision("item_tax_amount"))
|
||||||
|
|
||||||
|
def make_stock_adjustment_entry(self, gl_entries, item, voucher_wise_stock_value, account_currency):
|
||||||
|
net_amt_precision = item.precision("base_net_amount")
|
||||||
|
val_rate_db_precision = 6 if cint(item.precision("valuation_rate")) <= 6 else 9
|
||||||
|
|
||||||
|
warehouse_debit_amount = flt(flt(item.valuation_rate, val_rate_db_precision)
|
||||||
|
* flt(item.qty) * flt(item.conversion_factor), net_amt_precision)
|
||||||
|
|
||||||
|
# Stock ledger value is not matching with the warehouse amount
|
||||||
|
if (self.update_stock and voucher_wise_stock_value.get(item.name) and
|
||||||
|
warehouse_debit_amount != flt(voucher_wise_stock_value.get(item.name), net_amt_precision)):
|
||||||
|
|
||||||
|
cost_of_goods_sold_account = self.get_company_default("default_expense_account")
|
||||||
|
stock_amount = flt(voucher_wise_stock_value.get(item.name), net_amt_precision)
|
||||||
|
stock_adjustment_amt = warehouse_debit_amount - stock_amount
|
||||||
|
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": cost_of_goods_sold_account,
|
||||||
|
"against": item.expense_account,
|
||||||
|
"debit": stock_adjustment_amt,
|
||||||
|
"remarks": self.get("remarks") or _("Stock Adjustment"),
|
||||||
|
"cost_center": item.cost_center,
|
||||||
|
"project": item.project
|
||||||
|
}, account_currency)
|
||||||
|
)
|
||||||
|
|
||||||
|
warehouse_debit_amount = stock_amount
|
||||||
|
|
||||||
|
return warehouse_debit_amount
|
||||||
|
|
||||||
def make_tax_gl_entries(self, gl_entries):
|
def make_tax_gl_entries(self, gl_entries):
|
||||||
# tax table gl entries
|
# tax table gl entries
|
||||||
valuation_tax = {}
|
valuation_tax = {}
|
||||||
|
|||||||
@ -3,47 +3,75 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe.utils import flt
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
columns, data = get_columns(), get_data(filters)
|
columns, data = get_columns(), get_data(filters)
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
def get_data(filters):
|
def get_data(filters):
|
||||||
data = frappe.db.sql("""
|
data = []
|
||||||
select
|
depreciation_accounts = frappe.db.sql_list(""" select name from tabAccount
|
||||||
a.name as asset, a.asset_category, a.status,
|
where ifnull(account_type, '') = 'Depreciation' """)
|
||||||
a.depreciation_method, a.purchase_date, a.gross_purchase_amount,
|
|
||||||
ds.schedule_date as depreciation_date, ds.depreciation_amount,
|
filters_data = [["company", "=", filters.get('company')],
|
||||||
ds.accumulated_depreciation_amount,
|
["posting_date", ">=", filters.get('from_date')],
|
||||||
(a.gross_purchase_amount - ds.accumulated_depreciation_amount) as amount_after_depreciation,
|
["posting_date", "<=", filters.get('to_date')],
|
||||||
ds.journal_entry as depreciation_entry
|
["against_voucher_type", "=", "Asset"],
|
||||||
from
|
["account", "in", depreciation_accounts]]
|
||||||
`tabAsset` a, `tabDepreciation Schedule` ds
|
|
||||||
where
|
|
||||||
a.name = ds.parent
|
|
||||||
and a.docstatus=1
|
|
||||||
and ifnull(ds.journal_entry, '') != ''
|
|
||||||
and ds.schedule_date between %(from_date)s and %(to_date)s
|
|
||||||
and a.company = %(company)s
|
|
||||||
{conditions}
|
|
||||||
order by
|
|
||||||
a.name asc, ds.schedule_date asc
|
|
||||||
""".format(conditions=get_filter_conditions(filters)), filters, as_dict=1)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def get_filter_conditions(filters):
|
|
||||||
conditions = ""
|
|
||||||
|
|
||||||
if filters.get("asset"):
|
if filters.get("asset"):
|
||||||
conditions += " and a.name = %(asset)s"
|
filters_data.append(["against_voucher", "=", filters.get("asset")])
|
||||||
|
|
||||||
if filters.get("asset_category"):
|
if filters.get("asset_category"):
|
||||||
conditions += " and a.asset_category = %(asset_category)s"
|
assets = frappe.db.sql_list("""select name from tabAsset
|
||||||
|
where asset_category = %s and docstatus=1""", filters.get("asset_category"))
|
||||||
return conditions
|
|
||||||
|
filters_data.append(["against_voucher", "in", assets])
|
||||||
|
|
||||||
|
gl_entries = frappe.get_all('GL Entry',
|
||||||
|
filters= filters_data,
|
||||||
|
fields = ["against_voucher", "debit_in_account_currency as debit", "voucher_no", "posting_date"],
|
||||||
|
order_by= "against_voucher, posting_date")
|
||||||
|
|
||||||
|
if not gl_entries:
|
||||||
|
return data
|
||||||
|
|
||||||
|
assets = [d.against_voucher for d in gl_entries]
|
||||||
|
assets_details = get_assets_details(assets)
|
||||||
|
|
||||||
|
for d in gl_entries:
|
||||||
|
asset_data = assets_details.get(d.against_voucher)
|
||||||
|
if not asset_data.get("accumulated_depreciation_amount"):
|
||||||
|
asset_data.accumulated_depreciation_amount = d.debit
|
||||||
|
else:
|
||||||
|
asset_data.accumulated_depreciation_amount += d.debit
|
||||||
|
|
||||||
|
row = frappe._dict(asset_data)
|
||||||
|
row.update({
|
||||||
|
"depreciation_amount": d.debit,
|
||||||
|
"depreciation_date": d.posting_date,
|
||||||
|
"amount_after_depreciation": (flt(row.gross_purchase_amount) -
|
||||||
|
flt(row.accumulated_depreciation_amount)),
|
||||||
|
"depreciation_entry": d.voucher_no
|
||||||
|
})
|
||||||
|
|
||||||
|
data.append(row)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def get_assets_details(assets):
|
||||||
|
assets_details = {}
|
||||||
|
|
||||||
|
fields = ["name as asset", "gross_purchase_amount",
|
||||||
|
"asset_category", "status", "depreciation_method", "purchase_date"]
|
||||||
|
|
||||||
|
for d in frappe.get_all("Asset", fields = fields, filters = {'name': ('in', assets)}):
|
||||||
|
assets_details.setdefault(d.asset, d)
|
||||||
|
|
||||||
|
return assets_details
|
||||||
|
|
||||||
def get_columns():
|
def get_columns():
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
@ -67,11 +67,33 @@ frappe.ui.form.on('Asset', {
|
|||||||
frm.trigger("create_asset_maintenance");
|
frm.trigger("create_asset_maintenance");
|
||||||
}, __("Make"));
|
}, __("Make"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!frm.doc.calculate_depreciation) {
|
||||||
|
frm.add_custom_button(__("Depreciation Entry"), function() {
|
||||||
|
frm.trigger("make_journal_entry");
|
||||||
|
}, __("Make"));
|
||||||
|
}
|
||||||
|
|
||||||
frm.page.set_inner_btn_group_as_primary(__("Make"));
|
frm.page.set_inner_btn_group_as_primary(__("Make"));
|
||||||
frm.trigger("setup_chart");
|
frm.trigger("setup_chart");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
make_journal_entry: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.assets.doctype.asset.asset.make_journal_entry",
|
||||||
|
args: {
|
||||||
|
asset_name: frm.doc.name
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if (r.message) {
|
||||||
|
var doclist = frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
setup_chart: function(frm) {
|
setup_chart: function(frm) {
|
||||||
var x_intervals = [frm.doc.purchase_date];
|
var x_intervals = [frm.doc.purchase_date];
|
||||||
var asset_values = [frm.doc.gross_purchase_amount];
|
var asset_values = [frm.doc.gross_purchase_amount];
|
||||||
|
|||||||
@ -283,3 +283,34 @@ def get_item_details(item_code):
|
|||||||
})
|
})
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def make_journal_entry(asset_name):
|
||||||
|
asset = frappe.get_doc("Asset", asset_name)
|
||||||
|
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"])
|
||||||
|
depreciation_cost_center = asset.cost_center or depreciation_cost_center
|
||||||
|
|
||||||
|
je = frappe.new_doc("Journal Entry")
|
||||||
|
je.voucher_type = "Depreciation Entry"
|
||||||
|
je.naming_series = depreciation_series
|
||||||
|
je.company = asset.company
|
||||||
|
je.remark = "Depreciation Entry against asset {0}".format(asset_name)
|
||||||
|
|
||||||
|
je.append("accounts", {
|
||||||
|
"account": depreciation_expense_account,
|
||||||
|
"reference_type": "Asset",
|
||||||
|
"reference_name": asset.name,
|
||||||
|
"cost_center": depreciation_cost_center
|
||||||
|
})
|
||||||
|
|
||||||
|
je.append("accounts", {
|
||||||
|
"account": accumulated_depreciation_account,
|
||||||
|
"reference_type": "Asset",
|
||||||
|
"reference_name": asset.name
|
||||||
|
})
|
||||||
|
|
||||||
|
return je
|
||||||
@ -5,13 +5,13 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, today, getdate
|
from frappe.utils import flt, today, getdate, cint
|
||||||
|
|
||||||
def post_depreciation_entries(date=None):
|
def post_depreciation_entries(date=None):
|
||||||
# Return if automatic booking of asset depreciation is disabled
|
# Return if automatic booking of asset depreciation is disabled
|
||||||
if not frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically"):
|
if not cint(frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically")):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not date:
|
if not date:
|
||||||
date = today()
|
date = today()
|
||||||
for asset in get_depreciable_assets(date):
|
for asset in get_depreciable_assets(date):
|
||||||
|
|||||||
@ -139,7 +139,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
|||||||
.format(args.item_code), StockOverReturnError)
|
.format(args.item_code), StockOverReturnError)
|
||||||
elif abs(current_stock_qty) > max_returnable_qty:
|
elif abs(current_stock_qty) > max_returnable_qty:
|
||||||
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
|
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
|
||||||
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
|
.format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)
|
||||||
|
|
||||||
def get_ref_item_dict(valid_items, ref_item_row):
|
def get_ref_item_dict(valid_items, ref_item_row):
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|||||||
@ -113,16 +113,14 @@ frappe.ui.form.on('Salary Slip Timesheet', {
|
|||||||
// Get leave details
|
// Get leave details
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
var get_emp_and_leave_details = function(doc, dt, dn) {
|
var get_emp_and_leave_details = function(doc, dt, dn) {
|
||||||
if(!doc.start_date){
|
return frappe.call({
|
||||||
return frappe.call({
|
method: 'get_emp_and_leave_details',
|
||||||
method: 'get_emp_and_leave_details',
|
doc: locals[dt][dn],
|
||||||
doc: locals[dt][dn],
|
callback: function(r, rt) {
|
||||||
callback: function(r, rt) {
|
cur_frm.refresh();
|
||||||
cur_frm.refresh();
|
calculate_all(doc, dt, dn);
|
||||||
calculate_all(doc, dt, dn);
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.cscript.employee = function(doc,dt,dn){
|
cur_frm.cscript.employee = function(doc,dt,dn){
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import cstr, add_days, date_diff
|
from frappe.utils import cstr, add_days, date_diff, getdate
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils.csvutils import UnicodeWriter
|
from frappe.utils.csvutils import UnicodeWriter
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
@ -48,8 +48,9 @@ def add_data(w, args):
|
|||||||
for employee in employees:
|
for employee in employees:
|
||||||
existing_attendance = {}
|
existing_attendance = {}
|
||||||
if existing_attendance_records \
|
if existing_attendance_records \
|
||||||
and tuple([date, employee.name]) in existing_attendance_records:
|
and tuple([getdate(date), employee.name]) in existing_attendance_records:
|
||||||
existing_attendance = existing_attendance_records[tuple([date, employee.name])]
|
existing_attendance = existing_attendance_records[tuple([getdate(date), employee.name])]
|
||||||
|
|
||||||
row = [
|
row = [
|
||||||
existing_attendance and existing_attendance.name or "",
|
existing_attendance and existing_attendance.name or "",
|
||||||
employee.name, employee.employee_name, date,
|
employee.name, employee.employee_name, date,
|
||||||
@ -114,6 +115,7 @@ def upload():
|
|||||||
if not row: continue
|
if not row: continue
|
||||||
row_idx = i + 5
|
row_idx = i + 5
|
||||||
d = frappe._dict(zip(columns, row))
|
d = frappe._dict(zip(columns, row))
|
||||||
|
|
||||||
d["doctype"] = "Attendance"
|
d["doctype"] = "Attendance"
|
||||||
if d.name:
|
if d.name:
|
||||||
d["docstatus"] = frappe.db.get_value("Attendance", d.name, "docstatus")
|
d["docstatus"] = frappe.db.get_value("Attendance", d.name, "docstatus")
|
||||||
@ -121,6 +123,8 @@ def upload():
|
|||||||
try:
|
try:
|
||||||
check_record(d)
|
check_record(d)
|
||||||
ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True))
|
ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True))
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error = True
|
error = True
|
||||||
ret.append('Error for row (#%d) %s : %s' % (row_idx,
|
ret.append('Error for row (#%d) %s : %s' % (row_idx,
|
||||||
|
|||||||
@ -6,7 +6,8 @@ def get_data():
|
|||||||
'non_standard_fieldnames': {
|
'non_standard_fieldnames': {
|
||||||
'Purchase Invoice': 'purchase_receipt',
|
'Purchase Invoice': 'purchase_receipt',
|
||||||
'Landed Cost Voucher': 'receipt_document',
|
'Landed Cost Voucher': 'receipt_document',
|
||||||
'Subscription': 'reference_document'
|
'Subscription': 'reference_document',
|
||||||
|
'Purchase Receipt': 'return_against'
|
||||||
},
|
},
|
||||||
'internal_links': {
|
'internal_links': {
|
||||||
'Purchase Order': ['items', 'purchase_order'],
|
'Purchase Order': ['items', 'purchase_order'],
|
||||||
@ -24,7 +25,7 @@ def get_data():
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Returns'),
|
'label': _('Returns'),
|
||||||
'items': ['Stock Entry']
|
'items': ['Purchase Receipt']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Subscription'),
|
'label': _('Subscription'),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user