From dbbb864ba511a3029389a2b16e7854c90bf5b53d Mon Sep 17 00:00:00 2001 From: Jai Chavan <40264279+jaichavan@users.noreply.github.com> Date: Mon, 10 Aug 2020 16:55:03 +0530 Subject: [PATCH 01/10] fix: Consistent capitalization --- erpnext/setup/doctype/company/company.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 221044df3a7..03703fd82ef 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -242,7 +242,7 @@ { "fieldname": "default_warehouse_for_sales_return", "fieldtype": "Link", - "label": "Default warehouse for Sales Return", + "label": "Default Warehouse for Sales Return", "options": "Warehouse" }, { @@ -801,4 +801,4 @@ "sort_field": "modified", "sort_order": "ASC", "track_changes": 1 -} \ No newline at end of file +} From c992616d3514d8ba7994d1f01d4f85e563f4db1e Mon Sep 17 00:00:00 2001 From: Abhishek Balam Date: Tue, 11 Aug 2020 15:22:54 +0530 Subject: [PATCH 02/10] fix: change opportunity to 'Converted' when items not selected in opportunity itself for making quotation and sales order --- erpnext/crm/doctype/opportunity/opportunity.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.py b/erpnext/crm/doctype/opportunity/opportunity.py index efaeca0e938..e152850f170 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.py +++ b/erpnext/crm/doctype/opportunity/opportunity.py @@ -119,11 +119,19 @@ class Opportunity(TransactionBase): and q.status not in ('Lost', 'Closed')""", self.name) def has_ordered_quotation(self): - return frappe.db.sql(""" - select q.name - from `tabQuotation` q, `tabQuotation Item` qi - where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s - and q.status = 'Ordered'""", self.name) + if not self.with_items: + return frappe.get_all('Quotation', + { + 'opportunity': self.name, + 'status': 'Ordered', + 'docstatus': 1 + }, 'name') + else: + return frappe.db.sql(""" + select q.name + from `tabQuotation` q, `tabQuotation Item` qi + where q.name = qi.parent and q.docstatus=1 and qi.prevdoc_docname =%s + and q.status = 'Ordered'""", self.name) def has_lost_quotation(self): lost_quotation = frappe.db.sql(""" From 3325be1d8760e004fc562908afe1690d9bf815a0 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 11 Aug 2020 10:33:46 +0000 Subject: [PATCH 03/10] fix: spacing for slideshow (#22996) --- erpnext/public/less/website.less | 4 ++++ erpnext/templates/generators/item_group.html | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/public/less/website.less b/erpnext/public/less/website.less index 57a0a332a98..ac878de105b 100644 --- a/erpnext/public/less/website.less +++ b/erpnext/public/less/website.less @@ -297,6 +297,10 @@ margin-top: 30px; } +.item-group-slideshow { + margin-bottom: 1rem; +} + .product-image-img { border: 1px solid @light-border-color; border-radius: 3px; diff --git a/erpnext/templates/generators/item_group.html b/erpnext/templates/generators/item_group.html index 3f984536037..40a064fc768 100644 --- a/erpnext/templates/generators/item_group.html +++ b/erpnext/templates/generators/item_group.html @@ -4,7 +4,7 @@ {% block page_content %}
-
+
{% if slideshow %} {% include "templates/includes/slideshow.html" %} {% endif %} From ef3b82dae2e94e45ec88e0784975675bd8d8ef2d Mon Sep 17 00:00:00 2001 From: Abhishek Balam Date: Tue, 11 Aug 2020 16:05:02 +0530 Subject: [PATCH 04/10] fix(CRM): Move Source section above Follow Up section In Opportunity (#22974) * fix: move source section above follow up * fix: only moving source field to 1st section --- erpnext/crm/doctype/opportunity/opportunity.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index 545e2324acf..219ed890f5e 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -16,6 +16,7 @@ "opportunity_from", "party_name", "customer_name", + "source", "column_break0", "title", "opportunity_type", @@ -49,7 +50,6 @@ "contact_email", "contact_mobile", "more_info", - "source", "campaign", "column_break1", "company", @@ -424,7 +424,7 @@ "icon": "fa fa-info-sign", "idx": 195, "links": [], - "modified": "2020-07-14 16:49:15.888503", + "modified": "2020-08-11 14:49:13.496297", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", From 2621016884a208d164e2b478e7945b1324872bec Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Tue, 11 Aug 2020 16:06:13 +0530 Subject: [PATCH 05/10] fix: Allocated advance amount for multi-currency payment (#22923) * fix: Allocated advance amount for multicurrency payment * fix: Get grand total based on party currency * fix: Remove unwanted code --- erpnext/controllers/accounts_controller.py | 36 +++++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 89c38c710b4..66b5f3035db 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -479,7 +479,11 @@ class AccountsController(TransactionBase): if d.against_order: allocated_amount = flt(d.amount) else: - amount = self.rounded_total or self.grand_total + if self.get('party_account_currency') == self.company_currency: + amount = self.get('base_rounded_total') or self.base_grand_total + else: + amount = self.get('rounded_total') or self.grand_total + allocated_amount = min(amount - advance_allocated, d.amount) advance_allocated += flt(allocated_amount) @@ -802,10 +806,22 @@ class AccountsController(TransactionBase): self.payment_terms_template = '' return + party_account_currency = self.get('party_account_currency') + if not party_account_currency: + party_type, party = self.get_party() + + if party_type and party: + party_account_currency = get_party_account_currency(party_type, party, self.company) + posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date") date = self.get("due_date") due_date = date or posting_date - grand_total = self.get("rounded_total") or self.grand_total + + if party_account_currency == self.company_currency: + grand_total = self.get("base_rounded_total") or self.base_grand_total + else: + grand_total = self.get("rounded_total") or self.grand_total + if self.doctype in ("Sales Invoice", "Purchase Invoice"): grand_total = grand_total - flt(self.write_off_amount) @@ -850,13 +866,25 @@ class AccountsController(TransactionBase): def validate_payment_schedule_amount(self): if self.doctype == 'Sales Invoice' and self.is_pos: return + party_account_currency = self.get('party_account_currency') + if not party_account_currency: + party_type, party = self.get_party() + + if party_type and party: + party_account_currency = get_party_account_currency(party_type, party, self.company) + if self.get("payment_schedule"): total = 0 for d in self.get("payment_schedule"): total += flt(d.payment_amount) - total = flt(total, self.precision("grand_total")) - grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total')) + if party_account_currency == self.company_currency: + total = flt(total, self.precision("base_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") From 79d731dcd80b73fabeb5f510d4deddf8c5119806 Mon Sep 17 00:00:00 2001 From: Anupam Kumar Date: Tue, 11 Aug 2020 16:11:20 +0530 Subject: [PATCH 06/10] feat: Naming series for Sales/Purchase Return (#22942) * feat: adding return naming series * Update purchase_invoice.json Co-authored-by: Nabin Hait --- .../accounts/doctype/purchase_invoice/purchase_invoice.json | 6 +++--- erpnext/accounts/doctype/sales_invoice/sales_invoice.json | 5 ++--- erpnext/stock/doctype/delivery_note/delivery_note.json | 4 ++-- .../stock/doctype/purchase_receipt/purchase_receipt.json | 5 ++--- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 2e91c8ef19f..d62e73b6ac6 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -180,7 +180,7 @@ "no_copy": 1, "oldfieldname": "naming_series", "oldfieldtype": "Select", - "options": "ACC-PINV-.YYYY.-", + "options": "ACC-PINV-.YYYY.-\nACC-PINV-RET-.YYYY.-", "print_hide": 1, "reqd": 1, "set_only_once": 1 @@ -1334,7 +1334,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2020-08-03 12:46:01.411074", + "modified": "2020-08-03 23:20:04.466153", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", @@ -1396,4 +1396,4 @@ "timeline_field": "supplier", "title_field": "title", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 4dc81e90875..31613e50b04 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -1,7 +1,6 @@ { "actions": [], "allow_import": 1, - "allow_workflow": 1, "autoname": "naming_series:", "creation": "2013-05-24 19:29:05", "doctype": "DocType", @@ -217,7 +216,7 @@ "no_copy": 1, "oldfieldname": "naming_series", "oldfieldtype": "Select", - "options": "ACC-SINV-.YYYY.-", + "options": "ACC-SINV-.YYYY.-\nACC-SINV-RET-.YYYY.-", "print_hide": 1, "reqd": 1, "set_only_once": 1 @@ -1947,7 +1946,7 @@ "idx": 181, "is_submittable": 1, "links": [], - "modified": "2020-07-18 05:07:16.725974", + "modified": "2020-08-03 23:31:12.675040", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index 66efcf8cd85..ea385c8b2a9 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -175,7 +175,7 @@ "no_copy": 1, "oldfieldname": "naming_series", "oldfieldtype": "Select", - "options": "MAT-DN-.YYYY.-", + "options": "MAT-DN-.YYYY.-\nMAT-DN-RET-.YYYY.-", "print_hide": 1, "reqd": 1, "set_only_once": 1 @@ -1255,7 +1255,7 @@ "idx": 146, "is_submittable": 1, "links": [], - "modified": "2020-07-18 05:13:55.580420", + "modified": "2020-08-03 23:18:47.739997", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index 92e33ca64e3..ce54fc883f6 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -1,7 +1,6 @@ { "actions": [], "allow_import": 1, - "allow_workflow": 1, "autoname": "naming_series:", "creation": "2013-05-21 16:16:39", "doctype": "DocType", @@ -160,7 +159,7 @@ "no_copy": 1, "oldfieldname": "naming_series", "oldfieldtype": "Select", - "options": "MAT-PRE-.YYYY.-", + "options": "MAT-PRE-.YYYY.-\nMAT-PR-RET-.YYYY.-", "print_hide": 1, "reqd": 1, "set_only_once": 1 @@ -1110,7 +1109,7 @@ "idx": 261, "is_submittable": 1, "links": [], - "modified": "2020-07-18 05:19:12.148115", + "modified": "2020-08-03 23:20:26.381024", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", From 9f6d114265b2c8b156fb60491f90e2599ef50dee Mon Sep 17 00:00:00 2001 From: Abhishek Balam Date: Tue, 11 Aug 2020 16:16:05 +0530 Subject: [PATCH 07/10] fix: Change Source section name to 'Company Information' --- erpnext/crm/doctype/opportunity/opportunity.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index 219ed890f5e..80e707cea7e 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -344,7 +344,7 @@ "collapsible": 1, "fieldname": "more_info", "fieldtype": "Section Break", - "label": "Source", + "label": "Company Information", "oldfieldtype": "Section Break", "options": "fa fa-file-text" }, @@ -424,7 +424,7 @@ "icon": "fa fa-info-sign", "idx": 195, "links": [], - "modified": "2020-08-11 14:49:13.496297", + "modified": "2020-08-11 16:15:45.052240", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", From ee5b9c76912d193ae2fe4ea1ae062619fc1c8673 Mon Sep 17 00:00:00 2001 From: Abhishek Balam Date: Tue, 11 Aug 2020 16:23:47 +0530 Subject: [PATCH 08/10] feat(Accounting): Process Statement Of Accounts (#22901) * feat: Process Statement Of Accounts initial commit * fix: add jinja supported inputs for subject and body in email settings * feat: utils support in template, tested autoemail, fixed issues --- .../process_statement_of_accounts/__init__.py | 0 .../process_statement_of_accounts.html | 89 +++++ .../process_statement_of_accounts.js | 132 ++++++++ .../process_statement_of_accounts.json | 310 ++++++++++++++++++ .../process_statement_of_accounts.py | 271 +++++++++++++++ .../test_process_statement_of_accounts.py | 10 + .../__init__.py | 0 ...rocess_statement_of_accounts_customer.json | 47 +++ .../process_statement_of_accounts_customer.py | 10 + .../doctype/psoa_cost_center/__init__.py | 0 .../psoa_cost_center/psoa_cost_center.json | 30 ++ .../psoa_cost_center/psoa_cost_center.py | 10 + .../accounts/doctype/psoa_project/__init__.py | 0 .../doctype/psoa_project/psoa_project.json | 30 ++ .../doctype/psoa_project/psoa_project.py | 10 + erpnext/hooks.py | 3 +- 16 files changed, 951 insertions(+), 1 deletion(-) create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts/__init__.py create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json create mode 100644 erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py create mode 100644 erpnext/accounts/doctype/psoa_cost_center/__init__.py create mode 100644 erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json create mode 100644 erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py create mode 100644 erpnext/accounts/doctype/psoa_project/__init__.py create mode 100644 erpnext/accounts/doctype/psoa_project/psoa_project.json create mode 100644 erpnext/accounts/doctype/psoa_project/psoa_project.py diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py b/erpnext/accounts/doctype/process_statement_of_accounts/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html new file mode 100644 index 00000000000..e1ddeff61f7 --- /dev/null +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html @@ -0,0 +1,89 @@ +

{{ filters.party[0] }}

+

{{ _("Statement of Accounts") }}

+ +
+ {{ frappe.format(filters.from_date, 'Date')}} + {{ _("to") }} + {{ frappe.format(filters.to_date, 'Date')}} +
+ + + + + + + + + + + + + + {% for row in data %} + + {% if(row.posting_date) %} + + + + + + {% else %} + + + + + + {% endif %} + + + {% endfor %} + +
{{ _("Date") }}{{ _("Ref") }}{{ _("Party") }}{{ _("Debit") }}{{ _("Credit") }}{{ _("Balance (Dr - Cr)") }}
{{ frappe.format(row.posting_date, 'Date') }}{{ row.voucher_type }} +
{{ row.voucher_no }}
+ {% if not (filters.party or filters.account) %} + {{ row.party or row.account }} +
+ {% endif %} + + {{ _("Against") }}: {{ row.against }} +
{{ _("Remarks") }}: {{ row.remarks }} + {% if row.bill_no %} +
{{ _("Supplier Invoice No") }}: {{ row.bill_no }} + {% endif %} +
+ {{ frappe.utils.fmt_money(row.debit, filters.presentation_currency) }} + {{ frappe.utils.fmt_money(row.credit, filters.presentation_currency) }}{{ frappe.format(row.account, {fieldtype: "Link"}) or " " }} + {{ row.account and frappe.utils.fmt_money(row.debit, filters.presentation_currency) }} + + {{ row.account and frappe.utils.fmt_money(row.credit, filters.presentation_currency) }} + + {{ frappe.utils.fmt_money(row.balance, filters.presentation_currency) }} +
+

+{% if aging %} +

{{ _("Ageing Report Based On ") }} {{ aging.ageing_based_on }}

+
+ {{ _("Up to " ) }} {{ frappe.format(filters.to_date, 'Date')}} +
+
+ + + + + + + + + + + + + + + + + + +
30 Days60 Days90 Days120 Days
{{ aging.range1 }}{{ aging.range2 }}{{ aging.range3 }}{{ aging.range4 }}
+{% endif %} +

Printed On {{ frappe.format(frappe.utils.get_datetime(), 'Datetime') }}

\ No newline at end of file diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js new file mode 100644 index 00000000000..7425132c468 --- /dev/null +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.js @@ -0,0 +1,132 @@ +// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Process Statement Of Accounts', { + view_properties: function(frm) { + frappe.route_options = {doc_type: 'Customer'}; + frappe.set_route("Form", "Customize Form"); + }, + refresh: function(frm){ + if(!frm.doc.__islocal) { + frm.add_custom_button('Send Emails',function(){ + frappe.call({ + method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_emails", + args: { + "document_name": frm.doc.name, + }, + callback: function(r) { + if(r && r.message) { + frappe.show_alert({message: __('Emails Queued'), indicator: 'blue'}); + } + else{ + frappe.msgprint('No Records for these settings.') + } + } + }); + }); + frm.add_custom_button('Download',function(){ + var url = frappe.urllib.get_full_url( + '/api/method/erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.download_statements?' + + 'document_name='+encodeURIComponent(frm.doc.name)) + $.ajax({ + url: url, + type: 'GET', + success: function(result) { + if(jQuery.isEmptyObject(result)){ + frappe.msgprint('No Records for these settings.'); + } + else{ + window.location = url; + } + } + }); + }); + } + }, + onload: function(frm) { + frm.set_query('currency', function(){ + return { + filters: { + 'enabled': 1 + } + } + }); + if(frm.doc.__islocal){ + frm.set_value('from_date', frappe.datetime.add_months(frappe.datetime.get_today(), -1)); + frm.set_value('to_date', frappe.datetime.get_today()); + } + }, + customer_collection: function(frm){ + frm.set_value('collection_name', ''); + if(frm.doc.customer_collection){ + frm.get_field('collection_name').set_label(frm.doc.customer_collection); + } + }, + frequency: function(frm){ + if(frm.doc.frequency != ''){ + frm.set_value('start_date', frappe.datetime.get_today()); + } + else{ + frm.set_value('start_date', ''); + } + }, + fetch_customers: function(frm){ + if(frm.doc.collection_name){ + frappe.call({ + method: "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.fetch_customers", + args: { + 'customer_collection': frm.doc.customer_collection, + 'collection_name': frm.doc.collection_name, + 'primary_mandatory': frm.doc.primary_mandatory + }, + callback: function(r) { + if(!r.exc) { + if(r.message.length){ + frm.clear_table('customers'); + for (const customer of r.message){ + var row = frm.add_child('customers'); + row.customer = customer.name; + row.primary_email = customer.primary_email; + row.billing_email = customer.billing_email; + } + frm.refresh_field('customers'); + } + else{ + frappe.msgprint('No Customers found with selected options.'); + } + } + } + }); + } + else { + frappe.throw('Enter ' + frm.doc.customer_collection + ' name.'); + } + } +}); + +frappe.ui.form.on('Process Statement Of Accounts Customer', { + customer: function(frm, cdt, cdn){ + var row = locals[cdt][cdn]; + if (!row.customer){ + return; + } + frappe.call({ + method: 'erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.get_customer_emails', + args: { + 'customer_name': row.customer, + 'primary_mandatory': frm.doc.primary_mandatory + }, + callback: function(r){ + if(!r.exe){ + if(r.message.length){ + frappe.model.set_value(cdt, cdn, "primary_email", r.message[0]) + frappe.model.set_value(cdt, cdn, "billing_email", r.message[1]) + } + else { + return + } + } + } + }) + } +}); \ No newline at end of file diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json new file mode 100644 index 00000000000..4be0e2ec068 --- /dev/null +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json @@ -0,0 +1,310 @@ +{ + "actions": [], + "allow_workflow": 1, + "autoname": "Prompt", + "creation": "2020-05-22 16:46:18.712954", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "section_break_11", + "from_date", + "company", + "account", + "group_by", + "cost_center", + "column_break_14", + "to_date", + "finance_book", + "currency", + "project", + "section_break_3", + "customer_collection", + "collection_name", + "fetch_customers", + "column_break_6", + "primary_mandatory", + "column_break_17", + "customers", + "preferences", + "orientation", + "section_break_14", + "include_ageing", + "ageing_based_on", + "section_break_1", + "enable_auto_email", + "section_break_18", + "frequency", + "filter_duration", + "column_break_21", + "start_date", + "section_break_33", + "subject", + "column_break_28", + "cc_to", + "section_break_30", + "body", + "help_text" + ], + "fields": [ + { + "fieldname": "frequency", + "fieldtype": "Select", + "label": "Frequency", + "options": "Weekly\nMonthly\nQuarterly" + }, + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, + { + "depends_on": "eval:doc.enable_auto_email == 0;", + "fieldname": "from_date", + "fieldtype": "Date", + "label": "From Date", + "mandatory_depends_on": "eval:doc.frequency == '';" + }, + { + "depends_on": "eval:doc.enable_auto_email == 0;", + "fieldname": "to_date", + "fieldtype": "Date", + "label": "To Date", + "mandatory_depends_on": "eval:doc.frequency == '';" + }, + { + "fieldname": "cost_center", + "fieldtype": "Table MultiSelect", + "label": "Cost Center", + "options": "PSOA Cost Center" + }, + { + "fieldname": "project", + "fieldtype": "Table MultiSelect", + "label": "Project", + "options": "PSOA Project" + }, + { + "fieldname": "section_break_3", + "fieldtype": "Section Break", + "label": "Customers" + }, + { + "fieldname": "column_break_6", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_11", + "fieldtype": "Section Break", + "label": "General Ledger Filters" + }, + { + "fieldname": "column_break_14", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_17", + "fieldtype": "Section Break", + "hide_border": 1 + }, + { + "fieldname": "customer_collection", + "fieldtype": "Select", + "label": "Select Customers By", + "options": "\nCustomer Group\nTerritory\nSales Partner\nSales Person" + }, + { + "depends_on": "eval: doc.customer_collection !== ''", + "fieldname": "collection_name", + "fieldtype": "Dynamic Link", + "label": "Recipient", + "options": "customer_collection" + }, + { + "fieldname": "section_break_1", + "fieldtype": "Section Break", + "label": "Email Settings" + }, + { + "fieldname": "account", + "fieldtype": "Link", + "label": "Account", + "options": "Account" + }, + { + "fieldname": "finance_book", + "fieldtype": "Link", + "label": "Finance Book", + "options": "Finance Book" + }, + { + "fieldname": "preferences", + "fieldtype": "Section Break", + "label": "Print Preferences" + }, + { + "fieldname": "orientation", + "fieldtype": "Select", + "label": "Orientation", + "options": "Landscape\nPortrait" + }, + { + "default": "Today", + "fieldname": "start_date", + "fieldtype": "Date", + "label": "Start Date" + }, + { + "default": "Group by Voucher (Consolidated)", + "fieldname": "group_by", + "fieldtype": "Select", + "label": "Group By", + "options": "\nGroup by Voucher\nGroup by Voucher (Consolidated)" + }, + { + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency" + }, + { + "default": "0", + "fieldname": "include_ageing", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Include Ageing Summary" + }, + { + "default": "Due Date", + "depends_on": "eval:doc.include_ageing === 1", + "fieldname": "ageing_based_on", + "fieldtype": "Select", + "label": "Ageing Based On", + "options": "Due Date\nPosting Date" + }, + { + "default": "0", + "fieldname": "enable_auto_email", + "fieldtype": "Check", + "in_list_view": 1, + "label": "Enable Auto Email" + }, + { + "fieldname": "section_break_14", + "fieldtype": "Column Break", + "hide_border": 1 + }, + { + "depends_on": "eval: doc.enable_auto_email ==1", + "fieldname": "section_break_18", + "fieldtype": "Section Break", + "hide_border": 1 + }, + { + "fieldname": "column_break_21", + "fieldtype": "Column Break" + }, + { + "depends_on": "eval: doc.customer_collection !== ''", + "fieldname": "fetch_customers", + "fieldtype": "Button", + "label": "Fetch Customers", + "options": "fetch_customers", + "print_hide": 1, + "report_hide": 1 + }, + { + "default": "1", + "fieldname": "primary_mandatory", + "fieldtype": "Check", + "label": "Send To Primary Contact" + }, + { + "fieldname": "cc_to", + "fieldtype": "Link", + "label": "CC To", + "options": "User" + }, + { + "default": "1", + "fieldname": "filter_duration", + "fieldtype": "Int", + "label": "Filter Duration (Months)" + }, + { + "fieldname": "customers", + "fieldtype": "Table", + "label": "Customers", + "options": "Process Statement Of Accounts Customer", + "reqd": 1 + }, + { + "fieldname": "column_break_28", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_30", + "fieldtype": "Section Break", + "hide_border": 1 + }, + { + "fieldname": "section_break_33", + "fieldtype": "Section Break", + "hide_border": 1 + }, + { + "fieldname": "help_text", + "fieldtype": "HTML", + "label": "Help Text", + "options": "
\n

Note

\n
    \n
  • \nYou can use Jinja tags in Subject and Body fields for dynamic values.\n
  • \n All fields in this doctype are available under the doc object and all fields for the customer to whom the mail will go to is available under the customer object.\n
\n

Examples

\n\n
    \n
  • Subject:

    Statement Of Accounts for {{ customer.name }}

  • \n
  • Body:

    \n
    Hello {{ customer.name }},
    PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.
  • \n
\n" + }, + { + "fieldname": "subject", + "fieldtype": "Data", + "label": "Subject" + }, + { + "fieldname": "body", + "fieldtype": "Text Editor", + "label": "Body" + } + ], + "links": [], + "modified": "2020-08-08 08:47:09.185728", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Process Statement Of Accounts", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py new file mode 100644 index 00000000000..d50e4a8af95 --- /dev/null +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from frappe.model.document import Document +from erpnext.accounts.report.general_ledger.general_ledger import execute as get_soa +from erpnext.accounts.report.accounts_receivable_summary.accounts_receivable_summary import execute as get_ageing +from frappe.core.doctype.communication.email import make + +from frappe.utils.print_format import report_to_pdf +from frappe.utils.pdf import get_pdf +from frappe.utils import today, add_days, add_months, getdate, format_date +from frappe.utils.jinja import validate_template + +import copy +from datetime import timedelta +from frappe.www.printview import get_print_style + +class ProcessStatementOfAccounts(Document): + def validate(self): + if not self.subject: + self.subject = 'Statement Of Accounts for {{ customer.name }}' + if not self.body: + self.body = 'Hello {{ customer.name }},
PFA your Statement Of Accounts from {{ doc.from_date }} to {{ doc.to_date }}.' + + validate_template(self.subject) + validate_template(self.body) + + if not self.customers: + frappe.throw(frappe._('Customers not selected.')) + + if self.enable_auto_email: + self.to_date = self.start_date + self.from_date = add_months(self.to_date, -1 * self.filter_duration) + + +def get_report_pdf(doc, consolidated=True): + statement_dict = {} + aging = '' + base_template_path = "frappe/www/printview.html" + template_path = "erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html" + + for entry in doc.customers: + if doc.include_ageing: + ageing_filters = frappe._dict({ + 'company': doc.company, + 'report_date': doc.to_date, + 'ageing_based_on': doc.ageing_based_on, + 'range1': 30, + 'range2': 60, + 'range3': 90, + 'range4': 120, + 'customer': entry.customer + }) + col1, aging = get_ageing(ageing_filters) + aging[0]['ageing_based_on'] = doc.ageing_based_on + + tax_id = frappe.get_doc('Customer', entry.customer).tax_id + + filters= frappe._dict({ + 'from_date': doc.from_date, + 'to_date': doc.to_date, + 'company': doc.company, + 'finance_book': doc.finance_book if doc.finance_book else None, + "account": doc.account if doc.account else None, + 'party_type': 'Customer', + 'party': [entry.customer], + 'group_by': doc.group_by, + 'currency': doc.currency, + 'cost_center': [cc.cost_center_name for cc in doc.cost_center], + 'project': [p.project_name for p in doc.project], + 'show_opening_entries': 0, + 'include_default_book_entries': 0, + 'show_cancelled_entries': 1, + 'tax_id': tax_id if tax_id else None + }) + col, res = get_soa(filters) + + for x in [0, -2, -1]: + res[x]['account'] = res[x]['account'].replace("'","") + + if len(res) == 3: + continue + html = frappe.render_template(template_path, \ + {"filters": filters, "data": res, "aging": aging[0] if doc.include_ageing else None}) + html = frappe.render_template(base_template_path, {"body": html, \ + "css": get_print_style(), "title": "Statement For " + entry.customer}) + statement_dict[entry.customer] = html + if not bool(statement_dict): + return False + elif consolidated: + result = ''.join(list(statement_dict.values())) + return get_pdf(result, {'orientation': doc.orientation}) + else: + for customer, statement_html in statement_dict.items(): + statement_dict[customer]=get_pdf(statement_html, {'orientation': doc.orientation}) + return statement_dict + +def get_customers_based_on_territory_or_customer_group(customer_collection, collection_name): + fields_dict = { + 'Customer Group': 'customer_group', + 'Territory': 'territory', + } + collection = frappe.get_doc(customer_collection, collection_name) + selected = [customer.name for customer in frappe.get_list(customer_collection, filters=[ + ['lft', '>=', collection.lft], + ['rgt', '<=', collection.rgt] + ], + fields=['name'], + order_by='lft asc, rgt desc' + )] + return frappe.get_list('Customer', fields=['name', 'email_id'], \ + filters=[[fields_dict[customer_collection], 'IN', selected]]) + +def get_customers_based_on_sales_person(sales_person): + lft, rgt = frappe.db.get_value("Sales Person", + sales_person, ["lft", "rgt"]) + records = frappe.db.sql(""" + select distinct parent, parenttype + from `tabSales Team` steam + where parenttype = 'Customer' + and exists(select name from `tabSales Person` where lft >= %s and rgt <= %s and name = steam.sales_person) + """, (lft, rgt), as_dict=1) + sales_person_records = frappe._dict() + for d in records: + sales_person_records.setdefault(d.parenttype, set()).add(d.parent) + customers = frappe.get_list('Customer', fields=['name', 'email_id'], \ + filters=[['name', 'in', list(sales_person_records['Customer'])]]) + return customers + +def get_recipients_and_cc(customer, doc): + recipients = [] + for clist in doc.customers: + if clist.customer == customer: + recipients.append(clist.billing_email) + if doc.primary_mandatory and clist.primary_email: + recipients.append(clist.primary_email) + cc = [] + if doc.cc_to != '': + try: + cc=[frappe.get_value('User', doc.cc_to, 'email')] + except: + pass + + return recipients, cc + +def get_context(customer, doc): + template_doc = copy.deepcopy(doc) + del template_doc.customers + template_doc.from_date = format_date(template_doc.from_date) + template_doc.to_date = format_date(template_doc.to_date) + return { + 'doc': template_doc, + 'customer': frappe.get_doc('Customer', customer), + 'frappe': frappe.utils + } + +@frappe.whitelist() +def fetch_customers(customer_collection, collection_name, primary_mandatory): + customer_list = [] + customers = [] + + if customer_collection == 'Sales Person': + customers = get_customers_based_on_sales_person(collection_name) + if not bool(customers): + frappe.throw('No Customers found with selected options.') + else: + if customer_collection == 'Sales Partner': + customers = frappe.get_list('Customer', fields=['name', 'email_id'], \ + filters=[['default_sales_partner', '=', collection_name]]) + else: + customers = get_customers_based_on_territory_or_customer_group(customer_collection, collection_name) + + for customer in customers: + primary_email = customer.get('email_id') or '' + billing_email = get_customer_emails(customer.name, 1, billing_and_primary=False) + + if billing_email == '' or (primary_email == '' and int(primary_mandatory)): + continue + + customer_list.append({ + 'name': customer.name, + 'primary_email': primary_email, + 'billing_email': billing_email + }) + return customer_list + +@frappe.whitelist() +def get_customer_emails(customer_name, primary_mandatory, billing_and_primary=True): + billing_email = frappe.db.sql(""" + SELECT c.email_id FROM `tabContact` AS c JOIN `tabDynamic Link` AS l ON c.name=l.parent \ + WHERE l.link_doctype='Customer' and l.link_name='""" + customer_name + """' and \ + c.is_billing_contact=1 \ + order by c.creation desc""") + + if len(billing_email) == 0 or (billing_email[0][0] is None): + if billing_and_primary: + frappe.throw('No billing email found for customer: '+ customer_name) + else: + return '' + + if billing_and_primary: + primary_email = frappe.get_value('Customer', customer_name, 'email_id') + if primary_email is None and int(primary_mandatory): + frappe.throw('No primary email found for customer: '+ customer_name) + return [primary_email or '', billing_email[0][0]] + else: + return billing_email[0][0] or '' + +@frappe.whitelist() +def download_statements(document_name): + doc = frappe.get_doc('Process Statement Of Accounts', document_name) + report = get_report_pdf(doc) + if report: + frappe.local.response.filename = doc.name + '.pdf' + frappe.local.response.filecontent = report + frappe.local.response.type = "download" + +@frappe.whitelist() +def send_emails(document_name, from_scheduler=False): + doc = frappe.get_doc('Process Statement Of Accounts', document_name) + report = get_report_pdf(doc, consolidated=False) + + if report: + for customer, report_pdf in report.items(): + attachments = [{ + 'fname': customer + '.pdf', + 'fcontent': report_pdf + }] + + recipients, cc = get_recipients_and_cc(customer, doc) + context = get_context(customer, doc) + subject = frappe.render_template(doc.subject, context) + message = frappe.render_template(doc.body, context) + + frappe.enqueue( + queue='short', + method=frappe.sendmail, + recipients=recipients, + sender=frappe.session.user, + cc=cc, + subject=subject, + message=message, + now=True, + reference_doctype='Process Statement Of Accounts', + reference_name=document_name, + attachments=attachments + ) + + if doc.enable_auto_email and from_scheduler: + new_to_date = getdate(today()) + if doc.frequency == 'Weekly': + new_to_date = add_days(new_to_date, 7) + else: + new_to_date = add_months(new_to_date, 1 if doc.frequency == 'Monthly' else 3) + new_from_date = add_months(new_to_date, -1 * doc.filter_duration) + doc.add_comment('Comment', 'Emails sent on: ' + frappe.utils.format_datetime(frappe.utils.now())) + doc.db_set('to_date', new_to_date, commit=True) + doc.db_set('from_date', new_from_date, commit=True) + return True + else: + return False + +@frappe.whitelist() +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 \ No newline at end of file diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py new file mode 100644 index 00000000000..30efbb36833 --- /dev/null +++ b/erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestProcessStatementOfAccounts(unittest.TestCase): + pass diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json new file mode 100644 index 00000000000..dd04dc1b3c6 --- /dev/null +++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json @@ -0,0 +1,47 @@ +{ + "actions": [], + "allow_workflow": 1, + "creation": "2020-08-03 16:35:21.852178", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "customer", + "billing_email", + "primary_email" + ], + "fields": [ + { + "fieldname": "customer", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Customer", + "options": "Customer", + "reqd": 1 + }, + { + "fieldname": "primary_email", + "fieldtype": "Read Only", + "in_list_view": 1, + "label": "Primary Contact Email" + }, + { + "fieldname": "billing_email", + "fieldtype": "Read Only", + "in_list_view": 1, + "label": "Billing Email" + } + ], + "istable": 1, + "links": [], + "modified": "2020-08-03 22:55:38.875601", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Process Statement Of Accounts Customer", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py new file mode 100644 index 00000000000..1a760101dba --- /dev/null +++ b/erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class ProcessStatementOfAccountsCustomer(Document): + pass diff --git a/erpnext/accounts/doctype/psoa_cost_center/__init__.py b/erpnext/accounts/doctype/psoa_cost_center/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json new file mode 100644 index 00000000000..e292b60d68d --- /dev/null +++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json @@ -0,0 +1,30 @@ +{ + "actions": [], + "creation": "2020-08-03 16:56:45.744905", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "cost_center_name" + ], + "fields": [ + { + "fieldname": "cost_center_name", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center" + } + ], + "istable": 1, + "links": [], + "modified": "2020-08-03 16:56:45.744905", + "modified_by": "Administrator", + "module": "Accounts", + "name": "PSOA Cost Center", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py new file mode 100644 index 00000000000..0aeef3ed3a8 --- /dev/null +++ b/erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class PSOACostCenter(Document): + pass diff --git a/erpnext/accounts/doctype/psoa_project/__init__.py b/erpnext/accounts/doctype/psoa_project/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.json b/erpnext/accounts/doctype/psoa_project/psoa_project.json new file mode 100644 index 00000000000..20a03eed96e --- /dev/null +++ b/erpnext/accounts/doctype/psoa_project/psoa_project.json @@ -0,0 +1,30 @@ +{ + "actions": [], + "creation": "2020-08-03 16:52:14.731978", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "project_name" + ], + "fields": [ + { + "fieldname": "project_name", + "fieldtype": "Link", + "label": "Project", + "options": "Project" + } + ], + "istable": 1, + "links": [], + "modified": "2020-08-03 16:53:39.219736", + "modified_by": "Administrator", + "module": "Accounts", + "name": "PSOA Project", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/psoa_project/psoa_project.py b/erpnext/accounts/doctype/psoa_project/psoa_project.py new file mode 100644 index 00000000000..f4a5dee9752 --- /dev/null +++ b/erpnext/accounts/doctype/psoa_project/psoa_project.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +# import frappe +from frappe.model.document import Document + +class PSOAProject(Document): + pass diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 95a836fe652..463ad6c94b4 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -322,7 +322,8 @@ scheduler_events = { "erpnext.crm.doctype.email_campaign.email_campaign.set_email_campaign_status", "erpnext.selling.doctype.quotation.quotation.set_expired_status", "erpnext.healthcare.doctype.patient_appointment.patient_appointment.update_appointment_status", - "erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status" + "erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status", + "erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email" ], "daily_long": [ "erpnext.setup.doctype.email_digest.email_digest.send", From d0ae92d4bd11603bbdd8c646b7b17ecd3708b8d3 Mon Sep 17 00:00:00 2001 From: Abhishek Balam Date: Tue, 11 Aug 2020 17:39:17 +0530 Subject: [PATCH 09/10] fix: moved company field, renamed to 'More Information' --- erpnext/crm/doctype/opportunity/opportunity.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index 80e707cea7e..5cd5233b2e4 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -50,9 +50,9 @@ "contact_email", "contact_mobile", "more_info", + "company", "campaign", "column_break1", - "company", "transaction_date", "amended_from", "lost_reasons" @@ -344,7 +344,7 @@ "collapsible": 1, "fieldname": "more_info", "fieldtype": "Section Break", - "label": "Company Information", + "label": "More Information", "oldfieldtype": "Section Break", "options": "fa fa-file-text" }, @@ -424,7 +424,7 @@ "icon": "fa fa-info-sign", "idx": 195, "links": [], - "modified": "2020-08-11 16:15:45.052240", + "modified": "2020-08-11 17:34:35.066961", "modified_by": "Administrator", "module": "CRM", "name": "Opportunity", From ed6e9550ca12bce53e581ebee6b8a96f7f8aa79e Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Tue, 11 Aug 2020 18:04:42 +0530 Subject: [PATCH 10/10] fix: removed payroll from HR. (#22991) Co-authored-by: Rucha Mahabal --- erpnext/hr/desk_page/hr/hr.json | 17 +++++++++-------- erpnext/payroll/desk_page/payroll/payroll.json | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/erpnext/hr/desk_page/hr/hr.json b/erpnext/hr/desk_page/hr/hr.json index 0fed8d322f5..895cf7290c9 100644 --- a/erpnext/hr/desk_page/hr/hr.json +++ b/erpnext/hr/desk_page/hr/hr.json @@ -78,7 +78,7 @@ "idx": 0, "is_standard": 1, "label": "HR", - "modified": "2020-06-16 19:20:50.976045", + "modified": "2020-08-11 17:04:38.655417", "modified_by": "Administrator", "module": "HR", "name": "HR", @@ -88,7 +88,7 @@ "pin_to_top": 0, "shortcuts": [ { - "color": "#9deca2", + "color": "#cef6d1", "format": "{} Active", "label": "Employee", "link_to": "Employee", @@ -96,18 +96,19 @@ "type": "DocType" }, { - "label": "Attendance", - "link_to": "Attendance", - "stats_filter": "", - "type": "DocType" - }, - { + "color": "#ffe8cd", "format": "{} Open", "label": "Leave Application", "link_to": "Leave Application", "stats_filter": "{\"status\":\"Open\"}", "type": "DocType" }, + { + "label": "Attendance", + "link_to": "Attendance", + "stats_filter": "", + "type": "DocType" + }, { "label": "Job Applicant", "link_to": "Job Applicant", diff --git a/erpnext/payroll/desk_page/payroll/payroll.json b/erpnext/payroll/desk_page/payroll/payroll.json index b5eac465c82..285e3b3a135 100644 --- a/erpnext/payroll/desk_page/payroll/payroll.json +++ b/erpnext/payroll/desk_page/payroll/payroll.json @@ -8,7 +8,7 @@ { "hidden": 0, "label": "Taxation", - "links": "[\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Income Tax Slab\",\n \"name\": \"Income Tax Slab\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n \n }\n]" + "links": "[\n {\n \"label\": \"Payroll Period\",\n \"name\": \"Payroll Period\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Income Tax Slab\",\n \"name\": \"Income Tax Slab\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Other Income\",\n \"name\": \"Employee Other Income\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Declaration\",\n \"name\": \"Employee Tax Exemption Declaration\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Proof Submission\",\n \"name\": \"Employee Tax Exemption Proof Submission\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Category\",\n \"name\": \"Employee Tax Exemption Category\",\n \"type\": \"doctype\"\n \n },\n {\n \"label\": \"Employee Tax Exemption Sub Category\",\n \"name\": \"Employee Tax Exemption Sub Category\",\n \"type\": \"doctype\"\n \n }\n]" }, { "hidden": 0, @@ -38,7 +38,7 @@ "idx": 0, "is_standard": 1, "label": "Payroll", - "modified": "2020-06-19 12:23:06.034046", + "modified": "2020-08-10 19:38:45.976209", "modified_by": "Administrator", "module": "Payroll", "name": "Payroll",