Merge branch 'develop' of https://github.com/frappe/erpnext into crm-reports
This commit is contained in:
commit
61bfb8c817
@ -26,22 +26,22 @@ def test_create_test_data():
|
|||||||
"item_group": "_Test Item Group",
|
"item_group": "_Test Item Group",
|
||||||
"item_name": "_Test Tesla Car",
|
"item_name": "_Test Tesla Car",
|
||||||
"apply_warehouse_wise_reorder_level": 0,
|
"apply_warehouse_wise_reorder_level": 0,
|
||||||
"warehouse":"_Test Warehouse - _TC",
|
"warehouse":"Stores - TCP1",
|
||||||
"gst_hsn_code": "999800",
|
"gst_hsn_code": "999800",
|
||||||
"valuation_rate": 5000,
|
"valuation_rate": 5000,
|
||||||
"standard_rate":5000,
|
"standard_rate":5000,
|
||||||
"item_defaults": [{
|
"item_defaults": [{
|
||||||
"company": "_Test Company",
|
"company": "_Test Company with perpetual inventory",
|
||||||
"default_warehouse": "_Test Warehouse - _TC",
|
"default_warehouse": "Stores - TCP1",
|
||||||
"default_price_list":"_Test Price List",
|
"default_price_list":"_Test Price List",
|
||||||
"expense_account": "_Test Account Cost for Goods Sold - _TC",
|
"expense_account": "Cost of Goods Sold - TCP1",
|
||||||
"buying_cost_center": "_Test Cost Center - _TC",
|
"buying_cost_center": "Main - TCP1",
|
||||||
"selling_cost_center": "_Test Cost Center - _TC",
|
"selling_cost_center": "Main - TCP1",
|
||||||
"income_account": "Sales - _TC"
|
"income_account": "Sales - TCP1"
|
||||||
}],
|
}],
|
||||||
"show_in_website": 1,
|
"show_in_website": 1,
|
||||||
"route":"-test-tesla-car",
|
"route":"-test-tesla-car",
|
||||||
"website_warehouse": "_Test Warehouse - _TC"
|
"website_warehouse": "Stores - TCP1"
|
||||||
})
|
})
|
||||||
item.insert()
|
item.insert()
|
||||||
# create test item price
|
# create test item price
|
||||||
@ -63,12 +63,12 @@ def test_create_test_data():
|
|||||||
"items": [{
|
"items": [{
|
||||||
"item_code": "_Test Tesla Car"
|
"item_code": "_Test Tesla Car"
|
||||||
}],
|
}],
|
||||||
"warehouse":"_Test Warehouse - _TC",
|
"warehouse":"Stores - TCP1",
|
||||||
"coupon_code_based":1,
|
"coupon_code_based":1,
|
||||||
"selling": 1,
|
"selling": 1,
|
||||||
"rate_or_discount": "Discount Percentage",
|
"rate_or_discount": "Discount Percentage",
|
||||||
"discount_percentage": 30,
|
"discount_percentage": 30,
|
||||||
"company": "_Test Company",
|
"company": "_Test Company with perpetual inventory",
|
||||||
"currency":"INR",
|
"currency":"INR",
|
||||||
"for_price_list":"_Test Price List"
|
"for_price_list":"_Test Price List"
|
||||||
})
|
})
|
||||||
@ -112,7 +112,10 @@ class TestCouponCode(unittest.TestCase):
|
|||||||
self.assertEqual(coupon_code.get("used"),0)
|
self.assertEqual(coupon_code.get("used"),0)
|
||||||
|
|
||||||
def test_2_sales_order_with_coupon_code(self):
|
def test_2_sales_order_with_coupon_code(self):
|
||||||
so = make_sales_order(customer="_Test Customer",selling_price_list="_Test Price List",item_code="_Test Tesla Car", rate=5000,qty=1, do_not_submit=True)
|
so = make_sales_order(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1',
|
||||||
|
customer="_Test Customer", selling_price_list="_Test Price List", item_code="_Test Tesla Car", rate=5000,qty=1,
|
||||||
|
do_not_submit=True)
|
||||||
|
|
||||||
so = frappe.get_doc('Sales Order', so.name)
|
so = frappe.get_doc('Sales Order', so.name)
|
||||||
# check item price before coupon code is applied
|
# check item price before coupon code is applied
|
||||||
self.assertEqual(so.items[0].rate, 5000)
|
self.assertEqual(so.items[0].rate, 5000)
|
||||||
@ -120,7 +123,7 @@ class TestCouponCode(unittest.TestCase):
|
|||||||
so.sales_partner='_Test Coupon Partner'
|
so.sales_partner='_Test Coupon Partner'
|
||||||
so.save()
|
so.save()
|
||||||
# check item price after coupon code is applied
|
# check item price after coupon code is applied
|
||||||
self.assertEqual(so.items[0].rate, 3500)
|
self.assertEqual(so.items[0].rate, 3500)
|
||||||
so.submit()
|
so.submit()
|
||||||
|
|
||||||
def test_3_check_coupon_code_used_after_so(self):
|
def test_3_check_coupon_code_used_after_so(self):
|
||||||
|
@ -6,6 +6,7 @@ import unittest, frappe
|
|||||||
from frappe.utils import flt, nowdate
|
from frappe.utils import flt, nowdate
|
||||||
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
from erpnext.accounts.doctype.account.test_account import get_inventory_account
|
||||||
from erpnext.exceptions import InvalidAccountCurrency
|
from erpnext.exceptions import InvalidAccountCurrency
|
||||||
|
from erpnext.accounts.general_ledger import StockAccountInvalidTransaction
|
||||||
|
|
||||||
class TestJournalEntry(unittest.TestCase):
|
class TestJournalEntry(unittest.TestCase):
|
||||||
def test_journal_entry_with_against_jv(self):
|
def test_journal_entry_with_against_jv(self):
|
||||||
@ -81,19 +82,46 @@ class TestJournalEntry(unittest.TestCase):
|
|||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||||
set_perpetual_inventory()
|
set_perpetual_inventory()
|
||||||
|
|
||||||
jv = frappe.copy_doc(test_records[0])
|
jv = frappe.copy_doc({
|
||||||
|
"cheque_date": nowdate(),
|
||||||
|
"cheque_no": "33",
|
||||||
|
"company": "_Test Company with perpetual inventory",
|
||||||
|
"doctype": "Journal Entry",
|
||||||
|
"accounts": [
|
||||||
|
{
|
||||||
|
"account": "Debtors - TCP1",
|
||||||
|
"party_type": "Customer",
|
||||||
|
"party": "_Test Customer",
|
||||||
|
"credit_in_account_currency": 400.0,
|
||||||
|
"debit_in_account_currency": 0.0,
|
||||||
|
"doctype": "Journal Entry Account",
|
||||||
|
"parentfield": "accounts",
|
||||||
|
"cost_center": "Main - TCP1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account": "_Test Bank - TCP1",
|
||||||
|
"credit_in_account_currency": 0.0,
|
||||||
|
"debit_in_account_currency": 400.0,
|
||||||
|
"doctype": "Journal Entry Account",
|
||||||
|
"parentfield": "accounts",
|
||||||
|
"cost_center": "Main - TCP1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"naming_series": "_T-Journal Entry-",
|
||||||
|
"posting_date": nowdate(),
|
||||||
|
"user_remark": "test",
|
||||||
|
"voucher_type": "Bank Entry"
|
||||||
|
})
|
||||||
|
|
||||||
jv.get("accounts")[0].update({
|
jv.get("accounts")[0].update({
|
||||||
"account": get_inventory_account('_Test Company'),
|
"account": get_inventory_account('_Test Company with perpetual inventory'),
|
||||||
"company": "_Test Company",
|
"company": "_Test Company with perpetual inventory",
|
||||||
"party_type": None,
|
"party_type": None,
|
||||||
"party": None
|
"party": None
|
||||||
})
|
})
|
||||||
|
|
||||||
jv.insert()
|
|
||||||
|
|
||||||
from erpnext.accounts.general_ledger import StockAccountInvalidTransaction
|
|
||||||
self.assertRaises(StockAccountInvalidTransaction, jv.submit)
|
self.assertRaises(StockAccountInvalidTransaction, jv.submit)
|
||||||
|
jv.cancel()
|
||||||
set_perpetual_inventory(0)
|
set_perpetual_inventory(0)
|
||||||
|
|
||||||
def test_multi_currency(self):
|
def test_multi_currency(self):
|
||||||
|
@ -25,7 +25,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
});
|
});
|
||||||
frm.set_query("party_type", function() {
|
frm.set_query("party_type", function() {
|
||||||
return{
|
return{
|
||||||
"filters": {
|
filters: {
|
||||||
"name": ["in", Object.keys(frappe.boot.party_account_types)],
|
"name": ["in", Object.keys(frappe.boot.party_account_types)],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.set_query("party_bank_account", function() {
|
frm.set_query("party_bank_account", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
"is_company_account":0,
|
is_company_account: 0,
|
||||||
party_type: frm.doc.party_type,
|
party_type: frm.doc.party_type,
|
||||||
party: frm.doc.party
|
party: frm.doc.party
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
frm.set_query("bank_account", function() {
|
frm.set_query("bank_account", function() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
"is_company_account":1
|
is_company_account: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -342,7 +342,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
() => {
|
() => {
|
||||||
frm.set_party_account_based_on_party = false;
|
frm.set_party_account_based_on_party = false;
|
||||||
if (r.message.bank_account) {
|
if (r.message.bank_account) {
|
||||||
frm.set_value("party_bank_account", r.message.bank_account);
|
frm.set_value("bank_account", r.message.bank_account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -23,13 +23,13 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
import time
|
import time
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.assertRaises(frappe.TimestampMismatchError, w2.save)
|
self.assertRaises(frappe.TimestampMismatchError, w2.save)
|
||||||
|
|
||||||
def test_change_naming_series(self):
|
def test_change_naming_series(self):
|
||||||
inv = create_pos_invoice(do_not_submit=1)
|
inv = create_pos_invoice(do_not_submit=1)
|
||||||
inv.naming_series = 'TEST-'
|
inv.naming_series = 'TEST-'
|
||||||
|
|
||||||
self.assertRaises(frappe.CannotChangeConstantError, inv.save)
|
self.assertRaises(frappe.CannotChangeConstantError, inv.save)
|
||||||
|
|
||||||
def test_discount_and_inclusive_tax(self):
|
def test_discount_and_inclusive_tax(self):
|
||||||
inv = create_pos_invoice(qty=100, rate=50, do_not_save=1)
|
inv = create_pos_invoice(qty=100, rate=50, do_not_save=1)
|
||||||
inv.append("taxes", {
|
inv.append("taxes", {
|
||||||
@ -66,7 +66,7 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(inv.net_total, 4298.25)
|
self.assertEqual(inv.net_total, 4298.25)
|
||||||
self.assertEqual(inv.grand_total, 4900.00)
|
self.assertEqual(inv.grand_total, 4900.00)
|
||||||
|
|
||||||
def test_tax_calculation_with_multiple_items(self):
|
def test_tax_calculation_with_multiple_items(self):
|
||||||
inv = create_pos_invoice(qty=84, rate=4.6, do_not_save=True)
|
inv = create_pos_invoice(qty=84, rate=4.6, do_not_save=True)
|
||||||
item_row = inv.get("items")[0]
|
item_row = inv.get("items")[0]
|
||||||
@ -148,7 +148,7 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(inv.grand_total, 5675.57)
|
self.assertEqual(inv.grand_total, 5675.57)
|
||||||
self.assertEqual(inv.rounding_adjustment, 0.43)
|
self.assertEqual(inv.rounding_adjustment, 0.43)
|
||||||
self.assertEqual(inv.rounded_total, 5676.0)
|
self.assertEqual(inv.rounded_total, 5676.0)
|
||||||
|
|
||||||
def test_tax_calculation_with_multiple_items_and_discount(self):
|
def test_tax_calculation_with_multiple_items_and_discount(self):
|
||||||
inv = create_pos_invoice(qty=1, rate=75, do_not_save=True)
|
inv = create_pos_invoice(qty=1, rate=75, do_not_save=True)
|
||||||
item_row = inv.get("items")[0]
|
item_row = inv.get("items")[0]
|
||||||
@ -194,7 +194,7 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(pos_return.get('payments')[0].amount, -500)
|
self.assertEqual(pos_return.get('payments')[0].amount, -500)
|
||||||
self.assertEqual(pos_return.get('payments')[1].amount, -500)
|
self.assertEqual(pos_return.get('payments')[1].amount, -500)
|
||||||
|
|
||||||
def test_pos_change_amount(self):
|
def test_pos_change_amount(self):
|
||||||
pos = create_pos_invoice(company= "_Test Company", debit_to="Debtors - _TC",
|
pos = create_pos_invoice(company= "_Test Company", debit_to="Debtors - _TC",
|
||||||
income_account = "Sales - _TC", expense_account = "Cost of Goods Sold - _TC", rate=105,
|
income_account = "Sales - _TC", expense_account = "Cost of Goods Sold - _TC", rate=105,
|
||||||
@ -208,33 +208,43 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(pos.grand_total, 105.0)
|
self.assertEqual(pos.grand_total, 105.0)
|
||||||
self.assertEqual(pos.change_amount, 5.0)
|
self.assertEqual(pos.change_amount, 5.0)
|
||||||
|
|
||||||
def test_without_payment(self):
|
def test_without_payment(self):
|
||||||
inv = create_pos_invoice(do_not_save=1)
|
inv = create_pos_invoice(do_not_save=1)
|
||||||
# Check that the invoice cannot be submitted without payments
|
# Check that the invoice cannot be submitted without payments
|
||||||
inv.payments = []
|
inv.payments = []
|
||||||
self.assertRaises(frappe.ValidationError, inv.insert)
|
self.assertRaises(frappe.ValidationError, inv.insert)
|
||||||
|
|
||||||
def test_serialized_item_transaction(self):
|
def test_serialized_item_transaction(self):
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||||
|
|
||||||
se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
|
se = make_serialized_item(company='_Test Company with perpetual inventory',
|
||||||
|
target_warehouse="Stores - TCP1", cost_center='Main - TCP1', expense_account='Cost of Goods Sold - TCP1')
|
||||||
|
|
||||||
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
|
||||||
|
|
||||||
pos = create_pos_invoice(item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
pos = create_pos_invoice(company='_Test Company with perpetual inventory', debit_to='Debtors - TCP1',
|
||||||
|
account_for_change_amount='Cash - TCP1', warehouse='Stores - TCP1', income_account='Sales - TCP1',
|
||||||
|
expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1',
|
||||||
|
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
||||||
|
|
||||||
pos.get("items")[0].serial_no = serial_nos[0]
|
pos.get("items")[0].serial_no = serial_nos[0]
|
||||||
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 1000})
|
||||||
|
|
||||||
pos.insert()
|
pos.insert()
|
||||||
pos.submit()
|
pos.submit()
|
||||||
|
|
||||||
pos2 = create_pos_invoice(item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
pos2 = create_pos_invoice(company='_Test Company with perpetual inventory', debit_to='Debtors - TCP1',
|
||||||
|
account_for_change_amount='Cash - TCP1', warehouse='Stores - TCP1', income_account='Sales - TCP1',
|
||||||
|
expense_account='Cost of Goods Sold - TCP1', cost_center='Main - TCP1',
|
||||||
|
item=se.get("items")[0].item_code, rate=1000, do_not_save=1)
|
||||||
|
|
||||||
pos2.get("items")[0].serial_no = serial_nos[0]
|
pos2.get("items")[0].serial_no = serial_nos[0]
|
||||||
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - TCP1', 'amount': 1000})
|
||||||
|
|
||||||
self.assertRaises(frappe.ValidationError, pos2.insert)
|
self.assertRaises(frappe.ValidationError, pos2.insert)
|
||||||
|
|
||||||
def test_loyalty_points(self):
|
def test_loyalty_points(self):
|
||||||
from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records
|
from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records
|
||||||
from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
|
from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
|
||||||
@ -255,14 +265,14 @@ class TestPOSInvoice(unittest.TestCase):
|
|||||||
inv.cancel()
|
inv.cancel()
|
||||||
after_cancel_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
|
after_cancel_lp_details = get_loyalty_program_details_with_points(inv.customer, company=inv.company, loyalty_program=inv.loyalty_program)
|
||||||
self.assertEqual(after_cancel_lp_details.loyalty_points, before_lp_details.loyalty_points)
|
self.assertEqual(after_cancel_lp_details.loyalty_points, before_lp_details.loyalty_points)
|
||||||
|
|
||||||
def test_loyalty_points_redeemption(self):
|
def test_loyalty_points_redeemption(self):
|
||||||
from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
|
from erpnext.accounts.doctype.loyalty_program.loyalty_program import get_loyalty_program_details_with_points
|
||||||
# add 10 loyalty points
|
# add 10 loyalty points
|
||||||
create_pos_invoice(customer="Test Loyalty Customer", rate=10000)
|
create_pos_invoice(customer="Test Loyalty Customer", rate=10000)
|
||||||
|
|
||||||
before_lp_details = get_loyalty_program_details_with_points("Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty")
|
before_lp_details = get_loyalty_program_details_with_points("Test Loyalty Customer", company="_Test Company", loyalty_program="Test Single Loyalty")
|
||||||
|
|
||||||
inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1)
|
inv = create_pos_invoice(customer="Test Loyalty Customer", rate=10000, do_not_save=1)
|
||||||
inv.redeem_loyalty_points = 1
|
inv.redeem_loyalty_points = 1
|
||||||
inv.loyalty_points = before_lp_details.loyalty_points
|
inv.loyalty_points = before_lp_details.loyalty_points
|
||||||
@ -299,7 +309,7 @@ def create_pos_invoice(**args):
|
|||||||
pos_inv.return_against = args.return_against
|
pos_inv.return_against = args.return_against
|
||||||
pos_inv.currency=args.currency or "INR"
|
pos_inv.currency=args.currency or "INR"
|
||||||
pos_inv.conversion_rate = args.conversion_rate or 1
|
pos_inv.conversion_rate = args.conversion_rate or 1
|
||||||
pos_inv.account_for_change_amount = "Cash - _TC"
|
pos_inv.account_for_change_amount = args.account_for_change_amount or "Cash - _TC"
|
||||||
|
|
||||||
pos_inv.append("items", {
|
pos_inv.append("items", {
|
||||||
"item_code": args.item or args.item_code or "_Test Item",
|
"item_code": args.item or args.item_code or "_Test Item",
|
||||||
|
@ -158,8 +158,10 @@ def validate_account_for_perpetual_inventory(gl_map):
|
|||||||
if account not in aii_accounts:
|
if account not in aii_accounts:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Always use current date to get stock and account balance as there can future entries for
|
||||||
|
# other items
|
||||||
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(account,
|
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(account,
|
||||||
gl_map[0].posting_date, gl_map[0].company)
|
getdate(), gl_map[0].company)
|
||||||
|
|
||||||
if gl_map[0].voucher_type=="Journal Entry":
|
if gl_map[0].voucher_type=="Journal Entry":
|
||||||
# In case of Journal Entry, there are no corresponding SL entries,
|
# In case of Journal Entry, there are no corresponding SL entries,
|
||||||
@ -169,7 +171,6 @@ def validate_account_for_perpetual_inventory(gl_map):
|
|||||||
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
|
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
|
||||||
.format(account), StockAccountInvalidTransaction)
|
.format(account), StockAccountInvalidTransaction)
|
||||||
|
|
||||||
# This has been comment for a temporary, will add this code again on release of immutable ledger
|
|
||||||
elif account_bal != stock_bal:
|
elif account_bal != stock_bal:
|
||||||
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
|
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
|
||||||
currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
|
currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
|
||||||
|
@ -97,7 +97,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "default_bank_account",
|
"fieldname": "default_bank_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Default Bank Account",
|
"label": "Default Company Bank Account",
|
||||||
"options": "Bank Account"
|
"options": "Bank Account"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -384,7 +384,7 @@
|
|||||||
"idx": 370,
|
"idx": 370,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-03-17 09:48:30.578242",
|
"modified": "2020-06-17 23:18:20",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Supplier",
|
"name": "Supplier",
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
"name": "Lead Details",
|
"name": "Lead Details",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"prepared_report": 0,
|
"prepared_report": 0,
|
||||||
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n\t`tabLead`.notes as \"Notes::360\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabDynamic Link` on (\n\t\t`tabDynamic Link`.link_name=`tabLead`.name \n\t\tand `tabDynamic Link`.parenttype = 'Address'\n\t)\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.name=`tabDynamic Link`.parent\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
|
|
||||||
"ref_doctype": "Lead",
|
"ref_doctype": "Lead",
|
||||||
"report_name": "Lead Details",
|
"report_name": "Lead Details",
|
||||||
"report_type": "Script Report",
|
"report_type": "Script Report",
|
||||||
|
@ -40,7 +40,7 @@ def get_appointments_to_invoice(patient, company):
|
|||||||
patient_appointments = frappe.get_list(
|
patient_appointments = frappe.get_list(
|
||||||
'Patient Appointment',
|
'Patient Appointment',
|
||||||
fields = '*',
|
fields = '*',
|
||||||
filters = {'patient': patient.name, 'company': company, 'invoiced': 0},
|
filters = {'patient': patient.name, 'company': company, 'invoiced': 0, 'status': ['not in', 'Cancelled']},
|
||||||
order_by = 'appointment_date'
|
order_by = 'appointment_date'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ frappe.views.calendar["Holiday List"] = {
|
|||||||
"title": "description",
|
"title": "description",
|
||||||
"allDay": "allDay"
|
"allDay": "allDay"
|
||||||
},
|
},
|
||||||
|
order_by: `from_date`,
|
||||||
get_events_method: "erpnext.hr.doctype.holiday_list.holiday_list.get_events",
|
get_events_method: "erpnext.hr.doctype.holiday_list.holiday_list.get_events",
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
|
@ -29,6 +29,14 @@ frappe.ui.form.on('Member', {
|
|||||||
frappe.set_route('query-report', 'Accounts Receivable', {member:frm.doc.name});
|
frappe.set_route('query-report', 'Accounts Receivable', {member:frm.doc.name});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!frm.doc.customer) {
|
||||||
|
frm.add_custom_button(__('Create Customer'), () => {
|
||||||
|
frm.call('make_customer_and_link').then(() => {
|
||||||
|
frm.reload_doc();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// indicator
|
// indicator
|
||||||
erpnext.utils.set_party_dashboard_indicators(frm);
|
erpnext.utils.set_party_dashboard_indicators(frm);
|
||||||
|
|
||||||
|
@ -53,6 +53,19 @@ class Member(Document):
|
|||||||
|
|
||||||
return subscription
|
return subscription
|
||||||
|
|
||||||
|
def make_customer_and_link(self):
|
||||||
|
if self.customer:
|
||||||
|
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,
|
||||||
|
'phone': None
|
||||||
|
}))
|
||||||
|
|
||||||
|
self.customer = cust
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
|
||||||
def get_or_create_member(user_details):
|
def get_or_create_member(user_details):
|
||||||
member_list = frappe.get_all("Member", filters={'email': user_details.email, 'membership_type': user_details.plan_id})
|
member_list = frappe.get_all("Member", filters={'email': user_details.email, 'membership_type': user_details.plan_id})
|
||||||
if member_list and member_list[0]:
|
if member_list and member_list[0]:
|
||||||
@ -83,8 +96,10 @@ def create_customer(user_details):
|
|||||||
try:
|
try:
|
||||||
contact = frappe.new_doc("Contact")
|
contact = frappe.new_doc("Contact")
|
||||||
contact.first_name = user_details.fullname
|
contact.first_name = user_details.fullname
|
||||||
contact.add_phone(user_details.mobile, is_primary_phone=1, is_primary_mobile_no=1)
|
if user_details.mobile:
|
||||||
contact.add_email(user_details.email, is_primary=1)
|
contact.add_phone(user_details.mobile, is_primary_phone=1, is_primary_mobile_no=1)
|
||||||
|
if user_details.email:
|
||||||
|
contact.add_email(user_details.email, is_primary=1)
|
||||||
contact.insert(ignore_permissions=True)
|
contact.insert(ignore_permissions=True)
|
||||||
|
|
||||||
contact.append("links", {
|
contact.append("links", {
|
||||||
@ -121,7 +136,7 @@ def create_member_subscription_order(user_details):
|
|||||||
'subscription_id': 'sub_EZycCvXFvqnC6p'
|
'subscription_id': 'sub_EZycCvXFvqnC6p'
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
# {"plan_id":"IFF Starter","fullname":"Shivam Mishra","mobile":"7506056962","email":"shivam@shivam.dev","pan":"Testing123"}
|
|
||||||
user_details = frappe._dict(user_details)
|
user_details = frappe._dict(user_details)
|
||||||
member = get_or_create_member(user_details)
|
member = get_or_create_member(user_details)
|
||||||
if not member:
|
if not member:
|
||||||
|
@ -120,13 +120,15 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "webhook_payload",
|
"fieldname": "webhook_payload",
|
||||||
"fieldtype": "Code",
|
"fieldtype": "Code",
|
||||||
|
"hidden": 1,
|
||||||
"label": "Webhook Payload",
|
"label": "Webhook Payload",
|
||||||
"options": "JSON",
|
"options": "JSON",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-04-06 14:29:33.856060",
|
"modified": "2020-07-27 14:28:11.532696",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Non Profit",
|
"module": "Non Profit",
|
||||||
"name": "Membership",
|
"name": "Membership",
|
||||||
|
@ -81,7 +81,12 @@ def verify_signature(data):
|
|||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def trigger_razorpay_subscription(*args, **kwargs):
|
def trigger_razorpay_subscription(*args, **kwargs):
|
||||||
data = frappe.request.get_data(as_text=True)
|
data = frappe.request.get_data(as_text=True)
|
||||||
verify_signature(data)
|
try:
|
||||||
|
verify_signature(data)
|
||||||
|
except Exception as e:
|
||||||
|
signature = frappe.request.headers.get('X-Razorpay-Signature')
|
||||||
|
log = "{0} \n\n {1} \n\n {2} \n\n {3}".format(e, frappe.get_traceback(), signature, data)
|
||||||
|
frappe.log_error(e, "Webhook Verification Error")
|
||||||
|
|
||||||
if isinstance(data, six.string_types):
|
if isinstance(data, six.string_types):
|
||||||
data = json.loads(data)
|
data = json.loads(data)
|
||||||
@ -99,36 +104,40 @@ def trigger_razorpay_subscription(*args, **kwargs):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_log = frappe.log_error(frappe.get_traceback() + '\n' + data_json , _("Membership Webhook Failed"))
|
error_log = frappe.log_error(frappe.get_traceback() + '\n' + data_json , _("Membership Webhook Failed"))
|
||||||
notify_failure(error_log)
|
notify_failure(error_log)
|
||||||
return False
|
return { status: 'Failed' }
|
||||||
|
|
||||||
if not member:
|
if not member:
|
||||||
return False
|
return { status: 'Failed' }
|
||||||
|
try:
|
||||||
|
if data.event == "subscription.activated":
|
||||||
|
member.customer_id = payment.customer_id
|
||||||
|
elif data.event == "subscription.charged":
|
||||||
|
membership = frappe.new_doc("Membership")
|
||||||
|
membership.update({
|
||||||
|
"member": member.name,
|
||||||
|
"membership_status": "Current",
|
||||||
|
"membership_type": member.membership_type,
|
||||||
|
"currency": "INR",
|
||||||
|
"paid": 1,
|
||||||
|
"payment_id": payment.id,
|
||||||
|
"webhook_payload": data_json,
|
||||||
|
"from_date": datetime.fromtimestamp(subscription.current_start),
|
||||||
|
"to_date": datetime.fromtimestamp(subscription.current_end),
|
||||||
|
"amount": payment.amount / 100 # Convert to rupees from paise
|
||||||
|
})
|
||||||
|
membership.insert(ignore_permissions=True)
|
||||||
|
|
||||||
if data.event == "subscription.activated":
|
# Update these values anyway
|
||||||
member.customer_id = payment.customer_id
|
member.subscription_start = datetime.fromtimestamp(subscription.start_at)
|
||||||
elif data.event == "subscription.charged":
|
member.subscription_end = datetime.fromtimestamp(subscription.end_at)
|
||||||
membership = frappe.new_doc("Membership")
|
member.subscription_activated = 1
|
||||||
membership.update({
|
member.save(ignore_permissions=True)
|
||||||
"member": member.name,
|
except Exception as e:
|
||||||
"membership_status": "Current",
|
log = frappe.log_error(e, "Error creating membership entry")
|
||||||
"membership_type": member.membership_type,
|
notify_failure(log)
|
||||||
"currency": "INR",
|
return { status: 'Failed' }
|
||||||
"paid": 1,
|
|
||||||
"payment_id": payment.id,
|
|
||||||
"webhook_payload": data_json,
|
|
||||||
"from_date": datetime.fromtimestamp(subscription.current_start),
|
|
||||||
"to_date": datetime.fromtimestamp(subscription.current_end),
|
|
||||||
"amount": payment.amount / 100 # Convert to rupees from paise
|
|
||||||
})
|
|
||||||
membership.insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
# Update these values anyway
|
return { status: 'Success' }
|
||||||
member.subscription_start = datetime.fromtimestamp(subscription.start_at)
|
|
||||||
member.subscription_end = datetime.fromtimestamp(subscription.end_at)
|
|
||||||
member.subscription_activated = 1
|
|
||||||
member.save(ignore_permissions=True)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def notify_failure(log):
|
def notify_failure(log):
|
||||||
|
@ -15,7 +15,7 @@ erpnext.patches.v4_0.move_warehouse_user_to_restrictions
|
|||||||
erpnext.patches.v4_0.global_defaults_to_system_settings
|
erpnext.patches.v4_0.global_defaults_to_system_settings
|
||||||
erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
|
erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
|
||||||
execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28
|
execute:frappe.reload_doc("accounts", "doctype", "POS Payment Method") #2020-05-28
|
||||||
execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16
|
execute:frappe.reload_doc("HR", "doctype", "HR Settings") #2020-01-16 #2020-07-24
|
||||||
execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24
|
execute:frappe.reload_doc('stock', 'doctype', 'warehouse') # 2017-04-24
|
||||||
execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31
|
execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2016-08-31
|
||||||
execute:frappe.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-29
|
execute:frappe.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-29
|
||||||
|
@ -12,11 +12,11 @@ def execute():
|
|||||||
frappe.rename_doc('DocType', 'POS Closing Voucher Taxes', 'POS Closing Entry Taxes', force=True)
|
frappe.rename_doc('DocType', 'POS Closing Voucher Taxes', 'POS Closing Entry Taxes', force=True)
|
||||||
|
|
||||||
if not frappe.db.exists('DocType', 'POS Closing Voucher Details'):
|
if not frappe.db.exists('DocType', 'POS Closing Voucher Details'):
|
||||||
frappe.rename_doc('DocType', 'POS Closing Voucher Details', 'POS Closing Entry Details', force=True)
|
frappe.rename_doc('DocType', 'POS Closing Voucher Details', 'POS Closing Entry Detail', force=True)
|
||||||
|
|
||||||
frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry')
|
frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry')
|
||||||
frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry Taxes')
|
frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry Taxes')
|
||||||
frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry Details')
|
frappe.reload_doc('Accounts', 'doctype', 'POS Closing Entry Detail')
|
||||||
|
|
||||||
if frappe.db.exists("DocType", "POS Closing Voucher"):
|
if frappe.db.exists("DocType", "POS Closing Voucher"):
|
||||||
frappe.delete_doc("DocType", "POS Closing Voucher")
|
frappe.delete_doc("DocType", "POS Closing Voucher")
|
||||||
|
@ -6,7 +6,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
frappe.reload_doc("Selling", "doctype", "POS Payment Method")
|
frappe.reload_doc("accounts", "doctype", "POS Payment Method")
|
||||||
pos_profiles = frappe.get_all("POS Profile")
|
pos_profiles = frappe.get_all("POS Profile")
|
||||||
|
|
||||||
for pos_profile in pos_profiles:
|
for pos_profile in pos_profiles:
|
||||||
|
@ -13,7 +13,7 @@ from erpnext.controllers.item_variant import (ItemVariantExistsError,
|
|||||||
from erpnext.setup.doctype.item_group.item_group import (get_parent_item_groups, invalidate_cache_for)
|
from erpnext.setup.doctype.item_group.item_group import (get_parent_item_groups, invalidate_cache_for)
|
||||||
from frappe import _, msgprint
|
from frappe import _, msgprint
|
||||||
from frappe.utils import (cint, cstr, flt, formatdate, get_timestamp, getdate,
|
from frappe.utils import (cint, cstr, flt, formatdate, get_timestamp, getdate,
|
||||||
now_datetime, random_string, strip, get_link_to_form)
|
now_datetime, random_string, strip, get_link_to_form, nowtime)
|
||||||
from frappe.utils.html_utils import clean_html
|
from frappe.utils.html_utils import clean_html
|
||||||
from frappe.website.doctype.website_slideshow.website_slideshow import \
|
from frappe.website.doctype.website_slideshow.website_slideshow import \
|
||||||
get_slideshow
|
get_slideshow
|
||||||
@ -194,7 +194,7 @@ class Item(WebsiteGenerator):
|
|||||||
|
|
||||||
if default_warehouse:
|
if default_warehouse:
|
||||||
stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock,
|
stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock,
|
||||||
rate=self.valuation_rate, company=default.company)
|
rate=self.valuation_rate, company=default.company, posting_date=getdate(), posting_time=nowtime())
|
||||||
|
|
||||||
stock_entry.add_comment("Comment", _("Opening Stock"))
|
stock_entry.add_comment("Comment", _("Opening Stock"))
|
||||||
|
|
||||||
|
@ -413,7 +413,7 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
def test_serial_item_error(self):
|
def test_serial_item_error(self):
|
||||||
se, serial_nos = self.test_serial_by_series()
|
se, serial_nos = self.test_serial_by_series()
|
||||||
if not frappe.db.exists('Serial No', 'ABCD'):
|
if not frappe.db.exists('Serial No', 'ABCD'):
|
||||||
make_serialized_item("_Test Serialized Item", "ABCD\nEFGH")
|
make_serialized_item(item_code="_Test Serialized Item", serial_no="ABCD\nEFGH")
|
||||||
|
|
||||||
se = frappe.copy_doc(test_records[0])
|
se = frappe.copy_doc(test_records[0])
|
||||||
se.purpose = "Material Transfer"
|
se.purpose = "Material Transfer"
|
||||||
@ -823,15 +823,29 @@ class TestStockEntry(unittest.TestCase):
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|
||||||
def make_serialized_item(item_code=None, serial_no=None, target_warehouse=None):
|
def make_serialized_item(**args):
|
||||||
|
args = frappe._dict(args)
|
||||||
se = frappe.copy_doc(test_records[0])
|
se = frappe.copy_doc(test_records[0])
|
||||||
se.get("items")[0].item_code = item_code or "_Test Serialized Item With Series"
|
|
||||||
se.get("items")[0].serial_no = serial_no
|
if args.company:
|
||||||
|
se.company = args.company
|
||||||
|
|
||||||
|
se.get("items")[0].item_code = args.item_code or "_Test Serialized Item With Series"
|
||||||
|
|
||||||
|
if args.serial_no:
|
||||||
|
se.get("items")[0].serial_no = args.serial_no
|
||||||
|
|
||||||
|
if args.cost_center:
|
||||||
|
se.get("items")[0].cost_center = args.cost_center
|
||||||
|
|
||||||
|
if args.expense_account:
|
||||||
|
se.get("items")[0].expense_account = args.expense_account
|
||||||
|
|
||||||
se.get("items")[0].qty = 2
|
se.get("items")[0].qty = 2
|
||||||
se.get("items")[0].transfer_qty = 2
|
se.get("items")[0].transfer_qty = 2
|
||||||
|
|
||||||
if target_warehouse:
|
if args.target_warehouse:
|
||||||
se.get("items")[0].t_warehouse = target_warehouse
|
se.get("items")[0].t_warehouse = args.target_warehouse
|
||||||
|
|
||||||
se.set_stock_entry_type()
|
se.set_stock_entry_type()
|
||||||
se.insert()
|
se.insert()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user