mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-22 06:29:20 +00:00
Merge pull request #36176 from frappe/version-14-hotfix
chore: release v14
This commit is contained in:
38
.github/workflows/release_notes.yml
vendored
Normal file
38
.github/workflows/release_notes.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# This action:
|
||||||
|
#
|
||||||
|
# 1. Generates release notes using github API.
|
||||||
|
# 2. Strips unnecessary info like chore/style etc from notes.
|
||||||
|
# 3. Updates release info.
|
||||||
|
|
||||||
|
# This action needs to be maintained on all branches that do releases.
|
||||||
|
|
||||||
|
name: 'Release Notes'
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag_name:
|
||||||
|
description: 'Tag of release like v13.0.0'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release:
|
||||||
|
types: [released]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
regen-notes:
|
||||||
|
name: 'Regenerate release notes'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Update notes
|
||||||
|
run: |
|
||||||
|
NEW_NOTES=$(gh api --method POST -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/generate-notes -f tag_name=$RELEASE_TAG | jq -r '.body' | sed -E '/^\* (chore|ci|test|docs|style)/d' )
|
||||||
|
RELEASE_ID=$(gh api -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/tags/$RELEASE_TAG | jq -r '.id')
|
||||||
|
gh api --method PATCH -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/$RELEASE_ID -f body="$NEW_NOTES"
|
||||||
|
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
RELEASE_TAG: ${{ github.event.inputs.tag_name || github.event.release.tag_name }}
|
||||||
@@ -14,10 +14,8 @@ class AccountClosingBalance(Document):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def make_closing_entries(closing_entries, voucher_name):
|
def make_closing_entries(closing_entries, voucher_name, company, closing_date):
|
||||||
accounting_dimensions = get_accounting_dimensions()
|
accounting_dimensions = get_accounting_dimensions()
|
||||||
company = closing_entries[0].get("company")
|
|
||||||
closing_date = closing_entries[0].get("closing_date")
|
|
||||||
|
|
||||||
previous_closing_entries = get_previous_closing_entries(
|
previous_closing_entries = get_previous_closing_entries(
|
||||||
company, closing_date, accounting_dimensions
|
company, closing_date, accounting_dimensions
|
||||||
|
|||||||
@@ -271,6 +271,12 @@ def get_dimensions(with_cost_center_and_project=False):
|
|||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if isinstance(with_cost_center_and_project, str):
|
||||||
|
if with_cost_center_and_project.lower().strip() == "true":
|
||||||
|
with_cost_center_and_project = True
|
||||||
|
else:
|
||||||
|
with_cost_center_and_project = False
|
||||||
|
|
||||||
if with_cost_center_and_project:
|
if with_cost_center_and_project:
|
||||||
dimension_filters.extend(
|
dimension_filters.extend(
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -20,5 +20,11 @@ frappe.ui.form.on('Accounting Period', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.set_query("document_type", "closed_documents", () => {
|
||||||
|
return {
|
||||||
|
query: "erpnext.controllers.queries.get_doctypes_for_closing",
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ class OverlapError(frappe.ValidationError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ClosedAccountingPeriod(frappe.ValidationError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AccountingPeriod(Document):
|
class AccountingPeriod(Document):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_overlap()
|
self.validate_overlap()
|
||||||
@@ -65,3 +69,42 @@ class AccountingPeriod(Document):
|
|||||||
"closed_documents",
|
"closed_documents",
|
||||||
{"document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed},
|
{"document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_accounting_period_on_doc_save(doc, method=None):
|
||||||
|
if doc.doctype == "Bank Clearance":
|
||||||
|
return
|
||||||
|
elif doc.doctype == "Asset":
|
||||||
|
if doc.is_existing_asset:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
date = doc.available_for_use_date
|
||||||
|
elif doc.doctype == "Asset Repair":
|
||||||
|
date = doc.completion_date
|
||||||
|
else:
|
||||||
|
date = doc.posting_date
|
||||||
|
|
||||||
|
ap = frappe.qb.DocType("Accounting Period")
|
||||||
|
cd = frappe.qb.DocType("Closed Document")
|
||||||
|
|
||||||
|
accounting_period = (
|
||||||
|
frappe.qb.from_(ap)
|
||||||
|
.from_(cd)
|
||||||
|
.select(ap.name)
|
||||||
|
.where(
|
||||||
|
(ap.name == cd.parent)
|
||||||
|
& (ap.company == doc.company)
|
||||||
|
& (cd.closed == 1)
|
||||||
|
& (cd.document_type == doc.doctype)
|
||||||
|
& (date >= ap.start_date)
|
||||||
|
& (date <= ap.end_date)
|
||||||
|
)
|
||||||
|
).run(as_dict=1)
|
||||||
|
|
||||||
|
if accounting_period:
|
||||||
|
frappe.throw(
|
||||||
|
_("You cannot create a {0} within the closed Accounting Period {1}").format(
|
||||||
|
doc.doctype, frappe.bold(accounting_period[0]["name"])
|
||||||
|
),
|
||||||
|
ClosedAccountingPeriod,
|
||||||
|
)
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import unittest
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import add_months, nowdate
|
from frappe.utils import add_months, nowdate
|
||||||
|
|
||||||
from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError
|
from erpnext.accounts.doctype.accounting_period.accounting_period import (
|
||||||
|
ClosedAccountingPeriod,
|
||||||
|
OverlapError,
|
||||||
|
)
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
from erpnext.accounts.general_ledger import ClosedAccountingPeriod
|
|
||||||
|
|
||||||
test_dependencies = ["Item"]
|
test_dependencies = ["Item"]
|
||||||
|
|
||||||
@@ -33,9 +35,9 @@ class TestAccountingPeriod(unittest.TestCase):
|
|||||||
ap1.save()
|
ap1.save()
|
||||||
|
|
||||||
doc = create_sales_invoice(
|
doc = create_sales_invoice(
|
||||||
do_not_submit=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC"
|
do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC"
|
||||||
)
|
)
|
||||||
self.assertRaises(ClosedAccountingPeriod, doc.submit)
|
self.assertRaises(ClosedAccountingPeriod, doc.save)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
for d in frappe.get_all("Accounting Period"):
|
for d in frappe.get_all("Accounting Period"):
|
||||||
|
|||||||
@@ -8,17 +8,6 @@ frappe.ui.form.on('Fiscal Year', {
|
|||||||
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1));
|
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
refresh: function (frm) {
|
|
||||||
if (!frm.doc.__islocal && (frm.doc.name != frappe.sys_defaults.fiscal_year)) {
|
|
||||||
frm.add_custom_button(__("Set as Default"), () => frm.events.set_as_default(frm));
|
|
||||||
frm.set_intro(__("To set this Fiscal Year as Default, click on 'Set as Default'"));
|
|
||||||
} else {
|
|
||||||
frm.set_intro("");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set_as_default: function(frm) {
|
|
||||||
return frm.call('set_as_default');
|
|
||||||
},
|
|
||||||
year_start_date: function(frm) {
|
year_start_date: function(frm) {
|
||||||
if (!frm.doc.is_short_year) {
|
if (!frm.doc.is_short_year) {
|
||||||
let year_end_date =
|
let year_end_date =
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from frappe import _, msgprint
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import add_days, add_years, cstr, getdate
|
from frappe.utils import add_days, add_years, cstr, getdate
|
||||||
|
|
||||||
@@ -14,22 +14,6 @@ class FiscalYearIncorrectDate(frappe.ValidationError):
|
|||||||
|
|
||||||
|
|
||||||
class FiscalYear(Document):
|
class FiscalYear(Document):
|
||||||
@frappe.whitelist()
|
|
||||||
def set_as_default(self):
|
|
||||||
frappe.db.set_value("Global Defaults", None, "current_fiscal_year", self.name)
|
|
||||||
global_defaults = frappe.get_doc("Global Defaults")
|
|
||||||
global_defaults.check_permission("write")
|
|
||||||
global_defaults.on_update()
|
|
||||||
|
|
||||||
# clear cache
|
|
||||||
frappe.clear_cache()
|
|
||||||
|
|
||||||
msgprint(
|
|
||||||
_(
|
|
||||||
"{0} is now the default Fiscal Year. Please refresh your browser for the change to take effect."
|
|
||||||
).format(self.name)
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
self.validate_overlap()
|
self.validate_overlap()
|
||||||
@@ -77,13 +61,6 @@ class FiscalYear(Document):
|
|||||||
frappe.cache().delete_value("fiscal_years")
|
frappe.cache().delete_value("fiscal_years")
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
global_defaults = frappe.get_doc("Global Defaults")
|
|
||||||
if global_defaults.current_fiscal_year == self.name:
|
|
||||||
frappe.throw(
|
|
||||||
_(
|
|
||||||
"You cannot delete Fiscal Year {0}. Fiscal Year {0} is set as default in Global Settings"
|
|
||||||
).format(self.name)
|
|
||||||
)
|
|
||||||
frappe.cache().delete_value("fiscal_years")
|
frappe.cache().delete_value("fiscal_years")
|
||||||
|
|
||||||
def validate_overlap(self):
|
def validate_overlap(self):
|
||||||
|
|||||||
@@ -396,6 +396,15 @@ class JournalEntry(AccountsController):
|
|||||||
d.idx, d.account
|
d.idx, d.account
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
elif (
|
||||||
|
d.party_type
|
||||||
|
and frappe.db.get_value("Party Type", d.party_type, "account_type") != account_type
|
||||||
|
):
|
||||||
|
frappe.throw(
|
||||||
|
_("Row {0}: Account {1} and Party Type {2} have different account types").format(
|
||||||
|
d.idx, d.account, d.party_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def check_credit_limit(self):
|
def check_credit_limit(self):
|
||||||
customers = list(
|
customers = list(
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
gl_entries=gl_entries,
|
gl_entries=gl_entries,
|
||||||
closing_entries=closing_entries,
|
closing_entries=closing_entries,
|
||||||
voucher_name=self.name,
|
voucher_name=self.name,
|
||||||
|
company=self.company,
|
||||||
|
closing_date=self.posting_date,
|
||||||
queue="long",
|
queue="long",
|
||||||
)
|
)
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
@@ -140,7 +142,7 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
alert=True,
|
alert=True,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
process_gl_entries(gl_entries, closing_entries, voucher_name=self.name)
|
process_gl_entries(gl_entries, closing_entries, self.name, self.company, self.posting_date)
|
||||||
|
|
||||||
def get_grouped_gl_entries(self, get_opening_entries=False):
|
def get_grouped_gl_entries(self, get_opening_entries=False):
|
||||||
closing_entries = []
|
closing_entries = []
|
||||||
@@ -321,7 +323,7 @@ class PeriodClosingVoucher(AccountsController):
|
|||||||
return query.run(as_dict=1)
|
return query.run(as_dict=1)
|
||||||
|
|
||||||
|
|
||||||
def process_gl_entries(gl_entries, closing_entries, voucher_name=None):
|
def process_gl_entries(gl_entries, closing_entries, voucher_name, company, closing_date):
|
||||||
from erpnext.accounts.doctype.account_closing_balance.account_closing_balance import (
|
from erpnext.accounts.doctype.account_closing_balance.account_closing_balance import (
|
||||||
make_closing_entries,
|
make_closing_entries,
|
||||||
)
|
)
|
||||||
@@ -329,7 +331,7 @@ def process_gl_entries(gl_entries, closing_entries, voucher_name=None):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
make_gl_entries(gl_entries, merge_entries=False)
|
make_gl_entries(gl_entries, merge_entries=False)
|
||||||
make_closing_entries(gl_entries + closing_entries, voucher_name=voucher_name)
|
make_closing_entries(gl_entries + closing_entries, voucher_name, company, closing_date)
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
"Period Closing Voucher", gl_entries[0].get("voucher_no"), "gle_processing_status", "Completed"
|
"Period Closing Voucher", gl_entries[0].get("voucher_no"), "gle_processing_status", "Completed"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,14 +13,11 @@ import erpnext
|
|||||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||||
get_accounting_dimensions,
|
get_accounting_dimensions,
|
||||||
)
|
)
|
||||||
|
from erpnext.accounts.doctype.accounting_period.accounting_period import ClosedAccountingPeriod
|
||||||
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
|
from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget
|
||||||
from erpnext.accounts.utils import create_payment_ledger_entry
|
from erpnext.accounts.utils import create_payment_ledger_entry
|
||||||
|
|
||||||
|
|
||||||
class ClosedAccountingPeriod(frappe.ValidationError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def make_gl_entries(
|
def make_gl_entries(
|
||||||
gl_map,
|
gl_map,
|
||||||
cancel=False,
|
cancel=False,
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
"label": __("Start Year"),
|
"label": __("Start Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
on_change: () => {
|
on_change: () => {
|
||||||
frappe.model.with_doc("Fiscal Year", frappe.query_report.get_filter_value('from_fiscal_year'), function(r) {
|
frappe.model.with_doc("Fiscal Year", frappe.query_report.get_filter_value('from_fiscal_year'), function(r) {
|
||||||
@@ -65,7 +65,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
"label": __("End Year"),
|
"label": __("End Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
on_change: () => {
|
on_change: () => {
|
||||||
frappe.model.with_doc("Fiscal Year", frappe.query_report.get_filter_value('to_fiscal_year'), function(r) {
|
frappe.model.with_doc("Fiscal Year", frappe.query_report.get_filter_value('to_fiscal_year'), function(r) {
|
||||||
@@ -139,7 +139,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
onload: function() {
|
onload: function() {
|
||||||
let fiscal_year = frappe.defaults.get_user_default("fiscal_year")
|
let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today());
|
||||||
|
|
||||||
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
||||||
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ function get_filters() {
|
|||||||
"label": __("Start Year"),
|
"label": __("Start Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -56,7 +56,7 @@ function get_filters() {
|
|||||||
"label": __("End Year"),
|
"label": __("End Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,7 @@ frappe.query_reports["Deferred Revenue and Expense"] = {
|
|||||||
return default_formatter(value, row, column, data);
|
return default_formatter(value, row, column, data);
|
||||||
},
|
},
|
||||||
onload: function(report){
|
onload: function(report){
|
||||||
let fiscal_year = frappe.defaults.get_user_default("fiscal_year");
|
let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today());
|
||||||
|
|
||||||
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
||||||
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _, qb
|
from frappe import _, qb
|
||||||
from frappe.query_builder import Column, functions
|
from frappe.query_builder import Column, functions
|
||||||
from frappe.utils import add_days, date_diff, flt, get_first_day, get_last_day, rounded
|
from frappe.utils import add_days, date_diff, flt, get_first_day, get_last_day, getdate, rounded
|
||||||
|
|
||||||
from erpnext.accounts.report.financial_statements import get_period_list
|
from erpnext.accounts.report.financial_statements import get_period_list
|
||||||
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
|
|
||||||
|
|
||||||
class Deferred_Item(object):
|
class Deferred_Item(object):
|
||||||
@@ -226,7 +227,7 @@ class Deferred_Revenue_and_Expense_Report(object):
|
|||||||
|
|
||||||
# If no filters are provided, get user defaults
|
# If no filters are provided, get user defaults
|
||||||
if not filters:
|
if not filters:
|
||||||
fiscal_year = frappe.get_doc("Fiscal Year", frappe.defaults.get_user_default("fiscal_year"))
|
fiscal_year = frappe.get_doc("Fiscal Year", get_fiscal_year(date=getdate()))
|
||||||
self.filters = frappe._dict(
|
self.filters = frappe._dict(
|
||||||
{
|
{
|
||||||
"company": frappe.defaults.get_user_default("Company"),
|
"company": frappe.defaults.get_user_default("Company"),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
|
|||||||
from erpnext.accounts.report.deferred_revenue_and_expense.deferred_revenue_and_expense import (
|
from erpnext.accounts.report.deferred_revenue_and_expense.deferred_revenue_and_expense import (
|
||||||
Deferred_Revenue_and_Expense_Report,
|
Deferred_Revenue_and_Expense_Report,
|
||||||
)
|
)
|
||||||
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
|
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
|
||||||
from erpnext.stock.doctype.item.test_item import create_item
|
from erpnext.stock.doctype.item.test_item import create_item
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@ class TestDeferredRevenueAndExpense(unittest.TestCase):
|
|||||||
pda.submit()
|
pda.submit()
|
||||||
|
|
||||||
# execute report
|
# execute report
|
||||||
fiscal_year = frappe.get_doc("Fiscal Year", frappe.defaults.get_user_default("fiscal_year"))
|
fiscal_year = frappe.get_doc("Fiscal Year", get_fiscal_year(date="2021-05-01"))
|
||||||
self.filters = frappe._dict(
|
self.filters = frappe._dict(
|
||||||
{
|
{
|
||||||
"company": frappe.defaults.get_user_default("Company"),
|
"company": frappe.defaults.get_user_default("Company"),
|
||||||
@@ -209,7 +210,7 @@ class TestDeferredRevenueAndExpense(unittest.TestCase):
|
|||||||
pda.submit()
|
pda.submit()
|
||||||
|
|
||||||
# execute report
|
# execute report
|
||||||
fiscal_year = frappe.get_doc("Fiscal Year", frappe.defaults.get_user_default("fiscal_year"))
|
fiscal_year = frappe.get_doc("Fiscal Year", get_fiscal_year(date="2021-05-01"))
|
||||||
self.filters = frappe._dict(
|
self.filters = frappe._dict(
|
||||||
{
|
{
|
||||||
"company": frappe.defaults.get_user_default("Company"),
|
"company": frappe.defaults.get_user_default("Company"),
|
||||||
@@ -297,7 +298,7 @@ class TestDeferredRevenueAndExpense(unittest.TestCase):
|
|||||||
pda.submit()
|
pda.submit()
|
||||||
|
|
||||||
# execute report
|
# execute report
|
||||||
fiscal_year = frappe.get_doc("Fiscal Year", frappe.defaults.get_user_default("fiscal_year"))
|
fiscal_year = frappe.get_doc("Fiscal Year", get_fiscal_year(date="2021-05-01"))
|
||||||
self.filters = frappe._dict(
|
self.filters = frappe._dict(
|
||||||
{
|
{
|
||||||
"company": frappe.defaults.get_user_default("Company"),
|
"company": frappe.defaults.get_user_default("Company"),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
"label": __("Fiscal Year"),
|
"label": __("Fiscal Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"on_change": function(query_report) {
|
"on_change": function(query_report) {
|
||||||
var fiscal_year = query_report.get_values().fiscal_year;
|
var fiscal_year = query_report.get_values().fiscal_year;
|
||||||
|
|||||||
@@ -12,14 +12,6 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
erpnext.financial_statements);
|
erpnext.financial_statements);
|
||||||
|
|
||||||
frappe.query_reports["Gross and Net Profit Report"]["filters"].push(
|
frappe.query_reports["Gross and Net Profit Report"]["filters"].push(
|
||||||
{
|
|
||||||
"fieldname": "project",
|
|
||||||
"label": __("Project"),
|
|
||||||
"fieldtype": "MultiSelectList",
|
|
||||||
get_data: function(txt) {
|
|
||||||
return frappe.db.get_link_options('Project', txt);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "accumulated_values",
|
"fieldname": "accumulated_values",
|
||||||
"label": __("Accumulated Values"),
|
"label": __("Accumulated Values"),
|
||||||
|
|||||||
@@ -9,16 +9,6 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
erpnext.utils.add_dimensions('Profit and Loss Statement', 10);
|
erpnext.utils.add_dimensions('Profit and Loss Statement', 10);
|
||||||
|
|
||||||
frappe.query_reports["Profit and Loss Statement"]["filters"].push(
|
frappe.query_reports["Profit and Loss Statement"]["filters"].push(
|
||||||
{
|
|
||||||
"fieldname": "project",
|
|
||||||
"label": __("Project"),
|
|
||||||
"fieldtype": "MultiSelectList",
|
|
||||||
get_data: function(txt) {
|
|
||||||
return frappe.db.get_link_options('Project', txt, {
|
|
||||||
company: frappe.query_report.get_filter_value("company")
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "include_default_book_entries",
|
"fieldname": "include_default_book_entries",
|
||||||
"label": __("Include Default Book Entries"),
|
"label": __("Include Default Book Entries"),
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
"label": __("Fiscal Year"),
|
"label": __("Fiscal Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"on_change": function(query_report) {
|
"on_change": function(query_report) {
|
||||||
var fiscal_year = query_report.get_values().fiscal_year;
|
var fiscal_year = query_report.get_values().fiscal_year;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
|||||||
"label": __("Fiscal Year"),
|
"label": __("Fiscal Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"on_change": function(query_report) {
|
"on_change": function(query_report) {
|
||||||
var fiscal_year = query_report.get_values().fiscal_year;
|
var fiscal_year = query_report.get_values().fiscal_year;
|
||||||
|
|||||||
@@ -221,7 +221,10 @@ def get_opening_balance(
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if start_date:
|
if start_date:
|
||||||
opening_balance = opening_balance.where(closing_balance.posting_date >= start_date)
|
opening_balance = opening_balance.where(
|
||||||
|
(closing_balance.posting_date >= start_date)
|
||||||
|
& (closing_balance.posting_date < filters.from_date)
|
||||||
|
)
|
||||||
opening_balance = opening_balance.where(closing_balance.is_opening == "No")
|
opening_balance = opening_balance.where(closing_balance.is_opening == "No")
|
||||||
else:
|
else:
|
||||||
opening_balance = opening_balance.where(
|
opening_balance = opening_balance.where(
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ frappe.query_reports["Trial Balance for Party"] = {
|
|||||||
"label": __("Fiscal Year"),
|
"label": __("Fiscal Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"on_change": function(query_report) {
|
"on_change": function(query_report) {
|
||||||
var fiscal_year = query_report.get_values().fiscal_year;
|
var fiscal_year = query_report.get_values().fiscal_year;
|
||||||
|
|||||||
@@ -1106,6 +1106,11 @@ def get_autoname_with_number(number_value, doc_title, company):
|
|||||||
return " - ".join(parts)
|
return " - ".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_naming_series_variable(doc, variable):
|
||||||
|
if variable == "FY":
|
||||||
|
return get_fiscal_year(date=doc.get("posting_date"), company=doc.get("company"))[0]
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_coa(doctype, parent, is_root, chart=None):
|
def get_coa(doctype, parent, is_root, chart=None):
|
||||||
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import (
|
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import (
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ frappe.ui.form.on('Asset Movement', {
|
|||||||
fieldnames_to_be_altered = {
|
fieldnames_to_be_altered = {
|
||||||
target_location: { read_only: 0, reqd: 1 },
|
target_location: { read_only: 0, reqd: 1 },
|
||||||
source_location: { read_only: 1, reqd: 0 },
|
source_location: { read_only: 1, reqd: 0 },
|
||||||
from_employee: { read_only: 0, reqd: 1 },
|
from_employee: { read_only: 0, reqd: 0 },
|
||||||
to_employee: { read_only: 1, reqd: 0 }
|
to_employee: { read_only: 1, reqd: 0 }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,29 +62,20 @@ class AssetMovement(Document):
|
|||||||
frappe.throw(_("Source and Target Location cannot be same"))
|
frappe.throw(_("Source and Target Location cannot be same"))
|
||||||
|
|
||||||
if self.purpose == "Receipt":
|
if self.purpose == "Receipt":
|
||||||
# only when asset is bought and first entry is made
|
if not (d.source_location or d.from_employee) and not (d.target_location or d.to_employee):
|
||||||
if not d.source_location and not (d.target_location or d.to_employee):
|
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Target Location or To Employee is required while receiving Asset {0}").format(d.asset)
|
_("Target Location or To Employee is required while receiving Asset {0}").format(d.asset)
|
||||||
)
|
)
|
||||||
elif d.source_location:
|
elif d.from_employee and not d.target_location:
|
||||||
# when asset is received from an employee
|
frappe.throw(
|
||||||
if d.target_location and not d.from_employee:
|
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
|
||||||
frappe.throw(
|
)
|
||||||
_("From employee is required while receiving Asset {0} to a target location").format(
|
elif d.to_employee and d.target_location:
|
||||||
d.asset
|
frappe.throw(
|
||||||
)
|
_(
|
||||||
)
|
"Asset {0} cannot be received at a location and given to an employee in a single movement"
|
||||||
if d.from_employee and not d.target_location:
|
).format(d.asset)
|
||||||
frappe.throw(
|
)
|
||||||
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
|
|
||||||
)
|
|
||||||
if d.to_employee and d.target_location:
|
|
||||||
frappe.throw(
|
|
||||||
_(
|
|
||||||
"Asset {0} cannot be received at a location and given to employee in a single movement"
|
|
||||||
).format(d.asset)
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate_employee(self):
|
def validate_employee(self):
|
||||||
for d in self.assets:
|
for d in self.assets:
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ frappe.query_reports["Fixed Asset Register"] = {
|
|||||||
"label": __("Start Year"),
|
"label": __("Start Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
|
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -90,7 +90,7 @@ frappe.query_reports["Fixed Asset Register"] = {
|
|||||||
"label": __("End Year"),
|
"label": __("End Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
|
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -771,6 +771,15 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
return frappe.db.sql(query, filters)
|
return frappe.db.sql(query, filters)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
|
def get_doctypes_for_closing(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
doctypes = frappe.get_hooks("period_closing_doctypes")
|
||||||
|
if txt:
|
||||||
|
doctypes = [d for d in doctypes if txt.lower() in d.lower()]
|
||||||
|
return [(d,) for d in set(doctypes)]
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@frappe.validate_and_sanitize_search_inputs
|
@frappe.validate_and_sanitize_search_inputs
|
||||||
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ webform_list_context = "erpnext.controllers.website_list_for_contact.get_webform
|
|||||||
calendars = [
|
calendars = [
|
||||||
"Task",
|
"Task",
|
||||||
"Work Order",
|
"Work Order",
|
||||||
"Leave Application",
|
|
||||||
"Sales Order",
|
"Sales Order",
|
||||||
"Holiday List",
|
"Holiday List",
|
||||||
]
|
]
|
||||||
@@ -279,10 +278,34 @@ standard_queries = {
|
|||||||
"Customer": "erpnext.controllers.queries.customer_query",
|
"Customer": "erpnext.controllers.queries.customer_query",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
period_closing_doctypes = [
|
||||||
|
"Sales Invoice",
|
||||||
|
"Purchase Invoice",
|
||||||
|
"Journal Entry",
|
||||||
|
"Bank Clearance",
|
||||||
|
"Stock Entry",
|
||||||
|
"Dunning",
|
||||||
|
"Invoice Discounting",
|
||||||
|
"Payment Entry",
|
||||||
|
"Period Closing Voucher",
|
||||||
|
"Process Deferred Accounting",
|
||||||
|
"Asset",
|
||||||
|
"Asset Capitalization",
|
||||||
|
"Asset Repair",
|
||||||
|
"Delivery Note",
|
||||||
|
"Landed Cost Voucher",
|
||||||
|
"Purchase Receipt",
|
||||||
|
"Stock Reconciliation",
|
||||||
|
"Subcontracting Receipt",
|
||||||
|
]
|
||||||
|
|
||||||
doc_events = {
|
doc_events = {
|
||||||
"*": {
|
"*": {
|
||||||
"validate": "erpnext.support.doctype.service_level_agreement.service_level_agreement.apply",
|
"validate": "erpnext.support.doctype.service_level_agreement.service_level_agreement.apply",
|
||||||
},
|
},
|
||||||
|
tuple(period_closing_doctypes): {
|
||||||
|
"validate": "erpnext.accounts.doctype.accounting_period.accounting_period.validate_accounting_period_on_doc_save",
|
||||||
|
},
|
||||||
"Stock Entry": {
|
"Stock Entry": {
|
||||||
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
|
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
|
||||||
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
|
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
|
||||||
@@ -359,6 +382,11 @@ doc_events = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# function should expect the variable and doc as arguments
|
||||||
|
naming_series_variables = {
|
||||||
|
"FY": "erpnext.accounts.utils.parse_naming_series_variable",
|
||||||
|
}
|
||||||
|
|
||||||
# On cancel event Payment Entry will be exempted and all linked submittable doctype will get cancelled.
|
# On cancel event Payment Entry will be exempted and all linked submittable doctype will get cancelled.
|
||||||
# to maintain data integrity we exempted payment entry. it will un-link when sales invoice get cancelled.
|
# to maintain data integrity we exempted payment entry. it will un-link when sales invoice get cancelled.
|
||||||
# if payment entry not in auto cancel exempted doctypes it will cancel payment entry.
|
# if payment entry not in auto cancel exempted doctypes it will cancel payment entry.
|
||||||
@@ -467,15 +495,6 @@ advance_payment_doctypes = ["Sales Order", "Purchase Order"]
|
|||||||
|
|
||||||
invoice_doctypes = ["Sales Invoice", "Purchase Invoice"]
|
invoice_doctypes = ["Sales Invoice", "Purchase Invoice"]
|
||||||
|
|
||||||
period_closing_doctypes = [
|
|
||||||
"Sales Invoice",
|
|
||||||
"Purchase Invoice",
|
|
||||||
"Journal Entry",
|
|
||||||
"Bank Clearance",
|
|
||||||
"Asset",
|
|
||||||
"Stock Entry",
|
|
||||||
]
|
|
||||||
|
|
||||||
bank_reconciliation_doctypes = [
|
bank_reconciliation_doctypes = [
|
||||||
"Payment Entry",
|
"Payment Entry",
|
||||||
"Journal Entry",
|
"Journal Entry",
|
||||||
@@ -612,3 +631,8 @@ global_search_doctypes = {
|
|||||||
additional_timeline_content = {
|
additional_timeline_content = {
|
||||||
"*": ["erpnext.telephony.doctype.call_log.call_log.get_linked_call_logs"]
|
"*": ["erpnext.telephony.doctype.call_log.call_log.get_linked_call_logs"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extend_bootinfo = [
|
||||||
|
"erpnext.support.doctype.service_level_agreement.service_level_agreement.add_sla_doctypes",
|
||||||
|
]
|
||||||
|
|||||||
@@ -1001,7 +1001,7 @@ class WorkOrder(Document):
|
|||||||
consumed_qty = frappe.db.sql(
|
consumed_qty = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
SELECT
|
SELECT
|
||||||
SUM(qty)
|
SUM(detail.qty)
|
||||||
FROM
|
FROM
|
||||||
`tabStock Entry` entry,
|
`tabStock Entry` entry,
|
||||||
`tabStock Entry Detail` detail
|
`tabStock Entry Detail` detail
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ frappe.query_reports["Job Card Summary"] = {
|
|||||||
label: __("Fiscal Year"),
|
label: __("Fiscal Year"),
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Fiscal Year",
|
options: "Fiscal Year",
|
||||||
default: frappe.defaults.get_user_default("fiscal_year"),
|
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
reqd: 1,
|
reqd: 1,
|
||||||
on_change: function(query_report) {
|
on_change: function(query_report) {
|
||||||
var fiscal_year = query_report.get_values().fiscal_year;
|
var fiscal_year = query_report.get_values().fiscal_year;
|
||||||
|
|||||||
@@ -337,3 +337,4 @@ erpnext.patches.v14_0.enable_allow_existing_serial_no
|
|||||||
erpnext.patches.v14_0.set_report_in_process_SOA
|
erpnext.patches.v14_0.set_report_in_process_SOA
|
||||||
erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
|
erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
|
||||||
erpnext.patches.v14_0.update_closing_balances #15-07-2023
|
erpnext.patches.v14_0.update_closing_balances #15-07-2023
|
||||||
|
execute:frappe.defaults.clear_default("fiscal_year")
|
||||||
@@ -69,7 +69,6 @@ def execute():
|
|||||||
|
|
||||||
entries = gl_entries + closing_entries
|
entries = gl_entries + closing_entries
|
||||||
|
|
||||||
if entries:
|
make_closing_entries(entries, pcv.name, pcv.company, pcv.posting_date)
|
||||||
make_closing_entries(entries, voucher_name=pcv.name)
|
company_wise_order[pcv.company].append(pcv.posting_date)
|
||||||
i += 1
|
i += 1
|
||||||
company_wise_order[pcv.company].append(pcv.posting_date)
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ erpnext.financial_statements = {
|
|||||||
// dropdown for links to other financial statements
|
// dropdown for links to other financial statements
|
||||||
erpnext.financial_statements.filters = get_filters()
|
erpnext.financial_statements.filters = get_filters()
|
||||||
|
|
||||||
let fiscal_year = frappe.defaults.get_user_default("fiscal_year")
|
let fiscal_year = erpnext.utils.get_fiscal_year(frappe.datetime.get_today());
|
||||||
|
|
||||||
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
|
||||||
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
|
||||||
@@ -137,7 +137,7 @@ function get_filters() {
|
|||||||
"label": __("Start Year"),
|
"label": __("Start Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
|
"depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
|
||||||
},
|
},
|
||||||
@@ -146,7 +146,7 @@ function get_filters() {
|
|||||||
"label": __("End Year"),
|
"label": __("End Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
|
"depends_on": "eval:doc.filter_based_on == 'Fiscal Year'"
|
||||||
},
|
},
|
||||||
@@ -182,6 +182,16 @@ function get_filters() {
|
|||||||
company: frappe.query_report.get_filter_value("company")
|
company: frappe.query_report.get_filter_value("company")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "project",
|
||||||
|
"label": __("Project"),
|
||||||
|
"fieldtype": "MultiSelectList",
|
||||||
|
get_data: function(txt) {
|
||||||
|
return frappe.db.get_link_options('Project', txt, {
|
||||||
|
company: frappe.query_report.get_filter_value("company")
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -350,6 +350,23 @@ $.extend(erpnext.utils, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get_fiscal_year: function(date) {
|
||||||
|
let fiscal_year = '';
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.accounts.utils.get_fiscal_year",
|
||||||
|
args: {
|
||||||
|
date: date
|
||||||
|
},
|
||||||
|
async: false,
|
||||||
|
callback: function(r) {
|
||||||
|
if (r.message) {
|
||||||
|
fiscal_year = r.message[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return fiscal_year;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
erpnext.utils.select_alternate_items = function(opts) {
|
erpnext.utils.select_alternate_items = function(opts) {
|
||||||
@@ -600,7 +617,6 @@ erpnext.utils.update_child_items = function(opts) {
|
|||||||
fields.splice(3, 0, {
|
fields.splice(3, 0, {
|
||||||
fieldtype: 'Float',
|
fieldtype: 'Float',
|
||||||
fieldname: "conversion_factor",
|
fieldname: "conversion_factor",
|
||||||
in_list_view: 1,
|
|
||||||
label: __("Conversion Factor"),
|
label: __("Conversion Factor"),
|
||||||
precision: get_precision('conversion_factor')
|
precision: get_precision('conversion_factor')
|
||||||
})
|
})
|
||||||
@@ -608,6 +624,7 @@ erpnext.utils.update_child_items = function(opts) {
|
|||||||
|
|
||||||
new frappe.ui.Dialog({
|
new frappe.ui.Dialog({
|
||||||
title: __("Update Items"),
|
title: __("Update Items"),
|
||||||
|
size: "extra-large",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
fieldname: "trans_items",
|
fieldname: "trans_items",
|
||||||
@@ -822,95 +839,87 @@ $(document).on('app_ready', function() {
|
|||||||
|
|
||||||
// Show SLA dashboard
|
// Show SLA dashboard
|
||||||
$(document).on('app_ready', function() {
|
$(document).on('app_ready', function() {
|
||||||
frappe.call({
|
$.each(frappe.boot.service_level_agreement_doctypes, function(_i, d) {
|
||||||
method: 'erpnext.support.doctype.service_level_agreement.service_level_agreement.get_sla_doctypes',
|
frappe.ui.form.on(d, {
|
||||||
callback: function(r) {
|
onload: function(frm) {
|
||||||
if (!r.message)
|
if (!frm.doc.service_level_agreement)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$.each(r.message, function(_i, d) {
|
frappe.call({
|
||||||
frappe.ui.form.on(d, {
|
method: 'erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters',
|
||||||
onload: function(frm) {
|
args: {
|
||||||
if (!frm.doc.service_level_agreement)
|
doctype: frm.doc.doctype,
|
||||||
return;
|
name: frm.doc.service_level_agreement,
|
||||||
|
customer: frm.doc.customer
|
||||||
frappe.call({
|
|
||||||
method: 'erpnext.support.doctype.service_level_agreement.service_level_agreement.get_service_level_agreement_filters',
|
|
||||||
args: {
|
|
||||||
doctype: frm.doc.doctype,
|
|
||||||
name: frm.doc.service_level_agreement,
|
|
||||||
customer: frm.doc.customer
|
|
||||||
},
|
|
||||||
callback: function (r) {
|
|
||||||
if (r && r.message) {
|
|
||||||
frm.set_query('priority', function() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
'name': ['in', r.message.priority],
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
frm.set_query('service_level_agreement', function() {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
'name': ['in', r.message.service_level_agreements],
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
callback: function (r) {
|
||||||
refresh: function(frm) {
|
if (r && r.message) {
|
||||||
if (frm.doc.status !== 'Closed' && frm.doc.service_level_agreement
|
frm.set_query('priority', function() {
|
||||||
&& ['First Response Due', 'Resolution Due'].includes(frm.doc.agreement_status)) {
|
return {
|
||||||
frappe.call({
|
filters: {
|
||||||
'method': 'frappe.client.get',
|
'name': ['in', r.message.priority],
|
||||||
args: {
|
|
||||||
doctype: 'Service Level Agreement',
|
|
||||||
name: frm.doc.service_level_agreement
|
|
||||||
},
|
|
||||||
callback: function(data) {
|
|
||||||
let statuses = data.message.pause_sla_on;
|
|
||||||
const hold_statuses = [];
|
|
||||||
$.each(statuses, (_i, entry) => {
|
|
||||||
hold_statuses.push(entry.status);
|
|
||||||
});
|
|
||||||
if (hold_statuses.includes(frm.doc.status)) {
|
|
||||||
frm.dashboard.clear_headline();
|
|
||||||
let message = {'indicator': 'orange', 'msg': __('SLA is on hold since {0}', [moment(frm.doc.on_hold_since).fromNow(true)])};
|
|
||||||
frm.dashboard.set_headline_alert(
|
|
||||||
'<div class="row">' +
|
|
||||||
'<div class="col-xs-12">' +
|
|
||||||
'<span class="indicator whitespace-nowrap '+ message.indicator +'"><span>'+ message.msg +'</span></span> ' +
|
|
||||||
'</div>' +
|
|
||||||
'</div>'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
set_time_to_resolve_and_response(frm, data.message.apply_sla_for_resolution);
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
});
|
||||||
|
frm.set_query('service_level_agreement', function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
'name': ['in', r.message.service_level_agreements],
|
||||||
|
}
|
||||||
|
};
|
||||||
});
|
});
|
||||||
} else if (frm.doc.service_level_agreement) {
|
|
||||||
frm.dashboard.clear_headline();
|
|
||||||
|
|
||||||
let agreement_status = (frm.doc.agreement_status == 'Fulfilled') ?
|
|
||||||
{'indicator': 'green', 'msg': 'Service Level Agreement has been fulfilled'} :
|
|
||||||
{'indicator': 'red', 'msg': 'Service Level Agreement Failed'};
|
|
||||||
|
|
||||||
frm.dashboard.set_headline_alert(
|
|
||||||
'<div class="row">' +
|
|
||||||
'<div class="col-xs-12">' +
|
|
||||||
'<span class="indicator whitespace-nowrap '+ agreement_status.indicator +'"><span class="hidden-xs">'+ agreement_status.msg +'</span></span> ' +
|
|
||||||
'</div>' +
|
|
||||||
'</div>'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
}
|
|
||||||
|
refresh: function(frm) {
|
||||||
|
if (frm.doc.status !== 'Closed' && frm.doc.service_level_agreement
|
||||||
|
&& ['First Response Due', 'Resolution Due'].includes(frm.doc.agreement_status)) {
|
||||||
|
frappe.call({
|
||||||
|
'method': 'frappe.client.get',
|
||||||
|
args: {
|
||||||
|
doctype: 'Service Level Agreement',
|
||||||
|
name: frm.doc.service_level_agreement
|
||||||
|
},
|
||||||
|
callback: function(data) {
|
||||||
|
let statuses = data.message.pause_sla_on;
|
||||||
|
const hold_statuses = [];
|
||||||
|
$.each(statuses, (_i, entry) => {
|
||||||
|
hold_statuses.push(entry.status);
|
||||||
|
});
|
||||||
|
if (hold_statuses.includes(frm.doc.status)) {
|
||||||
|
frm.dashboard.clear_headline();
|
||||||
|
let message = {'indicator': 'orange', 'msg': __('SLA is on hold since {0}', [moment(frm.doc.on_hold_since).fromNow(true)])};
|
||||||
|
frm.dashboard.set_headline_alert(
|
||||||
|
'<div class="row">' +
|
||||||
|
'<div class="col-xs-12">' +
|
||||||
|
'<span class="indicator whitespace-nowrap '+ message.indicator +'"><span>'+ message.msg +'</span></span> ' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
set_time_to_resolve_and_response(frm, data.message.apply_sla_for_resolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (frm.doc.service_level_agreement) {
|
||||||
|
frm.dashboard.clear_headline();
|
||||||
|
|
||||||
|
let agreement_status = (frm.doc.agreement_status == 'Fulfilled') ?
|
||||||
|
{'indicator': 'green', 'msg': 'Service Level Agreement has been fulfilled'} :
|
||||||
|
{'indicator': 'red', 'msg': 'Service Level Agreement Failed'};
|
||||||
|
|
||||||
|
frm.dashboard.set_headline_alert(
|
||||||
|
'<div class="row">' +
|
||||||
|
'<div class="col-xs-12">' +
|
||||||
|
'<span class="indicator whitespace-nowrap '+ agreement_status.indicator +'"><span class="hidden-xs">'+ agreement_status.msg +'</span></span> ' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ frappe.query_reports["Fichier des Ecritures Comptables [FEC]"] = {
|
|||||||
"label": __("Fiscal Year"),
|
"label": __("Fiscal Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ frappe.query_reports["IRS 1099"] = {
|
|||||||
"label": __("Fiscal Year"),
|
"label": __("Fiscal Year"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"options": "Fiscal Year",
|
"options": "Fiscal Year",
|
||||||
"default": frappe.defaults.get_user_default("fiscal_year"),
|
"default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today()),
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"width": 80,
|
"width": 80,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,352 +1,99 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 1,
|
"actions": [],
|
||||||
"allow_guest_to_view": 0,
|
"allow_copy": 1,
|
||||||
"allow_import": 0,
|
"creation": "2013-05-02 17:53:24",
|
||||||
"allow_rename": 0,
|
"doctype": "DocType",
|
||||||
"beta": 0,
|
"engine": "InnoDB",
|
||||||
"creation": "2013-05-02 17:53:24",
|
"field_order": [
|
||||||
"custom": 0,
|
"default_company",
|
||||||
"docstatus": 0,
|
"country",
|
||||||
"doctype": "DocType",
|
"default_distance_unit",
|
||||||
"editable_grid": 0,
|
"column_break_8",
|
||||||
|
"default_currency",
|
||||||
|
"hide_currency_symbol",
|
||||||
|
"disable_rounded_total",
|
||||||
|
"disable_in_words"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "default_company",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Link",
|
||||||
"allow_on_submit": 0,
|
"ignore_user_permissions": 1,
|
||||||
"bold": 0,
|
"label": "Default Company",
|
||||||
"collapsible": 0,
|
"options": "Company"
|
||||||
"columns": 0,
|
},
|
||||||
"fieldname": "default_company",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 1,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Default Company",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "country",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Link",
|
||||||
"allow_on_submit": 0,
|
"label": "Country",
|
||||||
"bold": 0,
|
"options": "Country"
|
||||||
"collapsible": 0,
|
},
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "current_fiscal_year",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Current Fiscal Year",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Fiscal Year",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "default_distance_unit",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Link",
|
||||||
"allow_on_submit": 0,
|
"label": "Default Distance Unit",
|
||||||
"bold": 0,
|
"options": "UOM"
|
||||||
"collapsible": 0,
|
},
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "country",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Country",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Country",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "column_break_8",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Column Break"
|
||||||
"allow_on_submit": 0,
|
},
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "",
|
|
||||||
"fieldname": "default_distance_unit",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Default Distance Unit",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "UOM",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "INR",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldname": "default_currency",
|
||||||
"allow_on_submit": 0,
|
"fieldtype": "Link",
|
||||||
"bold": 0,
|
"ignore_user_permissions": 1,
|
||||||
"collapsible": 0,
|
"in_list_view": 1,
|
||||||
"columns": 0,
|
"label": "Default Currency",
|
||||||
"fieldname": "column_break_8",
|
"options": "Currency",
|
||||||
"fieldtype": "Column Break",
|
"reqd": 1
|
||||||
"hidden": 0,
|
},
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"description": "Do not show any symbol like $ etc next to currencies.",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldname": "hide_currency_symbol",
|
||||||
"allow_on_submit": 0,
|
"fieldtype": "Select",
|
||||||
"bold": 0,
|
"in_list_view": 1,
|
||||||
"collapsible": 0,
|
"label": "Hide Currency Symbol",
|
||||||
"columns": 0,
|
"options": "\nNo\nYes"
|
||||||
"default": "INR",
|
},
|
||||||
"fieldname": "default_currency",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 1,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Default Currency",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Currency",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
"description": "If disable, 'Rounded Total' field will not be visible in any transaction",
|
||||||
"allow_on_submit": 0,
|
"fieldname": "disable_rounded_total",
|
||||||
"bold": 0,
|
"fieldtype": "Check",
|
||||||
"collapsible": 0,
|
"in_list_view": 1,
|
||||||
"columns": 0,
|
"label": "Disable Rounded Total"
|
||||||
"description": "Do not show any symbol like $ etc next to currencies.",
|
},
|
||||||
"fieldname": "hide_currency_symbol",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Hide Currency Symbol",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "\nNo\nYes",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
"description": "If disable, 'In Words' field will not be visible in any transaction",
|
||||||
"allow_on_submit": 0,
|
"fieldname": "disable_in_words",
|
||||||
"bold": 0,
|
"fieldtype": "Check",
|
||||||
"collapsible": 0,
|
"in_list_view": 1,
|
||||||
"columns": 0,
|
"label": "Disable In Words"
|
||||||
"description": "If disable, 'Rounded Total' field will not be visible in any transaction",
|
|
||||||
"fieldname": "disable_rounded_total",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Disable Rounded Total",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "If disable, 'In Words' field will not be visible in any transaction",
|
|
||||||
"fieldname": "disable_in_words",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Disable In Words",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"icon": "fa fa-cog",
|
||||||
"hide_heading": 0,
|
"idx": 1,
|
||||||
"hide_toolbar": 0,
|
"in_create": 1,
|
||||||
"icon": "fa fa-cog",
|
"issingle": 1,
|
||||||
"idx": 1,
|
"links": [],
|
||||||
"image_view": 0,
|
"modified": "2023-07-01 19:45:00.323953",
|
||||||
"in_create": 1,
|
"modified_by": "Administrator",
|
||||||
"is_submittable": 0,
|
"module": "Setup",
|
||||||
"issingle": 1,
|
"name": "Global Defaults",
|
||||||
"istable": 0,
|
"owner": "Administrator",
|
||||||
"max_attachments": 0,
|
|
||||||
"menu_index": 0,
|
|
||||||
"modified": "2018-10-15 03:08:19.886212",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Setup",
|
|
||||||
"name": "Global Defaults",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
"create": 1,
|
||||||
"cancel": 0,
|
"read": 1,
|
||||||
"create": 1,
|
"role": "System Manager",
|
||||||
"delete": 0,
|
"share": 1,
|
||||||
"email": 0,
|
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 0,
|
|
||||||
"read": 1,
|
|
||||||
"report": 0,
|
|
||||||
"role": "System Manager",
|
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
"read_only": 1,
|
||||||
"read_only": 1,
|
"sort_field": "modified",
|
||||||
"read_only_onload": 0,
|
"sort_order": "DESC",
|
||||||
"show_name_in_global_search": 0,
|
"states": []
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 0,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,6 @@ from frappe.utils import cint
|
|||||||
|
|
||||||
keydict = {
|
keydict = {
|
||||||
# "key in defaults": "key in Global Defaults"
|
# "key in defaults": "key in Global Defaults"
|
||||||
"fiscal_year": "current_fiscal_year",
|
|
||||||
"company": "default_company",
|
"company": "default_company",
|
||||||
"currency": "default_currency",
|
"currency": "default_currency",
|
||||||
"country": "country",
|
"country": "country",
|
||||||
@@ -29,22 +28,6 @@ class GlobalDefaults(Document):
|
|||||||
for key in keydict:
|
for key in keydict:
|
||||||
frappe.db.set_default(key, self.get(keydict[key], ""))
|
frappe.db.set_default(key, self.get(keydict[key], ""))
|
||||||
|
|
||||||
# update year start date and year end date from fiscal_year
|
|
||||||
if self.current_fiscal_year:
|
|
||||||
if fiscal_year := frappe.get_all(
|
|
||||||
"Fiscal Year",
|
|
||||||
filters={"name": self.current_fiscal_year},
|
|
||||||
fields=["year_start_date", "year_end_date"],
|
|
||||||
limit=1,
|
|
||||||
order_by=None,
|
|
||||||
):
|
|
||||||
ysd = fiscal_year[0].year_start_date or ""
|
|
||||||
yed = fiscal_year[0].year_end_date or ""
|
|
||||||
|
|
||||||
if ysd and yed:
|
|
||||||
frappe.db.set_default("year_start_date", ysd.strftime("%Y-%m-%d"))
|
|
||||||
frappe.db.set_default("year_end_date", yed.strftime("%Y-%m-%d"))
|
|
||||||
|
|
||||||
# enable default currency
|
# enable default currency
|
||||||
if self.default_currency:
|
if self.default_currency:
|
||||||
frappe.db.set_value("Currency", self.default_currency, "enabled", 1)
|
frappe.db.set_value("Currency", self.default_currency, "enabled", 1)
|
||||||
|
|||||||
@@ -6,13 +6,41 @@ frappe.ui.form.on("Holiday List", {
|
|||||||
if (frm.doc.holidays) {
|
if (frm.doc.holidays) {
|
||||||
frm.set_value("total_holidays", frm.doc.holidays.length);
|
frm.set_value("total_holidays", frm.doc.holidays.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frm.call("get_supported_countries").then(r => {
|
||||||
|
frm.subdivisions_by_country = r.message.subdivisions_by_country;
|
||||||
|
frm.fields_dict.country.set_data(
|
||||||
|
r.message.countries.sort((a, b) => a.label.localeCompare(b.label))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (frm.doc.country) {
|
||||||
|
frm.trigger("set_subdivisions");
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
from_date: function(frm) {
|
from_date: function(frm) {
|
||||||
if (frm.doc.from_date && !frm.doc.to_date) {
|
if (frm.doc.from_date && !frm.doc.to_date) {
|
||||||
var a_year_from_start = frappe.datetime.add_months(frm.doc.from_date, 12);
|
var a_year_from_start = frappe.datetime.add_months(frm.doc.from_date, 12);
|
||||||
frm.set_value("to_date", frappe.datetime.add_days(a_year_from_start, -1));
|
frm.set_value("to_date", frappe.datetime.add_days(a_year_from_start, -1));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
country: function(frm) {
|
||||||
|
frm.set_value("subdivision", "");
|
||||||
|
|
||||||
|
if (frm.doc.country) {
|
||||||
|
frm.trigger("set_subdivisions");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set_subdivisions: function(frm) {
|
||||||
|
const subdivisions = [...frm.subdivisions_by_country[frm.doc.country]];
|
||||||
|
if (subdivisions && subdivisions.length > 0) {
|
||||||
|
frm.fields_dict.subdivision.set_data(subdivisions);
|
||||||
|
frm.set_df_property("subdivision", "hidden", 0);
|
||||||
|
} else {
|
||||||
|
frm.fields_dict.subdivision.set_data([]);
|
||||||
|
frm.set_df_property("subdivision", "hidden", 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.tour["Holiday List"] = [
|
frappe.tour["Holiday List"] = [
|
||||||
|
|||||||
@@ -1,480 +1,166 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "field:holiday_list_name",
|
"autoname": "field:holiday_list_name",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2013-01-10 16:34:14",
|
"creation": "2013-01-10 16:34:14",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Setup",
|
"document_type": "Setup",
|
||||||
"editable_grid": 0,
|
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"holiday_list_name",
|
||||||
|
"from_date",
|
||||||
|
"to_date",
|
||||||
|
"column_break_4",
|
||||||
|
"total_holidays",
|
||||||
|
"add_weekly_holidays",
|
||||||
|
"weekly_off",
|
||||||
|
"get_weekly_off_dates",
|
||||||
|
"add_local_holidays",
|
||||||
|
"country",
|
||||||
|
"subdivision",
|
||||||
|
"get_local_holidays",
|
||||||
|
"holidays_section",
|
||||||
|
"holidays",
|
||||||
|
"clear_table",
|
||||||
|
"section_break_9",
|
||||||
|
"color"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "holiday_list_name",
|
"fieldname": "holiday_list_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Holiday List Name",
|
"label": "Holiday List Name",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "holiday_list_name",
|
"oldfieldname": "holiday_list_name",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 1
|
"unique": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "from_date",
|
"fieldname": "from_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "From Date",
|
"label": "From Date",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "to_date",
|
"fieldname": "to_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "To Date",
|
"label": "To Date",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_4",
|
"fieldname": "column_break_4",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "total_holidays",
|
"fieldname": "total_holidays",
|
||||||
"fieldtype": "Int",
|
"fieldtype": "Int",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Total Holidays",
|
"label": "Total Holidays",
|
||||||
"length": 0,
|
"read_only": 1
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 1,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
"columns": 0,
|
"depends_on": "eval: doc.from_date && doc.to_date",
|
||||||
"fieldname": "add_weekly_holidays",
|
"fieldname": "add_weekly_holidays",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Add Weekly Holidays"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Add Weekly Holidays",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "weekly_off",
|
"fieldname": "weekly_off",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Weekly Off",
|
"label": "Weekly Off",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday",
|
"options": "\nSunday\nMonday\nTuesday\nWednesday\nThursday\nFriday\nSaturday",
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"report_hide": 1
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 1,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "get_weekly_off_dates",
|
"fieldname": "get_weekly_off_dates",
|
||||||
"fieldtype": "Button",
|
"fieldtype": "Button",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Add to Holidays",
|
"label": "Add to Holidays",
|
||||||
"length": 0,
|
"options": "get_weekly_off_dates"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "get_weekly_off_dates",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "holidays_section",
|
"fieldname": "holidays_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hidden": 0,
|
"label": "Holidays"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Holidays",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "holidays",
|
"fieldname": "holidays",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Holidays",
|
"label": "Holidays",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"oldfieldname": "holiday_list_details",
|
"oldfieldname": "holiday_list_details",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "Holiday",
|
"options": "Holiday"
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "clear_table",
|
"fieldname": "clear_table",
|
||||||
"fieldtype": "Button",
|
"fieldtype": "Button",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Clear Table",
|
"label": "Clear Table",
|
||||||
"length": 0,
|
"options": "clear_table"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "clear_table",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "section_break_9",
|
"fieldname": "section_break_9",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break"
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "color",
|
"fieldname": "color",
|
||||||
"fieldtype": "Color",
|
"fieldtype": "Color",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Color",
|
"label": "Color",
|
||||||
"length": 0,
|
"print_hide": 1
|
||||||
"no_copy": 0,
|
},
|
||||||
"permlevel": 0,
|
{
|
||||||
"precision": "",
|
"fieldname": "country",
|
||||||
"print_hide": 1,
|
"fieldtype": "Autocomplete",
|
||||||
"print_hide_if_no_value": 0,
|
"label": "Country"
|
||||||
"read_only": 0,
|
},
|
||||||
"remember_last_selected_value": 0,
|
{
|
||||||
"report_hide": 0,
|
"depends_on": "country",
|
||||||
"reqd": 0,
|
"fieldname": "subdivision",
|
||||||
"search_index": 0,
|
"fieldtype": "Autocomplete",
|
||||||
"set_only_once": 0,
|
"label": "Subdivision"
|
||||||
"translatable": 0,
|
},
|
||||||
"unique": 0
|
{
|
||||||
|
"collapsible": 1,
|
||||||
|
"depends_on": "eval: doc.from_date && doc.to_date",
|
||||||
|
"fieldname": "add_local_holidays",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Add Local Holidays"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "get_local_holidays",
|
||||||
|
"fieldtype": "Button",
|
||||||
|
"label": "Add to Holidays",
|
||||||
|
"options": "get_local_holidays"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"icon": "fa fa-calendar",
|
"icon": "fa fa-calendar",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
"links": [],
|
||||||
"in_create": 0,
|
"modified": "2023-07-14 13:28:53.156421",
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2018-07-03 07:22:46.474096",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Holiday List",
|
"name": "Holiday List",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "HR Manager",
|
"role": "HR Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"states": []
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,15 @@
|
|||||||
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from babel import Locale
|
||||||
from frappe import _, throw
|
from frappe import _, throw
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cint, formatdate, getdate, today
|
from frappe.utils import formatdate, getdate, today
|
||||||
|
from holidays import country_holidays
|
||||||
|
from holidays.utils import list_supported_countries
|
||||||
|
|
||||||
|
|
||||||
class OverlapError(frappe.ValidationError):
|
class OverlapError(frappe.ValidationError):
|
||||||
@@ -21,25 +25,66 @@ class HolidayList(Document):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_weekly_off_dates(self):
|
def get_weekly_off_dates(self):
|
||||||
self.validate_values()
|
|
||||||
date_list = self.get_weekly_off_date_list(self.from_date, self.to_date)
|
|
||||||
last_idx = max(
|
|
||||||
[cint(d.idx) for d in self.get("holidays")]
|
|
||||||
or [
|
|
||||||
0,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
for i, d in enumerate(date_list):
|
|
||||||
ch = self.append("holidays", {})
|
|
||||||
ch.description = _(self.weekly_off)
|
|
||||||
ch.holiday_date = d
|
|
||||||
ch.weekly_off = 1
|
|
||||||
ch.idx = last_idx + i + 1
|
|
||||||
|
|
||||||
def validate_values(self):
|
|
||||||
if not self.weekly_off:
|
if not self.weekly_off:
|
||||||
throw(_("Please select weekly off day"))
|
throw(_("Please select weekly off day"))
|
||||||
|
|
||||||
|
existing_holidays = self.get_holidays()
|
||||||
|
|
||||||
|
for d in self.get_weekly_off_date_list(self.from_date, self.to_date):
|
||||||
|
if d in existing_holidays:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.append("holidays", {"description": _(self.weekly_off), "holiday_date": d, "weekly_off": 1})
|
||||||
|
|
||||||
|
self.sort_holidays()
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_supported_countries(self):
|
||||||
|
subdivisions_by_country = list_supported_countries()
|
||||||
|
countries = [
|
||||||
|
{"value": country, "label": local_country_name(country)}
|
||||||
|
for country in subdivisions_by_country.keys()
|
||||||
|
]
|
||||||
|
return {
|
||||||
|
"countries": countries,
|
||||||
|
"subdivisions_by_country": subdivisions_by_country,
|
||||||
|
}
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_local_holidays(self):
|
||||||
|
if not self.country:
|
||||||
|
throw(_("Please select a country"))
|
||||||
|
|
||||||
|
existing_holidays = self.get_holidays()
|
||||||
|
from_date = getdate(self.from_date)
|
||||||
|
to_date = getdate(self.to_date)
|
||||||
|
|
||||||
|
for holiday_date, holiday_name in country_holidays(
|
||||||
|
self.country,
|
||||||
|
subdiv=self.subdivision,
|
||||||
|
years=[from_date.year, to_date.year],
|
||||||
|
language=frappe.local.lang,
|
||||||
|
).items():
|
||||||
|
if holiday_date in existing_holidays:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if holiday_date < from_date or holiday_date > to_date:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.append(
|
||||||
|
"holidays", {"description": holiday_name, "holiday_date": holiday_date, "weekly_off": 0}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.sort_holidays()
|
||||||
|
|
||||||
|
def sort_holidays(self):
|
||||||
|
self.holidays.sort(key=lambda x: getdate(x.holiday_date))
|
||||||
|
for i in range(len(self.holidays)):
|
||||||
|
self.holidays[i].idx = i + 1
|
||||||
|
|
||||||
|
def get_holidays(self) -> list[date]:
|
||||||
|
return [getdate(holiday.holiday_date) for holiday in self.holidays]
|
||||||
|
|
||||||
def validate_days(self):
|
def validate_days(self):
|
||||||
if getdate(self.from_date) > getdate(self.to_date):
|
if getdate(self.from_date) > getdate(self.to_date):
|
||||||
throw(_("To Date cannot be before From Date"))
|
throw(_("To Date cannot be before From Date"))
|
||||||
@@ -120,3 +165,8 @@ def is_holiday(holiday_list, date=None):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def local_country_name(country_code: str) -> str:
|
||||||
|
"""Return the localized country name for the given country code."""
|
||||||
|
return Locale.parse(frappe.local.lang).territories.get(country_code, country_code)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from datetime import timedelta
|
from datetime import date, timedelta
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
@@ -23,6 +23,41 @@ class TestHolidayList(unittest.TestCase):
|
|||||||
fetched_holiday_list = frappe.get_value("Holiday List", holiday_list.name)
|
fetched_holiday_list = frappe.get_value("Holiday List", holiday_list.name)
|
||||||
self.assertEqual(holiday_list.name, fetched_holiday_list)
|
self.assertEqual(holiday_list.name, fetched_holiday_list)
|
||||||
|
|
||||||
|
def test_weekly_off(self):
|
||||||
|
holiday_list = frappe.new_doc("Holiday List")
|
||||||
|
holiday_list.from_date = "2023-01-01"
|
||||||
|
holiday_list.to_date = "2023-02-28"
|
||||||
|
holiday_list.weekly_off = "Sunday"
|
||||||
|
holiday_list.get_weekly_off_dates()
|
||||||
|
|
||||||
|
holidays = [holiday.holiday_date for holiday in holiday_list.holidays]
|
||||||
|
|
||||||
|
self.assertNotIn(date(2022, 12, 25), holidays)
|
||||||
|
self.assertIn(date(2023, 1, 1), holidays)
|
||||||
|
self.assertIn(date(2023, 1, 8), holidays)
|
||||||
|
self.assertIn(date(2023, 1, 15), holidays)
|
||||||
|
self.assertIn(date(2023, 1, 22), holidays)
|
||||||
|
self.assertIn(date(2023, 1, 29), holidays)
|
||||||
|
self.assertIn(date(2023, 2, 5), holidays)
|
||||||
|
self.assertIn(date(2023, 2, 12), holidays)
|
||||||
|
self.assertIn(date(2023, 2, 19), holidays)
|
||||||
|
self.assertIn(date(2023, 2, 26), holidays)
|
||||||
|
self.assertNotIn(date(2023, 3, 5), holidays)
|
||||||
|
|
||||||
|
def test_local_holidays(self):
|
||||||
|
holiday_list = frappe.new_doc("Holiday List")
|
||||||
|
holiday_list.from_date = "2023-04-01"
|
||||||
|
holiday_list.to_date = "2023-04-30"
|
||||||
|
holiday_list.country = "DE"
|
||||||
|
holiday_list.subdivision = "SN"
|
||||||
|
holiday_list.get_local_holidays()
|
||||||
|
|
||||||
|
holidays = [holiday.holiday_date for holiday in holiday_list.holidays]
|
||||||
|
self.assertNotIn(date(2023, 1, 1), holidays)
|
||||||
|
self.assertIn(date(2023, 4, 7), holidays)
|
||||||
|
self.assertIn(date(2023, 4, 10), holidays)
|
||||||
|
self.assertNotIn(date(2023, 5, 1), holidays)
|
||||||
|
|
||||||
|
|
||||||
def make_holiday_list(
|
def make_holiday_list(
|
||||||
name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None
|
name, from_date=getdate() - timedelta(days=10), to_date=getdate(), holiday_dates=None
|
||||||
|
|||||||
@@ -462,11 +462,9 @@ def install_defaults(args=None): # nosemgrep
|
|||||||
|
|
||||||
def set_global_defaults(args):
|
def set_global_defaults(args):
|
||||||
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
|
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
|
||||||
current_fiscal_year = frappe.get_all("Fiscal Year")[0]
|
|
||||||
|
|
||||||
global_defaults.update(
|
global_defaults.update(
|
||||||
{
|
{
|
||||||
"current_fiscal_year": current_fiscal_year.name,
|
|
||||||
"default_currency": args.get("currency"),
|
"default_currency": args.get("currency"),
|
||||||
"default_company": args.get("company_name"),
|
"default_company": args.get("company_name"),
|
||||||
"country": args.get("country"),
|
"country": args.get("country"),
|
||||||
|
|||||||
@@ -194,7 +194,8 @@
|
|||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "disabled",
|
"fieldname": "disabled",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Disabled"
|
"label": "Disabled",
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@@ -911,7 +912,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"make_attachments_public": 1,
|
"make_attachments_public": 1,
|
||||||
"modified": "2023-02-14 04:48:26.343620",
|
"modified": "2023-07-14 17:18:18.658942",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item",
|
"name": "Item",
|
||||||
|
|||||||
@@ -1,370 +1,90 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
"creation": "2015-05-19 05:12:30.344797",
|
||||||
"allow_guest_to_view": 0,
|
"doctype": "DocType",
|
||||||
"allow_import": 0,
|
"document_type": "Other",
|
||||||
"allow_rename": 0,
|
"editable_grid": 1,
|
||||||
"autoname": "",
|
"engine": "InnoDB",
|
||||||
"beta": 0,
|
"field_order": [
|
||||||
"creation": "2015-05-19 05:12:30.344797",
|
"variant_of",
|
||||||
"custom": 0,
|
"attribute",
|
||||||
"docstatus": 0,
|
"column_break_2",
|
||||||
"doctype": "DocType",
|
"attribute_value",
|
||||||
"document_type": "Other",
|
"numeric_values",
|
||||||
"editable_grid": 1,
|
"section_break_4",
|
||||||
|
"from_range",
|
||||||
|
"increment",
|
||||||
|
"column_break_8",
|
||||||
|
"to_range"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "variant_of",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Link",
|
||||||
"allow_on_submit": 0,
|
"label": "Variant Of",
|
||||||
"bold": 0,
|
"options": "Item",
|
||||||
"collapsible": 0,
|
"search_index": 1
|
||||||
"columns": 0,
|
},
|
||||||
"fieldname": "variant_of",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Variant Of",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Item",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "attribute",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Link",
|
||||||
"allow_on_submit": 0,
|
"in_list_view": 1,
|
||||||
"bold": 0,
|
"label": "Attribute",
|
||||||
"collapsible": 0,
|
"options": "Item Attribute",
|
||||||
"columns": 0,
|
"reqd": 1,
|
||||||
"fieldname": "attribute",
|
"search_index": 1
|
||||||
"fieldtype": "Link",
|
},
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Attribute",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Item Attribute",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "column_break_2",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Column Break"
|
||||||
"allow_on_submit": 0,
|
},
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_2",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "attribute_value",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Data",
|
||||||
"allow_on_submit": 0,
|
"in_list_view": 1,
|
||||||
"bold": 0,
|
"label": "Attribute Value"
|
||||||
"collapsible": 0,
|
},
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "attribute_value",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Attribute Value",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "",
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
"depends_on": "has_variants",
|
||||||
"allow_on_submit": 0,
|
"fieldname": "numeric_values",
|
||||||
"bold": 0,
|
"fieldtype": "Check",
|
||||||
"collapsible": 0,
|
"label": "Numeric Values"
|
||||||
"columns": 0,
|
},
|
||||||
"depends_on": "has_variants",
|
|
||||||
"fieldname": "numeric_values",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Numeric Values",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"depends_on": "numeric_values",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldname": "section_break_4",
|
||||||
"allow_on_submit": 0,
|
"fieldtype": "Section Break"
|
||||||
"bold": 0,
|
},
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "numeric_values",
|
|
||||||
"fieldname": "section_break_4",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "from_range",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Float",
|
||||||
"allow_on_submit": 0,
|
"label": "From Range"
|
||||||
"bold": 0,
|
},
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "from_range",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "From Range",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "increment",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Float",
|
||||||
"allow_on_submit": 0,
|
"label": "Increment"
|
||||||
"bold": 0,
|
},
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "increment",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Increment",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "column_break_8",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Column Break"
|
||||||
"allow_on_submit": 0,
|
},
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_8",
|
|
||||||
"fieldtype": "Column Break",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"fieldname": "to_range",
|
||||||
"allow_in_quick_entry": 0,
|
"fieldtype": "Float",
|
||||||
"allow_on_submit": 0,
|
"label": "To Range"
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "to_range",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "To Range",
|
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"precision": "",
|
|
||||||
"print_hide": 0,
|
|
||||||
"print_hide_if_no_value": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"remember_last_selected_value": 0,
|
|
||||||
"report_hide": 0,
|
|
||||||
"reqd": 0,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"istable": 1,
|
||||||
"hide_heading": 0,
|
"links": [],
|
||||||
"hide_toolbar": 0,
|
"modified": "2023-07-14 17:15:19.112119",
|
||||||
"icon": "",
|
"modified_by": "Administrator",
|
||||||
"idx": 0,
|
"module": "Stock",
|
||||||
"image_view": 0,
|
"name": "Item Variant Attribute",
|
||||||
"in_create": 0,
|
"owner": "Administrator",
|
||||||
"is_submittable": 0,
|
"permissions": [],
|
||||||
"issingle": 0,
|
"sort_field": "modified",
|
||||||
"istable": 1,
|
"sort_order": "DESC",
|
||||||
"max_attachments": 0,
|
"states": []
|
||||||
"modified": "2019-01-03 15:36:59.129006",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Stock",
|
|
||||||
"name": "Item Variant Attribute",
|
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [],
|
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"track_changes": 0,
|
|
||||||
"track_seen": 0,
|
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -314,6 +314,30 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin):
|
|||||||
self.assertEqual(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Inactive")
|
self.assertEqual(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Inactive")
|
||||||
self.assertEqual(frappe.db.exists("Batch", batch_no), None)
|
self.assertEqual(frappe.db.exists("Batch", batch_no), None)
|
||||||
|
|
||||||
|
def test_stock_reco_balance_qty_for_serial_and_batch_item(self):
|
||||||
|
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||||
|
|
||||||
|
item = create_item("_TestBatchSerialItemReco_1")
|
||||||
|
item.has_batch_no = 1
|
||||||
|
item.create_new_batch = 1
|
||||||
|
item.has_serial_no = 1
|
||||||
|
item.batch_number_series = "TBS-BATCH1-.##"
|
||||||
|
item.serial_no_series = "TBS1-.####"
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
warehouse = "_Test Warehouse for Stock Reco2"
|
||||||
|
warehouse = create_warehouse(warehouse)
|
||||||
|
|
||||||
|
make_stock_entry(item_code=item.name, target=warehouse, qty=10, basic_rate=100)
|
||||||
|
|
||||||
|
sr = create_stock_reconciliation(item_code=item.name, warehouse=warehouse, qty=10, rate=200)
|
||||||
|
|
||||||
|
qty_after_transaction = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry", {"voucher_no": sr.name, "is_cancelled": 0}, "qty_after_transaction"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(qty_after_transaction, 20)
|
||||||
|
|
||||||
def test_stock_reco_for_serial_and_batch_item_with_future_dependent_entry(self):
|
def test_stock_reco_for_serial_and_batch_item_with_future_dependent_entry(self):
|
||||||
"""
|
"""
|
||||||
Behaviour: 1) Create Stock Reconciliation, which will be the origin document
|
Behaviour: 1) Create Stock Reconciliation, which will be the origin document
|
||||||
|
|||||||
@@ -9,13 +9,27 @@ frappe.query_reports["Batch Item Expiry Status"] = {
|
|||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"width": "80",
|
"width": "80",
|
||||||
"default": frappe.sys_defaults.year_start_date,
|
"default": frappe.sys_defaults.year_start_date,
|
||||||
|
"reqd": 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"to_date",
|
"fieldname":"to_date",
|
||||||
"label": __("To Date"),
|
"label": __("To Date"),
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"width": "80",
|
"width": "80",
|
||||||
"default": frappe.datetime.get_today()
|
"default": frappe.datetime.get_today(),
|
||||||
|
"reqd": 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"item",
|
||||||
|
"label": __("Item"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Item",
|
||||||
|
"width": "100",
|
||||||
|
"get_query": function () {
|
||||||
|
return {
|
||||||
|
filters: {"has_batch_no": 1}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,113 +4,86 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.query_builder.functions import IfNull
|
from frappe.query_builder.functions import Date
|
||||||
from frappe.utils import cint, getdate
|
|
||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
if not filters:
|
validate_filters(filters)
|
||||||
filters = {}
|
|
||||||
|
|
||||||
float_precision = cint(frappe.db.get_default("float_precision")) or 3
|
columns = get_columns()
|
||||||
|
data = get_data(filters)
|
||||||
columns = get_columns(filters)
|
|
||||||
item_map = get_item_details(filters)
|
|
||||||
iwb_map = get_item_warehouse_batch_map(filters, float_precision)
|
|
||||||
|
|
||||||
data = []
|
|
||||||
for item in sorted(iwb_map):
|
|
||||||
for wh in sorted(iwb_map[item]):
|
|
||||||
for batch in sorted(iwb_map[item][wh]):
|
|
||||||
qty_dict = iwb_map[item][wh][batch]
|
|
||||||
|
|
||||||
data.append(
|
|
||||||
[
|
|
||||||
item,
|
|
||||||
item_map[item]["item_name"],
|
|
||||||
item_map[item]["description"],
|
|
||||||
wh,
|
|
||||||
batch,
|
|
||||||
frappe.db.get_value("Batch", batch, "expiry_date"),
|
|
||||||
qty_dict.expiry_status,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
|
|
||||||
def get_columns(filters):
|
def validate_filters(filters):
|
||||||
"""return columns based on filters"""
|
if not filters:
|
||||||
|
frappe.throw(_("Please select the required filters"))
|
||||||
|
|
||||||
columns = (
|
|
||||||
[_("Item") + ":Link/Item:100"]
|
|
||||||
+ [_("Item Name") + "::150"]
|
|
||||||
+ [_("Description") + "::150"]
|
|
||||||
+ [_("Warehouse") + ":Link/Warehouse:100"]
|
|
||||||
+ [_("Batch") + ":Link/Batch:100"]
|
|
||||||
+ [_("Expires On") + ":Date:90"]
|
|
||||||
+ [_("Expiry (In Days)") + ":Int:120"]
|
|
||||||
)
|
|
||||||
|
|
||||||
return columns
|
|
||||||
|
|
||||||
|
|
||||||
def get_stock_ledger_entries(filters):
|
|
||||||
if not filters.get("from_date"):
|
if not filters.get("from_date"):
|
||||||
frappe.throw(_("'From Date' is required"))
|
frappe.throw(_("'From Date' is required"))
|
||||||
|
|
||||||
if not filters.get("to_date"):
|
if not filters.get("to_date"):
|
||||||
frappe.throw(_("'To Date' is required"))
|
frappe.throw(_("'To Date' is required"))
|
||||||
|
|
||||||
sle = frappe.qb.DocType("Stock Ledger Entry")
|
|
||||||
query = (
|
def get_columns():
|
||||||
frappe.qb.from_(sle)
|
return (
|
||||||
.select(sle.item_code, sle.batch_no, sle.warehouse, sle.posting_date, sle.actual_qty)
|
[_("Item") + ":Link/Item:150"]
|
||||||
.where(
|
+ [_("Item Name") + "::150"]
|
||||||
(sle.is_cancelled == 0)
|
+ [_("Batch") + ":Link/Batch:150"]
|
||||||
& (sle.docstatus < 2)
|
+ [_("Stock UOM") + ":Link/UOM:100"]
|
||||||
& (IfNull(sle.batch_no, "") != "")
|
+ [_("Quantity") + ":Float:100"]
|
||||||
& (sle.posting_date <= filters["to_date"])
|
+ [_("Expires On") + ":Date:100"]
|
||||||
)
|
+ [_("Expiry (In Days)") + ":Int:130"]
|
||||||
.orderby(sle.item_code, sle.warehouse)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return query.run(as_dict=True)
|
|
||||||
|
|
||||||
|
def get_data(filters):
|
||||||
|
data = []
|
||||||
|
|
||||||
def get_item_warehouse_batch_map(filters, float_precision):
|
for batch in get_batch_details(filters):
|
||||||
sle = get_stock_ledger_entries(filters)
|
data.append(
|
||||||
iwb_map = {}
|
[
|
||||||
|
batch.item,
|
||||||
from_date = getdate(filters["from_date"])
|
batch.item_name,
|
||||||
to_date = getdate(filters["to_date"])
|
batch.name,
|
||||||
|
batch.stock_uom,
|
||||||
for d in sle:
|
batch.batch_qty,
|
||||||
iwb_map.setdefault(d.item_code, {}).setdefault(d.warehouse, {}).setdefault(
|
batch.expiry_date,
|
||||||
d.batch_no, frappe._dict({"expires_on": None, "expiry_status": None})
|
max((batch.expiry_date - frappe.utils.datetime.date.today()).days, 0)
|
||||||
|
if batch.expiry_date
|
||||||
|
else None,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
qty_dict = iwb_map[d.item_code][d.warehouse][d.batch_no]
|
return data
|
||||||
|
|
||||||
expiry_date_unicode = frappe.db.get_value("Batch", d.batch_no, "expiry_date")
|
|
||||||
qty_dict.expires_on = expiry_date_unicode
|
|
||||||
|
|
||||||
exp_date = frappe.utils.data.getdate(expiry_date_unicode)
|
|
||||||
qty_dict.expires_on = exp_date
|
|
||||||
|
|
||||||
expires_in_days = (exp_date - frappe.utils.datetime.date.today()).days
|
|
||||||
|
|
||||||
if expires_in_days > 0:
|
|
||||||
qty_dict.expiry_status = expires_in_days
|
|
||||||
else:
|
|
||||||
qty_dict.expiry_status = 0
|
|
||||||
|
|
||||||
return iwb_map
|
|
||||||
|
|
||||||
|
|
||||||
def get_item_details(filters):
|
def get_batch_details(filters):
|
||||||
item_map = {}
|
batch = frappe.qb.DocType("Batch")
|
||||||
for d in (frappe.qb.from_("Item").select("name", "item_name", "description")).run(as_dict=True):
|
query = (
|
||||||
item_map.setdefault(d.name, d)
|
frappe.qb.from_(batch)
|
||||||
|
.select(
|
||||||
|
batch.name,
|
||||||
|
batch.creation,
|
||||||
|
batch.expiry_date,
|
||||||
|
batch.item,
|
||||||
|
batch.item_name,
|
||||||
|
batch.stock_uom,
|
||||||
|
batch.batch_qty,
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
(batch.disabled == 0)
|
||||||
|
& (batch.batch_qty > 0)
|
||||||
|
& (
|
||||||
|
(Date(batch.creation) >= filters["from_date"]) & (Date(batch.creation) <= filters["to_date"])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.orderby(batch.creation)
|
||||||
|
)
|
||||||
|
|
||||||
return item_map
|
if filters.get("item"):
|
||||||
|
query = query.where(batch.item == filters["item"])
|
||||||
|
|
||||||
|
return query.run(as_dict=True)
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ class update_entries_after(object):
|
|||||||
if get_serial_nos(sle.serial_no):
|
if get_serial_nos(sle.serial_no):
|
||||||
self.get_serialized_values(sle)
|
self.get_serialized_values(sle)
|
||||||
self.wh_data.qty_after_transaction += flt(sle.actual_qty)
|
self.wh_data.qty_after_transaction += flt(sle.actual_qty)
|
||||||
if sle.voucher_type == "Stock Reconciliation":
|
if sle.voucher_type == "Stock Reconciliation" and not sle.batch_no:
|
||||||
self.wh_data.qty_after_transaction = sle.qty_after_transaction
|
self.wh_data.qty_after_transaction = sle.qty_after_transaction
|
||||||
|
|
||||||
self.wh_data.stock_value = flt(self.wh_data.qty_after_transaction) * flt(
|
self.wh_data.stock_value = flt(self.wh_data.qty_after_transaction) * flt(
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from frappe.utils import (
|
|||||||
time_diff_in_seconds,
|
time_diff_in_seconds,
|
||||||
to_timedelta,
|
to_timedelta,
|
||||||
)
|
)
|
||||||
|
from frappe.utils.caching import redis_cache
|
||||||
from frappe.utils.nestedset import get_ancestors_of
|
from frappe.utils.nestedset import get_ancestors_of
|
||||||
from frappe.utils.safe_exec import get_safe_globals
|
from frappe.utils.safe_exec import get_safe_globals
|
||||||
|
|
||||||
@@ -209,6 +210,10 @@ class ServiceLevelAgreement(Document):
|
|||||||
def on_update(self):
|
def on_update(self):
|
||||||
set_documents_with_active_service_level_agreement()
|
set_documents_with_active_service_level_agreement()
|
||||||
|
|
||||||
|
def clear_cache(self):
|
||||||
|
get_sla_doctypes.clear_cache()
|
||||||
|
return super().clear_cache()
|
||||||
|
|
||||||
def create_docfields(self, meta, service_level_agreement_fields):
|
def create_docfields(self, meta, service_level_agreement_fields):
|
||||||
last_index = len(meta.fields)
|
last_index = len(meta.fields)
|
||||||
|
|
||||||
@@ -990,6 +995,7 @@ def get_user_time(user, to_string=False):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
@redis_cache()
|
||||||
def get_sla_doctypes():
|
def get_sla_doctypes():
|
||||||
doctypes = []
|
doctypes = []
|
||||||
data = frappe.get_all("Service Level Agreement", {"enabled": 1}, ["document_type"], distinct=1)
|
data = frappe.get_all("Service Level Agreement", {"enabled": 1}, ["document_type"], distinct=1)
|
||||||
@@ -998,3 +1004,7 @@ def get_sla_doctypes():
|
|||||||
doctypes.append(entry.document_type)
|
doctypes.append(entry.document_type)
|
||||||
|
|
||||||
return doctypes
|
return doctypes
|
||||||
|
|
||||||
|
|
||||||
|
def add_sla_doctypes(bootinfo):
|
||||||
|
bootinfo.service_level_agreement_doctypes = get_sla_doctypes()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
{% for item, taxes in itemised_tax.items() %}
|
{% for item, taxes in itemised_tax.items() %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ item }}</td>
|
<td>{{ item }}</td>
|
||||||
<td class='text-right'>
|
<td class="text-right">
|
||||||
{% if doc.get('is_return') %}
|
{% if doc.get('is_return') %}
|
||||||
{{ frappe.utils.fmt_money((itemised_taxable_amount.get(item, 0))|abs, None, doc.currency) }}
|
{{ frappe.utils.fmt_money((itemised_taxable_amount.get(item, 0))|abs, None, doc.currency) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
{% for tax_account in tax_accounts %}
|
{% for tax_account in tax_accounts %}
|
||||||
{% set tax_details = taxes.get(tax_account) %}
|
{% set tax_details = taxes.get(tax_account) %}
|
||||||
{% if tax_details %}
|
{% if tax_details %}
|
||||||
<td class='text-right'>
|
<td class="text-right">
|
||||||
{% if tax_details.tax_rate or not tax_details.tax_amount %}
|
{% if tax_details.tax_rate or not tax_details.tax_amount %}
|
||||||
({{ tax_details.tax_rate }}%)
|
({{ tax_details.tax_rate }}%)
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1221,7 +1221,7 @@ High Sensitivity,Hohe Empfindlichkeit,
|
|||||||
Hold,Anhalten,
|
Hold,Anhalten,
|
||||||
Hold Invoice,Rechnung zurückhalten,
|
Hold Invoice,Rechnung zurückhalten,
|
||||||
Holiday,Urlaub,
|
Holiday,Urlaub,
|
||||||
Holiday List,Urlaubsübersicht,
|
Holiday List,Feiertagsliste,
|
||||||
Hotel Rooms of type {0} are unavailable on {1},Hotelzimmer vom Typ {0} sind auf {1} nicht verfügbar,
|
Hotel Rooms of type {0} are unavailable on {1},Hotelzimmer vom Typ {0} sind auf {1} nicht verfügbar,
|
||||||
Hotels,Hotels,
|
Hotels,Hotels,
|
||||||
Hourly,Stündlich,
|
Hourly,Stündlich,
|
||||||
@@ -3330,7 +3330,7 @@ Workflow,Workflow,
|
|||||||
Working,In Bearbeitung,
|
Working,In Bearbeitung,
|
||||||
Working Hours,Arbeitszeit,
|
Working Hours,Arbeitszeit,
|
||||||
Workstation,Arbeitsplatz,
|
Workstation,Arbeitsplatz,
|
||||||
Workstation is closed on the following dates as per Holiday List: {0},Arbeitsplatz ist an folgenden Tagen gemäß der Urlaubsliste geschlossen: {0},
|
Workstation is closed on the following dates as per Holiday List: {0},Arbeitsplatz ist an folgenden Tagen gemäß der Feiertagsliste geschlossen: {0},
|
||||||
Wrapping up,Aufwickeln,
|
Wrapping up,Aufwickeln,
|
||||||
Wrong Password,Falsches Passwort,
|
Wrong Password,Falsches Passwort,
|
||||||
Year start date or end date is overlapping with {0}. To avoid please set company,"Jahresbeginn oder Enddatum überlappt mit {0}. Bitte ein Unternehmen wählen, um dies zu verhindern",
|
Year start date or end date is overlapping with {0}. To avoid please set company,"Jahresbeginn oder Enddatum überlappt mit {0}. Bitte ein Unternehmen wählen, um dies zu verhindern",
|
||||||
@@ -3599,6 +3599,7 @@ Activity,Aktivität,
|
|||||||
Add / Manage Email Accounts.,Hinzufügen/Verwalten von E-Mail-Konten,
|
Add / Manage Email Accounts.,Hinzufügen/Verwalten von E-Mail-Konten,
|
||||||
Add Child,Unterpunkt hinzufügen,
|
Add Child,Unterpunkt hinzufügen,
|
||||||
Add Loan Security,Darlehenssicherheit hinzufügen,
|
Add Loan Security,Darlehenssicherheit hinzufügen,
|
||||||
|
Add Local Holidays,Lokale Feiertage hinzufügen,
|
||||||
Add Multiple,Mehrere hinzufügen,
|
Add Multiple,Mehrere hinzufügen,
|
||||||
Add Participants,Teilnehmer hinzufügen,
|
Add Participants,Teilnehmer hinzufügen,
|
||||||
Add to Featured Item,Zum empfohlenen Artikel hinzufügen,
|
Add to Featured Item,Zum empfohlenen Artikel hinzufügen,
|
||||||
@@ -4088,6 +4089,7 @@ Stock Ledger ID,Bestandsbuch-ID,
|
|||||||
Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.,Der Bestandswert ({0}) und der Kontostand ({1}) sind für das Konto {2} und die verknüpften Lager nicht synchron.,
|
Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.,Der Bestandswert ({0}) und der Kontostand ({1}) sind für das Konto {2} und die verknüpften Lager nicht synchron.,
|
||||||
Stores - {0},Stores - {0},
|
Stores - {0},Stores - {0},
|
||||||
Student with email {0} does not exist,Der Student mit der E-Mail-Adresse {0} existiert nicht,
|
Student with email {0} does not exist,Der Student mit der E-Mail-Adresse {0} existiert nicht,
|
||||||
|
Subdivision,Teilgebiet,
|
||||||
Submit Review,Bewertung abschicken,
|
Submit Review,Bewertung abschicken,
|
||||||
Submitted,Gebucht,
|
Submitted,Gebucht,
|
||||||
Supplier Addresses And Contacts,Lieferanten-Adressen und Kontaktdaten,
|
Supplier Addresses And Contacts,Lieferanten-Adressen und Kontaktdaten,
|
||||||
@@ -4236,6 +4238,7 @@ Mode Of Payment,Zahlungsart,
|
|||||||
No students Found,Keine Schüler gefunden,
|
No students Found,Keine Schüler gefunden,
|
||||||
Not in Stock,Nicht lagernd,
|
Not in Stock,Nicht lagernd,
|
||||||
Please select a Customer,Bitte wählen Sie einen Kunden aus,
|
Please select a Customer,Bitte wählen Sie einen Kunden aus,
|
||||||
|
Please select a country,Bitte wählen Sie ein Land aus,
|
||||||
Printed On,Gedruckt auf,
|
Printed On,Gedruckt auf,
|
||||||
Received From,Erhalten von,
|
Received From,Erhalten von,
|
||||||
Sales Person,Verkäufer,
|
Sales Person,Verkäufer,
|
||||||
@@ -6546,7 +6549,7 @@ Reports to,Vorgesetzter,
|
|||||||
Attendance and Leave Details,Anwesenheits- und Urlaubsdetails,
|
Attendance and Leave Details,Anwesenheits- und Urlaubsdetails,
|
||||||
Leave Policy,Urlaubsrichtlinie,
|
Leave Policy,Urlaubsrichtlinie,
|
||||||
Attendance Device ID (Biometric/RF tag ID),Anwesenheitsgeräte-ID (biometrische / RF-Tag-ID),
|
Attendance Device ID (Biometric/RF tag ID),Anwesenheitsgeräte-ID (biometrische / RF-Tag-ID),
|
||||||
Applicable Holiday List,Geltende Urlaubsliste,
|
Applicable Holiday List,Geltende Feiertagsliste,
|
||||||
Default Shift,Standardverschiebung,
|
Default Shift,Standardverschiebung,
|
||||||
Salary Details,Gehaltsdetails,
|
Salary Details,Gehaltsdetails,
|
||||||
Salary Mode,Gehaltsmodus,
|
Salary Mode,Gehaltsmodus,
|
||||||
@@ -6708,15 +6711,15 @@ More Details,Mehr Details,
|
|||||||
Expense Claim Account,Kostenabrechnung Konto,
|
Expense Claim Account,Kostenabrechnung Konto,
|
||||||
Expense Claim Advance,Auslagenvorschuss,
|
Expense Claim Advance,Auslagenvorschuss,
|
||||||
Unclaimed amount,Nicht beanspruchter Betrag,
|
Unclaimed amount,Nicht beanspruchter Betrag,
|
||||||
Expense Claim Detail,Aufwandsabrechnungsdetail,
|
Expense Claim Detail,Auslage,
|
||||||
Expense Date,Datum der Aufwendung,
|
Expense Date,Datum der Auslage,
|
||||||
Expense Claim Type,Art der Aufwandsabrechnung,
|
Expense Claim Type,Art der Auslagenabrechnung,
|
||||||
Holiday List Name,Urlaubslistenname,
|
Holiday List Name,Name der Feiertagsliste,
|
||||||
Total Holidays,Insgesamt Feiertage,
|
Total Holidays,Insgesamt freie Tage,
|
||||||
Add Weekly Holidays,Wöchentliche Feiertage hinzufügen,
|
Add Weekly Holidays,Wöchentlich freie Tage hinzufügen,
|
||||||
Weekly Off,Wöchentlich frei,
|
Weekly Off,Wöchentlich frei,
|
||||||
Add to Holidays,Zu Feiertagen hinzufügen,
|
Add to Holidays,Zu freien Tagen hinzufügen,
|
||||||
Holidays,Ferien,
|
Holidays,Arbeitsfreie Tage,
|
||||||
Clear Table,Tabelle leeren,
|
Clear Table,Tabelle leeren,
|
||||||
HR Settings,Einstellungen zum Modul Personalwesen,
|
HR Settings,Einstellungen zum Modul Personalwesen,
|
||||||
Employee Settings,Mitarbeitereinstellungen,
|
Employee Settings,Mitarbeitereinstellungen,
|
||||||
@@ -6826,7 +6829,7 @@ Transaction Name,Transaktionsname,
|
|||||||
Is Carry Forward,Ist Übertrag,
|
Is Carry Forward,Ist Übertrag,
|
||||||
Is Expired,Ist abgelaufen,
|
Is Expired,Ist abgelaufen,
|
||||||
Is Leave Without Pay,Ist unbezahlter Urlaub,
|
Is Leave Without Pay,Ist unbezahlter Urlaub,
|
||||||
Holiday List for Optional Leave,Urlaubsliste für optionalen Urlaub,
|
Holiday List for Optional Leave,Feiertagsliste für optionalen Urlaub,
|
||||||
Leave Allocations,Zuteilungen verlassen,
|
Leave Allocations,Zuteilungen verlassen,
|
||||||
Leave Policy Details,Urlaubsrichtliniendetails,
|
Leave Policy Details,Urlaubsrichtliniendetails,
|
||||||
Leave Policy Detail,Urlaubsrichtliniendetail,
|
Leave Policy Detail,Urlaubsrichtliniendetail,
|
||||||
@@ -7786,7 +7789,7 @@ Legal Entity / Subsidiary with a separate Chart of Accounts belonging to the Org
|
|||||||
Change Abbreviation,Abkürzung ändern,
|
Change Abbreviation,Abkürzung ändern,
|
||||||
Parent Company,Muttergesellschaft,
|
Parent Company,Muttergesellschaft,
|
||||||
Default Values,Standardwerte,
|
Default Values,Standardwerte,
|
||||||
Default Holiday List,Standard-Urlaubsliste,
|
Default Holiday List,Standard Feiertagsliste,
|
||||||
Default Selling Terms,Standardverkaufsbedingungen,
|
Default Selling Terms,Standardverkaufsbedingungen,
|
||||||
Default Buying Terms,Standard-Einkaufsbedingungen,
|
Default Buying Terms,Standard-Einkaufsbedingungen,
|
||||||
Create Chart Of Accounts Based On,"Kontenplan erstellen, basierend auf",
|
Create Chart Of Accounts Based On,"Kontenplan erstellen, basierend auf",
|
||||||
|
|||||||
|
Can't render this file because it is too large.
|
@@ -14,6 +14,7 @@ dependencies = [
|
|||||||
"Unidecode~=1.2.0",
|
"Unidecode~=1.2.0",
|
||||||
"redisearch~=2.1.0",
|
"redisearch~=2.1.0",
|
||||||
"rapidfuzz~=2.15.0",
|
"rapidfuzz~=2.15.0",
|
||||||
|
"holidays~=0.28",
|
||||||
|
|
||||||
# integration dependencies
|
# integration dependencies
|
||||||
"gocardless-pro~=1.22.0",
|
"gocardless-pro~=1.22.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user