Merge branch 'develop' into fix-student-email-id
This commit is contained in:
commit
2388199347
@ -91,15 +91,11 @@ class TestBankTransaction(unittest.TestCase):
|
|||||||
self.assertEqual(frappe.db.get_value("Bank Transaction", bank_transaction.name, "unallocated_amount"), 0)
|
self.assertEqual(frappe.db.get_value("Bank Transaction", bank_transaction.name, "unallocated_amount"), 0)
|
||||||
self.assertTrue(frappe.db.get_value("Sales Invoice Payment", dict(parent=payment.name), "clearance_date") is not None)
|
self.assertTrue(frappe.db.get_value("Sales Invoice Payment", dict(parent=payment.name), "clearance_date") is not None)
|
||||||
|
|
||||||
def add_transactions():
|
def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
||||||
if frappe.flags.test_bank_transactions_created:
|
|
||||||
return
|
|
||||||
|
|
||||||
frappe.set_user("Administrator")
|
|
||||||
try:
|
try:
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Bank",
|
"doctype": "Bank",
|
||||||
"bank_name":"Citi Bank",
|
"bank_name":bank_name,
|
||||||
}).insert()
|
}).insert()
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
@ -108,12 +104,19 @@ def add_transactions():
|
|||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Bank Account",
|
"doctype": "Bank Account",
|
||||||
"account_name":"Checking Account",
|
"account_name":"Checking Account",
|
||||||
"bank": "Citi Bank",
|
"bank": bank_name,
|
||||||
"account": "_Test Bank - _TC"
|
"account": account_name
|
||||||
}).insert()
|
}).insert()
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def add_transactions():
|
||||||
|
if frappe.flags.test_bank_transactions_created:
|
||||||
|
return
|
||||||
|
|
||||||
|
frappe.set_user("Administrator")
|
||||||
|
create_bank_account()
|
||||||
|
|
||||||
doc = frappe.get_doc({
|
doc = frappe.get_doc({
|
||||||
"doctype": "Bank Transaction",
|
"doctype": "Bank Transaction",
|
||||||
"description":"1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G",
|
"description":"1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G",
|
||||||
|
@ -1023,7 +1023,7 @@ def make_inter_company_journal_entry(name, voucher_type, company):
|
|||||||
return journal_entry.as_dict()
|
return journal_entry.as_dict()
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_reverse_journal_entry(source_name, target_doc=None, ignore_permissions=False):
|
def make_reverse_journal_entry(source_name, target_doc=None):
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
|
|
||||||
def update_accounts(source, target, source_parent):
|
def update_accounts(source, target, source_parent):
|
||||||
@ -1049,6 +1049,6 @@ def make_reverse_journal_entry(source_name, target_doc=None, ignore_permissions=
|
|||||||
},
|
},
|
||||||
"postprocess": update_accounts,
|
"postprocess": update_accounts,
|
||||||
},
|
},
|
||||||
}, target_doc, ignore_permissions=ignore_permissions)
|
}, target_doc)
|
||||||
|
|
||||||
return doclist
|
return doclist
|
@ -1172,30 +1172,23 @@ def make_payment_order(source_name, target_doc=None):
|
|||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
def set_missing_values(source, target):
|
def set_missing_values(source, target):
|
||||||
target.payment_order_type = "Payment Entry"
|
target.payment_order_type = "Payment Entry"
|
||||||
|
target.append('references', dict(
|
||||||
def update_item(source_doc, target_doc, source_parent):
|
reference_doctype="Payment Entry",
|
||||||
target_doc.bank_account = source_parent.party_bank_account
|
reference_name=source.name,
|
||||||
target_doc.amount = source_doc.allocated_amount
|
bank_account=source.party_bank_account,
|
||||||
target_doc.account = source_parent.paid_to
|
amount=source.paid_amount,
|
||||||
target_doc.payment_entry = source_parent.name
|
account=source.paid_to,
|
||||||
target_doc.supplier = source_parent.party
|
supplier=source.party,
|
||||||
target_doc.mode_of_payment = source_parent.mode_of_payment
|
mode_of_payment=source.mode_of_payment,
|
||||||
|
))
|
||||||
|
|
||||||
doclist = get_mapped_doc("Payment Entry", source_name, {
|
doclist = get_mapped_doc("Payment Entry", source_name, {
|
||||||
"Payment Entry": {
|
"Payment Entry": {
|
||||||
"doctype": "Payment Order",
|
"doctype": "Payment Order",
|
||||||
"validation": {
|
"validation": {
|
||||||
"docstatus": ["=", 1]
|
"docstatus": ["=", 1]
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"Payment Entry Reference": {
|
|
||||||
"doctype": "Payment Order Reference",
|
|
||||||
"validation": {
|
|
||||||
"docstatus": ["=", 1]
|
|
||||||
},
|
|
||||||
"postprocess": update_item
|
|
||||||
},
|
|
||||||
|
|
||||||
}, target_doc, set_missing_values)
|
}, target_doc, set_missing_values)
|
||||||
|
|
||||||
|
@ -21,10 +21,15 @@ class PaymentOrder(Document):
|
|||||||
if cancel:
|
if cancel:
|
||||||
status = 'Initiated'
|
status = 'Initiated'
|
||||||
|
|
||||||
ref_field = "status" if self.payment_order_type == "Payment Request" else "payment_order_status"
|
if self.payment_order_type == "Payment Request":
|
||||||
|
ref_field = "status"
|
||||||
|
ref_doc_field = frappe.scrub(self.payment_order_type)
|
||||||
|
else:
|
||||||
|
ref_field = "payment_order_status"
|
||||||
|
ref_doc_field = "reference_name"
|
||||||
|
|
||||||
for d in self.references:
|
for d in self.references:
|
||||||
frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
|
frappe.db.set_value(self.payment_order_type, d.get(ref_doc_field), ref_field, status)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@frappe.validate_and_sanitize_search_inputs
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
|
@ -5,6 +5,45 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
import unittest
|
import unittest
|
||||||
|
from frappe.utils import getdate
|
||||||
|
from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
|
||||||
|
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry, make_payment_order
|
||||||
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
|
|
||||||
class TestPaymentOrder(unittest.TestCase):
|
class TestPaymentOrder(unittest.TestCase):
|
||||||
pass
|
def setUp(self):
|
||||||
|
create_bank_account()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
for bt in frappe.get_all("Payment Order"):
|
||||||
|
doc = frappe.get_doc("Payment Order", bt.name)
|
||||||
|
doc.cancel()
|
||||||
|
doc.delete()
|
||||||
|
|
||||||
|
def test_payment_order_creation_against_payment_entry(self):
|
||||||
|
purchase_invoice = make_purchase_invoice()
|
||||||
|
payment_entry = get_payment_entry("Purchase Invoice", purchase_invoice.name, bank_account="_Test Bank - _TC")
|
||||||
|
payment_entry.reference_no = "_Test_Payment_Order"
|
||||||
|
payment_entry.reference_date = getdate()
|
||||||
|
payment_entry.party_bank_account = "Checking Account - Citi Bank"
|
||||||
|
payment_entry.insert()
|
||||||
|
payment_entry.submit()
|
||||||
|
|
||||||
|
doc = create_payment_order_against_payment_entry(payment_entry, "Payment Entry")
|
||||||
|
reference_doc = doc.get("references")[0]
|
||||||
|
self.assertEquals(reference_doc.reference_name, payment_entry.name)
|
||||||
|
self.assertEquals(reference_doc.reference_doctype, "Payment Entry")
|
||||||
|
self.assertEquals(reference_doc.supplier, "_Test Supplier")
|
||||||
|
self.assertEquals(reference_doc.amount, 250)
|
||||||
|
|
||||||
|
def create_payment_order_against_payment_entry(ref_doc, order_type):
|
||||||
|
payment_order = frappe.get_doc(dict(
|
||||||
|
doctype="Payment Order",
|
||||||
|
company="_Test Company",
|
||||||
|
payment_order_type=order_type,
|
||||||
|
company_bank_account="Checking Account - Citi Bank"
|
||||||
|
))
|
||||||
|
doc = make_payment_order(ref_doc.name, payment_order)
|
||||||
|
doc.save()
|
||||||
|
doc.submit()
|
||||||
|
return doc
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"creation": "2018-07-20 16:38:06.630813",
|
"creation": "2018-07-20 16:38:06.630813",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@ -10,7 +11,6 @@
|
|||||||
"column_break_4",
|
"column_break_4",
|
||||||
"supplier",
|
"supplier",
|
||||||
"payment_request",
|
"payment_request",
|
||||||
"payment_entry",
|
|
||||||
"mode_of_payment",
|
"mode_of_payment",
|
||||||
"bank_account_details",
|
"bank_account_details",
|
||||||
"bank_account",
|
"bank_account",
|
||||||
@ -103,17 +103,12 @@
|
|||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "payment_entry",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Payment Entry",
|
|
||||||
"options": "Payment Entry",
|
|
||||||
"read_only": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-05-08 13:56:25.724557",
|
"links": [],
|
||||||
|
"modified": "2020-09-04 08:29:51.014390",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Order Reference",
|
"name": "Payment Order Reference",
|
||||||
|
@ -25,6 +25,12 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
this.frm.set_df_property("credit_to", "print_hide", 0);
|
this.frm.set_df_property("credit_to", "print_hide", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger supplier event on load if supplier is available
|
||||||
|
// The reason for this is PI can be created from PR or PO and supplier is pre populated
|
||||||
|
if (this.frm.doc.supplier) {
|
||||||
|
this.frm.trigger('supplier');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(doc) {
|
refresh: function(doc) {
|
||||||
@ -135,6 +141,8 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.frm.set_df_property("tax_withholding_category", "hidden", doc.apply_tds ? 0 : 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
unblock_invoice: function() {
|
unblock_invoice: function() {
|
||||||
|
@ -132,6 +132,11 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if not self.due_date:
|
if not self.due_date:
|
||||||
self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company, self.bill_date)
|
self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company, self.bill_date)
|
||||||
|
|
||||||
|
tds_category = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category")
|
||||||
|
if tds_category and not for_validate:
|
||||||
|
self.apply_tds = 1
|
||||||
|
self.tax_withholding_category = tds_category
|
||||||
|
|
||||||
super(PurchaseInvoice, self).set_missing_values(for_validate)
|
super(PurchaseInvoice, self).set_missing_values(for_validate)
|
||||||
|
|
||||||
def check_conversion_rate(self):
|
def check_conversion_rate(self):
|
||||||
|
@ -256,7 +256,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name, companies):
|
|||||||
"""accumulate children's values in parent accounts"""
|
"""accumulate children's values in parent accounts"""
|
||||||
for d in reversed(accounts):
|
for d in reversed(accounts):
|
||||||
if d.parent_account:
|
if d.parent_account:
|
||||||
account = d.parent_account.split('-')[0].strip()
|
account = d.parent_account.split(' - ')[0].strip()
|
||||||
if not accounts_by_name.get(account):
|
if not accounts_by_name.get(account):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ class Asset(AccountsController):
|
|||||||
'assets': assets,
|
'assets': assets,
|
||||||
'purpose': 'Receipt',
|
'purpose': 'Receipt',
|
||||||
'company': self.company,
|
'company': self.company,
|
||||||
'transaction_date': getdate(nowdate()),
|
'transaction_date': getdate(self.purchase_date),
|
||||||
'reference_doctype': reference_doctype,
|
'reference_doctype': reference_doctype,
|
||||||
'reference_name': reference_docname
|
'reference_name': reference_docname
|
||||||
}).insert()
|
}).insert()
|
||||||
|
@ -255,7 +255,7 @@ class StatusUpdater(Document):
|
|||||||
args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
|
args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
|
||||||
from `tab%(second_source_dt)s`
|
from `tab%(second_source_dt)s`
|
||||||
where `%(second_join_field)s`="%(detail_id)s"
|
where `%(second_join_field)s`="%(detail_id)s"
|
||||||
and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s), 0) """ % args
|
and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s FOR UPDATE), 0)""" % args
|
||||||
|
|
||||||
if args['detail_id']:
|
if args['detail_id']:
|
||||||
if not args.get("extra_cond"): args["extra_cond"] = ""
|
if not args.get("extra_cond"): args["extra_cond"] = ""
|
||||||
|
@ -98,7 +98,8 @@ def add_attendance(events, start, end, conditions=None):
|
|||||||
e = {
|
e = {
|
||||||
"name": d.name,
|
"name": d.name,
|
||||||
"doctype": "Attendance",
|
"doctype": "Attendance",
|
||||||
"date": d.attendance_date,
|
"start": d.attendance_date,
|
||||||
|
"end": d.attendance_date,
|
||||||
"title": cstr(d.status),
|
"title": cstr(d.status),
|
||||||
"docstatus": d.docstatus
|
"docstatus": d.docstatus
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
frappe.views.calendar["Attendance"] = {
|
frappe.views.calendar["Attendance"] = {
|
||||||
field_map: {
|
|
||||||
"start": "attendance_date",
|
|
||||||
"end": "attendance_date",
|
|
||||||
"id": "name",
|
|
||||||
"docstatus": 1
|
|
||||||
},
|
|
||||||
options: {
|
options: {
|
||||||
header: {
|
header: {
|
||||||
left: 'prev,next today',
|
left: 'prev,next today',
|
||||||
|
@ -103,7 +103,7 @@ def add_assignments(events, start, end, conditions=None):
|
|||||||
"doctype": "Shift Assignment",
|
"doctype": "Shift Assignment",
|
||||||
"start_date": d.start_date,
|
"start_date": d.start_date,
|
||||||
"end_date": d.end_date if d.end_date else nowdate(),
|
"end_date": d.end_date if d.end_date else nowdate(),
|
||||||
"title": cstr(d.employee_name) + \
|
"title": cstr(d.employee_name) + ": "+ \
|
||||||
cstr(d.shift_type),
|
cstr(d.shift_type),
|
||||||
"docstatus": d.docstatus
|
"docstatus": d.docstatus
|
||||||
}
|
}
|
||||||
|
@ -240,15 +240,19 @@ def unpledge_security(loan=None, loan_security_pledge=None, as_dict=0, save=0, s
|
|||||||
unpledge_request = create_loan_security_unpledge(security_map, pledge_doc.loan,
|
unpledge_request = create_loan_security_unpledge(security_map, pledge_doc.loan,
|
||||||
pledge_doc.company, pledge_doc.applicant_type, pledge_doc.applicant)
|
pledge_doc.company, pledge_doc.applicant_type, pledge_doc.applicant)
|
||||||
|
|
||||||
if approve:
|
|
||||||
unpledge_request.status = 'Approved'
|
|
||||||
|
|
||||||
if save:
|
if save:
|
||||||
unpledge_request.save()
|
unpledge_request.save()
|
||||||
|
|
||||||
if submit:
|
if submit:
|
||||||
unpledge_request.submit()
|
unpledge_request.submit()
|
||||||
|
|
||||||
|
if approve:
|
||||||
|
if unpledge_request.docstatus == 1:
|
||||||
|
unpledge_request.status = 'Approved'
|
||||||
|
unpledge_request.save()
|
||||||
|
else:
|
||||||
|
frappe.throw(_('Only submittted unpledge requests can be approved'))
|
||||||
|
|
||||||
if as_dict:
|
if as_dict:
|
||||||
return unpledge_request
|
return unpledge_request
|
||||||
else:
|
else:
|
||||||
|
@ -317,6 +317,11 @@ class TestLoan(unittest.TestCase):
|
|||||||
self.assertEqual(loan.status, 'Closed')
|
self.assertEqual(loan.status, 'Closed')
|
||||||
self.assertEquals(sum(pledged_qty.values()), 0)
|
self.assertEquals(sum(pledged_qty.values()), 0)
|
||||||
|
|
||||||
|
amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
|
||||||
|
self.assertEqual(amounts['pending_principal_amount'], 0)
|
||||||
|
self.assertEqual(amounts['payable_principal_amount'], 0)
|
||||||
|
self.assertEqual(amounts['interest_amount'], 0)
|
||||||
|
|
||||||
def test_disbursal_check_with_shortfall(self):
|
def test_disbursal_check_with_shortfall(self):
|
||||||
pledges = [{
|
pledges = [{
|
||||||
"loan_security": "Test Security 2",
|
"loan_security": "Test Security 2",
|
||||||
|
@ -327,7 +327,7 @@ def get_amounts(amounts, against_loan, posting_date, payment_type):
|
|||||||
if not final_due_date:
|
if not final_due_date:
|
||||||
final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
|
final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
|
||||||
|
|
||||||
if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested'):
|
if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested', 'Closed'):
|
||||||
pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
|
pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
|
||||||
else:
|
else:
|
||||||
pending_principal_amount = against_loan_doc.disbursed_amount
|
pending_principal_amount = against_loan_doc.disbursed_amount
|
||||||
|
@ -20,9 +20,6 @@ class LoanSecurityUnpledge(Document):
|
|||||||
self.update_loan_status(cancel=1)
|
self.update_loan_status(cancel=1)
|
||||||
self.db_set('status', 'Requested')
|
self.db_set('status', 'Requested')
|
||||||
|
|
||||||
def on_submit(self):
|
|
||||||
self.approve()
|
|
||||||
|
|
||||||
def validate_duplicate_securities(self):
|
def validate_duplicate_securities(self):
|
||||||
security_list = []
|
security_list = []
|
||||||
for d in self.securities:
|
for d in self.securities:
|
||||||
|
@ -697,7 +697,7 @@ erpnext.patches.v12_0.update_bom_in_so_mr
|
|||||||
execute:frappe.delete_doc("Report", "Department Analytics")
|
execute:frappe.delete_doc("Report", "Department Analytics")
|
||||||
execute:frappe.rename_doc("Desk Page", "Loan Management", "Loan", force=True)
|
execute:frappe.rename_doc("Desk Page", "Loan Management", "Loan", force=True)
|
||||||
erpnext.patches.v12_0.update_uom_conversion_factor
|
erpnext.patches.v12_0.update_uom_conversion_factor
|
||||||
execute:frappe.delete_doc_if_exists("Page", "pos") #29-05-2020
|
erpnext.patches.v13_0.replace_pos_page_with_point_of_sale_page
|
||||||
erpnext.patches.v13_0.delete_old_purchase_reports
|
erpnext.patches.v13_0.delete_old_purchase_reports
|
||||||
erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
|
erpnext.patches.v12_0.set_italian_import_supplier_invoice_permissions
|
||||||
erpnext.patches.v13_0.update_subscription
|
erpnext.patches.v13_0.update_subscription
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if frappe.db.exists("Page", "point-of-sale"):
|
||||||
|
frappe.rename_doc("Page", "pos", "point-of-sale", 1, 1)
|
@ -5,8 +5,8 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe import _
|
from frappe import _, bold
|
||||||
from frappe.utils import getdate, date_diff
|
from frappe.utils import getdate, date_diff, comma_and, formatdate
|
||||||
|
|
||||||
class AdditionalSalary(Document):
|
class AdditionalSalary(Document):
|
||||||
|
|
||||||
@ -22,9 +22,37 @@ class AdditionalSalary(Document):
|
|||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
|
self.validate_recurring_additional_salary_overlap()
|
||||||
if self.amount < 0:
|
if self.amount < 0:
|
||||||
frappe.throw(_("Amount should not be less than zero."))
|
frappe.throw(_("Amount should not be less than zero."))
|
||||||
|
|
||||||
|
def validate_recurring_additional_salary_overlap(self):
|
||||||
|
if self.is_recurring:
|
||||||
|
additional_salaries = frappe.db.sql("""
|
||||||
|
SELECT
|
||||||
|
name
|
||||||
|
FROM `tabAdditional Salary`
|
||||||
|
WHERE
|
||||||
|
employee=%s
|
||||||
|
AND name <> %s
|
||||||
|
AND docstatus=1
|
||||||
|
AND is_recurring=1
|
||||||
|
AND salary_component = %s
|
||||||
|
AND to_date >= %s
|
||||||
|
AND from_date <= %s""",
|
||||||
|
(self.employee, self.name, self.salary_component, self.from_date, self.to_date), as_dict = 1)
|
||||||
|
|
||||||
|
additional_salaries = [salary.name for salary in additional_salaries]
|
||||||
|
|
||||||
|
if additional_salaries and len(additional_salaries):
|
||||||
|
frappe.throw(_("Additional Salary: {0} already exist for Salary Component: {1} for period {2} and {3}").format(
|
||||||
|
bold(comma_and(additional_salaries)),
|
||||||
|
bold(self.salary_component),
|
||||||
|
bold(formatdate(self.from_date)),
|
||||||
|
bold(formatdate(self.to_date)
|
||||||
|
)))
|
||||||
|
|
||||||
|
|
||||||
def validate_dates(self):
|
def validate_dates(self):
|
||||||
date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee,
|
date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||||
["date_of_joining", "relieving_date"])
|
["date_of_joining", "relieving_date"])
|
||||||
|
@ -13,13 +13,15 @@ def get_field_filter_data():
|
|||||||
for f in fields:
|
for f in fields:
|
||||||
doctype = f.get_link_doctype()
|
doctype = f.get_link_doctype()
|
||||||
|
|
||||||
# apply enable/disable filter
|
# apply enable/disable/show_in_website filter
|
||||||
meta = frappe.get_meta(doctype)
|
meta = frappe.get_meta(doctype)
|
||||||
filters = {}
|
filters = {}
|
||||||
if meta.has_field('enabled'):
|
if meta.has_field('enabled'):
|
||||||
filters['enabled'] = 1
|
filters['enabled'] = 1
|
||||||
if meta.has_field('disabled'):
|
if meta.has_field('disabled'):
|
||||||
filters['disabled'] = 0
|
filters['disabled'] = 0
|
||||||
|
if meta.has_field('show_in_website'):
|
||||||
|
filters['show_in_website'] = 1
|
||||||
|
|
||||||
values = [d.name for d in frappe.get_all(doctype, filters)]
|
values = [d.name for d in frappe.get_all(doctype, filters)]
|
||||||
filter_data.append([f, values])
|
filter_data.append([f, values])
|
||||||
|
@ -16,9 +16,15 @@ from frappe.utils.jinja import render_template
|
|||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
filters = filters if isinstance(filters, _dict) else _dict(filters)
|
filters = filters if isinstance(filters, _dict) else _dict(filters)
|
||||||
|
|
||||||
if not filters:
|
if not filters:
|
||||||
filters.setdefault('fiscal_year', get_fiscal_year(nowdate())[0])
|
filters.setdefault('fiscal_year', get_fiscal_year(nowdate())[0])
|
||||||
filters.setdefault('company', frappe.db.get_default("company"))
|
filters.setdefault('company', frappe.db.get_default("company"))
|
||||||
|
|
||||||
|
region = frappe.db.get_value("Company", fieldname = ["country"], filters = { "name": filters.company })
|
||||||
|
if region != 'United States':
|
||||||
|
return [],[]
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
columns = get_columns()
|
columns = get_columns()
|
||||||
data = frappe.db.sql("""
|
data = frappe.db.sql("""
|
||||||
|
@ -24,7 +24,7 @@ class TestUnitedStates(unittest.TestCase):
|
|||||||
|
|
||||||
def test_irs_1099_report(self):
|
def test_irs_1099_report(self):
|
||||||
make_payment_entry_to_irs_1099_supplier()
|
make_payment_entry_to_irs_1099_supplier()
|
||||||
filters = frappe._dict({"fiscal_year": "_Test Fiscal Year 2016", "company": "_Test Company"})
|
filters = frappe._dict({"fiscal_year": "_Test Fiscal Year 2016", "company": "_Test Company 1"})
|
||||||
columns, data = execute_1099_report(filters)
|
columns, data = execute_1099_report(filters)
|
||||||
print(columns, data)
|
print(columns, data)
|
||||||
expected_row = {'supplier': '_US 1099 Test Supplier',
|
expected_row = {'supplier': '_US 1099 Test Supplier',
|
||||||
@ -42,10 +42,10 @@ def make_payment_entry_to_irs_1099_supplier():
|
|||||||
|
|
||||||
pe = frappe.new_doc("Payment Entry")
|
pe = frappe.new_doc("Payment Entry")
|
||||||
pe.payment_type = "Pay"
|
pe.payment_type = "Pay"
|
||||||
pe.company = "_Test Company"
|
pe.company = "_Test Company 1"
|
||||||
pe.posting_date = "2016-01-10"
|
pe.posting_date = "2016-01-10"
|
||||||
pe.paid_from = "_Test Bank USD - _TC"
|
pe.paid_from = "_Test Bank USD - _TC1"
|
||||||
pe.paid_to = "_Test Payable USD - _TC"
|
pe.paid_to = "_Test Payable USD - _TC1"
|
||||||
pe.paid_amount = 100
|
pe.paid_amount = 100
|
||||||
pe.received_amount = 100
|
pe.received_amount = 100
|
||||||
pe.reference_no = "For IRS 1099 testing"
|
pe.reference_no = "For IRS 1099 testing"
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"label": "Key Reports",
|
"label": "Key Reports",
|
||||||
"links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]"
|
"links": "[\n {\n \"dependencies\": [\n \"Item Price\"\n ],\n \"doctype\": \"Item Price\",\n \"is_query_report\": false,\n \"label\": \"Item-wise Price List Rate\",\n \"name\": \"Item-wise Price List Rate\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Stock Entry\"\n ],\n \"doctype\": \"Stock Entry\",\n \"is_query_report\": true,\n \"label\": \"Stock Analytics\",\n \"name\": \"Stock Analytics\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Item\"\n ],\n \"doctype\": \"Item\",\n \"is_query_report\": true,\n \"label\": \"Stock Qty vs Serial No Count\",\n \"name\": \"Stock Qty vs Serial No Count\",\n \"onboard\": 1,\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Delivery Note\"\n ],\n \"doctype\": \"Delivery Note\",\n \"is_query_report\": true,\n \"label\": \"Delivery Note Trends\",\n \"name\": \"Delivery Note Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Receipt\"\n ],\n \"doctype\": \"Purchase Receipt\",\n \"is_query_report\": true,\n \"label\": \"Purchase Receipt Trends\",\n \"name\": \"Purchase Receipt Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Order\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Bin\"\n ],\n \"doctype\": \"Bin\",\n \"is_query_report\": true,\n \"label\": \"Item Shortage Report\",\n \"name\": \"Item Shortage Report\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Batch\"\n ],\n \"doctype\": \"Batch\",\n \"is_query_report\": true,\n \"label\": \"Batch-Wise Balance History\",\n \"name\": \"Batch-Wise Balance History\",\n \"type\": \"report\"\n }\n]"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
@ -58,7 +58,7 @@
|
|||||||
"idx": 0,
|
"idx": 0,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"label": "Stock",
|
"label": "Stock",
|
||||||
"modified": "2020-05-30 17:32:11.062681",
|
"modified": "2020-08-11 17:29:32.626067",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock",
|
"name": "Stock",
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
frappe.query_reports["Stock Qty vs Serial No Count"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname":"company",
|
||||||
|
"label": __("Company"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company",
|
||||||
|
"default": frappe.defaults.get_user_default("Company"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"warehouse",
|
||||||
|
"label": __("Warehouse"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Warehouse",
|
||||||
|
"get_query": function() {
|
||||||
|
const company = frappe.query_report.get_filter_value('company');
|
||||||
|
return {
|
||||||
|
filters: { 'company': company }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
"formatter": function (value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (column.fieldname == "difference" && data) {
|
||||||
|
if (data.difference > 0) {
|
||||||
|
value = "<span style='color:red'>" + value + "</span>";
|
||||||
|
}
|
||||||
|
else if (data.difference < 0) {
|
||||||
|
value = "<span style='color:red'>" + value + "</span>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"creation": "2020-07-23 19:31:32.395011",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2020-07-23 19:32:02.168185",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Stock",
|
||||||
|
"name": "Stock Qty vs Serial No Count",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "Item",
|
||||||
|
"report_name": "Stock Qty vs Serial No Count",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Stock Manager"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "Stock User"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
columns = get_columns()
|
||||||
|
data = get_data(filters.warehouse)
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_columns():
|
||||||
|
columns = [
|
||||||
|
{
|
||||||
|
"label": _("Item Code"),
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Item",
|
||||||
|
"width": 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Item Name"),
|
||||||
|
"fieldname": "item_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"width": 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Serial No Count"),
|
||||||
|
"fieldname": "total",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"width": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Stock Qty"),
|
||||||
|
"fieldname": "stock_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"width": 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": _("Difference"),
|
||||||
|
"fieldname": "difference",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"width": 150
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return columns
|
||||||
|
|
||||||
|
def get_data(warehouse):
|
||||||
|
serial_item_list = frappe.get_all("Item", filters={
|
||||||
|
'has_serial_no': True,
|
||||||
|
}, fields=['item_code', 'item_name'])
|
||||||
|
|
||||||
|
status_list = ['Active', 'Expired']
|
||||||
|
data = []
|
||||||
|
for item in serial_item_list:
|
||||||
|
total_serial_no = frappe.db.count("Serial No",
|
||||||
|
filters={"item_code": item.item_code, "status": ("in", status_list), "warehouse": warehouse})
|
||||||
|
|
||||||
|
actual_qty = frappe.db.get_value('Bin', fieldname=['actual_qty'],
|
||||||
|
filters={"warehouse": warehouse, "item_code": item.item_code})
|
||||||
|
|
||||||
|
# frappe.db.get_value returns null if no record exist.
|
||||||
|
if not actual_qty:
|
||||||
|
actual_qty = 0
|
||||||
|
|
||||||
|
difference = total_serial_no - actual_qty
|
||||||
|
|
||||||
|
row = {
|
||||||
|
"item_code": item.item_code,
|
||||||
|
"item_name": item.item_name,
|
||||||
|
"total": total_serial_no,
|
||||||
|
"stock_qty": actual_qty,
|
||||||
|
"difference": difference,
|
||||||
|
}
|
||||||
|
|
||||||
|
data.append(row)
|
||||||
|
|
||||||
|
return data
|
Loading…
Reference in New Issue
Block a user