Merge branch 'develop' into gross-profit-product-bundle
This commit is contained in:
commit
3e5bbc9aa6
@ -13,3 +13,6 @@
|
||||
|
||||
# This commit just changes spaces to tabs for indentation in some files
|
||||
5f473611bd6ed57703716244a054d3fb5ba9cd23
|
||||
|
||||
# Whitespace fix throughout codebase
|
||||
4551d7d6029b6f587f6c99d4f8df5519241c6a86
|
||||
|
@ -6,4 +6,4 @@
|
||||
"scss/at-rule-no-unknown": true,
|
||||
"no-descending-specificity": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,4 +19,4 @@ frappe.dashboards.chart_sources["Account Balance Timeline"] = {
|
||||
reqd: 1
|
||||
},
|
||||
]
|
||||
};
|
||||
};
|
||||
|
@ -450,5 +450,3 @@ def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
|
||||
return debit_account
|
||||
else:
|
||||
return credit_account
|
||||
|
||||
|
||||
|
@ -60,4 +60,4 @@ frappe.ui.form.on('Accounting Dimension Detail', {
|
||||
let row = locals[cdt][cdn];
|
||||
row.reference_document = frm.doc.document_type;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -113,5 +113,3 @@ def disable_dimension():
|
||||
dimension2 = frappe.get_doc("Accounting Dimension", "Location")
|
||||
dimension2.disabled = 1
|
||||
dimension2.save()
|
||||
|
||||
|
||||
|
@ -79,4 +79,4 @@ frappe.ui.form.on('Allowed Dimension', {
|
||||
row.accounting_dimension = frm.doc.accounting_dimension;
|
||||
frm.refresh_field("dimensions");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -56,4 +56,4 @@ class AccountingPeriod(Document):
|
||||
self.append('closed_documents', {
|
||||
"document_type": doctype_for_closing.document_type,
|
||||
"closed": doctype_for_closing.closed
|
||||
})
|
||||
})
|
||||
|
@ -48,4 +48,4 @@ frappe.tour['Accounts Settings'] = [
|
||||
title: "Unlink Advance Payment on Cancellation of Order",
|
||||
description: __("Similar to the previous option, this unlinks any advance payments made against Purchase/Sales Orders.")
|
||||
}
|
||||
];
|
||||
];
|
||||
|
@ -37,7 +37,7 @@ class AccountsSettings(Document):
|
||||
|
||||
def toggle_discount_accounting_fields(self):
|
||||
enable_discount_accounting = cint(self.enable_discount_accounting)
|
||||
|
||||
|
||||
for doctype in ["Sales Invoice Item", "Purchase Invoice Item"]:
|
||||
make_property_setter(doctype, "discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False)
|
||||
if enable_discount_accounting:
|
||||
@ -52,4 +52,4 @@ class AccountsSettings(Document):
|
||||
else:
|
||||
make_property_setter(doctype, "additional_discount_account", "mandatory_depends_on", "", "Code", validate_fields_for_doctype=False)
|
||||
|
||||
make_property_setter("Item", "default_discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter("Item", "default_discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False)
|
||||
|
@ -5,4 +5,4 @@ frappe.ui.form.on('Accounts Settings', {
|
||||
frm.set_df_property("frozen_accounts_modifier", "label", "Role Allowed to Close Books & Make Changes to Closed Periods");
|
||||
frm.set_df_property("credit_controller", "label", "Credit Manager");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -120,4 +120,4 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
||||
plaid_success(token, response) {
|
||||
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -13,4 +13,4 @@ class Bank(Document):
|
||||
load_address_and_contact(self)
|
||||
|
||||
def on_trash(self):
|
||||
delete_contact_and_address('Bank', self.name)
|
||||
delete_contact_and_address('Bank', self.name)
|
||||
|
@ -26,4 +26,4 @@ def get_data():
|
||||
'items': ['Journal Entry']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ frappe.ui.form.on("Bank Clearance", {
|
||||
|
||||
onload: function(frm) {
|
||||
|
||||
let default_bank_account = frappe.defaults.get_user_default("Company")?
|
||||
let default_bank_account = frappe.defaults.get_user_default("Company")?
|
||||
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
|
||||
frm.set_value("account", default_bank_account);
|
||||
|
||||
|
@ -6,4 +6,4 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class BankClearanceDetail(Document):
|
||||
pass
|
||||
pass
|
||||
|
@ -25,6 +25,6 @@ class BankGuarantee(Document):
|
||||
def get_vouchar_detials(column_list, doctype, docname):
|
||||
column_list = json.loads(column_list)
|
||||
for col in column_list:
|
||||
sanitize_searchfield(col)
|
||||
sanitize_searchfield(col)
|
||||
return frappe.db.sql(''' select {columns} from `tab{doctype}` where name=%s'''
|
||||
.format(columns=", ".join(column_list), doctype=doctype), docname, as_dict=1)[0]
|
||||
|
@ -105,4 +105,3 @@ def unclear_reference_payment(doctype, docname):
|
||||
frappe.db.set_value(doc.payment_document, doc.payment_entry, "clearance_date", None)
|
||||
|
||||
return doc.payment_entry
|
||||
|
||||
|
@ -10,4 +10,4 @@ frappe.listview_settings['Bank Transaction'] = {
|
||||
return [__("Reconciled"), "green", "unallocated_amount,=,0"];
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -77,4 +77,4 @@ def get_bank_mapping(bank_account):
|
||||
|
||||
mapping = {row.file_field:row.bank_transaction_field for row in bank.bank_transaction_mapping}
|
||||
|
||||
return mapping
|
||||
return mapping
|
||||
|
@ -6,4 +6,4 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class CFormInvoiceDetail(Document):
|
||||
pass
|
||||
pass
|
||||
|
@ -18,5 +18,3 @@ class CashFlowMapping(Document):
|
||||
frappe._('You can only select a maximum of one option from the list of check boxes.'),
|
||||
title='Error'
|
||||
)
|
||||
|
||||
|
||||
|
@ -33,4 +33,4 @@ class CashierClosing(Document):
|
||||
|
||||
def validate_time(self):
|
||||
if self.from_time >= self.time:
|
||||
frappe.throw(_("From Time Should Be Less Than To Time"))
|
||||
frappe.throw(_("From Time Should Be Less Than To Time"))
|
||||
|
@ -10,10 +10,10 @@ frappe.ui.form.on('Cheque Print Template', {
|
||||
function() {
|
||||
erpnext.cheque_print.view_cheque_print(frm);
|
||||
}).addClass("btn-primary");
|
||||
|
||||
|
||||
$(frm.fields_dict.cheque_print_preview.wrapper).empty()
|
||||
|
||||
|
||||
|
||||
|
||||
var template = '<div style="position: relative; overflow-x: scroll;">\
|
||||
<div id="cheque_preview" style="width: {{ cheque_width }}cm; \
|
||||
height: {{ cheque_height }}cm;\
|
||||
@ -47,9 +47,9 @@ frappe.ui.form.on('Cheque Print Template', {
|
||||
position: absolute;"> Signatory Name </span>\
|
||||
</div>\
|
||||
</div>';
|
||||
|
||||
|
||||
$(frappe.render(template, frm.doc)).appendTo(frm.fields_dict.cheque_print_preview.wrapper)
|
||||
|
||||
|
||||
if (frm.doc.scanned_cheque) {
|
||||
$(frm.fields_dict.cheque_print_preview.wrapper).find("#cheque_preview").css('background-image', 'url(' + frm.doc.scanned_cheque + ')');
|
||||
}
|
||||
|
@ -129,4 +129,4 @@ def get_name_with_number(new_account, account_number):
|
||||
|
||||
def check_if_distributed_cost_center_enabled(cost_center_list):
|
||||
value_list = frappe.get_list("Cost Center", {"name": ["in", cost_center_list]}, "enable_distributed_cost_center", as_list=1)
|
||||
return next((True for x in value_list if x[0]), False)
|
||||
return next((True for x in value_list if x[0]), False)
|
||||
|
@ -12,4 +12,4 @@ def get_data():
|
||||
'items': ['Budget Variance Report', 'General Ledger']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -51,4 +51,4 @@ frappe.treeview_settings["Cost Center"] = {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,3 @@ def create_cost_center(**args):
|
||||
cc.is_group = args.is_group or 0
|
||||
cc.parent_cost_center = args.parent_cost_center or "_Test Company - _TC"
|
||||
cc.insert()
|
||||
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@ class CouponCode(Document):
|
||||
self.coupon_code =''.join(i for i in self.coupon_name if not i.isdigit())[0:8].upper()
|
||||
elif self.coupon_type == "Gift Card":
|
||||
self.coupon_code = frappe.generate_hash()[:10].upper()
|
||||
|
||||
|
||||
def validate(self):
|
||||
if self.coupon_type == "Gift Card":
|
||||
self.maximum_use = 1
|
||||
|
@ -124,6 +124,3 @@ class TestCouponCode(unittest.TestCase):
|
||||
|
||||
so.submit()
|
||||
self.assertEqual(frappe.db.get_value("Coupon Code", "SAVE30", "used"), 1)
|
||||
|
||||
|
||||
|
||||
|
@ -7,4 +7,4 @@ from __future__ import unicode_literals
|
||||
from frappe.model.document import Document
|
||||
|
||||
class DiscountedInvoice(Document):
|
||||
pass
|
||||
pass
|
||||
|
@ -14,4 +14,4 @@ def get_data():
|
||||
'items': ['Payment Entry', 'Journal Entry']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -143,4 +143,4 @@ def create_dunning_type_with_zero_interest_rate():
|
||||
'closing_text': 'We kindly request that you pay the outstanding amount immediately, and late fees.'
|
||||
}
|
||||
)
|
||||
dunning_type.save()
|
||||
dunning_type.save()
|
||||
|
@ -31,7 +31,7 @@ frappe.ui.form.on('Exchange Rate Revaluation', {
|
||||
}, __('Create'));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@ -128,4 +128,4 @@ var get_account_details = function(frm, cdt, cdn) {
|
||||
frm.events.get_total_gain_loss(frm);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
@ -44,7 +44,7 @@ class ExchangeRateRevaluation(Document):
|
||||
|
||||
if total_amt != total_debit:
|
||||
return True
|
||||
|
||||
|
||||
return False
|
||||
|
||||
@frappe.whitelist()
|
||||
@ -205,4 +205,4 @@ def get_account_details(account, company, posting_date, party_type=None, party=N
|
||||
"new_balance_in_base_currency": new_balance_in_base_currency
|
||||
}
|
||||
|
||||
return account_details
|
||||
return account_details
|
||||
|
@ -9,19 +9,8 @@ import frappe
|
||||
import unittest
|
||||
|
||||
class TestFinanceBook(unittest.TestCase):
|
||||
def create_finance_book(self):
|
||||
if not frappe.db.exists("Finance Book", "_Test Finance Book"):
|
||||
finance_book = frappe.get_doc({
|
||||
"doctype": "Finance Book",
|
||||
"finance_book_name": "_Test Finance Book"
|
||||
}).insert()
|
||||
else:
|
||||
finance_book = frappe.get_doc("Finance Book", "_Test Finance Book")
|
||||
|
||||
return finance_book
|
||||
|
||||
def test_finance_book(self):
|
||||
finance_book = self.create_finance_book()
|
||||
finance_book = create_finance_book()
|
||||
|
||||
# create jv entry
|
||||
jv = make_journal_entry("_Test Bank - _TC",
|
||||
@ -41,3 +30,14 @@ class TestFinanceBook(unittest.TestCase):
|
||||
|
||||
for gl_entry in gl_entries:
|
||||
self.assertEqual(gl_entry.finance_book, finance_book.name)
|
||||
|
||||
def create_finance_book():
|
||||
if not frappe.db.exists("Finance Book", "_Test Finance Book"):
|
||||
finance_book = frappe.get_doc({
|
||||
"doctype": "Finance Book",
|
||||
"finance_book_name": "_Test Finance Book"
|
||||
}).insert()
|
||||
else:
|
||||
finance_book = frappe.get_doc("Finance Book", "_Test Finance Book")
|
||||
|
||||
return finance_book
|
@ -17,4 +17,4 @@ def get_data():
|
||||
'items': ['Payment Entry', 'Journal Entry']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -18,4 +18,4 @@ frappe.listview_settings['Invoice Discounting'] = {
|
||||
return [__("Canceled"), "red", "status,=,Canceled"];
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -14,4 +14,4 @@ frappe.ui.form.on("Journal Entry", {
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -100,7 +100,7 @@ class TestJournalEntry(unittest.TestCase):
|
||||
"debit_in_account_currency": 0 if diff > 0 else abs(diff),
|
||||
"credit_in_account_currency": diff if diff > 0 else 0
|
||||
})
|
||||
|
||||
|
||||
jv.append("accounts", {
|
||||
"account": "Stock Adjustment - TCP1",
|
||||
"cost_center": "Main - TCP1",
|
||||
|
@ -88,4 +88,4 @@ frappe.ui.form.on("Journal Entry Template", {
|
||||
frappe.model.clear_table(frm.doc, "accounts");
|
||||
frm.refresh_field("accounts");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -14,4 +14,4 @@ frappe.ui.form.on('Mode of Payment', {
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -39,4 +39,3 @@ class ModeofPayment(Document):
|
||||
message = "POS Profile " + frappe.bold(", ".join(pos_profiles)) + " contains \
|
||||
Mode of Payment " + frappe.bold(str(self.name)) + ". Please remove them to disable this mode."
|
||||
frappe.throw(_(message), title="Not Allowed")
|
||||
|
||||
|
@ -55,4 +55,4 @@ def get_percentage(doc, start_date, period):
|
||||
if d.month in months:
|
||||
percentage += d.percentage_allocation
|
||||
|
||||
return percentage
|
||||
return percentage
|
||||
|
@ -20,4 +20,4 @@ def get_data():
|
||||
'items': ['Budget']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -162,4 +162,4 @@ frappe.ui.form.on('Opening Invoice Creation Tool Item', {
|
||||
invoices_add: (frm) => {
|
||||
frm.trigger('update_invoice_table');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -241,4 +241,3 @@ def get_temporary_opening_account(company=None):
|
||||
frappe.throw(_("Please add a Temporary Opening account in Chart of Accounts"))
|
||||
|
||||
return accounts[0].name
|
||||
|
||||
|
@ -533,8 +533,8 @@ frappe.ui.form.on('Payment Entry', {
|
||||
source_exchange_rate: function(frm) {
|
||||
if (frm.doc.paid_amount) {
|
||||
frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate));
|
||||
if(!frm.set_paid_amount_based_on_received_amount &&
|
||||
(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) {
|
||||
// target exchange rate should always be same as source if both account currencies is same
|
||||
if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) {
|
||||
frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate);
|
||||
frm.set_value("base_received_amount", frm.doc.base_paid_amount);
|
||||
}
|
||||
|
@ -55,14 +55,17 @@ class PaymentEntry(AccountsController):
|
||||
self.validate_mandatory()
|
||||
self.validate_reference_documents()
|
||||
self.set_tax_withholding()
|
||||
self.apply_taxes()
|
||||
self.set_amounts()
|
||||
self.validate_amounts()
|
||||
self.apply_taxes()
|
||||
self.set_amounts_after_tax()
|
||||
self.clear_unallocated_reference_document_rows()
|
||||
self.validate_payment_against_negative_invoice()
|
||||
self.validate_transaction_reference()
|
||||
self.set_title()
|
||||
self.set_remarks()
|
||||
self.validate_duplicate_entry()
|
||||
self.validate_payment_type_with_outstanding()
|
||||
self.validate_allocated_amount()
|
||||
self.validate_paid_invoices()
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
@ -118,6 +121,11 @@ class PaymentEntry(AccountsController):
|
||||
if not self.get(field):
|
||||
self.set(field, bank_data.account)
|
||||
|
||||
def validate_payment_type_with_outstanding(self):
|
||||
total_outstanding = sum(d.allocated_amount for d in self.get('references'))
|
||||
if total_outstanding < 0 and self.party_type == 'Customer' and self.payment_type == 'Receive':
|
||||
frappe.throw(_("Cannot receive from customer against negative outstanding"), title=_("Incorrect Payment Type"))
|
||||
|
||||
def validate_allocated_amount(self):
|
||||
for d in self.get("references"):
|
||||
if (flt(d.allocated_amount))> 0:
|
||||
@ -185,7 +193,7 @@ class PaymentEntry(AccountsController):
|
||||
for field, value in iteritems(ref_details):
|
||||
if d.exchange_gain_loss:
|
||||
# for cases where gain/loss is booked into invoice
|
||||
# exchange_gain_loss is calculated from invoice & populated
|
||||
# exchange_gain_loss is calculated from invoice & populated
|
||||
# and row.exchange_rate is already set to payment entry's exchange rate
|
||||
# refer -> `update_reference_in_payment_entry()` in utils.py
|
||||
continue
|
||||
@ -236,7 +244,9 @@ class PaymentEntry(AccountsController):
|
||||
self.company_currency, self.posting_date)
|
||||
|
||||
def set_target_exchange_rate(self, ref_doc=None):
|
||||
if self.paid_to and not self.target_exchange_rate:
|
||||
if self.paid_from_account_currency == self.paid_to_account_currency:
|
||||
self.target_exchange_rate = self.source_exchange_rate
|
||||
elif self.paid_to and not self.target_exchange_rate:
|
||||
if ref_doc:
|
||||
if self.paid_to_account_currency == ref_doc.currency:
|
||||
self.target_exchange_rate = ref_doc.get("exchange_rate")
|
||||
@ -417,7 +427,7 @@ class PaymentEntry(AccountsController):
|
||||
net_total_for_tds = 0
|
||||
if reference.reference_doctype == 'Purchase Order':
|
||||
net_total_for_tds += flt(frappe.db.get_value('Purchase Order', reference.reference_name, 'net_total'))
|
||||
|
||||
|
||||
if net_total_for_tds:
|
||||
net_total = net_total_for_tds
|
||||
|
||||
@ -468,13 +478,22 @@ class PaymentEntry(AccountsController):
|
||||
def set_amounts(self):
|
||||
self.set_received_amount()
|
||||
self.set_amounts_in_company_currency()
|
||||
self.set_amounts_after_tax()
|
||||
self.set_total_allocated_amount()
|
||||
self.set_unallocated_amount()
|
||||
self.set_difference_amount()
|
||||
|
||||
def validate_amounts(self):
|
||||
self.validate_received_amount()
|
||||
|
||||
def validate_received_amount(self):
|
||||
if self.paid_from_account_currency == self.paid_to_account_currency:
|
||||
if self.paid_amount != self.received_amount:
|
||||
frappe.throw(_("Received Amount cannot be greater than Paid Amount"))
|
||||
|
||||
def set_received_amount(self):
|
||||
self.base_received_amount = self.base_paid_amount
|
||||
if self.paid_from_account_currency == self.paid_to_account_currency:
|
||||
self.received_amount = self.paid_amount
|
||||
|
||||
def set_amounts_after_tax(self):
|
||||
applicable_tax = 0
|
||||
@ -841,7 +860,7 @@ class PaymentEntry(AccountsController):
|
||||
|
||||
if account_details:
|
||||
row.update(account_details)
|
||||
|
||||
|
||||
if not row.get('amount'):
|
||||
# if no difference amount
|
||||
return
|
||||
|
@ -11,4 +11,4 @@ frappe.listview_settings['Payment Entry'] = {
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -107,7 +107,7 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.target_exchange_rate = 50
|
||||
pe.source_exchange_rate = 50
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
@ -154,7 +154,7 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.target_exchange_rate = 50
|
||||
pe.source_exchange_rate = 50
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
@ -491,7 +491,7 @@ class TestPaymentEntry(unittest.TestCase):
|
||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC")
|
||||
pe.reference_no = "1"
|
||||
pe.reference_date = "2016-01-01"
|
||||
pe.target_exchange_rate = 55
|
||||
pe.source_exchange_rate = 55
|
||||
|
||||
pe.append("deductions", {
|
||||
"account": "_Test Exchange Gain/Loss - _TC",
|
||||
|
@ -57,4 +57,4 @@ QUnit.test("test payment entry", function(assert) {
|
||||
() => frappe.timeout(3),
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -25,4 +25,4 @@ QUnit.test("test payment entry", function(assert) {
|
||||
() => frappe.timeout(0.3),
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -64,4 +64,4 @@ QUnit.test("test payment entry", function(assert) {
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
@ -9,19 +9,19 @@ from frappe.model.document import Document
|
||||
class PaymentGatewayAccount(Document):
|
||||
def autoname(self):
|
||||
self.name = self.payment_gateway + " - " + self.currency
|
||||
|
||||
|
||||
def validate(self):
|
||||
self.currency = frappe.db.get_value("Account", self.payment_account, "account_currency")
|
||||
|
||||
|
||||
self.update_default_payment_gateway()
|
||||
self.set_as_default_if_not_set()
|
||||
|
||||
|
||||
def update_default_payment_gateway(self):
|
||||
if self.is_default:
|
||||
frappe.db.sql("""update `tabPayment Gateway Account` set is_default = 0
|
||||
where is_default = 1 """)
|
||||
|
||||
|
||||
def set_as_default_if_not_set(self):
|
||||
if not frappe.db.get_value("Payment Gateway Account",
|
||||
if not frappe.db.get_value("Payment Gateway Account",
|
||||
{"is_default": 1, "name": ("!=", self.name)}, "name"):
|
||||
self.is_default = 1
|
||||
|
@ -136,4 +136,4 @@ frappe.ui.form.on('Payment Order', {
|
||||
|
||||
dialog.show();
|
||||
},
|
||||
});
|
||||
});
|
||||
|
@ -9,4 +9,4 @@ def get_data():
|
||||
'items': ['Payment Entry', 'Journal Entry']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -46,4 +46,4 @@ def create_payment_order_against_payment_entry(ref_doc, order_type):
|
||||
doc = make_payment_order(ref_doc.name, payment_order)
|
||||
doc.save()
|
||||
doc.submit()
|
||||
return doc
|
||||
return doc
|
||||
|
@ -307,4 +307,4 @@ def reconcile_dr_cr_note(dr_cr_notes, company):
|
||||
]
|
||||
})
|
||||
jv.flags.ignore_mandatory = True
|
||||
jv.submit()
|
||||
jv.submit()
|
||||
|
@ -541,4 +541,4 @@ def make_payment_order(source_name, target_doc=None):
|
||||
}
|
||||
}, target_doc, set_missing_values)
|
||||
|
||||
return doclist
|
||||
return doclist
|
||||
|
@ -138,4 +138,4 @@ class TestPaymentRequest(unittest.TestCase):
|
||||
|
||||
# Try to make Payment Request more than SO amount, should give validation
|
||||
pr2.grand_total = 900
|
||||
self.assertRaises(frappe.ValidationError, pr2.save)
|
||||
self.assertRaises(frappe.ValidationError, pr2.save)
|
||||
|
@ -19,4 +19,4 @@ frappe.ui.form.on('Payment Term', {
|
||||
frm.set_df_property("discount", "description", description);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -3,6 +3,6 @@
|
||||
|
||||
frappe.ui.form.on('Payment Terms Template', {
|
||||
setup: function(frm) {
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
@ -30,4 +30,4 @@ def get_data():
|
||||
'items': ['Customer Group', 'Supplier Group']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -50,9 +50,13 @@ class PeriodClosingVoucher(AccountsController):
|
||||
.format(pce[0][0], self.posting_date))
|
||||
|
||||
def make_gl_entries(self):
|
||||
gl_entries = self.get_gl_entries()
|
||||
if gl_entries:
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries)
|
||||
|
||||
def get_gl_entries(self):
|
||||
gl_entries = []
|
||||
net_pl_balance = 0
|
||||
|
||||
pl_accounts = self.get_pl_balances()
|
||||
|
||||
for acc in pl_accounts:
|
||||
@ -60,6 +64,7 @@ class PeriodClosingVoucher(AccountsController):
|
||||
gl_entries.append(self.get_gl_dict({
|
||||
"account": acc.account,
|
||||
"cost_center": acc.cost_center,
|
||||
"finance_book": acc.finance_book,
|
||||
"account_currency": acc.account_currency,
|
||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
|
||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
|
||||
@ -67,35 +72,13 @@ class PeriodClosingVoucher(AccountsController):
|
||||
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0
|
||||
}, item=acc))
|
||||
|
||||
net_pl_balance += flt(acc.bal_in_company_currency)
|
||||
if gl_entries:
|
||||
gle_for_net_pl_bal = self.get_pnl_gl_entry(pl_accounts)
|
||||
gl_entries += gle_for_net_pl_bal
|
||||
|
||||
if net_pl_balance:
|
||||
if self.cost_center_wise_pnl:
|
||||
costcenter_wise_gl_entries = self.get_costcenter_wise_pnl_gl_entries(pl_accounts)
|
||||
gl_entries += costcenter_wise_gl_entries
|
||||
else:
|
||||
gl_entry = self.get_pnl_gl_entry(net_pl_balance)
|
||||
gl_entries.append(gl_entry)
|
||||
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
make_gl_entries(gl_entries)
|
||||
return gl_entries
|
||||
|
||||
def get_pnl_gl_entry(self, net_pl_balance):
|
||||
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
gl_entry = self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
|
||||
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
|
||||
"cost_center": cost_center
|
||||
})
|
||||
|
||||
self.update_default_dimensions(gl_entry)
|
||||
|
||||
return gl_entry
|
||||
|
||||
def get_costcenter_wise_pnl_gl_entries(self, pl_accounts):
|
||||
def get_pnl_gl_entry(self, pl_accounts):
|
||||
company_cost_center = frappe.db.get_value("Company", self.company, "cost_center")
|
||||
gl_entries = []
|
||||
|
||||
@ -104,6 +87,7 @@ class PeriodClosingVoucher(AccountsController):
|
||||
gl_entry = self.get_gl_dict({
|
||||
"account": self.closing_account_head,
|
||||
"cost_center": acc.cost_center or company_cost_center,
|
||||
"finance_book": acc.finance_book,
|
||||
"account_currency": acc.account_currency,
|
||||
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
|
||||
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
|
||||
@ -130,7 +114,7 @@ class PeriodClosingVoucher(AccountsController):
|
||||
def get_pl_balances(self):
|
||||
"""Get balance for dimension-wise pl accounts"""
|
||||
|
||||
dimension_fields = ['t1.cost_center']
|
||||
dimension_fields = ['t1.cost_center', 't1.finance_book']
|
||||
|
||||
self.accounting_dimensions = get_accounting_dimensions()
|
||||
for dimension in self.accounting_dimensions:
|
||||
|
@ -8,6 +8,7 @@ import frappe
|
||||
from frappe.utils import flt, today
|
||||
from erpnext.accounts.utils import get_fiscal_year, now
|
||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||
from erpnext.accounts.doctype.finance_book.test_finance_book import create_finance_book
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
|
||||
class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
@ -118,6 +119,58 @@ class TestPeriodClosingVoucher(unittest.TestCase):
|
||||
|
||||
self.assertTrue(pcv_gle, expected_gle)
|
||||
|
||||
def test_period_closing_with_finance_book_entries(self):
|
||||
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
|
||||
|
||||
company = create_company()
|
||||
surplus_account = create_account()
|
||||
cost_center = create_cost_center("Test Cost Center 1")
|
||||
|
||||
create_sales_invoice(
|
||||
company=company,
|
||||
income_account="Sales - TPC",
|
||||
expense_account="Cost of Goods Sold - TPC",
|
||||
cost_center=cost_center,
|
||||
rate=400,
|
||||
debit_to="Debtors - TPC"
|
||||
)
|
||||
jv = make_journal_entry(
|
||||
account1="Cash - TPC",
|
||||
account2="Sales - TPC",
|
||||
amount=400,
|
||||
cost_center=cost_center,
|
||||
posting_date=now()
|
||||
)
|
||||
jv.company = company
|
||||
jv.finance_book = create_finance_book().name
|
||||
jv.save()
|
||||
jv.submit()
|
||||
|
||||
pcv = frappe.get_doc({
|
||||
"transaction_date": today(),
|
||||
"posting_date": today(),
|
||||
"fiscal_year": get_fiscal_year(today())[0],
|
||||
"company": company,
|
||||
"closing_account_head": surplus_account,
|
||||
"remarks": "Test",
|
||||
"doctype": "Period Closing Voucher"
|
||||
})
|
||||
pcv.insert()
|
||||
pcv.submit()
|
||||
|
||||
expected_gle = (
|
||||
(surplus_account, 0.0, 400.0, ''),
|
||||
(surplus_account, 0.0, 400.0, jv.finance_book),
|
||||
('Sales - TPC', 400.0, 0.0, ''),
|
||||
('Sales - TPC', 400.0, 0.0, jv.finance_book)
|
||||
)
|
||||
|
||||
pcv_gle = frappe.db.sql("""
|
||||
select account, debit, credit, finance_book from `tabGL Entry` where voucher_no=%s
|
||||
""", (pcv.name))
|
||||
|
||||
self.assertTrue(pcv_gle, expected_gle)
|
||||
|
||||
def make_period_closing_voucher(self):
|
||||
pcv = frappe.get_doc({
|
||||
"doctype": "Period Closing Voucher",
|
||||
@ -139,7 +192,7 @@ def create_company():
|
||||
'company_name': "Test PCV Company",
|
||||
'country': 'United States',
|
||||
'default_currency': 'USD'
|
||||
})
|
||||
})
|
||||
company.insert(ignore_if_duplicate = True)
|
||||
return company.name
|
||||
|
||||
|
@ -20,9 +20,9 @@ frappe.ui.form.on('POS Closing Entry', {
|
||||
frm.set_query("pos_opening_entry", function(doc) {
|
||||
return { filters: { 'status': 'Open', 'docstatus': 1 } };
|
||||
});
|
||||
|
||||
|
||||
if (frm.doc.docstatus === 0 && !frm.doc.amended_from) frm.set_value("period_end_date", frappe.datetime.now_datetime());
|
||||
|
||||
|
||||
frappe.realtime.on('closing_process_complete', async function(data) {
|
||||
await frm.reload_doc();
|
||||
if (frm.doc.status == 'Failed' && frm.doc.error_message && data.user == frappe.session.user) {
|
||||
@ -43,7 +43,7 @@ frappe.ui.form.on('POS Closing Entry', {
|
||||
const issue = '<a id="jump_to_error" style="text-decoration: underline;">issue</a>';
|
||||
frm.dashboard.set_headline(
|
||||
__('POS Closing failed while running in a background process. You can resolve the {0} and retry the process again.', [issue]));
|
||||
|
||||
|
||||
$('#jump_to_error').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
frappe.utils.scroll_to(
|
||||
|
@ -85,9 +85,15 @@ class TestPOSClosingEntry(unittest.TestCase):
|
||||
|
||||
pcv_doc.load_from_db()
|
||||
pcv_doc.cancel()
|
||||
si_doc.load_from_db()
|
||||
|
||||
cancelled_invoice = frappe.db.get_value(
|
||||
'POS Invoice Merge Log', {'pos_closing_entry': pcv_doc.name},
|
||||
'consolidated_invoice'
|
||||
)
|
||||
docstatus = frappe.db.get_value("Sales Invoice", cancelled_invoice, 'docstatus')
|
||||
self.assertEqual(docstatus, 2)
|
||||
|
||||
pos_inv1.load_from_db()
|
||||
self.assertEqual(si_doc.docstatus, 2)
|
||||
self.assertEqual(pos_inv1.status, 'Paid')
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
|
||||
|
||||
onload(doc) {
|
||||
super.onload();
|
||||
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log'];
|
||||
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log', 'POS Closing Entry'];
|
||||
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
|
||||
this.frm.script_manager.trigger("is_pos");
|
||||
this.frm.refresh_fields();
|
||||
@ -111,16 +111,12 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
|
||||
}
|
||||
|
||||
write_off_outstanding_amount_automatically() {
|
||||
if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
|
||||
if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
|
||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
|
||||
// this will make outstanding amount 0
|
||||
this.frm.set_value("write_off_amount",
|
||||
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
|
||||
);
|
||||
this.frm.toggle_enable("write_off_amount", false);
|
||||
|
||||
} else {
|
||||
this.frm.toggle_enable("write_off_amount", true);
|
||||
}
|
||||
|
||||
this.calculate_outstanding_amount(false);
|
||||
|
@ -99,6 +99,7 @@
|
||||
"loyalty_redemption_account",
|
||||
"loyalty_redemption_cost_center",
|
||||
"section_break_49",
|
||||
"coupon_code",
|
||||
"apply_discount_on",
|
||||
"base_discount_amount",
|
||||
"column_break_51",
|
||||
@ -595,7 +596,8 @@
|
||||
{
|
||||
"fieldname": "scan_barcode",
|
||||
"fieldtype": "Data",
|
||||
"label": "Scan Barcode"
|
||||
"label": "Scan Barcode",
|
||||
"options": "Barcode"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 1,
|
||||
@ -1182,7 +1184,8 @@
|
||||
"label": "Write Off Amount",
|
||||
"no_copy": 1,
|
||||
"options": "currency",
|
||||
"print_hide": 1
|
||||
"print_hide": 1,
|
||||
"read_only_depends_on": "eval: doc.write_off_outstanding_amount_automatically"
|
||||
},
|
||||
{
|
||||
"fieldname": "base_write_off_amount",
|
||||
@ -1548,12 +1551,20 @@
|
||||
"no_copy": 1,
|
||||
"options": "Sales Invoice",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "coupon_code",
|
||||
"fieldname": "coupon_code",
|
||||
"fieldtype": "Link",
|
||||
"label": "Coupon Code",
|
||||
"options": "Coupon Code",
|
||||
"print_hide": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-07-29 13:37:20.636171",
|
||||
"modified": "2021-08-24 18:19:20.728433",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice",
|
||||
|
@ -44,6 +44,9 @@ class POSInvoice(SalesInvoice):
|
||||
self.validate_pos()
|
||||
self.validate_payment_amount()
|
||||
self.validate_loyalty_transaction()
|
||||
if self.coupon_code:
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import validate_coupon_code
|
||||
validate_coupon_code(self.coupon_code)
|
||||
|
||||
def on_submit(self):
|
||||
# create the loyalty point ledger entry if the customer is enrolled in any loyalty program
|
||||
@ -58,6 +61,10 @@ class POSInvoice(SalesInvoice):
|
||||
self.check_phone_payments()
|
||||
self.set_status(update=True)
|
||||
|
||||
if self.coupon_code:
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
|
||||
update_coupon_code_count(self.coupon_code,'used')
|
||||
|
||||
def before_cancel(self):
|
||||
if self.consolidated_invoice and frappe.db.get_value('Sales Invoice', self.consolidated_invoice, 'docstatus') == 1:
|
||||
pos_closing_entry = frappe.get_all(
|
||||
@ -84,6 +91,10 @@ class POSInvoice(SalesInvoice):
|
||||
against_psi_doc.delete_loyalty_point_entry()
|
||||
against_psi_doc.make_loyalty_point_entry()
|
||||
|
||||
if self.coupon_code:
|
||||
from erpnext.accounts.doctype.pricing_rule.utils import update_coupon_code_count
|
||||
update_coupon_code_count(self.coupon_code,'cancelled')
|
||||
|
||||
def check_phone_payments(self):
|
||||
for pay in self.payments:
|
||||
if pay.type == "Phone" and pay.amount >= 0:
|
||||
@ -127,7 +138,7 @@ class POSInvoice(SalesInvoice):
|
||||
.format(item.idx, bold_delivered_serial_nos), title=_("Item Unavailable"))
|
||||
|
||||
def validate_stock_availablility(self):
|
||||
if self.is_return:
|
||||
if self.is_return or self.docstatus != 1:
|
||||
return
|
||||
|
||||
allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock')
|
||||
|
@ -320,7 +320,8 @@ class TestPOSInvoice(unittest.TestCase):
|
||||
pos2.get("items")[0].serial_no = serial_nos[0]
|
||||
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
||||
|
||||
self.assertRaises(frappe.ValidationError, pos2.insert)
|
||||
pos2.insert()
|
||||
self.assertRaises(frappe.ValidationError, pos2.submit)
|
||||
|
||||
def test_delivered_serialized_item_transaction(self):
|
||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
|
||||
@ -348,7 +349,8 @@ class TestPOSInvoice(unittest.TestCase):
|
||||
pos2.get("items")[0].serial_no = serial_nos[0]
|
||||
pos2.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 1000})
|
||||
|
||||
self.assertRaises(frappe.ValidationError, pos2.insert)
|
||||
pos2.insert()
|
||||
self.assertRaises(frappe.ValidationError, pos2.submit)
|
||||
|
||||
def test_loyalty_points(self):
|
||||
from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records
|
||||
|
@ -5,10 +5,10 @@ frappe.ui.form.on('POS Invoice Merge Log', {
|
||||
setup: function(frm) {
|
||||
frm.set_query("pos_invoice", "pos_invoices", doc => {
|
||||
return{
|
||||
filters: {
|
||||
filters: {
|
||||
'docstatus': 1,
|
||||
'customer': doc.customer,
|
||||
'consolidated_invoice': ''
|
||||
'customer': doc.customer,
|
||||
'consolidated_invoice': ''
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -354,4 +354,4 @@ def safe_load_json(message):
|
||||
except Exception:
|
||||
json_message = message
|
||||
|
||||
return json_message
|
||||
return json_message
|
||||
|
@ -147,4 +147,3 @@ class TestPOSInvoiceMergeLog(unittest.TestCase):
|
||||
frappe.set_user("Administrator")
|
||||
frappe.db.sql("delete from `tabPOS Profile`")
|
||||
frappe.db.sql("delete from `tabPOS Invoice`")
|
||||
|
||||
|
@ -53,4 +53,4 @@ frappe.ui.form.on('POS Opening Entry', {
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -38,4 +38,4 @@ class POSOpeningEntry(StatusUpdater):
|
||||
frappe.throw(msg.format(", ".join(invalid_modes)), title=_("Missing Account"))
|
||||
|
||||
def on_submit(self):
|
||||
self.set_status(update=True)
|
||||
self.set_status(update=True)
|
||||
|
@ -21,8 +21,8 @@ def create_opening_entry(pos_profile, user):
|
||||
balance_details.append(frappe._dict({
|
||||
'mode_of_payment': d.mode_of_payment
|
||||
}))
|
||||
|
||||
|
||||
entry.set("balance_details", balance_details)
|
||||
entry.submit()
|
||||
|
||||
return entry.as_dict()
|
||||
|
||||
return entry.as_dict()
|
||||
|
@ -8,4 +8,4 @@ from frappe.model.document import Document
|
||||
|
||||
class POSSettings(Document):
|
||||
def validate(self):
|
||||
pass
|
||||
pass
|
||||
|
@ -198,12 +198,19 @@ def apply_pricing_rule(args, doc=None):
|
||||
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
|
||||
"automatically_set_serial_nos_based_on_fifo")
|
||||
|
||||
item_code_list = tuple(item.get('item_code') for item in item_list)
|
||||
query_items = frappe.get_all('Item', fields=['item_code','has_serial_no'], filters=[['item_code','in',item_code_list]],as_list=1)
|
||||
serialized_items = dict()
|
||||
for item_code, val in query_items:
|
||||
serialized_items.setdefault(item_code, val)
|
||||
|
||||
for item in item_list:
|
||||
args_copy = copy.deepcopy(args)
|
||||
args_copy.update(item)
|
||||
data = get_pricing_rule_for_item(args_copy, item.get('price_list_rate'), doc=doc)
|
||||
out.append(data)
|
||||
if not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'):
|
||||
|
||||
if serialized_items.get(item.get('item_code')) and not item.get("serial_no") and set_serial_nos_based_on_fifo and not args.get('is_return'):
|
||||
out[0].update(get_serial_no_for_item(args_copy))
|
||||
|
||||
return out
|
||||
|
@ -615,4 +615,4 @@ def delete_existing_pricing_rules():
|
||||
for doctype in ["Pricing Rule", "Pricing Rule Item Code",
|
||||
"Pricing Rule Item Group", "Pricing Rule Brand"]:
|
||||
|
||||
frappe.db.sql("delete from `tab{0}`".format(doctype))
|
||||
frappe.db.sql("delete from `tab{0}`".format(doctype))
|
||||
|
@ -26,4 +26,3 @@ QUnit.test("test pricing rule", function(assert) {
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -31,4 +31,4 @@ class ProcessDeferredAccounting(Document):
|
||||
'against_voucher': self.name
|
||||
})
|
||||
|
||||
make_reverse_gl_entries(gl_entries=gl_entries)
|
||||
make_reverse_gl_entries(gl_entries=gl_entries)
|
||||
|
@ -45,4 +45,4 @@ class TestProcessDeferredAccounting(unittest.TestCase):
|
||||
["Sales - _TC", 0.0, 33.85, "2019-01-31"]
|
||||
]
|
||||
|
||||
check_gl_entries(self, si.name, expected_gle, "2019-01-10")
|
||||
check_gl_entries(self, si.name, expected_gle, "2019-01-10")
|
||||
|
@ -284,4 +284,4 @@ def send_auto_email():
|
||||
selected = frappe.get_list('Process Statement Of Accounts', filters={'to_date': format_date(today()), 'enable_auto_email': 1})
|
||||
for entry in selected:
|
||||
send_emails(entry.name, from_scheduler=True)
|
||||
return True
|
||||
return True
|
||||
|
@ -48,4 +48,4 @@ frappe.ui.form.on('Promotional Scheme', {
|
||||
frm.doc.apply_on === key ? 1 : 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -9,4 +9,4 @@ def get_data():
|
||||
'items': ['Pricing Rule']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -11,25 +11,25 @@ class TestPromotionalScheme(unittest.TestCase):
|
||||
ps = make_promotional_scheme()
|
||||
price_rules = frappe.get_all('Pricing Rule', fields = ["promotional_scheme_id", "name", "creation"],
|
||||
filters = {'promotional_scheme': ps.name})
|
||||
self.assertTrue(len(price_rules),1)
|
||||
self.assertTrue(len(price_rules),1)
|
||||
price_doc_details = frappe.db.get_value('Pricing Rule', price_rules[0].name, ['customer', 'min_qty', 'discount_percentage'], as_dict = 1)
|
||||
self.assertTrue(price_doc_details.customer, '_Test Customer')
|
||||
self.assertTrue(price_doc_details.min_qty, 4)
|
||||
self.assertTrue(price_doc_details.discount_percentage, 20)
|
||||
|
||||
ps.price_discount_slabs[0].min_qty = 6
|
||||
ps.append('customer', {
|
||||
ps.append('customer', {
|
||||
'customer': "_Test Customer 2"})
|
||||
ps.save()
|
||||
price_rules = frappe.get_all('Pricing Rule', fields = ["promotional_scheme_id", "name"],
|
||||
filters = {'promotional_scheme': ps.name})
|
||||
self.assertTrue(len(price_rules), 2)
|
||||
self.assertTrue(len(price_rules), 2)
|
||||
|
||||
price_doc_details = frappe.db.get_value('Pricing Rule', price_rules[1].name, ['customer', 'min_qty', 'discount_percentage'], as_dict = 1)
|
||||
self.assertTrue(price_doc_details.customer, '_Test Customer 2')
|
||||
self.assertTrue(price_doc_details.min_qty, 6)
|
||||
self.assertTrue(price_doc_details.discount_percentage, 20)
|
||||
|
||||
|
||||
price_doc_details = frappe.db.get_value('Pricing Rule', price_rules[0].name, ['customer', 'min_qty', 'discount_percentage'], as_dict = 1)
|
||||
self.assertTrue(price_doc_details.customer, '_Test Customer')
|
||||
self.assertTrue(price_doc_details.min_qty, 6)
|
||||
@ -38,7 +38,7 @@ class TestPromotionalScheme(unittest.TestCase):
|
||||
price_rules = frappe.get_all('Pricing Rule', fields = ["promotional_scheme_id", "name"],
|
||||
filters = {'promotional_scheme': ps.name})
|
||||
self.assertEqual(price_rules, [])
|
||||
|
||||
|
||||
def make_promotional_scheme():
|
||||
ps = frappe.new_doc('Promotional Scheme')
|
||||
ps.name = '_Test Scheme'
|
||||
@ -57,4 +57,4 @@ def make_promotional_scheme():
|
||||
})
|
||||
ps.save()
|
||||
|
||||
return ps
|
||||
return ps
|
||||
|
@ -106,7 +106,6 @@
|
||||
"depends_on": "eval:doc.rate_or_discount==\"Rate\"",
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Rate"
|
||||
},
|
||||
{
|
||||
@ -170,7 +169,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-03-07 11:56:23.424137",
|
||||
"modified": "2021-08-19 15:49:29.598727",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Promotional Scheme Price Discount",
|
||||
|
@ -591,4 +591,4 @@ frappe.ui.form.on("Purchase Invoice", {
|
||||
company: function(frm) {
|
||||
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
|
||||
},
|
||||
})
|
||||
})
|
||||
|
@ -668,8 +668,7 @@
|
||||
"fieldname": "scan_barcode",
|
||||
"fieldtype": "Data",
|
||||
"label": "Scan Barcode",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
"options": "Barcode"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 1,
|
||||
@ -1715,7 +1714,7 @@
|
||||
"idx": 204,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-08-07 17:53:14.351439",
|
||||
"modified": "2021-08-17 20:16:12.737743",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
@ -34,4 +34,4 @@ def get_data():
|
||||
'items': ['Auto Repeat']
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -26,4 +26,4 @@ frappe.listview_settings['Purchase Invoice'] = {
|
||||
return [__("Paid"), "green", "outstanding_amount,=,0"];
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -72,4 +72,3 @@ QUnit.test("test purchase invoice", function(assert) {
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -7,4 +7,4 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PurchaseInvoiceAdvance(Document):
|
||||
pass
|
||||
pass
|
||||
|
@ -7,4 +7,4 @@ import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PurchaseTaxesandCharges(Document):
|
||||
pass
|
||||
pass
|
||||
|
@ -19,4 +19,4 @@ def get_data():
|
||||
'items': ['Supplier Quotation', 'Tax Rule']
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -26,4 +26,3 @@ QUnit.test("test sales taxes and charges template", function(assert) {
|
||||
() => done()
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
{% include "erpnext/regional/india/taxes.js" %}
|
||||
{% include "erpnext/regional/india/e_invoice/einvoice.js" %}
|
||||
|
||||
erpnext.setup_auto_gst_taxation('Sales Invoice');
|
||||
erpnext.setup_einvoice_actions('Sales Invoice')
|
||||
|
||||
frappe.ui.form.on("Sales Invoice", {
|
||||
setup: function(frm) {
|
||||
|
@ -36,139 +36,4 @@ frappe.listview_settings['Sales Invoice'].onload = function (list_view) {
|
||||
};
|
||||
|
||||
list_view.page.add_actions_menu_item(__('Generate E-Way Bill JSON'), action, false);
|
||||
|
||||
const generate_irns = () => {
|
||||
const docnames = list_view.get_checked_items(true);
|
||||
if (docnames && docnames.length) {
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.generate_einvoices',
|
||||
args: { docnames },
|
||||
freeze: true,
|
||||
freeze_message: __('Generating E-Invoices...')
|
||||
});
|
||||
} else {
|
||||
frappe.msgprint({
|
||||
message: __('Please select at least one sales invoice to generate IRN'),
|
||||
title: __('No Invoice Selected'),
|
||||
indicator: 'red'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const cancel_irns = () => {
|
||||
const docnames = list_view.get_checked_items(true);
|
||||
|
||||
const fields = [
|
||||
{
|
||||
"label": "Reason",
|
||||
"fieldname": "reason",
|
||||
"fieldtype": "Select",
|
||||
"reqd": 1,
|
||||
"default": "1-Duplicate",
|
||||
"options": ["1-Duplicate", "2-Data Entry Error", "3-Order Cancelled", "4-Other"]
|
||||
},
|
||||
{
|
||||
"label": "Remark",
|
||||
"fieldname": "remark",
|
||||
"fieldtype": "Data",
|
||||
"reqd": 1
|
||||
}
|
||||
];
|
||||
|
||||
const d = new frappe.ui.Dialog({
|
||||
title: __("Cancel IRN"),
|
||||
fields: fields,
|
||||
primary_action: function() {
|
||||
const data = d.get_values();
|
||||
frappe.call({
|
||||
method: 'erpnext.regional.india.e_invoice.utils.cancel_irns',
|
||||
args: {
|
||||
doctype: list_view.doctype,
|
||||
docnames,
|
||||
reason: data.reason.split('-')[0],
|
||||
remark: data.remark
|
||||
},
|
||||
freeze: true,
|
||||
freeze_message: __('Cancelling E-Invoices...'),
|
||||
});
|
||||
d.hide();
|
||||
},
|
||||
primary_action_label: __('Submit')
|
||||
});
|
||||
d.show();
|
||||
};
|
||||
|
||||
let einvoicing_enabled = false;
|
||||
frappe.db.get_single_value("E Invoice Settings", "enable").then(enabled => {
|
||||
einvoicing_enabled = enabled;
|
||||
});
|
||||
|
||||
list_view.$result.on("change", "input[type=checkbox]", () => {
|
||||
if (einvoicing_enabled) {
|
||||
const docnames = list_view.get_checked_items(true);
|
||||
// show/hide e-invoicing actions when no sales invoices are checked
|
||||
if (docnames && docnames.length) {
|
||||
// prevent adding actions twice if e-invoicing action group already exists
|
||||
if (list_view.page.get_inner_group_button(__('E-Invoicing')).length == 0) {
|
||||
list_view.page.add_inner_button(__('Generate IRNs'), generate_irns, __('E-Invoicing'));
|
||||
list_view.page.add_inner_button(__('Cancel IRNs'), cancel_irns, __('E-Invoicing'));
|
||||
}
|
||||
} else {
|
||||
list_view.page.remove_inner_button(__('Generate IRNs'), __('E-Invoicing'));
|
||||
list_view.page.remove_inner_button(__('Cancel IRNs'), __('E-Invoicing'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.realtime.on("bulk_einvoice_generation_complete", (data) => {
|
||||
const { failures, user, invoices } = data;
|
||||
|
||||
if (invoices.length != failures.length) {
|
||||
frappe.msgprint({
|
||||
message: __('{0} e-invoices generated successfully', [invoices.length]),
|
||||
title: __('Bulk E-Invoice Generation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
|
||||
if (failures && failures.length && user == frappe.session.user) {
|
||||
let message = `
|
||||
Failed to generate IRNs for following ${failures.length} sales invoices:
|
||||
<ul style="padding-left: 20px; padding-top: 5px;">
|
||||
${failures.map(d => `<li>${d.docname}</li>`).join('')}
|
||||
</ul>
|
||||
`;
|
||||
frappe.msgprint({
|
||||
message: message,
|
||||
title: __('Bulk E-Invoice Generation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
frappe.realtime.on("bulk_einvoice_cancellation_complete", (data) => {
|
||||
const { failures, user, invoices } = data;
|
||||
|
||||
if (invoices.length != failures.length) {
|
||||
frappe.msgprint({
|
||||
message: __('{0} e-invoices cancelled successfully', [invoices.length]),
|
||||
title: __('Bulk E-Invoice Cancellation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
|
||||
if (failures && failures.length && user == frappe.session.user) {
|
||||
let message = `
|
||||
Failed to cancel IRNs for following ${failures.length} sales invoices:
|
||||
<ul style="padding-left: 20px; padding-top: 5px;">
|
||||
${failures.map(d => `<li>${d.docname}</li>`).join('')}
|
||||
</ul>
|
||||
`;
|
||||
frappe.msgprint({
|
||||
message: message,
|
||||
title: __('Bulk E-Invoice Cancellation Complete'),
|
||||
indicator: 'orange'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user