mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-20 13:14:03 +00:00
Compare commits
194 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
927d14e021 | ||
|
|
7bb5313190 | ||
|
|
1d6bb3953d | ||
|
|
78d0a11d09 | ||
|
|
ccf62886e4 | ||
|
|
40747e1b49 | ||
|
|
87f8d66b79 | ||
|
|
d075399ecd | ||
|
|
c4ff9c72dd | ||
|
|
97ccb0eec2 | ||
|
|
2382312d41 | ||
|
|
348d10cad8 | ||
|
|
47f030b1bf | ||
|
|
7e4f8fa04d | ||
|
|
652181600d | ||
|
|
e4f300c903 | ||
|
|
d839c46f10 | ||
|
|
6d45dfd6e8 | ||
|
|
5caa40857d | ||
|
|
78b7f69e0c | ||
|
|
8d9b58d801 | ||
|
|
a611cc5916 | ||
|
|
c6466c7d97 | ||
|
|
b35db7e819 | ||
|
|
44875482ac | ||
|
|
f06cc233a8 | ||
|
|
fdd93cba03 | ||
|
|
10f53f04d7 | ||
|
|
884dc28af6 | ||
|
|
a506930b63 | ||
|
|
f6836c1d89 | ||
|
|
3e2fe12c9d | ||
|
|
5b2ca9e133 | ||
|
|
f8dc7b32d5 | ||
|
|
0393cb5c43 | ||
|
|
4206b52bdc | ||
|
|
9e66c86d6f | ||
|
|
ec46b4d4c6 | ||
|
|
39c71e26b9 | ||
|
|
77285317c0 | ||
|
|
a95c09bef6 | ||
|
|
6b901d0c1a | ||
|
|
8a7ccd9874 | ||
|
|
2f2e748b7a | ||
|
|
549ab68eb0 | ||
|
|
0b9bf4d0ac | ||
|
|
1c5df5dede | ||
|
|
41d2357dc4 | ||
|
|
af79714f40 | ||
|
|
8a5f31da34 | ||
|
|
47a7e3422b | ||
|
|
9efb087e22 | ||
|
|
3d58dd6aa5 | ||
|
|
ac7966cd7e | ||
|
|
61ddb508d4 | ||
|
|
d973fb8823 | ||
|
|
a649414419 | ||
|
|
270f23b966 | ||
|
|
4d745a39e0 | ||
|
|
5e0b5cb283 | ||
|
|
69358cfd40 | ||
|
|
ad1ba2bb76 | ||
|
|
c44abd2f78 | ||
|
|
0bcada8f3c | ||
|
|
a6b110a7d3 | ||
|
|
b4ce43306b | ||
|
|
85a9f55fa7 | ||
|
|
596c0d2060 | ||
|
|
723421f375 | ||
|
|
f9297416f2 | ||
|
|
a8d2916e61 | ||
|
|
0f70f20ec5 | ||
|
|
73d9d8fec9 | ||
|
|
c4756e938f | ||
|
|
faa5d90f1b | ||
|
|
3b37a109c5 | ||
|
|
ab4aa53f52 | ||
|
|
3483426fe7 | ||
|
|
3039094737 | ||
|
|
e21602d432 | ||
|
|
6067ef3c49 | ||
|
|
b78128a7fe | ||
|
|
c8cbb87168 | ||
|
|
aed8aeb83a | ||
|
|
fa47445e11 | ||
|
|
0220acf100 | ||
|
|
0fe8f8e6d9 | ||
|
|
f87b766a26 | ||
|
|
2262e5d443 | ||
|
|
b9cad8d891 | ||
|
|
dafdc6035a | ||
|
|
c8369c10ff | ||
|
|
08b8ed5ca6 | ||
|
|
6cefdb40d1 | ||
|
|
3ad65ec57d | ||
|
|
364332bcfe | ||
|
|
9965f443ee | ||
|
|
d87d644dc2 | ||
|
|
eeab3128aa | ||
|
|
7b2cec8da2 | ||
|
|
6e3cbd8698 | ||
|
|
b5e1f846ce | ||
|
|
f06b31aab4 | ||
|
|
f8502317a9 | ||
|
|
9c7a33405d | ||
|
|
0ee46a624c | ||
|
|
5485d4c435 | ||
|
|
fb2d4884b3 | ||
|
|
3b38a9e418 | ||
|
|
437d3e37d6 | ||
|
|
1b9a55e766 | ||
|
|
a5353a8d04 | ||
|
|
e1bc0a1028 | ||
|
|
92116abd92 | ||
|
|
e5731b3d0f | ||
|
|
a36c4326c3 | ||
|
|
5a0a4bdcff | ||
|
|
d2dc889849 | ||
|
|
dbcdf7e225 | ||
|
|
7fdef64152 | ||
|
|
b2be301988 | ||
|
|
68db5a6792 | ||
|
|
f232965392 | ||
|
|
2ff7197752 | ||
|
|
1d3b5b0437 | ||
|
|
8280d32967 | ||
|
|
4a79072c71 | ||
|
|
721a00cd22 | ||
|
|
8ce7893bf0 | ||
|
|
0f87282aef | ||
|
|
de51217a80 | ||
|
|
bc01dafbba | ||
|
|
a985bfc29a | ||
|
|
08dbb13451 | ||
|
|
170dd37b86 | ||
|
|
b1744972e0 | ||
|
|
7aa993b14b | ||
|
|
ad89cb0ef3 | ||
|
|
a185b51f0d | ||
|
|
1ff81bca7d | ||
|
|
b02db3c3e8 | ||
|
|
d1d835347e | ||
|
|
ba245553f0 | ||
|
|
112902a9c4 | ||
|
|
3f4cdcc7a4 | ||
|
|
91f81b07d9 | ||
|
|
66e92041b9 | ||
|
|
f2dc89c7a0 | ||
|
|
10b226af10 | ||
|
|
115887a886 | ||
|
|
a1f5c22da7 | ||
|
|
712c01d5bd | ||
|
|
bd4e296336 | ||
|
|
b52d81ef6a | ||
|
|
15432c76a4 | ||
|
|
dd3cd6e2ba | ||
|
|
5889a29656 | ||
|
|
0e7ca6ada7 | ||
|
|
5a2ea528e8 | ||
|
|
8957093439 | ||
|
|
507c435dee | ||
|
|
8889edad72 | ||
|
|
e27d1aebd5 | ||
|
|
ef567eac37 | ||
|
|
f8e0a2204e | ||
|
|
baecc7fd31 | ||
|
|
529b465337 | ||
|
|
675e2670b2 | ||
|
|
3919fd10ad | ||
|
|
b4e61e19bb | ||
|
|
85be3ec796 | ||
|
|
aa3d6ed11e | ||
|
|
382735ad2f | ||
|
|
8d42b75e29 | ||
|
|
7e03e046ec | ||
|
|
bfddc8aba1 | ||
|
|
d0dafcc46f | ||
|
|
43a0161257 | ||
|
|
f8996b64f1 | ||
|
|
867443ea6d | ||
|
|
acdc230ef3 | ||
|
|
86232e4449 | ||
|
|
78c7f03731 | ||
|
|
65b99a5109 | ||
|
|
8ec290d5ec | ||
|
|
65a259eb81 | ||
|
|
47420578ae | ||
|
|
35d8cd9f10 | ||
|
|
1e55ac6a4f | ||
|
|
ce60dc3ea3 | ||
|
|
ff7a5d18d1 | ||
|
|
5a15dcc060 | ||
|
|
b23da53fee | ||
|
|
d37a30fc47 |
14
.github/workflows/docker-release.yml
vendored
Normal file
14
.github/workflows/docker-release.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: Trigger Docker build on release
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
jobs:
|
||||
curl:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: alpine:latest
|
||||
steps:
|
||||
- name: curl
|
||||
run: |
|
||||
apk add curl bash
|
||||
curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Travis-API-Version: 3" -H "Authorization: token ${{ secrets.TRAVIS_CI_TOKEN }}" -d '{"request":{"branch":"master"}}' https://api.travis-ci.com/repo/frappe%2Ffrappe_docker/requests
|
||||
@@ -76,5 +76,6 @@ install:
|
||||
- bench --site test_site reinstall --yes
|
||||
|
||||
after_script:
|
||||
- pip install coverage==4.5.4
|
||||
- pip install python-coveralls
|
||||
- coveralls -b apps/erpnext -d ../../sites/.coverage
|
||||
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '11.1.64'
|
||||
__version__ = '11.1.77'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
@@ -144,4 +144,4 @@ def is_member():
|
||||
last_membership = get_last_membership()
|
||||
if last_membership and getdate(last_membership.to_date) > getdate():
|
||||
return True
|
||||
return False
|
||||
return False
|
||||
|
||||
@@ -174,6 +174,8 @@ def make_gl_entries(doc, credit_account, debit_account, against,
|
||||
# GL Entry for crediting the amount in the deferred expense
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
|
||||
if amount == 0: return
|
||||
|
||||
gl_entries = []
|
||||
gl_entries.append(
|
||||
doc.get_gl_dict({
|
||||
|
||||
@@ -100,7 +100,10 @@ class Account(NestedSet):
|
||||
if ancestors:
|
||||
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
|
||||
return
|
||||
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||
|
||||
if not frappe.db.get_value("Account",
|
||||
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
|
||||
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||
else:
|
||||
descendants = get_descendants_of('Company', self.company)
|
||||
if not descendants: return
|
||||
@@ -114,21 +117,7 @@ class Account(NestedSet):
|
||||
|
||||
if not parent_acc_name_map: return
|
||||
|
||||
for company in descendants:
|
||||
if not parent_acc_name_map.get(company):
|
||||
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
|
||||
.format(company, parent_acc_name))
|
||||
|
||||
doc = frappe.copy_doc(self)
|
||||
doc.flags.ignore_root_company_validation = True
|
||||
doc.update({
|
||||
"company": company,
|
||||
"account_currency": None,
|
||||
"parent_account": parent_acc_name_map[company]
|
||||
})
|
||||
doc.save()
|
||||
frappe.msgprint(_("Account {0} is added in the child company {1}")
|
||||
.format(doc.name, company))
|
||||
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
|
||||
|
||||
def validate_group_or_ledger(self):
|
||||
if self.get("__islocal"):
|
||||
@@ -170,6 +159,49 @@ class Account(NestedSet):
|
||||
if frappe.db.get_value("GL Entry", {"account": self.name}):
|
||||
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
|
||||
|
||||
def create_account_for_child_company(self, parent_acc_name_map, descendants, parent_acc_name):
|
||||
for company in descendants:
|
||||
if not parent_acc_name_map.get(company):
|
||||
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
|
||||
.format(company, parent_acc_name))
|
||||
|
||||
filters = {
|
||||
"account_name": self.account_name,
|
||||
"company": company
|
||||
}
|
||||
|
||||
if self.account_number:
|
||||
filters["account_number"] = self.account_number
|
||||
|
||||
child_account = frappe.db.get_value("Account", filters, 'name')
|
||||
|
||||
if not child_account:
|
||||
doc = frappe.copy_doc(self)
|
||||
doc.flags.ignore_root_company_validation = True
|
||||
doc.update({
|
||||
"company": company,
|
||||
# parent account's currency should be passed down to child account's curreny
|
||||
# if it is None, it picks it up from default company currency, which might be unintended
|
||||
"account_currency": self.account_currency,
|
||||
"parent_account": parent_acc_name_map[company]
|
||||
})
|
||||
|
||||
doc.save()
|
||||
frappe.msgprint(_("Account {0} is added in the child company {1}")
|
||||
.format(doc.name, company))
|
||||
elif child_account:
|
||||
# update the parent company's value in child companies
|
||||
doc = frappe.get_doc("Account", child_account)
|
||||
parent_value_changed = False
|
||||
for field in ['account_type', 'account_currency',
|
||||
'freeze_account', 'balance_must_be']:
|
||||
if doc.get(field) != self.get(field):
|
||||
parent_value_changed = True
|
||||
doc.set(field, self.get(field))
|
||||
|
||||
if parent_value_changed:
|
||||
doc.save()
|
||||
|
||||
def convert_group_to_ledger(self):
|
||||
if self.check_if_child_exists():
|
||||
throw(_("Account with child nodes cannot be converted to ledger"))
|
||||
|
||||
@@ -1,465 +1,466 @@
|
||||
{
|
||||
"country_code": "ae",
|
||||
"name": "U.A.E - Chart of Accounts",
|
||||
"country_code": "ae",
|
||||
"name": "U.A.E - Chart of Accounts",
|
||||
"tree": {
|
||||
"Assets": {
|
||||
"Current Assets": {
|
||||
"Accounts Receivable": {
|
||||
"Corporate Credit Cards": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"Other Receivable": {
|
||||
"Accrued Rebates Due from Suppliers": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
"Accured Income from Suppliers": {
|
||||
},
|
||||
"Accrued Income from Suppliers": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"Other Debtors": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"Post Dated Cheques Received": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"Staff Receivable": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"Trade Receivable": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"Trade in Opening Fees": {
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"account_type": "Receivable"
|
||||
},
|
||||
},
|
||||
"Cash in Hand & Banks": {
|
||||
"Banks": {
|
||||
"Bank Margin On LC & LG": {},
|
||||
"Banks Blocked Deposits": {},
|
||||
"Banks Call Deposit Accounts": {},
|
||||
"Bank Margin On LC & LG": {},
|
||||
"Banks Blocked Deposits": {},
|
||||
"Banks Call Deposit Accounts": {},
|
||||
"Banks Current Accounts": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"Cash in Hand": {
|
||||
"Cash in Safe": {
|
||||
"Main Safe": {
|
||||
"account_type": "Cash"
|
||||
},
|
||||
},
|
||||
"Main Safe - Foreign Currency": {
|
||||
"account_type": "Cash"
|
||||
}
|
||||
},
|
||||
},
|
||||
"Petty Cash": {
|
||||
"Petty Cash - Admininistration": {
|
||||
"account_type": "Cash"
|
||||
},
|
||||
},
|
||||
"Petty Cash - Others": {
|
||||
"account_type": "Cash"
|
||||
}
|
||||
},
|
||||
},
|
||||
"account_type": "Cash"
|
||||
},
|
||||
},
|
||||
"Cash in Transit": {
|
||||
"Credit Cards": {
|
||||
"Gateway Credit Cards": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"Manual Visa & Master Cards": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"PayPal Account": {
|
||||
"account_type": "Bank"
|
||||
},
|
||||
},
|
||||
"Visa & Master Credit Cards": {
|
||||
"account_type": "Bank"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Inventory": {
|
||||
"Consigned Stock": {
|
||||
"Handling Difference in Inventory": {
|
||||
"account_type": "Stock Adjustment"
|
||||
},
|
||||
"Items Delivered to Customs on temprary Base": {}
|
||||
},
|
||||
"Handling Difference in Inventory": {},
|
||||
"Items Delivered to Customs on temporary Base": {}
|
||||
},
|
||||
"Stock in Hand": {
|
||||
"account_type": "Stock"
|
||||
}
|
||||
},
|
||||
"Perliminary and Preoperating Expenses": {
|
||||
},
|
||||
"Preliminary and Preoperating Expenses": {
|
||||
"Preoperating Expenses": {}
|
||||
},
|
||||
},
|
||||
"Prepayments & Deposits": {
|
||||
"Deposits": {
|
||||
"Deposit - Office Rent": {},
|
||||
"Deposit Others": {},
|
||||
"Deposit to Immigration (Visa)": {},
|
||||
"Deposit - Office Rent": {},
|
||||
"Deposit Others": {},
|
||||
"Deposit to Immigration (Visa)": {},
|
||||
"Deposits - Customs": {}
|
||||
},
|
||||
},
|
||||
"Prepaid Taxes": {
|
||||
"Sales Taxes Receivables": {},
|
||||
"Sales Taxes Receivables": {},
|
||||
"Withholding Tax Receivables": {}
|
||||
},
|
||||
},
|
||||
"Prepayments": {
|
||||
"Other Prepayments": {},
|
||||
"PrePaid Advertisement Expenses": {},
|
||||
"Prepaid Bank Guarantee": {},
|
||||
"Prepaid Consultancy Fees": {},
|
||||
"Prepaid Employees Housing": {},
|
||||
"Prepaid Finance charge for Loans": {},
|
||||
"Prepaid Legal Fees": {},
|
||||
"Prepaid License Fees": {},
|
||||
"Prepaid Life Insurance": {},
|
||||
"Prepaid Maintenance": {},
|
||||
"Prepaid Medical Insurance": {},
|
||||
"Prepaid Office Rent": {},
|
||||
"Prepaid Other Insurance": {},
|
||||
"Prepaid Schooling Fees": {},
|
||||
"Prepaid Site Hosting Fees": {},
|
||||
"Other Prepayments": {},
|
||||
"PrePaid Advertisement Expenses": {},
|
||||
"Prepaid Bank Guarantee": {},
|
||||
"Prepaid Consultancy Fees": {},
|
||||
"Prepaid Employees Housing": {},
|
||||
"Prepaid Finance charge for Loans": {},
|
||||
"Prepaid Legal Fees": {},
|
||||
"Prepaid License Fees": {},
|
||||
"Prepaid Life Insurance": {},
|
||||
"Prepaid Maintenance": {},
|
||||
"Prepaid Medical Insurance": {},
|
||||
"Prepaid Office Rent": {},
|
||||
"Prepaid Other Insurance": {},
|
||||
"Prepaid Schooling Fees": {},
|
||||
"Prepaid Site Hosting Fees": {},
|
||||
"Prepaid Sponsorship Fees": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Long Term Assets": {
|
||||
"Fixed Assets": {
|
||||
"Accumulated Depreciation": {
|
||||
"Acc. Depreciation of Motor Vehicles": {
|
||||
"account_type": "Accumulated Depreciation"
|
||||
},
|
||||
},
|
||||
"Acc. Deprn.Computer Hardware & Software": {
|
||||
"account_type": "Accumulated Depreciation"
|
||||
},
|
||||
},
|
||||
"Acc.Deprn.of Furniture & Office Equipment": {
|
||||
"account_type": "Accumulated Depreciation"
|
||||
},
|
||||
},
|
||||
"Amortisation on Leasehold Improvement": {
|
||||
"account_type": "Accumulated Depreciation"
|
||||
},
|
||||
},
|
||||
"account_type": "Accumulated Depreciation"
|
||||
},
|
||||
},
|
||||
"Fixed Assets (Cost Price)": {
|
||||
"Computer Hardware & Software": {
|
||||
"account_type": "Fixed Asset"
|
||||
},
|
||||
},
|
||||
"Furniture and Equipment": {
|
||||
"account_type": "Fixed Asset"
|
||||
},
|
||||
"Leasehold Improvement": {},
|
||||
"Motor Vehicules": {
|
||||
},
|
||||
"Leasehold Improvement": {},
|
||||
"Motor Vehicles": {
|
||||
"account_type": "Fixed Asset"
|
||||
},
|
||||
"Work In Progrees": {},
|
||||
},
|
||||
"Work In Progress": {},
|
||||
"account_type": "Fixed Asset"
|
||||
}
|
||||
},
|
||||
},
|
||||
"Intangible Assets": {
|
||||
"Computer Card Renewal": {},
|
||||
"Dispoal of Outlets": {},
|
||||
"Computer Card Renewal": {},
|
||||
"Disposal of Outlets": {},
|
||||
"Registration of Trademarks": {}
|
||||
},
|
||||
"Intercompany Accounts": {},
|
||||
},
|
||||
"Intercompany Accounts": {},
|
||||
"Investments": {
|
||||
"Investments in Subsidiaries": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"root_type": "Asset"
|
||||
},
|
||||
},
|
||||
"Closing And Temporary Accounts": {
|
||||
"Closing Accounts": {
|
||||
"Closing Account": {}
|
||||
},
|
||||
},
|
||||
"root_type": "Liability"
|
||||
},
|
||||
},
|
||||
"Expenses": {
|
||||
"Commercial Expenses": {
|
||||
"Consultancy Fees": {},
|
||||
"Consultancy Fees": {},
|
||||
"Provision for Doubtful Debts": {}
|
||||
},
|
||||
},
|
||||
"Cost of Sale": {
|
||||
"Cost Of Goods Sold": {
|
||||
"Cost Of Goods Sold I/C Sales": {},
|
||||
"Cost Of Goods Sold I/C Sales": {},
|
||||
"Cost of Goods Sold in Trading": {
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
},
|
||||
"account_type": "Cost of Goods Sold"
|
||||
},
|
||||
},
|
||||
"Expenses Included In Valuation": {
|
||||
"account_type": "Expenses Included In Valuation"
|
||||
},
|
||||
"Stock Adjustment": {
|
||||
"account_type": "Stock Adjustment"
|
||||
}
|
||||
},
|
||||
},
|
||||
"Depreciation": {
|
||||
"Depreciation & Amortization": {
|
||||
"Amortization on Leasehold Improvement": {},
|
||||
"Amortization on Leasehold Improvement": {},
|
||||
"Depreciation Of Computer Hard & Soft": {
|
||||
"account_type": "Depreciation"
|
||||
},
|
||||
},
|
||||
"Depreciation Of Furniture & Office Equipment\n\t\t\t": {
|
||||
"account_type": "Depreciation"
|
||||
},
|
||||
},
|
||||
"Depreciation Of Motor Vehicles": {
|
||||
"account_type": "Depreciation"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Direct Expenses": {
|
||||
"Financial Charges": {
|
||||
"Air Miles Card Charges": {},
|
||||
"Amex Credit Cards Charges": {},
|
||||
"Bank Finance & Loan Charges": {},
|
||||
"Credit Card Charges": {},
|
||||
"Credit Card Swipe Charges": {},
|
||||
"Air Miles Card Charges": {},
|
||||
"Amex Credit Cards Charges": {},
|
||||
"Bank Finance & Loan Charges": {},
|
||||
"Credit Card Charges": {},
|
||||
"Credit Card Swipe Charges": {},
|
||||
"PayPal Charges": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"MISC Charges": {
|
||||
"Other Charges": {
|
||||
"Captial Loss": {
|
||||
"Disposal of Business Branch": {},
|
||||
"Loss On Fixed Assets Disposal": {},
|
||||
"Capital Loss": {
|
||||
"Disposal of Business Branch": {},
|
||||
"Loss On Fixed Assets Disposal": {},
|
||||
"Loss on Difference on Exchange": {}
|
||||
},
|
||||
},
|
||||
"Other Non Operating Exp": {
|
||||
"Other Non Operating Expenses": {}
|
||||
},
|
||||
},
|
||||
"Previous Year Adjustments": {
|
||||
"Previous Year Adjustments Account": {}
|
||||
},
|
||||
},
|
||||
"Royalty Fees": {
|
||||
"Royalty to Parent Co.": {}
|
||||
},
|
||||
},
|
||||
"Tax / Zakat Expenses": {
|
||||
"Income Tax": {
|
||||
"account_type": "Tax"
|
||||
},
|
||||
"Zakat": {},
|
||||
},
|
||||
"Zakat": {},
|
||||
"account_type": "Tax"
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Share Resources": {
|
||||
"Share Resource Expenses Account": {}
|
||||
},
|
||||
},
|
||||
"Store Operating Expenses": {
|
||||
"Selling, General & Admin Expenses": {
|
||||
"Advertising Expenses": {
|
||||
"Other - Advertising Expenses": {}
|
||||
},
|
||||
},
|
||||
"Bank & Finance Charges": {
|
||||
"Other Bank Charges": {}
|
||||
},
|
||||
},
|
||||
"Communications": {
|
||||
"Courrier": {},
|
||||
"Others - Communication": {},
|
||||
"Telephone": {},
|
||||
"Courier": {},
|
||||
"Others - Communication": {},
|
||||
"Telephone": {},
|
||||
"Web Site Hosting Fees": {}
|
||||
},
|
||||
},
|
||||
"Office & Various Expenses": {
|
||||
"Cleaning": {},
|
||||
"Convoyance Expenses": {},
|
||||
"Gifts & Donations": {},
|
||||
"Insurance": {},
|
||||
"Kitchen and Buffet Expenses": {},
|
||||
"Maintenance": {},
|
||||
"Others - Office Various Expenses": {},
|
||||
"Security & Guard": {},
|
||||
"Stationary From Suppliers": {},
|
||||
"Stationary Out Of Stock": {},
|
||||
"Subscriptions": {},
|
||||
"Training": {},
|
||||
"Cleaning": {},
|
||||
"Conveyance Expenses": {},
|
||||
"Gifts & Donations": {},
|
||||
"Insurance": {},
|
||||
"Kitchen and Buffet Expenses": {},
|
||||
"Maintenance": {},
|
||||
"Others - Office Various Expenses": {},
|
||||
"Security & Guard": {},
|
||||
"Stationary From Suppliers": {},
|
||||
"Stationary Out Of Stock": {},
|
||||
"Subscriptions": {},
|
||||
"Training": {},
|
||||
"Vehicle Expenses": {}
|
||||
},
|
||||
},
|
||||
"Personnel Cost": {
|
||||
"Basic Salary": {},
|
||||
"End Of Service Indemnity": {},
|
||||
"Housing Allowance": {},
|
||||
"Leave Salary": {},
|
||||
"Leave Ticket": {},
|
||||
"Life Insurance": {},
|
||||
"Medical Insurance": {},
|
||||
"Personnel Cost Others": {},
|
||||
"Sales Commission": {},
|
||||
"Staff School Allowances": {},
|
||||
"Transportation Allowance": {},
|
||||
"Uniform": {},
|
||||
"Basic Salary": {},
|
||||
"End Of Service Indemnity": {},
|
||||
"Housing Allowance": {},
|
||||
"Leave Salary": {},
|
||||
"Leave Ticket": {},
|
||||
"Life Insurance": {},
|
||||
"Medical Insurance": {},
|
||||
"Personnel Cost Others": {},
|
||||
"Sales Commission": {},
|
||||
"Staff School Allowances": {},
|
||||
"Transportation Allowance": {},
|
||||
"Uniform": {},
|
||||
"Visa Expenses": {}
|
||||
},
|
||||
},
|
||||
"Professional & Legal Fees": {
|
||||
"Audit Fees": {},
|
||||
"Legal fees": {},
|
||||
"Others - Professional Fees": {},
|
||||
"Sponsorship Fees": {},
|
||||
"Audit Fees": {},
|
||||
"Legal fees": {},
|
||||
"Others - Professional Fees": {},
|
||||
"Sponsorship Fees": {},
|
||||
"Trade License Fees": {}
|
||||
},
|
||||
},
|
||||
"Provision & Write Off": {
|
||||
"Amortisation of Preoperating Expenses": {},
|
||||
"Cash Shortage": {},
|
||||
"Others - Provision & Write off": {},
|
||||
"Write Off Inventory": {},
|
||||
"Amortisation of Preoperating Expenses": {},
|
||||
"Cash Shortage": {},
|
||||
"Others - Provision & Write off": {},
|
||||
"Write Off Inventory": {},
|
||||
"Write Off Receivables & Payables": {}
|
||||
},
|
||||
},
|
||||
"Rent Expenses": {
|
||||
"Office Rent": {},
|
||||
"Office Rent": {},
|
||||
"Warehouse Rent": {}
|
||||
},
|
||||
},
|
||||
"Travel Expenses": {
|
||||
"Air tickets": {},
|
||||
"Hotel": {},
|
||||
"Meals": {},
|
||||
"Others": {},
|
||||
"Air tickets": {},
|
||||
"Hotel": {},
|
||||
"Meals": {},
|
||||
"Others": {},
|
||||
"Per Diem": {}
|
||||
},
|
||||
},
|
||||
"Utilities": {
|
||||
"Other Utility Cahrges": {},
|
||||
"Other Utility Cahrges": {},
|
||||
"Water & Electricity": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"root_type": "Expense"
|
||||
},
|
||||
},
|
||||
"Liabilities": {
|
||||
"Current Liabilities": {
|
||||
"Accounts Payable": {
|
||||
"Payables": {
|
||||
"Advance Paybale to Suppliers": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
},
|
||||
"Consigned Payable": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
},
|
||||
"Other Payable": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
},
|
||||
"Post Dated Cheques Paid": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
"Staff Payable": {},
|
||||
},
|
||||
"Staff Payable": {},
|
||||
"Suppliers Price Protection": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
},
|
||||
"Trade Payable": {
|
||||
"account_type": "Payable"
|
||||
},
|
||||
},
|
||||
"account_type": "Payable"
|
||||
}
|
||||
},
|
||||
},
|
||||
"Accruals & Provisions": {
|
||||
"Accruals": {
|
||||
"Accrued Personnel Cost": {
|
||||
"Accrued - Commissions": {},
|
||||
"Accrued - Leave Salary": {},
|
||||
"Accrued - Leave Tickets": {},
|
||||
"Accrued - Salaries": {},
|
||||
"Accrued Other Personnel Cost": {},
|
||||
"Accrued Salaries Increment": {},
|
||||
"Accrued - Commissions": {},
|
||||
"Accrued - Leave Salary": {},
|
||||
"Accrued - Leave Tickets": {},
|
||||
"Accrued - Salaries": {},
|
||||
"Accrued Other Personnel Cost": {},
|
||||
"Accrued Salaries Increment": {},
|
||||
"Accrued-Staff Bonus": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Accrued Expenses": {
|
||||
"Accrued Other Expenses": {
|
||||
"Accrued - Audit Fees": {},
|
||||
"Accrued - Office Rent": {},
|
||||
"Accrued - Sponsorship": {},
|
||||
"Accrued - Telephone": {},
|
||||
"Accrued - Utilities": {},
|
||||
"Accrued - Audit Fees": {},
|
||||
"Accrued - Office Rent": {},
|
||||
"Accrued - Sponsorship": {},
|
||||
"Accrued - Telephone": {},
|
||||
"Accrued - Utilities": {},
|
||||
"Accrued Others": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Other Current Liabilities": {
|
||||
"Accrued Dubai Customs": {},
|
||||
"Deferred income": {},
|
||||
"Accrued Dubai Customs": {},
|
||||
"Deferred income": {},
|
||||
"Shipping & Handling": {}
|
||||
},
|
||||
},
|
||||
"Provisions": {
|
||||
"Tax Payables": {
|
||||
"Income Tax Payable": {},
|
||||
"Sales Tax Payable": {},
|
||||
"Income Tax Payable": {},
|
||||
"Sales Tax Payable": {},
|
||||
"Withholding Tax Payable": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Short Term Loan": {}
|
||||
},
|
||||
},
|
||||
"Duties and Taxes": {
|
||||
"account_type": "Tax",
|
||||
"account_type": "Tax",
|
||||
"is_group": 1
|
||||
},
|
||||
},
|
||||
"Reservations & Credit Notes": {
|
||||
"Credit Notes": {
|
||||
"Credit Notes to Customers": {},
|
||||
"Credit Notes to Customers": {},
|
||||
"Reservations": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Stock Liabilities": {
|
||||
"Stock Received But Not Billed": {
|
||||
"account_type": "Stock Received But Not Billed"
|
||||
}
|
||||
},
|
||||
},
|
||||
"Unearned Income": {}
|
||||
},
|
||||
},
|
||||
"Long Term Liabilities": {
|
||||
"Long Term Loans & Provisions": {}
|
||||
},
|
||||
},
|
||||
"root_type": "Liability"
|
||||
},
|
||||
},
|
||||
"Revenue": {
|
||||
"Direct Revenue": {
|
||||
"Other Direct Revenue": {
|
||||
"Other Revenue - Operating": {
|
||||
"Advertising Income": {},
|
||||
"Branding Income": {},
|
||||
"Early Setmt Margin from Suppliers": {},
|
||||
"Marketing Rebate from Suppliers": {},
|
||||
"Rebate from Suppliers": {},
|
||||
"Service Income": {},
|
||||
"Advertising Income": {},
|
||||
"Branding Income": {},
|
||||
"Early Setmt Margin from Suppliers": {},
|
||||
"Marketing Rebate from Suppliers": {},
|
||||
"Rebate from Suppliers": {},
|
||||
"Service Income": {},
|
||||
"Space Rental Income": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Indirect Revenue": {
|
||||
"Other Indirect Revenue": {
|
||||
"Capital Gain": {},
|
||||
"Excess In Till": {},
|
||||
"Gain On Difference Of Exchange": {},
|
||||
"Management Consultancy Fees": {},
|
||||
"Capital Gain": {},
|
||||
"Excess In Till": {},
|
||||
"Gain On Difference Of Exchange": {},
|
||||
"Management Consultancy Fees": {},
|
||||
"Other Income": {}
|
||||
},
|
||||
},
|
||||
"Other Revenue - Non Operating": {
|
||||
"Interest Revenue": {},
|
||||
"Interest from FD": {},
|
||||
"Products Listing Fees from Suppliers": {},
|
||||
"Interest Revenue": {},
|
||||
"Interest from FD": {},
|
||||
"Products Listing Fees from Suppliers": {},
|
||||
"Trade Opening Fees from suppliers": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"Sales": {
|
||||
"Sales from Other Regions": {
|
||||
"Sales from Other Region": {}
|
||||
},
|
||||
},
|
||||
"Sales of same region": {
|
||||
"Management Consultancy Fees 1": {},
|
||||
"Sales Account": {},
|
||||
"Management Consultancy Fees 1": {},
|
||||
"Sales Account": {},
|
||||
"Sales of I/C": {}
|
||||
}
|
||||
},
|
||||
},
|
||||
"root_type": "Income"
|
||||
},
|
||||
},
|
||||
"Share Holder Equity": {
|
||||
"Capital": {
|
||||
"Contributed Capital": {},
|
||||
"Share Capital": {},
|
||||
"Shareholders Current A/c": {},
|
||||
"Sub Ordinated Loan": {},
|
||||
"Contributed Capital": {},
|
||||
"Share Capital": {},
|
||||
"Shareholders Current A/c": {},
|
||||
"Sub Ordinated Loan": {},
|
||||
"Treasury Stocks": {}
|
||||
},
|
||||
},
|
||||
"Retained Earnings": {
|
||||
"Current Year Results": {},
|
||||
"Dividends Paid": {},
|
||||
"Current Year Results": {},
|
||||
"Dividends Paid": {},
|
||||
"Previous Years Results": {}
|
||||
},
|
||||
"account_type": "Equity",
|
||||
},
|
||||
"account_type": "Equity",
|
||||
"root_type": "Equity"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
from frappe.desk.search import sanitize_searchfield
|
||||
|
||||
class BankGuarantee(Document):
|
||||
def validate(self):
|
||||
@@ -22,5 +23,8 @@ class BankGuarantee(Document):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_vouchar_detials(column_list, doctype, docname):
|
||||
column_list = json.loads(column_list)
|
||||
for col in column_list:
|
||||
sanitize_searchfield(col)
|
||||
return frappe.db.sql(''' select {columns} from `tab{doctype}` where name=%s'''
|
||||
.format(columns=", ".join(json.loads(column_list)), doctype=doctype), docname, as_dict=1)[0]
|
||||
|
||||
@@ -92,10 +92,10 @@ frappe.ui.form.on("Journal Entry", {
|
||||
multi_currency: function(frm) {
|
||||
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
|
||||
},
|
||||
|
||||
|
||||
posting_date: function(frm) {
|
||||
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
|
||||
|
||||
|
||||
$.each(frm.doc.accounts || [], function(i, row) {
|
||||
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
|
||||
})
|
||||
@@ -234,7 +234,7 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
|
||||
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
|
||||
}
|
||||
|
||||
|
||||
if(jvd.party_type && jvd.party) {
|
||||
var party_field = "";
|
||||
if(jvd.reference_type.indexOf("Sales")===0) {
|
||||
@@ -382,7 +382,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
|
||||
});
|
||||
refresh_field("accounts");
|
||||
}
|
||||
|
||||
|
||||
if((!(doc.accounts || []).length) || ((doc.accounts || []).length==1 && !doc.accounts[0].account)) {
|
||||
if(in_list(["Bank Entry", "Cash Entry"], doc.voucher_type)) {
|
||||
return frappe.call({
|
||||
@@ -390,7 +390,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
|
||||
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
|
||||
args: {
|
||||
"account_type": (doc.voucher_type=="Bank Entry" ?
|
||||
"Bank" : (doc.voucher_type=="Cash" ? "Cash" : null)),
|
||||
"Bank" : (doc.voucher_type=="Cash Entry" ? "Cash" : null)),
|
||||
"company": doc.company
|
||||
},
|
||||
callback: function(r) {
|
||||
@@ -442,7 +442,7 @@ frappe.ui.form.on("Journal Entry Account", {
|
||||
account: function(frm, dt, dn) {
|
||||
erpnext.journal_entry.set_account_balance(frm, dt, dn);
|
||||
},
|
||||
|
||||
|
||||
debit_in_account_currency: function(frm, cdt, cdn) {
|
||||
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
@@ -294,7 +294,7 @@ frappe.ui.form.on('Payment Entry', {
|
||||
() => {
|
||||
frm.set_party_account_based_on_party = false;
|
||||
if (r.message.bank_account) {
|
||||
frm.set_value("bank_account", r.message.bank_account);
|
||||
frm.set_value("party_bank_account", r.message.bank_account);
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -1791,6 +1791,41 @@
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Draft",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "status",
|
||||
"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": 0,
|
||||
"label": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nDraft\nSubmitted\nCancelled",
|
||||
"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,
|
||||
@@ -2205,7 +2240,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-03-27 17:39:54.163016",
|
||||
"modified": "2019-11-06 15:15:45.223497",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Payment Entry",
|
||||
|
||||
@@ -60,6 +60,7 @@ class PaymentEntry(AccountsController):
|
||||
self.validate_duplicate_entry()
|
||||
self.validate_allocated_amount()
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
self.set_status()
|
||||
|
||||
def on_submit(self):
|
||||
self.setup_party_account_field()
|
||||
@@ -69,6 +70,7 @@ class PaymentEntry(AccountsController):
|
||||
self.update_outstanding_amounts()
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.set_status()
|
||||
|
||||
|
||||
def on_cancel(self):
|
||||
@@ -78,6 +80,7 @@ class PaymentEntry(AccountsController):
|
||||
self.update_advance_paid()
|
||||
self.update_expense_claim()
|
||||
self.delink_advance_entry_references()
|
||||
self.set_status()
|
||||
|
||||
def update_outstanding_amounts(self):
|
||||
self.set_missing_ref_details(force=True)
|
||||
@@ -274,6 +277,14 @@ class PaymentEntry(AccountsController):
|
||||
frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
|
||||
.format(d.reference_name, dr_or_cr))
|
||||
|
||||
def set_status(self):
|
||||
if self.docstatus == 2:
|
||||
self.status = 'Cancelled'
|
||||
elif self.docstatus == 1:
|
||||
self.status = 'Submitted'
|
||||
else:
|
||||
self.status = 'Draft'
|
||||
|
||||
def set_amounts(self):
|
||||
self.set_amounts_in_company_currency()
|
||||
self.set_total_allocated_amount()
|
||||
|
||||
@@ -2454,7 +2454,7 @@
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -4903,7 +4903,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-04-22 12:45:49.728359",
|
||||
"modified": "2020-04-16 19:04:18.599264",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -250,7 +250,7 @@ class PurchaseInvoice(BuyingController):
|
||||
def set_against_expense_account(self):
|
||||
against_accounts = []
|
||||
for item in self.get("items"):
|
||||
if item.expense_account not in against_accounts:
|
||||
if item.expense_account and (item.expense_account not in against_accounts):
|
||||
against_accounts.append(item.expense_account)
|
||||
|
||||
self.against_expense_account = ",".join(against_accounts)
|
||||
@@ -363,7 +363,7 @@ class PurchaseInvoice(BuyingController):
|
||||
update_outstanding = "No" if (cint(self.is_paid) or self.write_off_account) else "Yes"
|
||||
|
||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
|
||||
update_outstanding=update_outstanding, merge_entries=False)
|
||||
update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
|
||||
|
||||
if update_outstanding == "No":
|
||||
update_outstanding_amt(self.credit_to, "Supplier", self.supplier,
|
||||
@@ -750,7 +750,11 @@ class PurchaseInvoice(BuyingController):
|
||||
)
|
||||
|
||||
def make_gle_for_rounding_adjustment(self, gl_entries):
|
||||
if self.rounding_adjustment:
|
||||
# if rounding adjustment in small and conversion rate is also small then
|
||||
# base_rounding_adjustment may become zero due to small precision
|
||||
# eg: rounding_adjustment = 0.01 and exchange rate = 0.05 and precision of base_rounding_adjustment is 2
|
||||
# then base_rounding_adjustment becomes zero and error is thrown in GL Entry
|
||||
if self.rounding_adjustment and self.base_rounding_adjustment:
|
||||
round_off_account, round_off_cost_center = \
|
||||
get_round_off_account_and_cost_center(self.company)
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ frappe.listview_settings['Purchase Invoice'] = {
|
||||
} else if(frappe.datetime.get_diff(doc.due_date) < 0) {
|
||||
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<,Today"];
|
||||
} else {
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due,>=,Today"];
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>=,Today"];
|
||||
}
|
||||
} else if(cint(doc.is_return)) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
|
||||
@@ -2544,7 +2544,7 @@
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -5816,7 +5816,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-04-22 12:45:41.109345",
|
||||
"modified": "2020-04-16 19:05:00.498772",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -350,7 +350,7 @@ class SalesInvoice(SellingController):
|
||||
timesheet.calculate_percentage_billed()
|
||||
timesheet.flags.ignore_validate_update_after_submit = True
|
||||
timesheet.set_status()
|
||||
timesheet.save()
|
||||
timesheet.save(ignore_permissions=True)
|
||||
|
||||
def update_time_sheet_detail(self, timesheet, args, sales_invoice):
|
||||
for data in timesheet.time_logs:
|
||||
@@ -699,7 +699,7 @@ class SalesInvoice(SellingController):
|
||||
cint(self.redeem_loyalty_points)) else "Yes"
|
||||
|
||||
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
|
||||
update_outstanding=update_outstanding, merge_entries=False)
|
||||
update_outstanding=update_outstanding, merge_entries=False, from_repost=from_repost)
|
||||
|
||||
if update_outstanding == "No":
|
||||
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
|
||||
@@ -944,7 +944,7 @@ class SalesInvoice(SellingController):
|
||||
)
|
||||
|
||||
def make_gle_for_rounding_adjustment(self, gl_entries):
|
||||
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")):
|
||||
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")) and self.base_rounding_adjustment:
|
||||
round_off_account, round_off_cost_center = \
|
||||
get_round_off_account_and_cost_center(self.company)
|
||||
|
||||
@@ -992,10 +992,8 @@ class SalesInvoice(SellingController):
|
||||
continue
|
||||
|
||||
for serial_no in item.serial_no.split("\n"):
|
||||
if serial_no and frappe.db.exists('Serial No', serial_no):
|
||||
sno = frappe.get_doc('Serial No', serial_no)
|
||||
sno.sales_invoice = invoice
|
||||
sno.db_update()
|
||||
if serial_no and frappe.db.get_value('Serial No', serial_no, 'item_code') == item.item_code:
|
||||
frappe.db.set_value('Serial No', serial_no, 'sales_invoice', invoice)
|
||||
|
||||
def validate_serial_numbers(self):
|
||||
"""
|
||||
@@ -1041,12 +1039,18 @@ class SalesInvoice(SellingController):
|
||||
continue
|
||||
|
||||
for serial_no in item.serial_no.split("\n"):
|
||||
sales_invoice = frappe.db.get_value("Serial No", serial_no, "sales_invoice")
|
||||
if sales_invoice and self.name != sales_invoice:
|
||||
sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company")
|
||||
serial_no_details = frappe.db.get_value("Serial No", serial_no,
|
||||
["sales_invoice", "item_code"], as_dict=1)
|
||||
|
||||
if not serial_no_details:
|
||||
continue
|
||||
|
||||
if serial_no_details.sales_invoice and serial_no_details.item_code == item.item_code \
|
||||
and self.name != serial_no_details.sales_invoice:
|
||||
sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company")
|
||||
if sales_invoice_company == self.company:
|
||||
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
|
||||
.format(serial_no, sales_invoice)))
|
||||
.format(serial_no, serial_no_details.sales_invoice)))
|
||||
|
||||
def update_project(self):
|
||||
if self.project:
|
||||
|
||||
@@ -16,7 +16,7 @@ frappe.ui.form.on('Share Transfer', {
|
||||
};
|
||||
};
|
||||
});
|
||||
if (frm.doc.docstatus == 1) {
|
||||
if (frm.doc.docstatus == 1 && frm.doc.equity_or_liability_account && frm.doc.asset_account ) {
|
||||
frm.add_custom_button(__('Make Journal Entry'), function () {
|
||||
erpnext.share_transfer.make_jv(frm);
|
||||
});
|
||||
@@ -92,6 +92,7 @@ erpnext.share_transfer.make_jv = function (frm) {
|
||||
debit_applicant_type = "Shareholder";
|
||||
debit_applicant = frm.doc.from_shareholder;
|
||||
}
|
||||
|
||||
frappe.call({
|
||||
args: {
|
||||
"company": frm.doc.company,
|
||||
|
||||
@@ -292,11 +292,14 @@ def make_jv_entry( company, account, amount, payment_account,\
|
||||
"party_type": debit_applicant_type,
|
||||
"party": debit_applicant,
|
||||
})
|
||||
|
||||
account_amt_list.append({
|
||||
"account": payment_account,
|
||||
"credit_in_account_currency": amount,
|
||||
"party_type": credit_applicant_type,
|
||||
"party": credit_applicant,
|
||||
})
|
||||
|
||||
journal_entry.set("accounts", account_amt_list)
|
||||
|
||||
return journal_entry.as_dict()
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
<div class="col-xs-{{ "3" if df.fieldtype=="Check" else "7" }} value">
|
||||
{% if doc.get(df.fieldname) != None -%}
|
||||
{{ frappe.utils.fmt_money((doc[df.fieldname])|int|abs, currency=doc.currency) }}
|
||||
{{ frappe.utils.fmt_money((doc[df.fieldname])|abs, currency=doc.currency) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -26,7 +26,7 @@
|
||||
<div class="col-xs-5 {%- if doc.align_labels_right %} text-right{%- endif -%}">
|
||||
<label>{{ charge.get_formatted("description") }}</label></div>
|
||||
<div class="col-xs-7 text-right">
|
||||
{{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }}
|
||||
{{ frappe.utils.fmt_money((charge.tax_amount)|abs, currency=doc.currency) }}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
@@ -65,8 +65,10 @@
|
||||
{% for tdf in visible_columns %}
|
||||
{% if not d.flags.compact_item_print or tdf.fieldname in doc.get(df.fieldname)[0].flags.compact_item_fields %}
|
||||
<td class="{{ get_align_class(tdf) }}" {{ fieldmeta(df) }}>
|
||||
{% if tdf.fieldtype == 'Currency' %}
|
||||
<div class="value">{{ frappe.utils.fmt_money((d[tdf.fieldname])|int|abs, currency=doc.currency) }}</div></td>
|
||||
{% if tdf.fieldname == 'qty' %}
|
||||
<div class="value">{{ (d[tdf.fieldname])|abs }}</div></td>
|
||||
{% elif tdf.fieldtype == 'Currency' %}
|
||||
<div class="value">{{ frappe.utils.fmt_money((d[tdf.fieldname])|abs, currency=doc.currency) }}</div></td>
|
||||
{% else %}
|
||||
<div class="value">{{ print_value(tdf, d, doc, visible_columns) }}</div></td>
|
||||
{% endif %}
|
||||
@@ -117,7 +119,7 @@
|
||||
{{ render_currency(df, doc) }}
|
||||
{% elif df.fieldtype =='Table' %}
|
||||
{{ render_table(df, doc)}}
|
||||
{% elif doc[df.fieldname] %}
|
||||
{% elif doc[df.fieldname] and df.fieldname != 'total_qty' %}
|
||||
{{ render_field(df, doc) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -58,8 +58,8 @@ class ReceivablePayableReport(object):
|
||||
self.invoices = set()
|
||||
|
||||
def get_data(self):
|
||||
t1 = now()
|
||||
self.get_gl_entries()
|
||||
self.get_sales_invoices_or_customers_based_on_sales_person()
|
||||
self.voucher_balance = OrderedDict()
|
||||
self.init_voucher_balance() # invoiced, paid, credit_note, outstanding
|
||||
|
||||
@@ -72,6 +72,9 @@ class ReceivablePayableReport(object):
|
||||
# fetch future payments against invoices
|
||||
self.get_future_payments()
|
||||
|
||||
# Get return entries
|
||||
self.get_return_entries()
|
||||
|
||||
self.data = []
|
||||
for gle in self.gl_entries:
|
||||
self.update_voucher_balance(gle)
|
||||
@@ -90,6 +93,7 @@ class ReceivablePayableReport(object):
|
||||
party = gle.party,
|
||||
posting_date = gle.posting_date,
|
||||
remarks = gle.remarks,
|
||||
account_currency = gle.account_currency,
|
||||
invoiced = 0.0,
|
||||
paid = 0.0,
|
||||
credit_note = 0.0,
|
||||
@@ -99,13 +103,18 @@ class ReceivablePayableReport(object):
|
||||
|
||||
def get_invoices(self, gle):
|
||||
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
|
||||
self.invoices.add(gle.voucher_no)
|
||||
if self.filters.get("sales_person"):
|
||||
if gle.voucher_no in self.sales_person_records.get("Sales Invoice", []) \
|
||||
or gle.party in self.sales_person_records.get("Customer", []):
|
||||
self.invoices.add(gle.voucher_no)
|
||||
else:
|
||||
self.invoices.add(gle.voucher_no)
|
||||
|
||||
def update_voucher_balance(self, gle):
|
||||
# get the row where this balance needs to be updated
|
||||
# if its a payment, it will return the linked invoice or will be considered as advance
|
||||
row = self.get_voucher_balance(gle)
|
||||
|
||||
if not row: return
|
||||
# gle_balance will be the total "debit - credit" for receivable type reports and
|
||||
# and vice-versa for payable type reports
|
||||
gle_balance = self.get_gle_balance(gle)
|
||||
@@ -126,11 +135,27 @@ class ReceivablePayableReport(object):
|
||||
row.paid -= gle_balance
|
||||
|
||||
def get_voucher_balance(self, gle):
|
||||
voucher_balance = None
|
||||
if self.filters.get("sales_person"):
|
||||
against_voucher = gle.against_voucher or gle.voucher_no
|
||||
if not (gle.party in self.sales_person_records.get("Customer", []) or \
|
||||
against_voucher in self.sales_person_records.get("Sales Invoice", [])):
|
||||
return
|
||||
|
||||
voucher_balance = None
|
||||
if gle.against_voucher:
|
||||
# find invoice
|
||||
voucher_balance = self.voucher_balance.get((gle.against_voucher_type, gle.against_voucher, gle.party))
|
||||
against_voucher = gle.against_voucher
|
||||
|
||||
# If payment is made against credit note
|
||||
# and credit note is made against a Sales Invoice
|
||||
# then consider the payment against original sales invoice.
|
||||
if gle.against_voucher_type in ('Sales Invoice', 'Purchase Invoice'):
|
||||
if gle.against_voucher in self.return_entries:
|
||||
return_against = self.return_entries.get(gle.against_voucher)
|
||||
if return_against:
|
||||
against_voucher = return_against
|
||||
|
||||
voucher_balance = self.voucher_balance.get((gle.against_voucher_type, against_voucher, gle.party))
|
||||
|
||||
if not voucher_balance:
|
||||
# no invoice, this is an invoice / stand-alone payment / credit note
|
||||
@@ -174,7 +199,11 @@ class ReceivablePayableReport(object):
|
||||
self.data.append(row)
|
||||
|
||||
def set_invoice_details(self, row):
|
||||
row.update(self.invoice_details.get(row.voucher_no, {}))
|
||||
invoice_details = self.invoice_details.get(row.voucher_no, {})
|
||||
if row.due_date:
|
||||
invoice_details.pop("due_date", None)
|
||||
row.update(invoice_details)
|
||||
|
||||
if row.voucher_type == 'Sales Invoice':
|
||||
if self.filters.show_delivery_notes:
|
||||
self.set_delivery_notes(row)
|
||||
@@ -257,7 +286,6 @@ class ReceivablePayableReport(object):
|
||||
# customer / supplier name
|
||||
party_details = self.get_party_details(row.party)
|
||||
row.update(party_details)
|
||||
|
||||
if self.filters.get(scrub(self.filters.party_type)):
|
||||
row.currency = row.account_currency
|
||||
else:
|
||||
@@ -422,6 +450,19 @@ class ReceivablePayableReport(object):
|
||||
if row.future_ref:
|
||||
row.future_ref = ', '.join(row.future_ref)
|
||||
|
||||
def get_return_entries(self):
|
||||
doctype = "Sales Invoice" if self.party_type == "Customer" else "Purchase Invoice"
|
||||
filters={
|
||||
'is_return': 1,
|
||||
'docstatus': 1
|
||||
}
|
||||
party_field = scrub(self.filters.party_type)
|
||||
if self.filters.get(party_field):
|
||||
filters.update({party_field: self.filters.get(party_field)})
|
||||
self.return_entries = frappe._dict(
|
||||
frappe.get_all(doctype, filters, ['name', 'return_against'], as_list=1)
|
||||
)
|
||||
|
||||
def set_ageing(self, row):
|
||||
if self.filters.ageing_based_on == "Due Date":
|
||||
entry_date = row.due_date
|
||||
@@ -482,6 +523,22 @@ class ReceivablePayableReport(object):
|
||||
order by posting_date, party"""
|
||||
.format(select_fields, conditions), values, as_dict=True)
|
||||
|
||||
def get_sales_invoices_or_customers_based_on_sales_person(self):
|
||||
if self.filters.get("sales_person"):
|
||||
lft, rgt = frappe.db.get_value("Sales Person",
|
||||
self.filters.get("sales_person"), ["lft", "rgt"])
|
||||
|
||||
records = frappe.db.sql("""
|
||||
select distinct parent, parenttype
|
||||
from `tabSales Team` steam
|
||||
where parenttype in ('Customer', 'Sales Invoice')
|
||||
and exists(select name from `tabSales Person` where lft >= %s and rgt <= %s and name = steam.sales_person)
|
||||
""", (lft, rgt), as_dict=1)
|
||||
|
||||
self.sales_person_records = frappe._dict()
|
||||
for d in records:
|
||||
self.sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
|
||||
|
||||
def prepare_conditions(self):
|
||||
conditions = [""]
|
||||
values = [self.party_type, self.filters.report_date]
|
||||
@@ -532,16 +589,6 @@ class ReceivablePayableReport(object):
|
||||
conditions.append("party in (select name from tabCustomer where default_sales_partner=%s)")
|
||||
values.append(self.filters.get("sales_partner"))
|
||||
|
||||
if self.filters.get("sales_person"):
|
||||
lft, rgt = frappe.db.get_value("Sales Person",
|
||||
self.filters.get("sales_person"), ["lft", "rgt"])
|
||||
|
||||
conditions.append("""exists(select name from `tabSales Team` steam where
|
||||
steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1})
|
||||
and ((steam.parent = voucher_no and steam.parenttype = voucher_type)
|
||||
or (steam.parent = against_voucher and steam.parenttype = against_voucher_type)
|
||||
or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt))
|
||||
|
||||
def add_supplier_filters(self, conditions, values):
|
||||
if self.filters.get("supplier_group"):
|
||||
conditions.append("""party in (select name from tabSupplier
|
||||
@@ -677,11 +724,11 @@ class ReceivablePayableReport(object):
|
||||
def get_chart_data(self):
|
||||
rows = []
|
||||
for row in self.data:
|
||||
rows.append(
|
||||
{
|
||||
'values': [row.range1, row.range2, row.range3, row.range4, row.range5]
|
||||
}
|
||||
)
|
||||
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
|
||||
precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||
rows.append({
|
||||
'values': [flt(val, precision) for val in values]
|
||||
})
|
||||
|
||||
self.chart = {
|
||||
"data": {
|
||||
|
||||
@@ -36,6 +36,9 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
self.filters.report_date) or {}
|
||||
|
||||
for party, party_dict in iteritems(self.party_total):
|
||||
if party_dict.outstanding == 0:
|
||||
continue
|
||||
|
||||
row = frappe._dict()
|
||||
|
||||
row.party = party
|
||||
@@ -132,4 +135,4 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
"{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
|
||||
"{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
|
||||
"{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]):
|
||||
self.add_column(label=label, fieldname='range' + str(i+1))
|
||||
self.add_column(label=label, fieldname='range' + str(i+1))
|
||||
|
||||
@@ -4,126 +4,141 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import formatdate, getdate, flt, add_days
|
||||
from frappe.utils import formatdate, flt, add_days
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
filters.day_before_from_date = add_days(filters.from_date, -1)
|
||||
columns, data = get_columns(filters), get_data(filters)
|
||||
return columns, data
|
||||
|
||||
|
||||
|
||||
def get_data(filters):
|
||||
data = []
|
||||
|
||||
|
||||
asset_categories = get_asset_categories(filters)
|
||||
assets = get_assets(filters)
|
||||
asset_costs = get_asset_costs(assets, filters)
|
||||
asset_depreciations = get_accumulated_depreciations(assets, filters)
|
||||
|
||||
|
||||
for asset_category in asset_categories:
|
||||
row = frappe._dict()
|
||||
row.asset_category = asset_category
|
||||
row.update(asset_costs.get(asset_category))
|
||||
# row.asset_category = asset_category
|
||||
row.update(asset_category)
|
||||
|
||||
row.cost_as_on_to_date = (flt(row.cost_as_on_from_date) + flt(row.cost_of_new_purchase) -
|
||||
flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset))
|
||||
|
||||
row.update(next(asset for asset in assets if asset["asset_category"] == asset_category.get("asset_category", "")))
|
||||
row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) +
|
||||
flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
|
||||
|
||||
row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) -
|
||||
flt(row.accumulated_depreciation_as_on_from_date))
|
||||
|
||||
row.net_asset_value_as_on_to_date = (flt(row.cost_as_on_to_date) -
|
||||
flt(row.accumulated_depreciation_as_on_to_date))
|
||||
|
||||
row.cost_as_on_to_date = (flt(row.cost_as_on_from_date) + flt(row.cost_of_new_purchase)
|
||||
- flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset))
|
||||
|
||||
row.update(asset_depreciations.get(asset_category))
|
||||
row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) +
|
||||
flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
|
||||
|
||||
row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) -
|
||||
flt(row.accumulated_depreciation_as_on_from_date))
|
||||
|
||||
row.net_asset_value_as_on_to_date = (flt(row.cost_as_on_to_date) -
|
||||
flt(row.accumulated_depreciation_as_on_to_date))
|
||||
|
||||
data.append(row)
|
||||
|
||||
|
||||
return data
|
||||
|
||||
|
||||
|
||||
def get_asset_categories(filters):
|
||||
return frappe.db.sql_list("""
|
||||
select distinct asset_category from `tabAsset`
|
||||
where docstatus=1 and company=%s and purchase_date <= %s
|
||||
""", (filters.company, filters.to_date))
|
||||
|
||||
return frappe.db.sql("""
|
||||
SELECT asset_category,
|
||||
ifnull(sum(case when purchase_date < %(from_date)s then
|
||||
case when ifnull(disposal_date, 0) = 0 or disposal_date >= %(from_date)s then
|
||||
gross_purchase_amount
|
||||
else
|
||||
0
|
||||
end
|
||||
else
|
||||
0
|
||||
end), 0) as cost_as_on_from_date,
|
||||
ifnull(sum(case when purchase_date >= %(from_date)s then
|
||||
gross_purchase_amount
|
||||
else
|
||||
0
|
||||
end), 0) as cost_of_new_purchase,
|
||||
ifnull(sum(case when ifnull(disposal_date, 0) != 0
|
||||
and disposal_date >= %(from_date)s
|
||||
and disposal_date <= %(to_date)s then
|
||||
case when status = "Sold" then
|
||||
gross_purchase_amount
|
||||
else
|
||||
0
|
||||
end
|
||||
else
|
||||
0
|
||||
end), 0) as cost_of_sold_asset,
|
||||
ifnull(sum(case when ifnull(disposal_date, 0) != 0
|
||||
and disposal_date >= %(from_date)s
|
||||
and disposal_date <= %(to_date)s then
|
||||
case when status = "Scrapped" then
|
||||
gross_purchase_amount
|
||||
else
|
||||
0
|
||||
end
|
||||
else
|
||||
0
|
||||
end), 0) as cost_of_scrapped_asset
|
||||
from `tabAsset`
|
||||
where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s
|
||||
group by asset_category
|
||||
""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
|
||||
|
||||
|
||||
def get_assets(filters):
|
||||
return frappe.db.sql("""
|
||||
select name, asset_category, purchase_date, gross_purchase_amount, disposal_date, status
|
||||
from `tabAsset`
|
||||
where docstatus=1 and company=%s and purchase_date <= %s""",
|
||||
(filters.company, filters.to_date), as_dict=1)
|
||||
|
||||
def get_asset_costs(assets, filters):
|
||||
asset_costs = frappe._dict()
|
||||
for d in assets:
|
||||
asset_costs.setdefault(d.asset_category, frappe._dict({
|
||||
"cost_as_on_from_date": 0,
|
||||
"cost_of_new_purchase": 0,
|
||||
"cost_of_sold_asset": 0,
|
||||
"cost_of_scrapped_asset": 0
|
||||
}))
|
||||
|
||||
costs = asset_costs[d.asset_category]
|
||||
|
||||
if getdate(d.purchase_date) < getdate(filters.from_date):
|
||||
if not d.disposal_date or getdate(d.disposal_date) >= getdate(filters.from_date):
|
||||
costs.cost_as_on_from_date += flt(d.gross_purchase_amount)
|
||||
else:
|
||||
costs.cost_of_new_purchase += flt(d.gross_purchase_amount)
|
||||
|
||||
if d.disposal_date and getdate(d.disposal_date) >= getdate(filters.from_date) \
|
||||
and getdate(d.disposal_date) <= getdate(filters.to_date):
|
||||
if d.status == "Sold":
|
||||
costs.cost_of_sold_asset += flt(d.gross_purchase_amount)
|
||||
elif d.status == "Scrapped":
|
||||
costs.cost_of_scrapped_asset += flt(d.gross_purchase_amount)
|
||||
|
||||
return asset_costs
|
||||
|
||||
def get_accumulated_depreciations(assets, filters):
|
||||
asset_depreciations = frappe._dict()
|
||||
for d in assets:
|
||||
asset = frappe.get_doc("Asset", d.name)
|
||||
|
||||
if d.asset_category in asset_depreciations:
|
||||
asset_depreciations[d.asset_category]['accumulated_depreciation_as_on_from_date'] += asset.opening_accumulated_depreciation
|
||||
else:
|
||||
asset_depreciations.setdefault(d.asset_category, frappe._dict({
|
||||
"accumulated_depreciation_as_on_from_date": asset.opening_accumulated_depreciation,
|
||||
"depreciation_amount_during_the_period": 0,
|
||||
"depreciation_eliminated_during_the_period": 0
|
||||
}))
|
||||
SELECT results.asset_category,
|
||||
sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
|
||||
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
|
||||
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
|
||||
from (SELECT a.asset_category,
|
||||
ifnull(sum(a.opening_accumulated_depreciation +
|
||||
case when ds.schedule_date < %(from_date)s and
|
||||
(ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
|
||||
ds.depreciation_amount
|
||||
else
|
||||
0
|
||||
end), 0) as accumulated_depreciation_as_on_from_date,
|
||||
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
|
||||
and a.disposal_date <= %(to_date)s and ds.schedule_date <= a.disposal_date then
|
||||
ds.depreciation_amount
|
||||
else
|
||||
0
|
||||
end), 0) as depreciation_eliminated_during_the_period,
|
||||
|
||||
depr = asset_depreciations[d.asset_category]
|
||||
ifnull(sum(case when ds.schedule_date >= %(from_date)s and ds.schedule_date <= %(to_date)s
|
||||
and (ifnull(a.disposal_date, 0) = 0 or ds.schedule_date <= a.disposal_date) then
|
||||
ds.depreciation_amount
|
||||
else
|
||||
0
|
||||
end), 0) as depreciation_amount_during_the_period
|
||||
from `tabAsset` a, `tabDepreciation Schedule` ds
|
||||
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent
|
||||
group by a.asset_category
|
||||
union
|
||||
SELECT a.asset_category,
|
||||
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
|
||||
and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then
|
||||
0
|
||||
else
|
||||
a.opening_accumulated_depreciation
|
||||
end), 0) as accumulated_depreciation_as_on_from_date,
|
||||
ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
|
||||
a.opening_accumulated_depreciation
|
||||
else
|
||||
0
|
||||
end), 0) as depreciation_eliminated_during_the_period,
|
||||
0 as depreciation_amount_during_the_period
|
||||
from `tabAsset` a
|
||||
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s
|
||||
and not exists(select * from `tabDepreciation Schedule` ds where a.name = ds.parent)
|
||||
group by a.asset_category) as results
|
||||
group by results.asset_category
|
||||
""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
|
||||
|
||||
if not asset.schedules: # if no schedule,
|
||||
if asset.disposal_date:
|
||||
# and disposal is NOT within the period, then opening accumulated depreciation not included
|
||||
if getdate(asset.disposal_date) < getdate(filters.from_date) or getdate(asset.disposal_date) > getdate(filters.to_date):
|
||||
asset_depreciations[d.asset_category]['accumulated_depreciation_as_on_from_date'] = 0
|
||||
|
||||
# if no schedule, and disposal is within period, accumulated dep is the amount eliminated
|
||||
if getdate(asset.disposal_date) >= getdate(filters.from_date) and getdate(asset.disposal_date) <= getdate(filters.to_date):
|
||||
depr.depreciation_eliminated_during_the_period += asset.opening_accumulated_depreciation
|
||||
|
||||
for schedule in asset.get("schedules"):
|
||||
if getdate(schedule.schedule_date) < getdate(filters.from_date):
|
||||
if not asset.disposal_date or getdate(asset.disposal_date) >= getdate(filters.from_date):
|
||||
depr.accumulated_depreciation_as_on_from_date += flt(schedule.depreciation_amount)
|
||||
elif getdate(schedule.schedule_date) <= getdate(filters.to_date):
|
||||
if not asset.disposal_date:
|
||||
depr.depreciation_amount_during_the_period += flt(schedule.depreciation_amount)
|
||||
else:
|
||||
if getdate(schedule.schedule_date) <= getdate(asset.disposal_date):
|
||||
depr.depreciation_amount_during_the_period += flt(schedule.depreciation_amount)
|
||||
|
||||
if asset.disposal_date and getdate(asset.disposal_date) >= getdate(filters.from_date) and getdate(asset.disposal_date) <= getdate(filters.to_date):
|
||||
if getdate(schedule.schedule_date) <= getdate(asset.disposal_date):
|
||||
depr.depreciation_eliminated_during_the_period += flt(schedule.depreciation_amount)
|
||||
|
||||
return asset_depreciations
|
||||
|
||||
def get_columns(filters):
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
frappe.query_reports["Balance Sheet"] = erpnext.financial_statements;
|
||||
frappe.query_reports["Balance Sheet"] = $.extend({}, erpnext.financial_statements);
|
||||
|
||||
frappe.query_reports["Balance Sheet"]["filters"].push({
|
||||
"fieldname": "accumulated_values",
|
||||
|
||||
@@ -286,14 +286,14 @@ class PartyLedgerSummaryReport(object):
|
||||
|
||||
if parties and accounts:
|
||||
if len(parties) == 1:
|
||||
party = parties.keys()[0]
|
||||
party = list(parties.keys())[0]
|
||||
for account, amount in iteritems(accounts):
|
||||
self.party_adjustment_accounts.add(account)
|
||||
self.party_adjustment_details.setdefault(party, {})
|
||||
self.party_adjustment_details[party].setdefault(account, 0)
|
||||
self.party_adjustment_details[party][account] += amount
|
||||
elif len(accounts) == 1 and not has_irrelevant_entry:
|
||||
account = accounts.keys()[0]
|
||||
account = list(accounts.keys())[0]
|
||||
self.party_adjustment_accounts.add(account)
|
||||
for party, amount in iteritems(parties):
|
||||
self.party_adjustment_details.setdefault(party, {})
|
||||
|
||||
@@ -154,28 +154,31 @@ class GrossProfitGenerator(object):
|
||||
def get_average_rate_based_on_group_by(self):
|
||||
# sum buying / selling totals for group
|
||||
for key in list(self.grouped):
|
||||
for i, row in enumerate(self.grouped[key]):
|
||||
if row.parent in self.returned_invoices \
|
||||
and row.item_code in self.returned_invoices[row.parent]:
|
||||
returned_item_rows = self.returned_invoices[row.parent][row.item_code]
|
||||
for returned_item_row in returned_item_rows:
|
||||
row.qty += returned_item_row.qty
|
||||
row.base_amount += flt(returned_item_row.base_amount, self.currency_precision)
|
||||
row.buying_amount = flt(row.qty * row.buying_rate, self.currency_precision)
|
||||
|
||||
if i==0:
|
||||
new_row = row
|
||||
elif self.filters.get("group_by") != "Invoice":
|
||||
new_row.qty += row.qty
|
||||
new_row.buying_amount += flt(row.buying_amount, self.currency_precision)
|
||||
new_row.base_amount += flt(row.base_amount, self.currency_precision)
|
||||
|
||||
if self.filters.get("group_by") == "Invoice" and (row.qty or row.base_amount):
|
||||
self.grouped_data_based_on_group_by(row)
|
||||
|
||||
if self.filters.get("group_by") != "Invoice":
|
||||
for i, row in enumerate(self.grouped[key]):
|
||||
if i==0:
|
||||
new_row = row
|
||||
else:
|
||||
new_row.qty += row.qty
|
||||
new_row.buying_amount += flt(row.buying_amount, self.currency_precision)
|
||||
new_row.base_amount += flt(row.base_amount, self.currency_precision)
|
||||
new_row = self.set_average_rate(new_row)
|
||||
self.grouped_data.append(new_row)
|
||||
else:
|
||||
for i, row in enumerate(self.grouped[key]):
|
||||
if row.parent in self.returned_invoices \
|
||||
and row.item_code in self.returned_invoices[row.parent]:
|
||||
returned_item_rows = self.returned_invoices[row.parent][row.item_code]
|
||||
for returned_item_row in returned_item_rows:
|
||||
row.qty += returned_item_row.qty
|
||||
row.base_amount += flt(returned_item_row.base_amount, self.currency_precision)
|
||||
row.buying_amount = flt(row.qty * row.buying_rate, self.currency_precision)
|
||||
if row.qty or row.base_amount:
|
||||
row = self.set_average_rate(row)
|
||||
self.grouped_data.append(row)
|
||||
self.grouped_data_based_on_group_by(new_row)
|
||||
|
||||
def grouped_data_based_on_group_by(self, row):
|
||||
row = self.set_average_rate(row)
|
||||
self.grouped_data.append(row)
|
||||
|
||||
def set_average_rate(self, new_row):
|
||||
new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision)
|
||||
@@ -204,10 +207,7 @@ class GrossProfitGenerator(object):
|
||||
.setdefault(inv.item_code, []).append(inv)
|
||||
|
||||
def skip_row(self, row, product_bundles):
|
||||
if self.filters.get("group_by") != "Invoice":
|
||||
if not row.get(scrub(self.filters.get("group_by", ""))):
|
||||
return True
|
||||
elif row.get("is_return") == 1:
|
||||
if row.get("is_return") == 1:
|
||||
return True
|
||||
|
||||
def get_buying_amount_from_product_bundle(self, row, product_bundle):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import flt
|
||||
from frappe.model.meta import get_field_precision
|
||||
from frappe import msgprint, _
|
||||
|
||||
def execute(filters=None):
|
||||
@@ -69,6 +70,7 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
|
||||
if tax_acc not in income_accounts:
|
||||
tax_amount_precision = get_field_precision(frappe.get_meta("Sales Taxes and Charges").get_field("tax_amount"), currency=company_currency) or 2
|
||||
tax_amount = flt(invoice_tax_map.get(inv.name, {}).get(tax_acc), tax_amount_precision)
|
||||
total_tax += tax_amount
|
||||
row.append(tax_amount)
|
||||
|
||||
# total tax, grand total, outstanding amount & rounded total
|
||||
|
||||
@@ -75,8 +75,7 @@ def get_data(filters):
|
||||
accumulate_values_into_parents(accounts, accounts_by_name)
|
||||
|
||||
data = prepare_data(accounts, filters, total_row, parent_children_map, company_currency)
|
||||
data = filter_out_zero_value_rows(data, parent_children_map,
|
||||
show_zero_values=filters.get("show_zero_values"))
|
||||
data = filter_out_zero_value_rows(data, parent_children_map, show_zero_values=filters.get("show_zero_values"))
|
||||
|
||||
return data
|
||||
|
||||
@@ -175,33 +174,11 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances, filters,
|
||||
|
||||
d["closing_debit"] = d["opening_debit"] + d["debit"]
|
||||
d["closing_credit"] = d["opening_credit"] + d["credit"]
|
||||
total_row["debit"] += d["debit"]
|
||||
total_row["credit"] += d["credit"]
|
||||
|
||||
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
|
||||
d["opening_debit"] -= d["opening_credit"]
|
||||
d["closing_debit"] -= d["closing_credit"]
|
||||
prepare_opening_closing(d)
|
||||
|
||||
# For opening
|
||||
check_opening_closing_has_negative_value(d, "opening_debit", "opening_credit")
|
||||
|
||||
# For closing
|
||||
check_opening_closing_has_negative_value(d, "closing_debit", "closing_credit")
|
||||
|
||||
if d["root_type"] == "Liability" or d["root_type"] == "Income":
|
||||
d["opening_credit"] -= d["opening_debit"]
|
||||
d["closing_credit"] -= d["closing_debit"]
|
||||
|
||||
# For opening
|
||||
check_opening_closing_has_negative_value(d, "opening_credit", "opening_debit")
|
||||
|
||||
# For closing
|
||||
check_opening_closing_has_negative_value(d, "closing_credit", "closing_debit")
|
||||
|
||||
total_row["opening_debit"] += d["opening_debit"]
|
||||
total_row["closing_debit"] += d["closing_debit"]
|
||||
total_row["opening_credit"] += d["opening_credit"]
|
||||
total_row["closing_credit"] += d["closing_credit"]
|
||||
for field in value_fields:
|
||||
total_row[field] += d[field]
|
||||
|
||||
return total_row
|
||||
|
||||
@@ -215,6 +192,10 @@ def prepare_data(accounts, filters, total_row, parent_children_map, company_curr
|
||||
data = []
|
||||
|
||||
for d in accounts:
|
||||
# Prepare opening closing for group account
|
||||
if parent_children_map.get(d.account):
|
||||
prepare_opening_closing(d)
|
||||
|
||||
has_value = False
|
||||
row = {
|
||||
"account": d.name,
|
||||
@@ -301,11 +282,16 @@ def get_columns():
|
||||
}
|
||||
]
|
||||
|
||||
def check_opening_closing_has_negative_value(d, dr_or_cr, switch_to_column):
|
||||
# If opening debit has negetive value then move it to opening credit and vice versa.
|
||||
def prepare_opening_closing(row):
|
||||
dr_or_cr = "debit" if row["root_type"] in ["Asset", "Equity", "Expense"] else "credit"
|
||||
reverse_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit"
|
||||
|
||||
if d[dr_or_cr] < 0:
|
||||
d[switch_to_column] = abs(d[dr_or_cr])
|
||||
d[dr_or_cr] = 0.0
|
||||
else:
|
||||
d[switch_to_column] = 0.0
|
||||
for col_type in ["opening", "closing"]:
|
||||
valid_col = col_type + "_" + dr_or_cr
|
||||
reverse_col = col_type + "_" + reverse_dr_or_cr
|
||||
row[valid_col] -= row[reverse_col]
|
||||
if row[valid_col] < 0:
|
||||
row[reverse_col] = abs(row[valid_col])
|
||||
row[valid_col] = 0.0
|
||||
else:
|
||||
row[reverse_col] = 0.0
|
||||
@@ -18,14 +18,17 @@ def execute(filters=None):
|
||||
return columns, data
|
||||
|
||||
def get_data(filters, show_party_name):
|
||||
party_name_field = "{0}_name".format(frappe.scrub(filters.get('party_type')))
|
||||
if filters.get('party_type') in ('Customer', 'Supplier', 'Employee', 'Member'):
|
||||
party_name_field = "{0}_name".format(frappe.scrub(filters.get('party_type')))
|
||||
if filters.get('party_type') == 'Student':
|
||||
party_name_field = 'first_name'
|
||||
elif filters.get('party_type') == 'Shareholder':
|
||||
party_name_field = 'title'
|
||||
else:
|
||||
party_name_field = 'name'
|
||||
|
||||
party_filters = {"name": filters.get("party")} if filters.get("party") else {}
|
||||
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field],
|
||||
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field],
|
||||
filters = party_filters, order_by="name")
|
||||
company_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
|
||||
opening_balances = get_opening_balances(filters)
|
||||
@@ -70,7 +73,7 @@ def get_data(filters, show_party_name):
|
||||
# totals
|
||||
for col in total_row:
|
||||
total_row[col] += row.get(col)
|
||||
|
||||
|
||||
row.update({
|
||||
"currency": company_currency
|
||||
})
|
||||
@@ -78,7 +81,7 @@ def get_data(filters, show_party_name):
|
||||
has_value = False
|
||||
if (opening_debit or opening_credit or debit or credit or closing_debit or closing_credit):
|
||||
has_value =True
|
||||
|
||||
|
||||
if cint(filters.show_zero_values) or has_value:
|
||||
data.append(row)
|
||||
|
||||
@@ -94,9 +97,9 @@ def get_data(filters, show_party_name):
|
||||
|
||||
def get_opening_balances(filters):
|
||||
gle = frappe.db.sql("""
|
||||
select party, sum(debit) as opening_debit, sum(credit) as opening_credit
|
||||
select party, sum(debit) as opening_debit, sum(credit) as opening_credit
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s
|
||||
where company=%(company)s
|
||||
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
|
||||
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
|
||||
group by party""", {
|
||||
@@ -114,11 +117,11 @@ def get_opening_balances(filters):
|
||||
|
||||
def get_balances_within_period(filters):
|
||||
gle = frappe.db.sql("""
|
||||
select party, sum(debit) as debit, sum(credit) as credit
|
||||
select party, sum(debit) as debit, sum(credit) as credit
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s
|
||||
where company=%(company)s
|
||||
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
|
||||
and posting_date >= %(from_date)s and posting_date <= %(to_date)s
|
||||
and posting_date >= %(from_date)s and posting_date <= %(to_date)s
|
||||
and ifnull(is_opening, 'No') = 'No'
|
||||
group by party""", {
|
||||
"company": filters.company,
|
||||
|
||||
@@ -2176,7 +2176,7 @@
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -3948,7 +3948,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-06-24 20:55:03.466766",
|
||||
"modified": "2020-04-16 18:54:54.840653",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1395,7 +1395,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -2845,7 +2845,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-01-07 16:52:01.505553",
|
||||
"modified": "2020-04-16 19:05:41.924303",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Supplier Quotation",
|
||||
|
||||
@@ -138,7 +138,7 @@ def refresh_scorecards():
|
||||
# Check to see if any new scorecard periods are created
|
||||
if make_all_scorecards(sc.name) > 0:
|
||||
# Save the scorecard to update the score and standings
|
||||
sc.save()
|
||||
frappe.get_doc('Supplier Scorecard', sc.name).save()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -375,9 +375,10 @@ class AccountsController(TransactionBase):
|
||||
return gl_dict
|
||||
|
||||
def validate_qty_is_not_zero(self):
|
||||
for item in self.items:
|
||||
if not item.qty:
|
||||
frappe.throw(_("Item quantity can not be zero"))
|
||||
if self.doctype != "Purchase Receipt":
|
||||
for item in self.items:
|
||||
if not item.qty:
|
||||
frappe.throw(_("Item quantity can not be zero"))
|
||||
|
||||
def validate_account_currency(self, account, account_currency=None):
|
||||
valid_currency = [self.company_currency]
|
||||
@@ -1097,6 +1098,8 @@ def get_supplier_block_status(party_name):
|
||||
@frappe.whitelist()
|
||||
def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
|
||||
data = json.loads(trans_items)
|
||||
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
|
||||
|
||||
for d in data:
|
||||
child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
|
||||
|
||||
@@ -1114,8 +1117,26 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
|
||||
else:
|
||||
child_item.rate = flt(d.get("rate"))
|
||||
if flt(child_item.price_list_rate):
|
||||
child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0, \
|
||||
child_item.precision("discount_percentage"))
|
||||
if flt(child_item.rate) > flt(child_item.price_list_rate):
|
||||
# if rate is greater than price_list_rate, set margin
|
||||
# or set discount
|
||||
child_item.discount_percentage = 0
|
||||
|
||||
if parent_doctype in sales_doctypes:
|
||||
child_item.margin_type = "Amount"
|
||||
child_item.margin_rate_or_amount = flt(child_item.rate - child_item.price_list_rate,
|
||||
child_item.precision("margin_rate_or_amount"))
|
||||
child_item.rate_with_margin = child_item.rate
|
||||
else:
|
||||
child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0,
|
||||
child_item.precision("discount_percentage"))
|
||||
child_item.discount_amount = flt(
|
||||
child_item.price_list_rate) - flt(child_item.rate)
|
||||
|
||||
if parent_doctype in sales_doctypes:
|
||||
child_item.margin_type = ""
|
||||
child_item.margin_rate_or_amount = 0
|
||||
child_item.rate_with_margin = 0
|
||||
|
||||
child_item.flags.ignore_validate_update_after_submit = True
|
||||
child_item.save()
|
||||
|
||||
@@ -515,10 +515,15 @@ class BuyingController(StockController):
|
||||
for d in self.get('supplied_items'):
|
||||
# negative quantity is passed, as raw material qty has to be decreased
|
||||
# when PR is submitted and it has to be increased when PR is cancelled
|
||||
incoming_rate = 0
|
||||
if self.is_return and self.return_against and self.docstatus==1:
|
||||
incoming_rate = self.get_incoming_rate_for_sales_return(d.rm_item_code, self.return_against)
|
||||
|
||||
sl_entries.append(self.get_sl_entries(d, {
|
||||
"item_code": d.rm_item_code,
|
||||
"warehouse": self.supplier_warehouse,
|
||||
"actual_qty": -1*flt(d.consumed_qty),
|
||||
"incoming_rate": incoming_rate
|
||||
}))
|
||||
|
||||
def on_submit(self):
|
||||
|
||||
@@ -292,6 +292,7 @@ def copy_attributes_to_variant(item, variant):
|
||||
if not variant.description:
|
||||
variant.description = ""
|
||||
|
||||
else:
|
||||
if item.variant_based_on=='Item Attribute':
|
||||
if variant.attributes:
|
||||
attributes_description = item.description + " "
|
||||
@@ -299,7 +300,7 @@ def copy_attributes_to_variant(item, variant):
|
||||
attributes_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
|
||||
|
||||
if attributes_description not in variant.description:
|
||||
variant.description += attributes_description
|
||||
variant.description = attributes_description
|
||||
|
||||
def make_variant_item_code(template_item_code, template_item_name, variant):
|
||||
"""Uses template's item code and abbreviations to make variant's item code"""
|
||||
|
||||
@@ -152,6 +152,24 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
|
||||
conditions = []
|
||||
|
||||
#Get searchfields from meta and use in Item Link field query
|
||||
meta = frappe.get_meta("Item", cached=True)
|
||||
searchfields = meta.get_search_fields()
|
||||
|
||||
if "description" in searchfields:
|
||||
searchfields.remove("description")
|
||||
|
||||
columns = ''
|
||||
extra_searchfields = [field for field in searchfields
|
||||
if field not in ["name", "item_group", "description"]]
|
||||
|
||||
if extra_searchfields:
|
||||
columns = ", " + ", ".join(extra_searchfields)
|
||||
|
||||
searchfields = searchfields + [field for field in[searchfield or "name", "item_code", "item_group", "item_name"]
|
||||
if not field in searchfields]
|
||||
searchfields = " or ".join([field + " like %(txt)s" for field in searchfields])
|
||||
|
||||
description_cond = ''
|
||||
if frappe.db.count('Item', cache=True) < 50000:
|
||||
# scan description only if items are less than 50000
|
||||
@@ -162,17 +180,14 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
|
||||
tabItem.item_group,
|
||||
if(length(tabItem.description) > 40, \
|
||||
concat(substr(tabItem.description, 1, 40), "..."), description) as decription
|
||||
concat(substr(tabItem.description, 1, 40), "..."), description) as description
|
||||
{columns}
|
||||
from tabItem
|
||||
where tabItem.docstatus < 2
|
||||
and tabItem.has_variants=0
|
||||
and tabItem.disabled=0
|
||||
and (tabItem.end_of_life > %(today)s or ifnull(tabItem.end_of_life, '0000-00-00')='0000-00-00')
|
||||
and (tabItem.`{key}` LIKE %(txt)s
|
||||
or tabItem.item_code LIKE %(txt)s
|
||||
or tabItem.item_group LIKE %(txt)s
|
||||
or tabItem.item_name LIKE %(txt)s
|
||||
or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
|
||||
and ({scond} or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
|
||||
{description_cond})
|
||||
{fcond} {mcond}
|
||||
order by
|
||||
@@ -182,6 +197,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
name, item_name
|
||||
limit %(start)s, %(page_len)s """.format(
|
||||
key=searchfield,
|
||||
columns=columns,
|
||||
scond=searchfields,
|
||||
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
|
||||
mcond=get_match_cond(doctype).replace('%', '%%'),
|
||||
description_cond = description_cond),
|
||||
@@ -280,22 +297,32 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
"page_len": page_len
|
||||
}
|
||||
|
||||
having_clause = "having sum(sle.actual_qty) > 0"
|
||||
if filters.get("is_return"):
|
||||
having_clause = ""
|
||||
|
||||
if args.get('warehouse'):
|
||||
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom, concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
||||
from `tabStock Ledger Entry` sle
|
||||
INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
|
||||
where
|
||||
batch.disabled = 0
|
||||
and sle.item_code = %(item_code)s
|
||||
and sle.warehouse = %(warehouse)s
|
||||
and (sle.batch_no like %(txt)s
|
||||
or batch.manufacturing_date like %(txt)s)
|
||||
and batch.docstatus < 2
|
||||
{0}
|
||||
{match_conditions}
|
||||
group by batch_no having sum(sle.actual_qty) > 0
|
||||
order by batch.expiry_date, sle.batch_no desc
|
||||
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
|
||||
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
|
||||
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
||||
from `tabStock Ledger Entry` sle
|
||||
INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
|
||||
where
|
||||
batch.disabled = 0
|
||||
and sle.item_code = %(item_code)s
|
||||
and sle.warehouse = %(warehouse)s
|
||||
and (sle.batch_no like %(txt)s
|
||||
or batch.expiry_date like %(txt)s
|
||||
or batch.manufacturing_date like %(txt)s)
|
||||
and batch.docstatus < 2
|
||||
{cond}
|
||||
{match_conditions}
|
||||
group by batch_no {having_clause}
|
||||
order by batch.expiry_date, sle.batch_no desc
|
||||
limit %(start)s, %(page_len)s""".format(
|
||||
cond=cond,
|
||||
match_conditions=get_match_cond(doctype),
|
||||
having_clause = having_clause
|
||||
), args)
|
||||
|
||||
return batch_nos
|
||||
else:
|
||||
@@ -303,6 +330,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
where batch.disabled = 0
|
||||
and item = %(item_code)s
|
||||
and (name like %(txt)s
|
||||
or expiry_date like %(txt)s
|
||||
or manufacturing_date like %(txt)s)
|
||||
and docstatus < 2
|
||||
{0}
|
||||
|
||||
@@ -72,7 +72,7 @@ def validate_returned_items(doc):
|
||||
|
||||
items_returned = False
|
||||
for d in doc.get("items"):
|
||||
if d.item_code and (flt(d.qty) < 0 or d.get('received_qty') < 0):
|
||||
if d.item_code and (flt(d.qty) < 0 or flt(d.get('received_qty')) < 0):
|
||||
if d.item_code not in valid_items:
|
||||
frappe.throw(_("Row # {0}: Returned Item {1} does not exists in {2} {3}")
|
||||
.format(d.idx, d.item_code, doc.doctype, doc.return_against))
|
||||
|
||||
@@ -306,8 +306,9 @@ class SellingController(StockController):
|
||||
if flt(d.conversion_factor)==0.0:
|
||||
d.conversion_factor = get_conversion_factor(d.item_code, d.uom).get("conversion_factor") or 1.0
|
||||
return_rate = 0
|
||||
if cint(self.is_return) and self.return_against and self.docstatus==1:
|
||||
return_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
|
||||
if cint(self.is_return) and self.docstatus==1:
|
||||
return_rate = self.get_incoming_rate_for_sales_return(d.item_code,
|
||||
d.warehouse, self.return_against)
|
||||
|
||||
# On cancellation or if return entry submission, make stock ledger entry for
|
||||
# target warehouse first, to update serial no values properly
|
||||
|
||||
@@ -54,6 +54,7 @@ class StockController(AccountsController):
|
||||
gl_list = []
|
||||
warehouse_with_no_account = []
|
||||
|
||||
precision = frappe.get_precision('GL Entry', 'debit_in_account_currency')
|
||||
for item_row in voucher_details:
|
||||
sle_list = sle_map.get(item_row.name)
|
||||
if sle_list:
|
||||
@@ -79,7 +80,7 @@ class StockController(AccountsController):
|
||||
"against": item_row.expense_account,
|
||||
"cost_center": item_row.cost_center,
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"debit": flt(sle.stock_value_difference, 2),
|
||||
"debit": flt(sle.stock_value_difference, precision),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||
}, warehouse_account[sle.warehouse]["account_currency"]))
|
||||
|
||||
@@ -89,7 +90,7 @@ class StockController(AccountsController):
|
||||
"against": warehouse_account[sle.warehouse]["account"],
|
||||
"cost_center": item_row.cost_center,
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"credit": flt(sle.stock_value_difference, 2),
|
||||
"credit": flt(sle.stock_value_difference, precision),
|
||||
"project": item_row.get("project") or self.get("project"),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No"
|
||||
}))
|
||||
@@ -299,7 +300,7 @@ class StockController(AccountsController):
|
||||
|
||||
return serialized_items
|
||||
|
||||
def get_incoming_rate_for_sales_return(self, item_code, against_document):
|
||||
def get_incoming_rate_for_sales_return(self, item_code, warehouse, against_document):
|
||||
incoming_rate = 0.0
|
||||
if against_document and item_code:
|
||||
incoming_rate = frappe.db.sql("""select abs(stock_value_difference / actual_qty)
|
||||
@@ -308,6 +309,9 @@ class StockController(AccountsController):
|
||||
and item_code = %s limit 1""",
|
||||
(self.doctype, against_document, item_code))
|
||||
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
|
||||
else:
|
||||
incoming_rate = get_valuation_rate(item_code, warehouse,
|
||||
self.doctype, against_document, company=self.company, currency=self.currency)
|
||||
|
||||
return incoming_rate
|
||||
|
||||
|
||||
@@ -305,11 +305,19 @@ class calculate_taxes_and_totals(object):
|
||||
last_tax = self.doc.get("taxes")[-1]
|
||||
non_inclusive_tax_amount = sum([flt(d.tax_amount_after_discount_amount)
|
||||
for d in self.doc.get("taxes") if not d.included_in_print_rate])
|
||||
|
||||
diff = self.doc.total + non_inclusive_tax_amount \
|
||||
- flt(last_tax.total, last_tax.precision("total"))
|
||||
|
||||
# If discount amount applied, deduct the discount amount
|
||||
# because self.doc.total is always without discount, but last_tax.total is after discount
|
||||
if self.discount_amount_applied and self.doc.discount_amount:
|
||||
diff -= flt(self.doc.discount_amount)
|
||||
|
||||
diff = flt(diff, self.doc.precision("rounding_adjustment"))
|
||||
|
||||
if diff and abs(diff) <= (5.0 / 10**last_tax.precision("tax_amount")):
|
||||
self.doc.rounding_adjustment = flt(flt(self.doc.rounding_adjustment) +
|
||||
flt(diff), self.doc.precision("rounding_adjustment"))
|
||||
self.doc.rounding_adjustment = diff
|
||||
|
||||
def calculate_totals(self):
|
||||
self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt(self.doc.rounding_adjustment) \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1468,7 +1468,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-05-17 19:03:32.740910",
|
||||
"modified": "2019-10-22 11:11:32.740910",
|
||||
"modified_by": "Administrator",
|
||||
"module": "CRM",
|
||||
"name": "Opportunity",
|
||||
|
||||
@@ -67,7 +67,7 @@ def get_communication_details(filters):
|
||||
communication_count = None
|
||||
communication_list = []
|
||||
opportunities = frappe.db.get_values('Opportunity', {'opportunity_from': 'Lead'},\
|
||||
['name', 'customer_name', 'lead', 'contact_email'], as_dict=1)
|
||||
['name', 'customer_name', 'contact_email'], as_dict=1)
|
||||
|
||||
for d in opportunities:
|
||||
invoice = frappe.db.sql('''
|
||||
|
||||
@@ -234,14 +234,17 @@ def get_order_taxes(shopify_order, shopify_settings):
|
||||
return taxes
|
||||
|
||||
def update_taxes_with_shipping_lines(taxes, shipping_lines, shopify_settings):
|
||||
"""Shipping lines represents the shipping details,
|
||||
each such shipping detail consists of a list of tax_lines"""
|
||||
for shipping_charge in shipping_lines:
|
||||
taxes.append({
|
||||
"charge_type": _("Actual"),
|
||||
"account_head": get_tax_account_head(shipping_charge),
|
||||
"description": shipping_charge["title"],
|
||||
"tax_amount": shipping_charge["price"],
|
||||
"cost_center": shopify_settings.cost_center
|
||||
})
|
||||
for tax in shipping_charge.get("tax_lines"):
|
||||
taxes.append({
|
||||
"charge_type": _("Actual"),
|
||||
"account_head": get_tax_account_head(tax),
|
||||
"description": tax["title"],
|
||||
"tax_amount": tax["price"],
|
||||
"cost_center": shopify_settings.cost_center
|
||||
})
|
||||
|
||||
return taxes
|
||||
|
||||
|
||||
@@ -114,10 +114,11 @@ def add_account_subtype(account_subtype):
|
||||
|
||||
@frappe.whitelist()
|
||||
def sync_transactions(bank, bank_account):
|
||||
|
||||
last_sync_date = frappe.db.get_value("Bank Account", bank_account, "last_integration_date")
|
||||
if last_sync_date:
|
||||
start_date = formatdate(last_sync_date, "YYYY-MM-dd")
|
||||
'''Sync transactions based on the last integration date as the start date, after sync is completed
|
||||
add the transaction date of the oldest transaction as the last integration date'''
|
||||
last_transaction_date = frappe.db.get_value("Bank Account", bank_account, "last_integration_date")
|
||||
if last_transaction_date:
|
||||
start_date = formatdate(last_transaction_date, "YYYY-MM-dd")
|
||||
else:
|
||||
start_date = formatdate(add_months(today(), -12), "YYYY-MM-dd")
|
||||
end_date = formatdate(today(), "YYYY-MM-dd")
|
||||
@@ -125,13 +126,17 @@ def sync_transactions(bank, bank_account):
|
||||
try:
|
||||
transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date)
|
||||
result = []
|
||||
if transactions:
|
||||
for transaction in transactions:
|
||||
result.append(new_bank_transaction(transaction))
|
||||
for transaction in reversed(transactions):
|
||||
result += new_bank_transaction(transaction)
|
||||
|
||||
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", getdate(end_date))
|
||||
if result:
|
||||
last_transaction_date = frappe.db.get_value('Bank Transaction', result.pop(), 'date')
|
||||
|
||||
frappe.logger().info("Plaid added {} new Bank Transactions from '{}' between {} and {}".format(
|
||||
len(result), bank_account, start_date, end_date))
|
||||
|
||||
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", last_transaction_date)
|
||||
|
||||
return result
|
||||
except Exception:
|
||||
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import json
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import get_request_session
|
||||
from requests.exceptions import HTTPError
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||
from erpnext.erpnext_integrations.utils import get_webhook_address
|
||||
from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log
|
||||
@@ -39,24 +40,28 @@ class ShopifySettings(Document):
|
||||
def register_webhooks(self):
|
||||
webhooks = ["orders/create", "orders/paid", "orders/fulfilled"]
|
||||
|
||||
url = get_shopify_url('admin/webhooks.json', self)
|
||||
url = get_shopify_url('admin/api/2020-04/webhooks.json', self)
|
||||
created_webhooks = [d.method for d in self.webhooks]
|
||||
|
||||
for method in webhooks:
|
||||
if method in created_webhooks:
|
||||
continue
|
||||
|
||||
session = get_request_session()
|
||||
try:
|
||||
d = session.post(url, data=json.dumps({
|
||||
res = session.post(url, data=json.dumps({
|
||||
"webhook": {
|
||||
"topic": method,
|
||||
"address": get_webhook_address(connector_name='shopify_connection', method='store_request_data'),
|
||||
"format": "json"
|
||||
}
|
||||
}), headers=get_header(self))
|
||||
d.raise_for_status()
|
||||
self.update_webhook_table(method, d.json())
|
||||
res.raise_for_status()
|
||||
self.update_webhook_table(method, res.json())
|
||||
|
||||
except HTTPError as e:
|
||||
error_message = res.json().get('errors', e)
|
||||
make_shopify_log(status="Warning", exception=error_message, rollback=True)
|
||||
|
||||
except Exception as e:
|
||||
make_shopify_log(status="Warning", message=e.message, exception=False)
|
||||
|
||||
@@ -65,13 +70,18 @@ class ShopifySettings(Document):
|
||||
deleted_webhooks = []
|
||||
|
||||
for d in self.webhooks:
|
||||
url = get_shopify_url('admin/webhooks/{0}.json'.format(d.webhook_id), self)
|
||||
url = get_shopify_url('admin/api/2020-04/webhooks/{0}.json'.format(d.webhook_id), self)
|
||||
try:
|
||||
res = session.delete(url, headers=get_header(self))
|
||||
res.raise_for_status()
|
||||
deleted_webhooks.append(d)
|
||||
|
||||
except HTTPError as e:
|
||||
error_message = res.json().get('errors', e)
|
||||
make_shopify_log(status="Warning", exception=error_message, rollback=True)
|
||||
|
||||
except Exception as e:
|
||||
frappe.log_error(message=frappe.get_traceback(), title=e.message[:140])
|
||||
frappe.log_error(message=e, title='Shopify Webhooks Issue')
|
||||
|
||||
for d in deleted_webhooks:
|
||||
self.remove(d)
|
||||
@@ -144,4 +154,3 @@ def setup_custom_fields():
|
||||
}
|
||||
|
||||
create_custom_fields(custom_fields)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings impo
|
||||
shopify_variants_attr_list = ["option1", "option2", "option3"]
|
||||
|
||||
def sync_item_from_shopify(shopify_settings, item):
|
||||
url = get_shopify_url("/admin/products/{0}.json".format(item.get("product_id")), shopify_settings)
|
||||
url = get_shopify_url("admin/api/2020-04/products/{0}.json".format(item.get("product_id")), shopify_settings)
|
||||
session = get_request_session()
|
||||
|
||||
try:
|
||||
|
||||
@@ -386,5 +386,5 @@ def get_procedure_prescribed(patient):
|
||||
return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
|
||||
ct.encounter_date, pp.practitioner, pp.date, pp.department
|
||||
from `tabPatient Encounter` ct, `tabProcedure Prescription` pp
|
||||
where ct.patient='{0}' and pp.parent=ct.name and pp.appointment_booked=0
|
||||
order by ct.creation desc""".format(patient))
|
||||
where ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
|
||||
order by ct.creation desc""", {"patient": patient})
|
||||
|
||||
@@ -233,7 +233,6 @@ scheduler_events = {
|
||||
],
|
||||
"daily": [
|
||||
"erpnext.stock.reorder_item.reorder_item",
|
||||
"erpnext.setup.doctype.email_digest.email_digest.send",
|
||||
"erpnext.support.doctype.issue.issue.auto_close_tickets",
|
||||
"erpnext.crm.doctype.opportunity.opportunity.auto_close_opportunity",
|
||||
"erpnext.controllers.accounts_controller.update_invoice_status",
|
||||
@@ -252,6 +251,7 @@ scheduler_events = {
|
||||
"erpnext.projects.doctype.project.project.send_project_status_email_to_users"
|
||||
],
|
||||
"daily_long": [
|
||||
"erpnext.setup.doctype.email_digest.email_digest.send",
|
||||
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms"
|
||||
],
|
||||
"monthly_long": [
|
||||
|
||||
@@ -48,12 +48,17 @@ def get_abbreviated_name(name, company):
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
condition = ''
|
||||
var_dict = {
|
||||
"name": get_root_of("Department"),
|
||||
"parent": parent,
|
||||
"company": company,
|
||||
}
|
||||
if company == parent:
|
||||
condition = "name='{0}'".format(get_root_of("Department"))
|
||||
condition = "name=%(name)s"
|
||||
elif company:
|
||||
condition = "parent_department='{0}' and company='{1}'".format(parent, company)
|
||||
condition = "parent_department=%(parent)s and company=%(company)s"
|
||||
else:
|
||||
condition = "parent_department = '{0}'".format(parent)
|
||||
condition = "parent_department = %(parent)s"
|
||||
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
@@ -62,7 +67,7 @@ def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
from `tab{doctype}`
|
||||
where
|
||||
{condition}
|
||||
order by name""".format(doctype=doctype, condition=condition), as_dict=1)
|
||||
order by name""".format(doctype=doctype, condition=condition), var_dict, as_dict=1)
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_node():
|
||||
|
||||
@@ -157,10 +157,11 @@ class Employee(NestedSet):
|
||||
def validate_status(self):
|
||||
if self.status == 'Left':
|
||||
reports_to = frappe.db.get_all('Employee',
|
||||
filters={'reports_to': self.name}
|
||||
filters={'reports_to': self.name, 'status': "Active"},
|
||||
fields = ['name','employee_name']
|
||||
)
|
||||
if reports_to:
|
||||
link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name) for employee in reports_to]
|
||||
link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name, label=employee.employee_name) for employee in reports_to]
|
||||
throw(_("Employee status cannot be set to 'Left' as following employees are currently reporting to this employee: ")
|
||||
+ ', '.join(link_to_employees), EmployeeLeftValidationError)
|
||||
if not self.relieving_date:
|
||||
|
||||
@@ -7,6 +7,14 @@ frappe.ui.form.on('Employee Onboarding', {
|
||||
frm.add_fetch("employee_onboarding_template", "department", "department");
|
||||
frm.add_fetch("employee_onboarding_template", "designation", "designation");
|
||||
frm.add_fetch("employee_onboarding_template", "employee_grade", "employee_grade");
|
||||
|
||||
frm.set_query('job_offer', function () {
|
||||
return {
|
||||
filters: {
|
||||
'job_applicant': frm.doc.job_applicant
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
|
||||
@@ -13,6 +13,7 @@ class Loan(AccountsController):
|
||||
def validate(self):
|
||||
validate_repayment_method(self.repayment_method, self.loan_amount, self.monthly_repayment_amount, self.repayment_periods)
|
||||
self.set_missing_fields()
|
||||
self.validate_loan_application()
|
||||
self.make_repayment_schedule()
|
||||
self.set_repayment_period()
|
||||
self.calculate_totals()
|
||||
@@ -33,6 +34,13 @@ class Loan(AccountsController):
|
||||
if self.status == "Repaid/Closed":
|
||||
self.total_amount_paid = self.total_payment
|
||||
|
||||
def validate_loan_application(self):
|
||||
if self.loan_application:
|
||||
loan = frappe.db.get_value("Loan", {"loan_application": self.loan_application}, "name")
|
||||
|
||||
if loan and loan != self.name:
|
||||
frappe.throw(_("Loan {0} already created for Loan Application {1}").format(frappe.bold(loan),
|
||||
frappe.bold(self.loan_application)))
|
||||
|
||||
def make_jv_entry(self):
|
||||
self.check_permission('write')
|
||||
@@ -116,6 +124,7 @@ def update_disbursement_status(doc):
|
||||
""", (doc.payment_account, doc.name), as_dict=1)[0]
|
||||
|
||||
disbursement_date = None
|
||||
status = ''
|
||||
if not disbursement or disbursement.disbursed_amount == 0:
|
||||
status = "Sanctioned"
|
||||
elif disbursement.disbursed_amount == doc.loan_amount:
|
||||
|
||||
@@ -23,20 +23,25 @@ frappe.ui.form.on('Loan Application', {
|
||||
},
|
||||
add_toolbar_buttons: function(frm) {
|
||||
if (frm.doc.status == "Approved") {
|
||||
frm.add_custom_button(__('Create Loan'), function() {
|
||||
frappe.call({
|
||||
method: "erpnext.hr.doctype.loan_application.loan_application.make_loan",
|
||||
args: {
|
||||
"source_name": frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
var doc = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).addClass("btn-primary");
|
||||
// show create loan button if loan not created against loan aplication
|
||||
frappe.db.get_value("Loan", {"loan_application": frm.doc.name}, "name", (r) => {
|
||||
if (!r) {
|
||||
frm.add_custom_button(__('Create Loan'), function() {
|
||||
frappe.call({
|
||||
method: "erpnext.hr.doctype.loan_application.loan_application.make_loan",
|
||||
args: {
|
||||
"source_name": frm.doc.name
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
var doc = frappe.model.sync(r.message);
|
||||
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||
}
|
||||
}
|
||||
});
|
||||
}).addClass("btn-primary");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -117,7 +117,7 @@ frappe.ui.form.on("BOM", {
|
||||
args: {
|
||||
update_parent: true,
|
||||
from_child_bom:false,
|
||||
save: false
|
||||
save: frm.doc.docstatus === 1 ? true : false
|
||||
},
|
||||
callback: function(r) {
|
||||
refresh_field("items");
|
||||
|
||||
@@ -34,12 +34,15 @@ class BOM(WebsiteGenerator):
|
||||
# name can be BOM/ITEM/001, BOM/ITEM/001-1, BOM-ITEM-001, BOM-ITEM-001-1
|
||||
|
||||
# split by item
|
||||
names = [name.split(self.item)[-1][1:] for name in names]
|
||||
names = [name.split(self.item, 1) for name in names]
|
||||
names = [d[-1][1:] for d in filter(lambda x: len(x) > 1 and x[-1], names)]
|
||||
|
||||
# split by (-) if cancelled
|
||||
names = [cint(name.split('-')[-1]) for name in names]
|
||||
|
||||
idx = max(names) + 1
|
||||
if names:
|
||||
names = [cint(name.split('-')[-1]) for name in names]
|
||||
idx = max(names) + 1
|
||||
else:
|
||||
idx = 1
|
||||
else:
|
||||
idx = 1
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
@@ -14,10 +15,12 @@
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -41,14 +44,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -72,14 +78,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -103,14 +112,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -132,14 +144,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "quantity",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -162,14 +177,51 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "uom",
|
||||
"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": "UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "actual_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -192,14 +244,86 @@
|
||||
"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,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_details",
|
||||
"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,
|
||||
"label": "Item Description",
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"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": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": "300px",
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "min_order_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -222,14 +346,17 @@
|
||||
"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,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -252,14 +379,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sales_order",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -283,14 +413,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "requested_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -313,6 +446,7 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
@@ -326,7 +460,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-02-15 13:08:30.535963",
|
||||
"modified": "2019-11-08 14:59:58.805613",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Material Request Plan Item",
|
||||
@@ -340,5 +474,6 @@
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
|
||||
@@ -122,6 +122,8 @@ frappe.ui.form.on('Production Plan', {
|
||||
item.quantity = d.quantity;
|
||||
item.sales_order = d.sales_order;
|
||||
item.warehouse = d.warehouse;
|
||||
item.description = d.description;
|
||||
item.uom = d.uom;
|
||||
});
|
||||
}
|
||||
refresh_field('mr_items');
|
||||
|
||||
@@ -472,7 +472,9 @@ def get_material_request_items(row, sales_order, company, ignore_existing_ordere
|
||||
or row.get('default_warehouse') or item_group_defaults.get("default_warehouse"),
|
||||
'actual_qty': actual_qty,
|
||||
'min_order_qty': row['min_order_qty'],
|
||||
'sales_order': sales_order
|
||||
'sales_order': sales_order,
|
||||
'description': row.get("description"),
|
||||
'uom': row.get("purchase_uom") or row.get("stock_uom")
|
||||
}
|
||||
|
||||
def get_sales_orders(self):
|
||||
|
||||
@@ -318,7 +318,7 @@ frappe.ui.form.on("Work Order", {
|
||||
},
|
||||
|
||||
project: function(frm) {
|
||||
if(!erpnext.in_production_item_onchange) {
|
||||
if(!erpnext.in_production_item_onchange && !frm.doc.bom_no) {
|
||||
frm.trigger("production_item");
|
||||
}
|
||||
},
|
||||
@@ -371,6 +371,11 @@ frappe.ui.form.on("Work Order", {
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
additional_operating_cost: function(frm) {
|
||||
erpnext.work_order.calculate_cost(frm.doc);
|
||||
erpnext.work_order.calculate_total_cost(frm);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -507,8 +512,7 @@ erpnext.work_order = {
|
||||
},
|
||||
|
||||
calculate_total_cost: function(frm) {
|
||||
var variable_cost = frm.doc.actual_operating_cost ?
|
||||
flt(frm.doc.actual_operating_cost) : flt(frm.doc.planned_operating_cost)
|
||||
let variable_cost = flt(frm.doc.actual_operating_cost) || flt(frm.doc.planned_operating_cost);
|
||||
frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost))
|
||||
},
|
||||
|
||||
|
||||
@@ -204,6 +204,8 @@ class WorkOrder(Document):
|
||||
self.meta.get_label(fieldname), qty, completed_qty, self.name), StockOverProductionError)
|
||||
|
||||
self.db_set(fieldname, qty)
|
||||
from erpnext.selling.doctype.sales_order.sales_order import update_produced_qty_in_so_item
|
||||
update_produced_qty_in_so_item(self.sales_order_item)
|
||||
|
||||
if self.production_plan:
|
||||
self.update_production_plan_status()
|
||||
|
||||
@@ -496,6 +496,7 @@ erpnext.patches.v10_0.rename_offer_letter_to_job_offer
|
||||
execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True)
|
||||
erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_group # 24-12-2018
|
||||
erpnext.patches.v10_0.add_default_cash_flow_mappers
|
||||
erpnext.patches.v11_0.rename_duplicate_item_code_values
|
||||
erpnext.patches.v11_0.make_quality_inspection_template
|
||||
erpnext.patches.v10_0.update_status_for_multiple_source_in_po
|
||||
erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
|
||||
@@ -606,3 +607,5 @@ erpnext.patches.v11_1.set_missing_opportunity_from
|
||||
erpnext.patches.v11_1.set_quotation_status
|
||||
erpnext.patches.v11_1.update_default_supplier_in_item_defaults
|
||||
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
|
||||
erpnext.patches.v11_1.set_produced_qty_field_in_sales_order_for_work_order
|
||||
erpnext.patches.v11_1.set_payment_entry_status
|
||||
@@ -0,0 +1,8 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
items = []
|
||||
items = frappe.db.sql("""select item_code from `tabItem` group by item_code having count(*) > 1""", as_dict=True)
|
||||
if items:
|
||||
for item in items:
|
||||
frappe.db.sql("""update `tabItem` set item_code=name where item_code = %s""", (item.item_code))
|
||||
@@ -1,9 +1,10 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
|
||||
hr_settings = frappe.get_single("HR Settings")
|
||||
hr_settings.leave_approval_notification_template = "Leave Approval Notification"
|
||||
hr_settings.leave_status_notification_template = "Leave Status Notification"
|
||||
hr_settings.save()
|
||||
hr_settings.leave_approval_notification_template = _("Leave Approval Notification")
|
||||
hr_settings.leave_status_notification_template = _("Leave Status Notification")
|
||||
hr_settings.save()
|
||||
|
||||
9
erpnext/patches/v11_1/set_payment_entry_status.py
Normal file
9
erpnext/patches/v11_1/set_payment_entry_status.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doctype("Payment Entry")
|
||||
frappe.db.sql("""update `tabPayment Entry` set status = CASE
|
||||
WHEN docstatus = 1 THEN 'Submitted'
|
||||
WHEN docstatus = 2 THEN 'Cancelled'
|
||||
ELSE 'Draft'
|
||||
END;""")
|
||||
@@ -0,0 +1,9 @@
|
||||
import frappe
|
||||
from erpnext.selling.doctype.sales_order.sales_order import update_produced_qty_in_so_item
|
||||
|
||||
def execute():
|
||||
frappe.reload_doctype('Sales Order Item')
|
||||
frappe.reload_doctype('Sales Order')
|
||||
sales_order_items = frappe.db.get_all('Sales Order Item', ['name'])
|
||||
for so_item in sales_order_items:
|
||||
update_produced_qty_in_so_item(so_item.get('name'))
|
||||
@@ -200,7 +200,11 @@ class Project(Document):
|
||||
frappe.db.set_value("Sales Order", self.sales_order, "project", self.name)
|
||||
|
||||
def update_percent_complete(self, from_validate=False):
|
||||
if not self.tasks: return
|
||||
if not self.tasks:
|
||||
if self.status == "Completed" :
|
||||
self.percent_complete = 100
|
||||
return
|
||||
|
||||
total = frappe.db.sql("""select count(name) from tabTask where project=%s""", self.name)[0][0]
|
||||
if not total and self.percent_complete:
|
||||
self.percent_complete = 0
|
||||
|
||||
@@ -713,7 +713,7 @@
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "depends_on_tasks",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -1433,4 +1433,4 @@
|
||||
"track_changes": 0,
|
||||
"track_seen": 1,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate
|
||||
from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate, today
|
||||
from frappe.utils.nestedset import NestedSet
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ class Task(NestedSet):
|
||||
def validate_status(self):
|
||||
if self.status!=self.get_db_value("status") and self.status == "Closed":
|
||||
for d in self.depends_on:
|
||||
if frappe.db.get_value("Task", d.task, "status") != "Closed":
|
||||
frappe.throw(_("Cannot close task as its dependant task {0} is not closed.").format(d.task))
|
||||
if frappe.db.get_value("Task", d.task, "status") not in ("Closed", "Cancelled"):
|
||||
frappe.throw(_("Cannot close task as its dependant task {0} is not closed/cancelled.").format(d.task))
|
||||
|
||||
from frappe.desk.form.assign_to import clear
|
||||
clear(self.doctype, self.name)
|
||||
@@ -199,8 +199,11 @@ def set_multiple_status(names, status):
|
||||
task.save()
|
||||
|
||||
def set_tasks_as_overdue():
|
||||
tasks = frappe.get_all("Task", filters={'status':['not in',['Cancelled', 'Closed']]})
|
||||
tasks = frappe.get_all("Task", filters={"status": ["not in", ["Cancelled", "Closed"]]}, fields=["name", "status", "review_date"])
|
||||
for task in tasks:
|
||||
if task.status == "Pending Review":
|
||||
if getdate(task.review_date) > getdate(today()):
|
||||
continue
|
||||
frappe.get_doc("Task", task.name).update_status()
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
@@ -191,6 +191,9 @@ class Timesheet(Document):
|
||||
}, as_dict=True)
|
||||
# check internal overlap
|
||||
for time_log in self.time_logs:
|
||||
if not (time_log.from_time and time_log.to_time
|
||||
and args.from_time and args.to_time): continue
|
||||
|
||||
if (fieldname != 'workstation' or args.get(fieldname) == time_log.get(fieldname)) and \
|
||||
args.idx != time_log.idx and ((args.from_time > time_log.from_time and args.from_time < time_log.to_time) or
|
||||
(args.to_time > time_log.from_time and args.to_time < time_log.to_time) or
|
||||
|
||||
@@ -387,9 +387,14 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
||||
var diff = me.frm.doc.total + non_inclusive_tax_amount
|
||||
- flt(last_tax.total, precision("grand_total"));
|
||||
|
||||
if(me.discount_amount_applied && me.frm.doc.discount_amount) {
|
||||
diff -= flt(me.frm.doc.discount_amount);
|
||||
}
|
||||
|
||||
diff = flt(diff, precision("rounding_adjustment"));
|
||||
|
||||
if ( diff && Math.abs(diff) <= (5.0 / Math.pow(10, precision("tax_amount", last_tax))) ) {
|
||||
this.frm.doc.rounding_adjustment = flt(flt(this.frm.doc.rounding_adjustment) + diff,
|
||||
precision("rounding_adjustment"));
|
||||
me.frm.doc.rounding_adjustment = diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -853,15 +853,19 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
},
|
||||
|
||||
conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
|
||||
if(doc.doctype != 'Material Request' && frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
|
||||
if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
|
||||
item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item));
|
||||
item.total_weight = flt(item.stock_qty * item.weight_per_unit);
|
||||
refresh_field("stock_qty", item.name, item.parentfield);
|
||||
refresh_field("total_weight", item.name, item.parentfield);
|
||||
this.toggle_conversion_factor(item);
|
||||
this.calculate_net_weight();
|
||||
|
||||
if(doc.doctype != "Material Request") {
|
||||
item.total_weight = flt(item.stock_qty * item.weight_per_unit);
|
||||
refresh_field("total_weight", item.name, item.parentfield);
|
||||
this.calculate_net_weight();
|
||||
}
|
||||
|
||||
if (!dont_fetch_price_list_rate &&
|
||||
frappe.meta.has_field(doc.doctype, "price_list_currency")) {
|
||||
this.apply_price_list(item, true);
|
||||
@@ -1422,6 +1426,11 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
'item_code': item.item_code,
|
||||
'posting_date': me.frm.doc.posting_date || frappe.datetime.nowdate(),
|
||||
}
|
||||
|
||||
if (doc.is_return) {
|
||||
filters["is_return"] = 1;
|
||||
}
|
||||
|
||||
if (item.warehouse) filters["warehouse"] = item.warehouse;
|
||||
|
||||
return {
|
||||
|
||||
@@ -60,8 +60,8 @@ def validate_gstin_check_digit(gstin, label='GSTIN'):
|
||||
total += digit
|
||||
factor = 2 if factor == 1 else 1
|
||||
if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]:
|
||||
frappe.throw(_("Invalid {0}! The check digit validation has failed. " +
|
||||
"Please ensure you've typed the {0} correctly.".format(label)))
|
||||
frappe.throw(_("""Invalid {0}! The check digit validation has failed.
|
||||
Please ensure you've typed the {0} correctly.""".format(label)))
|
||||
|
||||
def get_itemised_tax_breakup_header(item_doctype, tax_accounts):
|
||||
if frappe.get_meta(item_doctype).has_field('gst_hsn_code'):
|
||||
@@ -379,7 +379,7 @@ def get_gstins_for_company(company):
|
||||
`tabDynamic Link`.parent = `tabAddress`.name and
|
||||
`tabDynamic Link`.parenttype = 'Address' and
|
||||
`tabDynamic Link`.link_doctype = 'Company' and
|
||||
`tabDynamic Link`.link_name = '{0}'""".format(company))
|
||||
`tabDynamic Link`.link_name = %(company)s""", {"company": company})
|
||||
return company_gstins
|
||||
|
||||
def get_address_details(data, doc, company_address, billing_address):
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro render_discount_or_margin(item) -%}
|
||||
{%- if item.discount_percentage > 0.0 or item.margin_type %}
|
||||
{%- if (item.discount_percentage and item.discount_percentage > 0.0) or item.margin_type %}
|
||||
<ScontoMaggiorazione>
|
||||
{%- if item.discount_percentage > 0.0 %}
|
||||
<Tipo>SC</Tipo>
|
||||
|
||||
@@ -1687,7 +1687,7 @@
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -3224,7 +3224,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 1,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-06-25 15:31:04.724730",
|
||||
"modified": "2020-04-16 19:05:32.197858",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Quotation",
|
||||
|
||||
@@ -142,7 +142,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
|
||||
// delivery note
|
||||
if(flt(doc.per_delivered, 6) < 100 && allow_delivery) {
|
||||
this.frm.add_custom_button(__('Delivery'),
|
||||
this.frm.add_custom_button(__('Delivery Note'),
|
||||
function() { me.make_delivery_note_based_on_delivery_date(); }, __("Make"));
|
||||
|
||||
if(["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1){
|
||||
|
||||
@@ -1981,7 +1981,7 @@
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -4204,7 +4204,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-04-05 03:44:46.037178",
|
||||
"modified": "2020-04-16 19:05:14.867404",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
||||
@@ -622,7 +622,6 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
||||
target.set_advances()
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.is_pos = 0
|
||||
target.ignore_pricing_rule = 1
|
||||
target.flags.ignore_permissions = True
|
||||
target.run_method("set_missing_values")
|
||||
@@ -645,12 +644,15 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
|
||||
|
||||
if source_parent.project:
|
||||
target.cost_center = frappe.db.get_value("Project", source_parent.project, "cost_center")
|
||||
if not target.cost_center and target.item_code:
|
||||
if target.item_code:
|
||||
item = get_item_defaults(target.item_code, source_parent.company)
|
||||
item_group = get_item_group_defaults(target.item_code, source_parent.company)
|
||||
target.cost_center = item.get("selling_cost_center") \
|
||||
cost_center = item.get("selling_cost_center") \
|
||||
or item_group.get("selling_cost_center")
|
||||
|
||||
if cost_center:
|
||||
target.cost_center = cost_center
|
||||
|
||||
doclist = get_mapped_doc("Sales Order", source_name, {
|
||||
"Sales Order": {
|
||||
"doctype": "Sales Invoice",
|
||||
@@ -973,3 +975,15 @@ def make_raw_material_request(items, company, sales_order, project=None):
|
||||
material_request.run_method("set_missing_values")
|
||||
material_request.submit()
|
||||
return material_request
|
||||
|
||||
def update_produced_qty_in_so_item(sales_order_item):
|
||||
#for multiple work orders against same sales order item
|
||||
linked_wo_with_so_item = frappe.db.get_all('Work Order', ['produced_qty'], {
|
||||
'sales_order_item': sales_order_item,
|
||||
'docstatus': 1
|
||||
})
|
||||
if len(linked_wo_with_so_item) > 0:
|
||||
total_produced_qty = 0
|
||||
for wo in linked_wo_with_so_item:
|
||||
total_produced_qty += flt(wo.get('produced_qty'))
|
||||
frappe.db.set_value('Sales Order Item', sales_order_item, 'produced_qty', total_produced_qty)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 3,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -57,6 +58,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_item_code",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -88,6 +90,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "ensure_delivery_based_on_produced_serial_no",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -120,6 +123,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -150,6 +154,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -185,6 +190,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -217,6 +223,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
@@ -252,6 +259,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "delivery_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@@ -284,6 +292,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_7",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -315,6 +324,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Attach",
|
||||
"hidden": 1,
|
||||
@@ -347,6 +357,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "image_view",
|
||||
"fieldtype": "Image",
|
||||
"hidden": 0,
|
||||
@@ -380,6 +391,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "quantity_and_rate",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -411,6 +423,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 1,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -446,6 +459,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -482,6 +496,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "col_break2",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -512,6 +527,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "uom",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -545,6 +561,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "conversion_factor",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -577,6 +594,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "stock_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -609,6 +627,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_16",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -640,6 +659,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "price_list_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -676,6 +696,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_price_list_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -712,6 +733,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "discount_and_margin",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -745,6 +767,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "price_list_rate",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "margin_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@@ -779,6 +802,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.margin_type && doc.price_list_rate",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "margin_rate_or_amount",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -812,6 +836,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "rate_with_margin",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -845,6 +870,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -877,6 +903,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "price_list_rate",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "discount_percentage",
|
||||
"fieldtype": "Percent",
|
||||
"hidden": 0,
|
||||
@@ -913,6 +940,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "discount_percentage",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -947,6 +975,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.margin_type && doc.price_list_rate && doc.margin_rate_or_amount",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_rate_with_margin",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -980,6 +1009,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_simple1",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1012,6 +1042,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"depends_on": "eval: doc.type != \"\"",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1048,6 +1079,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1085,6 +1117,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "col_break3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -1115,6 +1148,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1151,6 +1185,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1187,6 +1222,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "pricing_rule",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1219,6 +1255,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_24",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1250,6 +1287,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "net_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1283,6 +1321,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "net_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1316,6 +1355,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_27",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -1347,6 +1387,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_net_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1380,6 +1421,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_net_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1414,6 +1456,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "eval:doc.delivered_by_supplier==1||doc.supplier",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "drop_ship_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1446,6 +1489,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "delivered_by_supplier",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -1478,6 +1522,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1511,6 +1556,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_weight_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1543,6 +1589,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "weight_per_unit",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -1575,6 +1622,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_weight",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -1607,6 +1655,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_21",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -1638,6 +1687,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "weight_uom",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1671,6 +1721,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "warehouse_and_reference",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1703,6 +1754,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.delivered_by_supplier!=1",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1740,6 +1792,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.delivered_by_supplier!=1",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "target_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
@@ -1773,6 +1826,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "prevdoc_docname",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1807,6 +1861,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "brand",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
@@ -1842,6 +1897,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
@@ -1876,6 +1932,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "billed_amt",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1908,6 +1965,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "valuation_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1941,6 +1999,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "gross_profit",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1974,6 +2033,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "blanket_order",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -2007,6 +2067,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "blanket_order_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2039,6 +2100,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "page_break",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -2072,6 +2134,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "col_break4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -2102,6 +2165,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "projected_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -2137,6 +2201,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "actual_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -2170,6 +2235,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "ordered_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -2202,6 +2268,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "delivered_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -2237,6 +2304,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "work_order_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -2270,6 +2338,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "returned_qty",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "returned_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -2302,6 +2371,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_63",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -2334,6 +2404,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "For Production",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "planned_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
@@ -2370,9 +2441,10 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "For Production",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "produced_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
@@ -2405,6 +2477,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_tax_rate",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 1,
|
||||
@@ -2439,6 +2512,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Used for Production Plan",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "transaction_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 1,
|
||||
@@ -2477,8 +2551,8 @@
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-02-18 18:53:23.425126",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2019-09-30 16:58:52.524894",
|
||||
"modified_by": "ruchamahabal2@gmail.com",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order Item",
|
||||
"owner": "Administrator",
|
||||
|
||||
@@ -7,7 +7,7 @@ from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
|
||||
columns = get_columns()
|
||||
iwq_map = get_item_warehouse_quantity_map()
|
||||
item_map = get_item_details()
|
||||
@@ -15,22 +15,23 @@ def execute(filters=None):
|
||||
for sbom, warehouse in iwq_map.items():
|
||||
total = 0
|
||||
total_qty = 0
|
||||
|
||||
|
||||
for wh, item_qty in warehouse.items():
|
||||
total += 1
|
||||
row = [sbom, item_map.get(sbom).item_name, item_map.get(sbom).description,
|
||||
item_map.get(sbom).stock_uom, wh]
|
||||
available_qty = item_qty
|
||||
total_qty += flt(available_qty)
|
||||
row += [available_qty]
|
||||
|
||||
if available_qty:
|
||||
data.append(row)
|
||||
if (total == len(warehouse)):
|
||||
row = ["", "", "Total", "", "", total_qty]
|
||||
if item_map.get(sbom):
|
||||
row = [sbom, item_map.get(sbom).item_name, item_map.get(sbom).description,
|
||||
item_map.get(sbom).stock_uom, wh]
|
||||
available_qty = item_qty
|
||||
total_qty += flt(available_qty)
|
||||
row += [available_qty]
|
||||
|
||||
if available_qty:
|
||||
data.append(row)
|
||||
if (total == len(warehouse)):
|
||||
row = ["", "", "Total", "", "", total_qty]
|
||||
data.append(row)
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns():
|
||||
columns = ["Item Code:Link/Item:100", "Item Name::100", "Description::120", \
|
||||
"UOM:Link/UOM:80", "Warehouse:Link/Warehouse:100", "Quantity::100"]
|
||||
|
||||
@@ -80,10 +80,14 @@ frappe.query_reports["Sales Analytics"] = {
|
||||
|
||||
var tree_type = frappe.query_report.filters[0].value;
|
||||
|
||||
if(tree_type == "Customer" || tree_type == "Item") {
|
||||
if(tree_type == "Customer") {
|
||||
row_values = data.slice(4,length-1).map(function (column) {
|
||||
return column.content;
|
||||
})
|
||||
} else if (tree_type == "Item") {
|
||||
row_values = data.slice(5,length-1).map(function (column) {
|
||||
return column.content;
|
||||
})
|
||||
}
|
||||
else {
|
||||
row_values = data.slice(3,length-1).map(function (column) {
|
||||
|
||||
@@ -114,7 +114,7 @@ class Analytics(object):
|
||||
if self.filters["value_quantity"] == 'Value':
|
||||
value_field = 'base_amount'
|
||||
else:
|
||||
value_field = 'qty'
|
||||
value_field = 'stock_qty'
|
||||
|
||||
self.entries = frappe.db.sql("""
|
||||
select i.item_code as entity, i.item_name as entity_name, i.stock_uom, i.{value_field} as value_field, s.{date_field}
|
||||
@@ -301,8 +301,10 @@ class Analytics(object):
|
||||
def get_chart_data(self):
|
||||
length = len(self.columns)
|
||||
|
||||
if self.filters.tree_type in ["Customer", "Supplier", "Item"]:
|
||||
labels = [d.get("label") for d in self.columns[2:length-1]]
|
||||
if self.filters.tree_type in ["Customer", "Supplier"]:
|
||||
labels = [d.get("label") for d in self.columns[2:length - 1]]
|
||||
elif self.filters.tree_type == "Item":
|
||||
labels = [d.get("label") for d in self.columns[3:length - 1]]
|
||||
else:
|
||||
labels = [d.get("label") for d in self.columns[1:length-1]]
|
||||
self.chart = {
|
||||
|
||||
@@ -284,7 +284,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
||||
child: item,
|
||||
args: {
|
||||
"batch_no": item.batch_no,
|
||||
"stock_qty": item.stock_qty,
|
||||
"stock_qty": item.stock_qty || item.qty, //if stock_qty field is not available, fetch qty (in case of Packed Items table)
|
||||
"warehouse": item.warehouse,
|
||||
"item_code": item.item_code,
|
||||
"has_serial_no": has_serial_no
|
||||
|
||||
@@ -109,7 +109,7 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non
|
||||
or I.name like %(search)s)"""
|
||||
search = "%" + cstr(search) + "%"
|
||||
|
||||
query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (start, limit)
|
||||
query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (cint(start), cint(limit))
|
||||
|
||||
data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1)
|
||||
data = adjust_qty_for_expired_items(data)
|
||||
|
||||
@@ -141,6 +141,6 @@ def insert_record(records):
|
||||
raise
|
||||
|
||||
def welcome_email():
|
||||
site_name = get_default_company()
|
||||
title = _("Welcome to {0}".format(site_name))
|
||||
return title
|
||||
site_name = get_default_company() or "ERPNext"
|
||||
title = _("Welcome to {0}").format(site_name)
|
||||
return title
|
||||
|
||||
@@ -66,6 +66,7 @@ def place_order():
|
||||
|
||||
from erpnext.selling.doctype.quotation.quotation import _make_sales_order
|
||||
sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
|
||||
sales_order.payment_schedule = []
|
||||
|
||||
if not cart_settings.allow_items_not_in_stock:
|
||||
for item in sales_order.get("items"):
|
||||
@@ -454,9 +455,8 @@ def get_applicable_shipping_rules(party=None, quotation=None):
|
||||
shipping_rules = get_shipping_rules(quotation)
|
||||
|
||||
if shipping_rules:
|
||||
rule_label_map = frappe.db.get_values("Shipping Rule", shipping_rules, "label")
|
||||
# we need this in sorted order as per the position of the rule in the settings page
|
||||
return [[rule, rule_label_map.get(rule)] for rule in shipping_rules]
|
||||
return [[rule, rule] for rule in shipping_rules]
|
||||
|
||||
def get_shipping_rules(quotation=None, cart_settings=None):
|
||||
if not quotation:
|
||||
|
||||
@@ -48,7 +48,7 @@ def get_product_info_for_website(item_code):
|
||||
|
||||
def set_product_info_for_website(item):
|
||||
"""set product price uom for website"""
|
||||
product_info = get_product_info_for_website(item.item_code)
|
||||
product_info = get_product_info_for_website(item.item_code).get("product_info")
|
||||
|
||||
if product_info:
|
||||
item.update(product_info)
|
||||
|
||||
@@ -2156,7 +2156,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -4296,7 +4296,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2019-01-07 16:51:52.357859",
|
||||
"modified": "2020-04-16 19:05:56.439204",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note",
|
||||
|
||||
@@ -400,7 +400,6 @@ def make_sales_invoice(source_name, target_doc=None):
|
||||
invoiced_qty_map = get_invoiced_qty_map(source_name)
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.is_pos = 0
|
||||
target.ignore_pricing_rule = 1
|
||||
target.run_method("set_missing_values")
|
||||
target.run_method("set_po_nos")
|
||||
|
||||
@@ -6,9 +6,9 @@ frappe.listview_settings['Delivery Note'] = {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
} else if (doc.status === "Closed") {
|
||||
return [__("Closed"), "green", "status,=,Closed"];
|
||||
} else if (doc.grand_total !== 0 && flt(doc.per_billed, 2) < 100) {
|
||||
} else if (flt(doc.per_billed, 2) < 100) {
|
||||
return [__("To Bill"), "orange", "per_billed,<,100"];
|
||||
} else if (doc.grand_total === 0 || flt(doc.per_billed, 2) == 100) {
|
||||
} else if (flt(doc.per_billed, 2) == 100) {
|
||||
return [__("Completed"), "green", "per_billed,=,100"];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -518,7 +518,7 @@ class Item(WebsiteGenerator):
|
||||
"""select parent from `tabItem Barcode` where barcode = %s and parent != %s""", (item_barcode.barcode, self.name))
|
||||
if duplicate:
|
||||
frappe.throw(_("Barcode {0} already used in Item {1}").format(
|
||||
item_barcode.barcode, duplicate[0][0]), frappe.DuplicateEntryError)
|
||||
item_barcode.barcode, duplicate[0][0]))
|
||||
|
||||
item_barcode.barcode_type = "" if item_barcode.barcode_type not in options else item_barcode.barcode_type
|
||||
if item_barcode.barcode_type and item_barcode.barcode_type.upper() in ('EAN', 'UPC-A', 'EAN-13', 'EAN-8'):
|
||||
|
||||
@@ -124,7 +124,7 @@ class LandedCostVoucher(Document):
|
||||
|
||||
# update stock & gl entries for submit state of PR
|
||||
doc.docstatus = 1
|
||||
doc.update_stock_ledger(via_landed_cost_voucher=True)
|
||||
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
|
||||
doc.make_gl_entries()
|
||||
|
||||
def update_rate_in_serial_no(self, receipt_document):
|
||||
|
||||
@@ -217,7 +217,19 @@ frappe.ui.form.on('Material Request', {
|
||||
|
||||
make_purchase_order: function(frm) {
|
||||
frappe.prompt(
|
||||
{fieldname:'default_supplier', label: __('For Default Supplier (optional)'), fieldtype: 'Link', options: 'Supplier'},
|
||||
{
|
||||
label: __('For Default Supplier (optional)'),
|
||||
fieldname:'default_supplier',
|
||||
fieldtype: 'Link',
|
||||
options: 'Supplier',
|
||||
description: __('Select a Supplier from the Default Supplier List of the items below.'),
|
||||
get_query: () => {
|
||||
return {
|
||||
query: "erpnext.stock.doctype.material_request.material_request.get_default_supplier_query",
|
||||
filters: {'doc': frm.doc.name}
|
||||
}
|
||||
}
|
||||
},
|
||||
(values) => {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
|
||||
@@ -225,7 +237,8 @@ frappe.ui.form.on('Material Request', {
|
||||
args: { default_supplier: values.default_supplier },
|
||||
run_link_triggers: true
|
||||
});
|
||||
}
|
||||
},
|
||||
__('Enter Supplier')
|
||||
)
|
||||
},
|
||||
|
||||
|
||||
@@ -371,6 +371,18 @@ def get_material_requests_based_on_supplier(supplier):
|
||||
material_requests = []
|
||||
return material_requests, supplier_items
|
||||
|
||||
def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
doc = frappe.get_doc("Material Request", filters.get("doc"))
|
||||
item_list = []
|
||||
for d in doc.items:
|
||||
item_list.append(d.item_code)
|
||||
|
||||
return frappe.db.sql("""select default_supplier
|
||||
from `tabItem Default`
|
||||
where parent in ({0}) and
|
||||
default_supplier IS NOT NULL
|
||||
""".format(', '.join(['%s']*len(item_list))),tuple(item_list))
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_supplier_quotation(source_name, target_doc=None):
|
||||
def postprocess(source, target_doc):
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
@@ -11,10 +13,13 @@
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "parent_item",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -39,13 +44,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -70,13 +79,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -100,13 +113,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_5",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -128,13 +145,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
@@ -159,14 +180,18 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -188,13 +213,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -219,13 +248,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "target_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -249,13 +282,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -277,13 +314,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -307,13 +348,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -335,13 +380,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "serial_no",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
@@ -363,13 +412,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_11",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -391,13 +444,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "batch_no",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -420,13 +477,51 @@
|
||||
"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": "batch_no",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "actual_batch_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Actual Batch Quantity",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_13",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -448,13 +543,17 @@
|
||||
"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": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "actual_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -478,13 +577,17 @@
|
||||
"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": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "projected_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -508,13 +611,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_16",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -536,13 +643,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "uom",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -567,13 +678,17 @@
|
||||
"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": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "page_break",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -597,13 +712,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "prevdoc_doctype",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -627,13 +746,17 @@
|
||||
"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,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "parent_detail_docname",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -657,20 +780,21 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-02-20 13:27:37.569945",
|
||||
"modified": "2019-11-27 11:18:18.598759",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Packed Item",
|
||||
@@ -681,5 +805,6 @@
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
@@ -7,7 +7,6 @@ from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe.utils import cstr, flt
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
class PackedItem(Document):
|
||||
@@ -31,8 +30,11 @@ def get_bin_qty(item, warehouse):
|
||||
return det and det[0] or frappe._dict()
|
||||
|
||||
def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description):
|
||||
if doc.amended_from:
|
||||
old_packed_items_map = get_old_packed_item_details(doc.packed_items)
|
||||
else:
|
||||
old_packed_items_map = False
|
||||
item = get_packing_item_details(packing_item_code, doc.company)
|
||||
|
||||
# check if exists
|
||||
exists = 0
|
||||
for d in doc.get("packed_items"):
|
||||
@@ -52,11 +54,10 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip
|
||||
pi.uom = item.stock_uom
|
||||
pi.qty = flt(qty)
|
||||
pi.description = description
|
||||
if not pi.warehouse:
|
||||
if not pi.warehouse and not doc.amended_from:
|
||||
pi.warehouse = (main_item_row.warehouse if ((doc.get('is_pos')
|
||||
or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse)
|
||||
|
||||
if not pi.batch_no:
|
||||
if not pi.batch_no and not doc.amended_from:
|
||||
pi.batch_no = cstr(main_item_row.get("batch_no"))
|
||||
if not pi.target_warehouse:
|
||||
pi.target_warehouse = main_item_row.get("target_warehouse")
|
||||
@@ -64,9 +65,13 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip
|
||||
pi.actual_qty = flt(bin.get("actual_qty"))
|
||||
pi.projected_qty = flt(bin.get("projected_qty"))
|
||||
|
||||
if old_packed_items_map and old_packed_items_map.get((packing_item_code, main_item_row.item_code)):
|
||||
pi.batch_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].batch_no
|
||||
pi.serial_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].serial_no
|
||||
pi.warehouse = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].warehouse
|
||||
|
||||
def make_packing_list(doc):
|
||||
"""make packing list for Product Bundle item"""
|
||||
|
||||
if doc.get("_action") and doc._action == "update_after_submit": return
|
||||
|
||||
parent_items = []
|
||||
@@ -108,8 +113,14 @@ def get_items_from_product_bundle(args):
|
||||
"qty": flt(args["quantity"]) * flt(item.qty)
|
||||
})
|
||||
items.append(get_item_details(args))
|
||||
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Packed Item", ["item_code", "warehouse"])
|
||||
frappe.db.add_index("Packed Item", ["item_code", "warehouse"])
|
||||
|
||||
def get_old_packed_item_details(old_packed_items):
|
||||
old_packed_items_map = {}
|
||||
for items in old_packed_items:
|
||||
old_packed_items_map.setdefault((items.item_code ,items.parent_item), []).append(items.as_dict())
|
||||
return old_packed_items_map
|
||||
@@ -27,6 +27,12 @@ frappe.ui.form.on("Purchase Receipt", {
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("taxes_and_charges", function() {
|
||||
return {
|
||||
filters: {'company': frm.doc.company }
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
onload: function(frm) {
|
||||
erpnext.queries.setup_queries(frm, "Warehouse", function() {
|
||||
@@ -105,10 +111,10 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
cur_frm.add_custom_button(__("Close"), this.close_purchase_receipt, __("Status"))
|
||||
}
|
||||
|
||||
cur_frm.add_custom_button(__('Return'), this.make_purchase_return, __("Make"));
|
||||
cur_frm.add_custom_button(__('Purchase Return'), this.make_purchase_return, __("Make"));
|
||||
|
||||
if(flt(this.frm.doc.per_billed) < 100) {
|
||||
cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice, __("Make"));
|
||||
cur_frm.add_custom_button(__('Purchase Invoice'), this.make_purchase_invoice, __("Make"));
|
||||
}
|
||||
cur_frm.add_custom_button(__('Retention Stock Entry'), this.make_retention_stock_entry, __("Make"));
|
||||
|
||||
|
||||
@@ -1945,7 +1945,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"fieldtype": "Long Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -3708,7 +3708,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2018-11-02 19:59:01.423485",
|
||||
"modified": "2020-04-16 19:06:51.546358",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt",
|
||||
|
||||
@@ -227,7 +227,9 @@ class StockEntry(StockController):
|
||||
|
||||
for d in self.get("items"):
|
||||
if not d.expense_account:
|
||||
frappe.throw(_("Please enter Difference Account"))
|
||||
frappe.throw(_("Please enter <b>Difference Account</b> or set default <b>Stock Adjustment Account</b> for company {0}")
|
||||
.format(frappe.bold(self.company)))
|
||||
|
||||
elif self.is_opening == "Yes" and frappe.db.get_value("Account", d.expense_account, "report_type") == "Profit and Loss":
|
||||
frappe.throw(_("Difference Account must be a Asset/Liability type account, since this Stock Entry is an Opening Entry"), OpeningEntryAccountError)
|
||||
|
||||
@@ -346,7 +348,7 @@ class StockEntry(StockController):
|
||||
elif d.t_warehouse and not d.basic_rate:
|
||||
d.basic_rate = get_valuation_rate(d.item_code, d.t_warehouse,
|
||||
self.doctype, d.name, d.allow_zero_valuation_rate,
|
||||
currency=erpnext.get_company_currency(self.company))
|
||||
currency=erpnext.get_company_currency(self.company), company=self.company)
|
||||
|
||||
def set_actual_qty(self):
|
||||
allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user