mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-02 01:04:36 +00:00
Compare commits
237 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25eff13d35 | ||
|
|
415c90d9d0 | ||
|
|
97a49185c5 | ||
|
|
c2e5e569a0 | ||
|
|
d5384a110d | ||
|
|
4e9f1a08fe | ||
|
|
79f2779574 | ||
|
|
23251d9e4d | ||
|
|
e2652b9cc5 | ||
|
|
beca677276 | ||
|
|
1202dc1dd3 | ||
|
|
e2ddc82637 | ||
|
|
f269b66f39 | ||
|
|
850284abee | ||
|
|
a6a6171225 | ||
|
|
836aa5a1e6 | ||
|
|
453d484a96 | ||
|
|
3957880370 | ||
|
|
840bfa87e8 | ||
|
|
b2c43ee2d9 | ||
|
|
10878c4d0e | ||
|
|
7cb940b179 | ||
|
|
01c85e0420 | ||
|
|
41f36a6d92 | ||
|
|
2aff5384ec | ||
|
|
e592891121 | ||
|
|
e263a10fdd | ||
|
|
db8b6c59bc | ||
|
|
e1f3da2c2d | ||
|
|
ae255d6328 | ||
|
|
c283329581 | ||
|
|
f85e344ed4 | ||
|
|
aece8056f8 | ||
|
|
5d6ccafac9 | ||
|
|
ee22706182 | ||
|
|
013ae1172a | ||
|
|
069276473f | ||
|
|
a8289d4fd5 | ||
|
|
2ed653f433 | ||
|
|
b724e080b0 | ||
|
|
9de95528ef | ||
|
|
3cab94f130 | ||
|
|
b2cf38bbf4 | ||
|
|
6c7bfb37c1 | ||
|
|
6edd2b7f9f | ||
|
|
b47caf6642 | ||
|
|
67476e7e09 | ||
|
|
3bafada5a6 | ||
|
|
0743610487 | ||
|
|
bc7d39a16b | ||
|
|
618146cc63 | ||
|
|
4acd39b6a4 | ||
|
|
72056c26a8 | ||
|
|
fbab41668d | ||
|
|
14b5c96c58 | ||
|
|
d48d5c7cbd | ||
|
|
3d59ab5c55 | ||
|
|
12cb0ea633 | ||
|
|
c5e959fe9c | ||
|
|
13d01dd690 | ||
|
|
4e94e26ef8 | ||
|
|
8738f2e1c9 | ||
|
|
508b3ab8de | ||
|
|
8f1f6a89f1 | ||
|
|
523d89a2d9 | ||
|
|
8d45d5c4a7 | ||
|
|
437edb1f01 | ||
|
|
ac57edf7d3 | ||
|
|
3a2fec1ffb | ||
|
|
e2cf17e106 | ||
|
|
e5c7f3e542 | ||
|
|
d2bbc3ef3e | ||
|
|
96b6cfd810 | ||
|
|
b3cf5f0caa | ||
|
|
072948e827 | ||
|
|
8ef80fb669 | ||
|
|
4de1083096 | ||
|
|
e5647f7441 | ||
|
|
f9318f82ae | ||
|
|
4f78d14471 | ||
|
|
d41771b4b1 | ||
|
|
0c7afb389d | ||
|
|
77ed46242f | ||
|
|
acbdeb833f | ||
|
|
2493d5e0d3 | ||
|
|
820d66b42e | ||
|
|
8fb018de47 | ||
|
|
7987b1a681 | ||
|
|
750526b138 | ||
|
|
6b5c365cb6 | ||
|
|
1a5c0b3ae2 | ||
|
|
740c954679 | ||
|
|
c8b1fbd9e6 | ||
|
|
dc24fe60be | ||
|
|
86b33b2a10 | ||
|
|
1450a7b408 | ||
|
|
f7af9b8745 | ||
|
|
87a09d2bb3 | ||
|
|
c5283903be | ||
|
|
cfd6ec0dcb | ||
|
|
a59aaf48f2 | ||
|
|
c40d832e5e | ||
|
|
23f901c29a | ||
|
|
c06d1ec73d | ||
|
|
2fc6d1d210 | ||
|
|
49c6c909f8 | ||
|
|
ffd6b27f4b | ||
|
|
860b6bac75 | ||
|
|
9c3729b4ba | ||
|
|
1174e5a127 | ||
|
|
fe802a97a2 | ||
|
|
60f1750c96 | ||
|
|
6a198acd2f | ||
|
|
40968c78a8 | ||
|
|
e03892b130 | ||
|
|
844bbcdb1d | ||
|
|
d77cd79262 | ||
|
|
6e97f7fbd8 | ||
|
|
de04941ddb | ||
|
|
2de80fdc3e | ||
|
|
832884a7ea | ||
|
|
4bc86c7e9d | ||
|
|
cd2938e2d0 | ||
|
|
1d11ddc235 | ||
|
|
f37a09d9fe | ||
|
|
978bc1352e | ||
|
|
ab669ad055 | ||
|
|
443f9ed5f1 | ||
|
|
d72f4d7959 | ||
|
|
4c23c2ddec | ||
|
|
e0333c0756 | ||
|
|
066ae71581 | ||
|
|
2898c94f08 | ||
|
|
fc0df994b8 | ||
|
|
c5a4e423c6 | ||
|
|
949f170b48 | ||
|
|
576e68eef0 | ||
|
|
63af463a9a | ||
|
|
b20eda9996 | ||
|
|
88832daae4 | ||
|
|
3aa2df29f5 | ||
|
|
42d0ee7431 | ||
|
|
15e128f321 | ||
|
|
56757866f3 | ||
|
|
c3f3c156b1 | ||
|
|
62e8955b39 | ||
|
|
fad3789f64 | ||
|
|
a0b85d060b | ||
|
|
fd5d3f551b | ||
|
|
019014070d | ||
|
|
97f5dff656 | ||
|
|
0d28802485 | ||
|
|
254774f7a3 | ||
|
|
6f1e624465 | ||
|
|
2dcd03d17d | ||
|
|
ffcb7aa6ed | ||
|
|
9350b5a533 | ||
|
|
8cb2c7a89c | ||
|
|
50bdaa6d1a | ||
|
|
20a4cf1290 | ||
|
|
fc092d0df4 | ||
|
|
51bb2909c3 | ||
|
|
cab0cd55b3 | ||
|
|
4f579639c6 | ||
|
|
c5b68ef386 | ||
|
|
95dc4e4dc5 | ||
|
|
dc35138356 | ||
|
|
08617f7700 | ||
|
|
cfecf3c5b1 | ||
|
|
831100b657 | ||
|
|
f296a2f58a | ||
|
|
18a0120fc1 | ||
|
|
aae557e8a1 | ||
|
|
0f92c4b85b | ||
|
|
217df1761d | ||
|
|
d355741462 | ||
|
|
7b6ed4f16e | ||
|
|
c5a682e9d9 | ||
|
|
b4fa105555 | ||
|
|
e1aef6f0db | ||
|
|
6f35d2b52d | ||
|
|
197f57c050 | ||
|
|
c74fa7546b | ||
|
|
0261472ecd | ||
|
|
233ef8752d | ||
|
|
afd9e7546f | ||
|
|
8b1532d691 | ||
|
|
a887c29e06 | ||
|
|
7114b72be8 | ||
|
|
1c1a5958bc | ||
|
|
b7b5bcbd85 | ||
|
|
9638f0ef2b | ||
|
|
92ab345daf | ||
|
|
79dd4d707b | ||
|
|
a3a733fa91 | ||
|
|
7a9b014f72 | ||
|
|
61b4a98356 | ||
|
|
46db69b304 | ||
|
|
a0be41322d | ||
|
|
39d30718e2 | ||
|
|
05f29988f4 | ||
|
|
d7903de51c | ||
|
|
0e31cc9ff8 | ||
|
|
32280a11aa | ||
|
|
a2f9d2f89c | ||
|
|
5fc5355b96 | ||
|
|
30c73e6b35 | ||
|
|
7a6b88c791 | ||
|
|
9c42124fbc | ||
|
|
0378b15412 | ||
|
|
3f86369604 | ||
|
|
cc99d92116 | ||
|
|
f880975438 | ||
|
|
daa8db4d95 | ||
|
|
9ff39e2d1b | ||
|
|
9d70c5d13f | ||
|
|
a9a82919e7 | ||
|
|
31f5055287 | ||
|
|
ce9239af83 | ||
|
|
50de88417c | ||
|
|
2701f94491 | ||
|
|
13c9d041d9 | ||
|
|
7178218821 | ||
|
|
9eef60754d | ||
|
|
8908d4ee8f | ||
|
|
3799aabc46 | ||
|
|
4b2901704c | ||
|
|
e5f7af9e9f | ||
|
|
6fc136fcb8 | ||
|
|
f94951a51b | ||
|
|
9ef79d6c6b | ||
|
|
e82ab87f1c | ||
|
|
9c923ae418 | ||
|
|
8fd90410f1 | ||
|
|
f62e789173 | ||
|
|
91578757ff | ||
|
|
eac87b4764 |
25
.travis.yml
25
.travis.yml
@@ -3,6 +3,11 @@ dist: trusty
|
||||
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.6"
|
||||
|
||||
env:
|
||||
- TEST_TYPE="Server Side Test"
|
||||
- TEST_TYPE="Patch Test"
|
||||
|
||||
services:
|
||||
- mysql
|
||||
@@ -39,18 +44,8 @@ before_script:
|
||||
- bench start &
|
||||
- sleep 10
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: test
|
||||
script:
|
||||
- set -e
|
||||
- bench run-tests --app erpnext --coverage
|
||||
after_script:
|
||||
- coveralls -b apps/erpnext -d ../../sites/.coverage
|
||||
env: Server Side Test
|
||||
- # stage
|
||||
script:
|
||||
- wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
|
||||
- bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis
|
||||
- bench migrate
|
||||
env: Patch Testing
|
||||
script:
|
||||
- bash $TRAVIS_BUILD_DIR/travis/run-tests.sh
|
||||
|
||||
after_script:
|
||||
- coveralls -b apps/erpnext -d ../../sites/.coverage
|
||||
|
||||
20
MANIFEST.in
20
MANIFEST.in
@@ -1,20 +0,0 @@
|
||||
include MANIFEST.in
|
||||
include requirements.txt
|
||||
include *.json
|
||||
include *.md
|
||||
include *.py
|
||||
include *.txt
|
||||
include .travis.yml
|
||||
recursive-include erpnext *.txt
|
||||
recursive-include erpnext *.css
|
||||
recursive-include erpnext *.csv
|
||||
recursive-include erpnext *.html
|
||||
recursive-include erpnext *.ico
|
||||
recursive-include erpnext *.js
|
||||
recursive-include erpnext *.json
|
||||
recursive-include erpnext *.md
|
||||
recursive-include erpnext *.png
|
||||
recursive-include erpnext *.py
|
||||
recursive-include erpnext *.svg
|
||||
recursive-include erpnext/public *
|
||||
recursive-exclude * *.pyc
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '11.1.32'
|
||||
__version__ = '11.1.42'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -43,8 +43,13 @@ frappe.ui.form.on('Bank Guarantee', {
|
||||
|
||||
reference_docname: function(frm) {
|
||||
if (frm.doc.reference_docname && frm.doc.reference_doctype) {
|
||||
let fields_to_fetch = ["project", "grand_total"];
|
||||
let fields_to_fetch = ["grand_total"];
|
||||
let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier";
|
||||
|
||||
if (frm.doc.reference_doctype == "Sales Order") {
|
||||
fields_to_fetch.push("project");
|
||||
}
|
||||
|
||||
fields_to_fetch.push(party_field);
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_vouchar_detials",
|
||||
|
||||
@@ -425,8 +425,9 @@ class JournalEntry(AccountsController):
|
||||
pay_to_recd_from = frappe.db.get_value(d.party_type, d.party,
|
||||
"customer_name" if d.party_type=="Customer" else "supplier_name")
|
||||
|
||||
party_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
|
||||
party_account_currency = d.account_currency
|
||||
if pay_to_recd_from and pay_to_recd_from == d.party:
|
||||
party_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
|
||||
party_account_currency = d.account_currency
|
||||
|
||||
elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]:
|
||||
bank_amount += (d.debit_in_account_currency or d.credit_in_account_currency)
|
||||
|
||||
@@ -350,7 +350,7 @@ def filter_pricing_rules(args, pricing_rules):
|
||||
if len(pricing_rules) > 1:
|
||||
rate_or_discount = list(set([d.rate_or_discount for d in pricing_rules]))
|
||||
if len(rate_or_discount) == 1 and rate_or_discount[0] == "Discount Percentage":
|
||||
pricing_rules = filter(lambda x: x.for_price_list==args.price_list, pricing_rules) \
|
||||
pricing_rules = list(filter(lambda x: x.for_price_list==args.price_list, pricing_rules)) \
|
||||
or pricing_rules
|
||||
|
||||
if len(pricing_rules) > 1 and not args.for_shopping_cart:
|
||||
@@ -373,7 +373,7 @@ def apply_internal_priority(pricing_rules, field_set, args):
|
||||
filtered_rules = []
|
||||
for field in field_set:
|
||||
if args.get(field):
|
||||
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
|
||||
filtered_rules = list(filter(lambda x: x[field]==args[field], pricing_rules))
|
||||
if filtered_rules: break
|
||||
|
||||
return filtered_rules or pricing_rules
|
||||
|
||||
@@ -18,9 +18,6 @@ class TestPricingRule(unittest.TestCase):
|
||||
frappe.db.sql("delete from `tabPricing Rule`")
|
||||
|
||||
def test_pricing_rule_for_discount(self):
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
from frappe import MandatoryError
|
||||
|
||||
test_record = {
|
||||
"doctype": "Pricing Rule",
|
||||
"title": "_Test Pricing Rule",
|
||||
@@ -94,9 +91,6 @@ class TestPricingRule(unittest.TestCase):
|
||||
self.assertEquals(details.get("discount_percentage"), 15)
|
||||
|
||||
def test_pricing_rule_for_margin(self):
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
from frappe import MandatoryError
|
||||
|
||||
test_record = {
|
||||
"doctype": "Pricing Rule",
|
||||
"title": "_Test Pricing Rule",
|
||||
@@ -139,9 +133,6 @@ class TestPricingRule(unittest.TestCase):
|
||||
self.assertEquals(details.get("margin_rate_or_amount"), 10)
|
||||
|
||||
def test_pricing_rule_for_variants(self):
|
||||
from erpnext.stock.get_item_details import get_item_details
|
||||
from frappe import MandatoryError
|
||||
|
||||
if not frappe.db.exists("Item", "Test Variant PRT"):
|
||||
frappe.get_doc({
|
||||
"doctype": "Item",
|
||||
|
||||
@@ -6,8 +6,8 @@ frappe.listview_settings['Purchase Invoice'] = {
|
||||
add_fields: ["supplier", "supplier_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
||||
"currency", "is_return", "release_date", "on_hold"],
|
||||
get_indicator: function(doc) {
|
||||
if(cint(doc.is_return)==1) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
if(flt(doc.outstanding_amount) < 0 && doc.docstatus == 1) {
|
||||
return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<,0"]
|
||||
} else if(flt(doc.outstanding_amount) > 0 && doc.docstatus==1) {
|
||||
if(cint(doc.on_hold) && !doc.release_date) {
|
||||
return [__("On Hold"), "darkgrey"];
|
||||
@@ -18,9 +18,9 @@ frappe.listview_settings['Purchase Invoice'] = {
|
||||
} else {
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due,>=,Today"];
|
||||
}
|
||||
} else if(flt(doc.outstanding_amount) < 0 && doc.docstatus == 1) {
|
||||
return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<,0"]
|
||||
}else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) {
|
||||
} else if(cint(doc.is_return)) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
} else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) {
|
||||
return [__("Paid"), "green", "outstanding_amount,=,0"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ frappe.ui.form.on("Sales Invoice", {
|
||||
if(frm.doc.docstatus == 1 && !frm.is_dirty()
|
||||
&& !frm.doc.is_return && !frm.doc.ewaybill) {
|
||||
|
||||
frm.add_custom_button('Generate e-Way Bill JSON', () => {
|
||||
frm.add_custom_button('e-Way Bill JSON', () => {
|
||||
var w = window.open(
|
||||
frappe.urllib.get_full_url(
|
||||
"/api/method/erpnext.regional.india.utils.generate_ewb_json?"
|
||||
|
||||
@@ -371,6 +371,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
me.frm.pos_print_format = r.message.print_format;
|
||||
}
|
||||
me.frm.script_manager.trigger("update_stock");
|
||||
if(me.frm.doc.taxes_and_charges) {
|
||||
me.frm.script_manager.trigger("taxes_and_charges");
|
||||
}
|
||||
|
||||
frappe.model.set_default_values(me.frm.doc);
|
||||
me.set_dynamic_labels();
|
||||
me.calculate_taxes_and_totals();
|
||||
|
||||
@@ -54,8 +54,8 @@ class SalesInvoice(SellingController):
|
||||
|
||||
def set_indicator(self):
|
||||
"""Set indicator for portal"""
|
||||
if cint(self.is_return) == 1:
|
||||
self.indicator_title = _("Return")
|
||||
if self.outstanding_amount < 0:
|
||||
self.indicator_title = _("Credit Note Issued")
|
||||
self.indicator_color = "darkgrey"
|
||||
elif self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
|
||||
self.indicator_color = "orange"
|
||||
@@ -63,8 +63,8 @@ class SalesInvoice(SellingController):
|
||||
elif self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
|
||||
self.indicator_color = "red"
|
||||
self.indicator_title = _("Overdue")
|
||||
elif self.outstanding_amount < 0:
|
||||
self.indicator_title = _("Credit Note Issued")
|
||||
elif cint(self.is_return) == 1:
|
||||
self.indicator_title = _("Return")
|
||||
self.indicator_color = "darkgrey"
|
||||
else:
|
||||
self.indicator_color = "green"
|
||||
@@ -487,7 +487,7 @@ class SalesInvoice(SellingController):
|
||||
"""Set against account for debit to account"""
|
||||
against_acc = []
|
||||
for d in self.get('items'):
|
||||
if d.income_account not in against_acc:
|
||||
if d.income_account and d.income_account not in against_acc:
|
||||
against_acc.append(d.income_account)
|
||||
self.against_income_account = ','.join(against_acc)
|
||||
|
||||
|
||||
@@ -6,16 +6,16 @@ frappe.listview_settings['Sales Invoice'] = {
|
||||
add_fields: ["customer", "customer_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
||||
"currency", "is_return"],
|
||||
get_indicator: function(doc) {
|
||||
if(cint(doc.is_return)==1) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
} else if(flt(doc.outstanding_amount)==0) {
|
||||
return [__("Paid"), "green", "outstanding_amount,=,0"]
|
||||
} else if(flt(doc.outstanding_amount) < 0) {
|
||||
if(flt(doc.outstanding_amount) < 0) {
|
||||
return [__("Credit Note Issued"), "darkgrey", "outstanding_amount,<,0"]
|
||||
}else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) {
|
||||
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date >= frappe.datetime.get_today()) {
|
||||
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>,Today"]
|
||||
} else if (flt(doc.outstanding_amount) > 0 && doc.due_date < frappe.datetime.get_today()) {
|
||||
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<=,Today"]
|
||||
} else if(cint(doc.is_return)) {
|
||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||
} else if(flt(doc.outstanding_amount)==0) {
|
||||
return [__("Paid"), "green", "outstanding_amount,=,0"]
|
||||
}
|
||||
},
|
||||
right_column: "grand_total"
|
||||
|
||||
@@ -314,13 +314,11 @@ class Subscription(Document):
|
||||
|
||||
self.save()
|
||||
|
||||
@property
|
||||
def is_postpaid_to_invoice(self):
|
||||
return getdate(nowdate()) > getdate(self.current_invoice_end) or \
|
||||
(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \
|
||||
not self.has_outstanding_invoice()
|
||||
|
||||
@property
|
||||
def is_prepaid_to_invoice(self):
|
||||
if not self.generate_invoice_at_period_start:
|
||||
return False
|
||||
@@ -340,7 +338,7 @@ class Subscription(Document):
|
||||
2. Change the `Subscription` status to 'Past Due Date'
|
||||
3. Change the `Subscription` status to 'Cancelled'
|
||||
"""
|
||||
if self.is_postpaid_to_invoice or self.is_prepaid_to_invoice:
|
||||
if self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice():
|
||||
self.generate_invoice()
|
||||
if self.current_invoice_is_past_due():
|
||||
self.status = 'Past Due Date'
|
||||
|
||||
@@ -22,7 +22,7 @@ class TestTaxWithholdingCategory(unittest.TestCase):
|
||||
invoices = []
|
||||
|
||||
# create invoices for lower than single threshold tax rate
|
||||
for _ in xrange(2):
|
||||
for _ in range(2):
|
||||
pi = create_purchase_invoice(supplier = "Test TDS Supplier")
|
||||
pi.submit()
|
||||
invoices.append(pi)
|
||||
|
||||
@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"finance_book",
|
||||
"label": __("Finance Book"),
|
||||
|
||||
@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Payable Summary"] = {
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"finance_book",
|
||||
"label": __("Finance Book"),
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
var range2 = report.columns[12].label;
|
||||
var range3 = report.columns[13].label;
|
||||
var range4 = report.columns[14].label;
|
||||
var range5 = report.columns[15].label;
|
||||
var range6 = report.columns[16].label;
|
||||
%}
|
||||
{% if(balance_row) { %}
|
||||
<table class="table table-bordered table-condensed">
|
||||
@@ -56,8 +58,10 @@
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
<col style="width: 18mm;">
|
||||
</colgroup>
|
||||
|
||||
<thead>
|
||||
@@ -67,16 +71,20 @@
|
||||
<th>{%= __(range2) %}</th>
|
||||
<th>{%= __(range3) %}</th>
|
||||
<th>{%= __(range4) %}</th>
|
||||
<th>{%= __(range5) %}</th>
|
||||
<th>{%= __(range6) %}</th>
|
||||
<th>{%= __("Total") %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{%= __("Total Outstanding") %}</td>
|
||||
<td class="text-right">{%= format_currency(balance_row[range1]) %}</td>
|
||||
<td class="text-right">{%= format_number(balance_row[range1], null, 2) %}</td>
|
||||
<td class="text-right">{%= format_currency(balance_row[range2]) %}</td>
|
||||
<td class="text-right">{%= format_currency(balance_row[range3]) %}</td>
|
||||
<td class="text-right">{%= format_currency(balance_row[range4]) %}</td>
|
||||
<td class="text-right">{%= format_currency(balance_row[range5]) %}</td>
|
||||
<td class="text-right">{%= format_currency(balance_row[range6]) %}</td>
|
||||
<td class="text-right">
|
||||
{%= format_currency(flt(balance_row[("outstanding_amount")]), data[data.length-1]["currency"]) %}
|
||||
</td>
|
||||
@@ -86,6 +94,8 @@
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td class="text-right">
|
||||
{%= format_currency(flt(balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}
|
||||
</td>
|
||||
@@ -95,6 +105,8 @@
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th class="text-right">
|
||||
{%= format_currency(flt(balance_row[("outstanding_amount")]-balance_row[("pdc/lc_amount")]), data[data.length-1]["currency"]) %}</th>
|
||||
</tr>
|
||||
|
||||
@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"finance_book",
|
||||
"label": __("Finance Book"),
|
||||
|
||||
@@ -68,13 +68,13 @@ class ReceivablePayableReport(object):
|
||||
|
||||
if self.filters.based_on_payment_terms:
|
||||
columns.append({
|
||||
"label": "Payment Term",
|
||||
"label": _("Payment Term"),
|
||||
"fieldname": "payment_term",
|
||||
"fieldtype": "Data",
|
||||
"width": 120
|
||||
})
|
||||
columns.append({
|
||||
"label": "Invoice Grand Total",
|
||||
"label": _("Invoice Grand Total"),
|
||||
"fieldname": "invoice_grand_total",
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
@@ -83,7 +83,7 @@ class ReceivablePayableReport(object):
|
||||
|
||||
for label in ("Invoiced Amount", "Paid Amount", credit_or_debit_note, "Outstanding Amount"):
|
||||
columns.append({
|
||||
"label": label,
|
||||
"label": _(label),
|
||||
"fieldname": frappe.scrub(label),
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
@@ -100,11 +100,14 @@ class ReceivablePayableReport(object):
|
||||
self.filters["range2"] = "60"
|
||||
if not "range3" in self.filters:
|
||||
self.filters["range3"] = "90"
|
||||
if not "range4" in self.filters:
|
||||
self.filters["range4"] = "120"
|
||||
|
||||
for label in ("0-{range1}".format(range1=self.filters["range1"]),
|
||||
"{range1}-{range2}".format(range1=cint(self.filters["range1"])+ 1, range2=self.filters["range2"]),
|
||||
"{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
|
||||
"{range3}-{above}".format(range3=cint(self.filters["range3"])+ 1, above=_("Above"))):
|
||||
"{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
|
||||
"{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))):
|
||||
columns.append({
|
||||
"label": label,
|
||||
"fieldname":label,
|
||||
@@ -328,18 +331,17 @@ class ReceivablePayableReport(object):
|
||||
entry_date = gle.posting_date
|
||||
|
||||
row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
|
||||
cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount)
|
||||
|
||||
cint(self.filters.range3), cint(self.filters.range4), self.age_as_on, entry_date, outstanding_amount)
|
||||
|
||||
# issue 6371-Ageing buckets should not have amounts if due date is not reached
|
||||
if self.filters.ageing_based_on == "Due Date" \
|
||||
and getdate(due_date) > getdate(self.filters.report_date):
|
||||
row[-1]=row[-2]=row[-3]=row[-4]=0
|
||||
row[-1]=row[-2]=row[-3]=row[-4]=row[-5]=0
|
||||
|
||||
if self.filters.ageing_based_on == "Supplier Invoice Date" \
|
||||
and getdate(bill_date) > getdate(self.filters.report_date):
|
||||
|
||||
row[-1]=row[-2]=row[-3]=row[-4]=0
|
||||
row[-1]=row[-2]=row[-3]=row[-4]=row[-5]=0
|
||||
|
||||
if self.filters.get(scrub(args.get("party_type"))):
|
||||
row.append(gle.account_currency)
|
||||
@@ -585,13 +587,13 @@ class ReceivablePayableReport(object):
|
||||
return payment_term_map
|
||||
|
||||
def get_chart_data(self, columns, data):
|
||||
ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+4]
|
||||
ageing_columns = columns[self.ageing_col_idx_start : self.ageing_col_idx_start+5]
|
||||
|
||||
rows = []
|
||||
for d in data:
|
||||
rows.append(
|
||||
{
|
||||
'values': d[self.ageing_col_idx_start : self.ageing_col_idx_start+4]
|
||||
'values': d[self.ageing_col_idx_start : self.ageing_col_idx_start+5]
|
||||
}
|
||||
)
|
||||
|
||||
@@ -610,21 +612,22 @@ def execute(filters=None):
|
||||
}
|
||||
return ReceivablePayableReport(filters).run(args)
|
||||
|
||||
def get_ageing_data(first_range, second_range, third_range, age_as_on, entry_date, outstanding_amount):
|
||||
# [0-30, 30-60, 60-90, 90-above]
|
||||
outstanding_range = [0.0, 0.0, 0.0, 0.0]
|
||||
def get_ageing_data(first_range, second_range, third_range,
|
||||
fourth_range, age_as_on, entry_date, outstanding_amount):
|
||||
# [0-30, 30-60, 60-90, 90-120, 120-above]
|
||||
outstanding_range = [0.0, 0.0, 0.0, 0.0, 0.0]
|
||||
|
||||
if not (age_as_on and entry_date):
|
||||
return [0] + outstanding_range
|
||||
|
||||
age = (getdate(age_as_on) - getdate(entry_date)).days or 0
|
||||
index = None
|
||||
for i, days in enumerate([first_range, second_range, third_range]):
|
||||
for i, days in enumerate([first_range, second_range, third_range, fourth_range]):
|
||||
if age <= days:
|
||||
index = i
|
||||
break
|
||||
|
||||
if index is None: index = 3
|
||||
if index is None: index = 4
|
||||
outstanding_range[index] = outstanding_amount
|
||||
|
||||
return [age] + outstanding_range
|
||||
|
||||
@@ -44,6 +44,13 @@ frappe.query_reports["Accounts Receivable Summary"] = {
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"range4",
|
||||
"label": __("Ageing Range 4"),
|
||||
"fieldtype": "Int",
|
||||
"default": "120",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"finance_book",
|
||||
"label": __("Finance Book"),
|
||||
|
||||
@@ -82,8 +82,15 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
"width": 160
|
||||
},
|
||||
{
|
||||
"label": _(str(self.filters.range3) + _("-Above")),
|
||||
"fieldname": scrub(str(self.filters.range3) + _("-Above")),
|
||||
"label": _(str(self.filters.range3) + "-" + str(self.filters.range4)),
|
||||
"fieldname": scrub(str(self.filters.range3) + "-" + str(self.filters.range4)),
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 160
|
||||
},
|
||||
{
|
||||
"label": _(str(self.filters.range4) + _("-Above")),
|
||||
"fieldname": scrub(str(self.filters.range4) + _("-Above")),
|
||||
"fieldtype": "Currency",
|
||||
"options": "currency",
|
||||
"width": 160
|
||||
@@ -152,7 +159,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
|
||||
row += [
|
||||
party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
|
||||
party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4,
|
||||
party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4, party_dict.range5
|
||||
]
|
||||
|
||||
if args.get("party_type") == "Customer":
|
||||
@@ -178,6 +185,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
"range2": 0,
|
||||
"range3": 0,
|
||||
"range4": 0,
|
||||
"range5": 0,
|
||||
"sales_person": []
|
||||
})
|
||||
)
|
||||
@@ -209,7 +217,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
cols += ["bill_no", "bill_date"]
|
||||
|
||||
cols += ["invoiced_amt", "paid_amt", "credit_amt",
|
||||
"outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref",
|
||||
"outstanding_amt", "age", "range1", "range2", "range3", "range4", "range5", "currency", "pdc/lc_date", "pdc/lc_ref",
|
||||
"pdc/lc_amount"]
|
||||
|
||||
if args.get("party_type") == "Supplier":
|
||||
|
||||
@@ -10,4 +10,10 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
"fieldtype": "Check",
|
||||
"default": 1
|
||||
});
|
||||
|
||||
frappe.query_reports["Balance Sheet"]["filters"].push({
|
||||
"fieldname": "include_default_book_entries",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,8 +45,8 @@ def execute(filters=None):
|
||||
|
||||
if(filters.get("show_cumulative")):
|
||||
last_total = period_data[0] - period_data[1]
|
||||
|
||||
period_data[2] = period_data[0] - period_data[1]
|
||||
|
||||
period_data[2] = period_data[0] - period_data[1]
|
||||
row += period_data
|
||||
totals[2] = totals[0] - totals[1]
|
||||
if filters["period"] != "Yearly" :
|
||||
@@ -60,7 +60,7 @@ def validate_filters(filters):
|
||||
frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center"))
|
||||
|
||||
def get_columns(filters):
|
||||
columns = [_(filters.get("budget_against")) + ":Link/%s:80"%(filters.get("budget_against")), _("Account") + ":Link/Account:80"]
|
||||
columns = [_(filters.get("budget_against")) + ":Link/%s:150"%(filters.get("budget_against")), _("Account") + ":Link/Account:150"]
|
||||
|
||||
group_months = False if filters["period"] == "Monthly" else True
|
||||
|
||||
@@ -71,7 +71,7 @@ def get_columns(filters):
|
||||
if filters["period"] == "Yearly":
|
||||
labels = [_("Budget") + " " + str(year[0]), _("Actual ") + " " + str(year[0]), _("Varaiance ") + " " + str(year[0])]
|
||||
for label in labels:
|
||||
columns.append(label+":Float:80")
|
||||
columns.append(label+":Float:150")
|
||||
else:
|
||||
for label in [_("Budget") + " (%s)" + " " + str(year[0]), _("Actual") + " (%s)" + " " + str(year[0]), _("Variance") + " (%s)" + " " + str(year[0])]:
|
||||
if group_months:
|
||||
@@ -79,20 +79,20 @@ def get_columns(filters):
|
||||
else:
|
||||
label = label % formatdate(from_date, format_string="MMM")
|
||||
|
||||
columns.append(label+":Float:80")
|
||||
columns.append(label+":Float:150")
|
||||
|
||||
if filters["period"] != "Yearly" :
|
||||
return columns + [_("Total Budget") + ":Float:80", _("Total Actual") + ":Float:80",
|
||||
_("Total Variance") + ":Float:80"]
|
||||
return columns + [_("Total Budget") + ":Float:150", _("Total Actual") + ":Float:150",
|
||||
_("Total Variance") + ":Float:150"]
|
||||
else:
|
||||
return columns
|
||||
|
||||
|
||||
def get_cost_centers(filters):
|
||||
cond = "and 1=1"
|
||||
if filters.get("budget_against") == "Cost Center":
|
||||
cond = "order by lft"
|
||||
|
||||
return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
|
||||
return frappe.db.sql_list("""select name from `tab{tab}` where company=%s
|
||||
{cond}""".format(tab=filters.get("budget_against"), cond=cond), filters.get("company"))
|
||||
|
||||
#Get cost center & target details
|
||||
@@ -109,7 +109,7 @@ def get_cost_center_target_details(filters):
|
||||
""".format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond),
|
||||
(filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True)
|
||||
|
||||
|
||||
|
||||
|
||||
#Get target distribution details of accounts of cost center
|
||||
def get_target_distribution_details(filters):
|
||||
@@ -118,7 +118,7 @@ def get_target_distribution_details(filters):
|
||||
from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
|
||||
where mdp.parent=md.name and md.fiscal_year between %s and %s order by md.fiscal_year""",(filters.from_fiscal_year, filters.to_fiscal_year), as_dict=1):
|
||||
target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
|
||||
|
||||
|
||||
return target_details
|
||||
|
||||
#Get actual details from gl entry
|
||||
@@ -129,7 +129,7 @@ def get_actual_details(name, filters):
|
||||
if filters.get("budget_against") == "Cost Center":
|
||||
cc_lft, cc_rgt = frappe.db.get_value("Cost Center", name, ["lft", "rgt"])
|
||||
cond = "lft>='{lft}' and rgt<='{rgt}'".format(lft = cc_lft, rgt=cc_rgt)
|
||||
|
||||
|
||||
ac_details = frappe.db.sql("""select gl.account, gl.debit, gl.credit,gl.fiscal_year,
|
||||
MONTHNAME(gl.posting_date) as month_name, b.{budget_against} as budget_against
|
||||
from `tabGL Entry` gl, `tabBudget Account` ba, `tabBudget` b
|
||||
@@ -159,7 +159,7 @@ def get_cost_center_account_month_map(filters):
|
||||
|
||||
for ccd in cost_center_target_details:
|
||||
actual_details = get_actual_details(ccd.budget_against, filters)
|
||||
|
||||
|
||||
for month_id in range(1, 13):
|
||||
month = datetime.date(2013, month_id, 1).strftime('%B')
|
||||
cam_map.setdefault(ccd.budget_against, {}).setdefault(ccd.account, {}).setdefault(ccd.fiscal_year,{})\
|
||||
@@ -172,7 +172,7 @@ def get_cost_center_account_month_map(filters):
|
||||
if ccd.monthly_distribution else 100.0/12
|
||||
|
||||
tav_dict.target = flt(ccd.budget_amount) * month_percentage / 100
|
||||
|
||||
|
||||
for ad in actual_details.get(ccd.account, []):
|
||||
if ad.month_name == month:
|
||||
tav_dict.actual += flt(ad.debit) - flt(ad.credit)
|
||||
|
||||
@@ -15,4 +15,10 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
"label": __("Accumulated Values"),
|
||||
"fieldtype": "Check"
|
||||
});
|
||||
|
||||
frappe.query_reports["Cash Flow"]["filters"].push({
|
||||
"fieldname": "include_default_book_entries",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
});
|
||||
});
|
||||
@@ -14,8 +14,8 @@ def execute(filters=None):
|
||||
if cint(frappe.db.get_single_value('Accounts Settings', 'use_custom_cash_flow')):
|
||||
from erpnext.accounts.report.cash_flow.custom_cash_flow import execute as execute_custom
|
||||
return execute_custom(filters=filters)
|
||||
|
||||
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
|
||||
|
||||
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
|
||||
filters.periodicity, filters.accumulated_values, filters.company)
|
||||
|
||||
cash_flow_accounts = get_cash_flow_accounts()
|
||||
@@ -25,18 +25,18 @@ def execute(filters=None):
|
||||
accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
|
||||
expense = get_data(filters.company, "Expense", "Debit", period_list, filters=filters,
|
||||
accumulated_values=filters.accumulated_values, ignore_closing_entries=True, ignore_accumulated_values_for_fy= True)
|
||||
|
||||
|
||||
net_profit_loss = get_net_profit_loss(income, expense, period_list, filters.company)
|
||||
|
||||
data = []
|
||||
company_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
|
||||
|
||||
|
||||
for cash_flow_account in cash_flow_accounts:
|
||||
section_data = []
|
||||
data.append({
|
||||
"account_name": cash_flow_account['section_header'],
|
||||
"account_name": cash_flow_account['section_header'],
|
||||
"parent_account": None,
|
||||
"indent": 0.0,
|
||||
"indent": 0.0,
|
||||
"account": cash_flow_account['section_header']
|
||||
})
|
||||
|
||||
@@ -44,18 +44,18 @@ def execute(filters=None):
|
||||
# add first net income in operations section
|
||||
if net_profit_loss:
|
||||
net_profit_loss.update({
|
||||
"indent": 1,
|
||||
"indent": 1,
|
||||
"parent_account": cash_flow_accounts[0]['section_header']
|
||||
})
|
||||
data.append(net_profit_loss)
|
||||
section_data.append(net_profit_loss)
|
||||
|
||||
for account in cash_flow_account['account_types']:
|
||||
account_data = get_account_type_based_data(filters.company,
|
||||
account['account_type'], period_list, filters.accumulated_values)
|
||||
account_data = get_account_type_based_data(filters.company,
|
||||
account['account_type'], period_list, filters.accumulated_values, filters)
|
||||
account_data.update({
|
||||
"account_name": account['label'],
|
||||
"account": account['label'],
|
||||
"account": account['label'],
|
||||
"indent": 1,
|
||||
"parent_account": cash_flow_account['section_header'],
|
||||
"currency": company_currency
|
||||
@@ -63,7 +63,7 @@ def execute(filters=None):
|
||||
data.append(account_data)
|
||||
section_data.append(account_data)
|
||||
|
||||
add_total_row_account(data, section_data, cash_flow_account['section_footer'],
|
||||
add_total_row_account(data, section_data, cash_flow_account['section_footer'],
|
||||
period_list, company_currency)
|
||||
|
||||
add_total_row_account(data, data, _("Net Change in Cash"), period_list, company_currency)
|
||||
@@ -105,13 +105,15 @@ def get_cash_flow_accounts():
|
||||
# combine all cash flow accounts for iteration
|
||||
return [operation_accounts, investing_accounts, financing_accounts]
|
||||
|
||||
def get_account_type_based_data(company, account_type, period_list, accumulated_values):
|
||||
def get_account_type_based_data(company, account_type, period_list, accumulated_values, filters):
|
||||
data = {}
|
||||
total = 0
|
||||
for period in period_list:
|
||||
start_date = get_start_date(period, accumulated_values, company)
|
||||
|
||||
amount = get_account_type_based_gl_data(company, start_date, period['to_date'], account_type)
|
||||
amount = get_account_type_based_gl_data(company, start_date,
|
||||
period['to_date'], account_type, filters)
|
||||
|
||||
if amount and account_type == "Depreciation":
|
||||
amount *= -1
|
||||
|
||||
@@ -121,14 +123,24 @@ def get_account_type_based_data(company, account_type, period_list, accumulated_
|
||||
data["total"] = total
|
||||
return data
|
||||
|
||||
def get_account_type_based_gl_data(company, start_date, end_date, account_type):
|
||||
def get_account_type_based_gl_data(company, start_date, end_date, account_type, filters):
|
||||
cond = ""
|
||||
|
||||
if filters.finance_book:
|
||||
cond = " and finance_book = '%s'" %(frappe.db.escape(filters.finance_book))
|
||||
if filters.include_default_book_entries:
|
||||
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
|
||||
|
||||
cond = """ and finance_book in ('%s', '%s')
|
||||
""" %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
|
||||
|
||||
gl_sum = frappe.db.sql_list("""
|
||||
select sum(credit) - sum(debit)
|
||||
from `tabGL Entry`
|
||||
where company=%s and posting_date >= %s and posting_date <= %s
|
||||
and voucher_type != 'Period Closing Voucher'
|
||||
and account in ( SELECT name FROM tabAccount WHERE account_type = %s)
|
||||
""", (company, start_date, end_date, account_type))
|
||||
and account in ( SELECT name FROM tabAccount WHERE account_type = %s) {cond}
|
||||
""".format(cond=cond), (company, start_date, end_date, account_type))
|
||||
|
||||
return gl_sum[0] if gl_sum and gl_sum[0] else 0
|
||||
|
||||
@@ -154,7 +166,7 @@ def add_total_row_account(out, data, label, period_list, currency, consolidated
|
||||
key = period if consolidated else period['key']
|
||||
total_row.setdefault(key, 0.0)
|
||||
total_row[key] += row.get(key, 0.0)
|
||||
|
||||
|
||||
total_row.setdefault("total", 0.0)
|
||||
total_row["total"] += row["total"]
|
||||
|
||||
|
||||
@@ -55,5 +55,10 @@ frappe.query_reports["Consolidated Financial Statement"] = {
|
||||
"fieldtype": "Check",
|
||||
"default": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "include_default_book_entries",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -355,7 +355,8 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g
|
||||
"lft": root_lft,
|
||||
"rgt": root_rgt,
|
||||
"company": d.name,
|
||||
"finance_book": filters.get("finance_book")
|
||||
"finance_book": filters.get("finance_book"),
|
||||
"company_fb": frappe.db.get_value("Company", d.name, 'default_finance_book')
|
||||
},
|
||||
as_dict=True)
|
||||
|
||||
@@ -386,7 +387,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
|
||||
additional_conditions.append("gl.posting_date >= %(from_date)s")
|
||||
|
||||
if filters.get("finance_book"):
|
||||
additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
|
||||
if filters.get("include_default_book_entries"):
|
||||
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
||||
else:
|
||||
additional_conditions.append("finance_book in (%(finance_book)s)")
|
||||
|
||||
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for(var j=0, k=data.length; j<k; j++) { %}
|
||||
{% for(var j=0, k=data.length-1; j<k; j++) { %}
|
||||
{%
|
||||
var row = data[j];
|
||||
var row_class = data[j].parent_account ? "" : "financial-statements-important";
|
||||
|
||||
@@ -359,7 +359,8 @@ def set_gl_entries_by_account(
|
||||
"to_date": to_date,
|
||||
"cost_center": filters.cost_center,
|
||||
"project": filters.project,
|
||||
"finance_book": filters.get("finance_book")
|
||||
"finance_book": filters.get("finance_book"),
|
||||
"company_fb": frappe.db.get_value("Company", company, 'default_finance_book')
|
||||
},
|
||||
as_dict=True)
|
||||
|
||||
@@ -393,7 +394,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
|
||||
additional_conditions.append("cost_center in %(cost_center)s")
|
||||
|
||||
if filters.get("finance_book"):
|
||||
additional_conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
|
||||
if filters.get("include_default_book_entries"):
|
||||
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
||||
else:
|
||||
additional_conditions.append("finance_book in (%(finance_book)s)")
|
||||
|
||||
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for(var i=0, l=data.length; i<l; i++) { %}
|
||||
{% for(var i=0, l=data.length-1; i<l; i++) { %}
|
||||
<tr>
|
||||
{% if(data[i].posting_date) { %}
|
||||
<td>{%= frappe.datetime.str_to_user(data[i].posting_date) %}</td>
|
||||
|
||||
@@ -216,6 +216,11 @@ frappe.query_reports["General Ledger"] = {
|
||||
"fieldname": "show_opening_entries",
|
||||
"label": __("Show Opening Entries"),
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"fieldname": "include_default_book_entries",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -128,10 +128,15 @@ def get_gl_entries(filters):
|
||||
|
||||
if filters.get("group_by") == _("Group by Voucher (Consolidated)"):
|
||||
group_by_statement = "group by voucher_type, voucher_no, account, cost_center"
|
||||
|
||||
select_fields = """, sum(debit) as debit, sum(credit) as credit,
|
||||
sum(debit_in_account_currency) as debit_in_account_currency,
|
||||
sum(credit_in_account_currency) as credit_in_account_currency"""
|
||||
|
||||
if filters.get("include_default_book_entries"):
|
||||
filters['company_fb'] = frappe.db.get_value("Company",
|
||||
filters.get("company"), 'default_finance_book')
|
||||
|
||||
gl_entries = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
@@ -187,7 +192,10 @@ def get_conditions(filters):
|
||||
conditions.append("project in %(project)s")
|
||||
|
||||
if filters.get("finance_book"):
|
||||
conditions.append("ifnull(finance_book, '') in (%(finance_book)s, '')")
|
||||
if filters.get("include_default_book_entries"):
|
||||
conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
|
||||
else:
|
||||
conditions.append("finance_book in (%(finance_book)s)")
|
||||
|
||||
from frappe.desk.reportview import build_match_conditions
|
||||
match_conditions = build_match_conditions("GL Entry")
|
||||
|
||||
@@ -102,7 +102,9 @@ def get_conditions(filters):
|
||||
("customer", " and `tabSales Invoice`.customer = %(customer)s"),
|
||||
("item_code", " and `tabSales Invoice Item`.item_code = %(item_code)s"),
|
||||
("from_date", " and `tabSales Invoice`.posting_date>=%(from_date)s"),
|
||||
("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s")):
|
||||
("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s"),
|
||||
("company_gstin", " and `tabSales Invoice`.company_gstin = %(company_gstin)s"),
|
||||
("invoice_type", " and `tabSales Invoice`.invoice_type = %(invoice_type)s")):
|
||||
if filters.get(opts[0]):
|
||||
conditions += opts[1]
|
||||
|
||||
|
||||
@@ -12,20 +12,21 @@ def get_ordered_to_be_billed_data(args):
|
||||
child_tab = doctype + " Item"
|
||||
precision = get_field_precision(frappe.get_meta(child_tab).get_field("billed_amt"),
|
||||
currency=get_default_currency()) or 2
|
||||
|
||||
|
||||
project_field = get_project_field(doctype, party)
|
||||
|
||||
return frappe.db.sql("""
|
||||
Select
|
||||
`{parent_tab}`.name, `{parent_tab}`.{date_field}, `{parent_tab}`.{party}, `{parent_tab}`.{party}_name,
|
||||
{project_field}, `{child_tab}`.item_code, `{child_tab}`.base_amount,
|
||||
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
|
||||
(`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1)),
|
||||
(`{child_tab}`.base_amount - (`{child_tab}`.billed_amt * ifnull(`{parent_tab}`.conversion_rate, 1))),
|
||||
`{child_tab}`.item_name, `{child_tab}`.description, `{parent_tab}`.company
|
||||
from
|
||||
`{parent_tab}`, `{child_tab}`
|
||||
where
|
||||
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1 and `{parent_tab}`.status != 'Closed'
|
||||
`{parent_tab}`.name = `{child_tab}`.parent and `{parent_tab}`.docstatus = 1
|
||||
and `{parent_tab}`.status not in ('Closed', 'Completed')
|
||||
and `{child_tab}`.amount > 0 and round(`{child_tab}`.billed_amt *
|
||||
ifnull(`{parent_tab}`.conversion_rate, 1), {precision}) < `{child_tab}`.base_amount
|
||||
order by
|
||||
|
||||
@@ -18,22 +18,22 @@ def execute(filters=None):
|
||||
data = []
|
||||
for d in entries:
|
||||
invoice = invoice_details.get(d.against_voucher) or frappe._dict()
|
||||
|
||||
|
||||
if d.reference_type=="Purchase Invoice":
|
||||
payment_amount = flt(d.debit) or -1 * flt(d.credit)
|
||||
else:
|
||||
payment_amount = flt(d.credit) or -1 * flt(d.debit)
|
||||
|
||||
row = [d.voucher_type, d.voucher_no, d.party_type, d.party, d.posting_date, d.against_voucher,
|
||||
row = [d.voucher_type, d.voucher_no, d.party_type, d.party, d.posting_date, d.against_voucher,
|
||||
invoice.posting_date, invoice.due_date, d.debit, d.credit, d.remarks]
|
||||
|
||||
if d.against_voucher:
|
||||
row += get_ageing_data(30, 60, 90, d.posting_date, invoice.posting_date, payment_amount)
|
||||
row += get_ageing_data(30, 60, 90, 120, d.posting_date, invoice.posting_date, payment_amount)
|
||||
else:
|
||||
row += ["", "", "", "", ""]
|
||||
if invoice.due_date:
|
||||
row.append((getdate(d.posting_date) - getdate(invoice.due_date)).days or 0)
|
||||
|
||||
|
||||
data.append(row)
|
||||
|
||||
return columns, data
|
||||
@@ -48,19 +48,19 @@ def get_columns(filters):
|
||||
return [
|
||||
_("Payment Document") + ":: 100",
|
||||
_("Payment Entry") + ":Dynamic Link/"+_("Payment Document")+":140",
|
||||
_("Party Type") + "::100",
|
||||
_("Party Type") + "::100",
|
||||
_("Party") + ":Dynamic Link/Party Type:140",
|
||||
_("Posting Date") + ":Date:100",
|
||||
_("Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
|
||||
_("Invoice Posting Date") + ":Date:130",
|
||||
_("Payment Due Date") + ":Date:130",
|
||||
_("Debit") + ":Currency:120",
|
||||
_("Invoice Posting Date") + ":Date:130",
|
||||
_("Payment Due Date") + ":Date:130",
|
||||
_("Debit") + ":Currency:120",
|
||||
_("Credit") + ":Currency:120",
|
||||
_("Remarks") + "::150",
|
||||
_("Remarks") + "::150",
|
||||
_("Age") +":Int:40",
|
||||
"0-30:Currency:100",
|
||||
"30-60:Currency:100",
|
||||
"60-90:Currency:100",
|
||||
"0-30:Currency:100",
|
||||
"30-60:Currency:100",
|
||||
"60-90:Currency:100",
|
||||
_("90-Above") + ":Currency:100",
|
||||
_("Delay in payment (Days)") + "::150"
|
||||
]
|
||||
@@ -79,21 +79,21 @@ def get_conditions(filters):
|
||||
|
||||
if filters.party:
|
||||
conditions.append("party=%(party)s")
|
||||
|
||||
|
||||
if filters.party_type:
|
||||
conditions.append("against_voucher_type=%(reference_type)s")
|
||||
filters["reference_type"] = "Sales Invoice" if filters.party_type=="Customer" else "Purchase Invoice"
|
||||
|
||||
if filters.get("from_date"):
|
||||
conditions.append("posting_date >= %(from_date)s")
|
||||
|
||||
|
||||
if filters.get("to_date"):
|
||||
conditions.append("posting_date <= %(to_date)s")
|
||||
|
||||
return "and " + " and ".join(conditions) if conditions else ""
|
||||
|
||||
def get_entries(filters):
|
||||
return frappe.db.sql("""select
|
||||
return frappe.db.sql("""select
|
||||
voucher_type, voucher_no, party_type, party, posting_date, debit, credit, remarks, against_voucher
|
||||
from `tabGL Entry`
|
||||
where company=%(company)s and voucher_type in ('Journal Entry', 'Payment Entry') {0}
|
||||
|
||||
@@ -41,6 +41,11 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
|
||||
"fieldname": "accumulated_values",
|
||||
"label": __("Accumulated Values"),
|
||||
"fieldtype": "Check"
|
||||
},
|
||||
{
|
||||
"fieldname": "include_default_book_entries",
|
||||
"label": __("Include Default Book Entries"),
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -47,8 +47,8 @@ class TestSalesPaymentSummary(unittest.TestCase):
|
||||
pe.submit()
|
||||
|
||||
mop = get_mode_of_payments(filters)
|
||||
self.assertTrue('Credit Card' in mop.values()[0])
|
||||
self.assertTrue('Cash' in mop.values()[0])
|
||||
self.assertTrue('Credit Card' in list(mop.values())[0])
|
||||
self.assertTrue('Cash' in list(mop.values())[0])
|
||||
|
||||
# Cancel all Cash payment entry and check if this mode of payment is still fetched.
|
||||
payment_entries = frappe.get_all("Payment Entry", filters={"mode_of_payment": "Cash", "docstatus": 1}, fields=["name", "docstatus"])
|
||||
@@ -57,8 +57,8 @@ class TestSalesPaymentSummary(unittest.TestCase):
|
||||
pe.cancel()
|
||||
|
||||
mop = get_mode_of_payments(filters)
|
||||
self.assertTrue('Credit Card' in mop.values()[0])
|
||||
self.assertTrue('Cash' not in mop.values()[0])
|
||||
self.assertTrue('Credit Card' in list(mop.values())[0])
|
||||
self.assertTrue('Cash' not in list(mop.values())[0])
|
||||
|
||||
def test_get_mode_of_payments_details(self):
|
||||
filters = get_filters()
|
||||
@@ -84,7 +84,7 @@ class TestSalesPaymentSummary(unittest.TestCase):
|
||||
|
||||
mopd = get_mode_of_payment_details(filters)
|
||||
|
||||
mopd_values = mopd.values()[0]
|
||||
mopd_values = list(mopd.values())[0]
|
||||
for mopd_value in mopd_values:
|
||||
if mopd_value[0] == "Credit Card":
|
||||
cc_init_amount = mopd_value[1]
|
||||
@@ -96,7 +96,7 @@ class TestSalesPaymentSummary(unittest.TestCase):
|
||||
pe.cancel()
|
||||
|
||||
mopd = get_mode_of_payment_details(filters)
|
||||
mopd_values = mopd.values()[0]
|
||||
mopd_values = list(mopd.values())[0]
|
||||
for mopd_value in mopd_values:
|
||||
if mopd_value[0] == "Credit Card":
|
||||
cc_final_amount = mopd_value[1]
|
||||
|
||||
@@ -105,7 +105,7 @@ def get_rootwise_opening_balances(filters, report_type):
|
||||
if filters.finance_book:
|
||||
fb_conditions = " and finance_book = %(finance_book)s"
|
||||
if filters.include_default_book_entries:
|
||||
fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s) or finance_book is null)"
|
||||
fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s))"
|
||||
|
||||
additional_conditions += fb_conditions
|
||||
|
||||
@@ -180,20 +180,28 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances, filters,
|
||||
|
||||
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
|
||||
d["opening_debit"] -= d["opening_credit"]
|
||||
d["opening_credit"] = 0.0
|
||||
total_row["opening_debit"] += d["opening_debit"]
|
||||
d["closing_debit"] -= d["closing_credit"]
|
||||
|
||||
# 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["opening_debit"] = 0.0
|
||||
total_row["opening_credit"] += d["opening_credit"]
|
||||
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
|
||||
d["closing_debit"] -= d["closing_credit"]
|
||||
d["closing_credit"] = 0.0
|
||||
total_row["closing_debit"] += d["closing_debit"]
|
||||
if d["root_type"] == "Liability" or d["root_type"] == "Income":
|
||||
d["closing_credit"] -= d["closing_debit"]
|
||||
d["closing_debit"] = 0.0
|
||||
total_row["closing_credit"] += d["closing_credit"]
|
||||
|
||||
# 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"]
|
||||
|
||||
return total_row
|
||||
|
||||
@@ -219,8 +227,6 @@ def prepare_data(accounts, filters, total_row, parent_children_map, company_curr
|
||||
if d.account_number else d.account_name)
|
||||
}
|
||||
|
||||
prepare_opening_and_closing(d)
|
||||
|
||||
for key in value_fields:
|
||||
row[key] = flt(d.get(key, 0.0), 3)
|
||||
|
||||
@@ -295,22 +301,11 @@ def get_columns():
|
||||
}
|
||||
]
|
||||
|
||||
def prepare_opening_and_closing(d):
|
||||
d["closing_debit"] = d["opening_debit"] + d["debit"]
|
||||
d["closing_credit"] = d["opening_credit"] + d["credit"]
|
||||
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.
|
||||
|
||||
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
|
||||
d["opening_debit"] -= d["opening_credit"]
|
||||
d["opening_credit"] = 0.0
|
||||
|
||||
if d["root_type"] == "Liability" or d["root_type"] == "Income":
|
||||
d["opening_credit"] -= d["opening_debit"]
|
||||
d["opening_debit"] = 0.0
|
||||
|
||||
if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense":
|
||||
d["closing_debit"] -= d["closing_credit"]
|
||||
d["closing_credit"] = 0.0
|
||||
|
||||
if d["root_type"] == "Liability" or d["root_type"] == "Income":
|
||||
d["closing_credit"] -= d["closing_debit"]
|
||||
d["closing_debit"] = 0.0
|
||||
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
|
||||
|
||||
@@ -333,7 +333,7 @@ def reconcile_against_document(args):
|
||||
doc = frappe.get_doc(d.voucher_type, d.voucher_no)
|
||||
doc.make_gl_entries(cancel = 0, adv_adj =1)
|
||||
|
||||
if d.voucher_type == 'Payment Entry':
|
||||
if d.voucher_type in ('Payment Entry', 'Journal Entry'):
|
||||
doc.update_expense_claim()
|
||||
|
||||
def check_if_advance_entry_modified(args):
|
||||
@@ -378,9 +378,9 @@ def check_if_advance_entry_modified(args):
|
||||
|
||||
def validate_allocated_amount(args):
|
||||
if args.get("allocated_amount") < 0:
|
||||
throw(_("Allocated amount can not be negative"))
|
||||
throw(_("Allocated amount cannot be negative"))
|
||||
elif args.get("allocated_amount") > args.get("unadjusted_amount"):
|
||||
throw(_("Allocated amount can not greater than unadjusted amount"))
|
||||
throw(_("Allocated amount cannot be greater than unadjusted amount"))
|
||||
|
||||
def update_reference_in_journal_entry(d, jv_obj):
|
||||
"""
|
||||
|
||||
@@ -6,7 +6,6 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
|
||||
class Disease(Document):
|
||||
def validate(self):
|
||||
|
||||
@@ -7,7 +7,6 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt, cint
|
||||
from frappe import _
|
||||
|
||||
class SoilTexture(Document):
|
||||
soil_edit_order = [2, 1, 0]
|
||||
@@ -35,8 +34,8 @@ class SoilTexture(Document):
|
||||
if sum(self.soil_edit_order) < 5: return
|
||||
last_edit_index = self.soil_edit_order.index(min(self.soil_edit_order))
|
||||
|
||||
# set composition of the last edited soil
|
||||
self.set( self.soil_types[last_edit_index],
|
||||
# set composition of the last edited soil
|
||||
self.set( self.soil_types[last_edit_index],
|
||||
100 - sum(cint(self.get(soil_type)) for soil_type in self.soil_types) + cint(self.get(self.soil_types[last_edit_index])))
|
||||
|
||||
# calculate soil type
|
||||
|
||||
@@ -6,7 +6,6 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
|
||||
class WaterAnalysis(Document):
|
||||
def load_contents(self):
|
||||
|
||||
@@ -291,16 +291,19 @@ class Asset(AccountsController):
|
||||
|
||||
def validate_expected_value_after_useful_life(self):
|
||||
for row in self.get('finance_books'):
|
||||
accumulated_depreciation_after_full_schedule = max([d.accumulated_depreciation_amount
|
||||
for d in self.get("schedules") if cint(d.finance_book_id) == row.idx])
|
||||
accumulated_depreciation_after_full_schedule = [d.accumulated_depreciation_amount
|
||||
for d in self.get("schedules") if cint(d.finance_book_id) == row.idx]
|
||||
|
||||
asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
|
||||
flt(accumulated_depreciation_after_full_schedule),
|
||||
self.precision('gross_purchase_amount'))
|
||||
if accumulated_depreciation_after_full_schedule:
|
||||
accumulated_depreciation_after_full_schedule = max(accumulated_depreciation_after_full_schedule)
|
||||
|
||||
if row.expected_value_after_useful_life < asset_value_after_full_schedule:
|
||||
frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
|
||||
.format(row.idx, asset_value_after_full_schedule))
|
||||
asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) -
|
||||
flt(accumulated_depreciation_after_full_schedule),
|
||||
self.precision('gross_purchase_amount'))
|
||||
|
||||
if row.expected_value_after_useful_life < asset_value_after_full_schedule:
|
||||
frappe.throw(_("Depreciation Row {0}: Expected value after useful life must be greater than or equal to {1}")
|
||||
.format(row.idx, asset_value_after_full_schedule))
|
||||
|
||||
def validate_cancellation(self):
|
||||
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
|
||||
|
||||
@@ -36,7 +36,7 @@ class AssetValueAdjustment(Document):
|
||||
fixed_asset_account, accumulated_depreciation_account, depreciation_expense_account = \
|
||||
get_depreciation_accounts(asset)
|
||||
|
||||
depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company,
|
||||
depreciation_cost_center, depreciation_series = frappe.get_cached_value('Company', asset.company,
|
||||
["depreciation_cost_center", "series_for_depreciation_entry"])
|
||||
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
@@ -75,8 +75,8 @@ class AssetValueAdjustment(Document):
|
||||
rate_per_day = flt(d.value_after_depreciation) / flt(total_days)
|
||||
from_date = self.date
|
||||
else:
|
||||
no_of_depreciations = len([e.name for e in asset.schedules
|
||||
if (cint(s.finance_book_id) == d.idx and not e.journal_entry)])
|
||||
no_of_depreciations = len([s.name for s in asset.schedules
|
||||
if (cint(s.finance_book_id) == d.idx and not s.journal_entry)])
|
||||
|
||||
value_after_depreciation = d.value_after_depreciation
|
||||
for data in asset.schedules:
|
||||
|
||||
@@ -25,9 +25,12 @@ class TestLocation(unittest.TestCase):
|
||||
temp['features'][0]['properties']['feature_of'] = location
|
||||
formatted_locations.extend(temp['features'])
|
||||
|
||||
formatted_location_string = str(formatted_locations)
|
||||
test_location = frappe.get_doc('Location', 'Test Location Area')
|
||||
test_location.save()
|
||||
|
||||
self.assertEqual(formatted_location_string, str(json.loads(test_location.get('location'))['features']))
|
||||
test_location_features = json.loads(test_location.get('location'))['features']
|
||||
ordered_test_location_features = sorted(test_location_features, key=lambda x: x['properties']['feature_of'])
|
||||
ordered_formatted_locations = sorted(formatted_locations, key=lambda x: x['properties']['feature_of'])
|
||||
|
||||
self.assertEqual(ordered_formatted_locations, ordered_test_location_features)
|
||||
self.assertEqual(area, test_location.get('area'))
|
||||
|
||||
@@ -33,6 +33,14 @@ frappe.ui.form.on("Purchase Order", {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("expense_account", "items", function() {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.get_expense_account",
|
||||
filters: {'company': frm.doc.company}
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
@@ -96,7 +104,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
||||
|
||||
if(doc.docstatus == 1 && !in_list(["Closed", "Delivered"], doc.status)) {
|
||||
if (this.frm.has_perm("submit")) {
|
||||
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) {
|
||||
if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) {
|
||||
cur_frm.add_custom_button(__('Close'), this.close_purchase_order, __("Status"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "supplier_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -53,6 +54,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "{supplier_name}",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -86,6 +88,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@@ -121,6 +124,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -156,6 +160,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.supplier && doc.docstatus===0 && (!(doc.items && doc.items.length) || (doc.items.length==1 && !doc.items[0].item_code))",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "get_items_from_open_material_requests",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
@@ -189,6 +194,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_from": "supplier.supplier_name",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "supplier_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -222,6 +228,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -256,6 +263,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -290,6 +298,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Today",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "transaction_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@@ -324,6 +333,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "schedule_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@@ -357,6 +367,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.docstatus===1",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "order_confirmation_no",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -390,6 +401,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.order_confirmation_no",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "order_confirmation_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@@ -422,6 +434,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -457,6 +470,7 @@
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": "",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "drop_ship",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -490,6 +504,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -524,6 +539,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -556,6 +572,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -588,6 +605,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_contact_person",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -621,6 +639,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_contact_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
@@ -653,6 +672,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_contact_mobile",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 1,
|
||||
@@ -685,6 +705,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "customer_contact_email",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 1,
|
||||
@@ -718,6 +739,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_addresses",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -750,6 +772,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "supplier_address",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -782,6 +805,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "contact_person",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -815,6 +839,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "address_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
@@ -846,6 +871,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "contact_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
@@ -877,6 +903,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "contact_mobile",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
@@ -908,6 +935,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "contact_email",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
@@ -939,6 +967,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "col_break_address",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -971,6 +1000,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "shipping_address",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1004,6 +1034,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "shipping_address_display",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
@@ -1036,6 +1067,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "currency_and_price_list",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1068,6 +1100,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1103,6 +1136,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "conversion_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -1137,6 +1171,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "cb_price_list",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -1167,6 +1202,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "buying_price_list",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1199,6 +1235,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "price_list_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1231,6 +1268,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "plc_conversion_rate",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -1263,6 +1301,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "ignore_pricing_rule",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -1294,6 +1333,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sec_warehouse",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1325,6 +1365,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "set_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1358,6 +1399,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "col_break_warehouse",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -1390,6 +1432,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "No",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "is_subcontracted",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@@ -1423,6 +1466,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.is_subcontracted==\"Yes\"",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "supplier_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1456,6 +1500,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "items_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1489,6 +1534,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "scan_barcode",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -1521,6 +1567,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "items",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@@ -1556,6 +1603,7 @@
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": "supplied_items",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "raw_material_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1589,6 +1637,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "supplied_items",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@@ -1623,6 +1672,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sb_last_purchase",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1653,6 +1703,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_qty",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -1685,6 +1736,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1718,6 +1770,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_net_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1752,6 +1805,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_26",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -1782,6 +1836,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1815,6 +1870,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "net_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -1849,6 +1905,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_net_weight",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -1881,6 +1938,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "taxes_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -1915,6 +1973,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "taxes_and_charges",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -1949,6 +2008,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_50",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -1980,6 +2040,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "shipping_rule",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -2013,6 +2074,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_52",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -2044,6 +2106,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "taxes",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@@ -2078,6 +2141,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "sec_tax_breakup",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -2110,6 +2174,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "other_charges_calculation",
|
||||
"fieldtype": "Text",
|
||||
"hidden": 0,
|
||||
@@ -2142,6 +2207,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "totals",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -2175,6 +2241,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_taxes_and_charges_added",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2209,6 +2276,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_taxes_and_charges_deducted",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2243,6 +2311,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_total_taxes_and_charges",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2277,6 +2346,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_39",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -2308,6 +2378,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "taxes_and_charges_added",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2342,6 +2413,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "taxes_and_charges_deducted",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2376,6 +2448,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "total_taxes_and_charges",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2410,6 +2483,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "discount_amount",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "discount_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -2443,6 +2517,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Grand Total",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "apply_discount_on",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@@ -2476,6 +2551,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2509,6 +2585,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_45",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -2540,6 +2617,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "additional_discount_percentage",
|
||||
"fieldtype": "Float",
|
||||
"hidden": 0,
|
||||
@@ -2572,6 +2650,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "discount_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2605,6 +2684,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "totals_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -2636,6 +2716,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_grand_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2670,6 +2751,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2704,6 +2786,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "In Words will be visible once you save the Purchase Order.",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_in_words",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -2737,6 +2820,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "base_rounded_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2771,6 +2855,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -2802,6 +2887,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "grand_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2836,6 +2922,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "rounding_adjustment",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2869,6 +2956,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "rounded_total",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2881,6 +2969,7 @@
|
||||
"label": "Rounded Total",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
@@ -2901,6 +2990,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "disable_rounded_total",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -2933,6 +3023,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "in_words",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -2966,6 +3057,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "advance_paid",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
@@ -2998,6 +3090,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payment_schedule_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -3030,6 +3123,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payment_terms_template",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -3063,6 +3157,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payment_schedule",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@@ -3097,6 +3192,7 @@
|
||||
"collapsible": 1,
|
||||
"collapsible_depends_on": "terms",
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "terms_section_break",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -3130,6 +3226,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "tc_name",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -3164,6 +3261,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "terms",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
@@ -3197,6 +3295,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "more_info",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -3230,6 +3329,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Draft",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 0,
|
||||
@@ -3264,6 +3364,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "ref_sq",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -3297,6 +3398,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "party_account_currency",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
@@ -3330,6 +3432,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_74",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -3363,6 +3466,7 @@
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "per_received",
|
||||
"fieldtype": "Percent",
|
||||
"hidden": 0,
|
||||
@@ -3398,6 +3502,7 @@
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "per_billed",
|
||||
"fieldtype": "Percent",
|
||||
"hidden": 0,
|
||||
@@ -3431,6 +3536,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -3465,6 +3571,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -3499,6 +3606,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "select_print_heading",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -3533,6 +3641,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_86",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -3565,6 +3674,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "group_same_items",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -3598,6 +3708,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "language",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -3631,6 +3742,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "subscription_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -3665,6 +3777,7 @@
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "from_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@@ -3698,6 +3811,7 @@
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"description": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "to_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
@@ -3729,6 +3843,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_97",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
@@ -3760,6 +3875,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "auto_repeat",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -3794,6 +3910,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval: doc.auto_repeat",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "update_auto_repeat_reference",
|
||||
"fieldtype": "Button",
|
||||
"hidden": 0,
|
||||
@@ -3831,7 +3948,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-01-07 16:51:56.739693",
|
||||
"modified": "2019-06-24 20:55:03.466766",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -1915,7 +1915,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"default": "0",
|
||||
"depends_on": "eval:parent.is_subcontracted == 'Yes'",
|
||||
"fieldname": "include_exploded_items",
|
||||
"fieldtype": "Check",
|
||||
@@ -2344,7 +2344,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-01-07 16:51:57.546323",
|
||||
"modified": "2019-06-23 20:03:13.818917",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order Item",
|
||||
@@ -2359,4 +2359,4 @@
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +237,10 @@ class AccountsController(TransactionBase):
|
||||
document_type = "{} Item".format(self.doctype)
|
||||
parent_dict.update({"document_type": document_type})
|
||||
|
||||
# party_name field used for customer in quotation
|
||||
if self.doctype == "Quotation" and self.quotation_to == "Customer" and parent_dict.get("party_name"):
|
||||
parent_dict.update({"customer": parent_dict.get("party_name")})
|
||||
|
||||
for item in self.get("items"):
|
||||
if item.get("item_code"):
|
||||
args = parent_dict.copy()
|
||||
@@ -344,7 +348,7 @@ class AccountsController(TransactionBase):
|
||||
'fiscal_year': fiscal_year,
|
||||
'voucher_type': self.doctype,
|
||||
'voucher_no': self.name,
|
||||
'remarks': self.get("remarks"),
|
||||
'remarks': self.get("remarks") or self.get("remark"),
|
||||
'debit': 0,
|
||||
'credit': 0,
|
||||
'debit_in_account_currency': 0,
|
||||
@@ -743,7 +747,12 @@ class AccountsController(TransactionBase):
|
||||
count += 1
|
||||
item.qty = group_item_qty[item.item_code]
|
||||
item.amount = group_item_amount[item.item_code]
|
||||
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
|
||||
|
||||
if item.qty:
|
||||
item.rate = flt(flt(item.amount) / flt(item.qty), item.precision("rate"))
|
||||
else:
|
||||
item.rate = 0
|
||||
|
||||
item.idx = count
|
||||
del group_item_qty[item.item_code]
|
||||
else:
|
||||
|
||||
@@ -428,8 +428,9 @@ class BuyingController(StockController):
|
||||
elif not flt(d.rejected_qty):
|
||||
d.rejected_qty = flt(d.received_qty) - flt(d.qty)
|
||||
|
||||
val = flt(d.qty) + flt(d.rejected_qty)
|
||||
# Check Received Qty = Accepted Qty + Rejected Qty
|
||||
if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)):
|
||||
if (flt(val, d.precision("received_qty")) != flt(d.received_qty, d.precision("received_qty"))):
|
||||
frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code))
|
||||
|
||||
def validate_negative_quantity(self, item_row, field_list):
|
||||
|
||||
@@ -288,14 +288,18 @@ def copy_attributes_to_variant(item, variant):
|
||||
|
||||
variant.variant_of = item.name
|
||||
|
||||
if not variant.description:
|
||||
variant.description = ""
|
||||
|
||||
if 'description' not in allow_fields:
|
||||
if item.variant_based_on == 'Item Attribute' and not variant.description:
|
||||
variant.description = "<div><b>" + item.name + "</b></div>"
|
||||
for d in variant.attributes:
|
||||
variant.description += "<div><b>" + d.attribute + "</b>: " + cstr(d.attribute_value) + "</div>"
|
||||
if not variant.description:
|
||||
variant.description = ""
|
||||
|
||||
if item.variant_based_on=='Item Attribute':
|
||||
if variant.attributes:
|
||||
attributes_description = item.description + " "
|
||||
for d in variant.attributes:
|
||||
attributes_description += "<div>" + d.attribute + ": " + cstr(d.attribute_value) + "</div>"
|
||||
|
||||
if attributes_description not in variant.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"""
|
||||
|
||||
@@ -27,7 +27,7 @@ status_map = {
|
||||
],
|
||||
"Quotation": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
["Open", "eval:self.docstatus==1"],
|
||||
["Lost", "eval:self.status=='Lost'"],
|
||||
["Ordered", "has_sales_order"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
@@ -45,9 +45,9 @@ status_map = {
|
||||
"Sales Invoice": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
|
||||
["Return", "eval:self.is_return==1 and self.docstatus==1"],
|
||||
["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
|
||||
["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
|
||||
["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
|
||||
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
|
||||
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
@@ -55,9 +55,9 @@ status_map = {
|
||||
"Purchase Invoice": [
|
||||
["Draft", None],
|
||||
["Submitted", "eval:self.docstatus==1"],
|
||||
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"],
|
||||
["Return", "eval:self.is_return==1 and self.docstatus==1"],
|
||||
["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
|
||||
["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
|
||||
["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
|
||||
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
|
||||
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
|
||||
["Cancelled", "eval:self.docstatus==2"],
|
||||
@@ -316,19 +316,27 @@ class StatusUpdater(Document):
|
||||
.format(frappe.db.escape(frappe.session.user))
|
||||
|
||||
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
|
||||
ref_fieldname = ref_dt.lower().replace(" ", "_")
|
||||
zero_amount_refdoc = []
|
||||
all_zero_amount_refdoc = frappe.db.sql_list("""select name from `tab%s`
|
||||
where docstatus=1 and base_net_total = 0""" % ref_dt)
|
||||
ref_fieldname = frappe.scrub(ref_dt)
|
||||
|
||||
for item in self.get("items"):
|
||||
if item.get(ref_fieldname) \
|
||||
and item.get(ref_fieldname) in all_zero_amount_refdoc \
|
||||
and item.get(ref_fieldname) not in zero_amount_refdoc:
|
||||
zero_amount_refdoc.append(item.get(ref_fieldname))
|
||||
ref_docs = [item.get(ref_fieldname) for item in (self.get('items') or []) if item.get(ref_fieldname)]
|
||||
if not ref_docs:
|
||||
return
|
||||
|
||||
if zero_amount_refdoc:
|
||||
self.update_billing_status(zero_amount_refdoc, ref_dt, ref_fieldname)
|
||||
zero_amount_refdocs = frappe.db.sql_list("""
|
||||
SELECT
|
||||
name
|
||||
from
|
||||
`tab{ref_dt}`
|
||||
where
|
||||
docstatus = 1
|
||||
and base_net_total = 0
|
||||
and name in %(ref_docs)s
|
||||
""".format(ref_dt=ref_dt), {
|
||||
'ref_docs': ref_docs
|
||||
})
|
||||
|
||||
if zero_amount_refdocs:
|
||||
self.update_billing_status(zero_amount_refdocs, ref_dt, ref_fieldname)
|
||||
|
||||
def update_billing_status(self, zero_amount_refdoc, ref_dt, ref_fieldname):
|
||||
for ref_dn in zero_amount_refdoc:
|
||||
|
||||
@@ -80,7 +80,7 @@ class StockController(AccountsController):
|
||||
"cost_center": item_row.cost_center,
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"debit": flt(sle.stock_value_difference, 2),
|
||||
"is_opening": item_row.get("is_opening"),
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||
}, warehouse_account[sle.warehouse]["account_currency"]))
|
||||
|
||||
# to target warehouse / expense account
|
||||
@@ -91,7 +91,7 @@ class StockController(AccountsController):
|
||||
"remarks": self.get("remarks") or "Accounting Entry for Stock",
|
||||
"credit": flt(sle.stock_value_difference, 2),
|
||||
"project": item_row.get("project") or self.get("project"),
|
||||
"is_opening": item_row.get("is_opening")
|
||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No"
|
||||
}))
|
||||
elif sle.warehouse not in warehouse_with_no_account:
|
||||
warehouse_with_no_account.append(sle.warehouse)
|
||||
|
||||
@@ -390,7 +390,7 @@ class calculate_taxes_and_totals(object):
|
||||
net_total += item.net_amount
|
||||
|
||||
# discount amount rounding loss adjustment if no taxes
|
||||
if (not taxes or self.doc.apply_discount_on == "Net Total") \
|
||||
if (self.doc.apply_discount_on == "Net Total" or not taxes or total_for_discount_amount==self.doc.net_total) \
|
||||
and i == len(self.doc.get("items")) - 1:
|
||||
discount_amount_loss = flt(self.doc.net_total - net_total - self.doc.discount_amount,
|
||||
self.doc.precision("net_total"))
|
||||
|
||||
@@ -6,6 +6,18 @@ cur_frm.email_field = "email_id";
|
||||
|
||||
erpnext.LeadController = frappe.ui.form.Controller.extend({
|
||||
setup: function () {
|
||||
|
||||
this.frm.make_methods = {
|
||||
'Quotation': () => erpnext.utils.create_new_doc('Quotation', {
|
||||
'quotation_to': this.frm.doc.doctype,
|
||||
'party_name': this.frm.doc.name
|
||||
}),
|
||||
'Opportunity': () => erpnext.utils.create_new_doc('Opportunity', {
|
||||
'opportunity_from': this.frm.doc.doctype,
|
||||
'party_name': this.frm.doc.name
|
||||
})
|
||||
}
|
||||
|
||||
this.frm.fields_dict.customer.get_query = function (doc, cdt, cdn) {
|
||||
return { query: "erpnext.controllers.queries.customer_query" }
|
||||
}
|
||||
|
||||
@@ -150,8 +150,8 @@ def make_opportunity(source_name, target_doc=None):
|
||||
"doctype": "Opportunity",
|
||||
"field_map": {
|
||||
"campaign_name": "campaign",
|
||||
"doctype": "enquiry_from",
|
||||
"name": "lead",
|
||||
"doctype": "opportunity_from",
|
||||
"name": "party_name",
|
||||
"lead_name": "contact_display",
|
||||
"company_name": "customer_name",
|
||||
"email_id": "contact_email",
|
||||
|
||||
@@ -11,7 +11,7 @@ def execute(filters=None):
|
||||
columns=get_columns("Campaign Name")
|
||||
data=get_lead_data(filters or {}, "Campaign Name")
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns(based_on):
|
||||
return [
|
||||
{
|
||||
@@ -69,21 +69,21 @@ def get_columns(based_on):
|
||||
"width": 100
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def get_lead_data(filters, based_on):
|
||||
based_on_field = frappe.scrub(based_on)
|
||||
conditions = get_filter_conditions(filters)
|
||||
|
||||
|
||||
lead_details = frappe.db.sql("""
|
||||
select {based_on_field}, name
|
||||
from `tabLead`
|
||||
where {based_on_field} is not null and {based_on_field} != '' {conditions}
|
||||
from `tabLead`
|
||||
where {based_on_field} is not null and {based_on_field} != '' {conditions}
|
||||
""".format(based_on_field=based_on_field, conditions=conditions), filters, as_dict=1)
|
||||
|
||||
|
||||
lead_map = frappe._dict()
|
||||
for d in lead_details:
|
||||
lead_map.setdefault(d.get(based_on_field), []).append(d.name)
|
||||
|
||||
|
||||
data = []
|
||||
for based_on_value, leads in lead_map.items():
|
||||
row = {
|
||||
@@ -94,42 +94,42 @@ def get_lead_data(filters, based_on):
|
||||
row["opp_count"] = get_lead_opp_count(leads)
|
||||
row["order_count"] = get_quotation_ordered_count(leads)
|
||||
row["order_value"] = get_order_amount(leads) or 0
|
||||
|
||||
|
||||
row["opp_lead"] = flt(row["opp_count"]) / flt(row["lead_count"] or 1.0) * 100.0
|
||||
row["quot_lead"] = flt(row["quot_count"]) / flt(row["lead_count"] or 1.0) * 100.0
|
||||
|
||||
|
||||
row["order_quot"] = flt(row["order_count"]) / flt(row["quot_count"] or 1.0) * 100.0
|
||||
|
||||
|
||||
data.append(row)
|
||||
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_filter_conditions(filters):
|
||||
conditions=""
|
||||
if filters.from_date:
|
||||
conditions += " and date(creation) >= %(from_date)s"
|
||||
if filters.to_date:
|
||||
conditions += " and date(creation) <= %(to_date)s"
|
||||
|
||||
|
||||
return conditions
|
||||
|
||||
|
||||
def get_lead_quotation_count(leads):
|
||||
return frappe.db.sql("""select count(name) from `tabQuotation`
|
||||
where lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
|
||||
|
||||
return frappe.db.sql("""select count(name) from `tabQuotation`
|
||||
where quotation_to = 'Lead' and party_name in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0] #nosec
|
||||
|
||||
def get_lead_opp_count(leads):
|
||||
return frappe.db.sql("""select count(name) from `tabOpportunity`
|
||||
where lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
|
||||
|
||||
return frappe.db.sql("""select count(name) from `tabOpportunity`
|
||||
where opportunity_from = 'Lead' and party_name in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
|
||||
|
||||
def get_quotation_ordered_count(leads):
|
||||
return frappe.db.sql("""select count(name)
|
||||
from `tabQuotation` where status = 'Ordered'
|
||||
and lead in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
|
||||
|
||||
return frappe.db.sql("""select count(name)
|
||||
from `tabQuotation` where status = 'Ordered' and quotation_to = 'Lead'
|
||||
and party_name in (%s)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
|
||||
|
||||
def get_order_amount(leads):
|
||||
return frappe.db.sql("""select sum(base_net_amount)
|
||||
return frappe.db.sql("""select sum(base_net_amount)
|
||||
from `tabSales Order Item`
|
||||
where prevdoc_docname in (
|
||||
select name from `tabQuotation` where status = 'Ordered'
|
||||
and lead in (%s)
|
||||
select name from `tabQuotation` where status = 'Ordered'
|
||||
and quotation_to = 'Lead' and party_name in (%s)
|
||||
)""" % ', '.join(["%s"]*len(leads)), tuple(leads))[0][0]
|
||||
@@ -11,16 +11,61 @@ def execute(filters=None):
|
||||
columns=get_columns()
|
||||
data=get_lead_data(filters, "Lead Owner")
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
_("Lead Owner") + ":Data:130",
|
||||
_("Lead Count") + ":Int:80",
|
||||
_("Opp Count") + ":Int:80",
|
||||
_("Quot Count") + ":Int:80",
|
||||
_("Order Count") + ":Int:100",
|
||||
_("Order Value") + ":Float:100",
|
||||
_("Opp/Lead %") + ":Float:100",
|
||||
_("Quot/Lead %") + ":Float:100",
|
||||
_("Order/Quot %") + ":Float:100"
|
||||
{
|
||||
"fieldname": "lead_owner",
|
||||
"label": _("Lead Owner"),
|
||||
"fieldtype": "Data",
|
||||
"width": "130"
|
||||
},
|
||||
{
|
||||
"fieldname": "lead_count",
|
||||
"label": _("Lead Count"),
|
||||
"fieldtype": "Int",
|
||||
"width": "80"
|
||||
},
|
||||
{
|
||||
"fieldname": "opp_count",
|
||||
"label": _("Opp Count"),
|
||||
"fieldtype": "Int",
|
||||
"width": "80"
|
||||
},
|
||||
{
|
||||
"fieldname": "quot_count",
|
||||
"label": _("Quot Count"),
|
||||
"fieldtype": "Int",
|
||||
"width": "80"
|
||||
},
|
||||
{
|
||||
"fieldname": "order_count",
|
||||
"label": _("Order Count"),
|
||||
"fieldtype": "Int",
|
||||
"width": "100"
|
||||
},
|
||||
{
|
||||
"fieldname": "order_value",
|
||||
"label": _("Order Value"),
|
||||
"fieldtype": "Float",
|
||||
"width": "100"
|
||||
},
|
||||
{
|
||||
"fieldname": "opp_lead",
|
||||
"label": _("Opp/Lead %"),
|
||||
"fieldtype": "Float",
|
||||
"width": "100"
|
||||
},
|
||||
{
|
||||
"fieldname": "quot_lead",
|
||||
"label": _("Quot/Lead %"),
|
||||
"fieldtype": "Float",
|
||||
"width": "100"
|
||||
},
|
||||
{
|
||||
"fieldname": "order_quot",
|
||||
"label": _("Order/Quot %"),
|
||||
"fieldtype": "Float",
|
||||
"width": "100"
|
||||
}
|
||||
]
|
||||
@@ -35,14 +35,14 @@ def get_data(filters):
|
||||
|
||||
for lead in frappe.get_all('Lead', fields = ['name', 'lead_name', 'company_name'], filters=lead_filters):
|
||||
data = frappe.db.sql("""
|
||||
select
|
||||
`tabCommunication`.reference_doctype, `tabCommunication`.reference_name,
|
||||
select
|
||||
`tabCommunication`.reference_doctype, `tabCommunication`.reference_name,
|
||||
`tabCommunication`.content, `tabCommunication`.communication_date
|
||||
from
|
||||
from
|
||||
(
|
||||
(select name, lead from `tabOpportunity` where lead = %(lead)s)
|
||||
union
|
||||
(select name, lead from `tabQuotation` where lead = %(lead)s)
|
||||
(select name, party_name as lead from `tabOpportunity` where opportunity_from='Lead' and party_name = %(lead)s)
|
||||
union
|
||||
(select name, party_name as lead from `tabQuotation` where quotation_to = 'Lead' and party_name = %(lead)s)
|
||||
union
|
||||
(select name, lead from `tabIssue` where lead = %(lead)s and status!='Closed')
|
||||
union
|
||||
|
||||
@@ -22,7 +22,16 @@ def verify_request():
|
||||
frappe.set_user(woocommerce_settings.creation_user)
|
||||
|
||||
@frappe.whitelist(allow_guest=True)
|
||||
def order():
|
||||
def order(*args, **kwargs):
|
||||
try:
|
||||
_order(*args, **kwargs)
|
||||
except Exception:
|
||||
error_message = frappe.get_traceback()+"\n\n Request Data: \n"+json.loads(frappe.request.data).__str__()
|
||||
frappe.log_error(error_message, "WooCommerce Error")
|
||||
raise
|
||||
|
||||
|
||||
def _order(*args, **kwargs):
|
||||
woocommerce_settings = frappe.get_doc("Woocommerce Settings")
|
||||
if frappe.flags.woocomm_test_order_data:
|
||||
fd = frappe.flags.woocomm_test_order_data
|
||||
|
||||
@@ -40,7 +40,7 @@ def get_products_details():
|
||||
products_response = call_mws_method(products.get_matching_product,marketplaceid=marketplace,
|
||||
asins=asin_list)
|
||||
|
||||
matching_products_list = products_response.parsed
|
||||
matching_products_list = products_response.parsed
|
||||
for product in matching_products_list:
|
||||
skus = [row["sku"] for row in sku_asin if row["asin"]==product.ASIN]
|
||||
for sku in skus:
|
||||
@@ -116,7 +116,7 @@ def call_mws_method(mws_method, *args, **kwargs):
|
||||
mws_settings = frappe.get_doc("Amazon MWS Settings")
|
||||
max_retries = mws_settings.max_retry_limit
|
||||
|
||||
for x in xrange(0, max_retries):
|
||||
for x in range(0, max_retries):
|
||||
try:
|
||||
response = mws_method(*args, **kwargs)
|
||||
return response
|
||||
|
||||
@@ -107,10 +107,18 @@ def get_series():
|
||||
|
||||
def setup_custom_fields():
|
||||
custom_fields = {
|
||||
"Customer": [dict(fieldname='shopify_customer_id', label='Shopify Customer Id',
|
||||
fieldtype='Data', insert_after='series', read_only=1, print_hide=1)],
|
||||
"Address": [dict(fieldname='shopify_address_id', label='Shopify Address Id',
|
||||
fieldtype='Data', insert_after='fax', read_only=1, print_hide=1)],
|
||||
"Customer": [
|
||||
dict(fieldname='shopify_customer_id', label='Shopify Customer Id',
|
||||
fieldtype='Data', insert_after='series', read_only=1, print_hide=1)
|
||||
],
|
||||
"Supplier": [
|
||||
dict(fieldname='shopify_supplier_id', label='Shopify Supplier Id',
|
||||
fieldtype='Data', insert_after='supplier_name', read_only=1, print_hide=1)
|
||||
],
|
||||
"Address": [
|
||||
dict(fieldname='shopify_address_id', label='Shopify Address Id',
|
||||
fieldtype='Data', insert_after='fax', read_only=1, print_hide=1)
|
||||
],
|
||||
"Item": [
|
||||
dict(fieldname='shopify_variant_id', label='Shopify Variant Id',
|
||||
fieldtype='Data', insert_after='item_code', read_only=1, print_hide=1),
|
||||
@@ -119,16 +127,20 @@ def setup_custom_fields():
|
||||
dict(fieldname='shopify_description', label='Shopify Description',
|
||||
fieldtype='Text Editor', insert_after='description', read_only=1, print_hide=1)
|
||||
],
|
||||
"Sales Order": [dict(fieldname='shopify_order_id', label='Shopify Order Id',
|
||||
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)],
|
||||
"Sales Order": [
|
||||
dict(fieldname='shopify_order_id', label='Shopify Order Id',
|
||||
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
|
||||
],
|
||||
"Delivery Note":[
|
||||
dict(fieldname='shopify_order_id', label='Shopify Order Id',
|
||||
fieldtype='Data', insert_after='title', read_only=1, print_hide=1),
|
||||
dict(fieldname='shopify_fulfillment_id', label='Shopify Fulfillment Id',
|
||||
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
|
||||
],
|
||||
"Sales Invoice": [dict(fieldname='shopify_order_id', label='Shopify Order Id',
|
||||
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)]
|
||||
"Sales Invoice": [
|
||||
dict(fieldname='shopify_order_id', label='Shopify Order Id',
|
||||
fieldtype='Data', insert_after='title', read_only=1, print_hide=1)
|
||||
]
|
||||
}
|
||||
|
||||
create_custom_fields(custom_fields)
|
||||
|
||||
@@ -300,11 +300,15 @@ def insert_lab_test_to_medical_record(doc):
|
||||
|
||||
elif doc.special_test_items:
|
||||
item = doc.special_test_items[0]
|
||||
table_row = item.lab_test_particulars +" "+ item.result_value
|
||||
|
||||
if item.lab_test_particulars and item.result_value:
|
||||
table_row = item.lab_test_particulars +" "+ item.result_value
|
||||
|
||||
elif doc.sensitivity_test_items:
|
||||
item = doc.sensitivity_test_items[0]
|
||||
table_row = item.antibiotic +" "+ item.antibiotic_sensitivity
|
||||
|
||||
if item.antibiotic and item.antibiotic_sensitivity:
|
||||
table_row = item.antibiotic +" "+ item.antibiotic_sensitivity
|
||||
|
||||
if table_row:
|
||||
subject += "<br/>"+table_row
|
||||
|
||||
@@ -13,8 +13,6 @@ source_link = "https://github.com/frappe/erpnext"
|
||||
|
||||
develop_version = '12.x.x-develop'
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
||||
app_include_js = "assets/js/erpnext.min.js"
|
||||
app_include_css = "assets/css/erpnext.css"
|
||||
web_include_js = "assets/js/erpnext-web.min.js"
|
||||
@@ -44,7 +42,7 @@ update_and_get_user_progress = "erpnext.utilities.user_progress_utils.update_def
|
||||
on_session_creation = "erpnext.shopping_cart.utils.set_cart_count"
|
||||
on_logout = "erpnext.shopping_cart.utils.clear_cart_count"
|
||||
|
||||
treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group']
|
||||
treeviews = ['Account', 'Cost Center', 'Warehouse', 'Item Group', 'Customer Group', 'Sales Person', 'Territory', 'Assessment Group', 'Department']
|
||||
|
||||
# website
|
||||
update_website_context = "erpnext.shopping_cart.utils.update_website_context"
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// For license information, please see license.txt
|
||||
frappe.views.calendar["Attendance"] = {
|
||||
field_map: {
|
||||
"start": "date",
|
||||
"end": "date",
|
||||
"start": "attendance_date",
|
||||
"end": "attendance_date",
|
||||
"id": "name",
|
||||
"docstatus": 1
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
frappe.ui.form.on('Department', {
|
||||
refresh: function(frm) {
|
||||
// read-only for root department
|
||||
if(!frm.doc.parent_department) {
|
||||
if(!frm.doc.parent_department && !frm.is_new()) {
|
||||
frm.set_read_only();
|
||||
frm.set_intro(__("This is a root department and cannot be edited."));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
@@ -19,6 +20,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "department_name",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
@@ -52,6 +54,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "parent_department",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -85,6 +88,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -118,6 +122,7 @@
|
||||
"bold": 1,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "is_group",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -150,6 +155,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
@@ -182,6 +188,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -214,6 +221,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "Days for which Holidays are blocked for this department.",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "leave_block_list",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
@@ -246,6 +254,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "leave_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -279,6 +288,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "The first Leave Approver in the list will be set as the default Leave Approver.",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "leave_approvers",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@@ -312,6 +322,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "expense_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
@@ -345,6 +356,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "The first Expense Approver in the list will be set as the default Expense Approver.",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "expense_approvers",
|
||||
"fieldtype": "Table",
|
||||
"hidden": 0,
|
||||
@@ -378,6 +390,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "lft",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
@@ -410,6 +423,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "rgt",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 1,
|
||||
@@ -442,6 +456,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "old_parent",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
@@ -479,7 +494,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-08-29 06:26:12.995703",
|
||||
"modified": "2019-06-25 18:43:05.550387",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Department",
|
||||
@@ -543,7 +558,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 1,
|
||||
|
||||
@@ -2,9 +2,8 @@ frappe.ui.form.on("Employee Attendance Tool", {
|
||||
refresh: function(frm) {
|
||||
frm.disable_save();
|
||||
},
|
||||
|
||||
|
||||
onload: function(frm) {
|
||||
frm.doc.department = frm.doc.branch = frm.doc.company = "All";
|
||||
frm.set_value("date", frappe.datetime.get_today());
|
||||
erpnext.employee_attendance_tool.load_employees(frm);
|
||||
},
|
||||
@@ -24,7 +23,7 @@ frappe.ui.form.on("Employee Attendance Tool", {
|
||||
company: function(frm) {
|
||||
erpnext.employee_attendance_tool.load_employees(frm);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -17,12 +17,11 @@ def get_employees(date, department = None, branch = None, company = None):
|
||||
attendance_not_marked = []
|
||||
attendance_marked = []
|
||||
filters = {"status": "Active", "date_of_joining": ["<=", date]}
|
||||
if department != "All":
|
||||
filters["department"] = department
|
||||
if branch != "All":
|
||||
filters["branch"] = branch
|
||||
if company != "All":
|
||||
filters["company"] = company
|
||||
|
||||
for field, value in {'department': department,
|
||||
'branch': branch, 'company': company}.items():
|
||||
if value:
|
||||
filters[field] = value
|
||||
|
||||
employee_list = frappe.get_list("Employee", fields=["employee", "employee_name"], filters=filters, order_by="employee_name")
|
||||
marked_employee = {}
|
||||
|
||||
@@ -2,20 +2,8 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Employee Benefit Application', {
|
||||
setup: function(frm) {
|
||||
if(!frm.doc.employee || !frm.doc.date) {
|
||||
frappe.throw(__("Please select Employee and Date first"));
|
||||
} else {
|
||||
frm.set_query("earning_component", "employee_benefits", function() {
|
||||
return {
|
||||
query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components",
|
||||
filters: {date: frm.doc.date, employee: frm.doc.employee}
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
employee: function(frm) {
|
||||
frm.trigger('set_earning_component');
|
||||
var method, args;
|
||||
if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
|
||||
method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining";
|
||||
@@ -35,6 +23,21 @@ frappe.ui.form.on('Employee Benefit Application', {
|
||||
get_max_benefits(frm, method, args);
|
||||
}
|
||||
},
|
||||
|
||||
date: function(frm) {
|
||||
frm.trigger('set_earning_component');
|
||||
},
|
||||
|
||||
set_earning_component: function(frm) {
|
||||
if(!frm.doc.employee && !frm.doc.date) return;
|
||||
frm.set_query("earning_component", "employee_benefits", function() {
|
||||
return {
|
||||
query : "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_earning_components",
|
||||
filters: {date: frm.doc.date, employee: frm.doc.employee}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
payroll_period: function(frm) {
|
||||
var method, args;
|
||||
if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){
|
||||
|
||||
@@ -219,7 +219,8 @@ frappe.ui.form.on("Expense Claim", {
|
||||
frm.fields_dict["cost_center"].get_query = function() {
|
||||
return {
|
||||
filters: {
|
||||
"company": frm.doc.company
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -230,7 +231,9 @@ frappe.ui.form.on("Expense Claim", {
|
||||
return {
|
||||
filters: {
|
||||
"report_type": "Balance Sheet",
|
||||
"account_type": "Payable"
|
||||
"account_type": "Payable",
|
||||
"company": frm.doc.company,
|
||||
"is_group": 0
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,10 +4,17 @@ from frappe import _
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'reference_name',
|
||||
'internal_links': {
|
||||
'Employee Advance': ['advances', 'employee_advance']
|
||||
},
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Payment'),
|
||||
'items': ['Payment Entry']
|
||||
'items': ['Payment Entry', 'Journal Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Reference'),
|
||||
'items': ['Employee Advance']
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -79,6 +79,7 @@ def get_events(start, end, filters=None):
|
||||
filters.append(['Holiday', 'holiday_date', '>', getdate(start)])
|
||||
if end:
|
||||
filters.append(['Holiday', 'holiday_date', '<', getdate(end)])
|
||||
|
||||
return frappe.get_list('Holiday List',
|
||||
fields=['name', '`tabHoliday`.holiday_date', '`tabHoliday`.description', '`tabHoliday List`.color'],
|
||||
filters = filters,
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
frappe.views.calendar["Holiday List"] = {
|
||||
field_map: {
|
||||
"start": "from_date",
|
||||
"end": "to_date",
|
||||
"start": "holiday_date",
|
||||
"end": "holiday_date",
|
||||
"id": "name",
|
||||
"title": "description",
|
||||
"allDay": "allDay"
|
||||
|
||||
@@ -25,5 +25,13 @@ frappe.ui.form.on("Job Applicant", {
|
||||
}
|
||||
}
|
||||
|
||||
frm.set_query("job_title", function() {
|
||||
return {
|
||||
filters: {
|
||||
'status': 'Open'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
@@ -122,11 +122,42 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.type == \"Earning\"",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "is_tax_applicable",
|
||||
"fieldtype": "Check",
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "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": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@@ -134,7 +165,6 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Is Tax Applicable",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@@ -225,8 +255,10 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"depends_on": "eval:doc.type == \"Earning\"",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "do_not_include_in_total",
|
||||
"fieldname": "is_tax_applicable",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@@ -235,7 +267,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Do not include in total",
|
||||
"label": "Is Tax Applicable",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@@ -258,6 +290,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "is_tax_applicable",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "deduct_full_tax_on_selected_payroll_date",
|
||||
"fieldtype": "Check",
|
||||
@@ -292,39 +325,7 @@
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldname": "round_to_the_nearest_integer",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@@ -333,40 +334,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Disabled",
|
||||
"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": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"label": "Round to the Nearest Integer",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@@ -416,6 +384,72 @@
|
||||
"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": "do_not_include_in_total",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Do Not Include in Total",
|
||||
"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": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Disabled",
|
||||
"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,
|
||||
@@ -854,6 +888,40 @@
|
||||
"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": "eval:doc.amount_based_on_formula!==1",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Amount",
|
||||
"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,
|
||||
@@ -895,7 +963,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.amount_based_on_formula!==0",
|
||||
"depends_on": "amount_based_on_formula",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "formula",
|
||||
"fieldtype": "Code",
|
||||
@@ -922,40 +990,6 @@
|
||||
"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": "eval:doc.amount_based_on_formula!==1",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
"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": "Amount",
|
||||
"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,
|
||||
@@ -1034,7 +1068,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-05-13 12:55:55.424370",
|
||||
"modified": "2019-06-05 11:19:15.926608",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Salary Component",
|
||||
|
||||
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe, erpnext
|
||||
import datetime, math
|
||||
|
||||
from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words, getdate
|
||||
from frappe.utils import add_days, cint, cstr, flt, getdate, rounded, date_diff, money_in_words
|
||||
from frappe.model.naming import make_autoname
|
||||
|
||||
from frappe import msgprint, _
|
||||
@@ -119,7 +119,7 @@ class SalarySlip(TransactionBase):
|
||||
if not self.salary_slip_based_on_timesheet:
|
||||
self.get_date_details()
|
||||
self.validate_dates()
|
||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
self.get_leave_details(joining_date, relieving_date)
|
||||
@@ -183,7 +183,7 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
def get_leave_details(self, joining_date=None, relieving_date=None, lwp=None, for_preview=0):
|
||||
if not joining_date:
|
||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
working_days = date_diff(self.end_date, self.start_date) + 1
|
||||
@@ -297,9 +297,6 @@ class SalarySlip(TransactionBase):
|
||||
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
|
||||
self.rounded_total = rounded(self.net_pay)
|
||||
|
||||
if self.net_pay < 0:
|
||||
frappe.throw(_("Net Pay cannnot be negative"))
|
||||
|
||||
def calculate_component_amounts(self):
|
||||
if not getattr(self, '_salary_structure_doc', None):
|
||||
self._salary_structure_doc = frappe.get_doc('Salary Structure', self.salary_structure)
|
||||
@@ -310,6 +307,7 @@ class SalarySlip(TransactionBase):
|
||||
self.add_employee_benefits(payroll_period)
|
||||
self.add_additional_salary_components()
|
||||
self.add_tax_components(payroll_period)
|
||||
self.set_component_amounts_based_on_payment_days()
|
||||
|
||||
def add_structure_components(self):
|
||||
data = self.get_data_for_eval()
|
||||
@@ -401,14 +399,18 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
def add_tax_components(self, payroll_period):
|
||||
# Calculate variable_based_on_taxable_salary after all components updated in salary slip
|
||||
struct_tax_components = [d.salary_component for d in self._salary_structure_doc.get("deductions")
|
||||
if d.variable_based_on_taxable_salary == 1 and not d.formula and not d.amount]
|
||||
tax_components, other_deduction_components = [], []
|
||||
for d in self._salary_structure_doc.get("deductions"):
|
||||
if d.variable_based_on_taxable_salary == 1 and not d.formula and not flt(d.amount):
|
||||
tax_components.append(d.salary_component)
|
||||
else:
|
||||
other_deduction_components.append(d.salary_component)
|
||||
|
||||
if not struct_tax_components:
|
||||
struct_tax_components = [d.name for d in
|
||||
frappe.get_all("Salary Component", filters={"variable_based_on_taxable_salary": 1})]
|
||||
if not tax_components:
|
||||
tax_components = [d.name for d in frappe.get_all("Salary Component", filters={"variable_based_on_taxable_salary": 1})
|
||||
if d.name not in other_deduction_components]
|
||||
|
||||
for d in struct_tax_components:
|
||||
for d in tax_components:
|
||||
tax_amount = self.calculate_variable_based_on_taxable_salary(d, payroll_period)
|
||||
tax_row = self.get_salary_slip_row(d)
|
||||
self.update_component_row(tax_row, tax_amount, "deductions")
|
||||
@@ -441,8 +443,10 @@ class SalarySlip(TransactionBase):
|
||||
else:
|
||||
component_row.additional_amount = amount
|
||||
|
||||
if not overwrite:
|
||||
if not overwrite and component_row.default_amount:
|
||||
amount += component_row.default_amount
|
||||
else:
|
||||
component_row.default_amount = amount
|
||||
|
||||
component_row.amount = amount
|
||||
component_row.deduct_full_tax_on_selected_payroll_date = struct_row.deduct_full_tax_on_selected_payroll_date
|
||||
@@ -474,8 +478,7 @@ class SalarySlip(TransactionBase):
|
||||
future_structured_taxable_earnings = current_taxable_earnings.taxable_earnings * (math.ceil(remaining_sub_periods) - 1)
|
||||
|
||||
# get taxable_earnings, addition_earnings for current actual payment days
|
||||
self.set_component_amounts_based_on_payment_days()
|
||||
current_taxable_earnings_for_payment_days = self.get_taxable_earnings()
|
||||
current_taxable_earnings_for_payment_days = self.get_taxable_earnings(based_on_payment_days=1)
|
||||
current_structured_taxable_earnings = current_taxable_earnings_for_payment_days.taxable_earnings
|
||||
current_additional_earnings = current_taxable_earnings_for_payment_days.additional_income
|
||||
current_additional_earnings_with_full_tax = current_taxable_earnings_for_payment_days.additional_income_with_full_tax
|
||||
@@ -498,7 +501,6 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
# Structured tax amount
|
||||
total_structured_tax_amount = self.calculate_tax_by_tax_slab(payroll_period, total_taxable_earnings_without_full_tax_addl_components)
|
||||
|
||||
current_structured_tax_amount = (total_structured_tax_amount - previous_total_paid_taxes) / remaining_sub_periods
|
||||
|
||||
# Total taxable earnings with additional earnings with full tax
|
||||
@@ -557,25 +559,39 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
return total_tax_paid
|
||||
|
||||
def get_taxable_earnings(self, only_flexi=0):
|
||||
def get_taxable_earnings(self, based_on_payment_days=0):
|
||||
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
if not relieving_date:
|
||||
relieving_date = getdate(self.end_date)
|
||||
|
||||
if not joining_date:
|
||||
frappe.throw(_("Please set the Date Of Joining for employee {0}").format(frappe.bold(self.employee_name)))
|
||||
|
||||
taxable_earnings = 0
|
||||
additional_income = 0
|
||||
additional_income_with_full_tax = 0
|
||||
flexi_benefits = 0
|
||||
|
||||
for earning in self.earnings:
|
||||
if based_on_payment_days:
|
||||
amount, additional_amount = self.get_amount_based_on_payment_days(earning, joining_date, relieving_date)
|
||||
else:
|
||||
amount, additional_amount = earning.amount, earning.additional_amount
|
||||
|
||||
if earning.is_tax_applicable:
|
||||
if flt(earning.additional_amount):
|
||||
taxable_earnings += (earning.amount - earning.additional_amount)
|
||||
additional_income += earning.additional_amount
|
||||
if additional_amount:
|
||||
taxable_earnings += (amount - additional_amount)
|
||||
additional_income += additional_amount
|
||||
if earning.deduct_full_tax_on_selected_payroll_date:
|
||||
additional_income_with_full_tax += earning.additional_amount
|
||||
additional_income_with_full_tax += additional_amount
|
||||
continue
|
||||
|
||||
if earning.is_flexible_benefit:
|
||||
flexi_benefits += earning.amount
|
||||
flexi_benefits += amount
|
||||
else:
|
||||
taxable_earnings += earning.amount
|
||||
taxable_earnings += amount
|
||||
|
||||
return frappe._dict({
|
||||
"taxable_earnings": taxable_earnings,
|
||||
@@ -584,6 +600,30 @@ class SalarySlip(TransactionBase):
|
||||
"flexi_benefits": flexi_benefits
|
||||
})
|
||||
|
||||
def get_amount_based_on_payment_days(self, row, joining_date, relieving_date):
|
||||
amount, additional_amount = row.amount, row.additional_amount
|
||||
if (self.salary_structure and
|
||||
cint(row.depends_on_payment_days) and cint(self.total_working_days) and
|
||||
(not self.salary_slip_based_on_timesheet or
|
||||
getdate(self.start_date) < joining_date or
|
||||
getdate(self.end_date) > relieving_date
|
||||
)):
|
||||
additional_amount = flt((flt(row.additional_amount) * flt(self.payment_days)
|
||||
/ cint(self.total_working_days)), row.precision("additional_amount"))
|
||||
amount = flt((flt(row.default_amount) * flt(self.payment_days)
|
||||
/ cint(self.total_working_days)), row.precision("amount")) + additional_amount
|
||||
|
||||
elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(row.depends_on_payment_days):
|
||||
amount, additional_amount = 0, 0
|
||||
elif not row.amount:
|
||||
amount = row.default_amount + row.additional_amount
|
||||
|
||||
# apply rounding
|
||||
if frappe.get_cached_value("Salary Component", row.salary_component, "round_to_the_nearest_integer"):
|
||||
amount, additional_amount = rounded(amount), rounded(additional_amount)
|
||||
|
||||
return amount, additional_amount
|
||||
|
||||
def calculate_unclaimed_taxable_benefits(self, payroll_period):
|
||||
# get total sum of benefits paid
|
||||
total_benefits_paid = flt(frappe.db.sql("""
|
||||
@@ -685,7 +725,7 @@ class SalarySlip(TransactionBase):
|
||||
return total
|
||||
|
||||
def set_component_amounts_based_on_payment_days(self):
|
||||
joining_date, relieving_date = frappe.db.get_value("Employee", self.employee,
|
||||
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
|
||||
if not relieving_date:
|
||||
@@ -696,22 +736,7 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
for component_type in ("earnings", "deductions"):
|
||||
for d in self.get(component_type):
|
||||
if (self.salary_structure and
|
||||
cint(d.depends_on_payment_days) and cint(self.total_working_days) and
|
||||
(not self.salary_slip_based_on_timesheet or
|
||||
getdate(self.start_date) < joining_date or
|
||||
getdate(self.end_date) > relieving_date
|
||||
)):
|
||||
|
||||
d.amount = flt(
|
||||
(flt(d.default_amount + d.additional_amount) * flt(self.payment_days)
|
||||
/ cint(self.total_working_days))
|
||||
, d.precision("amount"))
|
||||
|
||||
elif not self.payment_days and not self.salary_slip_based_on_timesheet and cint(d.depends_on_payment_days):
|
||||
d.amount = 0
|
||||
elif not d.amount:
|
||||
d.amount = d.default_amount + d.additional_amount
|
||||
d.amount = self.get_amount_based_on_payment_days(d, joining_date, relieving_date)[0]
|
||||
|
||||
def set_loan_repayment(self):
|
||||
self.set('loans', [])
|
||||
|
||||
@@ -211,7 +211,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
tax_paid = get_tax_paid_in_period(employee)
|
||||
|
||||
# total taxable income 586000, 250000 @ 5%, 86000 @ 20% ie. 12500 + 17200
|
||||
annual_tax = 113567.79
|
||||
annual_tax = 113568
|
||||
try:
|
||||
self.assertEqual(tax_paid, annual_tax)
|
||||
except AssertionError:
|
||||
@@ -250,7 +250,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
|
||||
# total taxable income 416000, 166000 @ 5% ie. 8300
|
||||
try:
|
||||
self.assertEqual(tax_paid, 88607.79)
|
||||
self.assertEqual(tax_paid, 88608)
|
||||
except AssertionError:
|
||||
print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
|
||||
raise
|
||||
@@ -265,7 +265,7 @@ class TestSalarySlip(unittest.TestCase):
|
||||
# total taxable income 566000, 250000 @ 5%, 66000 @ 20%, 12500 + 13200
|
||||
tax_paid = get_tax_paid_in_period(employee)
|
||||
try:
|
||||
self.assertEqual(tax_paid, 121211.48)
|
||||
self.assertEqual(tax_paid, 121211)
|
||||
except AssertionError:
|
||||
print("\nSalary Slip - Tax calculation failed on following case\n", data, "\n")
|
||||
raise
|
||||
@@ -442,7 +442,9 @@ def make_deduction_salary_component(setup=False, test_tax=False):
|
||||
"formula": 'base*.1',
|
||||
"type": "Deduction",
|
||||
"amount_based_on_formula": 1,
|
||||
"depends_on_payment_days": 0
|
||||
"depends_on_payment_days": 0,
|
||||
"variable_based_on_taxable_salary": 1,
|
||||
"round_to_the_nearest_integer": 1
|
||||
}
|
||||
]
|
||||
if not test_tax:
|
||||
@@ -452,7 +454,8 @@ def make_deduction_salary_component(setup=False, test_tax=False):
|
||||
"condition": 'employment_type=="Intern"',
|
||||
"formula": 'base*.1',
|
||||
"type": "Deduction",
|
||||
"amount_based_on_formula": 1
|
||||
"amount_based_on_formula": 1,
|
||||
"round_to_the_nearest_integer": 1
|
||||
})
|
||||
if setup or test_tax:
|
||||
make_salary_component(data, test_tax)
|
||||
|
||||
@@ -19,12 +19,12 @@ def execute(filters=None):
|
||||
data = []
|
||||
for ss in salary_slips:
|
||||
row = [ss.name, ss.employee, ss.employee_name, ss.branch, ss.department, ss.designation,
|
||||
ss.company, ss.start_date, ss.end_date, ss.leave_withut_pay, ss.payment_days]
|
||||
ss.company, ss.start_date, ss.end_date, ss.leave_without_pay, ss.payment_days]
|
||||
|
||||
if not ss.branch == None:columns[3] = columns[3].replace('-1','120')
|
||||
if not ss.department == None: columns[4] = columns[4].replace('-1','120')
|
||||
if not ss.designation == None: columns[5] = columns[5].replace('-1','120')
|
||||
if not ss.leave_withut_pay == None: columns[9] = columns[9].replace('-1','130')
|
||||
if not ss.leave_without_pay == None: columns[9] = columns[9].replace('-1','130')
|
||||
|
||||
|
||||
for e in earning_types:
|
||||
@@ -117,4 +117,4 @@ def get_ss_ded_map(salary_slips):
|
||||
ss_ded_map.setdefault(d.parent, frappe._dict()).setdefault(d.salary_component, [])
|
||||
ss_ded_map[d.parent][d.salary_component] = flt(d.amount)
|
||||
|
||||
return ss_ded_map
|
||||
return ss_ded_map
|
||||
|
||||
@@ -90,7 +90,7 @@ class TestBOM(unittest.TestCase):
|
||||
self.assertEqual(bom.base_total_cost, 486000)
|
||||
|
||||
def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self):
|
||||
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependant", 1)
|
||||
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependent", 1)
|
||||
for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)):
|
||||
frappe.db.sql("delete from `tabItem Price` where price_list='_Test Price List' and item_code=%s",
|
||||
item_code)
|
||||
|
||||
@@ -18,21 +18,22 @@ class JobCard(Document):
|
||||
self.total_completed_qty = 0.0
|
||||
self.total_time_in_mins = 0.0
|
||||
|
||||
for d in self.get('time_logs'):
|
||||
if get_datetime(d.from_time) > get_datetime(d.to_time):
|
||||
frappe.throw(_("Row {0}: From time must be less than to time").format(d.idx))
|
||||
if self.get('time_logs'):
|
||||
for d in self.get('time_logs'):
|
||||
if get_datetime(d.from_time) > get_datetime(d.to_time):
|
||||
frappe.throw(_("Row {0}: From time must be less than to time").format(d.idx))
|
||||
|
||||
data = self.get_overlap_for(d)
|
||||
if data:
|
||||
frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}")
|
||||
.format(d.idx, self.name, data.name))
|
||||
data = self.get_overlap_for(d)
|
||||
if data:
|
||||
frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}")
|
||||
.format(d.idx, self.name, data.name))
|
||||
|
||||
if d.from_time and d.to_time:
|
||||
d.time_in_mins = time_diff_in_hours(d.to_time, d.from_time) * 60
|
||||
self.total_time_in_mins += d.time_in_mins
|
||||
if d.from_time and d.to_time:
|
||||
d.time_in_mins = time_diff_in_hours(d.to_time, d.from_time) * 60
|
||||
self.total_time_in_mins += d.time_in_mins
|
||||
|
||||
if d.completed_qty:
|
||||
self.total_completed_qty += d.completed_qty
|
||||
if d.completed_qty:
|
||||
self.total_completed_qty += d.completed_qty
|
||||
|
||||
def get_overlap_for(self, args):
|
||||
existing = frappe.db.sql("""select jc.name as name from
|
||||
@@ -112,8 +113,10 @@ class JobCard(Document):
|
||||
for_quantity += doc.total_completed_qty
|
||||
time_in_mins += doc.total_time_in_mins
|
||||
for time_log in doc.time_logs:
|
||||
from_time_list.append(time_log.from_time)
|
||||
to_time_list.append(time_log.to_time)
|
||||
if time_log.from_time:
|
||||
from_time_list.append(time_log.from_time)
|
||||
if time_log.to_time:
|
||||
to_time_list.append(time_log.to_time)
|
||||
|
||||
if for_quantity:
|
||||
wo = frappe.get_doc('Work Order', self.work_order)
|
||||
|
||||
@@ -18,6 +18,7 @@ from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
|
||||
from frappe.utils.csvutils import getlink
|
||||
from erpnext.stock.utils import get_bin, validate_warehouse_company, get_latest_stock_qty
|
||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||
from six import text_type
|
||||
|
||||
class OverProductionError(frappe.ValidationError): pass
|
||||
class StockOverProductionError(frappe.ValidationError): pass
|
||||
@@ -591,10 +592,10 @@ def make_timesheet(production_order, company):
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_timesheet_detail(timesheet, args):
|
||||
if isinstance(timesheet, unicode):
|
||||
if isinstance(timesheet, text_type):
|
||||
timesheet = frappe.get_doc('Timesheet', timesheet)
|
||||
|
||||
if isinstance(args, unicode):
|
||||
if isinstance(args, text_type):
|
||||
args = json.loads(args)
|
||||
|
||||
timesheet.append('time_logs', args)
|
||||
|
||||
@@ -533,7 +533,7 @@ erpnext.patches.v11_0.create_department_records_for_each_company
|
||||
erpnext.patches.v11_0.make_location_from_warehouse
|
||||
erpnext.patches.v11_0.make_asset_finance_book_against_old_entries
|
||||
erpnext.patches.v11_0.check_buying_selling_in_currency_exchange
|
||||
erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018
|
||||
erpnext.patches.v11_0.move_item_defaults_to_child_table_for_multicompany #02-07-2018 #19-06-2019
|
||||
erpnext.patches.v11_0.refactor_erpnext_shopify #2018-09-07
|
||||
erpnext.patches.v11_0.rename_overproduction_percent_field
|
||||
erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom
|
||||
@@ -586,7 +586,7 @@ erpnext.patches.v11_0.add_permissions_in_gst_settings
|
||||
erpnext.patches.v11_1.setup_guardian_role
|
||||
execute:frappe.delete_doc('DocType', 'Notification Control')
|
||||
erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
|
||||
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
|
||||
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 #25-06-2019
|
||||
erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019
|
||||
erpnext.patches.v11_1.make_job_card_time_logs
|
||||
erpnext.patches.v11_1.set_variant_based_on
|
||||
@@ -599,4 +599,7 @@ erpnext.patches.v11_1.rename_depends_on_lwp
|
||||
erpnext.patches.v11_1.set_missing_title_for_quotation
|
||||
execute:frappe.delete_doc("Report", "Inactive Items")
|
||||
erpnext.patches.v11_1.delete_scheduling_tool
|
||||
erpnext.patches.v11_1.update_bank_transaction_status
|
||||
erpnext.patches.v11_1.update_bank_transaction_status
|
||||
erpnext.patches.v11_1.renamed_delayed_item_report
|
||||
erpnext.patches.v11_1.set_missing_opportunity_from
|
||||
erpnext.patches.v11_1.set_quotation_status
|
||||
@@ -8,8 +8,10 @@ import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("stock", "doctype", "item_barcode")
|
||||
if frappe.get_all("Item Barcode", limit=1): return
|
||||
if "barcode" not in frappe.db.get_table_columns("Item"): return
|
||||
|
||||
items_barcode = frappe.get_all('Item', ['name', 'barcode'], { 'barcode': ('!=', '') })
|
||||
items_barcode = frappe.db.sql("select name, barcode from tabItem where barcode is not null", as_dict=True)
|
||||
frappe.reload_doc("stock", "doctype", "item")
|
||||
|
||||
|
||||
|
||||
@@ -17,10 +17,8 @@ def execute():
|
||||
frappe.reload_doc('stock', 'doctype', 'item_default')
|
||||
frappe.reload_doc('stock', 'doctype', 'item')
|
||||
|
||||
if frappe.db.a_row_exists('Item Default'): return
|
||||
|
||||
companies = frappe.get_all("Company")
|
||||
if len(companies) == 1:
|
||||
if len(companies) == 1 and not frappe.get_all("Item Default", limit=1):
|
||||
try:
|
||||
frappe.db.sql('''
|
||||
INSERT INTO `tabItem Default`
|
||||
@@ -35,32 +33,64 @@ def execute():
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
item_details = frappe.get_all("Item", fields=["name", "default_warehouse", "buying_cost_center",
|
||||
"expense_account", "selling_cost_center", "income_account"], limit=100)
|
||||
item_details = frappe.db.sql(""" SELECT name, default_warehouse,
|
||||
buying_cost_center, expense_account, selling_cost_center, income_account
|
||||
FROM tabItem
|
||||
WHERE
|
||||
name not in (select distinct parent from `tabItem Default`) and ifnull(disabled, 0) = 0"""
|
||||
, as_dict=1)
|
||||
|
||||
for item in item_details:
|
||||
item_defaults = []
|
||||
items_default_data = {}
|
||||
for item_data in item_details:
|
||||
for d in [["default_warehouse", "Warehouse"], ["expense_account", "Account"],
|
||||
["income_account", "Account"], ["buying_cost_center", "Cost Center"],
|
||||
["selling_cost_center", "Cost Center"]]:
|
||||
if item_data.get(d[0]):
|
||||
company = frappe.get_value(d[1], item_data.get(d[0]), "company", cache=True)
|
||||
|
||||
def insert_into_item_defaults(doc_field_name, doc_field_value, company):
|
||||
for d in item_defaults:
|
||||
if d.get("company") == company:
|
||||
d[doc_field_name] = doc_field_value
|
||||
return
|
||||
item_defaults.append({
|
||||
"company": company,
|
||||
doc_field_name: doc_field_value
|
||||
})
|
||||
if item_data.name not in items_default_data:
|
||||
items_default_data[item_data.name] = {}
|
||||
|
||||
for d in [
|
||||
["default_warehouse", "Warehouse"], ["expense_account", "Account"], ["income_account", "Account"],
|
||||
["buying_cost_center", "Cost Center"], ["selling_cost_center", "Cost Center"]
|
||||
]:
|
||||
if item.get(d[0]):
|
||||
company = frappe.get_value(d[1], item.get(d[0]), "company", cache=True)
|
||||
insert_into_item_defaults(d[0], item.get(d[0]), company)
|
||||
company_wise_data = items_default_data[item_data.name]
|
||||
|
||||
doc = frappe.get_doc("Item", item.name)
|
||||
doc.extend("item_defaults", item_defaults)
|
||||
if company not in company_wise_data:
|
||||
company_wise_data[company] = {}
|
||||
|
||||
for child_doc in doc.item_defaults:
|
||||
child_doc.db_insert()
|
||||
default_data = company_wise_data[company]
|
||||
default_data[d[0]] = item_data.get(d[0])
|
||||
|
||||
to_insert_data = []
|
||||
|
||||
# items_default_data data structure will be as follow
|
||||
# {
|
||||
# 'item_code 1': {'company 1': {'default_warehouse': 'Test Warehouse 1'}},
|
||||
# 'item_code 2': {
|
||||
# 'company 1': {'default_warehouse': 'Test Warehouse 1'},
|
||||
# 'company 2': {'default_warehouse': 'Test Warehouse 1'}
|
||||
# }
|
||||
# }
|
||||
|
||||
for item_code, companywise_item_data in items_default_data.items():
|
||||
for company, item_default_data in companywise_item_data.items():
|
||||
to_insert_data.append((
|
||||
frappe.generate_hash("", 10),
|
||||
item_code,
|
||||
'Item',
|
||||
'item_defaults',
|
||||
company,
|
||||
item_default_data.get('default_warehouse'),
|
||||
item_default_data.get('expense_account'),
|
||||
item_default_data.get('income_account'),
|
||||
item_default_data.get('buying_cost_center'),
|
||||
item_default_data.get('selling_cost_center'),
|
||||
))
|
||||
|
||||
if to_insert_data:
|
||||
frappe.db.sql('''
|
||||
INSERT INTO `tabItem Default`
|
||||
(
|
||||
`name`, `parent`, `parenttype`, `parentfield`, `company`, `default_warehouse`,
|
||||
`expense_account`, `income_account`, `buying_cost_center`, `selling_cost_center`
|
||||
)
|
||||
VALUES {}
|
||||
'''.format(', '.join(['%s'] * len(to_insert_data))), tuple(to_insert_data))
|
||||
@@ -40,7 +40,7 @@ def execute():
|
||||
# This is probably never used anywhere else as of now, but should be
|
||||
values = []
|
||||
for d in batch_transactions:
|
||||
values.append("('{}', {})".format(d.parent, d.qty))
|
||||
values.append("('{}', {})".format(frappe.db.escape(d.parent), d.qty))
|
||||
conditions = ",".join(values)
|
||||
frappe.db.sql("""
|
||||
INSERT INTO `tab{}` (name, total_qty) VALUES {}
|
||||
|
||||
10
erpnext/patches/v11_1/renamed_delayed_item_report.py
Normal file
10
erpnext/patches/v11_1/renamed_delayed_item_report.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for report in ["Delayed Order Item Summary", "Delayed Order Summary"]:
|
||||
if frappe.db.exists("Report", report):
|
||||
frappe.delete_doc("Report", report)
|
||||
17
erpnext/patches/v11_1/set_missing_opportunity_from.py
Normal file
17
erpnext/patches/v11_1/set_missing_opportunity_from.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
|
||||
frappe.reload_doctype("Opportunity")
|
||||
if frappe.db.has_column("Opportunity", "enquiry_from"):
|
||||
frappe.db.sql(""" UPDATE `tabOpportunity` set opportunity_from = enquiry_from
|
||||
where ifnull(opportunity_from, '') = '' and ifnull(enquiry_from, '') != ''""")
|
||||
|
||||
if frappe.db.has_column("Opportunity", "lead") and frappe.db.has_column("Opportunity", "enquiry_from"):
|
||||
frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = lead
|
||||
where enquiry_from = 'Lead' and ifnull(party_name, '') = '' and ifnull(lead, '') != ''""")
|
||||
|
||||
if frappe.db.has_column("Opportunity", "customer") and frappe.db.has_column("Opportunity", "enquiry_from"):
|
||||
frappe.db.sql(""" UPDATE `tabOpportunity` set party_name = customer
|
||||
where enquiry_from = 'Customer' and ifnull(party_name, '') = '' and ifnull(customer, '') != ''""")
|
||||
7
erpnext/patches/v11_1/set_quotation_status.py
Normal file
7
erpnext/patches/v11_1/set_quotation_status.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
|
||||
frappe.db.sql(""" UPDATE `tabQuotation` set status = 'Open'
|
||||
where docstatus = 1 and status = 'Submitted' """)
|
||||
@@ -19,43 +19,38 @@ frappe.ui.form.on("Task", {
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.fields_dict['parent_task'].get_query = function() {
|
||||
frm.fields_dict['parent_task'].get_query = function () {
|
||||
return {
|
||||
filters: {
|
||||
"is_group": 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!frm.is_group){
|
||||
var doc = frm.doc;
|
||||
if(doc.__islocal) {
|
||||
if(!frm.doc.exp_end_date) {
|
||||
frm.set_value("exp_end_date", frappe.datetime.add_days(new Date(), 7));
|
||||
}
|
||||
}
|
||||
|
||||
if(!doc.__islocal) {
|
||||
if(frappe.model.can_read("Timesheet")) {
|
||||
frm.add_custom_button(__("Timesheet"), function() {
|
||||
frappe.route_options = {"project": doc.project, "task": doc.name}
|
||||
if (!frm.doc.is_group) {
|
||||
if (!frm.is_new()) {
|
||||
if (frappe.model.can_read("Timesheet")) {
|
||||
frm.add_custom_button(__("Timesheet"), () => {
|
||||
frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name }
|
||||
frappe.set_route("List", "Timesheet");
|
||||
}, __("View"), true);
|
||||
}
|
||||
if(frappe.model.can_read("Expense Claim")) {
|
||||
frm.add_custom_button(__("Expense Claims"), function() {
|
||||
frappe.route_options = {"project": doc.project, "task": doc.name}
|
||||
|
||||
if (frappe.model.can_read("Expense Claim")) {
|
||||
frm.add_custom_button(__("Expense Claims"), () => {
|
||||
frappe.route_options = { "project": frm.doc.project, "task": frm.doc.name }
|
||||
frappe.set_route("List", "Expense Claim");
|
||||
}, __("View"), true);
|
||||
}
|
||||
|
||||
if(frm.perm[0].write) {
|
||||
if(frm.doc.status!=="Closed" && frm.doc.status!=="Cancelled") {
|
||||
frm.add_custom_button(__("Close"), function() {
|
||||
if (frm.perm[0].write) {
|
||||
if (!["Closed", "Cancelled"].includes(frm.doc.status)) {
|
||||
frm.add_custom_button(__("Close"), () => {
|
||||
frm.set_value("status", "Closed");
|
||||
frm.save();
|
||||
});
|
||||
} else {
|
||||
frm.add_custom_button(__("Reopen"), function() {
|
||||
frm.add_custom_button(__("Reopen"), () => {
|
||||
frm.set_value("status", "Open");
|
||||
frm.save();
|
||||
});
|
||||
|
||||
@@ -103,8 +103,8 @@ class TestTimesheet(unittest.TestCase):
|
||||
{
|
||||
"billable": 1,
|
||||
"activity_type": "_Test Activity Type",
|
||||
"from_type": now_datetime(),
|
||||
"hours": 3,
|
||||
"from_time": now_datetime(),
|
||||
"to_time": now_datetime() + datetime.timedelta(hours=3),
|
||||
"company": "_Test Company"
|
||||
}
|
||||
)
|
||||
@@ -113,8 +113,8 @@ class TestTimesheet(unittest.TestCase):
|
||||
{
|
||||
"billable": 1,
|
||||
"activity_type": "_Test Activity Type",
|
||||
"from_type": now_datetime(),
|
||||
"hours": 3,
|
||||
"from_time": now_datetime(),
|
||||
"to_time": now_datetime() + datetime.timedelta(hours=3),
|
||||
"company": "_Test Company"
|
||||
}
|
||||
)
|
||||
|
||||
@@ -30,23 +30,23 @@ def get_columns():
|
||||
"options": "Timesheet",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"label": _("Billable Hours"),
|
||||
"fieldtype": "Float",
|
||||
"fieldname": "total_billable_hours",
|
||||
"width": 50
|
||||
},
|
||||
{
|
||||
"label": _("Working Hours"),
|
||||
"fieldtype": "Float",
|
||||
"fieldname": "total_hours",
|
||||
"width": 50
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"label": _("Billable Hours"),
|
||||
"fieldtype": "Float",
|
||||
"fieldname": "total_billable_hours",
|
||||
"width": 150
|
||||
},
|
||||
{
|
||||
"label": _("Billing Amount"),
|
||||
"fieldtype": "Currency",
|
||||
"fieldname": "amount",
|
||||
"width": 100
|
||||
"width": 150
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -514,7 +514,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
||||
net_total += item.net_amount;
|
||||
|
||||
// discount amount rounding loss adjustment if no taxes
|
||||
if ((!(me.frm.doc.taxes || []).length || (me.frm.doc.apply_discount_on == "Net Total"))
|
||||
if ((!(me.frm.doc.taxes || []).length || total_for_discount_amount==me.frm.doc.net_total || (me.frm.doc.apply_discount_on == "Net Total"))
|
||||
&& i == (me.frm.doc.items || []).length - 1) {
|
||||
var discount_amount_loss = flt(me.frm.doc.net_total - net_total
|
||||
- me.frm.doc.discount_amount, precision("net_total"));
|
||||
|
||||
@@ -1121,7 +1121,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
return {
|
||||
"items": this._get_item_list(item),
|
||||
"customer": me.frm.doc.customer || me.frm.doc.party_name,
|
||||
"quotation_to": me.doc.frm.quotation_to,
|
||||
"quotation_to": me.frm.doc.quotation_to,
|
||||
"customer_group": me.frm.doc.customer_group,
|
||||
"territory": me.frm.doc.territory,
|
||||
"supplier": me.frm.doc.supplier,
|
||||
@@ -1291,7 +1291,12 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
me.frm.set_value("taxes", r.message);
|
||||
me.calculate_taxes_and_totals();
|
||||
|
||||
if(me.frm.doc.shipping_rule) {
|
||||
me.frm.script_manager.trigger("shipping_rule");
|
||||
} else {
|
||||
me.calculate_taxes_and_totals();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 ">
|
||||
<div class ="row multimode-payments">
|
||||
<div class ="row multimode-payments" style = "margin-right:10px">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 payment-toolbar">
|
||||
|
||||
@@ -286,6 +286,16 @@ $.extend(erpnext.utils, {
|
||||
refresh_field(table_fieldname);
|
||||
},
|
||||
|
||||
create_new_doc: function (doctype, update_fields) {
|
||||
frappe.model.with_doctype(doctype, function() {
|
||||
var new_doc = frappe.model.get_new_doc(doctype);
|
||||
for (let [key, value] of Object.entries(update_fields)) {
|
||||
new_doc[key] = value;
|
||||
}
|
||||
frappe.ui.form.make_quick_entry(doctype, null, null, new_doc);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
erpnext.utils.select_alternate_items = function(opts) {
|
||||
|
||||
@@ -233,30 +233,32 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
||||
get_batch_fields: function() {
|
||||
var me = this;
|
||||
return [
|
||||
{fieldtype:'Section Break', label: __('Batches')},
|
||||
{fieldname: 'batches', fieldtype: 'Table',
|
||||
{ fieldtype: 'Section Break', label: __('Batches') },
|
||||
{
|
||||
fieldname: 'batches', fieldtype: 'Table',
|
||||
fields: [
|
||||
{
|
||||
fieldtype:'Link',
|
||||
fieldname:'batch_no',
|
||||
options: 'Batch',
|
||||
label: __('Select Batch'),
|
||||
in_list_view:1,
|
||||
get_query: function() {
|
||||
'fieldtype': 'Link',
|
||||
'read_only': 0,
|
||||
'fieldname': 'batch_no',
|
||||
'options': 'Batch',
|
||||
'label': __('Select Batch'),
|
||||
'in_list_view': 1,
|
||||
get_query: function () {
|
||||
return {
|
||||
filters: {item: me.item_code },
|
||||
query: 'erpnext.controllers.queries.get_batch_numbers'
|
||||
};
|
||||
filters: { item: me.item_code },
|
||||
query: 'erpnext.controllers.queries.get_batch_numbers'
|
||||
};
|
||||
},
|
||||
onchange: function(e) {
|
||||
change: function () {
|
||||
let val = this.get_value();
|
||||
if(val.length === 0) {
|
||||
if (val.length === 0) {
|
||||
this.grid_row.on_grid_fields_dict
|
||||
.available_qty.set_value(0);
|
||||
return;
|
||||
}
|
||||
let selected_batches = this.grid.grid_rows.map((row) => {
|
||||
if(row === this.grid_row) {
|
||||
if (row === this.grid_row) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -264,12 +266,12 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
||||
return row.on_grid_fields_dict.batch_no.get_value();
|
||||
}
|
||||
});
|
||||
if(selected_batches.includes(val)) {
|
||||
if (selected_batches.includes(val)) {
|
||||
this.set_value("");
|
||||
frappe.throw(__(`Batch ${val} already selected.`));
|
||||
return;
|
||||
}
|
||||
if(me.warehouse_details.name) {
|
||||
if (me.warehouse_details.name) {
|
||||
frappe.call({
|
||||
method: 'erpnext.stock.doctype.batch.batch.get_batch_qty',
|
||||
args: {
|
||||
@@ -292,31 +294,32 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
||||
}
|
||||
},
|
||||
{
|
||||
fieldtype:'Float',
|
||||
read_only:1,
|
||||
fieldname:'available_qty',
|
||||
label: __('Available'),
|
||||
in_list_view:1,
|
||||
default: 0,
|
||||
onchange: function() {
|
||||
'fieldtype': 'Float',
|
||||
'read_only': 1,
|
||||
'fieldname': 'available_qty',
|
||||
'label': __('Available'),
|
||||
'in_list_view': 1,
|
||||
'default': 0,
|
||||
change: function () {
|
||||
this.grid_row.on_grid_fields_dict.selected_qty.set_value('0');
|
||||
}
|
||||
},
|
||||
{
|
||||
fieldtype:'Float',
|
||||
fieldname:'selected_qty',
|
||||
label: __('Qty'),
|
||||
in_list_view:1,
|
||||
'fieldtype': 'Float',
|
||||
'read_only': 0,
|
||||
'fieldname': 'selected_qty',
|
||||
'label': __('Qty'),
|
||||
'in_list_view': 1,
|
||||
'default': 0,
|
||||
onchange: function(e) {
|
||||
change: function () {
|
||||
var batch_no = this.grid_row.on_grid_fields_dict.batch_no.get_value();
|
||||
var available_qty = this.grid_row.on_grid_fields_dict.available_qty.get_value();
|
||||
var selected_qty = this.grid_row.on_grid_fields_dict.selected_qty.get_value();
|
||||
|
||||
if(batch_no.length === 0 && parseInt(selected_qty)!==0) {
|
||||
if (batch_no.length === 0 && parseInt(selected_qty) !== 0) {
|
||||
frappe.throw(__("Please select a batch"));
|
||||
}
|
||||
if(me.warehouse_details.type === 'Source Warehouse' &&
|
||||
if (me.warehouse_details.type === 'Source Warehouse' &&
|
||||
parseFloat(available_qty) < parseFloat(selected_qty)) {
|
||||
|
||||
this.set_value('0');
|
||||
@@ -332,7 +335,7 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
||||
],
|
||||
in_place_edit: true,
|
||||
data: this.data,
|
||||
get_data: function() {
|
||||
get_data: function () {
|
||||
return this.data;
|
||||
},
|
||||
}
|
||||
@@ -342,13 +345,24 @@ erpnext.SerialNoBatchSelector = Class.extend({
|
||||
get_serial_no_fields: function() {
|
||||
var me = this;
|
||||
this.serial_list = [];
|
||||
|
||||
let serial_no_filters = {
|
||||
item_code: me.item_code,
|
||||
delivery_document_no: ""
|
||||
}
|
||||
|
||||
if (me.warehouse_details.name) {
|
||||
serial_no_filters['warehouse'] = me.warehouse_details.name;
|
||||
}
|
||||
return [
|
||||
{fieldtype: 'Section Break', label: __('Serial No')},
|
||||
{
|
||||
fieldtype: 'Link', fieldname: 'serial_no_select', options: 'Serial No',
|
||||
label: __('Select'),
|
||||
get_query: function() {
|
||||
return { filters: {item_code: me.item_code, warehouse: me.warehouse_details.name}};
|
||||
return {
|
||||
filters: serial_no_filters
|
||||
};
|
||||
},
|
||||
onchange: function(e) {
|
||||
if(this.in_local_change) return;
|
||||
|
||||
@@ -367,6 +367,20 @@ def generate_ewb_json(dt, dn):
|
||||
|
||||
frappe.local.response.filename = '{0}_e-WayBill_Data_{1}.json'.format(doc_name, frappe.utils.random_string(5))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_gstins_for_company(company):
|
||||
company_gstins =[]
|
||||
if company:
|
||||
company_gstins = frappe.db.sql("""select
|
||||
distinct `tabAddress`.gstin
|
||||
from
|
||||
`tabAddress`, `tabDynamic Link`
|
||||
where
|
||||
`tabDynamic Link`.parent = `tabAddress`.name and
|
||||
`tabDynamic Link`.parenttype = 'Address' and
|
||||
`tabDynamic Link`.link_doctype = 'Company' and
|
||||
`tabDynamic Link`.link_name = '{0}'""".format(company))
|
||||
return company_gstins
|
||||
|
||||
def get_address_details(data, doc, company_address, billing_address):
|
||||
data.fromPincode = validate_pincode(company_address.pincode, 'Company Address')
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
<DatiGenerali>
|
||||
<DatiGeneraliDocumento>
|
||||
<TipoDocumento>{{ doc.type_of_document }}</TipoDocumento>
|
||||
<Divisa>EUR</Divisa>
|
||||
<Divisa>{{ doc.currency }}</Divisa>
|
||||
<Data>{{ doc.posting_date }}</Data>
|
||||
<Numero>{{ doc.unamended_name }}</Numero>
|
||||
{%- if doc.stamp_duty %}
|
||||
|
||||
@@ -80,8 +80,7 @@ def prepare_invoice(invoice, progressive_number):
|
||||
invoice.stamp_duty = stamp_duty_charge_row.tax_amount
|
||||
|
||||
for item in invoice.e_invoice_items:
|
||||
if (item.tax_rate == 0.0 and item.tax_amount == 0.0
|
||||
and item.charge_type != 'Actual' and tax_data.get("0.0")):
|
||||
if item.tax_rate == 0.0 and item.tax_amount == 0.0 and tax_data.get("0.0"):
|
||||
item.tax_exemption_reason = tax_data["0.0"]["tax_exemption_reason"]
|
||||
|
||||
customer_po_data = {}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user