mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-07 15:12:51 +00:00
Merge branch 'develop' into datev_fixes
This commit is contained in:
23
.github/workflows/ci-tests.yml
vendored
23
.github/workflows/ci-tests.yml
vendored
@@ -80,14 +80,29 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TYPE: ${{ matrix.TYPE }}
|
TYPE: ${{ matrix.TYPE }}
|
||||||
|
|
||||||
- name: Coverage
|
- name: Coverage - Pull Request
|
||||||
if: matrix.TYPE == 'server'
|
if: matrix.TYPE == 'server' && github.event_name == 'pull_request'
|
||||||
run: |
|
run: |
|
||||||
cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
|
cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
|
||||||
cd ${GITHUB_WORKSPACE}
|
cd ${GITHUB_WORKSPACE}
|
||||||
pip install coveralls==3.0.1
|
pip install coveralls==2.2.0
|
||||||
pip install coverage==5.5
|
pip install coverage==4.5.4
|
||||||
coveralls --service=github
|
coveralls --service=github
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
||||||
|
COVERALLS_SERVICE_NAME: github
|
||||||
|
|
||||||
|
- name: Coverage - Push
|
||||||
|
if: matrix.TYPE == 'server' && github.event_name == 'push'
|
||||||
|
run: |
|
||||||
|
cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
|
||||||
|
cd ${GITHUB_WORKSPACE}
|
||||||
|
pip install coveralls==2.2.0
|
||||||
|
pip install coverage==4.5.4
|
||||||
|
coveralls --service=github-actions
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
||||||
|
COVERALLS_SERVICE_NAME: github-actions
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import frappe
|
|||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
__version__ = '13.1.0'
|
__version__ = '13.1.1'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
|||||||
@@ -561,7 +561,7 @@ frappe.ui.form.on('Payment Entry', {
|
|||||||
flt(frm.doc.received_amount) * flt(frm.doc.target_exchange_rate));
|
flt(frm.doc.received_amount) * flt(frm.doc.target_exchange_rate));
|
||||||
|
|
||||||
if(frm.doc.payment_type == "Pay")
|
if(frm.doc.payment_type == "Pay")
|
||||||
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount);
|
frm.events.allocate_party_amount_against_ref_docs(frm, frm.doc.received_amount, 1);
|
||||||
else
|
else
|
||||||
frm.events.set_unallocated_amount(frm);
|
frm.events.set_unallocated_amount(frm);
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (invoices) {
|
if (invoices) {
|
||||||
this.frm.fields_dict.payment.grid.update_docfield_property(
|
this.frm.fields_dict.payments.grid.update_docfield_property(
|
||||||
'invoice_number', 'options', "\n" + invoices.join("\n")
|
'invoice_number', 'options', "\n" + invoices.join("\n")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,11 @@
|
|||||||
"discount",
|
"discount",
|
||||||
"section_break_9",
|
"section_break_9",
|
||||||
"payment_amount",
|
"payment_amount",
|
||||||
|
"outstanding",
|
||||||
|
"paid_amount",
|
||||||
"discounted_amount",
|
"discounted_amount",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"outstanding",
|
"base_payment_amount"
|
||||||
"paid_amount"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -78,7 +79,8 @@
|
|||||||
"depends_on": "paid_amount",
|
"depends_on": "paid_amount",
|
||||||
"fieldname": "paid_amount",
|
"fieldname": "paid_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Paid Amount"
|
"label": "Paid Amount",
|
||||||
|
"options": "currency"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
@@ -97,6 +99,7 @@
|
|||||||
"fieldname": "outstanding",
|
"fieldname": "outstanding",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Outstanding",
|
"label": "Outstanding",
|
||||||
|
"options": "currency",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -145,12 +148,18 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "section_break_4",
|
"fieldname": "section_break_4",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "base_payment_amount",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Payment Amount (Company Currency)",
|
||||||
|
"options": "Company:company:default_currency"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-02-15 21:03:12.540546",
|
"modified": "2021-04-28 05:41:35.084233",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Payment Schedule",
|
"name": "Payment Schedule",
|
||||||
|
|||||||
@@ -235,11 +235,11 @@ def get_invoice_customer_map(pos_invoices):
|
|||||||
|
|
||||||
return pos_invoice_customer_map
|
return pos_invoice_customer_map
|
||||||
|
|
||||||
def consolidate_pos_invoices(pos_invoices=[], closing_entry={}):
|
def consolidate_pos_invoices(pos_invoices=None, closing_entry=None):
|
||||||
invoices = pos_invoices or closing_entry.get('pos_transactions') or get_all_unconsolidated_invoices()
|
invoices = pos_invoices or (closing_entry and closing_entry.get('pos_transactions')) or get_all_unconsolidated_invoices()
|
||||||
invoice_by_customer = get_invoice_customer_map(invoices)
|
invoice_by_customer = get_invoice_customer_map(invoices)
|
||||||
|
|
||||||
if len(invoices) >= 5 and closing_entry:
|
if len(invoices) >= 1 and closing_entry:
|
||||||
closing_entry.set_status(update=True, status='Queued')
|
closing_entry.set_status(update=True, status='Queued')
|
||||||
enqueue_job(create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry)
|
enqueue_job(create_merge_logs, invoice_by_customer=invoice_by_customer, closing_entry=closing_entry)
|
||||||
else:
|
else:
|
||||||
@@ -252,18 +252,18 @@ def unconsolidate_pos_invoices(closing_entry):
|
|||||||
pluck='name'
|
pluck='name'
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(merge_logs) >= 5:
|
if len(merge_logs) >= 1:
|
||||||
closing_entry.set_status(update=True, status='Queued')
|
closing_entry.set_status(update=True, status='Queued')
|
||||||
enqueue_job(cancel_merge_logs, merge_logs=merge_logs, closing_entry=closing_entry)
|
enqueue_job(cancel_merge_logs, merge_logs=merge_logs, closing_entry=closing_entry)
|
||||||
else:
|
else:
|
||||||
cancel_merge_logs(merge_logs, closing_entry)
|
cancel_merge_logs(merge_logs, closing_entry)
|
||||||
|
|
||||||
def create_merge_logs(invoice_by_customer, closing_entry={}):
|
def create_merge_logs(invoice_by_customer, closing_entry=None):
|
||||||
for customer, invoices in iteritems(invoice_by_customer):
|
for customer, invoices in iteritems(invoice_by_customer):
|
||||||
merge_log = frappe.new_doc('POS Invoice Merge Log')
|
merge_log = frappe.new_doc('POS Invoice Merge Log')
|
||||||
merge_log.posting_date = getdate(closing_entry.get('posting_date'))
|
merge_log.posting_date = getdate(closing_entry.get('posting_date')) if closing_entry else nowdate()
|
||||||
merge_log.customer = customer
|
merge_log.customer = customer
|
||||||
merge_log.pos_closing_entry = closing_entry.get('name', None)
|
merge_log.pos_closing_entry = closing_entry.get('name') if closing_entry else None
|
||||||
|
|
||||||
merge_log.set('pos_invoices', invoices)
|
merge_log.set('pos_invoices', invoices)
|
||||||
merge_log.save(ignore_permissions=True)
|
merge_log.save(ignore_permissions=True)
|
||||||
@@ -273,7 +273,7 @@ def create_merge_logs(invoice_by_customer, closing_entry={}):
|
|||||||
closing_entry.set_status(update=True, status='Submitted')
|
closing_entry.set_status(update=True, status='Submitted')
|
||||||
closing_entry.update_opening_entry()
|
closing_entry.update_opening_entry()
|
||||||
|
|
||||||
def cancel_merge_logs(merge_logs, closing_entry={}):
|
def cancel_merge_logs(merge_logs, closing_entry=None):
|
||||||
for log in merge_logs:
|
for log in merge_logs:
|
||||||
merge_log = frappe.get_doc('POS Invoice Merge Log', log)
|
merge_log = frappe.get_doc('POS Invoice Merge Log', log)
|
||||||
merge_log.flags.ignore_permissions = True
|
merge_log.flags.ignore_permissions = True
|
||||||
@@ -283,20 +283,20 @@ def cancel_merge_logs(merge_logs, closing_entry={}):
|
|||||||
closing_entry.set_status(update=True, status='Cancelled')
|
closing_entry.set_status(update=True, status='Cancelled')
|
||||||
closing_entry.update_opening_entry(for_cancel=True)
|
closing_entry.update_opening_entry(for_cancel=True)
|
||||||
|
|
||||||
def enqueue_job(job, merge_logs=None, invoice_by_customer=None, closing_entry=None):
|
def enqueue_job(job, **kwargs):
|
||||||
check_scheduler_status()
|
check_scheduler_status()
|
||||||
|
|
||||||
|
closing_entry = kwargs.get('closing_entry') or {}
|
||||||
|
|
||||||
job_name = closing_entry.get("name")
|
job_name = closing_entry.get("name")
|
||||||
if not job_already_enqueued(job_name):
|
if not job_already_enqueued(job_name):
|
||||||
enqueue(
|
enqueue(
|
||||||
job,
|
job,
|
||||||
|
**kwargs,
|
||||||
queue="long",
|
queue="long",
|
||||||
timeout=10000,
|
timeout=10000,
|
||||||
event="processing_merge_logs",
|
event="processing_merge_logs",
|
||||||
job_name=job_name,
|
job_name=job_name,
|
||||||
closing_entry=closing_entry,
|
|
||||||
invoice_by_customer=invoice_by_customer,
|
|
||||||
merge_logs=merge_logs,
|
|
||||||
now=frappe.conf.developer_mode or frappe.flags.in_test
|
now=frappe.conf.developer_mode or frappe.flags.in_test
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,8 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<br><br>
|
<br><br>
|
||||||
{% if aging %}
|
{% if ageing %}
|
||||||
<h3 class="text-center">{{ _("Ageing Report Based On ") }} {{ aging.ageing_based_on }}</h3>
|
<h3 class="text-center">{{ _("Ageing Report Based On ") }} {{ ageing.ageing_based_on }}</h3>
|
||||||
<h5 class="text-center">
|
<h5 class="text-center">
|
||||||
{{ _("Up to " ) }} {{ frappe.format(filters.to_date, 'Date')}}
|
{{ _("Up to " ) }} {{ frappe.format(filters.to_date, 'Date')}}
|
||||||
</h5>
|
</h5>
|
||||||
@@ -78,10 +78,10 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ frappe.utils.fmt_money(aging.range1, currency=filters.presentation_currency) }}</td>
|
<td>{{ frappe.utils.fmt_money(ageing.range1, currency=filters.presentation_currency) }}</td>
|
||||||
<td>{{ frappe.utils.fmt_money(aging.range2, currency=filters.presentation_currency) }}</td>
|
<td>{{ frappe.utils.fmt_money(ageing.range2, currency=filters.presentation_currency) }}</td>
|
||||||
<td>{{ frappe.utils.fmt_money(aging.range3, currency=filters.presentation_currency) }}</td>
|
<td>{{ frappe.utils.fmt_money(ageing.range3, currency=filters.presentation_currency) }}</td>
|
||||||
<td>{{ frappe.utils.fmt_money(aging.range4, currency=filters.presentation_currency) }}</td>
|
<td>{{ frappe.utils.fmt_money(ageing.range4, currency=filters.presentation_currency) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class ProcessStatementOfAccounts(Document):
|
|||||||
|
|
||||||
def get_report_pdf(doc, consolidated=True):
|
def get_report_pdf(doc, consolidated=True):
|
||||||
statement_dict = {}
|
statement_dict = {}
|
||||||
aging = ''
|
ageing = ''
|
||||||
base_template_path = "frappe/www/printview.html"
|
base_template_path = "frappe/www/printview.html"
|
||||||
template_path = "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
|
template_path = "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html"
|
||||||
|
|
||||||
@@ -56,8 +56,10 @@ def get_report_pdf(doc, consolidated=True):
|
|||||||
'range4': 120,
|
'range4': 120,
|
||||||
'customer': entry.customer
|
'customer': entry.customer
|
||||||
})
|
})
|
||||||
col1, aging = get_ageing(ageing_filters)
|
col1, ageing = get_ageing(ageing_filters)
|
||||||
aging[0]['ageing_based_on'] = doc.ageing_based_on
|
|
||||||
|
if ageing:
|
||||||
|
ageing[0]['ageing_based_on'] = doc.ageing_based_on
|
||||||
|
|
||||||
tax_id = frappe.get_doc('Customer', entry.customer).tax_id
|
tax_id = frappe.get_doc('Customer', entry.customer).tax_id
|
||||||
presentation_currency = get_party_account_currency('Customer', entry.customer, doc.company) \
|
presentation_currency = get_party_account_currency('Customer', entry.customer, doc.company) \
|
||||||
@@ -87,11 +89,14 @@ def get_report_pdf(doc, consolidated=True):
|
|||||||
|
|
||||||
if len(res) == 3:
|
if len(res) == 3:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
html = frappe.render_template(template_path, \
|
html = frappe.render_template(template_path, \
|
||||||
{"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None})
|
{"filters": filters, "data": res, "ageing": ageing[0] if (doc.include_ageing and ageing) else None})
|
||||||
|
|
||||||
html = frappe.render_template(base_template_path, {"body": html, \
|
html = frappe.render_template(base_template_path, {"body": html, \
|
||||||
"css": get_print_style(), "title": "Statement For " + entry.customer})
|
"css": get_print_style(), "title": "Statement For " + entry.customer})
|
||||||
statement_dict[entry.customer] = html
|
statement_dict[entry.customer] = html
|
||||||
|
|
||||||
if not bool(statement_dict):
|
if not bool(statement_dict):
|
||||||
return False
|
return False
|
||||||
elif consolidated:
|
elif consolidated:
|
||||||
|
|||||||
@@ -397,7 +397,7 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
pi.update({
|
pi.update({
|
||||||
"payment_schedule": get_payment_terms("_Test Payment Term Template",
|
"payment_schedule": get_payment_terms("_Test Payment Term Template",
|
||||||
pi.posting_date, pi.grand_total)
|
pi.posting_date, pi.grand_total, pi.base_grand_total)
|
||||||
})
|
})
|
||||||
|
|
||||||
pi.save()
|
pi.save()
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
"additional_discount_percentage",
|
"additional_discount_percentage",
|
||||||
"additional_discount_amount",
|
"additional_discount_amount",
|
||||||
"sb_3",
|
"sb_3",
|
||||||
|
"submit_invoice",
|
||||||
"invoices",
|
"invoices",
|
||||||
"accounting_dimensions_section",
|
"accounting_dimensions_section",
|
||||||
"cost_center",
|
"cost_center",
|
||||||
@@ -45,9 +46,7 @@
|
|||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "cb_1",
|
"fieldname": "cb_1",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
@@ -55,97 +54,73 @@
|
|||||||
"label": "Status",
|
"label": "Status",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
|
"options": "\nTrialling\nActive\nPast Due Date\nCancelled\nUnpaid\nCompleted",
|
||||||
"read_only": 1,
|
"read_only": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "subscription_period",
|
"fieldname": "subscription_period",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Subscription Period",
|
"label": "Subscription Period"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "cancelation_date",
|
"fieldname": "cancelation_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Cancelation Date",
|
"label": "Cancelation Date",
|
||||||
"read_only": 1,
|
"read_only": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "trial_period_start",
|
"fieldname": "trial_period_start",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Trial Period Start Date",
|
"label": "Trial Period Start Date",
|
||||||
"set_only_once": 1,
|
"set_only_once": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.trial_period_start",
|
"depends_on": "eval:doc.trial_period_start",
|
||||||
"fieldname": "trial_period_end",
|
"fieldname": "trial_period_end",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Trial Period End Date",
|
"label": "Trial Period End Date",
|
||||||
"set_only_once": 1,
|
"set_only_once": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_11",
|
"fieldname": "column_break_11",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "current_invoice_start",
|
"fieldname": "current_invoice_start",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Current Invoice Start Date",
|
"label": "Current Invoice Start Date",
|
||||||
"read_only": 1,
|
"read_only": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "current_invoice_end",
|
"fieldname": "current_invoice_end",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Current Invoice End Date",
|
"label": "Current Invoice End Date",
|
||||||
"read_only": 1,
|
"read_only": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"description": "Number of days that the subscriber has to pay invoices generated by this subscription",
|
"description": "Number of days that the subscriber has to pay invoices generated by this subscription",
|
||||||
"fieldname": "days_until_due",
|
"fieldname": "days_until_due",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"label": "Days Until Due",
|
"label": "Days Until Due"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "cancel_at_period_end",
|
"fieldname": "cancel_at_period_end",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Cancel At End Of Period",
|
"label": "Cancel At End Of Period"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "generate_invoice_at_period_start",
|
"fieldname": "generate_invoice_at_period_start",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Generate Invoice At Beginning Of Period",
|
"label": "Generate Invoice At Beginning Of Period"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "sb_4",
|
"fieldname": "sb_4",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Plans",
|
"label": "Plans"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
@@ -153,84 +128,62 @@
|
|||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Plans",
|
"label": "Plans",
|
||||||
"options": "Subscription Plan Detail",
|
"options": "Subscription Plan Detail",
|
||||||
"reqd": 1,
|
"reqd": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:['Customer', 'Supplier'].includes(doc.party_type)",
|
"depends_on": "eval:['Customer', 'Supplier'].includes(doc.party_type)",
|
||||||
"fieldname": "sb_1",
|
"fieldname": "sb_1",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Taxes",
|
"label": "Taxes"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "sb_2",
|
"fieldname": "sb_2",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Discounts",
|
"label": "Discounts"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "apply_additional_discount",
|
"fieldname": "apply_additional_discount",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Apply Additional Discount On",
|
"label": "Apply Additional Discount On",
|
||||||
"options": "\nGrand Total\nNet Total",
|
"options": "\nGrand Total\nNet Total"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "cb_2",
|
"fieldname": "cb_2",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "additional_discount_percentage",
|
"fieldname": "additional_discount_percentage",
|
||||||
"fieldtype": "Percent",
|
"fieldtype": "Percent",
|
||||||
"label": "Additional DIscount Percentage",
|
"label": "Additional DIscount Percentage"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "additional_discount_amount",
|
"fieldname": "additional_discount_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Additional DIscount Amount",
|
"label": "Additional DIscount Amount"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.invoices",
|
"depends_on": "eval:doc.invoices",
|
||||||
"fieldname": "sb_3",
|
"fieldname": "sb_3",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Invoices",
|
"label": "Invoices"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "invoices",
|
"fieldname": "invoices",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Invoices",
|
"label": "Invoices",
|
||||||
"options": "Subscription Invoice",
|
"options": "Subscription Invoice"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"fieldname": "accounting_dimensions_section",
|
"fieldname": "accounting_dimensions_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Accounting Dimensions",
|
"label": "Accounting Dimensions"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "dimension_col_break",
|
"fieldname": "dimension_col_break",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "party_type",
|
"fieldname": "party_type",
|
||||||
@@ -238,9 +191,7 @@
|
|||||||
"label": "Party Type",
|
"label": "Party Type",
|
||||||
"options": "DocType",
|
"options": "DocType",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"set_only_once": 1,
|
"set_only_once": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "party",
|
"fieldname": "party",
|
||||||
@@ -249,27 +200,21 @@
|
|||||||
"label": "Party",
|
"label": "Party",
|
||||||
"options": "party_type",
|
"options": "party_type",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"set_only_once": 1,
|
"set_only_once": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.party_type === 'Customer'",
|
"depends_on": "eval:doc.party_type === 'Customer'",
|
||||||
"fieldname": "sales_tax_template",
|
"fieldname": "sales_tax_template",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Sales Taxes and Charges Template",
|
"label": "Sales Taxes and Charges Template",
|
||||||
"options": "Sales Taxes and Charges Template",
|
"options": "Sales Taxes and Charges Template"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.party_type === 'Supplier'",
|
"depends_on": "eval:doc.party_type === 'Supplier'",
|
||||||
"fieldname": "purchase_tax_template",
|
"fieldname": "purchase_tax_template",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Purchase Taxes and Charges Template",
|
"label": "Purchase Taxes and Charges Template",
|
||||||
"options": "Purchase Taxes and Charges Template",
|
"options": "Purchase Taxes and Charges Template"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@@ -277,55 +222,49 @@
|
|||||||
"fieldname": "follow_calendar_months",
|
"fieldname": "follow_calendar_months",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Follow Calendar Months",
|
"label": "Follow Calendar Months",
|
||||||
"set_only_once": 1,
|
"set_only_once": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"description": "New invoices will be generated as per schedule even if current invoices are unpaid or past due date",
|
"description": "New invoices will be generated as per schedule even if current invoices are unpaid or past due date",
|
||||||
"fieldname": "generate_new_invoices_past_due_date",
|
"fieldname": "generate_new_invoices_past_due_date",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Generate New Invoices Past Due Date",
|
"label": "Generate New Invoices Past Due Date"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "end_date",
|
"fieldname": "end_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Subscription End Date",
|
"label": "Subscription End Date",
|
||||||
"set_only_once": 1,
|
"set_only_once": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "start_date",
|
"fieldname": "start_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Subscription Start Date",
|
"label": "Subscription Start Date",
|
||||||
"set_only_once": 1,
|
"set_only_once": 1
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Cost Center",
|
"label": "Cost Center",
|
||||||
"options": "Cost Center",
|
"options": "Cost Center"
|
||||||
"show_days": 1,
|
|
||||||
"show_seconds": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company",
|
"options": "Company"
|
||||||
"show_days": 1,
|
},
|
||||||
"show_seconds": 1
|
{
|
||||||
|
"default": "1",
|
||||||
|
"fieldname": "submit_invoice",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Submit Invoice Automatically"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-02-09 15:44:20.024789",
|
"modified": "2021-04-19 15:24:27.550797",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Subscription",
|
"name": "Subscription",
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ class Subscription(Document):
|
|||||||
frappe.throw(_('Subscription End Date is mandatory to follow calendar months'))
|
frappe.throw(_('Subscription End Date is mandatory to follow calendar months'))
|
||||||
|
|
||||||
if billing_info[0]['billing_interval'] != 'Month':
|
if billing_info[0]['billing_interval'] != 'Month':
|
||||||
frappe.throw('Billing Interval in Subscription Plan must be Month to follow calendar months')
|
frappe.throw(_('Billing Interval in Subscription Plan must be Month to follow calendar months'))
|
||||||
|
|
||||||
def after_insert(self):
|
def after_insert(self):
|
||||||
# todo: deal with users who collect prepayments. Maybe a new Subscription Invoice doctype?
|
# todo: deal with users who collect prepayments. Maybe a new Subscription Invoice doctype?
|
||||||
@@ -383,6 +383,8 @@ class Subscription(Document):
|
|||||||
|
|
||||||
invoice.flags.ignore_mandatory = True
|
invoice.flags.ignore_mandatory = True
|
||||||
invoice.save()
|
invoice.save()
|
||||||
|
|
||||||
|
if self.submit_invoice:
|
||||||
invoice.submit()
|
invoice.submit()
|
||||||
|
|
||||||
return invoice
|
return invoice
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ def round_off_debit_credit(gl_map):
|
|||||||
else:
|
else:
|
||||||
allowance = .5
|
allowance = .5
|
||||||
|
|
||||||
if abs(debit_credit_diff) >= allowance:
|
if abs(debit_credit_diff) > allowance:
|
||||||
frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.")
|
frappe.throw(_("Debit and Credit not equal for {0} #{1}. Difference is {2}.")
|
||||||
.format(gl_map[0].voucher_type, gl_map[0].voucher_no, debit_credit_diff))
|
.format(gl_map[0].voucher_type, gl_map[0].voucher_no, debit_credit_diff))
|
||||||
|
|
||||||
|
|||||||
@@ -923,29 +923,34 @@ class AccountsController(TransactionBase):
|
|||||||
date = self.get("due_date")
|
date = self.get("due_date")
|
||||||
due_date = date or posting_date
|
due_date = date or posting_date
|
||||||
|
|
||||||
if party_account_currency == self.company_currency:
|
base_grand_total = self.get("base_rounded_total") or self.base_grand_total
|
||||||
grand_total = self.get("base_rounded_total") or self.base_grand_total
|
|
||||||
else:
|
|
||||||
grand_total = self.get("rounded_total") or self.grand_total
|
grand_total = self.get("rounded_total") or self.grand_total
|
||||||
|
|
||||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||||
|
base_grand_total = base_grand_total - flt(self.base_write_off_amount)
|
||||||
grand_total = grand_total - flt(self.write_off_amount)
|
grand_total = grand_total - flt(self.write_off_amount)
|
||||||
|
|
||||||
if self.get("total_advance"):
|
if self.get("total_advance"):
|
||||||
|
if party_account_currency == self.company_currency:
|
||||||
|
base_grand_total -= self.get("total_advance")
|
||||||
|
grand_total = flt(base_grand_total / self.get("conversion_rate"), self.precision("grand_total"))
|
||||||
|
else:
|
||||||
grand_total -= self.get("total_advance")
|
grand_total -= self.get("total_advance")
|
||||||
|
base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
|
||||||
|
|
||||||
if not self.get("payment_schedule"):
|
if not self.get("payment_schedule"):
|
||||||
if self.get("payment_terms_template"):
|
if self.get("payment_terms_template"):
|
||||||
data = get_payment_terms(self.payment_terms_template, posting_date, grand_total)
|
data = get_payment_terms(self.payment_terms_template, posting_date, grand_total, base_grand_total)
|
||||||
for item in data:
|
for item in data:
|
||||||
self.append("payment_schedule", item)
|
self.append("payment_schedule", item)
|
||||||
else:
|
else:
|
||||||
data = dict(due_date=due_date, invoice_portion=100, payment_amount=grand_total)
|
data = dict(due_date=due_date, invoice_portion=100, payment_amount=grand_total, base_payment_amount=base_grand_total)
|
||||||
self.append("payment_schedule", data)
|
self.append("payment_schedule", data)
|
||||||
else:
|
else:
|
||||||
for d in self.get("payment_schedule"):
|
for d in self.get("payment_schedule"):
|
||||||
if d.invoice_portion:
|
if d.invoice_portion:
|
||||||
d.payment_amount = flt(grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount'))
|
d.payment_amount = flt(grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount'))
|
||||||
|
d.base_payment_amount = flt(base_grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount'))
|
||||||
d.outstanding = d.payment_amount
|
d.outstanding = d.payment_amount
|
||||||
|
|
||||||
def set_due_date(self):
|
def set_due_date(self):
|
||||||
@@ -982,22 +987,28 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
if self.get("payment_schedule"):
|
if self.get("payment_schedule"):
|
||||||
total = 0
|
total = 0
|
||||||
|
base_total = 0
|
||||||
for d in self.get("payment_schedule"):
|
for d in self.get("payment_schedule"):
|
||||||
total += flt(d.payment_amount)
|
total += flt(d.payment_amount)
|
||||||
|
base_total += flt(d.base_payment_amount)
|
||||||
|
|
||||||
if party_account_currency == self.company_currency:
|
base_grand_total = self.get("base_rounded_total") or self.base_grand_total
|
||||||
total = flt(total, self.precision("base_grand_total"))
|
grand_total = self.get("rounded_total") or self.grand_total
|
||||||
grand_total = flt(self.get("base_rounded_total") or self.base_grand_total, self.precision('base_grand_total'))
|
|
||||||
else:
|
|
||||||
total = flt(total, self.precision("grand_total"))
|
|
||||||
grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total'))
|
|
||||||
|
|
||||||
if self.get("total_advance"):
|
|
||||||
grand_total -= self.get("total_advance")
|
|
||||||
|
|
||||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||||
|
base_grand_total = base_grand_total - flt(self.base_write_off_amount)
|
||||||
grand_total = grand_total - flt(self.write_off_amount)
|
grand_total = grand_total - flt(self.write_off_amount)
|
||||||
if total != flt(grand_total, self.precision("grand_total")):
|
|
||||||
|
if self.get("total_advance"):
|
||||||
|
if party_account_currency == self.company_currency:
|
||||||
|
base_grand_total -= self.get("total_advance")
|
||||||
|
grand_total = flt(base_grand_total / self.get("conversion_rate"), self.precision("grand_total"))
|
||||||
|
else:
|
||||||
|
grand_total -= self.get("total_advance")
|
||||||
|
base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total"))
|
||||||
|
print(grand_total, base_grand_total)
|
||||||
|
if total != flt(grand_total, self.precision("grand_total")) or \
|
||||||
|
base_total != flt(base_grand_total, self.precision("base_grand_total")):
|
||||||
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
|
frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total"))
|
||||||
|
|
||||||
def is_rounded_total_disabled(self):
|
def is_rounded_total_disabled(self):
|
||||||
@@ -1237,7 +1248,7 @@ def update_invoice_status():
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_payment_terms(terms_template, posting_date=None, grand_total=None, bill_date=None):
|
def get_payment_terms(terms_template, posting_date=None, grand_total=None, base_grand_total=None, bill_date=None):
|
||||||
if not terms_template:
|
if not terms_template:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -1245,14 +1256,14 @@ def get_payment_terms(terms_template, posting_date=None, grand_total=None, bill_
|
|||||||
|
|
||||||
schedule = []
|
schedule = []
|
||||||
for d in terms_doc.get("terms"):
|
for d in terms_doc.get("terms"):
|
||||||
term_details = get_payment_term_details(d, posting_date, grand_total, bill_date)
|
term_details = get_payment_term_details(d, posting_date, grand_total, base_grand_total, bill_date)
|
||||||
schedule.append(term_details)
|
schedule.append(term_details)
|
||||||
|
|
||||||
return schedule
|
return schedule
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_payment_term_details(term, posting_date=None, grand_total=None, bill_date=None):
|
def get_payment_term_details(term, posting_date=None, grand_total=None, base_grand_total=None, bill_date=None):
|
||||||
term_details = frappe._dict()
|
term_details = frappe._dict()
|
||||||
if isinstance(term, text_type):
|
if isinstance(term, text_type):
|
||||||
term = frappe.get_doc("Payment Term", term)
|
term = frappe.get_doc("Payment Term", term)
|
||||||
@@ -1261,9 +1272,9 @@ def get_payment_term_details(term, posting_date=None, grand_total=None, bill_dat
|
|||||||
term_details.description = term.description
|
term_details.description = term.description
|
||||||
term_details.invoice_portion = term.invoice_portion
|
term_details.invoice_portion = term.invoice_portion
|
||||||
term_details.payment_amount = flt(term.invoice_portion) * flt(grand_total) / 100
|
term_details.payment_amount = flt(term.invoice_portion) * flt(grand_total) / 100
|
||||||
|
term_details.base_payment_amount = flt(term.invoice_portion) * flt(base_grand_total) / 100
|
||||||
term_details.discount_type = term.discount_type
|
term_details.discount_type = term.discount_type
|
||||||
term_details.discount = term.discount
|
term_details.discount = term.discount
|
||||||
# term_details.discounted_amount = flt(grand_total) * (term.discount / 100) if term.discount_type == 'Percentage' else discount
|
|
||||||
term_details.outstanding = term_details.payment_amount
|
term_details.outstanding = term_details.payment_amount
|
||||||
term_details.mode_of_payment = term.mode_of_payment
|
term_details.mode_of_payment = term.mode_of_payment
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ class Loan(AccountsController):
|
|||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.unlink_loan_security_pledge()
|
self.unlink_loan_security_pledge()
|
||||||
|
self.ignore_linked_doctypes = ['GL Entry']
|
||||||
|
|
||||||
def set_missing_fields(self):
|
def set_missing_fields(self):
|
||||||
if not self.company:
|
if not self.company:
|
||||||
|
|||||||
@@ -16,11 +16,11 @@ frappe.ui.form.on('Salary Structure', {
|
|||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
|
|
||||||
let help_button = $(`<a class = 'control-label'>
|
let help_button = $(`<a class = 'control-label'>
|
||||||
Condition and Formula Help
|
${__("Condition and Formula Help")}
|
||||||
</a>`).click(()=>{
|
</a>`).click(()=>{
|
||||||
|
|
||||||
let d = new frappe.ui.Dialog({
|
let d = new frappe.ui.Dialog({
|
||||||
title: 'Condition and Formula Help',
|
title: __('Condition and Formula Help'),
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: 'msg_wrapper',
|
fieldname: 'msg_wrapper',
|
||||||
|
|||||||
@@ -131,25 +131,25 @@ def get_report_summary(data):
|
|||||||
{
|
{
|
||||||
"value": avg_completion,
|
"value": avg_completion,
|
||||||
"indicator": "Green" if avg_completion > 50 else "Red",
|
"indicator": "Green" if avg_completion > 50 else "Red",
|
||||||
"label": "Average Completion",
|
"label": _("Average Completion"),
|
||||||
"datatype": "Percent",
|
"datatype": "Percent",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"value": total,
|
"value": total,
|
||||||
"indicator": "Blue",
|
"indicator": "Blue",
|
||||||
"label": "Total Tasks",
|
"label": _("Total Tasks"),
|
||||||
"datatype": "Int",
|
"datatype": "Int",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"value": completed,
|
"value": completed,
|
||||||
"indicator": "Green",
|
"indicator": "Green",
|
||||||
"label": "Completed Tasks",
|
"label": _("Completed Tasks"),
|
||||||
"datatype": "Int",
|
"datatype": "Int",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"value": total_overdue,
|
"value": total_overdue,
|
||||||
"indicator": "Green" if total_overdue == 0 else "Red",
|
"indicator": "Green" if total_overdue == 0 else "Red",
|
||||||
"label": "Overdue Tasks",
|
"label": _("Overdue Tasks"),
|
||||||
"datatype": "Int",
|
"datatype": "Int",
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -640,6 +640,10 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
let key = item.name;
|
let key = item.name;
|
||||||
me.apply_rule_on_other_items({key: item});
|
me.apply_rule_on_other_items({key: item});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
var company_currency = me.get_company_currency();
|
||||||
|
me.update_item_grid_labels(company_currency);
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -1321,11 +1325,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
change_grid_labels: function(company_currency) {
|
change_grid_labels: function(company_currency) {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
|
||||||
this.frm.set_currency_labels(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount", "base_rate_with_margin"],
|
this.update_item_grid_labels(company_currency);
|
||||||
company_currency, "items");
|
|
||||||
|
|
||||||
this.frm.set_currency_labels(["rate", "net_rate", "price_list_rate", "amount", "net_amount", "stock_uom_rate", "rate_with_margin"],
|
this.toggle_item_grid_columns(company_currency);
|
||||||
this.frm.doc.currency, "items");
|
|
||||||
|
|
||||||
if(this.frm.fields_dict["operations"]) {
|
if(this.frm.fields_dict["operations"]) {
|
||||||
this.frm.set_currency_labels(["operating_cost", "hour_rate"], this.frm.doc.currency, "operations");
|
this.frm.set_currency_labels(["operating_cost", "hour_rate"], this.frm.doc.currency, "operations");
|
||||||
@@ -1360,6 +1362,39 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
this.frm.doc.party_account_currency, "advances");
|
this.frm.doc.party_account_currency, "advances");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.update_payment_schedule_grid_labels(company_currency);
|
||||||
|
},
|
||||||
|
|
||||||
|
update_item_grid_labels: function(company_currency) {
|
||||||
|
this.frm.set_currency_labels([
|
||||||
|
"base_rate", "base_net_rate", "base_price_list_rate",
|
||||||
|
"base_amount", "base_net_amount", "base_rate_with_margin"
|
||||||
|
], company_currency, "items");
|
||||||
|
|
||||||
|
this.frm.set_currency_labels([
|
||||||
|
"rate", "net_rate", "price_list_rate", "amount",
|
||||||
|
"net_amount", "stock_uom_rate", "rate_with_margin"
|
||||||
|
], this.frm.doc.currency, "items");
|
||||||
|
},
|
||||||
|
|
||||||
|
update_payment_schedule_grid_labels: function(company_currency) {
|
||||||
|
const me = this;
|
||||||
|
if (this.frm.fields_dict["payment_schedule"]) {
|
||||||
|
this.frm.set_currency_labels(["base_payment_amount", "base_outstanding", "base_paid_amount"],
|
||||||
|
company_currency, "payment_schedule");
|
||||||
|
this.frm.set_currency_labels(["payment_amount", "outstanding", "paid_amount"],
|
||||||
|
this.frm.doc.currency, "payment_schedule");
|
||||||
|
|
||||||
|
var schedule_grid = this.frm.fields_dict["payment_schedule"].grid;
|
||||||
|
$.each(["base_payment_amount", "base_outstanding", "base_paid_amount"], function(i, fname) {
|
||||||
|
if (frappe.meta.get_docfield(schedule_grid.doctype, fname))
|
||||||
|
schedule_grid.set_column_disp(fname, me.frm.doc.currency != company_currency);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle_item_grid_columns: function(company_currency) {
|
||||||
|
const me = this;
|
||||||
// toggle columns
|
// toggle columns
|
||||||
var item_grid = this.frm.fields_dict["items"].grid;
|
var item_grid = this.frm.fields_dict["items"].grid;
|
||||||
$.each(["base_rate", "base_price_list_rate", "base_amount", "base_rate_with_margin"], function(i, fname) {
|
$.each(["base_rate", "base_price_list_rate", "base_amount", "base_rate_with_margin"], function(i, fname) {
|
||||||
@@ -1379,9 +1414,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
if(frappe.meta.get_docfield(item_grid.doctype, fname))
|
if(frappe.meta.get_docfield(item_grid.doctype, fname))
|
||||||
item_grid.set_column_disp(fname, (show && (me.frm.doc.currency != company_currency)));
|
item_grid.set_column_disp(fname, (show && (me.frm.doc.currency != company_currency)));
|
||||||
});
|
});
|
||||||
|
|
||||||
// set labels
|
|
||||||
var $wrapper = $(this.frm.wrapper);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
recalculate: function() {
|
recalculate: function() {
|
||||||
@@ -1995,11 +2027,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
terms_template: doc.payment_terms_template,
|
terms_template: doc.payment_terms_template,
|
||||||
posting_date: posting_date,
|
posting_date: posting_date,
|
||||||
grand_total: doc.rounded_total || doc.grand_total,
|
grand_total: doc.rounded_total || doc.grand_total,
|
||||||
|
base_grand_total: doc.base_rounded_total || doc.base_grand_total,
|
||||||
bill_date: doc.bill_date
|
bill_date: doc.bill_date
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message && !r.exc) {
|
if(r.message && !r.exc) {
|
||||||
me.frm.set_value("payment_schedule", r.message);
|
me.frm.set_value("payment_schedule", r.message);
|
||||||
|
const company_currency = me.get_company_currency();
|
||||||
|
this.update_payment_schedule_grid_labels(company_currency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -2007,6 +2042,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
payment_term: function(doc, cdt, cdn) {
|
payment_term: function(doc, cdt, cdn) {
|
||||||
|
const me = this;
|
||||||
var row = locals[cdt][cdn];
|
var row = locals[cdt][cdn];
|
||||||
if(row.payment_term) {
|
if(row.payment_term) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
@@ -2015,12 +2051,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
term: row.payment_term,
|
term: row.payment_term,
|
||||||
bill_date: this.frm.doc.bill_date,
|
bill_date: this.frm.doc.bill_date,
|
||||||
posting_date: this.frm.doc.posting_date || this.frm.doc.transaction_date,
|
posting_date: this.frm.doc.posting_date || this.frm.doc.transaction_date,
|
||||||
grand_total: this.frm.doc.rounded_total || this.frm.doc.grand_total
|
grand_total: this.frm.doc.rounded_total || this.frm.doc.grand_total,
|
||||||
|
base_grand_total: this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total
|
||||||
},
|
},
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if(r.message && !r.exc) {
|
if(r.message && !r.exc) {
|
||||||
for (var d in r.message) {
|
for (var d in r.message) {
|
||||||
frappe.model.set_value(cdt, cdn, d, r.message[d]);
|
frappe.model.set_value(cdt, cdn, d, r.message[d]);
|
||||||
|
const company_currency = me.get_company_currency();
|
||||||
|
me.update_payment_schedule_grid_labels(company_currency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,9 +46,6 @@ frappe.ui.form.on("Item", {
|
|||||||
}, __("View"));
|
}, __("View"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!frm.doc.is_fixed_asset) {
|
|
||||||
erpnext.item.make_dashboard(frm);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frm.doc.is_fixed_asset) {
|
if (frm.doc.is_fixed_asset) {
|
||||||
frm.trigger('is_fixed_asset');
|
frm.trigger('is_fixed_asset');
|
||||||
@@ -97,6 +94,10 @@ frappe.ui.form.on("Item", {
|
|||||||
erpnext.item.edit_prices_button(frm);
|
erpnext.item.edit_prices_button(frm);
|
||||||
erpnext.item.toggle_attributes(frm);
|
erpnext.item.toggle_attributes(frm);
|
||||||
|
|
||||||
|
if (!frm.doc.is_fixed_asset) {
|
||||||
|
erpnext.item.make_dashboard(frm);
|
||||||
|
}
|
||||||
|
|
||||||
frm.add_custom_button(__('Duplicate'), function() {
|
frm.add_custom_button(__('Duplicate'), function() {
|
||||||
var new_item = frappe.model.copy_doc(frm.doc);
|
var new_item = frappe.model.copy_doc(frm.doc);
|
||||||
if(new_item.item_name===new_item.item_code) {
|
if(new_item.item_name===new_item.item_code) {
|
||||||
@@ -473,11 +474,15 @@ $.extend(erpnext.item, {
|
|||||||
me.multiple_variant_dialog.get_primary_btn().html(__('Create Variants'));
|
me.multiple_variant_dialog.get_primary_btn().html(__('Create Variants'));
|
||||||
me.multiple_variant_dialog.disable_primary_action();
|
me.multiple_variant_dialog.disable_primary_action();
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
let no_of_combinations = lengths.reduce((a, b) => a * b, 1);
|
let no_of_combinations = lengths.reduce((a, b) => a * b, 1);
|
||||||
me.multiple_variant_dialog.get_primary_btn()
|
let msg;
|
||||||
.html(__(
|
if (no_of_combinations === 1) {
|
||||||
`Make ${no_of_combinations} Variant${no_of_combinations === 1 ? '' : 's'}`
|
msg = __("Make {0} Variant", [no_of_combinations]);
|
||||||
));
|
} else {
|
||||||
|
msg = __("Make {0} Variants", [no_of_combinations]);
|
||||||
|
}
|
||||||
|
me.multiple_variant_dialog.get_primary_btn().html(msg);
|
||||||
me.multiple_variant_dialog.enable_primary_action();
|
me.multiple_variant_dialog.enable_primary_action();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
frappe
|
# frappe # https://github.com/frappe/frappe is installed during bench-init
|
||||||
gocardless-pro~=1.22.0
|
gocardless-pro~=1.22.0
|
||||||
googlemaps # used in ERPNext, but dependency is defined in Frappe
|
googlemaps # used in ERPNext, but dependency is defined in Frappe
|
||||||
pandas~=1.1.5
|
pandas~=1.1.5
|
||||||
|
|||||||
Reference in New Issue
Block a user