Merge branch 'develop' into payments-based-dunning
This commit is contained in:
commit
1c1e7380e3
22
.github/workflows/initiate_release.yml
vendored
22
.github/workflows/initiate_release.yml
vendored
@ -9,7 +9,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
stable-release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@ -30,3 +30,23 @@ jobs:
|
|||||||
head: version-${{ matrix.version }}-hotfix
|
head: version-${{ matrix.version }}-hotfix
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
|
||||||
|
beta-release:
|
||||||
|
name: Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: POST /repos/{owner}/{repo}/pulls
|
||||||
|
owner: frappe
|
||||||
|
repo: erpnext
|
||||||
|
title: |-
|
||||||
|
"chore: release v15 beta"
|
||||||
|
body: "Automated beta release."
|
||||||
|
base: version-15-beta
|
||||||
|
head: develop
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||||
|
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 }}
|
@ -136,7 +136,7 @@ def convert_deferred_revenue_to_income(
|
|||||||
send_mail(deferred_process)
|
send_mail(deferred_process)
|
||||||
|
|
||||||
|
|
||||||
def get_booking_dates(doc, item, posting_date=None):
|
def get_booking_dates(doc, item, posting_date=None, prev_posting_date=None):
|
||||||
if not posting_date:
|
if not posting_date:
|
||||||
posting_date = add_days(today(), -1)
|
posting_date = add_days(today(), -1)
|
||||||
|
|
||||||
@ -146,6 +146,7 @@ def get_booking_dates(doc, item, posting_date=None):
|
|||||||
"deferred_revenue_account" if doc.doctype == "Sales Invoice" else "deferred_expense_account"
|
"deferred_revenue_account" if doc.doctype == "Sales Invoice" else "deferred_expense_account"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not prev_posting_date:
|
||||||
prev_gl_entry = frappe.db.sql(
|
prev_gl_entry = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select name, posting_date from `tabGL Entry` where company=%s and account=%s and
|
select name, posting_date from `tabGL Entry` where company=%s and account=%s and
|
||||||
@ -179,6 +180,8 @@ def get_booking_dates(doc, item, posting_date=None):
|
|||||||
else:
|
else:
|
||||||
start_date = item.service_start_date
|
start_date = item.service_start_date
|
||||||
|
|
||||||
|
else:
|
||||||
|
start_date = getdate(add_days(prev_posting_date, 1))
|
||||||
end_date = get_last_day(start_date)
|
end_date = get_last_day(start_date)
|
||||||
if end_date >= item.service_end_date:
|
if end_date >= item.service_end_date:
|
||||||
end_date = item.service_end_date
|
end_date = item.service_end_date
|
||||||
@ -341,9 +344,15 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
accounts_frozen_upto = frappe.get_cached_value("Accounts Settings", "None", "acc_frozen_upto")
|
accounts_frozen_upto = frappe.get_cached_value("Accounts Settings", "None", "acc_frozen_upto")
|
||||||
|
|
||||||
def _book_deferred_revenue_or_expense(
|
def _book_deferred_revenue_or_expense(
|
||||||
item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on
|
item,
|
||||||
|
via_journal_entry,
|
||||||
|
submit_journal_entry,
|
||||||
|
book_deferred_entries_based_on,
|
||||||
|
prev_posting_date=None,
|
||||||
):
|
):
|
||||||
start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date)
|
start_date, end_date, last_gl_entry = get_booking_dates(
|
||||||
|
doc, item, posting_date=posting_date, prev_posting_date=prev_posting_date
|
||||||
|
)
|
||||||
if not (start_date and end_date):
|
if not (start_date and end_date):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -377,9 +386,12 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
if not amount:
|
if not amount:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
gl_posting_date = end_date
|
||||||
|
prev_posting_date = None
|
||||||
# check if books nor frozen till endate:
|
# check if books nor frozen till endate:
|
||||||
if accounts_frozen_upto and getdate(end_date) <= getdate(accounts_frozen_upto):
|
if accounts_frozen_upto and getdate(end_date) <= getdate(accounts_frozen_upto):
|
||||||
end_date = get_last_day(add_days(accounts_frozen_upto, 1))
|
gl_posting_date = get_last_day(add_days(accounts_frozen_upto, 1))
|
||||||
|
prev_posting_date = end_date
|
||||||
|
|
||||||
if via_journal_entry:
|
if via_journal_entry:
|
||||||
book_revenue_via_journal_entry(
|
book_revenue_via_journal_entry(
|
||||||
@ -388,7 +400,7 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
debit_account,
|
debit_account,
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
end_date,
|
gl_posting_date,
|
||||||
project,
|
project,
|
||||||
account_currency,
|
account_currency,
|
||||||
item.cost_center,
|
item.cost_center,
|
||||||
@ -404,7 +416,7 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
against,
|
against,
|
||||||
amount,
|
amount,
|
||||||
base_amount,
|
base_amount,
|
||||||
end_date,
|
gl_posting_date,
|
||||||
project,
|
project,
|
||||||
account_currency,
|
account_currency,
|
||||||
item.cost_center,
|
item.cost_center,
|
||||||
@ -418,7 +430,11 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
|
|||||||
|
|
||||||
if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
|
if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
|
||||||
_book_deferred_revenue_or_expense(
|
_book_deferred_revenue_or_expense(
|
||||||
item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on
|
item,
|
||||||
|
via_journal_entry,
|
||||||
|
submit_journal_entry,
|
||||||
|
book_deferred_entries_based_on,
|
||||||
|
prev_posting_date,
|
||||||
)
|
)
|
||||||
|
|
||||||
via_journal_entry = cint(
|
via_journal_entry = cint(
|
||||||
|
@ -2,10 +2,6 @@
|
|||||||
"country_code": "nl",
|
"country_code": "nl",
|
||||||
"name": "Netherlands - Grootboekschema",
|
"name": "Netherlands - Grootboekschema",
|
||||||
"tree": {
|
"tree": {
|
||||||
"FABRIKAGEREKENINGEN": {
|
|
||||||
"is_group": 1,
|
|
||||||
"root_type": "Expense"
|
|
||||||
},
|
|
||||||
"FINANCIELE REKENINGEN, KORTLOPENDE VORDERINGEN EN SCHULDEN": {
|
"FINANCIELE REKENINGEN, KORTLOPENDE VORDERINGEN EN SCHULDEN": {
|
||||||
"Bank": {
|
"Bank": {
|
||||||
"RABO Bank": {
|
"RABO Bank": {
|
||||||
@ -13,6 +9,144 @@
|
|||||||
},
|
},
|
||||||
"account_type": "Bank"
|
"account_type": "Bank"
|
||||||
},
|
},
|
||||||
|
"LIQUIDE MIDDELEN": {
|
||||||
|
"ABN-AMRO bank": {},
|
||||||
|
"Bankbetaalkaarten": {},
|
||||||
|
"Effecten": {},
|
||||||
|
"Girobetaalkaarten": {},
|
||||||
|
"Kas": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Kas valuta": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Kleine kas": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Kruisposten": {},
|
||||||
|
"Postbank": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"TUSSENREKENINGEN": {
|
||||||
|
"Betaalwijze cadeaubonnen": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Betaalwijze chipknip": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Betaalwijze contant": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Betaalwijze pin": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen Nederland hoog": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen Nederland laag": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen Nederland onbelast": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen Nederland overig": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen Nederland verlegd": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen binnen EU hoog": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen binnen EU laag": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen binnen EU overig": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen buiten EU hoog": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen buiten EU laag": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Inkopen buiten EU overig": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Kassa 1": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Kassa 2": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Netto lonen": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tegenrekening Inkopen": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tussenrek. autom. betalingen": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tussenrek. autom. loonbetalingen": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tussenrek. cadeaubonbetalingen": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tussenrekening balans": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tussenrekening chipknip": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tussenrekening correcties": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Tussenrekening pin": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"Vraagposten": {
|
||||||
|
"account_type": "Cash"
|
||||||
|
},
|
||||||
|
"VOORRAAD GRONDSTOFFEN, HULPMATERIALEN EN HANDELSGOEDEREN": {
|
||||||
|
"Emballage": {},
|
||||||
|
"Gereed product 1": {},
|
||||||
|
"Gereed product 2": {},
|
||||||
|
"Goederen 1": {},
|
||||||
|
"Goederen 2": {},
|
||||||
|
"Goederen in consignatie": {},
|
||||||
|
"Goederen onderweg": {},
|
||||||
|
"Grondstoffen 1": {},
|
||||||
|
"Grondstoffen 2": {},
|
||||||
|
"Halffabrikaten 1": {},
|
||||||
|
"Halffabrikaten 2": {},
|
||||||
|
"Hulpstoffen 1": {},
|
||||||
|
"Hulpstoffen 2": {},
|
||||||
|
"Kantoorbenodigdheden": {},
|
||||||
|
"Onderhanden werk": {},
|
||||||
|
"Verpakkingsmateriaal": {},
|
||||||
|
"Zegels": {},
|
||||||
|
"root_type": "Asset"
|
||||||
|
},
|
||||||
|
"root_type": "Asset"
|
||||||
|
},
|
||||||
|
"VORDERINGEN": {
|
||||||
|
"Debiteuren": {
|
||||||
|
"account_type": "Receivable"
|
||||||
|
},
|
||||||
|
"Dubieuze debiteuren": {},
|
||||||
|
"Overige vorderingen": {},
|
||||||
|
"Rekening-courant directie 1": {},
|
||||||
|
"Te ontvangen ziekengeld": {},
|
||||||
|
"Voorschotten personeel": {},
|
||||||
|
"Vooruitbetaalde kosten": {},
|
||||||
|
"Voorziening dubieuze debiteuren": {}
|
||||||
|
},
|
||||||
|
"root_type": "Asset"
|
||||||
|
},
|
||||||
"KORTLOPENDE SCHULDEN": {
|
"KORTLOPENDE SCHULDEN": {
|
||||||
"Af te dragen Btw-verlegd": {
|
"Af te dragen Btw-verlegd": {
|
||||||
"account_type": "Tax"
|
"account_type": "Tax"
|
||||||
@ -69,42 +203,13 @@
|
|||||||
"Vakantiegeld 1": {},
|
"Vakantiegeld 1": {},
|
||||||
"Vakantiezegels": {},
|
"Vakantiezegels": {},
|
||||||
"Vennootschapsbelasting": {},
|
"Vennootschapsbelasting": {},
|
||||||
"Vooruit ontvangen bedr.": {}
|
"Vooruit ontvangen bedr.": {},
|
||||||
},
|
"is_group": 1,
|
||||||
"LIQUIDE MIDDELEN": {
|
"root_type": "Liability"
|
||||||
"ABN-AMRO bank": {},
|
|
||||||
"Bankbetaalkaarten": {},
|
|
||||||
"Effecten": {},
|
|
||||||
"Girobetaalkaarten": {},
|
|
||||||
"Kas": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Kas valuta": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Kleine kas": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Kruisposten": {},
|
|
||||||
"Postbank": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"VORDERINGEN": {
|
|
||||||
"Debiteuren": {
|
|
||||||
"account_type": "Receivable"
|
|
||||||
},
|
|
||||||
"Dubieuze debiteuren": {},
|
|
||||||
"Overige vorderingen": {},
|
|
||||||
"Rekening-courant directie 1": {},
|
|
||||||
"Te ontvangen ziekengeld": {},
|
|
||||||
"Voorschotten personeel": {},
|
|
||||||
"Vooruitbetaalde kosten": {},
|
|
||||||
"Voorziening dubieuze debiteuren": {}
|
|
||||||
},
|
|
||||||
"root_type": "Asset"
|
|
||||||
},
|
},
|
||||||
|
"FABRIKAGEREKENINGEN": {
|
||||||
|
"is_group": 1,
|
||||||
|
"root_type": "Expense",
|
||||||
"INDIRECTE KOSTEN": {
|
"INDIRECTE KOSTEN": {
|
||||||
"is_group": 1,
|
"is_group": 1,
|
||||||
"root_type": "Expense"
|
"root_type": "Expense"
|
||||||
@ -291,91 +396,49 @@
|
|||||||
"Priv\u00e9-gebruik auto's": {},
|
"Priv\u00e9-gebruik auto's": {},
|
||||||
"Wegenbelasting": {}
|
"Wegenbelasting": {}
|
||||||
},
|
},
|
||||||
|
"VOORRAAD GEREED PRODUCT EN ONDERHANDEN WERK": {
|
||||||
|
"Betalingskort. crediteuren": {},
|
||||||
|
"Garantiekosten": {},
|
||||||
|
"Hulpmaterialen": {},
|
||||||
|
"Inkomende vrachten": {
|
||||||
|
"account_type": "Expenses Included In Valuation"
|
||||||
|
},
|
||||||
|
"Inkoop import buiten EU hoog": {},
|
||||||
|
"Inkoop import buiten EU laag": {},
|
||||||
|
"Inkoop import buiten EU overig": {},
|
||||||
|
"Inkoopbonussen": {},
|
||||||
|
"Inkoopkosten": {},
|
||||||
|
"Inkoopprovisie": {},
|
||||||
|
"Inkopen BTW verlegd": {},
|
||||||
|
"Inkopen EU hoog tarief": {},
|
||||||
|
"Inkopen EU laag tarief": {},
|
||||||
|
"Inkopen EU overig": {},
|
||||||
|
"Inkopen hoog": {},
|
||||||
|
"Inkopen laag": {},
|
||||||
|
"Inkopen nul": {},
|
||||||
|
"Inkopen overig": {},
|
||||||
|
"Invoerkosten": {},
|
||||||
|
"Kosten inkoopvereniging": {},
|
||||||
|
"Kostprijs omzet grondstoffen": {
|
||||||
|
"account_type": "Cost of Goods Sold"
|
||||||
|
},
|
||||||
|
"Kostprijs omzet handelsgoederen": {},
|
||||||
|
"Onttrekking uitgev.garantie": {},
|
||||||
|
"Priv\u00e9-gebruik goederen": {},
|
||||||
|
"Stock aanpassing": {
|
||||||
|
"account_type": "Stock Adjustment"
|
||||||
|
},
|
||||||
|
"Tegenrekening inkoop": {},
|
||||||
|
"Toev. Voorz. incour. grondst.": {},
|
||||||
|
"Toevoeging garantieverpl.": {},
|
||||||
|
"Toevoeging voorz. incour. handelsgoed.": {},
|
||||||
|
"Uitbesteed werk": {},
|
||||||
|
"Voorz. Incourourant grondst.": {},
|
||||||
|
"Voorz.incour. handelsgoed.": {},
|
||||||
"root_type": "Expense"
|
"root_type": "Expense"
|
||||||
},
|
},
|
||||||
"TUSSENREKENINGEN": {
|
"root_type": "Expense"
|
||||||
"Betaalwijze cadeaubonnen": {
|
}
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Betaalwijze chipknip": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Betaalwijze contant": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Betaalwijze pin": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen Nederland hoog": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen Nederland laag": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen Nederland onbelast": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen Nederland overig": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen Nederland verlegd": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen binnen EU hoog": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen binnen EU laag": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen binnen EU overig": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen buiten EU hoog": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen buiten EU laag": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Inkopen buiten EU overig": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Kassa 1": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Kassa 2": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Netto lonen": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tegenrekening Inkopen": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tussenrek. autom. betalingen": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tussenrek. autom. loonbetalingen": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tussenrek. cadeaubonbetalingen": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tussenrekening balans": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tussenrekening chipknip": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tussenrekening correcties": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Tussenrekening pin": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"Vraagposten": {
|
|
||||||
"account_type": "Cash"
|
|
||||||
},
|
|
||||||
"root_type": "Asset"
|
|
||||||
},
|
},
|
||||||
"VASTE ACTIVA, EIGEN VERMOGEN, LANGLOPEND VREEMD VERMOGEN EN VOORZIENINGEN": {
|
"VASTE ACTIVA, EIGEN VERMOGEN, LANGLOPEND VREEMD VERMOGEN EN VOORZIENINGEN": {
|
||||||
"EIGEN VERMOGEN": {
|
"EIGEN VERMOGEN": {
|
||||||
@ -602,7 +665,7 @@
|
|||||||
"account_type": "Equity"
|
"account_type": "Equity"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root_type": "Asset"
|
"root_type": "Equity"
|
||||||
},
|
},
|
||||||
"VERKOOPRESULTATEN": {
|
"VERKOOPRESULTATEN": {
|
||||||
"Diensten fabric. 0% niet-EU": {},
|
"Diensten fabric. 0% niet-EU": {},
|
||||||
@ -627,67 +690,6 @@
|
|||||||
"Verleende Kredietbep. fabricage": {},
|
"Verleende Kredietbep. fabricage": {},
|
||||||
"Verleende Kredietbep. handel": {},
|
"Verleende Kredietbep. handel": {},
|
||||||
"root_type": "Income"
|
"root_type": "Income"
|
||||||
},
|
|
||||||
"VOORRAAD GEREED PRODUCT EN ONDERHANDEN WERK": {
|
|
||||||
"Betalingskort. crediteuren": {},
|
|
||||||
"Garantiekosten": {},
|
|
||||||
"Hulpmaterialen": {},
|
|
||||||
"Inkomende vrachten": {
|
|
||||||
"account_type": "Expenses Included In Valuation"
|
|
||||||
},
|
|
||||||
"Inkoop import buiten EU hoog": {},
|
|
||||||
"Inkoop import buiten EU laag": {},
|
|
||||||
"Inkoop import buiten EU overig": {},
|
|
||||||
"Inkoopbonussen": {},
|
|
||||||
"Inkoopkosten": {},
|
|
||||||
"Inkoopprovisie": {},
|
|
||||||
"Inkopen BTW verlegd": {},
|
|
||||||
"Inkopen EU hoog tarief": {},
|
|
||||||
"Inkopen EU laag tarief": {},
|
|
||||||
"Inkopen EU overig": {},
|
|
||||||
"Inkopen hoog": {},
|
|
||||||
"Inkopen laag": {},
|
|
||||||
"Inkopen nul": {},
|
|
||||||
"Inkopen overig": {},
|
|
||||||
"Invoerkosten": {},
|
|
||||||
"Kosten inkoopvereniging": {},
|
|
||||||
"Kostprijs omzet grondstoffen": {
|
|
||||||
"account_type": "Cost of Goods Sold"
|
|
||||||
},
|
|
||||||
"Kostprijs omzet handelsgoederen": {},
|
|
||||||
"Onttrekking uitgev.garantie": {},
|
|
||||||
"Priv\u00e9-gebruik goederen": {},
|
|
||||||
"Stock aanpassing": {
|
|
||||||
"account_type": "Stock Adjustment"
|
|
||||||
},
|
|
||||||
"Tegenrekening inkoop": {},
|
|
||||||
"Toev. Voorz. incour. grondst.": {},
|
|
||||||
"Toevoeging garantieverpl.": {},
|
|
||||||
"Toevoeging voorz. incour. handelsgoed.": {},
|
|
||||||
"Uitbesteed werk": {},
|
|
||||||
"Voorz. Incourourant grondst.": {},
|
|
||||||
"Voorz.incour. handelsgoed.": {},
|
|
||||||
"root_type": "Expense"
|
|
||||||
},
|
|
||||||
"VOORRAAD GRONDSTOFFEN, HULPMATERIALEN EN HANDELSGOEDEREN": {
|
|
||||||
"Emballage": {},
|
|
||||||
"Gereed product 1": {},
|
|
||||||
"Gereed product 2": {},
|
|
||||||
"Goederen 1": {},
|
|
||||||
"Goederen 2": {},
|
|
||||||
"Goederen in consignatie": {},
|
|
||||||
"Goederen onderweg": {},
|
|
||||||
"Grondstoffen 1": {},
|
|
||||||
"Grondstoffen 2": {},
|
|
||||||
"Halffabrikaten 1": {},
|
|
||||||
"Halffabrikaten 2": {},
|
|
||||||
"Hulpstoffen 1": {},
|
|
||||||
"Hulpstoffen 2": {},
|
|
||||||
"Kantoorbenodigdheden": {},
|
|
||||||
"Onderhanden werk": {},
|
|
||||||
"Verpakkingsmateriaal": {},
|
|
||||||
"Zegels": {},
|
|
||||||
"root_type": "Asset"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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(
|
||||||
[
|
[
|
||||||
|
@ -8,9 +8,6 @@ frappe.ui.form.on('Bank', {
|
|||||||
},
|
},
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
add_fields_to_mapping_table(frm);
|
add_fields_to_mapping_table(frm);
|
||||||
|
|
||||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' };
|
|
||||||
|
|
||||||
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
|
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
|
||||||
|
|
||||||
if (frm.doc.__islocal) {
|
if (frm.doc.__islocal) {
|
||||||
|
@ -19,7 +19,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
|
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
// Set default filter dates
|
// Set default filter dates
|
||||||
today = frappe.datetime.get_today()
|
let today = frappe.datetime.get_today()
|
||||||
frm.doc.bank_statement_from_date = frappe.datetime.add_months(today, -1);
|
frm.doc.bank_statement_from_date = frappe.datetime.add_months(today, -1);
|
||||||
frm.doc.bank_statement_to_date = today;
|
frm.doc.bank_statement_to_date = today;
|
||||||
frm.trigger('bank_account');
|
frm.trigger('bank_account');
|
||||||
|
@ -93,6 +93,12 @@ class ExchangeRateRevaluation(Document):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def fetch_and_calculate_accounts_data(self):
|
||||||
|
accounts = self.get_accounts_data()
|
||||||
|
if accounts:
|
||||||
|
for acc in accounts:
|
||||||
|
self.append("accounts", acc)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_accounts_data(self):
|
def get_accounts_data(self):
|
||||||
self.validate_mandatory()
|
self.validate_mandatory()
|
||||||
@ -252,8 +258,8 @@ class ExchangeRateRevaluation(Document):
|
|||||||
new_balance_in_base_currency = 0
|
new_balance_in_base_currency = 0
|
||||||
new_balance_in_account_currency = 0
|
new_balance_in_account_currency = 0
|
||||||
|
|
||||||
current_exchange_rate = calculate_exchange_rate_using_last_gle(
|
current_exchange_rate = (
|
||||||
company, d.account, d.party_type, d.party
|
calculate_exchange_rate_using_last_gle(company, d.account, d.party_type, d.party) or 0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
gain_loss = new_balance_in_account_currency - (
|
gain_loss = new_balance_in_account_currency - (
|
||||||
|
@ -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,28 +4,12 @@
|
|||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
class FiscalYear(Document):
|
class FiscalYear(Document):
|
||||||
@frappe.whitelist()
|
|
||||||
def set_as_default(self):
|
|
||||||
frappe.db.set_single_value("Global Defaults", "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()
|
||||||
@ -68,13 +52,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):
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"in_filter": 1,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
@ -56,7 +57,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-01-18 21:11:23.105589",
|
"modified": "2023-07-09 18:11:23.105589",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Item Tax Template",
|
"name": "Item Tax Template",
|
||||||
|
@ -408,6 +408,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(
|
||||||
|
@ -8,6 +8,7 @@ from functools import reduce
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import ValidationError, _, qb, scrub, throw
|
from frappe import ValidationError, _, qb, scrub, throw
|
||||||
from frappe.utils import cint, comma_or, flt, getdate, nowdate
|
from frappe.utils import cint, comma_or, flt, getdate, nowdate
|
||||||
|
from frappe.utils.data import comma_and, fmt_money
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
from erpnext.accounts.doctype.bank_account.bank_account import (
|
from erpnext.accounts.doctype.bank_account.bank_account import (
|
||||||
@ -124,13 +125,16 @@ class PaymentEntry(AccountsController):
|
|||||||
|
|
||||||
self.set(self.party_account_field, liability_account)
|
self.set(self.party_account_field, liability_account)
|
||||||
|
|
||||||
msg = "Book Advance Payments as Liability option is chosen. Paid From account changed from {0} to {1}.".format(
|
frappe.msgprint(
|
||||||
|
_(
|
||||||
|
"Book Advance Payments as Liability option is chosen. Paid From account changed from {0} to {1}."
|
||||||
|
).format(
|
||||||
frappe.bold(self.party_account),
|
frappe.bold(self.party_account),
|
||||||
frappe.bold(liability_account),
|
frappe.bold(liability_account),
|
||||||
|
),
|
||||||
|
alert=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.msgprint(_(msg), alert=True)
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.ignore_linked_doctypes = (
|
self.ignore_linked_doctypes = (
|
||||||
"GL Entry",
|
"GL Entry",
|
||||||
@ -230,17 +234,16 @@ class PaymentEntry(AccountsController):
|
|||||||
# The reference has already been fully paid
|
# The reference has already been fully paid
|
||||||
if not latest:
|
if not latest:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("{0} {1} has already been fully paid.").format(d.reference_doctype, d.reference_name)
|
_("{0} {1} has already been fully paid.").format(_(d.reference_doctype), d.reference_name)
|
||||||
)
|
)
|
||||||
# The reference has already been partly paid
|
# The reference has already been partly paid
|
||||||
elif (
|
elif latest.outstanding_amount < latest.invoice_amount and flt(
|
||||||
latest.outstanding_amount < latest.invoice_amount
|
d.outstanding_amount, d.precision("outstanding_amount")
|
||||||
and d.outstanding_amount != latest.outstanding_amount
|
) != flt(latest.outstanding_amount, d.precision("outstanding_amount")):
|
||||||
):
|
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_(
|
_(
|
||||||
"{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' or the 'Get Outstanding Orders' button to get the latest outstanding amounts."
|
"{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' or the 'Get Outstanding Orders' button to get the latest outstanding amounts."
|
||||||
).format(d.reference_doctype, d.reference_name)
|
).format(_(d.reference_doctype), d.reference_name)
|
||||||
)
|
)
|
||||||
|
|
||||||
fail_message = _("Row #{0}: Allocated Amount cannot be greater than outstanding amount.")
|
fail_message = _("Row #{0}: Allocated Amount cannot be greater than outstanding amount.")
|
||||||
@ -342,7 +345,7 @@ class PaymentEntry(AccountsController):
|
|||||||
def validate_party_details(self):
|
def validate_party_details(self):
|
||||||
if self.party:
|
if self.party:
|
||||||
if not frappe.db.exists(self.party_type, self.party):
|
if not frappe.db.exists(self.party_type, self.party):
|
||||||
frappe.throw(_("Invalid {0}: {1}").format(self.party_type, self.party))
|
frappe.throw(_("{0} {1} does not exist").format(_(self.party_type), self.party))
|
||||||
|
|
||||||
def set_exchange_rate(self, ref_doc=None):
|
def set_exchange_rate(self, ref_doc=None):
|
||||||
self.set_source_exchange_rate(ref_doc)
|
self.set_source_exchange_rate(ref_doc)
|
||||||
@ -391,7 +394,9 @@ class PaymentEntry(AccountsController):
|
|||||||
continue
|
continue
|
||||||
if d.reference_doctype not in valid_reference_doctypes:
|
if d.reference_doctype not in valid_reference_doctypes:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Reference Doctype must be one of {0}").format(comma_or(valid_reference_doctypes))
|
_("Reference Doctype must be one of {0}").format(
|
||||||
|
comma_or((_(d) for d in valid_reference_doctypes))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
elif d.reference_name:
|
elif d.reference_name:
|
||||||
@ -404,7 +409,7 @@ class PaymentEntry(AccountsController):
|
|||||||
if self.party != ref_doc.get(scrub(self.party_type)):
|
if self.party != ref_doc.get(scrub(self.party_type)):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("{0} {1} is not associated with {2} {3}").format(
|
_("{0} {1} is not associated with {2} {3}").format(
|
||||||
d.reference_doctype, d.reference_name, self.party_type, self.party
|
_(d.reference_doctype), d.reference_name, _(self.party_type), self.party
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -426,18 +431,18 @@ class PaymentEntry(AccountsController):
|
|||||||
):
|
):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("{0} {1} is associated with {2}, but Party Account is {3}").format(
|
_("{0} {1} is associated with {2}, but Party Account is {3}").format(
|
||||||
d.reference_doctype, d.reference_name, ref_party_account, self.party_account
|
_(d.reference_doctype), d.reference_name, ref_party_account, self.party_account
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if ref_doc.doctype == "Purchase Invoice" and ref_doc.get("on_hold"):
|
if ref_doc.doctype == "Purchase Invoice" and ref_doc.get("on_hold"):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("{0} {1} is on hold").format(d.reference_doctype, d.reference_name),
|
_("{0} {1} is on hold").format(_(d.reference_doctype), d.reference_name),
|
||||||
title=_("Invalid Invoice"),
|
title=_("Invalid Purchase Invoice"),
|
||||||
)
|
)
|
||||||
|
|
||||||
if ref_doc.docstatus != 1:
|
if ref_doc.docstatus != 1:
|
||||||
frappe.throw(_("{0} {1} must be submitted").format(d.reference_doctype, d.reference_name))
|
frappe.throw(_("{0} {1} must be submitted").format(_(d.reference_doctype), d.reference_name))
|
||||||
|
|
||||||
def get_valid_reference_doctypes(self):
|
def get_valid_reference_doctypes(self):
|
||||||
if self.party_type == "Customer":
|
if self.party_type == "Customer":
|
||||||
@ -463,14 +468,13 @@ class PaymentEntry(AccountsController):
|
|||||||
if outstanding_amount <= 0 and not is_return:
|
if outstanding_amount <= 0 and not is_return:
|
||||||
no_oustanding_refs.setdefault(d.reference_doctype, []).append(d)
|
no_oustanding_refs.setdefault(d.reference_doctype, []).append(d)
|
||||||
|
|
||||||
for k, v in no_oustanding_refs.items():
|
for reference_doctype, references in no_oustanding_refs.items():
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
_(
|
_(
|
||||||
"{} - {} now has {} as it had no outstanding amount left before submitting the Payment Entry."
|
"References {0} of type {1} had no outstanding amount left before submitting the Payment Entry. Now they have a negative outstanding amount."
|
||||||
).format(
|
).format(
|
||||||
_(k),
|
frappe.bold(comma_and((d.reference_name for d in references))),
|
||||||
frappe.bold(", ".join(d.reference_name for d in v)),
|
_(reference_doctype),
|
||||||
frappe.bold(_("negative outstanding amount")),
|
|
||||||
)
|
)
|
||||||
+ "<br><br>"
|
+ "<br><br>"
|
||||||
+ _("If this is undesirable please cancel the corresponding Payment Entry."),
|
+ _("If this is undesirable please cancel the corresponding Payment Entry."),
|
||||||
@ -505,7 +509,7 @@ class PaymentEntry(AccountsController):
|
|||||||
if not valid:
|
if not valid:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
|
_("Against Journal Entry {0} does not have any unmatched {1} entry").format(
|
||||||
d.reference_name, dr_or_cr
|
d.reference_name, _(dr_or_cr)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -572,7 +576,7 @@ class PaymentEntry(AccountsController):
|
|||||||
if allocated_amount > outstanding:
|
if allocated_amount > outstanding:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Row #{0}: Cannot allocate more than {1} against payment term {2}").format(
|
_("Row #{0}: Cannot allocate more than {1} against payment term {2}").format(
|
||||||
idx, outstanding, key[0]
|
idx, fmt_money(outstanding), key[0]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -876,7 +880,7 @@ class PaymentEntry(AccountsController):
|
|||||||
elif paid_amount - additional_charges > total_negative_outstanding:
|
elif paid_amount - additional_charges > total_negative_outstanding:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Paid Amount cannot be greater than total negative outstanding amount {0}").format(
|
_("Paid Amount cannot be greater than total negative outstanding amount {0}").format(
|
||||||
total_negative_outstanding
|
fmt_money(total_negative_outstanding)
|
||||||
),
|
),
|
||||||
InvalidPaymentEntry,
|
InvalidPaymentEntry,
|
||||||
)
|
)
|
||||||
@ -1428,6 +1432,9 @@ def get_outstanding_reference_documents(args, validate=False):
|
|||||||
if args.get("party_type") == "Member":
|
if args.get("party_type") == "Member":
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not args.get("get_outstanding_invoices") and not args.get("get_orders_to_be_billed"):
|
||||||
|
args["get_outstanding_invoices"] = True
|
||||||
|
|
||||||
ple = qb.DocType("Payment Ledger Entry")
|
ple = qb.DocType("Payment Ledger Entry")
|
||||||
common_filter = []
|
common_filter = []
|
||||||
accounting_dimensions_filter = []
|
accounting_dimensions_filter = []
|
||||||
@ -1546,7 +1553,7 @@ def get_outstanding_reference_documents(args, validate=False):
|
|||||||
_(
|
_(
|
||||||
"No outstanding {0} found for the {1} {2} which qualify the filters you have specified."
|
"No outstanding {0} found for the {1} {2} which qualify the filters you have specified."
|
||||||
).format(
|
).format(
|
||||||
ref_document_type, _(args.get("party_type")).lower(), frappe.bold(args.get("party"))
|
_(ref_document_type), _(args.get("party_type")).lower(), frappe.bold(args.get("party"))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1622,22 +1629,21 @@ def get_orders_to_be_billed(
|
|||||||
cost_center=None,
|
cost_center=None,
|
||||||
filters=None,
|
filters=None,
|
||||||
):
|
):
|
||||||
|
voucher_type = None
|
||||||
if party_type == "Customer":
|
if party_type == "Customer":
|
||||||
voucher_type = "Sales Order"
|
voucher_type = "Sales Order"
|
||||||
elif party_type == "Supplier":
|
elif party_type == "Supplier":
|
||||||
voucher_type = "Purchase Order"
|
voucher_type = "Purchase Order"
|
||||||
elif party_type == "Employee":
|
|
||||||
voucher_type = None
|
if not voucher_type:
|
||||||
|
return []
|
||||||
|
|
||||||
# Add cost center condition
|
# Add cost center condition
|
||||||
if voucher_type:
|
|
||||||
doc = frappe.get_doc({"doctype": voucher_type})
|
doc = frappe.get_doc({"doctype": voucher_type})
|
||||||
condition = ""
|
condition = ""
|
||||||
if doc and hasattr(doc, "cost_center") and doc.cost_center:
|
if doc and hasattr(doc, "cost_center") and doc.cost_center:
|
||||||
condition = " and cost_center='%s'" % cost_center
|
condition = " and cost_center='%s'" % cost_center
|
||||||
|
|
||||||
orders = []
|
|
||||||
if voucher_type:
|
|
||||||
if party_account_currency == company_currency:
|
if party_account_currency == company_currency:
|
||||||
grand_total_field = "base_grand_total"
|
grand_total_field = "base_grand_total"
|
||||||
rounded_total_field = "base_rounded_total"
|
rounded_total_field = "base_rounded_total"
|
||||||
@ -1708,6 +1714,8 @@ def get_negative_outstanding_invoices(
|
|||||||
cost_center=None,
|
cost_center=None,
|
||||||
condition=None,
|
condition=None,
|
||||||
):
|
):
|
||||||
|
if party_type not in ["Customer", "Supplier"]:
|
||||||
|
return []
|
||||||
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
|
voucher_type = "Sales Invoice" if party_type == "Customer" else "Purchase Invoice"
|
||||||
account = "debit_to" if voucher_type == "Sales Invoice" else "credit_to"
|
account = "debit_to" if voucher_type == "Sales Invoice" else "credit_to"
|
||||||
supplier_condition = ""
|
supplier_condition = ""
|
||||||
@ -1758,7 +1766,7 @@ def get_negative_outstanding_invoices(
|
|||||||
def get_party_details(company, party_type, party, date, cost_center=None):
|
def get_party_details(company, party_type, party, date, cost_center=None):
|
||||||
bank_account = ""
|
bank_account = ""
|
||||||
if not frappe.db.exists(party_type, party):
|
if not frappe.db.exists(party_type, party):
|
||||||
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
|
frappe.throw(_("{0} {1} does not exist").format(_(party_type), party))
|
||||||
|
|
||||||
party_account = get_party_account(party_type, party, company)
|
party_account = get_party_account(party_type, party, company)
|
||||||
account_currency = get_account_currency(party_account)
|
account_currency = get_account_currency(party_account)
|
||||||
@ -1912,7 +1920,7 @@ def get_payment_entry(
|
|||||||
if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) >= (
|
if dt in ("Sales Order", "Purchase Order") and flt(doc.per_billed, 2) >= (
|
||||||
100.0 + over_billing_allowance
|
100.0 + over_billing_allowance
|
||||||
):
|
):
|
||||||
frappe.throw(_("Can only make payment against unbilled {0}").format(dt))
|
frappe.throw(_("Can only make payment against unbilled {0}").format(_(dt)))
|
||||||
|
|
||||||
if not party_type:
|
if not party_type:
|
||||||
party_type = set_party_type(dt)
|
party_type = set_party_type(dt)
|
||||||
|
@ -16,8 +16,10 @@ from erpnext.stock.doctype.item.test_item import create_item
|
|||||||
class TestProcessDeferredAccounting(unittest.TestCase):
|
class TestProcessDeferredAccounting(unittest.TestCase):
|
||||||
def test_creation_of_ledger_entry_on_submit(self):
|
def test_creation_of_ledger_entry_on_submit(self):
|
||||||
"""test creation of gl entries on submission of document"""
|
"""test creation of gl entries on submission of document"""
|
||||||
|
change_acc_settings(acc_frozen_upto="2023-05-31", book_deferred_entries_based_on="Months")
|
||||||
|
|
||||||
deferred_account = create_account(
|
deferred_account = create_account(
|
||||||
account_name="Deferred Revenue",
|
account_name="Deferred Revenue for Accounts Frozen",
|
||||||
parent_account="Current Liabilities - _TC",
|
parent_account="Current Liabilities - _TC",
|
||||||
company="_Test Company",
|
company="_Test Company",
|
||||||
)
|
)
|
||||||
@ -29,21 +31,21 @@ class TestProcessDeferredAccounting(unittest.TestCase):
|
|||||||
item.save()
|
item.save()
|
||||||
|
|
||||||
si = create_sales_invoice(
|
si = create_sales_invoice(
|
||||||
item=item.name, update_stock=0, posting_date="2019-01-10", do_not_submit=True
|
item=item.name, rate=3000, update_stock=0, posting_date="2023-07-01", do_not_submit=True
|
||||||
)
|
)
|
||||||
si.items[0].enable_deferred_revenue = 1
|
si.items[0].enable_deferred_revenue = 1
|
||||||
si.items[0].service_start_date = "2019-01-10"
|
si.items[0].service_start_date = "2023-05-01"
|
||||||
si.items[0].service_end_date = "2019-03-15"
|
si.items[0].service_end_date = "2023-07-31"
|
||||||
si.items[0].deferred_revenue_account = deferred_account
|
si.items[0].deferred_revenue_account = deferred_account
|
||||||
si.save()
|
si.save()
|
||||||
si.submit()
|
si.submit()
|
||||||
|
|
||||||
process_deferred_accounting = frappe.get_doc(
|
process_deferred_accounting = doc = frappe.get_doc(
|
||||||
dict(
|
dict(
|
||||||
doctype="Process Deferred Accounting",
|
doctype="Process Deferred Accounting",
|
||||||
posting_date="2019-01-01",
|
posting_date="2023-07-01",
|
||||||
start_date="2019-01-01",
|
start_date="2023-05-01",
|
||||||
end_date="2019-01-31",
|
end_date="2023-06-30",
|
||||||
type="Income",
|
type="Income",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -52,11 +54,16 @@ class TestProcessDeferredAccounting(unittest.TestCase):
|
|||||||
process_deferred_accounting.submit()
|
process_deferred_accounting.submit()
|
||||||
|
|
||||||
expected_gle = [
|
expected_gle = [
|
||||||
[deferred_account, 33.85, 0.0, "2019-01-31"],
|
["Debtors - _TC", 3000, 0.0, "2023-07-01"],
|
||||||
["Sales - _TC", 0.0, 33.85, "2019-01-31"],
|
[deferred_account, 0.0, 3000, "2023-07-01"],
|
||||||
|
["Sales - _TC", 0.0, 1000, "2023-06-30"],
|
||||||
|
[deferred_account, 1000, 0.0, "2023-06-30"],
|
||||||
|
["Sales - _TC", 0.0, 1000, "2023-06-30"],
|
||||||
|
[deferred_account, 1000, 0.0, "2023-06-30"],
|
||||||
]
|
]
|
||||||
|
|
||||||
check_gl_entries(self, si.name, expected_gle, "2019-01-31")
|
check_gl_entries(self, si.name, expected_gle, "2023-07-01")
|
||||||
|
change_acc_settings()
|
||||||
|
|
||||||
def test_pda_submission_and_cancellation(self):
|
def test_pda_submission_and_cancellation(self):
|
||||||
pda = frappe.get_doc(
|
pda = frappe.get_doc(
|
||||||
@ -70,3 +77,10 @@ class TestProcessDeferredAccounting(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
pda.submit()
|
pda.submit()
|
||||||
pda.cancel()
|
pda.cancel()
|
||||||
|
|
||||||
|
|
||||||
|
def change_acc_settings(acc_frozen_upto="", book_deferred_entries_based_on="Days"):
|
||||||
|
acc_settings = frappe.get_doc("Accounts Settings", "Accounts Settings")
|
||||||
|
acc_settings.acc_frozen_upto = acc_frozen_upto
|
||||||
|
acc_settings.book_deferred_entries_based_on = book_deferred_entries_based_on
|
||||||
|
acc_settings.save()
|
||||||
|
@ -549,6 +549,7 @@
|
|||||||
"depends_on": "update_stock",
|
"depends_on": "update_stock",
|
||||||
"fieldname": "rejected_warehouse",
|
"fieldname": "rejected_warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
"label": "Rejected Warehouse",
|
"label": "Rejected Warehouse",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Warehouse",
|
"options": "Warehouse",
|
||||||
@ -1576,7 +1577,7 @@
|
|||||||
"idx": 204,
|
"idx": 204,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-06-03 16:21:54.637245",
|
"modified": "2023-07-04 17:22:59.145031",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice",
|
"name": "Purchase Invoice",
|
||||||
|
@ -423,6 +423,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "rejected_warehouse",
|
"fieldname": "rejected_warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
"label": "Rejected Warehouse",
|
"label": "Rejected Warehouse",
|
||||||
"options": "Warehouse"
|
"options": "Warehouse"
|
||||||
},
|
},
|
||||||
@ -904,7 +905,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-07-02 18:39:41.495723",
|
"modified": "2023-07-04 17:22:21.501152",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice Item",
|
"name": "Purchase Invoice Item",
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Shareholder', {
|
frappe.ui.form.on('Shareholder', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Shareholder' };
|
|
||||||
|
|
||||||
frm.toggle_display(['contact_html'], !frm.doc.__islocal);
|
frm.toggle_display(['contact_html'], !frm.doc.__islocal);
|
||||||
|
|
||||||
if (frm.doc.__islocal) {
|
if (frm.doc.__islocal) {
|
||||||
|
@ -73,7 +73,7 @@ def get_entries(filters):
|
|||||||
|
|
||||||
return sorted(
|
return sorted(
|
||||||
entries,
|
entries,
|
||||||
key=lambda k: k[2] or getdate(nowdate()),
|
key=lambda k: k[2].strftime("%H%M%S") or getdate(nowdate()),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -650,7 +650,7 @@ def set_gl_entries_by_account(
|
|||||||
if filters and filters.get("presentation_currency") != d.default_currency:
|
if filters and filters.get("presentation_currency") != d.default_currency:
|
||||||
currency_info["company"] = d.name
|
currency_info["company"] = d.name
|
||||||
currency_info["company_currency"] = d.default_currency
|
currency_info["company_currency"] = d.default_currency
|
||||||
convert_to_presentation_currency(gl_entries, currency_info, filters.get("company"))
|
convert_to_presentation_currency(gl_entries, currency_info)
|
||||||
|
|
||||||
for entry in gl_entries:
|
for entry in gl_entries:
|
||||||
if entry.account_number:
|
if entry.account_number:
|
||||||
|
@ -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;
|
||||||
|
@ -416,6 +416,7 @@ def set_gl_entries_by_account(
|
|||||||
filters,
|
filters,
|
||||||
gl_entries_by_account,
|
gl_entries_by_account,
|
||||||
ignore_closing_entries=False,
|
ignore_closing_entries=False,
|
||||||
|
ignore_opening_entries=False,
|
||||||
):
|
):
|
||||||
"""Returns a dict like { "account": [gl entries], ... }"""
|
"""Returns a dict like { "account": [gl entries], ... }"""
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
@ -426,7 +427,6 @@ def set_gl_entries_by_account(
|
|||||||
pluck="name",
|
pluck="name",
|
||||||
)
|
)
|
||||||
|
|
||||||
ignore_opening_entries = False
|
|
||||||
if accounts_list:
|
if accounts_list:
|
||||||
# For balance sheet
|
# For balance sheet
|
||||||
if not from_date:
|
if not from_date:
|
||||||
@ -462,7 +462,7 @@ def set_gl_entries_by_account(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if filters and filters.get("presentation_currency"):
|
if filters and filters.get("presentation_currency"):
|
||||||
convert_to_presentation_currency(gl_entries, get_currency(filters), filters.get("company"))
|
convert_to_presentation_currency(gl_entries, get_currency(filters))
|
||||||
|
|
||||||
for entry in gl_entries:
|
for entry in gl_entries:
|
||||||
gl_entries_by_account.setdefault(entry.account, []).append(entry)
|
gl_entries_by_account.setdefault(entry.account, []).append(entry)
|
||||||
|
@ -204,7 +204,7 @@ def get_gl_entries(filters, accounting_dimensions):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if filters.get("presentation_currency"):
|
if filters.get("presentation_currency"):
|
||||||
return convert_to_presentation_currency(gl_entries, currency_map, filters.get("company"))
|
return convert_to_presentation_currency(gl_entries, currency_map)
|
||||||
else:
|
else:
|
||||||
return gl_entries
|
return gl_entries
|
||||||
|
|
||||||
|
@ -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"),
|
||||||
|
@ -15,20 +15,21 @@ from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register i
|
|||||||
get_group_by_conditions,
|
get_group_by_conditions,
|
||||||
get_tax_accounts,
|
get_tax_accounts,
|
||||||
)
|
)
|
||||||
|
from erpnext.accounts.report.utils import get_query_columns, get_values_for_columns
|
||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
return _execute(filters)
|
return _execute(filters)
|
||||||
|
|
||||||
|
|
||||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
def _execute(filters=None, additional_table_columns=None):
|
||||||
if not filters:
|
if not filters:
|
||||||
filters = {}
|
filters = {}
|
||||||
columns = get_columns(additional_table_columns, filters)
|
columns = get_columns(additional_table_columns, filters)
|
||||||
|
|
||||||
company_currency = erpnext.get_company_currency(filters.company)
|
company_currency = erpnext.get_company_currency(filters.company)
|
||||||
|
|
||||||
item_list = get_items(filters, additional_query_columns)
|
item_list = get_items(filters, get_query_columns(additional_table_columns))
|
||||||
aii_account_map = get_aii_accounts()
|
aii_account_map = get_aii_accounts()
|
||||||
if item_list:
|
if item_list:
|
||||||
itemised_tax, tax_columns = get_tax_accounts(
|
itemised_tax, tax_columns = get_tax_accounts(
|
||||||
@ -79,14 +80,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
"posting_date": d.posting_date,
|
"posting_date": d.posting_date,
|
||||||
"supplier": d.supplier,
|
"supplier": d.supplier,
|
||||||
"supplier_name": d.supplier_name,
|
"supplier_name": d.supplier_name,
|
||||||
}
|
**get_values_for_columns(additional_table_columns, d),
|
||||||
|
|
||||||
if additional_query_columns:
|
|
||||||
for col in additional_query_columns:
|
|
||||||
row.update({col: d.get(col)})
|
|
||||||
|
|
||||||
row.update(
|
|
||||||
{
|
|
||||||
"credit_to": d.credit_to,
|
"credit_to": d.credit_to,
|
||||||
"mode_of_payment": d.mode_of_payment,
|
"mode_of_payment": d.mode_of_payment,
|
||||||
"project": d.project,
|
"project": d.project,
|
||||||
@ -99,7 +93,6 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
"rate": d.base_net_amount / d.stock_qty if d.stock_qty else d.base_net_amount,
|
"rate": d.base_net_amount / d.stock_qty if d.stock_qty else d.base_net_amount,
|
||||||
"amount": d.base_net_amount,
|
"amount": d.base_net_amount,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
total_tax = 0
|
total_tax = 0
|
||||||
for tax in tax_columns:
|
for tax in tax_columns:
|
||||||
@ -317,11 +310,6 @@ def get_conditions(filters):
|
|||||||
def get_items(filters, additional_query_columns):
|
def get_items(filters, additional_query_columns):
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
|
|
||||||
if additional_query_columns:
|
|
||||||
additional_query_columns = ", " + ", ".join(additional_query_columns)
|
|
||||||
else:
|
|
||||||
additional_query_columns = ""
|
|
||||||
|
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select
|
select
|
||||||
@ -340,11 +328,10 @@ def get_items(filters, additional_query_columns):
|
|||||||
from `tabPurchase Invoice`, `tabPurchase Invoice Item`, `tabItem`
|
from `tabPurchase Invoice`, `tabPurchase Invoice Item`, `tabItem`
|
||||||
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
|
||||||
`tabItem`.name = `tabPurchase Invoice Item`.`item_code` and
|
`tabItem`.name = `tabPurchase Invoice Item`.`item_code` and
|
||||||
`tabPurchase Invoice`.docstatus = 1 %s
|
`tabPurchase Invoice`.docstatus = 1 {1}
|
||||||
""".format(
|
""".format(
|
||||||
additional_query_columns
|
additional_query_columns, conditions
|
||||||
)
|
),
|
||||||
% (conditions),
|
|
||||||
filters,
|
filters,
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
@ -9,6 +9,7 @@ from frappe.utils import cstr, flt
|
|||||||
from frappe.utils.xlsxutils import handle_html
|
from frappe.utils.xlsxutils import handle_html
|
||||||
|
|
||||||
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
|
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
|
||||||
|
from erpnext.accounts.report.utils import get_query_columns, get_values_for_columns
|
||||||
from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import (
|
from erpnext.selling.report.item_wise_sales_history.item_wise_sales_history import (
|
||||||
get_customer_details,
|
get_customer_details,
|
||||||
)
|
)
|
||||||
@ -18,19 +19,14 @@ def execute(filters=None):
|
|||||||
return _execute(filters)
|
return _execute(filters)
|
||||||
|
|
||||||
|
|
||||||
def _execute(
|
def _execute(filters=None, additional_table_columns=None, additional_conditions=None):
|
||||||
filters=None,
|
|
||||||
additional_table_columns=None,
|
|
||||||
additional_query_columns=None,
|
|
||||||
additional_conditions=None,
|
|
||||||
):
|
|
||||||
if not filters:
|
if not filters:
|
||||||
filters = {}
|
filters = {}
|
||||||
columns = get_columns(additional_table_columns, filters)
|
columns = get_columns(additional_table_columns, filters)
|
||||||
|
|
||||||
company_currency = frappe.get_cached_value("Company", filters.get("company"), "default_currency")
|
company_currency = frappe.get_cached_value("Company", filters.get("company"), "default_currency")
|
||||||
|
|
||||||
item_list = get_items(filters, additional_query_columns, additional_conditions)
|
item_list = get_items(filters, get_query_columns(additional_table_columns), additional_conditions)
|
||||||
if item_list:
|
if item_list:
|
||||||
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
|
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
|
||||||
|
|
||||||
@ -79,14 +75,7 @@ def _execute(
|
|||||||
"customer": d.customer,
|
"customer": d.customer,
|
||||||
"customer_name": customer_record.customer_name,
|
"customer_name": customer_record.customer_name,
|
||||||
"customer_group": customer_record.customer_group,
|
"customer_group": customer_record.customer_group,
|
||||||
}
|
**get_values_for_columns(additional_table_columns, d),
|
||||||
|
|
||||||
if additional_query_columns:
|
|
||||||
for col in additional_query_columns:
|
|
||||||
row.update({col: d.get(col)})
|
|
||||||
|
|
||||||
row.update(
|
|
||||||
{
|
|
||||||
"debit_to": d.debit_to,
|
"debit_to": d.debit_to,
|
||||||
"mode_of_payment": ", ".join(mode_of_payments.get(d.parent, [])),
|
"mode_of_payment": ", ".join(mode_of_payments.get(d.parent, [])),
|
||||||
"territory": d.territory,
|
"territory": d.territory,
|
||||||
@ -101,7 +90,6 @@ def _execute(
|
|||||||
"stock_qty": d.stock_qty,
|
"stock_qty": d.stock_qty,
|
||||||
"stock_uom": d.stock_uom,
|
"stock_uom": d.stock_uom,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
if d.stock_uom != d.uom and d.stock_qty:
|
if d.stock_uom != d.uom and d.stock_qty:
|
||||||
row.update({"rate": (d.base_net_rate * d.qty) / d.stock_qty, "amount": d.base_net_amount})
|
row.update({"rate": (d.base_net_rate * d.qty) / d.stock_qty, "amount": d.base_net_amount})
|
||||||
@ -394,11 +382,6 @@ def get_group_by_conditions(filters, doctype):
|
|||||||
def get_items(filters, additional_query_columns, additional_conditions=None):
|
def get_items(filters, additional_query_columns, additional_conditions=None):
|
||||||
conditions = get_conditions(filters, additional_conditions)
|
conditions = get_conditions(filters, additional_conditions)
|
||||||
|
|
||||||
if additional_query_columns:
|
|
||||||
additional_query_columns = ", " + ", ".join(additional_query_columns)
|
|
||||||
else:
|
|
||||||
additional_query_columns = ""
|
|
||||||
|
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
select
|
select
|
||||||
@ -424,7 +407,7 @@ def get_items(filters, additional_query_columns, additional_conditions=None):
|
|||||||
`tabItem`.name = `tabSales Invoice Item`.`item_code` and
|
`tabItem`.name = `tabSales Invoice Item`.`item_code` and
|
||||||
`tabSales Invoice`.docstatus = 1 {1}
|
`tabSales Invoice`.docstatus = 1 {1}
|
||||||
""".format(
|
""".format(
|
||||||
additional_query_columns or "", conditions
|
additional_query_columns, conditions
|
||||||
),
|
),
|
||||||
filters,
|
filters,
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
|
@ -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;
|
||||||
|
@ -10,17 +10,18 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
|||||||
get_accounting_dimensions,
|
get_accounting_dimensions,
|
||||||
get_dimension_with_children,
|
get_dimension_with_children,
|
||||||
)
|
)
|
||||||
|
from erpnext.accounts.report.utils import get_query_columns, get_values_for_columns
|
||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
return _execute(filters)
|
return _execute(filters)
|
||||||
|
|
||||||
|
|
||||||
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
|
def _execute(filters=None, additional_table_columns=None):
|
||||||
if not filters:
|
if not filters:
|
||||||
filters = {}
|
filters = {}
|
||||||
|
|
||||||
invoice_list = get_invoices(filters, additional_query_columns)
|
invoice_list = get_invoices(filters, get_query_columns(additional_table_columns))
|
||||||
columns, expense_accounts, tax_accounts, unrealized_profit_loss_accounts = get_columns(
|
columns, expense_accounts, tax_accounts, unrealized_profit_loss_accounts = get_columns(
|
||||||
invoice_list, additional_table_columns
|
invoice_list, additional_table_columns
|
||||||
)
|
)
|
||||||
@ -47,13 +48,12 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
|||||||
purchase_receipt = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", [])))
|
purchase_receipt = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", [])))
|
||||||
project = list(set(invoice_po_pr_map.get(inv.name, {}).get("project", [])))
|
project = list(set(invoice_po_pr_map.get(inv.name, {}).get("project", [])))
|
||||||
|
|
||||||
row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name]
|
row = [
|
||||||
|
inv.name,
|
||||||
if additional_query_columns:
|
inv.posting_date,
|
||||||
for col in additional_query_columns:
|
inv.supplier,
|
||||||
row.append(inv.get(col))
|
inv.supplier_name,
|
||||||
|
*get_values_for_columns(additional_table_columns, inv).values(),
|
||||||
row += [
|
|
||||||
supplier_details.get(inv.supplier), # supplier_group
|
supplier_details.get(inv.supplier), # supplier_group
|
||||||
inv.tax_id,
|
inv.tax_id,
|
||||||
inv.credit_to,
|
inv.credit_to,
|
||||||
@ -244,9 +244,6 @@ def get_conditions(filters):
|
|||||||
|
|
||||||
|
|
||||||
def get_invoices(filters, additional_query_columns):
|
def get_invoices(filters, additional_query_columns):
|
||||||
if additional_query_columns:
|
|
||||||
additional_query_columns = ", " + ", ".join(additional_query_columns)
|
|
||||||
|
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
@ -255,11 +252,10 @@ def get_invoices(filters, additional_query_columns):
|
|||||||
remarks, base_net_total, base_grand_total, outstanding_amount,
|
remarks, base_net_total, base_grand_total, outstanding_amount,
|
||||||
mode_of_payment {0}
|
mode_of_payment {0}
|
||||||
from `tabPurchase Invoice`
|
from `tabPurchase Invoice`
|
||||||
where docstatus = 1 %s
|
where docstatus = 1 {1}
|
||||||
order by posting_date desc, name desc""".format(
|
order by posting_date desc, name desc""".format(
|
||||||
additional_query_columns or ""
|
additional_query_columns, conditions
|
||||||
)
|
),
|
||||||
% conditions,
|
|
||||||
filters,
|
filters,
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
@ -11,17 +11,18 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
|||||||
get_accounting_dimensions,
|
get_accounting_dimensions,
|
||||||
get_dimension_with_children,
|
get_dimension_with_children,
|
||||||
)
|
)
|
||||||
|
from erpnext.accounts.report.utils import get_query_columns, get_values_for_columns
|
||||||
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
return _execute(filters)
|
return _execute(filters)
|
||||||
|
|
||||||
|
|
||||||
def _execute(filters, additional_table_columns=None, additional_query_columns=None):
|
def _execute(filters, additional_table_columns=None):
|
||||||
if not filters:
|
if not filters:
|
||||||
filters = frappe._dict({})
|
filters = frappe._dict({})
|
||||||
|
|
||||||
invoice_list = get_invoices(filters, additional_query_columns)
|
invoice_list = get_invoices(filters, get_query_columns(additional_table_columns))
|
||||||
columns, income_accounts, tax_accounts, unrealized_profit_loss_accounts = get_columns(
|
columns, income_accounts, tax_accounts, unrealized_profit_loss_accounts = get_columns(
|
||||||
invoice_list, additional_table_columns
|
invoice_list, additional_table_columns
|
||||||
)
|
)
|
||||||
@ -54,14 +55,7 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
|
|||||||
"posting_date": inv.posting_date,
|
"posting_date": inv.posting_date,
|
||||||
"customer": inv.customer,
|
"customer": inv.customer,
|
||||||
"customer_name": inv.customer_name,
|
"customer_name": inv.customer_name,
|
||||||
}
|
**get_values_for_columns(additional_table_columns, inv),
|
||||||
|
|
||||||
if additional_query_columns:
|
|
||||||
for col in additional_query_columns:
|
|
||||||
row.update({col: inv.get(col)})
|
|
||||||
|
|
||||||
row.update(
|
|
||||||
{
|
|
||||||
"customer_group": inv.get("customer_group"),
|
"customer_group": inv.get("customer_group"),
|
||||||
"territory": inv.get("territory"),
|
"territory": inv.get("territory"),
|
||||||
"tax_id": inv.get("tax_id"),
|
"tax_id": inv.get("tax_id"),
|
||||||
@ -76,7 +70,6 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
|
|||||||
"warehouse": ", ".join(warehouse),
|
"warehouse": ", ".join(warehouse),
|
||||||
"currency": company_currency,
|
"currency": company_currency,
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
# map income values
|
# map income values
|
||||||
base_net_total = 0
|
base_net_total = 0
|
||||||
@ -402,9 +395,6 @@ def get_conditions(filters):
|
|||||||
|
|
||||||
|
|
||||||
def get_invoices(filters, additional_query_columns):
|
def get_invoices(filters, additional_query_columns):
|
||||||
if additional_query_columns:
|
|
||||||
additional_query_columns = ", " + ", ".join(additional_query_columns)
|
|
||||||
|
|
||||||
conditions = get_conditions(filters)
|
conditions = get_conditions(filters)
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
@ -413,10 +403,10 @@ def get_invoices(filters, additional_query_columns):
|
|||||||
base_net_total, base_grand_total, base_rounded_total, outstanding_amount,
|
base_net_total, base_grand_total, base_rounded_total, outstanding_amount,
|
||||||
is_internal_customer, represents_company, company {0}
|
is_internal_customer, represents_company, company {0}
|
||||||
from `tabSales Invoice`
|
from `tabSales Invoice`
|
||||||
where docstatus = 1 %s order by posting_date desc, name desc""".format(
|
where docstatus = 1 {1}
|
||||||
additional_query_columns or ""
|
order by posting_date desc, name desc""".format(
|
||||||
)
|
additional_query_columns, conditions
|
||||||
% conditions,
|
),
|
||||||
filters,
|
filters,
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
|
@ -67,8 +67,9 @@ def get_all_transfers(date, shareholder):
|
|||||||
# condition = 'AND company = %(company)s '
|
# condition = 'AND company = %(company)s '
|
||||||
return frappe.db.sql(
|
return frappe.db.sql(
|
||||||
"""SELECT * FROM `tabShare Transfer`
|
"""SELECT * FROM `tabShare Transfer`
|
||||||
WHERE (DATE(date) <= %(date)s AND from_shareholder = %(shareholder)s {condition})
|
WHERE ((DATE(date) <= %(date)s AND from_shareholder = %(shareholder)s {condition})
|
||||||
OR (DATE(date) <= %(date)s AND to_shareholder = %(shareholder)s {condition})
|
OR (DATE(date) <= %(date)s AND to_shareholder = %(shareholder)s {condition}))
|
||||||
|
AND docstatus = 1
|
||||||
ORDER BY date""".format(
|
ORDER BY date""".format(
|
||||||
condition=condition
|
condition=condition
|
||||||
),
|
),
|
||||||
|
@ -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;
|
||||||
|
@ -17,6 +17,7 @@ from erpnext.accounts.report.financial_statements import (
|
|||||||
filter_out_zero_value_rows,
|
filter_out_zero_value_rows,
|
||||||
set_gl_entries_by_account,
|
set_gl_entries_by_account,
|
||||||
)
|
)
|
||||||
|
from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency
|
||||||
|
|
||||||
value_fields = (
|
value_fields = (
|
||||||
"opening_debit",
|
"opening_debit",
|
||||||
@ -116,6 +117,7 @@ def get_data(filters):
|
|||||||
filters,
|
filters,
|
||||||
gl_entries_by_account,
|
gl_entries_by_account,
|
||||||
ignore_closing_entries=not flt(filters.with_period_closing_entry),
|
ignore_closing_entries=not flt(filters.with_period_closing_entry),
|
||||||
|
ignore_opening_entries=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
calculate_values(accounts, gl_entries_by_account, opening_balances)
|
calculate_values(accounts, gl_entries_by_account, opening_balances)
|
||||||
@ -158,6 +160,8 @@ def get_rootwise_opening_balances(filters, report_type):
|
|||||||
accounting_dimensions,
|
accounting_dimensions,
|
||||||
period_closing_voucher=last_period_closing_voucher[0].name,
|
period_closing_voucher=last_period_closing_voucher[0].name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Report getting generate from the mid of a fiscal year
|
||||||
if getdate(last_period_closing_voucher[0].posting_date) < getdate(
|
if getdate(last_period_closing_voucher[0].posting_date) < getdate(
|
||||||
add_days(filters.from_date, -1)
|
add_days(filters.from_date, -1)
|
||||||
):
|
):
|
||||||
@ -178,8 +182,8 @@ def get_rootwise_opening_balances(filters, report_type):
|
|||||||
"opening_credit": 0.0,
|
"opening_credit": 0.0,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
opening[d.account]["opening_debit"] += flt(d.opening_debit)
|
opening[d.account]["opening_debit"] += flt(d.debit)
|
||||||
opening[d.account]["opening_credit"] += flt(d.opening_credit)
|
opening[d.account]["opening_credit"] += flt(d.credit)
|
||||||
|
|
||||||
return opening
|
return opening
|
||||||
|
|
||||||
@ -194,8 +198,11 @@ def get_opening_balance(
|
|||||||
frappe.qb.from_(closing_balance)
|
frappe.qb.from_(closing_balance)
|
||||||
.select(
|
.select(
|
||||||
closing_balance.account,
|
closing_balance.account,
|
||||||
Sum(closing_balance.debit).as_("opening_debit"),
|
closing_balance.account_currency,
|
||||||
Sum(closing_balance.credit).as_("opening_credit"),
|
Sum(closing_balance.debit).as_("debit"),
|
||||||
|
Sum(closing_balance.credit).as_("credit"),
|
||||||
|
Sum(closing_balance.debit_in_account_currency).as_("debit_in_account_currency"),
|
||||||
|
Sum(closing_balance.credit_in_account_currency).as_("credit_in_account_currency"),
|
||||||
)
|
)
|
||||||
.where(
|
.where(
|
||||||
(closing_balance.company == filters.company)
|
(closing_balance.company == filters.company)
|
||||||
@ -216,7 +223,10 @@ def get_opening_balance(
|
|||||||
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)
|
||||||
opening_balance = opening_balance.where(closing_balance.is_opening == "No")
|
opening_balance = opening_balance.where(closing_balance.is_opening == "No")
|
||||||
opening_balance = opening_balance.where(closing_balance.posting_date < filters.from_date)
|
else:
|
||||||
|
opening_balance = opening_balance.where(
|
||||||
|
(closing_balance.posting_date < filters.from_date) | (closing_balance.is_opening == "Yes")
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not filters.show_unclosed_fy_pl_balances
|
not filters.show_unclosed_fy_pl_balances
|
||||||
@ -282,6 +292,9 @@ def get_opening_balance(
|
|||||||
|
|
||||||
gle = opening_balance.run(as_dict=1)
|
gle = opening_balance.run(as_dict=1)
|
||||||
|
|
||||||
|
if filters and filters.get("presentation_currency"):
|
||||||
|
convert_to_presentation_currency(gle, get_currency(filters))
|
||||||
|
|
||||||
return gle
|
return gle
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import flt, formatdate, get_datetime_str
|
from frappe.utils import flt, formatdate, get_datetime_str, get_table_name
|
||||||
|
|
||||||
from erpnext import get_company_currency, get_default_company
|
from erpnext import get_company_currency, get_default_company
|
||||||
from erpnext.accounts.doctype.fiscal_year.fiscal_year import get_from_and_to_date
|
from erpnext.accounts.doctype.fiscal_year.fiscal_year import get_from_and_to_date
|
||||||
@ -78,7 +78,7 @@ def get_rate_as_at(date, from_currency, to_currency):
|
|||||||
return rate
|
return rate
|
||||||
|
|
||||||
|
|
||||||
def convert_to_presentation_currency(gl_entries, currency_info, company):
|
def convert_to_presentation_currency(gl_entries, currency_info):
|
||||||
"""
|
"""
|
||||||
Take a list of GL Entries and change the 'debit' and 'credit' values to currencies
|
Take a list of GL Entries and change the 'debit' and 'credit' values to currencies
|
||||||
in `currency_info`.
|
in `currency_info`.
|
||||||
@ -93,7 +93,6 @@ def convert_to_presentation_currency(gl_entries, currency_info, company):
|
|||||||
account_currencies = list(set(entry["account_currency"] for entry in gl_entries))
|
account_currencies = list(set(entry["account_currency"] for entry in gl_entries))
|
||||||
|
|
||||||
for entry in gl_entries:
|
for entry in gl_entries:
|
||||||
account = entry["account"]
|
|
||||||
debit = flt(entry["debit"])
|
debit = flt(entry["debit"])
|
||||||
credit = flt(entry["credit"])
|
credit = flt(entry["credit"])
|
||||||
debit_in_account_currency = flt(entry["debit_in_account_currency"])
|
debit_in_account_currency = flt(entry["debit_in_account_currency"])
|
||||||
@ -151,3 +150,32 @@ def get_invoiced_item_gross_margin(
|
|||||||
result = sum(d.gross_profit for d in result)
|
result = sum(d.gross_profit for d in result)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_query_columns(report_columns):
|
||||||
|
if not report_columns:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
columns = []
|
||||||
|
for column in report_columns:
|
||||||
|
fieldname = column["fieldname"]
|
||||||
|
|
||||||
|
if doctype := column.get("_doctype"):
|
||||||
|
columns.append(f"`{get_table_name(doctype)}`.`{fieldname}`")
|
||||||
|
else:
|
||||||
|
columns.append(fieldname)
|
||||||
|
|
||||||
|
return ", " + ", ".join(columns)
|
||||||
|
|
||||||
|
|
||||||
|
def get_values_for_columns(report_columns, report_row):
|
||||||
|
values = {}
|
||||||
|
|
||||||
|
if not report_columns:
|
||||||
|
return values
|
||||||
|
|
||||||
|
for column in report_columns:
|
||||||
|
fieldname = column["fieldname"]
|
||||||
|
values[fieldname] = report_row.get(fieldname)
|
||||||
|
|
||||||
|
return values
|
||||||
|
@ -850,7 +850,7 @@ def get_held_invoices(party_type, party):
|
|||||||
|
|
||||||
if party_type == "Supplier":
|
if party_type == "Supplier":
|
||||||
held_invoices = frappe.db.sql(
|
held_invoices = frappe.db.sql(
|
||||||
"select name from `tabPurchase Invoice` where release_date IS NOT NULL and release_date > CURDATE()",
|
"select name from `tabPurchase Invoice` where on_hold = 1 and release_date IS NOT NULL and release_date > CURDATE()",
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
)
|
)
|
||||||
held_invoices = set(d["name"] for d in held_invoices)
|
held_invoices = set(d["name"] for d in held_invoices)
|
||||||
@ -1110,6 +1110,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 (
|
||||||
@ -1408,6 +1413,50 @@ def check_and_delete_linked_reports(report):
|
|||||||
frappe.delete_doc("Desktop Icon", icon)
|
frappe.delete_doc("Desktop Icon", icon)
|
||||||
|
|
||||||
|
|
||||||
|
def create_err_and_its_journals(companies: list = None) -> None:
|
||||||
|
if companies:
|
||||||
|
for company in companies:
|
||||||
|
err = frappe.new_doc("Exchange Rate Revaluation")
|
||||||
|
err.company = company.name
|
||||||
|
err.posting_date = nowdate()
|
||||||
|
err.rounding_loss_allowance = 0.0
|
||||||
|
|
||||||
|
err.fetch_and_calculate_accounts_data()
|
||||||
|
if err.accounts:
|
||||||
|
err.save().submit()
|
||||||
|
response = err.make_jv_entries()
|
||||||
|
|
||||||
|
if company.submit_err_jv:
|
||||||
|
jv = response.get("revaluation_jv", None)
|
||||||
|
jv and frappe.get_doc("Journal Entry", jv).submit()
|
||||||
|
jv = response.get("zero_balance_jv", None)
|
||||||
|
jv and frappe.get_doc("Journal Entry", jv).submit()
|
||||||
|
|
||||||
|
|
||||||
|
def auto_create_exchange_rate_revaluation_daily() -> None:
|
||||||
|
"""
|
||||||
|
Executed by background job
|
||||||
|
"""
|
||||||
|
companies = frappe.db.get_all(
|
||||||
|
"Company",
|
||||||
|
filters={"auto_exchange_rate_revaluation": 1, "auto_err_frequency": "Daily"},
|
||||||
|
fields=["name", "submit_err_jv"],
|
||||||
|
)
|
||||||
|
create_err_and_its_journals(companies)
|
||||||
|
|
||||||
|
|
||||||
|
def auto_create_exchange_rate_revaluation_weekly() -> None:
|
||||||
|
"""
|
||||||
|
Executed by background job
|
||||||
|
"""
|
||||||
|
companies = frappe.db.get_all(
|
||||||
|
"Company",
|
||||||
|
filters={"auto_exchange_rate_revaluation": 1, "auto_err_frequency": "Weekly"},
|
||||||
|
fields=["name", "submit_err_jv"],
|
||||||
|
)
|
||||||
|
create_err_and_its_journals(companies)
|
||||||
|
|
||||||
|
|
||||||
def get_payment_ledger_entries(gl_entries, cancel=0):
|
def get_payment_ledger_entries(gl_entries, cancel=0):
|
||||||
ple_map = []
|
ple_map = []
|
||||||
if gl_entries:
|
if gl_entries:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"label": "Profit and Loss"
|
"label": "Profit and Loss"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"i0EtSjDAXq\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"X78jcbq1u3\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Bank Statement\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"id\":\"OX7lZHbiTr\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
"content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"i0EtSjDAXq\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"X78jcbq1u3\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"iAwpe-Chra\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Accounting\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Bank Statement\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"id\":\"OX7lZHbiTr\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
||||||
"creation": "2020-03-02 15:41:59.515192",
|
"creation": "2020-03-02 15:41:59.515192",
|
||||||
"custom_blocks": [],
|
"custom_blocks": [],
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -1061,7 +1061,7 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-05-30 13:23:29.316711",
|
"modified": "2023-07-04 14:32:15.842044",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounting",
|
"name": "Accounting",
|
||||||
@ -1074,6 +1074,13 @@
|
|||||||
"roles": [],
|
"roles": [],
|
||||||
"sequence_id": 2.0,
|
"sequence_id": 2.0,
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"color": "Grey",
|
||||||
|
"doc_view": "List",
|
||||||
|
"label": "Learn Accounting",
|
||||||
|
"type": "URL",
|
||||||
|
"url": "https://frappe.school/courses/erpnext-accounting?utm_source=in_app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Chart of Accounts",
|
"label": "Chart of Accounts",
|
||||||
"link_to": "Account",
|
"link_to": "Account",
|
||||||
|
@ -40,6 +40,7 @@ def post_depreciation_entries(date=None):
|
|||||||
date = today()
|
date = today()
|
||||||
|
|
||||||
failed_asset_names = []
|
failed_asset_names = []
|
||||||
|
error_log_names = []
|
||||||
|
|
||||||
for asset_name in get_depreciable_assets(date):
|
for asset_name in get_depreciable_assets(date):
|
||||||
asset_doc = frappe.get_doc("Asset", asset_name)
|
asset_doc = frappe.get_doc("Asset", asset_name)
|
||||||
@ -50,10 +51,12 @@ def post_depreciation_entries(date=None):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
frappe.db.rollback()
|
frappe.db.rollback()
|
||||||
failed_asset_names.append(asset_name)
|
failed_asset_names.append(asset_name)
|
||||||
|
error_log = frappe.log_error(e)
|
||||||
|
error_log_names.append(error_log.name)
|
||||||
|
|
||||||
if failed_asset_names:
|
if failed_asset_names:
|
||||||
set_depr_entry_posting_status_for_failed_assets(failed_asset_names)
|
set_depr_entry_posting_status_for_failed_assets(failed_asset_names)
|
||||||
notify_depr_entry_posting_error(failed_asset_names)
|
notify_depr_entry_posting_error(failed_asset_names, error_log_names)
|
||||||
|
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
|
|
||||||
@ -239,7 +242,7 @@ def set_depr_entry_posting_status_for_failed_assets(failed_asset_names):
|
|||||||
frappe.db.set_value("Asset", asset_name, "depr_entry_posting_status", "Failed")
|
frappe.db.set_value("Asset", asset_name, "depr_entry_posting_status", "Failed")
|
||||||
|
|
||||||
|
|
||||||
def notify_depr_entry_posting_error(failed_asset_names):
|
def notify_depr_entry_posting_error(failed_asset_names, error_log_names):
|
||||||
recipients = get_users_with_role("Accounts Manager")
|
recipients = get_users_with_role("Accounts Manager")
|
||||||
|
|
||||||
if not recipients:
|
if not recipients:
|
||||||
@ -247,7 +250,8 @@ def notify_depr_entry_posting_error(failed_asset_names):
|
|||||||
|
|
||||||
subject = _("Error while posting depreciation entries")
|
subject = _("Error while posting depreciation entries")
|
||||||
|
|
||||||
asset_links = get_comma_separated_asset_links(failed_asset_names)
|
asset_links = get_comma_separated_links(failed_asset_names, "Asset")
|
||||||
|
error_log_links = get_comma_separated_links(error_log_names, "Error Log")
|
||||||
|
|
||||||
message = (
|
message = (
|
||||||
_("Hello,")
|
_("Hello,")
|
||||||
@ -257,23 +261,26 @@ def notify_depr_entry_posting_error(failed_asset_names):
|
|||||||
)
|
)
|
||||||
+ "."
|
+ "."
|
||||||
+ "<br><br>"
|
+ "<br><br>"
|
||||||
+ _(
|
+ _("Here are the error logs for the aforementioned failed depreciation entries: {0}").format(
|
||||||
"Please raise a support ticket and share this email, or forward this email to your development team so that they can find the issue in the developer console by manually creating the depreciation entry via the asset's depreciation schedule table."
|
error_log_links
|
||||||
)
|
)
|
||||||
|
+ "."
|
||||||
|
+ "<br><br>"
|
||||||
|
+ _("Please share this email with your support team so that they can find and fix the issue.")
|
||||||
)
|
)
|
||||||
|
|
||||||
frappe.sendmail(recipients=recipients, subject=subject, message=message)
|
frappe.sendmail(recipients=recipients, subject=subject, message=message)
|
||||||
|
|
||||||
|
|
||||||
def get_comma_separated_asset_links(asset_names):
|
def get_comma_separated_links(names, doctype):
|
||||||
asset_links = []
|
links = []
|
||||||
|
|
||||||
for asset_name in asset_names:
|
for name in names:
|
||||||
asset_links.append(get_link_to_form("Asset", asset_name))
|
links.append(get_link_to_form(doctype, name))
|
||||||
|
|
||||||
asset_links = ", ".join(asset_links)
|
links = ", ".join(links)
|
||||||
|
|
||||||
return asset_links
|
return links
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
@ -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,27 +62,18 @@ 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
|
|
||||||
if d.target_location and not d.from_employee:
|
|
||||||
frappe.throw(
|
|
||||||
_("From employee is required while receiving Asset {0} to a target location").format(
|
|
||||||
d.asset
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if d.from_employee and not d.target_location:
|
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
|
_("Target Location is required while receiving Asset {0} from an employee").format(d.asset)
|
||||||
)
|
)
|
||||||
if d.to_employee and d.target_location:
|
elif d.to_employee and d.target_location:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_(
|
_(
|
||||||
"Asset {0} cannot be received at a location and given to employee in a single movement"
|
"Asset {0} cannot be received at a location and given to an employee in a single movement"
|
||||||
).format(d.asset)
|
).format(d.asset)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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'",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -66,8 +66,6 @@ frappe.ui.form.on("Supplier", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Supplier' }
|
|
||||||
|
|
||||||
if (frappe.defaults.get_default("supp_master_name") != "Naming Series") {
|
if (frappe.defaults.get_default("supp_master_name") != "Naming Series") {
|
||||||
frm.toggle_display("naming_series", false);
|
frm.toggle_display("naming_series", false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"label": "Purchase Order Trends"
|
"label": "Purchase Order Trends"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"content": "[{\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Buying\",\"col\":12}},{\"type\":\"chart\",\"data\":{\"chart_name\":\"Purchase Order Trends\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Order\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Analytics\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Order Analysis\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Buying\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Items & Pricing\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Supplier\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Supplier Scorecard\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Regional\",\"col\":4}}]",
|
"content": "[{\"id\":\"I3JijHOxil\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Buying\",\"col\":12}},{\"id\":\"j3dJGo8Ok6\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Purchase Order Trends\",\"col\":12}},{\"id\":\"oN7lXSwQji\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"Ivw1PI_wEJ\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"RrWFEi4kCf\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"id\":\"RFIakryyJP\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Material Request\",\"col\":3}},{\"id\":\"bM10abFmf6\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Order\",\"col\":3}},{\"id\":\"lR0Hw_37Pu\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Analytics\",\"col\":3}},{\"id\":\"_HN0Ljw1lX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Order Analysis\",\"col\":3}},{\"id\":\"kuLuiMRdnX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"tQFeiKptW2\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Procurement\",\"col\":3}},{\"id\":\"0NiuFE_EGS\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"Xe2GVLOq8J\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"QwqyG6XuUt\",\"type\":\"card\",\"data\":{\"card_name\":\"Buying\",\"col\":4}},{\"id\":\"bTPjOxC_N_\",\"type\":\"card\",\"data\":{\"card_name\":\"Items & Pricing\",\"col\":4}},{\"id\":\"87ht0HIneb\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"id\":\"EDOsBOmwgw\",\"type\":\"card\",\"data\":{\"card_name\":\"Supplier\",\"col\":4}},{\"id\":\"oWNNIiNb2i\",\"type\":\"card\",\"data\":{\"card_name\":\"Supplier Scorecard\",\"col\":4}},{\"id\":\"7F_13-ihHB\",\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"id\":\"pfwiLvionl\",\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}},{\"id\":\"8ySDy6s4qn\",\"type\":\"card\",\"data\":{\"card_name\":\"Regional\",\"col\":4}}]",
|
||||||
"creation": "2020-01-28 11:50:26.195467",
|
"creation": "2020-01-28 11:50:26.195467",
|
||||||
"custom_blocks": [],
|
"custom_blocks": [],
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -511,7 +511,7 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-05-24 14:47:20.535772",
|
"modified": "2023-07-04 14:43:30.387683",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Buying",
|
"name": "Buying",
|
||||||
@ -532,6 +532,13 @@
|
|||||||
"stats_filter": "{\n \"disabled\": 0\n}",
|
"stats_filter": "{\n \"disabled\": 0\n}",
|
||||||
"type": "DocType"
|
"type": "DocType"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"color": "Grey",
|
||||||
|
"doc_view": "List",
|
||||||
|
"label": "Learn Procurement",
|
||||||
|
"type": "URL",
|
||||||
|
"url": "https://frappe.school/courses/procurement?utm_source=in_app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"color": "Yellow",
|
"color": "Yellow",
|
||||||
"format": "{} Pending",
|
"format": "{} Pending",
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
"fieldname": "communication_channel",
|
"fieldname": "communication_channel",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Communication Channel",
|
"label": "Communication Channel",
|
||||||
"options": "\nExotel"
|
"options": ""
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
|
@ -437,18 +437,23 @@ class BuyingController(SubcontractingController):
|
|||||||
# validate rate with ref PR
|
# validate rate with ref PR
|
||||||
|
|
||||||
def validate_rejected_warehouse(self):
|
def validate_rejected_warehouse(self):
|
||||||
for d in self.get("items"):
|
for item in self.get("items"):
|
||||||
if flt(d.rejected_qty) and not d.rejected_warehouse:
|
if flt(item.rejected_qty) and not item.rejected_warehouse:
|
||||||
if self.rejected_warehouse:
|
if self.rejected_warehouse:
|
||||||
d.rejected_warehouse = self.rejected_warehouse
|
item.rejected_warehouse = self.rejected_warehouse
|
||||||
|
|
||||||
if not d.rejected_warehouse:
|
if not item.rejected_warehouse:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Row #{0}: Rejected Warehouse is mandatory against rejected Item {1}").format(
|
_("Row #{0}: Rejected Warehouse is mandatory for the rejected Item {1}").format(
|
||||||
d.idx, d.item_code
|
item.idx, item.item_code
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if item.get("rejected_warehouse") and (item.get("rejected_warehouse") == item.get("warehouse")):
|
||||||
|
frappe.throw(
|
||||||
|
_("Row #{0}: Accepted Warehouse and Rejected Warehouse cannot be same").format(item.idx)
|
||||||
|
)
|
||||||
|
|
||||||
# validate accepted and rejected qty
|
# validate accepted and rejected qty
|
||||||
def validate_accepted_rejected_qty(self):
|
def validate_accepted_rejected_qty(self):
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
|
@ -669,7 +669,11 @@ def get_filters(
|
|||||||
if reference_voucher_detail_no:
|
if reference_voucher_detail_no:
|
||||||
filters["voucher_detail_no"] = reference_voucher_detail_no
|
filters["voucher_detail_no"] = reference_voucher_detail_no
|
||||||
|
|
||||||
if item_row and item_row.get("warehouse"):
|
if (
|
||||||
|
voucher_type in ["Purchase Receipt", "Purchase Invoice"]
|
||||||
|
and item_row
|
||||||
|
and item_row.get("warehouse")
|
||||||
|
):
|
||||||
filters["warehouse"] = item_row.get("warehouse")
|
filters["warehouse"] = item_row.get("warehouse")
|
||||||
|
|
||||||
return filters
|
return filters
|
||||||
|
@ -201,6 +201,12 @@ class StockController(AccountsController):
|
|||||||
warehouse_asset_account = warehouse_account[item_row.get("warehouse")]["account"]
|
warehouse_asset_account = warehouse_account[item_row.get("warehouse")]["account"]
|
||||||
|
|
||||||
expense_account = frappe.get_cached_value("Company", self.company, "default_expense_account")
|
expense_account = frappe.get_cached_value("Company", self.company, "default_expense_account")
|
||||||
|
if not expense_account:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Please set default cost of goods sold account in company {0} for booking rounding gain and loss during stock transfer"
|
||||||
|
).format(frappe.bold(self.company))
|
||||||
|
)
|
||||||
|
|
||||||
gl_list.append(
|
gl_list.append(
|
||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
|
@ -30,11 +30,6 @@ erpnext.LeadController = class LeadController extends frappe.ui.form.Controller
|
|||||||
var me = this;
|
var me = this;
|
||||||
let doc = this.frm.doc;
|
let doc = this.frm.doc;
|
||||||
erpnext.toggle_naming_series();
|
erpnext.toggle_naming_series();
|
||||||
frappe.dynamic_link = {
|
|
||||||
doc: doc,
|
|
||||||
fieldname: 'name',
|
|
||||||
doctype: 'Lead'
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!this.frm.is_new() && doc.__onload && !doc.__onload.is_customer) {
|
if (!this.frm.is_new() && doc.__onload && !doc.__onload.is_customer) {
|
||||||
this.frm.add_custom_button(__("Customer"), this.make_customer, __("Create"));
|
this.frm.add_custom_button(__("Customer"), this.make_customer, __("Create"));
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Prospect', {
|
frappe.ui.form.on('Prospect', {
|
||||||
refresh (frm) {
|
refresh (frm) {
|
||||||
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: frm.doctype };
|
|
||||||
|
|
||||||
if (!frm.is_new() && frappe.boot.user.can_create.includes("Customer")) {
|
if (!frm.is_new() && frappe.boot.user.can_create.includes("Customer")) {
|
||||||
frm.add_custom_button(__("Customer"), function() {
|
frm.add_custom_button(__("Customer"), function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"creation": "2019-05-21 07:41:53.536536",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"enabled",
|
|
||||||
"section_break_2",
|
|
||||||
"account_sid",
|
|
||||||
"api_key",
|
|
||||||
"api_token",
|
|
||||||
"section_break_6",
|
|
||||||
"map_custom_field_to_doctype",
|
|
||||||
"target_doctype"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "enabled",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Enabled"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "enabled",
|
|
||||||
"fieldname": "section_break_2",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Credentials"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "account_sid",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Account SID"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "api_token",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "API Token"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "api_key",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "API Key"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "enabled",
|
|
||||||
"fieldname": "section_break_6",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Custom Field"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "map_custom_field_to_doctype",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Map Custom Field to DocType"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "map_custom_field_to_doctype",
|
|
||||||
"fieldname": "target_doctype",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Target DocType",
|
|
||||||
"mandatory_depends_on": "map_custom_field_to_doctype",
|
|
||||||
"options": "DocType"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"issingle": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2022-12-14 17:24:50.176107",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "ERPNext Integrations",
|
|
||||||
"name": "Exotel Settings",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"role": "System Manager",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"quick_entry": 1,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "ASC",
|
|
||||||
"states": [],
|
|
||||||
"track_changes": 1
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
import requests
|
|
||||||
from frappe import _
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class ExotelSettings(Document):
|
|
||||||
def validate(self):
|
|
||||||
self.verify_credentials()
|
|
||||||
|
|
||||||
def verify_credentials(self):
|
|
||||||
if self.enabled:
|
|
||||||
response = requests.get(
|
|
||||||
"https://api.exotel.com/v1/Accounts/{sid}".format(sid=self.account_sid),
|
|
||||||
auth=(self.api_key, self.api_token),
|
|
||||||
)
|
|
||||||
if response.status_code != 200:
|
|
||||||
frappe.throw(_("Invalid credentials"))
|
|
@ -1,151 +0,0 @@
|
|||||||
import frappe
|
|
||||||
import requests
|
|
||||||
|
|
||||||
# api/method/erpnext.erpnext_integrations.exotel_integration.handle_incoming_call
|
|
||||||
# api/method/erpnext.erpnext_integrations.exotel_integration.handle_end_call
|
|
||||||
# api/method/erpnext.erpnext_integrations.exotel_integration.handle_missed_call
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
|
||||||
def handle_incoming_call(**kwargs):
|
|
||||||
try:
|
|
||||||
exotel_settings = get_exotel_settings()
|
|
||||||
if not exotel_settings.enabled:
|
|
||||||
return
|
|
||||||
|
|
||||||
call_payload = kwargs
|
|
||||||
status = call_payload.get("Status")
|
|
||||||
if status == "free":
|
|
||||||
return
|
|
||||||
|
|
||||||
call_log = get_call_log(call_payload)
|
|
||||||
if not call_log:
|
|
||||||
create_call_log(call_payload)
|
|
||||||
else:
|
|
||||||
update_call_log(call_payload, call_log=call_log)
|
|
||||||
except Exception as e:
|
|
||||||
frappe.db.rollback()
|
|
||||||
exotel_settings.log_error("Error in Exotel incoming call")
|
|
||||||
frappe.db.commit()
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
|
||||||
def handle_end_call(**kwargs):
|
|
||||||
update_call_log(kwargs, "Completed")
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
|
||||||
def handle_missed_call(**kwargs):
|
|
||||||
status = ""
|
|
||||||
call_type = kwargs.get("CallType")
|
|
||||||
dial_call_status = kwargs.get("DialCallStatus")
|
|
||||||
|
|
||||||
if call_type == "incomplete" and dial_call_status == "no-answer":
|
|
||||||
status = "No Answer"
|
|
||||||
elif call_type == "client-hangup" and dial_call_status == "canceled":
|
|
||||||
status = "Canceled"
|
|
||||||
elif call_type == "incomplete" and dial_call_status == "failed":
|
|
||||||
status = "Failed"
|
|
||||||
|
|
||||||
update_call_log(kwargs, status)
|
|
||||||
|
|
||||||
|
|
||||||
def update_call_log(call_payload, status="Ringing", call_log=None):
|
|
||||||
call_log = call_log or get_call_log(call_payload)
|
|
||||||
|
|
||||||
# for a new sid, call_log and get_call_log will be empty so create a new log
|
|
||||||
if not call_log:
|
|
||||||
call_log = create_call_log(call_payload)
|
|
||||||
if call_log:
|
|
||||||
call_log.status = status
|
|
||||||
call_log.to = call_payload.get("DialWhomNumber")
|
|
||||||
call_log.duration = call_payload.get("DialCallDuration") or 0
|
|
||||||
call_log.recording_url = call_payload.get("RecordingUrl")
|
|
||||||
call_log.save(ignore_permissions=True)
|
|
||||||
frappe.db.commit()
|
|
||||||
return call_log
|
|
||||||
|
|
||||||
|
|
||||||
def get_call_log(call_payload):
|
|
||||||
call_log_id = call_payload.get("CallSid")
|
|
||||||
if frappe.db.exists("Call Log", call_log_id):
|
|
||||||
return frappe.get_doc("Call Log", call_log_id)
|
|
||||||
|
|
||||||
|
|
||||||
def map_custom_field(call_payload, call_log):
|
|
||||||
field_value = call_payload.get("CustomField")
|
|
||||||
|
|
||||||
if not field_value:
|
|
||||||
return call_log
|
|
||||||
|
|
||||||
settings = get_exotel_settings()
|
|
||||||
target_doctype = settings.target_doctype
|
|
||||||
mapping_enabled = settings.map_custom_field_to_doctype
|
|
||||||
|
|
||||||
if not mapping_enabled or not target_doctype:
|
|
||||||
return call_log
|
|
||||||
|
|
||||||
call_log.append("links", {"link_doctype": target_doctype, "link_name": field_value})
|
|
||||||
|
|
||||||
return call_log
|
|
||||||
|
|
||||||
|
|
||||||
def create_call_log(call_payload):
|
|
||||||
call_log = frappe.new_doc("Call Log")
|
|
||||||
call_log.id = call_payload.get("CallSid")
|
|
||||||
call_log.to = call_payload.get("DialWhomNumber")
|
|
||||||
call_log.medium = call_payload.get("To")
|
|
||||||
call_log.status = "Ringing"
|
|
||||||
setattr(call_log, "from", call_payload.get("CallFrom"))
|
|
||||||
map_custom_field(call_payload, call_log)
|
|
||||||
call_log.save(ignore_permissions=True)
|
|
||||||
frappe.db.commit()
|
|
||||||
return call_log
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def get_call_status(call_id):
|
|
||||||
endpoint = get_exotel_endpoint("Calls/{call_id}.json".format(call_id=call_id))
|
|
||||||
response = requests.get(endpoint)
|
|
||||||
status = response.json().get("Call", {}).get("Status")
|
|
||||||
return status
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def make_a_call(from_number, to_number, caller_id, **kwargs):
|
|
||||||
endpoint = get_exotel_endpoint("Calls/connect.json?details=true")
|
|
||||||
response = requests.post(
|
|
||||||
endpoint, data={"From": from_number, "To": to_number, "CallerId": caller_id, **kwargs}
|
|
||||||
)
|
|
||||||
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
|
|
||||||
def get_exotel_settings():
|
|
||||||
return frappe.get_single("Exotel Settings")
|
|
||||||
|
|
||||||
|
|
||||||
def whitelist_numbers(numbers, caller_id):
|
|
||||||
endpoint = get_exotel_endpoint("CustomerWhitelist")
|
|
||||||
response = requests.post(
|
|
||||||
endpoint,
|
|
||||||
data={
|
|
||||||
"VirtualNumber": caller_id,
|
|
||||||
"Number": numbers,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def get_all_exophones():
|
|
||||||
endpoint = get_exotel_endpoint("IncomingPhoneNumbers")
|
|
||||||
response = requests.post(endpoint)
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def get_exotel_endpoint(action):
|
|
||||||
settings = get_exotel_settings()
|
|
||||||
return "https://{api_key}:{api_token}@api.exotel.com/v1/Accounts/{sid}/{action}".format(
|
|
||||||
api_key=settings.api_key, api_token=settings.api_token, sid=settings.account_sid, action=action
|
|
||||||
)
|
|
@ -230,17 +230,6 @@
|
|||||||
"onboard": 0,
|
"onboard": 0,
|
||||||
"type": "Card Break"
|
"type": "Card Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"dependencies": "",
|
|
||||||
"hidden": 0,
|
|
||||||
"is_query_report": 0,
|
|
||||||
"label": "Exotel Settings",
|
|
||||||
"link_count": 0,
|
|
||||||
"link_to": "Exotel Settings",
|
|
||||||
"link_type": "DocType",
|
|
||||||
"onboard": 0,
|
|
||||||
"type": "Link"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"hidden": 0,
|
"hidden": 0,
|
||||||
"is_query_report": 0,
|
"is_query_report": 0,
|
||||||
@ -252,7 +241,7 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-05-24 14:47:25.984717",
|
"modified": "2023-05-24 14:47:26.984717",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "ERPNext Integrations",
|
"module": "ERPNext Integrations",
|
||||||
"name": "ERPNext Integrations",
|
"name": "ERPNext Integrations",
|
||||||
|
@ -83,7 +83,7 @@ update_website_context = [
|
|||||||
my_account_context = "erpnext.e_commerce.shopping_cart.utils.update_my_account_context"
|
my_account_context = "erpnext.e_commerce.shopping_cart.utils.update_my_account_context"
|
||||||
webform_list_context = "erpnext.controllers.website_list_for_contact.get_webform_list_context"
|
webform_list_context = "erpnext.controllers.website_list_for_contact.get_webform_list_context"
|
||||||
|
|
||||||
calendars = ["Task", "Work Order", "Leave Application", "Sales Order", "Holiday List", "ToDo"]
|
calendars = ["Task", "Work Order", "Sales Order", "Holiday List", "ToDo"]
|
||||||
|
|
||||||
website_generators = ["Item Group", "Website Item", "BOM", "Sales Partner"]
|
website_generators = ["Item Group", "Website Item", "BOM", "Sales Partner"]
|
||||||
|
|
||||||
@ -355,6 +355,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.
|
||||||
@ -416,6 +421,10 @@ scheduler_events = {
|
|||||||
"erpnext.selling.doctype.quotation.quotation.set_expired_status",
|
"erpnext.selling.doctype.quotation.quotation.set_expired_status",
|
||||||
"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status",
|
"erpnext.buying.doctype.supplier_quotation.supplier_quotation.set_expired_status",
|
||||||
"erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email",
|
"erpnext.accounts.doctype.process_statement_of_accounts.process_statement_of_accounts.send_auto_email",
|
||||||
|
"erpnext.accounts.utils.auto_create_exchange_rate_revaluation_daily",
|
||||||
|
],
|
||||||
|
"weekly": [
|
||||||
|
"erpnext.accounts.utils.auto_create_exchange_rate_revaluation_weekly",
|
||||||
],
|
],
|
||||||
"daily_long": [
|
"daily_long": [
|
||||||
"erpnext.setup.doctype.email_digest.email_digest.send",
|
"erpnext.setup.doctype.email_digest.email_digest.send",
|
||||||
@ -608,3 +617,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",
|
||||||
|
]
|
||||||
|
@ -621,7 +621,7 @@ class ProductionPlan(Document):
|
|||||||
def create_work_order(self, item):
|
def create_work_order(self, item):
|
||||||
from erpnext.manufacturing.doctype.work_order.work_order import OverProductionError
|
from erpnext.manufacturing.doctype.work_order.work_order import OverProductionError
|
||||||
|
|
||||||
if item.get("qty") <= 0:
|
if flt(item.get("qty")) <= 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
wo = frappe.new_doc("Work Order")
|
wo = frappe.new_doc("Work Order")
|
||||||
@ -697,10 +697,9 @@ class ProductionPlan(Document):
|
|||||||
material_request.flags.ignore_permissions = 1
|
material_request.flags.ignore_permissions = 1
|
||||||
material_request.run_method("set_missing_values")
|
material_request.run_method("set_missing_values")
|
||||||
|
|
||||||
|
material_request.save()
|
||||||
if self.get("submit_material_request"):
|
if self.get("submit_material_request"):
|
||||||
material_request.submit()
|
material_request.submit()
|
||||||
else:
|
|
||||||
material_request.save()
|
|
||||||
|
|
||||||
frappe.flags.mute_messages = False
|
frappe.flags.mute_messages = False
|
||||||
|
|
||||||
|
@ -1026,7 +1026,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;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"charts": [],
|
"charts": [],
|
||||||
"content": "[{\"id\":\"csBCiDglCE\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"xit0dg7KvY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM\",\"col\":3}},{\"id\":\"LRhGV9GAov\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Plan\",\"col\":3}},{\"id\":\"69KKosI6Hg\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order\",\"col\":3}},{\"id\":\"PwndxuIpB3\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Job Card\",\"col\":3}},{\"id\":\"OaiDqTT03Y\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Forecasting\",\"col\":3}},{\"id\":\"OtMcArFRa5\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Stock Report\",\"col\":3}},{\"id\":\"76yYsI5imF\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Planning Report\",\"col\":3}},{\"id\":\"bN_6tHS-Ct\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yVEFZMqVwd\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"rwrmsTI58-\",\"type\":\"card\",\"data\":{\"card_name\":\"Production\",\"col\":4}},{\"id\":\"6dnsyX-siZ\",\"type\":\"card\",\"data\":{\"card_name\":\"Bill of Materials\",\"col\":4}},{\"id\":\"CIq-v5f5KC\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"8RRiQeYr0G\",\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"id\":\"Pu8z7-82rT\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
"content": "[{\"id\":\"csBCiDglCE\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"xit0dg7KvY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM\",\"col\":3}},{\"id\":\"LRhGV9GAov\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Plan\",\"col\":3}},{\"id\":\"69KKosI6Hg\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order\",\"col\":3}},{\"id\":\"PwndxuIpB3\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Job Card\",\"col\":3}},{\"id\":\"OaiDqTT03Y\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Forecasting\",\"col\":3}},{\"id\":\"OtMcArFRa5\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Stock Report\",\"col\":3}},{\"id\":\"76yYsI5imF\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Planning Report\",\"col\":3}},{\"id\":\"PIQJYZOMnD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Manufacturing\",\"col\":3}},{\"id\":\"bN_6tHS-Ct\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yVEFZMqVwd\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"rwrmsTI58-\",\"type\":\"card\",\"data\":{\"card_name\":\"Production\",\"col\":4}},{\"id\":\"6dnsyX-siZ\",\"type\":\"card\",\"data\":{\"card_name\":\"Bill of Materials\",\"col\":4}},{\"id\":\"CIq-v5f5KC\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"8RRiQeYr0G\",\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"id\":\"Pu8z7-82rT\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
||||||
"creation": "2020-03-02 17:11:37.032604",
|
"creation": "2020-03-02 17:11:37.032604",
|
||||||
"custom_blocks": [],
|
"custom_blocks": [],
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -316,7 +316,7 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-05-27 16:41:04.776115",
|
"modified": "2023-07-04 14:40:47.281125",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Manufacturing",
|
"name": "Manufacturing",
|
||||||
@ -329,6 +329,13 @@
|
|||||||
"roles": [],
|
"roles": [],
|
||||||
"sequence_id": 8.0,
|
"sequence_id": 8.0,
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"color": "Grey",
|
||||||
|
"doc_view": "List",
|
||||||
|
"label": "Learn Manufacturing",
|
||||||
|
"type": "URL",
|
||||||
|
"url": "https://frappe.school/courses/manufacturing?utm_source=in_app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"color": "Grey",
|
"color": "Grey",
|
||||||
"doc_view": "List",
|
"doc_view": "List",
|
||||||
|
@ -317,7 +317,7 @@ erpnext.patches.v13_0.update_docs_link
|
|||||||
erpnext.patches.v15_0.update_asset_value_for_manual_depr_entries
|
erpnext.patches.v15_0.update_asset_value_for_manual_depr_entries
|
||||||
erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
|
erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
|
||||||
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 #17-05-2023
|
erpnext.patches.v14_0.update_closing_balances #14-07-2023
|
||||||
execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
|
execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
|
||||||
# below migration patches should always run last
|
# below migration patches should always run last
|
||||||
erpnext.patches.v14_0.migrate_gl_to_payment_ledger
|
erpnext.patches.v14_0.migrate_gl_to_payment_ledger
|
||||||
@ -334,4 +334,6 @@ erpnext.patches.v14_0.cleanup_workspaces
|
|||||||
erpnext.patches.v15_0.remove_loan_management_module #2023-07-03
|
erpnext.patches.v15_0.remove_loan_management_module #2023-07-03
|
||||||
erpnext.patches.v14_0.set_report_in_process_SOA
|
erpnext.patches.v14_0.set_report_in_process_SOA
|
||||||
erpnext.buying.doctype.supplier.patches.migrate_supplier_portal_users
|
erpnext.buying.doctype.supplier.patches.migrate_supplier_portal_users
|
||||||
|
execute:frappe.defaults.clear_default("fiscal_year")
|
||||||
|
erpnext.patches.v15_0.remove_exotel_integration
|
||||||
erpnext.patches.v14_0.single_to_multi_dunning
|
erpnext.patches.v14_0.single_to_multi_dunning
|
||||||
|
@ -13,12 +13,13 @@ from erpnext.accounts.utils import get_fiscal_year
|
|||||||
def execute():
|
def execute():
|
||||||
frappe.db.truncate("Account Closing Balance")
|
frappe.db.truncate("Account Closing Balance")
|
||||||
|
|
||||||
|
for company in frappe.get_all("Company", pluck="name"):
|
||||||
i = 0
|
i = 0
|
||||||
company_wise_order = {}
|
company_wise_order = {}
|
||||||
for pcv in frappe.db.get_all(
|
for pcv in frappe.db.get_all(
|
||||||
"Period Closing Voucher",
|
"Period Closing Voucher",
|
||||||
fields=["company", "posting_date", "name"],
|
fields=["company", "posting_date", "name"],
|
||||||
filters={"docstatus": 1},
|
filters={"docstatus": 1, "company": company},
|
||||||
order_by="posting_date",
|
order_by="posting_date",
|
||||||
):
|
):
|
||||||
|
|
||||||
@ -38,6 +39,9 @@ def execute():
|
|||||||
entry["closing_date"] = pcv_doc.posting_date
|
entry["closing_date"] = pcv_doc.posting_date
|
||||||
entry["period_closing_voucher"] = pcv_doc.name
|
entry["period_closing_voucher"] = pcv_doc.name
|
||||||
|
|
||||||
|
closing_entries = []
|
||||||
|
|
||||||
|
if pcv.posting_date not in company_wise_order[pcv.company]:
|
||||||
# get all gl entries for the year
|
# get all gl entries for the year
|
||||||
closing_entries = frappe.db.get_all(
|
closing_entries = frappe.db.get_all(
|
||||||
"GL Entry",
|
"GL Entry",
|
||||||
@ -46,6 +50,7 @@ def execute():
|
|||||||
"voucher_no": ["!=", pcv.name],
|
"voucher_no": ["!=", pcv.name],
|
||||||
"posting_date": ["between", [pcv_doc.year_start_date, pcv.posting_date]],
|
"posting_date": ["between", [pcv_doc.year_start_date, pcv.posting_date]],
|
||||||
"is_opening": "No",
|
"is_opening": "No",
|
||||||
|
"company": company,
|
||||||
},
|
},
|
||||||
fields=["*"],
|
fields=["*"],
|
||||||
)
|
)
|
||||||
@ -54,7 +59,7 @@ def execute():
|
|||||||
# add opening entries only for the first pcv
|
# add opening entries only for the first pcv
|
||||||
closing_entries += frappe.db.get_all(
|
closing_entries += frappe.db.get_all(
|
||||||
"GL Entry",
|
"GL Entry",
|
||||||
filters={"is_cancelled": 0, "is_opening": "Yes"},
|
filters={"is_cancelled": 0, "is_opening": "Yes", "company": company},
|
||||||
fields=["*"],
|
fields=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -62,7 +67,9 @@ def execute():
|
|||||||
entry["closing_date"] = pcv_doc.posting_date
|
entry["closing_date"] = pcv_doc.posting_date
|
||||||
entry["period_closing_voucher"] = pcv_doc.name
|
entry["period_closing_voucher"] = pcv_doc.name
|
||||||
|
|
||||||
make_closing_entries(gl_entries + closing_entries, voucher_name=pcv.name)
|
entries = gl_entries + closing_entries
|
||||||
company_wise_order[pcv.company].append(pcv.posting_date)
|
|
||||||
|
|
||||||
|
if entries:
|
||||||
|
make_closing_entries(entries, voucher_name=pcv.name)
|
||||||
i += 1
|
i += 1
|
||||||
|
company_wise_order[pcv.company].append(pcv.posting_date)
|
||||||
|
37
erpnext/patches/v15_0/remove_exotel_integration.py
Normal file
37
erpnext/patches/v15_0/remove_exotel_integration.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
from contextlib import suppress
|
||||||
|
|
||||||
|
import click
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.desk.doctype.notification_log.notification_log import make_notification_logs
|
||||||
|
from frappe.utils.user import get_system_managers
|
||||||
|
|
||||||
|
SETTINGS_DOCTYPE = "Exotel Settings"
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if "exotel_integration" in frappe.get_installed_apps():
|
||||||
|
return
|
||||||
|
|
||||||
|
with suppress(Exception):
|
||||||
|
exotel = frappe.get_doc(SETTINGS_DOCTYPE)
|
||||||
|
if exotel.enabled:
|
||||||
|
notify_existing_users()
|
||||||
|
|
||||||
|
frappe.delete_doc("DocType", SETTINGS_DOCTYPE)
|
||||||
|
|
||||||
|
|
||||||
|
def notify_existing_users():
|
||||||
|
click.secho(
|
||||||
|
"Exotel integration is moved to a separate app and will be removed from ERPNext in version-15.\n"
|
||||||
|
"Please install the app to continue using the integration: https://github.com/frappe/exotel_integration",
|
||||||
|
fg="yellow",
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = {
|
||||||
|
"subject": _(
|
||||||
|
"WARNING: Exotel app has been separated from ERPNext, please install the app to continue using Exotel integration."
|
||||||
|
),
|
||||||
|
"type": "Alert",
|
||||||
|
}
|
||||||
|
make_notification_logs(notification, get_system_managers(only_name=True))
|
@ -5,7 +5,7 @@
|
|||||||
"label": "Open Projects"
|
"label": "Open Projects"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"content": "[{\"type\":\"chart\",\"data\":{\"chart_name\":\"Open Projects\",\"col\":12}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Task\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Project\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Timesheet\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Project Billing Summary\",\"col\":3}},{\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"type\":\"spacer\",\"data\":{\"col\":12}},{\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"type\":\"card\",\"data\":{\"card_name\":\"Projects\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Time Tracking\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
"content": "[{\"id\":\"VDMms0hapk\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Open Projects\",\"col\":12}},{\"id\":\"7Mbx6I5JUf\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"nyuMo9byw7\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"dILbX_r0ve\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Task\",\"col\":3}},{\"id\":\"JT8ntrqRiJ\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Project\",\"col\":3}},{\"id\":\"RsafDhm1MS\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Timesheet\",\"col\":3}},{\"id\":\"cVJH-gD0CR\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Project Billing Summary\",\"col\":3}},{\"id\":\"DbctrdmAy1\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"jx5aPK9aXN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Project Management\",\"col\":3}},{\"id\":\"ncIHWGQQvX\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"oGhjvYjfv-\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"TdsgJyG3EI\",\"type\":\"card\",\"data\":{\"card_name\":\"Projects\",\"col\":4}},{\"id\":\"nIc0iyvf1T\",\"type\":\"card\",\"data\":{\"card_name\":\"Time Tracking\",\"col\":4}},{\"id\":\"8G1if4jsQ7\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"o7qTNRXZI8\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
|
||||||
"creation": "2020-03-02 15:46:04.874669",
|
"creation": "2020-03-02 15:46:04.874669",
|
||||||
"custom_blocks": [],
|
"custom_blocks": [],
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -192,7 +192,7 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-05-24 14:47:23.179860",
|
"modified": "2023-07-04 14:39:08.935853",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Projects",
|
"name": "Projects",
|
||||||
@ -205,6 +205,13 @@
|
|||||||
"roles": [],
|
"roles": [],
|
||||||
"sequence_id": 11.0,
|
"sequence_id": 11.0,
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"color": "Grey",
|
||||||
|
"doc_view": "List",
|
||||||
|
"label": "Learn Project Management",
|
||||||
|
"type": "URL",
|
||||||
|
"url": "https://frappe.school/courses/project-management?utm_source=in_app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"color": "Blue",
|
"color": "Blue",
|
||||||
"format": "{} Assigned",
|
"format": "{} Assigned",
|
||||||
|
@ -358,12 +358,14 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
|
|
||||||
erpnext.toggle_naming_series();
|
erpnext.toggle_naming_series();
|
||||||
erpnext.hide_company();
|
erpnext.hide_company();
|
||||||
this.set_dynamic_labels();
|
this.set_dynamic_labels();
|
||||||
this.setup_sms();
|
this.setup_sms();
|
||||||
this.setup_quality_inspection();
|
this.setup_quality_inspection();
|
||||||
this.validate_has_items();
|
this.validate_has_items();
|
||||||
|
erpnext.utils.view_serial_batch_nos(this.frm);
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_barcode() {
|
scan_barcode() {
|
||||||
|
@ -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")
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -113,6 +113,23 @@ $.extend(erpnext.utils, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
view_serial_batch_nos: function(frm) {
|
||||||
|
let bundle_ids = frm.doc.items.filter(d => d.serial_and_batch_bundle);
|
||||||
|
|
||||||
|
if (bundle_ids?.length) {
|
||||||
|
frm.add_custom_button(__('Serial / Batch Nos'), () => {
|
||||||
|
frappe.route_options = {
|
||||||
|
"voucher_no": frm.doc.name,
|
||||||
|
"voucher_type": frm.doc.doctype,
|
||||||
|
"from_date": frm.doc.posting_date || frm.doc.transaction_date,
|
||||||
|
"to_date": frm.doc.posting_date || frm.doc.transaction_date,
|
||||||
|
"company": frm.doc.company,
|
||||||
|
};
|
||||||
|
frappe.set_route("query-report", "Serial and Batch Summary");
|
||||||
|
}, __('View'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
add_indicator_for_multicompany: function(frm, info) {
|
add_indicator_for_multicompany: function(frm, info) {
|
||||||
frm.dashboard.stats_area.show();
|
frm.dashboard.stats_area.show();
|
||||||
frm.dashboard.stats_area_row.addClass('flex');
|
frm.dashboard.stats_area_row.addClass('flex');
|
||||||
@ -381,6 +398,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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -632,7 +666,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')
|
||||||
})
|
})
|
||||||
@ -640,6 +673,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",
|
||||||
@ -854,13 +888,7 @@ $(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',
|
|
||||||
callback: function(r) {
|
|
||||||
if (!r.message)
|
|
||||||
return;
|
|
||||||
|
|
||||||
$.each(r.message, function(_i, d) {
|
|
||||||
frappe.ui.form.on(d, {
|
frappe.ui.form.on(d, {
|
||||||
onload: function(frm) {
|
onload: function(frm) {
|
||||||
if (!frm.doc.service_level_agreement)
|
if (!frm.doc.service_level_agreement)
|
||||||
@ -942,8 +970,6 @@ $(document).on('app_ready', function() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function set_time_to_resolve_and_response(frm, apply_sla_for_resolution) {
|
function set_time_to_resolve_and_response(frm, apply_sla_for_resolution) {
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
|
@ -131,8 +131,6 @@ frappe.ui.form.on("Customer", {
|
|||||||
erpnext.toggle_naming_series();
|
erpnext.toggle_naming_series();
|
||||||
}
|
}
|
||||||
|
|
||||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Customer'}
|
|
||||||
|
|
||||||
if(!frm.doc.__islocal) {
|
if(!frm.doc.__islocal) {
|
||||||
frappe.contacts.render_address_and_contact(frm);
|
frappe.contacts.render_address_and_contact(frm);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"label": "Sales Order Trends"
|
"label": "Sales Order Trends"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"content": "[{\"id\":\"ow595dYDrI\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Selling\",\"col\":12}},{\"id\":\"vBSf8Vi9U8\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Sales Order Trends\",\"col\":12}},{\"id\":\"aW2i5R5GRP\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"1it3dCOnm6\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Quick Access</b></span>\",\"col\":12}},{\"id\":\"x7pLl-spS4\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"id\":\"SSGrXWmY-H\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Order\",\"col\":3}},{\"id\":\"-5J_yLxDaS\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Analytics\",\"col\":3}},{\"id\":\"6YEYpnIBKV\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Point of Sale\",\"col\":3}},{\"id\":\"c_GjZuZ2oN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"oNjjNbnUHp\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"0BcePLg0g1\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"uze5dJ1ipL\",\"type\":\"card\",\"data\":{\"card_name\":\"Selling\",\"col\":4}},{\"id\":\"3j2fYwMAkq\",\"type\":\"card\",\"data\":{\"card_name\":\"Point of Sale\",\"col\":4}},{\"id\":\"xImm8NepFt\",\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"id\":\"6MjIe7KCQo\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"id\":\"lBu2EKgmJF\",\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"id\":\"1ARHrjg4kI\",\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
|
"content": "[{\"id\":\"ow595dYDrI\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Selling\",\"col\":12}},{\"id\":\"vBSf8Vi9U8\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Sales Order Trends\",\"col\":12}},{\"id\":\"aW2i5R5GRP\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"1it3dCOnm6\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Quick Access</b></span>\",\"col\":12}},{\"id\":\"x7pLl-spS4\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Item\",\"col\":3}},{\"id\":\"SSGrXWmY-H\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Order\",\"col\":3}},{\"id\":\"-5J_yLxDaS\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Analytics\",\"col\":3}},{\"id\":\"6YEYpnIBKV\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Point of Sale\",\"col\":3}},{\"id\":\"c_GjZuZ2oN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"mX-9DJSyT2\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Sales Management\",\"col\":3}},{\"id\":\"oNjjNbnUHp\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"0BcePLg0g1\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports & Masters</b></span>\",\"col\":12}},{\"id\":\"uze5dJ1ipL\",\"type\":\"card\",\"data\":{\"card_name\":\"Selling\",\"col\":4}},{\"id\":\"3j2fYwMAkq\",\"type\":\"card\",\"data\":{\"card_name\":\"Point of Sale\",\"col\":4}},{\"id\":\"xImm8NepFt\",\"type\":\"card\",\"data\":{\"card_name\":\"Items and Pricing\",\"col\":4}},{\"id\":\"6MjIe7KCQo\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"id\":\"lBu2EKgmJF\",\"type\":\"card\",\"data\":{\"card_name\":\"Key Reports\",\"col\":4}},{\"id\":\"1ARHrjg4kI\",\"type\":\"card\",\"data\":{\"card_name\":\"Other Reports\",\"col\":4}}]",
|
||||||
"creation": "2020-01-28 11:49:12.092882",
|
"creation": "2020-01-28 11:49:12.092882",
|
||||||
"custom_blocks": [],
|
"custom_blocks": [],
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
@ -621,7 +621,7 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2023-05-26 16:31:53.634851",
|
"modified": "2023-07-04 14:35:58.204465",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Selling",
|
"name": "Selling",
|
||||||
@ -634,6 +634,13 @@
|
|||||||
"roles": [],
|
"roles": [],
|
||||||
"sequence_id": 6.0,
|
"sequence_id": 6.0,
|
||||||
"shortcuts": [
|
"shortcuts": [
|
||||||
|
{
|
||||||
|
"color": "Grey",
|
||||||
|
"doc_view": "List",
|
||||||
|
"label": "Learn Sales Management",
|
||||||
|
"type": "URL",
|
||||||
|
"url": "https://frappe.school/courses/sales-management-course?utm_source=in_app"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Point of Sale",
|
"label": "Point of Sale",
|
||||||
"link_to": "point-of-sale",
|
"link_to": "point-of-sale",
|
||||||
|
@ -81,8 +81,6 @@ frappe.ui.form.on("Company", {
|
|||||||
disbale_coa_fields(frm);
|
disbale_coa_fields(frm);
|
||||||
frappe.contacts.render_address_and_contact(frm);
|
frappe.contacts.render_address_and_contact(frm);
|
||||||
|
|
||||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Company'}
|
|
||||||
|
|
||||||
if (frappe.perm.has_perm("Cost Center", 0, 'read')) {
|
if (frappe.perm.has_perm("Cost Center", 0, 'read')) {
|
||||||
frm.add_custom_button(__('Cost Centers'), function() {
|
frm.add_custom_button(__('Cost Centers'), function() {
|
||||||
frappe.set_route('Tree', 'Cost Center', {'company': frm.doc.name});
|
frappe.set_route('Tree', 'Cost Center', {'company': frm.doc.name});
|
||||||
|
@ -95,6 +95,10 @@
|
|||||||
"depreciation_cost_center",
|
"depreciation_cost_center",
|
||||||
"capital_work_in_progress_account",
|
"capital_work_in_progress_account",
|
||||||
"asset_received_but_not_billed",
|
"asset_received_but_not_billed",
|
||||||
|
"exchange_rate_revaluation_settings_section",
|
||||||
|
"auto_exchange_rate_revaluation",
|
||||||
|
"auto_err_frequency",
|
||||||
|
"submit_err_jv",
|
||||||
"budget_detail",
|
"budget_detail",
|
||||||
"exception_budget_approver_role",
|
"exception_budget_approver_role",
|
||||||
"registration_info",
|
"registration_info",
|
||||||
@ -731,6 +735,29 @@
|
|||||||
"fieldname": "book_advance_payments_in_separate_party_account",
|
"fieldname": "book_advance_payments_in_separate_party_account",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Book Advance Payments in Separate Party Account"
|
"label": "Book Advance Payments in Separate Party Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "exchange_rate_revaluation_settings_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Exchange Rate Revaluation Settings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "auto_exchange_rate_revaluation",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Auto Create Exchange Rate Revaluation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "auto_err_frequency",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Frequency",
|
||||||
|
"options": "Daily\nWeekly"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "submit_err_jv",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Submit ERR Journals?"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-building",
|
"icon": "fa fa-building",
|
||||||
@ -738,7 +765,7 @@
|
|||||||
"image_field": "company_logo",
|
"image_field": "company_logo",
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-06-23 18:22:27.219706",
|
"modified": "2023-07-07 05:41:41.537256",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Company",
|
"name": "Company",
|
||||||
|
@ -1,352 +1,99 @@
|
|||||||
{
|
{
|
||||||
|
"actions": [],
|
||||||
"allow_copy": 1,
|
"allow_copy": 1,
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2013-05-02 17:53:24",
|
"creation": "2013-05-02 17:53:24",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 0,
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"default_company",
|
||||||
|
"country",
|
||||||
|
"default_distance_unit",
|
||||||
|
"column_break_8",
|
||||||
|
"default_currency",
|
||||||
|
"hide_currency_symbol",
|
||||||
|
"disable_rounded_total",
|
||||||
|
"disable_in_words"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "default_company",
|
"fieldname": "default_company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 1,
|
"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",
|
"label": "Default Company",
|
||||||
"length": 0,
|
"options": "Company"
|
||||||
"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,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"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,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "country",
|
"fieldname": "country",
|
||||||
"fieldtype": "Link",
|
"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",
|
"label": "Country",
|
||||||
"length": 0,
|
"options": "Country"
|
||||||
"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,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"default": "",
|
|
||||||
"fieldname": "default_distance_unit",
|
"fieldname": "default_distance_unit",
|
||||||
"fieldtype": "Link",
|
"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",
|
"label": "Default Distance Unit",
|
||||||
"length": 0,
|
"options": "UOM"
|
||||||
"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,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_8",
|
"fieldname": "column_break_8",
|
||||||
"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,
|
|
||||||
"default": "INR",
|
"default": "INR",
|
||||||
"fieldname": "default_currency",
|
"fieldname": "default_currency",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Default Currency",
|
"label": "Default Currency",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Currency",
|
"options": "Currency",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"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,
|
|
||||||
"description": "Do not show any symbol like $ etc next to currencies.",
|
"description": "Do not show any symbol like $ etc next to currencies.",
|
||||||
"fieldname": "hide_currency_symbol",
|
"fieldname": "hide_currency_symbol",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"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": "Hide Currency Symbol",
|
"label": "Hide Currency Symbol",
|
||||||
"length": 0,
|
"options": "\nNo\nYes"
|
||||||
"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,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"description": "If disable, 'Rounded Total' field will not be visible in any transaction",
|
"description": "If disable, 'Rounded Total' field will not be visible in any transaction",
|
||||||
"fieldname": "disable_rounded_total",
|
"fieldname": "disable_rounded_total",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"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": "Disable Rounded Total"
|
||||||
"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,
|
"default": "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",
|
"description": "If disable, 'In Words' field will not be visible in any transaction",
|
||||||
"fieldname": "disable_in_words",
|
"fieldname": "disable_in_words",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"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": "Disable In Words"
|
||||||
"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,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"icon": "fa fa-cog",
|
"icon": "fa fa-cog",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"istable": 0,
|
"links": [],
|
||||||
"max_attachments": 0,
|
"modified": "2023-07-01 19:45:00.323953",
|
||||||
"menu_index": 0,
|
|
||||||
"modified": "2018-10-15 03:08:19.886212",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Global Defaults",
|
"name": "Global Defaults",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 0,
|
|
||||||
"email": 0,
|
|
||||||
"export": 0,
|
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 0,
|
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 0,
|
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"read_only_onload": 0,
|
"sort_field": "modified",
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 0,
|
"states": []
|
||||||
"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
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Sales Partner', {
|
frappe.ui.form.on('Sales Partner', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
frappe.dynamic_link = {doc: frm.doc, fieldname: 'name', doctype: 'Sales Partner'}
|
|
||||||
|
|
||||||
if(frm.doc.__islocal){
|
if(frm.doc.__islocal){
|
||||||
hide_field(['address_html', 'contact_html', 'address_contacts']);
|
hide_field(['address_html', 'contact_html', 'address_contacts']);
|
||||||
frappe.contacts.clear_address_and_contact(frm);
|
frappe.contacts.clear_address_and_contact(frm);
|
||||||
|
@ -169,7 +169,7 @@ def add_standard_navbar_items():
|
|||||||
{
|
{
|
||||||
"item_label": "Documentation",
|
"item_label": "Documentation",
|
||||||
"item_type": "Route",
|
"item_type": "Route",
|
||||||
"route": "https://docs.erpnext.com/docs/v14/user/manual/en/introduction",
|
"route": "https://docs.erpnext.com/",
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -178,6 +178,12 @@ def add_standard_navbar_items():
|
|||||||
"route": "https://discuss.frappe.io",
|
"route": "https://discuss.frappe.io",
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"item_label": "Frappe School",
|
||||||
|
"item_type": "Route",
|
||||||
|
"route": "https://frappe.school?utm_source=in_app",
|
||||||
|
"is_standard": 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"item_label": "Report an Issue",
|
"item_label": "Report an Issue",
|
||||||
"item_type": "Route",
|
"item_type": "Route",
|
||||||
|
@ -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"),
|
||||||
|
@ -47,8 +47,6 @@ frappe.ui.form.on('Batch', {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugger
|
|
||||||
|
|
||||||
const section = frm.dashboard.add_section('', __("Stock Levels"));
|
const section = frm.dashboard.add_section('', __("Stock Levels"));
|
||||||
|
|
||||||
// sort by qty
|
// sort by qty
|
||||||
|
@ -59,6 +59,73 @@ class TestBatch(FrappeTestCase):
|
|||||||
|
|
||||||
return receipt
|
return receipt
|
||||||
|
|
||||||
|
def test_batch_stock_levels(self, batch_qty=100):
|
||||||
|
"""Test automated batch creation from Purchase Receipt"""
|
||||||
|
self.make_batch_item("ITEM-BATCH-1")
|
||||||
|
|
||||||
|
receipt = frappe.get_doc(
|
||||||
|
dict(
|
||||||
|
doctype="Purchase Receipt",
|
||||||
|
supplier="_Test Supplier",
|
||||||
|
company="_Test Company",
|
||||||
|
items=[dict(item_code="ITEM-BATCH-1", qty=10, rate=10, warehouse="Stores - _TC")],
|
||||||
|
)
|
||||||
|
).insert()
|
||||||
|
receipt.submit()
|
||||||
|
|
||||||
|
receipt.load_from_db()
|
||||||
|
batch_no = get_batch_from_bundle(receipt.items[0].serial_and_batch_bundle)
|
||||||
|
|
||||||
|
bundle_id = (
|
||||||
|
SerialBatchCreation(
|
||||||
|
{
|
||||||
|
"item_code": "ITEM-BATCH-1",
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"actual_qty": 20,
|
||||||
|
"voucher_type": "Purchase Receipt",
|
||||||
|
"batches": frappe._dict({batch_no: 20}),
|
||||||
|
"type_of_transaction": "Inward",
|
||||||
|
"company": receipt.company,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.make_serial_and_batch_bundle()
|
||||||
|
.name
|
||||||
|
)
|
||||||
|
|
||||||
|
receipt2 = frappe.get_doc(
|
||||||
|
dict(
|
||||||
|
doctype="Purchase Receipt",
|
||||||
|
supplier="_Test Supplier",
|
||||||
|
company="_Test Company",
|
||||||
|
items=[
|
||||||
|
dict(
|
||||||
|
item_code="ITEM-BATCH-1",
|
||||||
|
qty=20,
|
||||||
|
rate=10,
|
||||||
|
warehouse="_Test Warehouse - _TC",
|
||||||
|
serial_and_batch_bundle=bundle_id,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
).insert()
|
||||||
|
receipt2.submit()
|
||||||
|
|
||||||
|
receipt.load_from_db()
|
||||||
|
receipt2.load_from_db()
|
||||||
|
|
||||||
|
self.assertTrue(receipt.items[0].serial_and_batch_bundle)
|
||||||
|
self.assertTrue(receipt2.items[0].serial_and_batch_bundle)
|
||||||
|
|
||||||
|
batchwise_qty = frappe._dict({})
|
||||||
|
for receipt in [receipt, receipt2]:
|
||||||
|
batch_no = get_batch_from_bundle(receipt.items[0].serial_and_batch_bundle)
|
||||||
|
key = (batch_no, receipt.items[0].warehouse)
|
||||||
|
batchwise_qty[key] = receipt.items[0].qty
|
||||||
|
|
||||||
|
batches = get_batch_qty(batch_no)
|
||||||
|
for d in batches:
|
||||||
|
self.assertEqual(d.qty, batchwise_qty[(d.batch_no, d.warehouse)])
|
||||||
|
|
||||||
def test_stock_entry_incoming(self):
|
def test_stock_entry_incoming(self):
|
||||||
"""Test batch creation via Stock Entry (Work Order)"""
|
"""Test batch creation via Stock Entry (Work Order)"""
|
||||||
|
|
||||||
|
@ -318,6 +318,37 @@ class TestDeliveryNote(FrappeTestCase):
|
|||||||
self.assertEqual(dn.per_returned, 100)
|
self.assertEqual(dn.per_returned, 100)
|
||||||
self.assertEqual(dn.status, "Return Issued")
|
self.assertEqual(dn.status, "Return Issued")
|
||||||
|
|
||||||
|
def test_delivery_note_return_valuation_on_different_warehuose(self):
|
||||||
|
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||||
|
|
||||||
|
company = frappe.db.get_value("Warehouse", "Stores - TCP1", "company")
|
||||||
|
item_code = "Test Return Valuation For DN"
|
||||||
|
make_item("Test Return Valuation For DN", {"is_stock_item": 1})
|
||||||
|
return_warehouse = create_warehouse("Returned Test Warehouse", company=company)
|
||||||
|
|
||||||
|
make_stock_entry(item_code=item_code, target="Stores - TCP1", qty=5, basic_rate=150)
|
||||||
|
|
||||||
|
dn = create_delivery_note(
|
||||||
|
item_code=item_code,
|
||||||
|
qty=5,
|
||||||
|
rate=500,
|
||||||
|
warehouse="Stores - TCP1",
|
||||||
|
company=company,
|
||||||
|
expense_account="Cost of Goods Sold - TCP1",
|
||||||
|
cost_center="Main - TCP1",
|
||||||
|
)
|
||||||
|
|
||||||
|
dn.submit()
|
||||||
|
self.assertEqual(dn.items[0].incoming_rate, 150)
|
||||||
|
|
||||||
|
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||||
|
|
||||||
|
return_dn = make_return_doc(dn.doctype, dn.name)
|
||||||
|
return_dn.items[0].warehouse = return_warehouse
|
||||||
|
return_dn.save().submit()
|
||||||
|
|
||||||
|
self.assertEqual(return_dn.items[0].incoming_rate, 150)
|
||||||
|
|
||||||
def test_return_single_item_from_bundled_items(self):
|
def test_return_single_item_from_bundled_items(self):
|
||||||
company = frappe.db.get_value("Warehouse", "Stores - TCP1", "company")
|
company = frappe.db.get_value("Warehouse", "Stores - TCP1", "company")
|
||||||
|
|
||||||
|
@ -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",
|
||||||
|
@ -773,7 +773,7 @@ class Item(Document):
|
|||||||
|
|
||||||
rows = ""
|
rows = ""
|
||||||
for docname, attr_list in not_included.items():
|
for docname, attr_list in not_included.items():
|
||||||
link = "<a href='/app/Form/Item/{0}'>{0}</a>".format(frappe.bold(_(docname)))
|
link = f"<a href='/app/item/{docname}'>{frappe.bold(docname)}</a>"
|
||||||
rows += table_row(link, body(attr_list))
|
rows += table_row(link, body(attr_list))
|
||||||
|
|
||||||
error_description = _(
|
error_description = _(
|
||||||
|
@ -1,370 +1,90 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_events_in_timeline": 0,
|
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 0,
|
|
||||||
"allow_rename": 0,
|
|
||||||
"autoname": "",
|
|
||||||
"beta": 0,
|
|
||||||
"creation": "2015-05-19 05:12:30.344797",
|
"creation": "2015-05-19 05:12:30.344797",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Other",
|
"document_type": "Other",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"variant_of",
|
||||||
|
"attribute",
|
||||||
|
"column_break_2",
|
||||||
|
"attribute_value",
|
||||||
|
"numeric_values",
|
||||||
|
"section_break_4",
|
||||||
|
"from_range",
|
||||||
|
"increment",
|
||||||
|
"column_break_8",
|
||||||
|
"to_range"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "variant_of",
|
"fieldname": "variant_of",
|
||||||
"fieldtype": "Link",
|
"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",
|
"label": "Variant Of",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"permlevel": 0,
|
"search_index": 1
|
||||||
"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": "attribute",
|
"fieldname": "attribute",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"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": "Attribute",
|
"label": "Attribute",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Item Attribute",
|
"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,
|
"reqd": 1,
|
||||||
"search_index": 0,
|
"search_index": 1
|
||||||
"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_2",
|
"fieldname": "column_break_2",
|
||||||
"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,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "attribute_value",
|
"fieldname": "attribute_value",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"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": "Attribute Value"
|
||||||
"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,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "has_variants",
|
"depends_on": "has_variants",
|
||||||
"fieldname": "numeric_values",
|
"fieldname": "numeric_values",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"label": "Numeric Values"
|
||||||
"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,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "numeric_values",
|
"depends_on": "numeric_values",
|
||||||
"fieldname": "section_break_4",
|
"fieldname": "section_break_4",
|
||||||
"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,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "from_range",
|
"fieldname": "from_range",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"label": "From Range"
|
||||||
"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,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "increment",
|
"fieldname": "increment",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"label": "Increment"
|
||||||
"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,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "column_break_8",
|
"fieldname": "column_break_8",
|
||||||
"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,
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "to_range",
|
"fieldname": "to_range",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hidden": 0,
|
"label": "To Range"
|
||||||
"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,
|
|
||||||
"hide_heading": 0,
|
|
||||||
"hide_toolbar": 0,
|
|
||||||
"icon": "",
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"links": [],
|
||||||
"modified": "2019-01-03 15:36:59.129006",
|
"modified": "2023-07-14 17:15:19.112119",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item Variant Attribute",
|
"name": "Item Variant Attribute",
|
||||||
"name_case": "",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"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,7 +3,6 @@
|
|||||||
|
|
||||||
frappe.ui.form.on('Manufacturer', {
|
frappe.ui.form.on('Manufacturer', {
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Manufacturer' };
|
|
||||||
if (frm.doc.__islocal) {
|
if (frm.doc.__islocal) {
|
||||||
hide_field(['address_html','contact_html']);
|
hide_field(['address_html','contact_html']);
|
||||||
frappe.contacts.clear_address_and_contact(frm);
|
frappe.contacts.clear_address_and_contact(frm);
|
||||||
|
@ -438,6 +438,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "rejected_warehouse",
|
"fieldname": "rejected_warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
"label": "Rejected Warehouse",
|
"label": "Rejected Warehouse",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "rejected_warehouse",
|
"oldfieldname": "rejected_warehouse",
|
||||||
@ -1240,7 +1241,7 @@
|
|||||||
"idx": 261,
|
"idx": 261,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-06-03 16:23:20.781368",
|
"modified": "2023-07-04 17:23:17.025390",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Purchase Receipt",
|
"name": "Purchase Receipt",
|
||||||
|
@ -350,6 +350,15 @@ class TestPurchaseReceipt(FrappeTestCase):
|
|||||||
pr.cancel()
|
pr.cancel()
|
||||||
self.assertFalse(frappe.db.get_value("Serial No", pr_row_1_serial_no, "warehouse"))
|
self.assertFalse(frappe.db.get_value("Serial No", pr_row_1_serial_no, "warehouse"))
|
||||||
|
|
||||||
|
def test_rejected_warehouse_filter(self):
|
||||||
|
pr = frappe.copy_doc(test_records[0])
|
||||||
|
pr.get("items")[0].item_code = "_Test Serialized Item With Series"
|
||||||
|
pr.get("items")[0].qty = 3
|
||||||
|
pr.get("items")[0].rejected_qty = 2
|
||||||
|
pr.get("items")[0].received_qty = 5
|
||||||
|
pr.get("items")[0].rejected_warehouse = pr.get("items")[0].warehouse
|
||||||
|
self.assertRaises(frappe.ValidationError, pr.save)
|
||||||
|
|
||||||
def test_rejected_serial_no(self):
|
def test_rejected_serial_no(self):
|
||||||
pr = frappe.copy_doc(test_records[0])
|
pr = frappe.copy_doc(test_records[0])
|
||||||
pr.get("items")[0].item_code = "_Test Serialized Item With Series"
|
pr.get("items")[0].item_code = "_Test Serialized Item With Series"
|
||||||
@ -1956,6 +1965,32 @@ class TestPurchaseReceipt(FrappeTestCase):
|
|||||||
ste5.reload()
|
ste5.reload()
|
||||||
self.assertEqual(ste5.items[0].valuation_rate, 275.00)
|
self.assertEqual(ste5.items[0].valuation_rate, 275.00)
|
||||||
|
|
||||||
|
ste6 = make_stock_entry(
|
||||||
|
purpose="Material Transfer",
|
||||||
|
posting_date=add_days(today(), -3),
|
||||||
|
source=warehouse1,
|
||||||
|
target=warehouse,
|
||||||
|
item_code=item_code,
|
||||||
|
qty=20,
|
||||||
|
company=pr.company,
|
||||||
|
)
|
||||||
|
|
||||||
|
ste6.reload()
|
||||||
|
self.assertEqual(ste6.items[0].valuation_rate, 275.00)
|
||||||
|
|
||||||
|
ste7 = make_stock_entry(
|
||||||
|
purpose="Material Transfer",
|
||||||
|
posting_date=add_days(today(), -3),
|
||||||
|
source=warehouse,
|
||||||
|
target=warehouse1,
|
||||||
|
item_code=item_code,
|
||||||
|
qty=20,
|
||||||
|
company=pr.company,
|
||||||
|
)
|
||||||
|
|
||||||
|
ste7.reload()
|
||||||
|
self.assertEqual(ste7.items[0].valuation_rate, 275.00)
|
||||||
|
|
||||||
create_landed_cost_voucher("Purchase Receipt", pr.name, pr.company, charges=2500 * -1)
|
create_landed_cost_voucher("Purchase Receipt", pr.name, pr.company, charges=2500 * -1)
|
||||||
|
|
||||||
pr.reload()
|
pr.reload()
|
||||||
@ -1976,6 +2011,12 @@ class TestPurchaseReceipt(FrappeTestCase):
|
|||||||
ste5.reload()
|
ste5.reload()
|
||||||
self.assertEqual(ste5.items[0].valuation_rate, valuation_rate)
|
self.assertEqual(ste5.items[0].valuation_rate, valuation_rate)
|
||||||
|
|
||||||
|
ste6.reload()
|
||||||
|
self.assertEqual(ste6.items[0].valuation_rate, valuation_rate)
|
||||||
|
|
||||||
|
ste7.reload()
|
||||||
|
self.assertEqual(ste7.items[0].valuation_rate, valuation_rate)
|
||||||
|
|
||||||
|
|
||||||
def prepare_data_for_internal_transfer():
|
def prepare_data_for_internal_transfer():
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
||||||
|
@ -502,6 +502,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "rejected_warehouse",
|
"fieldname": "rejected_warehouse",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"ignore_user_permissions": 1,
|
||||||
"label": "Rejected Warehouse",
|
"label": "Rejected Warehouse",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"oldfieldname": "rejected_warehouse",
|
"oldfieldname": "rejected_warehouse",
|
||||||
@ -1058,7 +1059,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-07-02 18:40:48.152637",
|
"modified": "2023-07-04 17:22:02.830029",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Purchase Receipt Item",
|
"name": "Purchase Receipt Item",
|
||||||
|
@ -193,7 +193,7 @@
|
|||||||
"fieldname": "naming_series",
|
"fieldname": "naming_series",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Naming Series",
|
"label": "Naming Series",
|
||||||
"options": "SBB-.####"
|
"options": "SABB-.########"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -244,7 +244,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-04-10 20:02:42.964309",
|
"modified": "2023-07-16 10:53:04.045605",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Serial and Batch Bundle",
|
"name": "Serial and Batch Bundle",
|
||||||
|
@ -889,13 +889,16 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_serial_batch_ledgers(item_code, docstatus=None, voucher_no=None, name=None):
|
def get_serial_batch_ledgers(item_code=None, docstatus=None, voucher_no=None, name=None):
|
||||||
filters = get_filters_for_bundle(item_code, docstatus=docstatus, voucher_no=voucher_no, name=name)
|
filters = get_filters_for_bundle(
|
||||||
|
item_code=item_code, docstatus=docstatus, voucher_no=voucher_no, name=name
|
||||||
|
)
|
||||||
|
|
||||||
return frappe.get_all(
|
return frappe.get_all(
|
||||||
"Serial and Batch Bundle",
|
"Serial and Batch Bundle",
|
||||||
fields=[
|
fields=[
|
||||||
"`tabSerial and Batch Bundle`.`name`",
|
"`tabSerial and Batch Bundle`.`name`",
|
||||||
|
"`tabSerial and Batch Bundle`.`item_code`",
|
||||||
"`tabSerial and Batch Entry`.`qty`",
|
"`tabSerial and Batch Entry`.`qty`",
|
||||||
"`tabSerial and Batch Entry`.`warehouse`",
|
"`tabSerial and Batch Entry`.`warehouse`",
|
||||||
"`tabSerial and Batch Entry`.`batch_no`",
|
"`tabSerial and Batch Entry`.`batch_no`",
|
||||||
@ -906,12 +909,14 @@ def get_serial_batch_ledgers(item_code, docstatus=None, voucher_no=None, name=No
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_filters_for_bundle(item_code, docstatus=None, voucher_no=None, name=None):
|
def get_filters_for_bundle(item_code=None, docstatus=None, voucher_no=None, name=None):
|
||||||
filters = [
|
filters = [
|
||||||
["Serial and Batch Bundle", "item_code", "=", item_code],
|
|
||||||
["Serial and Batch Bundle", "is_cancelled", "=", 0],
|
["Serial and Batch Bundle", "is_cancelled", "=", 0],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if item_code:
|
||||||
|
filters.append(["Serial and Batch Bundle", "item_code", "=", item_code])
|
||||||
|
|
||||||
if not docstatus:
|
if not docstatus:
|
||||||
docstatus = [0, 1]
|
docstatus = [0, 1]
|
||||||
|
|
||||||
@ -1272,24 +1277,29 @@ def get_reserved_batches_for_pos(kwargs):
|
|||||||
|
|
||||||
if ids:
|
if ids:
|
||||||
for d in get_serial_batch_ledgers(kwargs.item_code, docstatus=1, name=ids):
|
for d in get_serial_batch_ledgers(kwargs.item_code, docstatus=1, name=ids):
|
||||||
if d.batch_no not in pos_batches:
|
key = (d.batch_no, d.warehouse)
|
||||||
pos_batches[d.batch_no] = frappe._dict(
|
if key not in pos_batches:
|
||||||
|
pos_batches[key] = frappe._dict(
|
||||||
{
|
{
|
||||||
"qty": d.qty,
|
"qty": d.qty,
|
||||||
"warehouse": d.warehouse,
|
"warehouse": d.warehouse,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
pos_batches[d.batch_no].qty += d.qty
|
pos_batches[key].qty += d.qty
|
||||||
|
|
||||||
for row in pos_invoices:
|
for row in pos_invoices:
|
||||||
if not row.batch_no:
|
if not row.batch_no:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if row.batch_no in pos_batches:
|
if kwargs.get("batch_no") and row.batch_no != kwargs.get("batch_no"):
|
||||||
pos_batches[row.batch_no] -= row.qty * -1 if row.is_return else row.qty
|
continue
|
||||||
|
|
||||||
|
key = (row.batch_no, row.warehouse)
|
||||||
|
if key in pos_batches:
|
||||||
|
pos_batches[key] -= row.qty * -1 if row.is_return else row.qty
|
||||||
else:
|
else:
|
||||||
pos_batches[row.batch_no] = frappe._dict(
|
pos_batches[key] = frappe._dict(
|
||||||
{
|
{
|
||||||
"qty": (row.qty * -1 if row.is_return else row.qty),
|
"qty": (row.qty * -1 if row.is_return else row.qty),
|
||||||
"warehouse": row.warehouse,
|
"warehouse": row.warehouse,
|
||||||
@ -1309,6 +1319,7 @@ def get_auto_batch_nos(kwargs):
|
|||||||
update_available_batches(available_batches, stock_ledgers_batches, pos_invoice_batches)
|
update_available_batches(available_batches, stock_ledgers_batches, pos_invoice_batches)
|
||||||
|
|
||||||
available_batches = list(filter(lambda x: x.qty > 0, available_batches))
|
available_batches = list(filter(lambda x: x.qty > 0, available_batches))
|
||||||
|
|
||||||
if not qty:
|
if not qty:
|
||||||
return available_batches
|
return available_batches
|
||||||
|
|
||||||
@ -1351,10 +1362,11 @@ def get_qty_based_available_batches(available_batches, qty):
|
|||||||
def update_available_batches(available_batches, reserved_batches=None, pos_invoice_batches=None):
|
def update_available_batches(available_batches, reserved_batches=None, pos_invoice_batches=None):
|
||||||
for batches in [reserved_batches, pos_invoice_batches]:
|
for batches in [reserved_batches, pos_invoice_batches]:
|
||||||
if batches:
|
if batches:
|
||||||
for batch_no, data in batches.items():
|
for key, data in batches.items():
|
||||||
|
batch_no, warehouse = key
|
||||||
batch_not_exists = True
|
batch_not_exists = True
|
||||||
for batch in available_batches:
|
for batch in available_batches:
|
||||||
if batch.batch_no == batch_no and batch.warehouse == data.warehouse:
|
if batch.batch_no == batch_no and batch.warehouse == warehouse:
|
||||||
batch.qty += data.qty
|
batch.qty += data.qty
|
||||||
batch_not_exists = False
|
batch_not_exists = False
|
||||||
|
|
||||||
@ -1563,7 +1575,7 @@ def get_stock_ledgers_batches(kwargs):
|
|||||||
.groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse)
|
.groupby(stock_ledger_entry.batch_no, stock_ledger_entry.warehouse)
|
||||||
)
|
)
|
||||||
|
|
||||||
for field in ["warehouse", "item_code"]:
|
for field in ["warehouse", "item_code", "batch_no"]:
|
||||||
if not kwargs.get(field):
|
if not kwargs.get(field):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -1582,6 +1594,10 @@ def get_stock_ledgers_batches(kwargs):
|
|||||||
data = query.run(as_dict=True)
|
data = query.run(as_dict=True)
|
||||||
batches = {}
|
batches = {}
|
||||||
for d in data:
|
for d in data:
|
||||||
batches[d.batch_no] = d
|
key = (d.batch_no, d.warehouse)
|
||||||
|
if key not in batches:
|
||||||
|
batches[key] = d
|
||||||
|
else:
|
||||||
|
batches[key].qty += d.qty
|
||||||
|
|
||||||
return batches
|
return batches
|
||||||
|
@ -925,6 +925,7 @@ erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockControlle
|
|||||||
this.toggle_related_fields(this.frm.doc);
|
this.toggle_related_fields(this.frm.doc);
|
||||||
this.toggle_enable_bom();
|
this.toggle_enable_bom();
|
||||||
this.show_stock_ledger();
|
this.show_stock_ledger();
|
||||||
|
erpnext.utils.view_serial_batch_nos(this.frm);
|
||||||
if (this.frm.doc.docstatus===1 && erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
|
if (this.frm.doc.docstatus===1 && erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
|
||||||
this.show_general_ledger();
|
this.show_general_ledger();
|
||||||
}
|
}
|
||||||
|
@ -337,6 +337,7 @@ erpnext.stock.StockReconciliation = class StockReconciliation extends erpnext.st
|
|||||||
refresh() {
|
refresh() {
|
||||||
if(this.frm.doc.docstatus > 0) {
|
if(this.frm.doc.docstatus > 0) {
|
||||||
this.show_stock_ledger();
|
this.show_stock_ledger();
|
||||||
|
erpnext.utils.view_serial_batch_nos(this.frm);
|
||||||
if (erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
|
if (erpnext.is_perpetual_inventory_enabled(this.frm.doc.company)) {
|
||||||
this.show_general_ledger();
|
this.show_general_ledger();
|
||||||
}
|
}
|
||||||
|
@ -83,12 +83,6 @@ frappe.ui.form.on("Warehouse", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
frm.toggle_enable(["is_group", "company"], false);
|
frm.toggle_enable(["is_group", "company"], false);
|
||||||
|
|
||||||
frappe.dynamic_link = {
|
|
||||||
doc: frm.doc,
|
|
||||||
fieldname: "name",
|
|
||||||
doctype: "Warehouse",
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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")
|
|
||||||
|
def get_columns():
|
||||||
|
return (
|
||||||
|
[_("Item") + ":Link/Item:150"]
|
||||||
|
+ [_("Item Name") + "::150"]
|
||||||
|
+ [_("Batch") + ":Link/Batch:150"]
|
||||||
|
+ [_("Stock UOM") + ":Link/UOM:100"]
|
||||||
|
+ [_("Quantity") + ":Float:100"]
|
||||||
|
+ [_("Expires On") + ":Date:100"]
|
||||||
|
+ [_("Expiry (In Days)") + ":Int:130"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_data(filters):
|
||||||
|
data = []
|
||||||
|
|
||||||
|
for batch in get_batch_details(filters):
|
||||||
|
data.append(
|
||||||
|
[
|
||||||
|
batch.item,
|
||||||
|
batch.item_name,
|
||||||
|
batch.name,
|
||||||
|
batch.stock_uom,
|
||||||
|
batch.batch_qty,
|
||||||
|
batch.expiry_date,
|
||||||
|
max((batch.expiry_date - frappe.utils.datetime.date.today()).days, 0)
|
||||||
|
if batch.expiry_date
|
||||||
|
else None,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_batch_details(filters):
|
||||||
|
batch = frappe.qb.DocType("Batch")
|
||||||
query = (
|
query = (
|
||||||
frappe.qb.from_(sle)
|
frappe.qb.from_(batch)
|
||||||
.select(sle.item_code, sle.batch_no, sle.warehouse, sle.posting_date, sle.actual_qty)
|
.select(
|
||||||
|
batch.name,
|
||||||
|
batch.creation,
|
||||||
|
batch.expiry_date,
|
||||||
|
batch.item,
|
||||||
|
batch.item_name,
|
||||||
|
batch.stock_uom,
|
||||||
|
batch.batch_qty,
|
||||||
|
)
|
||||||
.where(
|
.where(
|
||||||
(sle.is_cancelled == 0)
|
(batch.disabled == 0)
|
||||||
& (sle.docstatus < 2)
|
& (batch.batch_qty > 0)
|
||||||
& (IfNull(sle.batch_no, "") != "")
|
& (
|
||||||
& (sle.posting_date <= filters["to_date"])
|
(Date(batch.creation) >= filters["from_date"]) & (Date(batch.creation) <= filters["to_date"])
|
||||||
)
|
)
|
||||||
.orderby(sle.item_code, sle.warehouse)
|
|
||||||
)
|
)
|
||||||
|
.orderby(batch.creation)
|
||||||
|
)
|
||||||
|
|
||||||
|
if filters.get("item"):
|
||||||
|
query = query.where(batch.item == filters["item"])
|
||||||
|
|
||||||
return query.run(as_dict=True)
|
return query.run(as_dict=True)
|
||||||
|
|
||||||
|
|
||||||
def get_item_warehouse_batch_map(filters, float_precision):
|
|
||||||
sle = get_stock_ledger_entries(filters)
|
|
||||||
iwb_map = {}
|
|
||||||
|
|
||||||
from_date = getdate(filters["from_date"])
|
|
||||||
to_date = getdate(filters["to_date"])
|
|
||||||
|
|
||||||
for d in sle:
|
|
||||||
iwb_map.setdefault(d.item_code, {}).setdefault(d.warehouse, {}).setdefault(
|
|
||||||
d.batch_no, frappe._dict({"expires_on": None, "expiry_status": None})
|
|
||||||
)
|
|
||||||
|
|
||||||
qty_dict = iwb_map[d.item_code][d.warehouse][d.batch_no]
|
|
||||||
|
|
||||||
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):
|
|
||||||
item_map = {}
|
|
||||||
for d in (frappe.qb.from_("Item").select("name", "item_name", "description")).run(as_dict=True):
|
|
||||||
item_map.setdefault(d.name, d)
|
|
||||||
|
|
||||||
return item_map
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user