Merge branch 'develop' of https://github.com/frappe/erpnext into lcv_multicurrency
This commit is contained in:
commit
f48296ddf0
4
.github/helper/documentation.py
vendored
4
.github/helper/documentation.py
vendored
@ -21,8 +21,8 @@ def docs_link_exists(body):
|
||||
if word.startswith('http') and uri_validator(word):
|
||||
parsed_url = urlparse(word)
|
||||
if parsed_url.netloc == "github.com":
|
||||
_, org, repo, _type, ref = parsed_url.path.split('/')
|
||||
if org == "frappe" and repo in docs_repos:
|
||||
parts = parsed_url.path.split('/')
|
||||
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos:
|
||||
return True
|
||||
|
||||
|
||||
|
@ -13,8 +13,8 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import g
|
||||
class AssetValueAdjustment(Document):
|
||||
def validate(self):
|
||||
self.validate_date()
|
||||
self.set_difference_amount()
|
||||
self.set_current_asset_value()
|
||||
self.set_difference_amount()
|
||||
|
||||
def on_submit(self):
|
||||
self.make_depreciation_entry()
|
||||
@ -25,7 +25,7 @@ class AssetValueAdjustment(Document):
|
||||
frappe.throw(_("Cancel the journal entry {0} first").format(self.journal_entry))
|
||||
|
||||
self.reschedule_depreciations(self.current_asset_value)
|
||||
|
||||
|
||||
def validate_date(self):
|
||||
asset_purchase_date = frappe.db.get_value('Asset', self.asset, 'purchase_date')
|
||||
if getdate(self.date) < getdate(asset_purchase_date):
|
||||
@ -53,6 +53,7 @@ class AssetValueAdjustment(Document):
|
||||
je.posting_date = self.date
|
||||
je.company = self.company
|
||||
je.remark = "Depreciation Entry against {0} worth {1}".format(self.asset, self.difference_amount)
|
||||
je.finance_book = self.finance_book
|
||||
|
||||
credit_entry = {
|
||||
"account": accumulated_depreciation_account,
|
||||
@ -78,7 +79,7 @@ class AssetValueAdjustment(Document):
|
||||
debit_entry.update({
|
||||
dimension['fieldname']: self.get(dimension['fieldname']) or dimension.get('default_dimension')
|
||||
})
|
||||
|
||||
|
||||
je.append("accounts", credit_entry)
|
||||
je.append("accounts", debit_entry)
|
||||
|
||||
|
@ -254,22 +254,26 @@ class StatusUpdater(Document):
|
||||
if not args.get("second_source_extra_cond"):
|
||||
args["second_source_extra_cond"] = ""
|
||||
|
||||
args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
|
||||
args['second_source_condition'] = frappe.db.sql(""" select ifnull((select sum(%(second_source_field)s)
|
||||
from `tab%(second_source_dt)s`
|
||||
where `%(second_join_field)s`="%(detail_id)s"
|
||||
and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s FOR UPDATE), 0)""" % args
|
||||
and (`tab%(second_source_dt)s`.docstatus=1)
|
||||
%(second_source_extra_cond)s), 0) """ % args)[0][0]
|
||||
|
||||
if args['detail_id']:
|
||||
if not args.get("extra_cond"): args["extra_cond"] = ""
|
||||
|
||||
frappe.db.sql("""update `tab%(target_dt)s`
|
||||
set %(target_field)s = (
|
||||
args["source_dt_value"] = frappe.db.sql("""
|
||||
(select ifnull(sum(%(source_field)s), 0)
|
||||
from `tab%(source_dt)s` where `%(join_field)s`="%(detail_id)s"
|
||||
and (docstatus=1 %(cond)s) %(extra_cond)s)
|
||||
%(second_source_condition)s
|
||||
)
|
||||
%(update_modified)s
|
||||
""" % args)[0][0] or 0.0
|
||||
|
||||
if args['second_source_condition']:
|
||||
args["source_dt_value"] += flt(args['second_source_condition'])
|
||||
|
||||
frappe.db.sql("""update `tab%(target_dt)s`
|
||||
set %(target_field)s = %(source_dt_value)s %(update_modified)s
|
||||
where name='%(detail_id)s'""" % args)
|
||||
|
||||
def _update_percent_field_in_targets(self, args, update_modified=True):
|
||||
|
@ -260,6 +260,15 @@ def update_taxes_with_shipping_lines(taxes, shipping_lines, shopify_settings):
|
||||
"""Shipping lines represents the shipping details,
|
||||
each such shipping detail consists of a list of tax_lines"""
|
||||
for shipping_charge in shipping_lines:
|
||||
if shipping_charge.get("price"):
|
||||
taxes.append({
|
||||
"charge_type": _("Actual"),
|
||||
"account_head": get_tax_account_head(shipping_charge),
|
||||
"description": shipping_charge["title"],
|
||||
"tax_amount": shipping_charge["price"],
|
||||
"cost_center": shopify_settings.cost_center
|
||||
})
|
||||
|
||||
for tax in shipping_charge.get("tax_lines"):
|
||||
taxes.append({
|
||||
"charge_type": _("Actual"),
|
||||
|
@ -18,13 +18,18 @@ frappe.ui.form.on('Employee Advance', {
|
||||
if (!frm.doc.employee) {
|
||||
frappe.msgprint(__("Please select employee first"));
|
||||
}
|
||||
var company_currency = erpnext.get_currency(frm.doc.company);
|
||||
let company_currency = erpnext.get_currency(frm.doc.company);
|
||||
let currencies = [company_currency];
|
||||
if (frm.doc.currency && (frm.doc.currency != company_currency)) {
|
||||
currencies.push(frm.doc.currency);
|
||||
}
|
||||
|
||||
return {
|
||||
filters: {
|
||||
"root_type": "Asset",
|
||||
"is_group": 0,
|
||||
"company": frm.doc.company,
|
||||
"account_currency": ["in", [frm.doc.currency, company_currency]],
|
||||
"account_currency": ["in", currencies],
|
||||
}
|
||||
};
|
||||
});
|
||||
@ -181,21 +186,23 @@ frappe.ui.form.on('Employee Advance', {
|
||||
},
|
||||
|
||||
currency: function(frm) {
|
||||
var from_currency = frm.doc.currency;
|
||||
var company_currency;
|
||||
if (!frm.doc.company) {
|
||||
company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
|
||||
} else {
|
||||
company_currency = erpnext.get_currency(frm.doc.company);
|
||||
if (frm.doc.currency) {
|
||||
var from_currency = frm.doc.currency;
|
||||
var company_currency;
|
||||
if (!frm.doc.company) {
|
||||
company_currency = erpnext.get_currency(frappe.defaults.get_default("Company"));
|
||||
} else {
|
||||
company_currency = erpnext.get_currency(frm.doc.company);
|
||||
}
|
||||
if (from_currency != company_currency) {
|
||||
frm.events.set_exchange_rate(frm, from_currency, company_currency);
|
||||
} else {
|
||||
frm.set_value("exchange_rate", 1.0);
|
||||
frm.set_df_property('exchange_rate', 'hidden', 1);
|
||||
frm.set_df_property("exchange_rate", "description", "" );
|
||||
}
|
||||
frm.refresh_fields();
|
||||
}
|
||||
if (from_currency != company_currency) {
|
||||
frm.events.set_exchange_rate(frm, from_currency, company_currency);
|
||||
} else {
|
||||
frm.set_value("exchange_rate", 1.0);
|
||||
frm.set_df_property('exchange_rate', 'hidden', 1);
|
||||
frm.set_df_property("exchange_rate", "description", "" );
|
||||
}
|
||||
frm.refresh_fields();
|
||||
},
|
||||
|
||||
set_exchange_rate: function(frm, from_currency, company_currency) {
|
||||
|
@ -8,7 +8,17 @@ frappe.views.calendar["Job Card"] = {
|
||||
"allDay": "allDay",
|
||||
"progress": "progress"
|
||||
},
|
||||
gantt: true,
|
||||
gantt: {
|
||||
field_map: {
|
||||
"start": "started_time",
|
||||
"end": "started_time",
|
||||
"id": "name",
|
||||
"title": "subject",
|
||||
"color": "color",
|
||||
"allDay": "allDay",
|
||||
"progress": "progress"
|
||||
}
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
"fieldtype": "Link",
|
||||
|
@ -491,6 +491,39 @@ class TestWorkOrder(unittest.TestCase):
|
||||
work_order1.save()
|
||||
self.assertEqual(work_order1.operations[0].time_in_mins, 40.0)
|
||||
|
||||
def test_partial_material_consumption(self):
|
||||
frappe.db.set_value("Manufacturing Settings", None, "material_consumption", 1)
|
||||
wo_order = make_wo_order_test_record(planned_start_date=now(), qty=4)
|
||||
|
||||
ste_cancel_list = []
|
||||
ste1 = test_stock_entry.make_stock_entry(item_code="_Test Item",
|
||||
target="_Test Warehouse - _TC", qty=20, basic_rate=5000.0)
|
||||
ste2 = test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
|
||||
target="_Test Warehouse - _TC", qty=20, basic_rate=1000.0)
|
||||
|
||||
ste_cancel_list.extend([ste1, ste2])
|
||||
|
||||
s = frappe.get_doc(make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 4))
|
||||
s.submit()
|
||||
ste_cancel_list.append(s)
|
||||
|
||||
ste1 = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2))
|
||||
ste1.submit()
|
||||
ste_cancel_list.append(ste1)
|
||||
|
||||
print(wo_order.name)
|
||||
ste3 = frappe.get_doc(make_stock_entry(wo_order.name, "Material Consumption for Manufacture", 2))
|
||||
self.assertEquals(ste3.fg_completed_qty, 2)
|
||||
|
||||
expected_qty = {"_Test Item": 2, "_Test Item Home Desktop 100": 4}
|
||||
for row in ste3.items:
|
||||
self.assertEquals(row.qty, expected_qty.get(row.item_code))
|
||||
|
||||
for ste_doc in ste_cancel_list:
|
||||
ste_doc.cancel()
|
||||
|
||||
frappe.db.set_value("Manufacturing Settings", None, "material_consumption", 0)
|
||||
|
||||
def get_scrap_item_details(bom_no):
|
||||
scrap_items = {}
|
||||
for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item`
|
||||
|
@ -545,7 +545,8 @@ erpnext.work_order = {
|
||||
var tbl = frm.doc.required_items || [];
|
||||
var tbl_lenght = tbl.length;
|
||||
for (var i = 0, len = tbl_lenght; i < len; i++) {
|
||||
if (flt(frm.doc.required_items[i].required_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
|
||||
let wo_item_qty = frm.doc.required_items[i].transferred_qty || frm.doc.required_items[i].required_qty;
|
||||
if (flt(wo_item_qty) > flt(frm.doc.required_items[i].consumed_qty)) {
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ class Member(Document):
|
||||
frappe.msgprint(_("A customer is already linked to this Member"))
|
||||
cust = create_customer(frappe._dict({
|
||||
'fullname': self.member_name,
|
||||
'email': self.email_id or self.user,
|
||||
'email': self.email_id or self.email,
|
||||
'phone': None
|
||||
}))
|
||||
|
||||
@ -177,4 +177,4 @@ def register_member(fullname, email, rzpay_plan_id, subscription_id, pan=None, m
|
||||
mobile=mobile
|
||||
))
|
||||
|
||||
return member.name
|
||||
return member.name
|
||||
|
@ -450,7 +450,6 @@ erpnext.patches.v8_9.set_member_party_type
|
||||
erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile
|
||||
erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order
|
||||
erpnext.patches.v9_0.student_admission_childtable_migrate
|
||||
erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23
|
||||
erpnext.patches.v9_0.add_healthcare_domain
|
||||
erpnext.patches.v9_0.set_variant_item_description
|
||||
erpnext.patches.v9_0.set_uoms_in_variant_field
|
||||
|
@ -5,6 +5,8 @@ from frappe.utils import nowdate
|
||||
from erpnext.accounts.doctype.account.test_account import create_account
|
||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
|
||||
from erpnext.loan_management.doctype.loan.loan import make_repayment_entry
|
||||
from erpnext.loan_management.doctype.loan_repayment.loan_repayment import get_accrued_interest_entries
|
||||
from frappe.model.naming import make_autoname
|
||||
|
||||
def execute():
|
||||
|
||||
@ -18,15 +20,29 @@ def execute():
|
||||
frappe.reload_doc('loan_management', 'doctype', 'loan_repayment_detail')
|
||||
frappe.reload_doc('loan_management', 'doctype', 'loan_interest_accrual')
|
||||
frappe.reload_doc('accounts', 'doctype', 'gl_entry')
|
||||
frappe.reload_doc('accounts', 'doctype', 'journal_entry_account')
|
||||
|
||||
updated_loan_types = []
|
||||
loans_to_close = []
|
||||
|
||||
# Update old loan status as closed
|
||||
if frappe.db.has_column('Repayment Schedule', 'paid'):
|
||||
loans_list = frappe.db.sql("""SELECT distinct parent from `tabRepayment Schedule`
|
||||
where paid = 0 and docstatus = 1""", as_dict=1)
|
||||
|
||||
loans_to_close = [d.parent for d in loans_list]
|
||||
|
||||
if loans_to_close:
|
||||
frappe.db.sql("UPDATE `tabLoan` set status = 'Closed' where name not in (%s)" % (', '.join(['%s'] * len(loans_to_close))), tuple(loans_to_close))
|
||||
|
||||
loans = frappe.get_all('Loan', fields=['name', 'loan_type', 'company', 'status', 'mode_of_payment',
|
||||
'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account'])
|
||||
'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account'],
|
||||
filters={'docstatus': 1, 'status': ('!=', 'Closed')})
|
||||
|
||||
for loan in loans:
|
||||
# Update details in Loan Types and Loan
|
||||
loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company')
|
||||
loan_type = loan.loan_type
|
||||
|
||||
group_income_account = frappe.get_value('Account', {'company': loan.company,
|
||||
'is_group': 1, 'root_type': 'Income', 'account_name': _('Indirect Income')})
|
||||
@ -38,7 +54,26 @@ def execute():
|
||||
penalty_account = create_account(company=loan.company, account_type='Income Account',
|
||||
account_name='Penalty Account', parent_account=group_income_account)
|
||||
|
||||
if not loan_type_company:
|
||||
# Same loan type used for multiple companies
|
||||
if loan_type_company and loan_type_company != loan.company:
|
||||
# get loan type for appropriate company
|
||||
loan_type_name = frappe.get_value('Loan Type', {'company': loan.company,
|
||||
'mode_of_payment': loan.mode_of_payment, 'loan_account': loan.loan_account,
|
||||
'payment_account': loan.payment_account, 'interest_income_account': loan.interest_income_account,
|
||||
'penalty_income_account': loan.penalty_income_account}, 'name')
|
||||
|
||||
if not loan_type_name:
|
||||
loan_type_name = create_loan_type(loan, loan_type_name, penalty_account)
|
||||
|
||||
# update loan type in loan
|
||||
frappe.db.sql("UPDATE `tabLoan` set loan_type = %s where name = %s", (loan_type_name,
|
||||
loan.name))
|
||||
|
||||
loan_type = loan_type_name
|
||||
if loan_type_name not in updated_loan_types:
|
||||
updated_loan_types.append(loan_type_name)
|
||||
|
||||
elif not loan_type_company:
|
||||
loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type)
|
||||
loan_type_doc.is_term_loan = 1
|
||||
loan_type_doc.company = loan.company
|
||||
@ -49,8 +84,9 @@ def execute():
|
||||
loan_type_doc.penalty_income_account = penalty_account
|
||||
loan_type_doc.submit()
|
||||
updated_loan_types.append(loan.loan_type)
|
||||
loan_type = loan.loan_type
|
||||
|
||||
if loan.loan_type in updated_loan_types:
|
||||
if loan_type in updated_loan_types:
|
||||
if loan.status == 'Fully Disbursed':
|
||||
status = 'Disbursed'
|
||||
elif loan.status == 'Repaid/Closed':
|
||||
@ -64,25 +100,48 @@ def execute():
|
||||
'status': status
|
||||
})
|
||||
|
||||
process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan.loan_type,
|
||||
process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan_type,
|
||||
loan=loan.name)
|
||||
|
||||
payments = frappe.db.sql(''' SELECT j.name, a.debit, a.debit_in_account_currency, j.posting_date
|
||||
FROM `tabJournal Entry` j, `tabJournal Entry Account` a
|
||||
WHERE a.parent = j.name and a.reference_type='Loan' and a.reference_name = %s
|
||||
and account = %s
|
||||
''', (loan.name, loan.loan_account), as_dict=1)
|
||||
|
||||
for payment in payments:
|
||||
repayment_entry = make_repayment_entry(loan.name, loan.loan_applicant_type, loan.applicant,
|
||||
loan.loan_type, loan.company)
|
||||
if frappe.db.has_column('Repayment Schedule', 'paid'):
|
||||
total_principal, total_interest = frappe.db.get_value('Repayment Schedule', {'paid': 1, 'parent': loan.name},
|
||||
['sum(principal_amount) as total_principal', 'sum(interest_amount) as total_interest'])
|
||||
|
||||
repayment_entry.amount_paid = payment.debit_in_account_currency
|
||||
repayment_entry.posting_date = payment.posting_date
|
||||
repayment_entry.save()
|
||||
repayment_entry.submit()
|
||||
accrued_entries = get_accrued_interest_entries(loan.name)
|
||||
for entry in accrued_entries:
|
||||
interest_paid = 0
|
||||
principal_paid = 0
|
||||
|
||||
jv = frappe.get_doc('Journal Entry', payment.name)
|
||||
jv.flags.ignore_links = True
|
||||
jv.cancel()
|
||||
if total_interest > entry.interest_amount:
|
||||
interest_paid = entry.interest_amount
|
||||
else:
|
||||
interest_paid = total_interest
|
||||
|
||||
if total_principal > entry.payable_principal_amount:
|
||||
principal_paid = entry.payable_principal_amount
|
||||
else:
|
||||
principal_paid = total_principal
|
||||
|
||||
frappe.db.sql(""" UPDATE `tabLoan Interest Accrual`
|
||||
SET paid_principal_amount = `paid_principal_amount` + %s,
|
||||
paid_interest_amount = `paid_interest_amount` + %s
|
||||
WHERE name = %s""",
|
||||
(principal_paid, interest_paid, entry.name))
|
||||
|
||||
total_principal -= principal_paid
|
||||
total_interest -= interest_paid
|
||||
|
||||
def create_loan_type(loan, loan_type_name, penalty_account):
|
||||
loan_type_doc = frappe.new_doc('Loan Type')
|
||||
loan_type_doc.loan_name = make_autoname("Loan Type-.####")
|
||||
loan_type_doc.is_term_loan = 1
|
||||
loan_type_doc.company = loan.company
|
||||
loan_type_doc.mode_of_payment = loan.mode_of_payment
|
||||
loan_type_doc.payment_account = loan.payment_account
|
||||
loan_type_doc.loan_account = loan.loan_account
|
||||
loan_type_doc.interest_income_account = loan.interest_income_account
|
||||
loan_type_doc.penalty_income_account = penalty_account
|
||||
loan_type_doc.submit()
|
||||
|
||||
return loan_type_doc.name
|
||||
|
@ -1,48 +0,0 @@
|
||||
# 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 import getdate
|
||||
from frappe.automation.doctype.auto_repeat.auto_repeat import get_next_schedule_date
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('accounts', 'doctype', 'subscription')
|
||||
fields = ["name", "reference_doctype", "reference_document",
|
||||
"start_date", "frequency", "repeat_on_day"]
|
||||
|
||||
for d in fields:
|
||||
if not frappe.db.has_column('Subscription', d):
|
||||
return
|
||||
|
||||
doctypes = ('Purchase Order', 'Sales Order', 'Purchase Invoice', 'Sales Invoice')
|
||||
for data in frappe.get_all('Subscription',
|
||||
fields = fields,
|
||||
filters = {'reference_doctype': ('in', doctypes), 'docstatus': 1}):
|
||||
|
||||
recurring_id = frappe.db.get_value(data.reference_doctype, data.reference_document, "recurring_id")
|
||||
if recurring_id:
|
||||
frappe.db.sql("update `tab{0}` set subscription=%s where recurring_id=%s"
|
||||
.format(data.reference_doctype), (data.name, recurring_id))
|
||||
|
||||
date_field = 'transaction_date'
|
||||
if data.reference_doctype in ['Sales Invoice', 'Purchase Invoice']:
|
||||
date_field = 'posting_date'
|
||||
|
||||
start_date = frappe.db.get_value(data.reference_doctype, data.reference_document, date_field)
|
||||
|
||||
if start_date and getdate(start_date) != getdate(data.start_date):
|
||||
last_ref_date = frappe.db.sql("""
|
||||
select {0}
|
||||
from `tab{1}`
|
||||
where subscription=%s and docstatus < 2
|
||||
order by creation desc
|
||||
limit 1
|
||||
""".format(date_field, data.reference_doctype), data.name)[0][0]
|
||||
|
||||
next_schedule_date = get_next_schedule_date(last_ref_date, data.frequency, data.repeat_on_day)
|
||||
|
||||
frappe.db.set_value("Subscription", data.name, {
|
||||
"start_date": start_date,
|
||||
"next_schedule_date": next_schedule_date
|
||||
}, None)
|
@ -12,14 +12,6 @@ frappe.ui.form.on('Additional Salary', {
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
if (!frm.doc.currency) return;
|
||||
frm.set_query("salary_component", function() {
|
||||
return {
|
||||
query: "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
|
||||
filters: {currency: frm.doc.currency, company: frm.doc.company}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
employee: function(frm) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
"employee_benefits",
|
||||
"totals",
|
||||
"total_amount",
|
||||
"column_break",
|
||||
"pro_rata_dispensed_amount"
|
||||
],
|
||||
"fields": [
|
||||
@ -139,11 +140,15 @@
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-25 11:49:05.095101",
|
||||
"modified": "2020-12-14 15:52:08.566418",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Payroll",
|
||||
"name": "Employee Benefit Application",
|
||||
|
@ -11,11 +11,11 @@ frappe.ui.form.on('Employee Incentive', {
|
||||
};
|
||||
});
|
||||
|
||||
if (!frm.doc.currency) return;
|
||||
if (!frm.doc.company) return;
|
||||
frm.set_query("salary_component", function() {
|
||||
return {
|
||||
query: "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
|
||||
filters: {type: "earning", currency: frm.doc.currency, company: frm.doc.company}
|
||||
filters: {type: "earning", company: frm.doc.company}
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -4,9 +4,13 @@
|
||||
frappe.ui.form.on('Retention Bonus', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("employee", function() {
|
||||
if (!frm.doc.company) {
|
||||
frappe.msgprint(__("Please Select Company First"));
|
||||
}
|
||||
return {
|
||||
filters: {
|
||||
"status": "Active"
|
||||
"status": "Active",
|
||||
"company": frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
|
@ -55,17 +55,17 @@ frappe.ui.form.on('Salary Structure', {
|
||||
},
|
||||
|
||||
set_earning_deduction_component: function(frm) {
|
||||
if(!frm.doc.currency && !frm.doc.company) return;
|
||||
if(!frm.doc.company) return;
|
||||
frm.set_query("salary_component", "earnings", function() {
|
||||
return {
|
||||
query : "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
|
||||
filters: {type: "earning", currency: frm.doc.currency, company: frm.doc.company}
|
||||
filters: {type: "earning", company: frm.doc.company}
|
||||
};
|
||||
});
|
||||
frm.set_query("salary_component", "deductions", function() {
|
||||
return {
|
||||
query : "erpnext.payroll.doctype.salary_structure.salary_structure.get_earning_deduction_components",
|
||||
filters: {type: "deduction", currency: frm.doc.currency, company: frm.doc.company}
|
||||
filters: {type: "deduction", company: frm.doc.company}
|
||||
};
|
||||
});
|
||||
},
|
||||
@ -74,7 +74,6 @@ frappe.ui.form.on('Salary Structure', {
|
||||
currency: function(frm) {
|
||||
calculate_totals(frm.doc);
|
||||
frm.trigger("set_dynamic_labels")
|
||||
frm.trigger('set_earning_deduction_component');
|
||||
frm.refresh()
|
||||
},
|
||||
|
||||
|
@ -210,7 +210,7 @@ def get_employees(salary_structure):
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_earning_deduction_components(doctype, txt, searchfield, start, page_len, filters):
|
||||
if len(filters) < 3:
|
||||
if len(filters) < 2:
|
||||
return {}
|
||||
|
||||
return frappe.db.sql("""
|
||||
|
@ -20,4 +20,4 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlData.extend( {
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -12,6 +12,9 @@ erpnext.setup_auto_gst_taxation = (doctype) => {
|
||||
tax_category: function(frm) {
|
||||
frm.trigger('get_tax_template');
|
||||
},
|
||||
customer_address: function(frm) {
|
||||
frm.trigger('get_tax_template');
|
||||
},
|
||||
get_tax_template: function(frm) {
|
||||
if (!frm.doc.company) return;
|
||||
|
||||
|
@ -151,6 +151,7 @@ class Gstr1Report(object):
|
||||
{select_columns}
|
||||
from `tab{doctype}`
|
||||
where docstatus = 1 {where_conditions}
|
||||
and is_opening = 'No'
|
||||
order by posting_date desc
|
||||
""".format(select_columns=self.select_columns, doctype=self.doctype,
|
||||
where_conditions=conditions), self.filters, as_dict=1)
|
||||
|
@ -14,7 +14,6 @@ from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty
|
||||
from frappe.desk.notifications import clear_doctype_notifications
|
||||
from frappe.contacts.doctype.address.address import get_company_address
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from frappe.automation.doctype.auto_repeat.auto_repeat import get_next_schedule_date
|
||||
from erpnext.selling.doctype.customer.customer import check_credit_limit
|
||||
from erpnext.stock.doctype.item.item import get_item_defaults
|
||||
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
|
||||
@ -418,8 +417,7 @@ class SalesOrder(SellingController):
|
||||
def on_recurring(self, reference_doc, auto_repeat_doc):
|
||||
|
||||
def _get_delivery_date(ref_doc_delivery_date, red_doc_transaction_date, transaction_date):
|
||||
delivery_date = get_next_schedule_date(ref_doc_delivery_date,
|
||||
auto_repeat_doc.frequency, auto_repeat_doc.start_date, cint(auto_repeat_doc.repeat_on_day))
|
||||
delivery_date = auto_repeat_doc.get_next_schedule_date(schedule_date=ref_doc_delivery_date)
|
||||
|
||||
if delivery_date <= transaction_date:
|
||||
delivery_date_diff = frappe.utils.date_diff(ref_doc_delivery_date, red_doc_transaction_date)
|
||||
|
@ -841,6 +841,10 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
}
|
||||
},
|
||||
|
||||
fg_completed_qty: function() {
|
||||
this.get_items();
|
||||
},
|
||||
|
||||
get_items: function() {
|
||||
var me = this;
|
||||
if(!this.frm.doc.fg_completed_qty || !this.frm.doc.bom_no)
|
||||
@ -850,6 +854,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
// if work order / bom is mentioned, get items
|
||||
return this.frm.call({
|
||||
doc: me.frm.doc,
|
||||
freeze: true,
|
||||
method: "get_items",
|
||||
callback: function(r) {
|
||||
if(!r.exc) refresh_field("items");
|
||||
|
@ -120,6 +120,7 @@ class StockEntry(StockController):
|
||||
self.update_transferred_qty()
|
||||
self.update_quality_inspection()
|
||||
self.delete_auto_created_batches()
|
||||
self.delete_linked_stock_entry()
|
||||
|
||||
if self.purpose == 'Material Transfer' and self.add_to_transit:
|
||||
self.set_material_request_transfer_status('Not Started')
|
||||
@ -152,6 +153,12 @@ class StockEntry(StockController):
|
||||
frappe.throw(_("For job card {0}, you can only make the 'Material Transfer for Manufacture' type stock entry")
|
||||
.format(self.job_card))
|
||||
|
||||
def delete_linked_stock_entry(self):
|
||||
if self.purpose == "Send to Warehouse":
|
||||
for d in frappe.get_all("Stock Entry", filters={"docstatus": 0,
|
||||
"outgoing_stock_entry": self.name, "purpose": "Receive at Warehouse"}):
|
||||
frappe.delete_doc("Stock Entry", d.name)
|
||||
|
||||
def set_transfer_qty(self):
|
||||
for item in self.get("items"):
|
||||
if not flt(item.qty):
|
||||
@ -1033,26 +1040,22 @@ class StockEntry(StockController):
|
||||
wo = frappe.get_doc("Work Order", self.work_order)
|
||||
wo_items = frappe.get_all('Work Order Item',
|
||||
filters={'parent': self.work_order},
|
||||
fields=["item_code", "required_qty", "consumed_qty"]
|
||||
fields=["item_code", "required_qty", "consumed_qty", "transferred_qty"]
|
||||
)
|
||||
|
||||
work_order_qty = wo.material_transferred_for_manufacturing or wo.qty
|
||||
for item in wo_items:
|
||||
qty = item.required_qty
|
||||
|
||||
item_account_details = get_item_defaults(item.item_code, self.company)
|
||||
# Take into account consumption if there are any.
|
||||
if self.purpose == 'Manufacture':
|
||||
req_qty_each = flt(item.required_qty / wo.qty)
|
||||
if (flt(item.consumed_qty) != 0):
|
||||
remaining_qty = flt(item.consumed_qty) - (flt(wo.produced_qty) * req_qty_each)
|
||||
exhaust_qty = req_qty_each * wo.produced_qty
|
||||
if remaining_qty > exhaust_qty :
|
||||
if (remaining_qty/(req_qty_each * flt(self.fg_completed_qty))) >= 1:
|
||||
qty =0
|
||||
else:
|
||||
qty = (req_qty_each * flt(self.fg_completed_qty)) - remaining_qty
|
||||
else:
|
||||
qty = req_qty_each * flt(self.fg_completed_qty)
|
||||
|
||||
wo_item_qty = item.transferred_qty or item.required_qty
|
||||
|
||||
req_qty_each = (
|
||||
(flt(wo_item_qty) - flt(item.consumed_qty)) /
|
||||
(flt(work_order_qty) - flt(wo.produced_qty))
|
||||
)
|
||||
|
||||
qty = req_qty_each * flt(self.fg_completed_qty)
|
||||
|
||||
if qty > 0:
|
||||
self.add_to_stock_entry_detail({
|
||||
@ -1134,13 +1137,15 @@ class StockEntry(StockController):
|
||||
else:
|
||||
qty = req_qty_each * flt(self.fg_completed_qty)
|
||||
|
||||
|
||||
elif backflushed_materials.get(item.item_code):
|
||||
for d in backflushed_materials.get(item.item_code):
|
||||
if d.get(item.warehouse):
|
||||
if (qty > req_qty):
|
||||
qty = (qty/trans_qty) * flt(self.fg_completed_qty)
|
||||
|
||||
if consumed_qty:
|
||||
qty -= consumed_qty
|
||||
|
||||
if cint(frappe.get_cached_value('UOM', item.stock_uom, 'must_be_whole_number')):
|
||||
qty = frappe.utils.ceil(qty)
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestVoiceCallSettings(unittest.TestCase):
|
||||
pass
|
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Voice Call Settings', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
@ -0,0 +1,124 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "field:user",
|
||||
"creation": "2020-12-08 16:52:40.590146",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"user",
|
||||
"call_receiving_device",
|
||||
"column_break_3",
|
||||
"greeting_message",
|
||||
"agent_busy_message",
|
||||
"agent_unavailable_message"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "User",
|
||||
"options": "User",
|
||||
"permlevel": 1,
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "greeting_message",
|
||||
"fieldtype": "Data",
|
||||
"label": "Greeting Message"
|
||||
},
|
||||
{
|
||||
"fieldname": "agent_busy_message",
|
||||
"fieldtype": "Data",
|
||||
"label": "Agent Busy Message"
|
||||
},
|
||||
{
|
||||
"fieldname": "agent_unavailable_message",
|
||||
"fieldtype": "Data",
|
||||
"label": "Agent Unavailable Message"
|
||||
},
|
||||
{
|
||||
"default": "Computer",
|
||||
"fieldname": "call_receiving_device",
|
||||
"fieldtype": "Select",
|
||||
"label": "Call Receiving Device",
|
||||
"options": "Computer\nPhone"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2020-12-14 18:49:34.600194",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Telephony",
|
||||
"name": "Voice Call Settings",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "All",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"permlevel": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"permlevel": 2,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"permlevel": 2,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "All",
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, 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 VoiceCallSettings(Document):
|
||||
pass
|
Loading…
Reference in New Issue
Block a user