Compare commits
218 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ad556cd4c | ||
|
|
475729cefe | ||
|
|
f7713ebfa7 | ||
|
|
92640cc899 | ||
|
|
826f020862 | ||
|
|
93a186aa11 | ||
|
|
742d3e5549 | ||
|
|
bcbe32ce7c | ||
|
|
b434f2687e | ||
|
|
a752eca82c | ||
|
|
37da7d7d05 | ||
|
|
b5d9b38dee | ||
|
|
11e2a9ac90 | ||
|
|
1275ea5123 | ||
|
|
812224e56e | ||
|
|
8f17281011 | ||
|
|
8233cb11ed | ||
|
|
984a7a7e61 | ||
|
|
b5cc946771 | ||
|
|
65dd1f6b4c | ||
|
|
7c9a6eba3f | ||
|
|
f2ccde0454 | ||
|
|
b81ece9ddf | ||
|
|
2f822476dd | ||
|
|
dcfe19d868 | ||
|
|
4f40b2dca5 | ||
|
|
1b48fde986 | ||
|
|
33db332eca | ||
|
|
257e18b640 | ||
|
|
292f46fec0 | ||
|
|
78a0be666f | ||
|
|
ce4f520908 | ||
|
|
29160441bb | ||
|
|
1b18bba04a | ||
|
|
f8c26bb778 | ||
|
|
ccd0617e19 | ||
|
|
bf10d0f98b | ||
|
|
dbb67fb4fd | ||
|
|
404f39d373 | ||
|
|
bbee9b6cc4 | ||
|
|
69b0535e10 | ||
|
|
7f63c1ad7c | ||
|
|
ebe1ebead2 | ||
|
|
f2b3307136 | ||
|
|
9d215c2d9b | ||
|
|
3cf0d51e65 | ||
|
|
9fc5ddc26e | ||
|
|
0ff31f0ebf | ||
|
|
40349f4b00 | ||
|
|
b36517158b | ||
|
|
3b9720f0be | ||
|
|
cf26b2ca1c | ||
|
|
02a40e9d7b | ||
|
|
ea199f9cd9 | ||
|
|
161f35a687 | ||
|
|
fcb984b294 | ||
|
|
723fe8fb1b | ||
|
|
47c0c8ba49 | ||
|
|
3e0a937cb8 | ||
|
|
bd63f0056a | ||
|
|
55daa9cd24 | ||
|
|
764b9bfeba | ||
|
|
62b985d405 | ||
|
|
ed393d1025 | ||
|
|
ed376cacc8 | ||
|
|
7461806b1c | ||
|
|
bb7c5ac0f8 | ||
|
|
0272fc05bf | ||
|
|
4f6b68fef2 | ||
|
|
eae2ddac69 | ||
|
|
99be9d17d5 | ||
|
|
5df63e36d4 | ||
|
|
bd99606a14 | ||
|
|
b0a46f397a | ||
|
|
53c9b63c0b | ||
|
|
9b2078feab | ||
|
|
30304e68ff | ||
|
|
6bc500bffa | ||
|
|
8be895091e | ||
|
|
f5f8a1f288 | ||
|
|
c925a38f79 | ||
|
|
c23230faea | ||
|
|
6855b87f76 | ||
|
|
07d030208f | ||
|
|
47f6e32920 | ||
|
|
7bd1453f8f | ||
|
|
bf416cfbf8 | ||
|
|
67918fff32 | ||
|
|
132dac9712 | ||
|
|
57914f140e | ||
|
|
ede0af97cd | ||
|
|
ad4ede0e23 | ||
|
|
cfcf9b3832 | ||
|
|
d2065ce3bf | ||
|
|
31edddace6 | ||
|
|
8f29159fb7 | ||
|
|
d9f1b539dc | ||
|
|
60bd383a25 | ||
|
|
c0ec3c3f7b | ||
|
|
60aa1170d5 | ||
|
|
9630aa3d7f | ||
|
|
aa6576c0ea | ||
|
|
fa5ecb066e | ||
|
|
c36524ec54 | ||
|
|
cba3570cf6 | ||
|
|
5b7503c074 | ||
|
|
8441dd9184 | ||
|
|
78869f1e77 | ||
|
|
ff8f1bc88e | ||
|
|
91b0dce4d8 | ||
|
|
59f7b8c4a1 | ||
|
|
2476a8aab9 | ||
|
|
46ffbb74ff | ||
|
|
492aff2a8b | ||
|
|
c3fbc04aab | ||
|
|
5b866db6bc | ||
|
|
9fbb8192e1 | ||
|
|
ea1408f2e0 | ||
|
|
f2a941b1a4 | ||
|
|
ca1cfd91ea | ||
|
|
c3d43e672b | ||
|
|
e141fdcfcc | ||
|
|
7cb8f890bc | ||
|
|
d6aadef395 | ||
|
|
11c899bc1f | ||
|
|
00efeb26f4 | ||
|
|
1129ac711e | ||
|
|
2ea593bdd8 | ||
|
|
02fd6f56d6 | ||
|
|
098b444f6f | ||
|
|
e72bde5159 | ||
|
|
c10e106f8f | ||
|
|
2c111b7b14 | ||
|
|
f92fcdbac4 | ||
|
|
1ff9e0432a | ||
|
|
c0f149a3be | ||
|
|
2ae6cfda5f | ||
|
|
22d9f0a4aa | ||
|
|
aa7cddef5c | ||
|
|
3d2b3d37d4 | ||
|
|
821222653b | ||
|
|
adddb15380 | ||
|
|
5fd79f7f77 | ||
|
|
2505c74d64 | ||
|
|
d5f9ebd008 | ||
|
|
d021e45301 | ||
|
|
e9ca5e81d2 | ||
|
|
a7f5589564 | ||
|
|
a8df73c263 | ||
|
|
40a5a3063c | ||
|
|
d17c24f969 | ||
|
|
0289ad285f | ||
|
|
562227db8f | ||
|
|
9c1cac80fe | ||
|
|
03016e5000 | ||
|
|
9240eaa0a6 | ||
|
|
618940b5c9 | ||
|
|
ccf2b7b08b | ||
|
|
1e989b35ad | ||
|
|
cae2723920 | ||
|
|
badc855400 | ||
|
|
a4502c4f6b | ||
|
|
1f02c62339 | ||
|
|
ef770b593a | ||
|
|
a9c90c96a9 | ||
|
|
c5d222253a | ||
|
|
94769d81a8 | ||
|
|
edd63a178f | ||
|
|
ace68cd283 | ||
|
|
d3bd151c30 | ||
|
|
0794816527 | ||
|
|
7041a45294 | ||
|
|
a6746407e5 | ||
|
|
e3407083fe | ||
|
|
63e40b52af | ||
|
|
2e203e53c6 | ||
|
|
c0201877dd | ||
|
|
745292ce98 | ||
|
|
00279f27f3 | ||
|
|
f620dae8ca | ||
|
|
9d7fe1f7cd | ||
|
|
ba4f32be5c | ||
|
|
85f63a3866 | ||
|
|
149f7ee875 | ||
|
|
c9a1eb1081 | ||
|
|
2e560cb25d | ||
|
|
651b612909 | ||
|
|
398eac3f4c | ||
|
|
f3025f1596 | ||
|
|
0712013960 | ||
|
|
3fdda7a9b7 | ||
|
|
9bcadf8126 | ||
|
|
492de67d7b | ||
|
|
80a9f523d5 | ||
|
|
e3f0412570 | ||
|
|
23fa8893a8 | ||
|
|
a3714e1678 | ||
|
|
0f6c35d63f | ||
|
|
93779c21a7 | ||
|
|
e010ddf65f | ||
|
|
969c8aaf52 | ||
|
|
c711445b91 | ||
|
|
2b88ac948e | ||
|
|
c672530210 | ||
|
|
c5b061834b | ||
|
|
8a8966ce9b | ||
|
|
54f3a0f7c6 | ||
|
|
ecc4fdd3ef | ||
|
|
60da37b502 | ||
|
|
2777fd4332 | ||
|
|
9602bf4ba3 | ||
|
|
5042dd32da | ||
|
|
4d347b1ca0 | ||
|
|
3d85951c1f | ||
|
|
7b91042ae6 | ||
|
|
633a39144d | ||
|
|
94b41ea4f6 | ||
|
|
d8f7de9946 |
@@ -11,6 +11,7 @@ install:
|
||||
- pip install flake8==3.3.0
|
||||
- flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics
|
||||
- sudo rm /etc/apt/sources.list.d/docker.list
|
||||
- sudo apt-get install hhvm && rm -rf /home/travis/.kiex/
|
||||
- sudo apt-get purge -y mysql-common mysql-server mysql-client
|
||||
- nvm install v7.10.0
|
||||
- wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
|
||||
@@ -32,6 +33,7 @@ before_script:
|
||||
- bench reinstall --yes
|
||||
- bench build
|
||||
- bench scheduler disable
|
||||
- sed -i 's/9000/9001/g' sites/common_site_config.json
|
||||
- bench start &
|
||||
- sleep 10
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
from frappe.utils import getdate
|
||||
|
||||
__version__ = '10.1.13'
|
||||
__version__ = '10.1.35'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
||||
@@ -71,7 +71,7 @@ frappe.treeview_settings["Account"] = {
|
||||
|
||||
// financial statements
|
||||
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet',
|
||||
'Profit and Loss', 'Cash Flow Statement', 'Accounts Payable', 'Accounts Receivable']) {
|
||||
'Profit and Loss Statement', 'Cash Flow Statement', 'Accounts Payable', 'Accounts Receivable']) {
|
||||
treeview.page.add_inner_button(__(report), function() {
|
||||
frappe.set_route('query-report', report, {company: get_company()});
|
||||
}, __('Financial Statements'));
|
||||
|
||||
@@ -165,7 +165,7 @@ def build_account_tree(tree, parent, all_accounts):
|
||||
tree[child.account_name] = {}
|
||||
|
||||
# assign account_type and root_type
|
||||
if child.account_type:
|
||||
if child.account_number:
|
||||
tree[child.account_name]["account_number"] = child.account_number
|
||||
if child.account_type:
|
||||
tree[child.account_name]["account_type"] = child.account_type
|
||||
@@ -175,4 +175,4 @@ def build_account_tree(tree, parent, all_accounts):
|
||||
tree[child.account_name]["root_type"] = child.root_type
|
||||
|
||||
# call recursively to build a subtree for current account
|
||||
build_account_tree(tree[child.account_name], child, all_accounts)
|
||||
build_account_tree(tree[child.account_name], child, all_accounts)
|
||||
|
||||
@@ -27,22 +27,32 @@ def create_or_update_cheque_print_format(template_name):
|
||||
doc = frappe.get_doc("Cheque Print Template", template_name)
|
||||
|
||||
cheque_print.html = """
|
||||
<style>
|
||||
.print-format {
|
||||
padding: 0px;
|
||||
}
|
||||
@media screen {
|
||||
.print-format {
|
||||
padding: 0in;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div style="position: relative; top:%(starting_position_from_top_edge)scm">
|
||||
<div style="width:%(cheque_width)scm;height:%(cheque_height)scm;">
|
||||
<span style="top: {{ %(acc_pay_dist_from_top_edge)s }}cm; left: {{ %(acc_pay_dist_from_left_edge)s }}cm;
|
||||
border-bottom: solid 1px;border-top:solid 1px; position: absolute;">
|
||||
<span style="top:%(acc_pay_dist_from_top_edge)scm; left:%(acc_pay_dist_from_left_edge)scm;
|
||||
border-bottom: solid 1px;border-top:solid 1px; width:2cm;text-align: center; position: absolute;">
|
||||
%(message_to_show)s
|
||||
</span>
|
||||
<span style="top:%(date_dist_from_top_edge)s cm; left:%(date_dist_from_left_edge)scm;
|
||||
<span style="top:%(date_dist_from_top_edge)scm; left:%(date_dist_from_left_edge)scm;
|
||||
position: absolute;">
|
||||
{{ frappe.utils.formatdate(doc.reference_date) or '' }}
|
||||
</span>
|
||||
<span style="top:%(acc_no_dist_from_top_edge)scm;left:%(acc_no_dist_from_left_edge)scm;
|
||||
position: absolute;">
|
||||
position: absolute; min-width: 6cm;">
|
||||
{{ doc.account_no or '' }}
|
||||
</span>
|
||||
<span style="top:%(payer_name_from_top_edge)scm;left: %(payer_name_from_left_edge)scm;
|
||||
position: absolute;">
|
||||
position: absolute; min-width: 6cm;">
|
||||
{{doc.party_name}}
|
||||
</span>
|
||||
<span style="top:%(amt_in_words_from_top_edge)scm; left:%(amt_in_words_from_left_edge)scm;
|
||||
@@ -51,11 +61,11 @@ def create_or_update_cheque_print_format(template_name):
|
||||
{{frappe.utils.money_in_words(doc.base_paid_amount or doc.base_received_amount)}}
|
||||
</span>
|
||||
<span style="top:%(amt_in_figures_from_top_edge)scm;left: %(amt_in_figures_from_left_edge)scm;
|
||||
position: absolute;">
|
||||
position: absolute; min-width: 4cm;">
|
||||
{{doc.get_formatted("base_paid_amount") or doc.get_formatted("base_received_amount")}}
|
||||
</span>
|
||||
<span style="top:%(signatory_from_top_edge)scm;left: %(signatory_from_left_edge)scm;
|
||||
position: absolute;">
|
||||
position: absolute; min-width: 6cm;">
|
||||
{{doc.company}}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -48,5 +48,10 @@ frappe.treeview_settings["Cost Center"] = {
|
||||
}, __('Budget'));
|
||||
|
||||
},
|
||||
onrender: function(node) {
|
||||
if(node.is_root){
|
||||
node.hide_add = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -82,7 +82,7 @@ class JournalEntry(AccountsController):
|
||||
d.reference_type = ''
|
||||
d.reference_name = ''
|
||||
d.db_update()
|
||||
|
||||
|
||||
def unlink_asset_reference(self):
|
||||
for d in self.get("accounts"):
|
||||
if d.reference_type=="Asset" and d.reference_name:
|
||||
@@ -125,7 +125,7 @@ class JournalEntry(AccountsController):
|
||||
if (d.party_type == 'Customer' and flt(d.credit) > 0) or \
|
||||
(d.party_type == 'Supplier' and flt(d.debit) > 0):
|
||||
if d.is_advance=="No":
|
||||
msgprint(_("Row {0}: Please check 'Is Advance' against Account {1} if this is an advance entry.").format(d.idx, d.account))
|
||||
msgprint(_("Row {0}: Please check 'Is Advance' against Account {1} if this is an advance entry.").format(d.idx, d.account), alert=1)
|
||||
elif d.reference_type in ("Sales Order", "Purchase Order") and d.is_advance != "Yes":
|
||||
frappe.throw(_("Row {0}: Payment against Sales/Purchase Order should always be marked as advance").format(d.idx))
|
||||
|
||||
|
||||
@@ -138,7 +138,8 @@ class OpeningInvoiceCreationTool(Document):
|
||||
income_expense_account_field = "expense_account"
|
||||
|
||||
item = get_item_dict()
|
||||
return frappe._dict({
|
||||
|
||||
args = frappe._dict({
|
||||
"items": [item],
|
||||
"is_opening": "Yes",
|
||||
"set_posting_time": 1,
|
||||
@@ -150,6 +151,11 @@ class OpeningInvoiceCreationTool(Document):
|
||||
"currency": frappe.db.get_value("Company", self.company, "default_currency")
|
||||
})
|
||||
|
||||
if self.invoice_type == "Sales":
|
||||
args["is_pos"] = 0
|
||||
|
||||
return args
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_temporary_opening_account(company=None):
|
||||
if not company:
|
||||
|
||||
@@ -768,6 +768,8 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
|
||||
party_account = doc.receivable_account
|
||||
elif dt == "Employee Advance":
|
||||
party_account = doc.advance_account
|
||||
elif dt == "Expense Claim":
|
||||
party_account = doc.payable_account
|
||||
else:
|
||||
party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
|
||||
|
||||
|
||||
@@ -78,6 +78,9 @@ class PaymentRequest(Document):
|
||||
controller = get_payment_gateway_controller(self.payment_gateway)
|
||||
controller.validate_transaction_currency(self.currency)
|
||||
|
||||
if hasattr(controller, 'validate_minimum_transaction_amount'):
|
||||
controller.validate_minimum_transaction_amount(self.currency, self.grand_total)
|
||||
|
||||
return controller.get_payment_url(**{
|
||||
"amount": flt(self.grand_total, self.precision("grand_total")),
|
||||
"title": data.company.encode("utf-8"),
|
||||
|
||||
@@ -111,8 +111,8 @@ def apply_pricing_rule(args):
|
||||
|
||||
item_list = args.get("items")
|
||||
args.pop("items")
|
||||
|
||||
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
|
||||
|
||||
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
|
||||
"automatically_set_serial_nos_based_on_fifo")
|
||||
|
||||
for item in item_list:
|
||||
@@ -122,7 +122,7 @@ def apply_pricing_rule(args):
|
||||
if set_serial_nos_based_on_fifo and not args.get('is_return'):
|
||||
out.append(get_serial_no_for_item(args_copy))
|
||||
return out
|
||||
|
||||
|
||||
def get_serial_no_for_item(args):
|
||||
from erpnext.stock.get_item_details import get_serial_no
|
||||
|
||||
@@ -131,7 +131,7 @@ def get_serial_no_for_item(args):
|
||||
"name": args.name,
|
||||
"serial_no": args.serial_no
|
||||
})
|
||||
if args.get("parenttype") in ("Sales Invoice", "Delivery Note") and args.stock_qty > 0:
|
||||
if args.get("parenttype") in ("Sales Invoice", "Delivery Note") and flt(args.stock_qty) > 0:
|
||||
item_details.serial_no = get_serial_no(args)
|
||||
return item_details
|
||||
|
||||
@@ -143,7 +143,7 @@ def get_pricing_rule_for_item(args):
|
||||
"name": args.name,
|
||||
"pricing_rule": None
|
||||
})
|
||||
|
||||
|
||||
if args.ignore_pricing_rule or not args.item_code:
|
||||
if frappe.db.exists(args.doctype, args.name) and args.get("pricing_rule"):
|
||||
item_details = remove_pricing_rule_for_item(args.get("pricing_rule"), item_details)
|
||||
@@ -180,7 +180,7 @@ def get_pricing_rule_for_item(args):
|
||||
item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
|
||||
if pricing_rule.price_or_discount == "Price":
|
||||
item_details.update({
|
||||
"price_list_rate": (pricing_rule.price/flt(args.conversion_rate)) * args.conversion_factor or 1.0 \
|
||||
"price_list_rate": (pricing_rule.price/flt(args.conversion_rate)) * (args.conversion_factor or 1.0) \
|
||||
if args.conversion_rate else 0.0,
|
||||
"discount_percentage": 0.0
|
||||
})
|
||||
@@ -192,7 +192,7 @@ def get_pricing_rule_for_item(args):
|
||||
return item_details
|
||||
|
||||
def remove_pricing_rule_for_item(pricing_rule, item_details):
|
||||
pricing_rule = frappe.db.get_value('Pricing Rule', pricing_rule,
|
||||
pricing_rule = frappe.db.get_value('Pricing Rule', pricing_rule,
|
||||
['price_or_discount', 'margin_type'], as_dict=1)
|
||||
if pricing_rule and pricing_rule.price_or_discount == 'Discount Percentage':
|
||||
item_details.discount_percentage = 0.0
|
||||
@@ -209,14 +209,14 @@ def remove_pricing_rule_for_item(pricing_rule, item_details):
|
||||
def remove_pricing_rules(item_list):
|
||||
if isinstance(item_list, basestring):
|
||||
item_list = json.loads(item_list)
|
||||
|
||||
out = []
|
||||
|
||||
out = []
|
||||
for item in item_list:
|
||||
item = frappe._dict(item)
|
||||
out.append(remove_pricing_rule_for_item(item.get("pricing_rule"), item))
|
||||
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def get_pricing_rules(args):
|
||||
def _get_tree_conditions(parenttype, allow_blank=True):
|
||||
field = frappe.scrub(parenttype)
|
||||
|
||||
@@ -319,6 +319,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
},
|
||||
|
||||
pos_profile: function() {
|
||||
this.frm.doc.taxes = []
|
||||
this.set_pos_data();
|
||||
},
|
||||
|
||||
|
||||
@@ -751,7 +751,7 @@
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@@ -4683,7 +4683,7 @@
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2018-03-13 15:19:54.711885",
|
||||
"modified": "2018-03-16 15:19:54.711885",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -334,7 +334,7 @@ class SalesInvoice(SellingController):
|
||||
for item in self.get("items"):
|
||||
if item.get('item_code'):
|
||||
for fname, val in get_pos_profile_item_details(pos,
|
||||
frappe._dict(item.as_dict()), pos).items():
|
||||
frappe._dict(item.as_dict()), pos, True).items():
|
||||
|
||||
if (not for_validate) or (for_validate and not item.get(fname)):
|
||||
item.set(fname, val)
|
||||
|
||||
@@ -39,18 +39,20 @@ frappe.ui.form.on("Tax Rule", "customer", function(frm) {
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Tax Rule", "supplier", function(frm) {
|
||||
frappe.call({
|
||||
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||
args: {
|
||||
"party": frm.doc.supplier,
|
||||
"party_type": "supplier"
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frm.set_value(k, v);
|
||||
});
|
||||
if(frm.doc.supplier) {
|
||||
frappe.call({
|
||||
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
|
||||
args: {
|
||||
"party": frm.doc.supplier,
|
||||
"party_type": "supplier"
|
||||
},
|
||||
callback: function(r) {
|
||||
if(!r.exc) {
|
||||
$.each(r.message, function(k, v) {
|
||||
frm.set_value(k, v);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"font": "Default",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<p><b>Tax Breakup:</b></p>\n<div style=\"font-size: 8px\">\n\t{{ doc.other_charges_calculation }}\n</div>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{% if doc.company_address_display %}\n\t\t{% set company_address = doc.company_address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t{% if \"GSTIN\" not in company_address %}\n\t\t\t{{ company_address }}\n\t\t\t<b>{{ _(\"GSTIN\") }}:</b>{{ doc.company_gstin }}\n\t\t{% else %}\n\t\t\t{{ company_address.replace(\"GSTIN\", \"<br>GSTIN\") }}\n\t\t{% endif %}\n\t{% endif %}\n\t<br>\n\t<b>{{ doc.select_print_heading or _(\"Invoice\") }}</b><br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t{% if doc.grand_total > 50000 %}\n\t\t{% set customer_address = doc.address_display.replace(\"\\n\", \" \").replace(\"<br>\", \" \") %}\n\t\t<b>{{ _(\"Customer\") }}:</b><br>\n\t\t{{ doc.customer_name }}<br>\n\t\t{{ customer_address }}\n\t{% endif %}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"40%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.gst_hsn_code -%}\n\t\t\t\t\t<br><b>{{ _(\"HSN/SAC\") }}:</b> {{ item.gst_hsn_code }}\n\t\t\t\t{%- endif -%}\n\t\t\t\t{%- if item.serial_no -%}\n\t\t\t\t\t<br><b>{{ _(\"Serial No\") }}:</b> {{ item.serial_no }}\n\t\t\t\t{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.rate }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- if doc.change_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t{%- endif -%}\n\t</tbody>\n</table>\n<p><b>Tax Breakup:</b></p>\n<div style=\"font-size: 8px\">\n\t{{ doc.other_charges_calculation }}\n</div>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"idx": 0,
|
||||
"line_breaks": 0,
|
||||
"modified": "2018-01-12 11:19:17.432600",
|
||||
"modified": "2018-03-20 14:24:08.167930",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "GST POS Invoice",
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
"doc_type": "Sales Invoice",
|
||||
"docstatus": 0,
|
||||
"doctype": "Print Format",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ _(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.items -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}<br>@ {{ item.get_formatted(\"rate\") }}</td>\n\t\t\t<td class=\"text-right\">{{ item.get_formatted(\"amount\") }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t{% if doc.flags.show_inclusive_tax_in_print %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total Excl. Tax\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"net_total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% else %}\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ _(\"Total\") }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"total\", doc) }}\n\t\t\t\t</td>\n\t\t\t{% endif %}\n\t\t</tr>\n\t\t{%- for row in doc.taxes -%}\n\t\t {%- if not row.included_in_print_rate or doc.flags.show_inclusive_tax_in_print -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t\t{{ row.description }}\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t\t</td>\n\t\t\t<tr>\n\t\t {%- endif -%}\n\t\t{%- endfor -%}\n\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.rounded_total -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Rounded Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"rounded_total\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ _(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"paid_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- if doc.change_amount -%}\n\t\t\t<tr>\n\t\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t\t<b>{{ _(\"Change Amount\") }}</b>\n\t\t\t\t</td>\n\t\t\t\t<td class=\"text-right\">\n\t\t\t\t\t{{ doc.get_formatted(\"change_amount\") }}\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t{%- endif -%}\n\t</tbody>\n</table>\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
|
||||
"idx": 1,
|
||||
"line_breaks": 0,
|
||||
"modified": "2018-01-12 11:18:54.229254",
|
||||
"modified": "2018-03-20 14:24:12.394354",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice",
|
||||
|
||||
@@ -14,7 +14,13 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"fieldname":"supplier",
|
||||
"label": __("Supplier"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Supplier"
|
||||
"options": "Supplier",
|
||||
on_change: () => {
|
||||
var supplier = frappe.query_report_filters_by_name.supplier.get_value();
|
||||
frappe.db.get_value('Supplier', supplier, "tax_id", function(value) {
|
||||
frappe.query_report_filters_by_name.tax_id.set_value(value["tax_id"]);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"report_date",
|
||||
@@ -52,6 +58,12 @@ frappe.query_reports["Accounts Payable"] = {
|
||||
"fieldtype": "Int",
|
||||
"default": "90",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"tax_id",
|
||||
"label": __("Tax Id"),
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1
|
||||
}
|
||||
],
|
||||
onload: function(report) {
|
||||
|
||||
@@ -2,17 +2,35 @@
|
||||
<style>
|
||||
@media screen {
|
||||
.print-format {
|
||||
padding: 8mm;
|
||||
margin:4mm;
|
||||
font-size:10px;
|
||||
padding: 4mm;
|
||||
font-size: 8.0pt !important;
|
||||
font-family: Tahoma, sans-serif;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% } %}
|
||||
<style>
|
||||
.print-format {
|
||||
padding: 4mm;
|
||||
font-size: 8.0pt !important;
|
||||
font-family: Tahoma, sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<h2 class="text-center">{%= __(report.report_name) %}</h2>
|
||||
<h4 class="text-center">{%= filters.customer || filters.supplier %} </h4>
|
||||
<h4 class="text-center">
|
||||
{% if (filters.customer_name) { %}
|
||||
{%= filters.customer_name %}
|
||||
{% } else { %}
|
||||
{%= filters.customer || filters.supplier %}
|
||||
{% } %}
|
||||
</h4>
|
||||
<h6 class="text-center">
|
||||
{% if (filters.tax_id) { %}
|
||||
{%= __("Tax Id: ")%} {%= filters.tax_id %}
|
||||
{% } %}
|
||||
</h6>
|
||||
<h5 class="text-center">
|
||||
{%= __(filters.ageing_based_on) %}
|
||||
{%= __("Until") %}
|
||||
@@ -27,7 +45,7 @@
|
||||
var range4 = report.columns[14].label;
|
||||
%}
|
||||
{% if(balance_row) { %}
|
||||
<table class="table table-bordered table-condensed table-sm small">
|
||||
<table class="table table-bordered table-condensed">
|
||||
<caption class="text-right">(Amount in {%= data[0][__("currency")] || "" %})</caption>
|
||||
<colgroup>
|
||||
<col style="width: 30mm;">
|
||||
@@ -86,8 +104,8 @@
|
||||
<thead>
|
||||
<tr>
|
||||
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
|
||||
<th style="width: 10%">{%= __("Date") %}</th>
|
||||
<th style="width: 15%">{%= __("Ref") %}</th>
|
||||
<th style="width: 18%">{%= __("Date") %}</th>
|
||||
<th style="width: 17%">{%= __("Reference") %}</th>
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
|
||||
{% } %}
|
||||
@@ -120,10 +138,15 @@
|
||||
<tr>
|
||||
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
|
||||
{% if(data[i][__("Customer")] || data[i][__("Supplier")]) { %}
|
||||
<td>{%= dateutil.str_to_user(data[i][__("Posting Date")]) %}</td>
|
||||
<td>{%= data[i][__("Voucher Type")] %}
|
||||
<br>{%= data[i][__("Voucher No")] %}</td>
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<td>{%= dateutil.str_to_user(data[i]["posting_date"]) %}</td>
|
||||
<td>
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
{%= data[i]["voucher_type"] %}
|
||||
<br>
|
||||
{% } %}
|
||||
{%= data[i]["voucher_no"] %}
|
||||
</td>
|
||||
{% if(!filters.show_pdc_in_print) { %}
|
||||
<td>
|
||||
{% if(!(filters.customer || filters.supplier)) { %}
|
||||
{%= data[i][__("Customer")] || data[i][__("Supplier")] %}
|
||||
@@ -215,4 +238,4 @@
|
||||
{% } %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="text-right text-muted">{{ __("Printed On") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||
<p class="text-right text-muted">{{ __("Printed On ") }}{%= dateutil.str_to_user(dateutil.get_datetime_as_string()) %}</p>
|
||||
@@ -14,7 +14,14 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"fieldname":"customer",
|
||||
"label": __("Customer"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Customer"
|
||||
"options": "Customer",
|
||||
on_change: () => {
|
||||
var customer = frappe.query_report_filters_by_name.customer.get_value();
|
||||
frappe.db.get_value('Customer', customer, ["tax_id", "customer_name"], function(value) {
|
||||
frappe.query_report_filters_by_name.tax_id.set_value(value["tax_id"]);
|
||||
frappe.query_report_filters_by_name.customer_name.set_value(value["customer_name"]);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"customer_group",
|
||||
@@ -69,6 +76,18 @@ frappe.query_reports["Accounts Receivable"] = {
|
||||
"fieldname":"show_pdc_in_print",
|
||||
"label": __("Show PDC in Print"),
|
||||
"fieldtype": "Check",
|
||||
},
|
||||
{
|
||||
"fieldname":"tax_id",
|
||||
"label": __("Tax Id"),
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"customer_name",
|
||||
"label": __("Customer Name"),
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
@@ -22,13 +22,35 @@ class ReceivablePayableReport(object):
|
||||
return columns, data, None, chart
|
||||
|
||||
def get_columns(self, party_naming_by, args):
|
||||
columns = [_("Posting Date") + ":Date:80", _(args.get("party_type")) + ":Link/" + args.get("party_type") + ":200"]
|
||||
columns = []
|
||||
columns.append({
|
||||
"label": _("Posting Date"),
|
||||
"fieldtype": "Date",
|
||||
"fieldname": "posting_date",
|
||||
"width": 90
|
||||
})
|
||||
|
||||
columns += [_(args.get("party_type")) + ":Link/" + args.get("party_type") + ":200"]
|
||||
|
||||
if party_naming_by == "Naming Series":
|
||||
columns += [args.get("party_type") + " Name::110"]
|
||||
|
||||
columns += [_("Voucher Type") + "::110", _("Voucher No") + ":Dynamic Link/"+_("Voucher Type")+":120",
|
||||
_("Due Date") + ":Date:80"]
|
||||
columns.append({
|
||||
"label": _("Voucher Type"),
|
||||
"fieldtype": "Data",
|
||||
"fieldname": "voucher_type",
|
||||
"width": 110
|
||||
})
|
||||
|
||||
columns.append({
|
||||
"label": _("Voucher No"),
|
||||
"fieldtype": "Dynamic Link",
|
||||
"fieldname": "voucher_no",
|
||||
"width": 110,
|
||||
"options": "voucher_type",
|
||||
})
|
||||
|
||||
columns += [_("Due Date") + ":Date:80"]
|
||||
|
||||
if args.get("party_type") == "Supplier":
|
||||
columns += [_("Bill No") + "::80", _("Bill Date") + ":Date:80"]
|
||||
@@ -114,7 +136,7 @@ class ReceivablePayableReport(object):
|
||||
return_entries = self.get_return_entries(args.get("party_type"))
|
||||
|
||||
data = []
|
||||
pdc_details = get_pdc_details(args.get("party_type"))
|
||||
pdc_details = get_pdc_details(args.get("party_type"), self.filters.report_date)
|
||||
|
||||
for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
|
||||
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
|
||||
@@ -160,6 +182,7 @@ class ReceivablePayableReport(object):
|
||||
row.append(company_currency)
|
||||
|
||||
pdc = pdc_details.get((gle.voucher_no, gle.party), {})
|
||||
|
||||
remaining_balance = outstanding_amount - flt(pdc.get("pdc_amount"))
|
||||
row += [pdc.get("pdc_date"), pdc.get("pdc_ref"),
|
||||
flt(pdc.get("pdc_amount")), remaining_balance]
|
||||
@@ -376,7 +399,7 @@ def get_ageing_data(first_range, second_range, third_range, age_as_on, entry_dat
|
||||
|
||||
return [age] + outstanding_range
|
||||
|
||||
def get_pdc_details(party_type):
|
||||
def get_pdc_details(party_type, report_date):
|
||||
pdc_details = frappe._dict()
|
||||
|
||||
for pdc in frappe.db.sql("""
|
||||
@@ -389,13 +412,14 @@ def get_pdc_details(party_type):
|
||||
on
|
||||
(pref.parent = pent.name)
|
||||
where
|
||||
pent.docstatus < 2 and pent.reference_date >= pent.posting_date
|
||||
pent.docstatus < 2 and pent.reference_date >= %s
|
||||
and pent.party_type = %s
|
||||
group by pent.party, pref.reference_name""", party_type, as_dict=1):
|
||||
group by pent.party, pref.reference_name""", (report_date, party_type), as_dict=1):
|
||||
pdc_details.setdefault((pdc.invoice_no, pdc.party), pdc)
|
||||
|
||||
if scrub(party_type):
|
||||
amount_field = "jea.debit_in_account_currency + jea.credit_in_account_currency"
|
||||
amount_field = ("jea.debit_in_account_currency"
|
||||
if party_type == 'Supplier' else "jea.credit_in_account_currency")
|
||||
else:
|
||||
amount_field = "jea.debit + jea.credit"
|
||||
|
||||
@@ -409,9 +433,9 @@ def get_pdc_details(party_type):
|
||||
on
|
||||
(jea.parent = je.name)
|
||||
where
|
||||
je.docstatus < 2 and je.cheque_date >= je.posting_date
|
||||
je.docstatus < 2 and je.cheque_date >= %s
|
||||
and jea.party_type = %s
|
||||
group by jea.party, jea.reference_name""".format(amount_field), party_type, as_dict=1):
|
||||
group by jea.party, jea.reference_name""".format(amount_field), (report_date, party_type), as_dict=1):
|
||||
if (pdc.invoice_no, pdc.party) in pdc_details:
|
||||
pdc_details[(pdc.invoice_no, pdc.party)]["pdc_amount"] += pdc.pdc_amount
|
||||
else:
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
from erpnext.accounts.report.accounts_receivable.accounts_receivable import ReceivablePayableReport
|
||||
|
||||
class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
@@ -88,7 +89,8 @@ class AccountsReceivableSummary(ReceivablePayableReport):
|
||||
})
|
||||
)
|
||||
for k in party_total[d.party].keys():
|
||||
party_total[d.party][k] += d.get(k, 0)
|
||||
if k != "currency":
|
||||
party_total[d.party][k] += flt(d.get(k, 0))
|
||||
|
||||
party_total[d.party].currency = d.currency
|
||||
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
{%= filters.account %}
|
||||
{% } %}
|
||||
</h4>
|
||||
|
||||
<h6 class="text-center">
|
||||
{% if (filters.tax_id) { %}
|
||||
{%= __("Tax Id: ")%} {%= filters.tax_id %}
|
||||
{% } %}
|
||||
</h6>
|
||||
|
||||
<h5 class="text-center">
|
||||
{%= dateutil.str_to_user(filters.from_date) %}
|
||||
{%= __("to") %}
|
||||
|
||||
@@ -61,7 +61,10 @@ frappe.query_reports["General Ledger"] = {
|
||||
"label": __("Party Type"),
|
||||
"fieldtype": "Link",
|
||||
"options": "Party Type",
|
||||
"default": ""
|
||||
"default": "",
|
||||
on_change: function() {
|
||||
frappe.query_report_filters_by_name.party.set_value("");
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname":"party",
|
||||
@@ -82,11 +85,16 @@ frappe.query_reports["General Ledger"] = {
|
||||
frappe.query_report_filters_by_name.party_name.set_value("");
|
||||
return;
|
||||
}
|
||||
|
||||
var fieldname = frappe.scrub(party_type) + "_name";
|
||||
var fieldname = erpnext.utils.get_party_name(party_type) || "name";
|
||||
frappe.db.get_value(party_type, party, fieldname, function(value) {
|
||||
frappe.query_report_filters_by_name.party_name.set_value(value[fieldname]);
|
||||
});
|
||||
|
||||
if (party_type === "Customer" || party_type === "Supplier") {
|
||||
frappe.db.get_value(party_type, party, "tax_id", function(value) {
|
||||
frappe.query_report_filters_by_name.tax_id.set_value(value["tax_id"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -95,6 +103,12 @@ frappe.query_reports["General Ledger"] = {
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"tax_id",
|
||||
"label": __("Tax Id"),
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"group_by_voucher",
|
||||
"label": __("Group by Voucher"),
|
||||
|
||||
@@ -71,8 +71,8 @@ def set_account_currency(filters):
|
||||
if gle_currency:
|
||||
account_currency = gle_currency
|
||||
else:
|
||||
account_currency = None if filters.party_type == "Employee" else \
|
||||
frappe.db.get_value(filters.party_type, filters.party, "default_currency")
|
||||
account_currency = (None if filters.party_type in ["Employee", "Student", "Shareholder", "Member"] else
|
||||
frappe.db.get_value(filters.party_type, filters.party, "default_currency"))
|
||||
|
||||
filters["account_currency"] = account_currency or filters.company_currency
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
|
||||
|
||||
row += [
|
||||
supplier_details.get(inv.supplier), # supplier_type
|
||||
inv.credit_to, inv.mode_of_payment, ", ".join(project),
|
||||
inv.tax_id, inv.credit_to, inv.mode_of_payment, ", ".join(project),
|
||||
inv.bill_no, inv.bill_date, inv.remarks,
|
||||
", ".join(purchase_order), ", ".join(purchase_receipt), company_currency
|
||||
]
|
||||
@@ -83,7 +83,7 @@ def get_columns(invoice_list, additional_table_columns):
|
||||
columns += additional_table_columns
|
||||
|
||||
columns += [
|
||||
_("Supplier Type") + ":Link/Supplier Type:120", _("Payable Account") + ":Link/Account:120",
|
||||
_("Supplier Type") + ":Link/Supplier Type:120", _("Tax Id") + "::80", _("Payable Account") + ":Link/Account:120",
|
||||
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
|
||||
_("Bill No") + "::120", _("Bill Date") + ":Date:80", _("Remarks") + "::150",
|
||||
_("Purchase Order") + ":Link/Purchase Order:100",
|
||||
@@ -143,7 +143,7 @@ def get_invoices(filters, additional_query_columns):
|
||||
conditions = get_conditions(filters)
|
||||
return frappe.db.sql("""
|
||||
select
|
||||
name, posting_date, credit_to, supplier, supplier_name, bill_no, bill_date,
|
||||
name, posting_date, credit_to, supplier, supplier_name, tax_id, bill_no, bill_date,
|
||||
remarks, base_net_total, base_grand_total, outstanding_amount,
|
||||
mode_of_payment {0}
|
||||
from `tabPurchase Invoice`
|
||||
|
||||
@@ -47,6 +47,7 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
|
||||
row +=[
|
||||
inv.get("customer_group"),
|
||||
inv.get("territory"),
|
||||
inv.get("tax_id"),
|
||||
inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])),
|
||||
inv.project, inv.owner, inv.remarks,
|
||||
", ".join(sales_order), ", ".join(delivery_note),", ".join(cost_center),
|
||||
@@ -89,7 +90,7 @@ def get_columns(invoice_list, additional_table_columns):
|
||||
|
||||
columns +=[
|
||||
_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
|
||||
_("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
|
||||
_("Tax Id") + "::80", _("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
|
||||
_("Project") +":Link/Project:80", _("Owner") + "::150", _("Remarks") + "::150",
|
||||
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
|
||||
_("Cost Center") + ":Link/Cost Center:100", _("Warehouse") + ":Link/Warehouse:100",
|
||||
@@ -161,7 +162,7 @@ def get_invoices(filters, additional_query_columns):
|
||||
conditions = get_conditions(filters)
|
||||
return frappe.db.sql("""
|
||||
select name, posting_date, debit_to, project, customer,
|
||||
customer_name, owner, remarks, territory, customer_group,
|
||||
customer_name, owner, remarks, territory, tax_id, customer_group,
|
||||
base_net_total, base_grand_total, base_rounded_total, outstanding_amount {0}
|
||||
from `tabSales Invoice`
|
||||
where docstatus = 1 %s order by posting_date desc, name desc""".format(additional_query_columns or '') %
|
||||
|
||||
@@ -217,7 +217,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
|
||||
me.frm.doc['supplied_items'].forEach((item, index) => {
|
||||
if (item.rm_item_code && item.main_item_code) {
|
||||
me.raw_material_data.push ({
|
||||
'name':index,
|
||||
'name':item.name,
|
||||
'item_code': item.main_item_code,
|
||||
'rm_item_code': item.rm_item_code,
|
||||
'item_name': item.rm_item_code,
|
||||
|
||||
@@ -135,6 +135,10 @@ def get_data():
|
||||
"name": "Assessment Plan Status",
|
||||
"doctype": "Assessment Plan"
|
||||
},
|
||||
{
|
||||
"type": "doctype",
|
||||
"name": "Student Report Generation Tool"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -232,7 +232,7 @@ class AccountsController(TransactionBase):
|
||||
|
||||
tax_master_doctype = self.meta.get_field("taxes_and_charges").options
|
||||
|
||||
if self.is_new() and not self.get("taxes"):
|
||||
if (self.is_new() or self.is_pos_profile_changed()) and not self.get("taxes"):
|
||||
if self.company and not self.get("taxes_and_charges"):
|
||||
# get the default tax master
|
||||
self.taxes_and_charges = frappe.db.get_value(tax_master_doctype,
|
||||
@@ -240,6 +240,11 @@ class AccountsController(TransactionBase):
|
||||
|
||||
self.append_taxes_from_master(tax_master_doctype)
|
||||
|
||||
def is_pos_profile_changed(self):
|
||||
if (self.doctype == 'Sales Invoice' and self.is_pos and
|
||||
self.pos_profile != frappe.db.get_value('Sales Invoice', self.name, 'pos_profile')):
|
||||
return True
|
||||
|
||||
def append_taxes_from_master(self, tax_master_doctype=None):
|
||||
if self.get("taxes_and_charges"):
|
||||
if not tax_master_doctype:
|
||||
@@ -666,7 +671,9 @@ class AccountsController(TransactionBase):
|
||||
self.remove(item)
|
||||
|
||||
def set_payment_schedule(self):
|
||||
if self.doctype == 'Sales Invoice' and self.is_pos: return
|
||||
if self.doctype == 'Sales Invoice' and self.is_pos:
|
||||
self.payment_terms_template = ''
|
||||
return
|
||||
|
||||
posting_date = self.get("bill_date") or self.get("posting_date") or self.get("transaction_date")
|
||||
date = self.get("due_date")
|
||||
|
||||
@@ -152,9 +152,15 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
|
||||
conditions = []
|
||||
|
||||
return frappe.db.sql("""select tabItem.name, tabItem.item_group,
|
||||
description_cond = ''
|
||||
if frappe.db.count('Item', cache=True) < 50000:
|
||||
# scan description only if items are less than 50000
|
||||
description_cond = 'or tabItem.description LIKE %(txt)s'
|
||||
|
||||
return frappe.db.sql("""select tabItem.name,
|
||||
if(length(tabItem.item_name) > 40,
|
||||
concat(substr(tabItem.item_name, 1, 40), "..."), item_name) as item_name,
|
||||
tabItem.item_group,
|
||||
if(length(tabItem.description) > 40, \
|
||||
concat(substr(tabItem.description, 1, 40), "..."), description) as decription
|
||||
from tabItem
|
||||
@@ -166,7 +172,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
or tabItem.item_group LIKE %(txt)s
|
||||
or tabItem.item_name LIKE %(txt)s
|
||||
or tabItem.barcode LIKE %(txt)s
|
||||
or tabItem.description LIKE %(txt)s)
|
||||
{description_cond})
|
||||
{fcond} {mcond}
|
||||
order by
|
||||
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
|
||||
@@ -176,7 +182,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
|
||||
limit %(start)s, %(page_len)s """.format(
|
||||
key=searchfield,
|
||||
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
|
||||
mcond=get_match_cond(doctype).replace('%', '%%')),
|
||||
mcond=get_match_cond(doctype).replace('%', '%%'),
|
||||
description_cond = description_cond),
|
||||
{
|
||||
"today": nowdate(),
|
||||
"txt": "%%%s%%" % txt,
|
||||
|
||||
@@ -83,15 +83,15 @@ def validate_returned_items(doc):
|
||||
else:
|
||||
ref = valid_items.get(d.item_code, frappe._dict())
|
||||
validate_quantity(doc, d, ref, valid_items, already_returned_items)
|
||||
|
||||
|
||||
if ref.rate and doc.doctype in ("Delivery Note", "Sales Invoice") and flt(d.rate) > ref.rate:
|
||||
frappe.throw(_("Row # {0}: Rate cannot be greater than the rate used in {1} {2}")
|
||||
.format(d.idx, doc.doctype, doc.return_against))
|
||||
|
||||
|
||||
elif ref.batch_no and d.batch_no not in ref.batch_no:
|
||||
frappe.throw(_("Row # {0}: Batch No must be same as {1} {2}")
|
||||
.format(d.idx, doc.doctype, doc.return_against))
|
||||
|
||||
|
||||
elif ref.serial_no:
|
||||
if not d.serial_no:
|
||||
frappe.throw(_("Row # {0}: Serial No is mandatory").format(d.idx))
|
||||
@@ -120,25 +120,30 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
|
||||
|
||||
for column in fields:
|
||||
returned_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0
|
||||
reference_qty = (ref.get(column) if column == 'stock_qty'
|
||||
else ref.get(column) * ref.get("conversion_factor", 1.0))
|
||||
|
||||
if column == 'stock_qty':
|
||||
reference_qty = ref.get(column)
|
||||
current_stock_qty = args.get(column)
|
||||
else:
|
||||
reference_qty = ref.get(column) * ref.get("conversion_factor", 1.0)
|
||||
current_stock_qty = args.get(column) * args.get("conversion_factor", 1.0)
|
||||
|
||||
max_returnable_qty = flt(reference_qty) - returned_qty
|
||||
label = column.replace('_', ' ').title()
|
||||
|
||||
if reference_qty:
|
||||
if reference_qty:
|
||||
if flt(args.get(column)) > 0:
|
||||
frappe.throw(_("{0} must be negative in return document").format(label))
|
||||
elif returned_qty >= reference_qty and args.get(column):
|
||||
frappe.throw(_("Item {0} has already been returned")
|
||||
.format(args.item_code), StockOverReturnError)
|
||||
elif (abs(args.get(column)) * args.get("conversion_factor", 1.0)) > max_returnable_qty:
|
||||
elif abs(current_stock_qty) > max_returnable_qty:
|
||||
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
|
||||
.format(args.idx, reference_qty, args.item_code), StockOverReturnError)
|
||||
|
||||
def get_ref_item_dict(valid_items, ref_item_row):
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
|
||||
|
||||
valid_items.setdefault(ref_item_row.item_code, frappe._dict({
|
||||
"qty": 0,
|
||||
"rate": 0,
|
||||
@@ -160,10 +165,10 @@ def get_ref_item_dict(valid_items, ref_item_row):
|
||||
|
||||
if ref_item_row.get("serial_no"):
|
||||
item_dict["serial_no"] += get_serial_nos(ref_item_row.serial_no)
|
||||
|
||||
|
||||
if ref_item_row.get("batch_no"):
|
||||
item_dict["batch_no"].append(ref_item_row.batch_no)
|
||||
|
||||
|
||||
return valid_items
|
||||
|
||||
def get_already_returned_items(doc):
|
||||
|
||||
@@ -330,7 +330,7 @@ class SellingController(StockController):
|
||||
self.make_sl_entries(sl_entries)
|
||||
|
||||
def set_po_nos(self):
|
||||
if self.doctype in ("Delivery Note", "Sales Invoice"):
|
||||
if self.doctype in ("Delivery Note", "Sales Invoice") and hasattr(self, "items"):
|
||||
ref_fieldname = "against_sales_order" if self.doctype == "Delivery Note" else "sales_order"
|
||||
sales_orders = list(set([d.get(ref_fieldname) for d in self.items if d.get(ref_fieldname)]))
|
||||
if sales_orders:
|
||||
|
||||
@@ -285,7 +285,7 @@ class StatusUpdater(Document):
|
||||
ifnull((select
|
||||
ifnull(sum(if(%(target_ref_field)s > %(target_field)s, abs(%(target_field)s), abs(%(target_ref_field)s))), 0)
|
||||
/ sum(abs(%(target_ref_field)s)) * 100
|
||||
from `tab%(target_dt)s` where parent="%(name)s"), 0), 2)
|
||||
from `tab%(target_dt)s` where parent="%(name)s" having sum(abs(%(target_ref_field)s)) > 0), 0), 6)
|
||||
%(update_modified)s
|
||||
where name='%(name)s'""" % args)
|
||||
|
||||
@@ -293,7 +293,7 @@ class StatusUpdater(Document):
|
||||
if args.get('status_field'):
|
||||
frappe.db.sql("""update `tab%(target_parent_dt)s`
|
||||
set %(status_field)s = if(%(target_parent_field)s<0.001,
|
||||
'Not %(keyword)s', if(%(target_parent_field)s>=99.99,
|
||||
'Not %(keyword)s', if(%(target_parent_field)s>=99.999999,
|
||||
'Fully %(keyword)s', 'Partly %(keyword)s'))
|
||||
where name='%(name)s'""" % args)
|
||||
|
||||
|
||||
@@ -252,7 +252,7 @@ class StockController(AccountsController):
|
||||
"company": self.company,
|
||||
"batch_no": cstr(d.get("batch_no")).strip(),
|
||||
"serial_no": d.get("serial_no"),
|
||||
"project": d.get("project"),
|
||||
"project": d.get("project") or self.get('project'),
|
||||
"is_cancelled": self.docstatus==2 and "Yes" or "No"
|
||||
})
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ class calculate_taxes_and_totals(object):
|
||||
self.set_item_wise_tax_breakup()
|
||||
|
||||
def _calculate(self):
|
||||
self.validate_conversion_rate()
|
||||
self.calculate_item_values()
|
||||
self.initialize_taxes()
|
||||
self.determine_exclusive_rate()
|
||||
@@ -557,7 +558,8 @@ def get_itemised_tax_breakup_html(doc):
|
||||
itemised_tax=itemised_tax,
|
||||
itemised_taxable_amount=itemised_taxable_amount,
|
||||
tax_accounts=tax_accounts,
|
||||
company_currency=erpnext.get_company_currency(doc.company)
|
||||
conversion_rate=doc.conversion_rate,
|
||||
currency=doc.currency
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -20,6 +20,10 @@ frappe.ui.form.on("Opportunity", {
|
||||
frm.trigger('set_contact_link');
|
||||
},
|
||||
|
||||
with_items: function(frm) {
|
||||
frm.trigger('toggle_mandatory');
|
||||
},
|
||||
|
||||
customer_address: function(frm, cdt, cdn) {
|
||||
erpnext.utils.get_address_display(frm, 'customer_address', 'address_display', false);
|
||||
},
|
||||
@@ -35,6 +39,7 @@ frappe.ui.form.on("Opportunity", {
|
||||
var doc = frm.doc;
|
||||
frm.events.enquiry_from(frm);
|
||||
frm.trigger('set_contact_link');
|
||||
frm.trigger('toggle_mandatory');
|
||||
erpnext.toggle_naming_series();
|
||||
|
||||
if(!doc.__islocal && doc.status!=="Lost") {
|
||||
@@ -84,6 +89,10 @@ frappe.ui.form.on("Opportunity", {
|
||||
method: "erpnext.crm.doctype.opportunity.opportunity.make_supplier_quotation",
|
||||
frm: cur_frm
|
||||
})
|
||||
},
|
||||
|
||||
toggle_mandatory: function(frm) {
|
||||
frm.toggle_reqd("items", frm.doc.with_items ? 1:0);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -34,14 +34,14 @@ def work():
|
||||
payroll_entry.salary_slip_based_on_timesheet = 0
|
||||
payroll_entry.create_salary_slips()
|
||||
payroll_entry.submit_salary_slips()
|
||||
payroll_entry.make_accural_jv_entry()
|
||||
payroll_entry.make_accrual_jv_entry()
|
||||
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
||||
# reference_number=random_string(10))
|
||||
|
||||
payroll_entry.salary_slip_based_on_timesheet = 1
|
||||
payroll_entry.create_salary_slips()
|
||||
payroll_entry.submit_salary_slips()
|
||||
payroll_entry.make_accural_jv_entry()
|
||||
payroll_entry.make_accrual_jv_entry()
|
||||
# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
|
||||
# reference_number=random_string(10))
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ We can also send the feedback request to Customer/User without configuring the
|
||||
Feedback Trigger.
|
||||
|
||||
To request a feedback manually go to respective document e.g. Sales Order, Issue etc.
|
||||
and click on Ask a Feedback option in Menu.
|
||||
and click on Request Feedback option in Menu.
|
||||
|
||||
<img class="screenshot" alt="Setting Condition" src="/docs/assets/img/setup/feedback/manual-feedback-request-option.png">
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ In the document, you can select multiple Purchase Receipts and fetch all items f
|
||||
|
||||
<img class="screenshot" alt="Landed Cost Vouher" src="/docs/assets/img/stock/landed-cost.png">
|
||||
|
||||
### What happend on submission?
|
||||
### What happens on submission?
|
||||
|
||||
1. On submission of Landed Cost Voucher, the applicable landed cost charges are updated in Purchase Receipt Item table.
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@ frappe.ui.form.on("Program Enrollment Tool", {
|
||||
});
|
||||
},
|
||||
|
||||
get_students_from: function(frm) {
|
||||
if (frm.doc.get_students_from == "Student Applicant") {
|
||||
frm.dashboard.add_comment(__('Only the Student Applicant with the status "Approved" will be selected in the table below.'));
|
||||
}
|
||||
},
|
||||
|
||||
"get_students": function(frm) {
|
||||
frm.set_value("students",[]);
|
||||
frappe.call({
|
||||
|
||||
@@ -26,7 +26,7 @@ class ProgramEnrollmentTool(Document):
|
||||
elif self.get_students_from == "Program Enrollment":
|
||||
condition2 = 'and student_batch_name=%(student_batch)s' if self.student_batch else " "
|
||||
students = frappe.db.sql('''select student, student_name, student_batch_name from `tabProgram Enrollment`
|
||||
where program=%(program)s and academic_year=%(academic_year)s {0} {1}'''
|
||||
where program=%(program)s and academic_year=%(academic_year)s {0} {1} and docstatus != 2'''
|
||||
.format(condition, condition2), self.as_dict(), as_dict=1)
|
||||
|
||||
student_list = [d.student for d in students]
|
||||
|
||||
@@ -22,14 +22,16 @@ class Student(Document):
|
||||
def update_student_name_in_linked_doctype(self):
|
||||
linked_doctypes = get_linked_doctypes("Student")
|
||||
for d in linked_doctypes:
|
||||
if "student_name" in [f.fieldname for f in frappe.get_meta(d).fields]:
|
||||
frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
|
||||
.format(d, linked_doctypes[d]["fieldname"]),(self.title, self.name))
|
||||
meta = frappe.get_meta(d)
|
||||
if not meta.issingle:
|
||||
if "student_name" in [f.fieldname for f in meta.fields]:
|
||||
frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
|
||||
.format(d, linked_doctypes[d]["fieldname"]),(self.title, self.name))
|
||||
|
||||
if "child_doctype" in linked_doctypes[d].keys() and "student_name" in \
|
||||
[f.fieldname for f in frappe.get_meta(linked_doctypes[d]["child_doctype"]).fields]:
|
||||
frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
|
||||
.format(linked_doctypes[d]["child_doctype"], linked_doctypes[d]["fieldname"]),(self.title, self.name))
|
||||
if "child_doctype" in linked_doctypes[d].keys() and "student_name" in \
|
||||
[f.fieldname for f in frappe.get_meta(linked_doctypes[d]["child_doctype"]).fields]:
|
||||
frappe.db.sql("""UPDATE `tab{0}` set student_name = %s where {1} = %s"""
|
||||
.format(linked_doctypes[d]["child_doctype"], linked_doctypes[d]["fieldname"]),(self.title, self.name))
|
||||
|
||||
def check_unique(self):
|
||||
"""Validates if the Student Applicant is Unique"""
|
||||
|
||||
@@ -82,36 +82,39 @@ frappe.ui.form.on("Student Group", {
|
||||
max_roll_no = d.group_roll_number;
|
||||
}
|
||||
});
|
||||
frappe.call({
|
||||
method: "erpnext.education.doctype.student_group.student_group.get_students",
|
||||
args: {
|
||||
"academic_year": frm.doc.academic_year,
|
||||
"academic_term": frm.doc.academic_term,
|
||||
"group_based_on": frm.doc.group_based_on,
|
||||
"program": frm.doc.program,
|
||||
"batch" : frm.doc.batch,
|
||||
"course": frm.doc.course
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
$.each(r.message, function(i, d) {
|
||||
if(!in_list(student_list, d.student)) {
|
||||
var s = frm.add_child("students");
|
||||
s.student = d.student;
|
||||
s.student_name = d.student_name;
|
||||
if (d.active === 0) {
|
||||
s.active = 0;
|
||||
|
||||
if(frm.doc.academic_year) {
|
||||
frappe.call({
|
||||
method: "erpnext.education.doctype.student_group.student_group.get_students",
|
||||
args: {
|
||||
"academic_year": frm.doc.academic_year,
|
||||
"academic_term": frm.doc.academic_term,
|
||||
"group_based_on": frm.doc.group_based_on,
|
||||
"program": frm.doc.program,
|
||||
"batch" : frm.doc.batch,
|
||||
"course": frm.doc.course
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r.message) {
|
||||
$.each(r.message, function(i, d) {
|
||||
if(!in_list(student_list, d.student)) {
|
||||
var s = frm.add_child("students");
|
||||
s.student = d.student;
|
||||
s.student_name = d.student_name;
|
||||
if (d.active === 0) {
|
||||
s.active = 0;
|
||||
}
|
||||
s.group_roll_number = ++max_roll_no;
|
||||
}
|
||||
s.group_roll_number = ++max_roll_no;
|
||||
}
|
||||
});
|
||||
refresh_field("students");
|
||||
frm.save();
|
||||
} else {
|
||||
frappe.msgprint(__("Student Group is already updated."))
|
||||
});
|
||||
refresh_field("students");
|
||||
frm.save();
|
||||
} else {
|
||||
frappe.msgprint(__("Student Group is already updated."))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
frappe.msgprint(__("Select students manually for the Activity based Group"));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
<style>
|
||||
@media screen {
|
||||
.print-format-gutter {
|
||||
background-color: #ddd;
|
||||
padding: 15px 0px;
|
||||
}
|
||||
.print-format {
|
||||
background-color: white;
|
||||
box-shadow: 0px 0px 9px rgba(0,0,0,0.5);
|
||||
max-width: 8.3in;
|
||||
min-height: 11.69in;
|
||||
padding: 0.75in;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.print-format.landscape {
|
||||
max-width: 11.69in;
|
||||
padding: 0.2in;
|
||||
}
|
||||
|
||||
.page-break {
|
||||
padding: 30px 0px;
|
||||
border-bottom: 1px dashed #888;
|
||||
}
|
||||
|
||||
.page-break:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.page-break:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
/* mozilla hack for images in table */
|
||||
body:last-child .print-format td img {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
@media(max-width: 767px) {
|
||||
.print-format {
|
||||
padding: 0.2in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
.print-format p {
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.data-field {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.data-field .value {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.important .value {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.important label {
|
||||
line-height: 1.8;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.table {
|
||||
margin: 20px 0px;
|
||||
}
|
||||
|
||||
.square-image {
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding: 50% 0;
|
||||
background-size: contain;
|
||||
/*background-size: cover;*/
|
||||
background-repeat: no-repeat !important;
|
||||
background-position: center center;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.print-item-image {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.pdf-variables,
|
||||
.pdf-variable,
|
||||
.visible-pdf {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.print-format {
|
||||
font-size: 9pt;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, "Open Sans", sans-serif;
|
||||
-webkit-print-color-adjust:exact;
|
||||
}
|
||||
|
||||
.page-break {
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
.print-heading {
|
||||
border-bottom: 1px solid #aaa;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.print-heading h2 {
|
||||
margin: 0px;
|
||||
}
|
||||
.print-heading h4 {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
table.no-border, table.no-border td {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.print-format label {
|
||||
/* wkhtmltopdf breaks label into multiple lines when it is inline-block */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.print-format img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.print-format table td > .primary:first-child {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.print-format td, .print-format th {
|
||||
vertical-align: top !important;
|
||||
padding: 6px !important;
|
||||
}
|
||||
|
||||
.print-format p {
|
||||
margin: 3px 0px 3px;
|
||||
}
|
||||
|
||||
table td div {
|
||||
|
||||
/* needed to avoid partial cutting of text between page break in wkhtmltopdf */
|
||||
page-break-inside: avoid !important;
|
||||
|
||||
}
|
||||
|
||||
/* hack for webkit specific browser */
|
||||
@media (-webkit-min-device-pixel-ratio:0) {
|
||||
thead, tfoot { display: table-row-group; }
|
||||
}
|
||||
|
||||
[document-status] {
|
||||
margin-bottom: 5mm;
|
||||
}
|
||||
|
||||
.signature-img {
|
||||
background: #fff;
|
||||
border-radius: 3px;
|
||||
margin-top: 5px;
|
||||
max-height: 150px;
|
||||
}
|
||||
|
||||
.print-heading {
|
||||
text-align: right;
|
||||
text-transform: uppercase;
|
||||
color: #666;
|
||||
padding-bottom: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #d1d8dd;
|
||||
}
|
||||
|
||||
.print-heading h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.print-format th {
|
||||
background-color: #eee !important;
|
||||
border-bottom: 0px !important;
|
||||
}
|
||||
|
||||
/* modern format: for-test */
|
||||
|
||||
.pbi_avoid {
|
||||
page-break-inside: avoid !important;
|
||||
}
|
||||
.pb_before {
|
||||
page-break-before: always !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<div class="page-break">
|
||||
|
||||
<div id="header-html" class="hidden-pdf">
|
||||
|
||||
{% if letterhead and add_letterhead %}
|
||||
<div class="">{{ letterhead }}</div>
|
||||
{% endif %}
|
||||
<div class="print-heading">
|
||||
<h2>{{ _("Student Report Card") }}<br>
|
||||
<small>{{ doc.student_name }}</small>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row section-break">
|
||||
<div class="col-xs-6 column-break">
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-5">
|
||||
<label>{{ _("Student ID: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-7">
|
||||
{{ doc.students[0] }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-5">
|
||||
<label>{{ _("Student Name: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-7">
|
||||
{{ doc.student_name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-5">
|
||||
<label>{{ _("Program: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-7">
|
||||
{{ doc.program }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-5">
|
||||
<label>{{ _("Batch: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-7">
|
||||
{{ doc.student_batch }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 column-break">
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-5">
|
||||
<label>{{ _("Academic Year: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-7">
|
||||
{{ doc.academic_year }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if doc.academic_term %}
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-5">
|
||||
<label>{{ _("Academic Term: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-7">
|
||||
{{ doc.academic_term }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row data-field">
|
||||
<div class="col-xs-5">
|
||||
<label>{{ _("Assessment Group: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-7">
|
||||
{{ doc.assessment_group }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if doc.show_marks | int %}
|
||||
{% set result_data = 'score' %}
|
||||
{% else %}
|
||||
{% set result_data = 'grade' %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% for course in courses %}
|
||||
|
||||
<div class="row section-break pbi_avoid">
|
||||
<div class="col-xs-12 column-break">
|
||||
|
||||
<div>
|
||||
<table class="table table-bordered table-condensed">
|
||||
<caption>
|
||||
<div class="row">
|
||||
<div class="col-xs-1">
|
||||
<label>{{ _("Course: ") }}</label>
|
||||
</div>
|
||||
<div class="col-xs-11">
|
||||
{{ course }} ({{ frappe.db.get_value("Course", course, "course_name") }})
|
||||
</div>
|
||||
</div>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: {{ 650//(assessment_groups|length + 1) }}px">{{ _("Assessment Criteria") }}</th>
|
||||
{% for assessment_group in assessment_groups %}
|
||||
<th> {{ assessment_group }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for criteria in course_criteria[course] %}
|
||||
<tr>
|
||||
<td>{{ criteria }}</td>
|
||||
{% for assessment_group in assessment_groups %}
|
||||
{% if (assessment_result.get(course) and assessment_result.get(course).get(assessment_group) and assessment_result.get(course).get(assessment_group).get(criteria)) %}
|
||||
<td>
|
||||
{{ assessment_result.get(course).get(assessment_group).get(criteria).get(result_data) }}
|
||||
{% if result_data == 'score' %}
|
||||
({{ assessment_result.get(course).get(assessment_group).get(criteria).get('maximum_score') }})
|
||||
{% endif %}
|
||||
</td>
|
||||
{% else %}
|
||||
<td></td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<br>
|
||||
|
||||
<div class="row section-break pbi_avoid">
|
||||
<div class="col-xs-6 column-break">
|
||||
<h4>{{ _("Student Attendance")}}</h4> <br>
|
||||
<div>
|
||||
Present {{ doc.attendance.get("Present") if doc.attendance.get("Present") != None else '0' }} days
|
||||
out of {{ doc.attendance.get("Present") + doc.attendance.get("Absent") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-6 column-break">
|
||||
<h4>{{ _("Parents Teacher Meeting Attendance")}}</h4> <br>
|
||||
<div>
|
||||
Present {{ doc.parents_attendance if doc.parents_attendance != None else '0' }}
|
||||
out of {{ doc.parents_meeting if doc.parents_meeting != None else '0' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if doc.assessment_terms %}
|
||||
<div class="row section-break pb_before">
|
||||
<div class="col-xs-12">
|
||||
<p> {{ doc.assessment_terms }} </p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Student Report Generation Tool', {
|
||||
onload: function(frm) {
|
||||
frm.set_query("academic_term",function(){
|
||||
return{
|
||||
"filters":{
|
||||
"academic_year": frm.doc.academic_year
|
||||
}
|
||||
};
|
||||
});
|
||||
frm.set_query("assessment_group", function() {
|
||||
return{
|
||||
filters: {
|
||||
"is_group": 1
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.disable_save();
|
||||
frm.page.clear_indicator();
|
||||
frm.page.set_primary_action(__('Print Report Card'), () => {
|
||||
let url = "/api/method/erpnext.education.doctype.student_report_generation_tool.student_report_generation_tool.preview_report_card";
|
||||
open_url_post(url, {"doc": frm.doc}, true);
|
||||
});
|
||||
},
|
||||
|
||||
student: function(frm) {
|
||||
if (frm.doc.student) {
|
||||
frappe.call({
|
||||
method:"erpnext.education.api.get_current_enrollment",
|
||||
args: {
|
||||
"student": frm.doc.student,
|
||||
"academic_year": frm.doc.academic_year
|
||||
},
|
||||
callback: function(r) {
|
||||
if(r){
|
||||
$.each(r.message, function(i, d) {
|
||||
if (frm.fields_dict.hasOwnProperty(i)) {
|
||||
frm.set_value(i, d);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
terms: function(frm) {
|
||||
if(frm.doc.terms) {
|
||||
return frappe.call({
|
||||
method: 'erpnext.setup.doctype.terms_and_conditions.terms_and_conditions.get_terms_and_conditions',
|
||||
args: {
|
||||
template_name: frm.doc.terms,
|
||||
doc: frm.doc
|
||||
},
|
||||
callback: function(r) {
|
||||
frm.set_value("assessment_terms", r.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,582 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-01-15 15:36:32.830069",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "student",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Student",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Student",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "student_name",
|
||||
"fieldtype": "Read Only",
|
||||
"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": "Student Name",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "program",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Program",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Program",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "student_batch",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Batch",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Student Batch Name",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "include_all_assessment",
|
||||
"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": "Include All Assessment Group",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "show_marks",
|
||||
"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": "Show Marks",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "1",
|
||||
"fieldname": "add_letterhead",
|
||||
"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": "Add letterhead",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "assessment_group",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Assessment Group",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Assessment Group",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "academic_year",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Academic Year",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Academic Year",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "academic_term",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Academic Term",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Academic Term",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "add_letterhead",
|
||||
"fieldname": "letter_head",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Letter Head",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Letter Head",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Print Section",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "parents_meeting",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Total Parents Teacher Meeting",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "parents_attendance",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Attended by Parents",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "terms",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Terms",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Terms and Conditions",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "assessment_terms",
|
||||
"fieldtype": "Text Editor",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Assessment Terms",
|
||||
"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,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 1,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-03-20 17:57:53.936119",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Education",
|
||||
"name": "Student Report Generation Tool",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe.model.document import Document
|
||||
from erpnext.education.api import get_grade
|
||||
from frappe.utils.pdf import get_pdf
|
||||
from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_formatted_result
|
||||
from erpnext.education.report.course_wise_assessment_report.course_wise_assessment_report import get_child_assessment_groups
|
||||
|
||||
|
||||
class StudentReportGenerationTool(Document):
|
||||
pass
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def preview_report_card(doc):
|
||||
doc = frappe._dict(json.loads(doc))
|
||||
doc.students = [doc.student]
|
||||
if not (doc.student_name and doc.student_batch):
|
||||
program_enrollment = frappe.get_all("Program Enrollment", fields=["student_batch_name", "student_name"],
|
||||
filters={"student": doc.student, "docstatus": ('!=', 2), "academic_year": doc.academic_year})
|
||||
if program_enrollment:
|
||||
doc.batch = program_enrollment[0].student_batch_name
|
||||
doc.student_name = program_enrollment[0].student_name
|
||||
|
||||
# get the assessment result of the selected student
|
||||
values = get_formatted_result(doc, get_course=True, get_all_assessment_groups=doc.include_all_assessment)
|
||||
assessment_result = values.get("assessment_result").get(doc.student)
|
||||
courses = values.get("course_dict")
|
||||
course_criteria = get_courses_criteria(courses)
|
||||
|
||||
# get the assessment group as per the user selection
|
||||
if doc.include_all_assessment:
|
||||
assessment_groups = get_child_assessment_groups(doc.assessment_group)
|
||||
else:
|
||||
assessment_groups = [doc.assessment_group]
|
||||
|
||||
# get the attendance of the student for that peroid of time.
|
||||
doc.attendance = get_attendance_count(doc.students[0], doc.academic_year, doc.academic_term)
|
||||
|
||||
template = "erpnext/education/doctype/student_report_generation_tool/student_report_generation_tool.html"
|
||||
base_template_path = "frappe/www/printview.html"
|
||||
|
||||
from frappe.www.printview import get_letter_head
|
||||
letterhead = get_letter_head(frappe._dict({"letter_head": doc.letterhead}), not doc.add_letterhead)
|
||||
|
||||
html = frappe.render_template(template,
|
||||
{
|
||||
"doc": doc,
|
||||
"assessment_result": assessment_result,
|
||||
"courses": courses,
|
||||
"assessment_groups": assessment_groups,
|
||||
"course_criteria": course_criteria,
|
||||
"letterhead": letterhead.content,
|
||||
"add_letterhead": doc.add_letterhead if doc.add_letterhead else 0
|
||||
})
|
||||
final_template = frappe.render_template(base_template_path, {"body": html, "title": "Report Card"})
|
||||
|
||||
frappe.response.filename = "Report Card " + doc.students[0] + ".pdf"
|
||||
frappe.response.filecontent = get_pdf(final_template)
|
||||
frappe.response.type = "download"
|
||||
|
||||
|
||||
def get_courses_criteria(courses):
|
||||
course_criteria = frappe._dict()
|
||||
for course in courses:
|
||||
course_criteria[course] = [d.assessment_criteria for d in frappe.get_all("Course Assessment Criteria",
|
||||
fields=["assessment_criteria"], filters={"parent": course})]
|
||||
return course_criteria
|
||||
|
||||
|
||||
def get_attendance_count(student, academic_year, academic_term=None):
|
||||
if academic_year:
|
||||
from_date, to_date = frappe.db.get_value("Academic Year", academic_year, ["year_start_date", "year_end_date"])
|
||||
elif academic_term:
|
||||
from_date, to_date = frappe.db.get_value("Academic Term", academic_term, ["term_start_date", "term_end_date"])
|
||||
if from_date and to_date:
|
||||
attendance = dict(frappe.db.sql('''select status, count(student) as no_of_days
|
||||
from `tabStudent Attendance` where student = %s
|
||||
and date between %s and %s group by status''',
|
||||
(student, from_date, to_date)))
|
||||
if "Absent" not in attendance.keys():
|
||||
attendance["Absent"] = 0
|
||||
if "Present" not in attendance.keys():
|
||||
attendance["Present"] = 0
|
||||
return attendance
|
||||
else:
|
||||
frappe.throw("Provide the academic year and set the starting and ending date.")
|
||||
@@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Student Report Generation Tool", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Student Report Generation Tool
|
||||
() => frappe.tests.make('Student Report Generation Tool', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestStudentReportGenerationTool(unittest.TestCase):
|
||||
pass
|
||||
@@ -60,7 +60,7 @@ def execute(filters=None):
|
||||
return columns, data, None, chart
|
||||
|
||||
|
||||
def get_formatted_result(args, get_assessment_criteria=False, get_course=False):
|
||||
def get_formatted_result(args, get_assessment_criteria=False, get_course=False, get_all_assessment_groups=False):
|
||||
cond, cond1, cond2, cond3, cond4 = " ", " ", " ", " ", " "
|
||||
args_list = [args.academic_year]
|
||||
|
||||
@@ -77,15 +77,9 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False):
|
||||
args_list.append(args.student_group)
|
||||
|
||||
create_total_dict = False
|
||||
group_type = frappe.get_value("Assessment Group", args.assessment_group, "is_group")
|
||||
if group_type:
|
||||
from frappe.desk.treeview import get_children
|
||||
assessment_groups = [d.get("value") for d in get_children("Assessment Group",
|
||||
args.assessment_group) if d.get("value") and not d.get("expandable")]
|
||||
cond3 = " and ar.assessment_group in (%s)"%(', '.join(['%s']*len(assessment_groups)))
|
||||
else:
|
||||
assessment_groups = [args.assessment_group]
|
||||
cond3 = " and ar.assessment_group=%s"
|
||||
|
||||
assessment_groups = get_child_assessment_groups(args.assessment_group)
|
||||
cond3 = " and ar.assessment_group in (%s)"%(', '.join(['%s']*len(assessment_groups)))
|
||||
args_list += assessment_groups
|
||||
|
||||
if args.students:
|
||||
@@ -156,6 +150,9 @@ def get_formatted_result(args, get_assessment_criteria=False, get_course=False):
|
||||
|
||||
# create the total of all the assessment groups criteria-wise
|
||||
elif create_total_dict:
|
||||
if get_all_assessment_groups:
|
||||
formatted_assessment_result[result.student][result.course][result.assessment_group]\
|
||||
[result.assessment_criteria] = assessment_criteria_details
|
||||
if not formatted_assessment_result[result.student][result.course][args.assessment_group]:
|
||||
formatted_assessment_result[result.student][result.course][args.assessment_group] = defaultdict(dict)
|
||||
formatted_assessment_result[result.student][result.course][args.assessment_group]\
|
||||
@@ -238,3 +235,15 @@ def get_chart_data(grades, criteria_list, kounter):
|
||||
},
|
||||
"type": 'bar',
|
||||
}
|
||||
|
||||
|
||||
def get_child_assessment_groups(assessment_group):
|
||||
assessment_groups = []
|
||||
group_type = frappe.get_value("Assessment Group", assessment_group, "is_group")
|
||||
if group_type:
|
||||
from frappe.desk.treeview import get_children
|
||||
assessment_groups = [d.get("value") for d in get_children("Assessment Group",
|
||||
assessment_group) if d.get("value") and not d.get("expandable")]
|
||||
else:
|
||||
assessment_groups = [assessment_group]
|
||||
return assessment_groups
|
||||
|
||||
@@ -113,9 +113,11 @@ def insert_consultation_to_medical_record(doc):
|
||||
|
||||
def update_consultation_to_medical_record(consultation):
|
||||
medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s", (consultation.name))
|
||||
if(medical_record_id[0][0]):
|
||||
if medical_record_id and medical_record_id[0][0]:
|
||||
subject = set_subject_field(consultation)
|
||||
frappe.db.set_value("Patient Medical Record", medical_record_id[0][0], "subject", subject)
|
||||
else:
|
||||
insert_consultation_to_medical_record(consultation)
|
||||
|
||||
def delete_medical_record(consultation):
|
||||
frappe.db.sql("""delete from `tabPatient Medical Record` where reference_name = %s""", (consultation.name))
|
||||
|
||||
@@ -244,7 +244,7 @@ def insert_lab_test_to_medical_record(doc):
|
||||
def delete_lab_test_from_medical_record(self):
|
||||
medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s",(self.name))
|
||||
|
||||
if(medical_record_id[0][0]):
|
||||
if medical_record_id and medical_record_id[0][0]:
|
||||
frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
|
||||
|
||||
def create_item_line(test_code, sales_invoice):
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
frappe.views.calendar["Patient Appointment"] = {
|
||||
field_map: {
|
||||
"start": "start",
|
||||
"end": "end",
|
||||
"start": "appointment_date",
|
||||
"end": "appointment_datetime",
|
||||
"id": "name",
|
||||
"title": "patient",
|
||||
"allDay": "allDay"
|
||||
|
||||
@@ -27,7 +27,7 @@ def insert_vital_signs_to_medical_record(doc):
|
||||
|
||||
def delete_vital_signs_from_medical_record(doc):
|
||||
medical_record_id = frappe.db.sql("select name from `tabPatient Medical Record` where reference_name=%s",(doc.name))
|
||||
if(medical_record_id[0][0]):
|
||||
if medical_record_id and medical_record_id[0][0]:
|
||||
frappe.delete_doc("Patient Medical Record", medical_record_id[0][0])
|
||||
|
||||
def set_subject_field(doc):
|
||||
|
||||
@@ -204,7 +204,7 @@ doc_events = {
|
||||
'Address': {
|
||||
'validate': 'erpnext.regional.india.utils.validate_gstin_for_india'
|
||||
},
|
||||
('Sales Invoice', 'Purchase Invoice'): {
|
||||
('Sales Invoice', 'Purchase Invoice', 'Delivery Note'): {
|
||||
'validate': 'erpnext.regional.india.utils.set_place_of_supply'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,19 @@ class Attendance(Document):
|
||||
set_employee_name(self)
|
||||
|
||||
def check_leave_record(self):
|
||||
leave_record = frappe.db.sql("""select leave_type, half_day from `tabLeave Application`
|
||||
leave_record = frappe.db.sql("""select leave_type, half_day, half_day_date from `tabLeave Application`
|
||||
where employee = %s and %s between from_date and to_date and status = 'Approved'
|
||||
and docstatus = 1""", (self.employee, self.attendance_date), as_dict=True)
|
||||
if leave_record:
|
||||
if leave_record[0].half_day:
|
||||
self.status = 'Half Day'
|
||||
frappe.msgprint(_("Employee {0} on Half day on {1}").format(self.employee, self.attendance_date))
|
||||
else:
|
||||
self.status = 'On Leave'
|
||||
self.leave_type = leave_record[0].leave_type
|
||||
frappe.msgprint(_("Employee {0} on Leave on {1}").format(self.employee, self.attendance_date))
|
||||
for d in leave_record:
|
||||
if d.half_day_date == getdate(self.attendance_date):
|
||||
self.status = 'Half Day'
|
||||
frappe.msgprint(_("Employee {0} on Half day on {1}").format(self.employee, self.attendance_date))
|
||||
else:
|
||||
self.status = 'On Leave'
|
||||
self.leave_type = d.leave_type
|
||||
frappe.msgprint(_("Employee {0} on Leave on {1}").format(self.employee, self.attendance_date))
|
||||
|
||||
if self.status == "On Leave" and not leave_record:
|
||||
frappe.throw(_("No leave record found for employee {0} for {1}").format(self.employee, self.attendance_date))
|
||||
|
||||
|
||||
@@ -98,9 +98,9 @@ cur_frm.cscript.refresh = function(doc) {
|
||||
if (cint(doc.total_amount_reimbursed) > 0 && frappe.model.can_read(entry_doctype)) {
|
||||
cur_frm.add_custom_button(__('Bank Entries'), function() {
|
||||
frappe.route_options = {
|
||||
entry_route_doctype: me.frm.doc.doctype,
|
||||
entry_route_name: me.frm.doc.name,
|
||||
company: me.frm.doc.company
|
||||
party_type: "Employee",
|
||||
party: doc.employee,
|
||||
company: doc.company
|
||||
};
|
||||
frappe.set_route("List", entry_doctype);
|
||||
}, __("View"));
|
||||
@@ -205,7 +205,7 @@ frappe.ui.form.on("Expense Claim", {
|
||||
make_payment_entry: function(frm) {
|
||||
var method = "erpnext.accounts.doctype.payment_entry.payment_entry.get_payment_entry";
|
||||
if(frm.doc.__onload && frm.doc.__onload.make_payment_via_journal_entry) {
|
||||
method = "erpnext.hr.doctype.expense_claim.expense_claim.make_bank_entry"
|
||||
method = "erpnext.hr.doctype.expense_claim.expense_claim.make_bank_entry";
|
||||
}
|
||||
return frappe.call({
|
||||
method: method,
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
|
||||
frappe.views.calendar["Holiday List"] = {
|
||||
field_map: {
|
||||
"start": "holiday_date",
|
||||
"end": "holiday_date",
|
||||
"start": "from_date",
|
||||
"end": "to_date",
|
||||
"id": "name",
|
||||
"title": "description",
|
||||
"allDay": "allDay"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
@@ -11,6 +12,7 @@
|
||||
"editable_grid": 1,
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -21,6 +23,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Settings",
|
||||
@@ -38,6 +41,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -50,6 +54,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Retirement Age",
|
||||
@@ -68,6 +73,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -80,6 +86,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Employee Records to be created by",
|
||||
@@ -98,6 +105,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -108,6 +116,7 @@
|
||||
"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,
|
||||
@@ -125,6 +134,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -136,6 +146,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Stop Birthday Reminders",
|
||||
@@ -153,6 +164,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -163,6 +175,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Maintain Billing Hours and Working Hours Same on Timesheet",
|
||||
@@ -181,6 +194,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -191,6 +205,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Payroll Settings",
|
||||
@@ -208,6 +223,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -219,6 +235,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Include holidays in Total no. of Working Days",
|
||||
@@ -236,6 +253,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -248,6 +266,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Email Salary Slip to Employee",
|
||||
@@ -266,6 +285,7 @@
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -276,6 +296,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Max working hours against Timesheet",
|
||||
@@ -292,21 +313,81 @@
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "leave_settings",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Leave Settings",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "show_leaves_of_all_department_members_in_calendar",
|
||||
"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": "Show Leaves Of All Department Members In Calendar",
|
||||
"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,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-cog",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 1,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-01-16 14:01:31.183485",
|
||||
"modified_by": "anastasiadis.st00@gmail.com",
|
||||
"modified": "2018-05-03 15:35:13.015466",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "HR Settings",
|
||||
"owner": "Administrator",
|
||||
@@ -321,7 +402,6 @@
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"is_custom": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
@@ -336,6 +416,7 @@
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_order": "ASC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
|
||||
23
erpnext/hr/doctype/hr_settings/test_hr_settings.js
Normal file
23
erpnext/hr/doctype/hr_settings/test_hr_settings.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: HR Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new HR Settings
|
||||
() => frappe.tests.make('HR Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
||||
10
erpnext/hr/doctype/hr_settings/test_hr_settings.py
Normal file
10
erpnext/hr/doctype/hr_settings/test_hr_settings.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestHRSettings(unittest.TestCase):
|
||||
pass
|
||||
@@ -42,6 +42,7 @@ frappe.ui.form.on("Leave Application", {
|
||||
|
||||
employee: function(frm) {
|
||||
frm.trigger("get_leave_balance");
|
||||
frm.trigger("set_leave_approver");
|
||||
},
|
||||
|
||||
leave_type: function(frm) {
|
||||
@@ -95,6 +96,9 @@ frappe.ui.form.on("Leave Application", {
|
||||
if (!r.exc && r.message) {
|
||||
frm.set_value('leave_balance', r.message);
|
||||
}
|
||||
else {
|
||||
frm.set_value('leave_balance', "0");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -122,4 +126,21 @@ frappe.ui.form.on("Leave Application", {
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
set_leave_approver: function(frm) {
|
||||
if(frm.doc.employee) {
|
||||
// server call is done to include holidays in leave days calculations
|
||||
return frappe.call({
|
||||
method: 'erpnext.hr.doctype.leave_application.leave_application.get_leave_approver_data',
|
||||
args: {
|
||||
"employee": frm.doc.employee,
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r && r.message) {
|
||||
frm.set_value('leave_approver', r.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,12 +5,12 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_link_to_form, \
|
||||
comma_or, get_fullname
|
||||
comma_or, get_fullname, nowdate
|
||||
from erpnext.hr.utils import set_employee_name
|
||||
from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates
|
||||
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
||||
from erpnext.hr.doctype.employee_leave_approver.employee_leave_approver import get_approver_list
|
||||
|
||||
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import daterange
|
||||
|
||||
class LeaveDayBlockedError(frappe.ValidationError): pass
|
||||
class OverlapError(frappe.ValidationError): pass
|
||||
@@ -52,6 +52,7 @@ class LeaveApplication(Document):
|
||||
frappe.throw(_("Only Leave Applications with status 'Approved' and 'Rejected' can be submitted"))
|
||||
|
||||
self.validate_back_dated_application()
|
||||
self.update_attendance()
|
||||
|
||||
# notify leave applier about approval
|
||||
self.notify_employee(self.status)
|
||||
@@ -100,6 +101,43 @@ class LeaveApplication(Document):
|
||||
frappe.throw(_("Leave cannot be applied/cancelled before {0}, as leave balance has already been carry-forwarded in the future leave allocation record {1}")
|
||||
.format(formatdate(future_allocation[0].from_date), future_allocation[0].name))
|
||||
|
||||
def update_attendance(self):
|
||||
if self.status == "Approved":
|
||||
attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s\
|
||||
and (attendance_date between %s and %s) and docstatus < 2""",(self.employee, self.from_date, self.to_date), as_dict=1)
|
||||
|
||||
if attendance:
|
||||
for d in attendance:
|
||||
doc = frappe.get_doc("Attendance", d.name)
|
||||
if getdate(self.half_day_date) == doc.attendance_date:
|
||||
status = "Half Day"
|
||||
else:
|
||||
status = "On Leave"
|
||||
frappe.db.sql("""update `tabAttendance` set status = %s, leave_type = %s\
|
||||
where name = %s""",(status, self.leave_type, d.name))
|
||||
|
||||
elif self.to_date <= nowdate():
|
||||
for dt in daterange(getdate(self.from_date), getdate(self.to_date)):
|
||||
date = dt.strftime("%Y-%m-%d")
|
||||
if not date == self.half_day_date:
|
||||
doc = frappe.new_doc("Attendance")
|
||||
doc.employee = self.employee
|
||||
doc.attendance_date = date
|
||||
doc.company = self.company
|
||||
doc.status = "On Leave"
|
||||
doc.leave_type = self.leave_type
|
||||
doc.insert(ignore_permissions=True)
|
||||
doc.submit()
|
||||
else:
|
||||
doc = frappe.new_doc("Attendance")
|
||||
doc.employee = self.employee
|
||||
doc.attendance_date = date
|
||||
doc.company = self.company
|
||||
doc.status = "Half Day"
|
||||
doc.leave_type = self.leave_type
|
||||
doc.insert(ignore_permissions=True)
|
||||
doc.submit()
|
||||
|
||||
def validate_salary_processed_days(self):
|
||||
if not frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"):
|
||||
return
|
||||
@@ -384,7 +422,7 @@ def get_leave_allocation_records(date, employee=None):
|
||||
|
||||
return allocated_leaves
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_holidays(employee, from_date, to_date):
|
||||
'''get holidays between two dates for the given employee'''
|
||||
holiday_list = get_holiday_list_for_employee(employee)
|
||||
@@ -494,3 +532,8 @@ def add_holidays(events, start, end, employee, company):
|
||||
"title": _("Holiday") + ": " + cstr(holiday.description),
|
||||
"name": holiday.name
|
||||
})
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_leave_approver_data(employee):
|
||||
return frappe.db.get_value("Employee Leave Approver",
|
||||
{'parent': employee}, 'leave_approver')
|
||||
|
||||
@@ -146,6 +146,7 @@ class PayrollEntry(Document):
|
||||
ss_list = self.get_sal_slip_list(ss_status=0)
|
||||
submitted_ss = []
|
||||
not_submitted_ss = []
|
||||
frappe.flags.via_payroll_entry = True
|
||||
for ss in ss_list:
|
||||
ss_obj = frappe.get_doc("Salary Slip",ss[0])
|
||||
ss_dict = {}
|
||||
@@ -159,17 +160,24 @@ class PayrollEntry(Document):
|
||||
else:
|
||||
try:
|
||||
ss_obj.submit()
|
||||
submitted_ss.append(ss_dict)
|
||||
submitted_ss.append(ss_obj)
|
||||
|
||||
except frappe.ValidationError:
|
||||
not_submitted_ss.append(ss_dict)
|
||||
if submitted_ss:
|
||||
jv_name = self.make_accural_jv_entry()
|
||||
jv_name = self.make_accrual_jv_entry()
|
||||
frappe.msgprint(_("Salary Slip submitted for period from {0} to {1}")
|
||||
.format(ss_obj.start_date, ss_obj.end_date))
|
||||
|
||||
self.email_salary_slip(submitted_ss)
|
||||
|
||||
return create_submit_log(submitted_ss, not_submitted_ss, jv_name)
|
||||
|
||||
def email_salary_slip(self, submitted_ss):
|
||||
if frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee"):
|
||||
for ss in submitted_ss:
|
||||
ss.email_salary_slip()
|
||||
|
||||
def get_loan_details(self):
|
||||
"""
|
||||
Get loan details from submitted salary slip based on selected criteria
|
||||
@@ -237,7 +245,7 @@ class PayrollEntry(Document):
|
||||
|
||||
return payroll_payable_account
|
||||
|
||||
def make_accural_jv_entry(self):
|
||||
def make_accrual_jv_entry(self):
|
||||
self.check_permission('write')
|
||||
earnings = self.get_salary_component_total(component_type = "earnings") or {}
|
||||
deductions = self.get_salary_component_total(component_type = "deductions") or {}
|
||||
@@ -249,7 +257,7 @@ class PayrollEntry(Document):
|
||||
if earnings or deductions:
|
||||
journal_entry = frappe.new_doc('Journal Entry')
|
||||
journal_entry.voucher_type = 'Journal Entry'
|
||||
journal_entry.user_remark = _('Accural Journal Entry for salaries from {0} to {1}')\
|
||||
journal_entry.user_remark = _('Accrual Journal Entry for salaries from {0} to {1}')\
|
||||
.format(self.start_date, self.end_date)
|
||||
journal_entry.company = self.company
|
||||
journal_entry.posting_date = self.posting_date
|
||||
|
||||
@@ -17,6 +17,5 @@ class SalaryComponent(Document):
|
||||
self.salary_component.split()]).upper()
|
||||
|
||||
self.salary_component_abbr = self.salary_component_abbr.strip()
|
||||
|
||||
self.salary_component_abbr = append_number_if_name_exists('Salary Component',
|
||||
self.salary_component_abbr, 'salary_component_abbr', separator='_')
|
||||
self.salary_component_abbr = append_number_if_name_exists('Salary Component', self.salary_component_abbr,
|
||||
'salary_component_abbr', separator='_', filters={"name": ["!=", self.name]})
|
||||
@@ -29,9 +29,10 @@ frappe.ui.form.on("Salary Slip", {
|
||||
})
|
||||
},
|
||||
|
||||
start_date: function(frm){
|
||||
start_date: function(frm, dt, dn){
|
||||
if(frm.doc.start_date){
|
||||
frm.trigger("set_end_date");
|
||||
get_emp_and_leave_details(frm.doc, dt, dn);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -65,18 +66,20 @@ frappe.ui.form.on("Salary Slip", {
|
||||
cur_frm.fields_dict['deductions'].grid.set_column_disp(salary_detail_fields,false);
|
||||
},
|
||||
|
||||
salary_slip_based_on_timesheet: function(frm) {
|
||||
salary_slip_based_on_timesheet: function(frm, dt, dn) {
|
||||
frm.trigger("toggle_fields");
|
||||
frm.set_value('start_date', '');
|
||||
get_emp_and_leave_details(frm.doc, dt, dn);
|
||||
},
|
||||
|
||||
payroll_frequency: function(frm) {
|
||||
payroll_frequency: function(frm, dt, dn) {
|
||||
frm.trigger("toggle_fields");
|
||||
frm.set_value('end_date', '');
|
||||
frm.set_value('start_date', '');
|
||||
get_emp_and_leave_details(frm.doc, dt, dn);
|
||||
},
|
||||
|
||||
employee: function(frm){
|
||||
frm.set_value('start_date', '');
|
||||
employee: function(frm, dt, dn) {
|
||||
get_emp_and_leave_details(frm.doc, dt, dn);
|
||||
},
|
||||
|
||||
toggle_fields: function(frm) {
|
||||
@@ -109,7 +112,7 @@ frappe.ui.form.on('Salary Slip Timesheet', {
|
||||
|
||||
// Get leave details
|
||||
//---------------------------------------------------------------------
|
||||
cur_frm.cscript.start_date = function(doc, dt, dn){
|
||||
var get_emp_and_leave_details = function(doc, dt, dn) {
|
||||
if(!doc.start_date){
|
||||
return frappe.call({
|
||||
method: 'get_emp_and_leave_details',
|
||||
@@ -122,11 +125,9 @@ cur_frm.cscript.start_date = function(doc, dt, dn){
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.payroll_frequency = cur_frm.cscript.salary_slip_based_on_timesheet = cur_frm.cscript.start_date;
|
||||
|
||||
cur_frm.cscript.employee = function(doc,dt,dn){
|
||||
doc.salary_structure = ''
|
||||
cur_frm.cscript.start_date(doc, dt, dn)
|
||||
get_emp_and_leave_details(doc, dt, dn);
|
||||
}
|
||||
|
||||
cur_frm.cscript.leave_without_pay = function(doc,dt,dn){
|
||||
|
||||
@@ -411,7 +411,7 @@ class SalarySlip(TransactionBase):
|
||||
else:
|
||||
self.set_status()
|
||||
self.update_status(self.name)
|
||||
if(frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")):
|
||||
if(frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry:
|
||||
self.email_salary_slip()
|
||||
|
||||
def on_cancel(self):
|
||||
|
||||
@@ -39,6 +39,16 @@ frappe.ui.form.on('Salary Structure', {
|
||||
}
|
||||
}
|
||||
});
|
||||
frm.set_query("payment_account", function () {
|
||||
var account_types = ["Bank", "Cash"];
|
||||
return {
|
||||
filters: {
|
||||
"account_type": ["in", account_types],
|
||||
"is_group": 0,
|
||||
"company": frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
@@ -151,6 +161,28 @@ frappe.ui.form.on('Salary Structure', {
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Salary Structure Employee', {
|
||||
from_date: function(frm, cdt, cdn) {
|
||||
validate_date(frm, cdt, cdn);
|
||||
},
|
||||
to_date: function(frm, cdt, cdn) {
|
||||
validate_date(frm, cdt, cdn);
|
||||
}
|
||||
});
|
||||
|
||||
var validate_date = function(frm, cdt, cdn) {
|
||||
var doc = locals[cdt][cdn];
|
||||
if(doc.to_date && doc.from_date) {
|
||||
var from_date = frappe.datetime.str_to_obj(doc.from_date);
|
||||
var to_date = frappe.datetime.str_to_obj(doc.to_date);
|
||||
|
||||
if(to_date < from_date) {
|
||||
frappe.model.set_value(cdt, cdn, "to_date", "");
|
||||
frappe.throw(__("From Date cannot be greater than To Date"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cur_frm.cscript.amount = function(doc, cdt, cdn){
|
||||
calculate_totals(doc, cdt, cdn);
|
||||
|
||||
@@ -22,6 +22,10 @@ def execute(filters=None):
|
||||
holiday_map = get_holiday(holiday_list, filters["month"])
|
||||
|
||||
data = []
|
||||
leave_types = frappe.db.sql("""select name from `tabLeave Type`""", as_list=True)
|
||||
leave_list = [d[0] for d in leave_types]
|
||||
columns.extend(leave_list)
|
||||
|
||||
for emp in sorted(att_map):
|
||||
emp_det = emp_map.get(emp)
|
||||
if not emp_det:
|
||||
@@ -49,10 +53,35 @@ def execute(filters=None):
|
||||
elif status == "Half Day":
|
||||
total_p += 0.5
|
||||
total_a += 0.5
|
||||
total_l += 0.5
|
||||
|
||||
row += [total_p, total_l, total_a]
|
||||
data.append(row)
|
||||
|
||||
if not filters.get("employee"):
|
||||
filters.update({"employee": emp})
|
||||
conditions += " and employee = %(employee)s"
|
||||
elif not filters.get("employee") == emp:
|
||||
filters.update({"employee": emp})
|
||||
|
||||
leave_details = frappe.db.sql("""select leave_type, status, count(*) as count from `tabAttendance`\
|
||||
where leave_type is not NULL %s group by leave_type, status""" % conditions, filters, as_dict=1)
|
||||
|
||||
leaves = {}
|
||||
for d in leave_details:
|
||||
if d.status == "Half Day":
|
||||
d.count = d.count * 0.5
|
||||
if d.leave_type in leaves:
|
||||
leaves[d.leave_type] += d.count
|
||||
else:
|
||||
leaves[d.leave_type] = d.count
|
||||
|
||||
for d in leave_list:
|
||||
if d in leaves:
|
||||
row.append(leaves[d])
|
||||
else:
|
||||
row.append("0.0")
|
||||
|
||||
data.append(row)
|
||||
return columns, data
|
||||
|
||||
def get_columns(filters):
|
||||
|
||||
@@ -602,6 +602,9 @@ def validate_bom_no(item, bom_no):
|
||||
for d in bom.items:
|
||||
if (d.item_code.lower() == item.lower()):
|
||||
rm_item_exists = True
|
||||
for d in bom.scrap_items:
|
||||
if (d.item_code.lower() == item.lower()):
|
||||
rm_item_exists = True
|
||||
if bom.item.lower() == item.lower() or \
|
||||
bom.item.lower() == cstr(frappe.db.get_value("Item", item, "variant_of")).lower():
|
||||
rm_item_exists = True
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
@@ -12,6 +13,7 @@
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -21,6 +23,8 @@
|
||||
"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": "Operation",
|
||||
@@ -38,9 +42,11 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -50,6 +56,8 @@
|
||||
"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": "Workstation",
|
||||
@@ -67,9 +75,11 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -79,6 +89,8 @@
|
||||
"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",
|
||||
@@ -95,9 +107,11 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -107,6 +121,8 @@
|
||||
"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,
|
||||
@@ -120,9 +136,11 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -132,6 +150,8 @@
|
||||
"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": "Hour Rate",
|
||||
@@ -149,9 +169,11 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -162,7 +184,9 @@
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Operation Time ",
|
||||
"length": 0,
|
||||
@@ -179,9 +203,11 @@
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -191,6 +217,8 @@
|
||||
"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": "Operating Cost",
|
||||
@@ -208,9 +236,11 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -220,6 +250,8 @@
|
||||
"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": "Base Hour Rate(Company Currency)",
|
||||
@@ -236,9 +268,11 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -249,6 +283,8 @@
|
||||
"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": "Operating Cost(Company Currency)",
|
||||
@@ -265,9 +301,11 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
@@ -277,6 +315,8 @@
|
||||
"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": "Image",
|
||||
@@ -292,20 +332,21 @@
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"in_dialog": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-02-10 07:12:41.255544",
|
||||
"modified": "2018-03-26 09:55:28.107451",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Operation",
|
||||
@@ -314,6 +355,7 @@
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
}
|
||||
@@ -64,7 +64,7 @@ class ProductionOrder(Document):
|
||||
so.name, so_item.delivery_date, so.project
|
||||
from
|
||||
`tabSales Order` so, `tabSales Order Item` so_item, `tabPacked Item` packed_item
|
||||
where so.name=%s
|
||||
where so.name=%s
|
||||
and so.name=so_item.parent
|
||||
and so.name=packed_item.parent
|
||||
and so_item.item_code = packed_item.parent_item
|
||||
@@ -88,7 +88,7 @@ class ProductionOrder(Document):
|
||||
self.wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
|
||||
if not self.fg_warehouse:
|
||||
self.fg_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_fg_warehouse")
|
||||
|
||||
|
||||
def validate_warehouse_belongs_to_company(self):
|
||||
warehouses = [self.fg_warehouse, self.wip_warehouse]
|
||||
for d in self.get("required_items"):
|
||||
@@ -524,7 +524,7 @@ def get_item_details(item, project = None):
|
||||
if not res["bom_no"]:
|
||||
if project:
|
||||
res = get_item_details(item)
|
||||
frappe.msgprint(_("Default BOM not found for Item {0} and Project {1}").format(item, project))
|
||||
frappe.msgprint(_("Default BOM not found for Item {0} and Project {1}").format(item, project), alert=1)
|
||||
else:
|
||||
frappe.throw(_("Default BOM for {0} not found").format(item))
|
||||
|
||||
@@ -642,5 +642,5 @@ def query_sales_order(production_item):
|
||||
select distinct so.name from `tabSales Order` so, `tabPacked Item` pi_item
|
||||
where pi_item.parent=so.name and pi_item.item_code=%s and so.docstatus=1
|
||||
""", (production_item, production_item))
|
||||
|
||||
|
||||
return out
|
||||
|
||||
@@ -64,8 +64,7 @@ erpnext.ProductionAnalytics = frappe.views.GridReportWithPlot.extend({
|
||||
|
||||
var chart_data = this.get_chart_data ? this.get_chart_data() : null;
|
||||
|
||||
this.chart = new Chart({
|
||||
parent: ".chart",
|
||||
this.chart = new frappeChart.Chart(".chart", {
|
||||
data: chart_data,
|
||||
type: 'line'
|
||||
});
|
||||
|
||||
@@ -12,6 +12,10 @@ frappe.query_reports["BOM Stock Report"] = {
|
||||
"fieldtype": "Link",
|
||||
"options": "Warehouse",
|
||||
"reqd": 1
|
||||
}, {
|
||||
"fieldname": "show_exploded_view",
|
||||
"label": __("Show exploded view"),
|
||||
"fieldtype": "Check"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,52 +6,61 @@ import frappe
|
||||
from frappe import _
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
columns = get_columns()
|
||||
data = get_bom_stock(filters)
|
||||
return columns, data
|
||||
if not filters: filters = {}
|
||||
columns = get_columns()
|
||||
|
||||
data = get_bom_stock(filters)
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
"""return columns"""
|
||||
columns = [
|
||||
_("Item") + ":Link/Item:150",
|
||||
_("Description") + "::500",
|
||||
_("Required Qty") + ":Float:100",
|
||||
_("In Stock Qty") + ":Float:100",
|
||||
_("Enough Parts to Build") + ":Float:200",
|
||||
]
|
||||
"""return columns"""
|
||||
columns = [
|
||||
_("Item") + ":Link/Item:150",
|
||||
_("Description") + "::500",
|
||||
_("Required Qty") + ":Float:100",
|
||||
_("In Stock Qty") + ":Float:100",
|
||||
_("Enough Parts to Build") + ":Float:200",
|
||||
]
|
||||
|
||||
return columns
|
||||
return columns
|
||||
|
||||
def get_bom_stock(filters):
|
||||
conditions = ""
|
||||
bom = filters.get("bom")
|
||||
conditions = ""
|
||||
bom = filters.get("bom")
|
||||
|
||||
if filters.get("warehouse"):
|
||||
warehouse_details = frappe.db.get_value("Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1)
|
||||
if warehouse_details:
|
||||
conditions += " and exists (select name from `tabWarehouse` wh \
|
||||
where wh.lft >= %s and wh.rgt <= %s and ledger.warehouse = wh.name)" % (warehouse_details.lft,
|
||||
warehouse_details.rgt)
|
||||
else:
|
||||
conditions += " and ledger.warehouse = '%s'" % frappe.db.escape(filters.get("warehouse"))
|
||||
table = "`tabBOM Item`"
|
||||
qty_field = "qty"
|
||||
|
||||
else:
|
||||
conditions += ""
|
||||
if filters.get("show_exploded_view"):
|
||||
table = "`tabBOM Explosion Item`"
|
||||
qty_field = "stock_qty"
|
||||
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
bom_item.item_code ,
|
||||
bom_item.description ,
|
||||
bom_item.qty,
|
||||
sum(ledger.actual_qty) as actual_qty,
|
||||
sum(FLOOR(ledger.actual_qty /bom_item.qty))as to_build
|
||||
FROM
|
||||
`tabBOM Item` AS bom_item
|
||||
LEFT JOIN `tabBin` AS ledger
|
||||
ON bom_item.item_code = ledger.item_code
|
||||
%s
|
||||
WHERE
|
||||
bom_item.parent = '%s' and bom_item.parenttype='BOM'
|
||||
if filters.get("warehouse"):
|
||||
warehouse_details = frappe.db.get_value("Warehouse", filters.get("warehouse"), ["lft", "rgt"], as_dict=1)
|
||||
if warehouse_details:
|
||||
conditions += " and exists (select name from `tabWarehouse` wh \
|
||||
where wh.lft >= %s and wh.rgt <= %s and ledger.warehouse = wh.name)" % (warehouse_details.lft,
|
||||
warehouse_details.rgt)
|
||||
else:
|
||||
conditions += " and ledger.warehouse = '%s'" % frappe.db.escape(filters.get("warehouse"))
|
||||
|
||||
GROUP BY bom_item.item_code""" % (conditions, bom))
|
||||
else:
|
||||
conditions += ""
|
||||
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
bom_item.item_code ,
|
||||
bom_item.description ,
|
||||
bom_item.{qty_field},
|
||||
sum(ledger.actual_qty) as actual_qty,
|
||||
sum(FLOOR(ledger.actual_qty / bom_item.{qty_field}))as to_build
|
||||
FROM
|
||||
{table} AS bom_item
|
||||
LEFT JOIN `tabBin` AS ledger
|
||||
ON bom_item.item_code = ledger.item_code
|
||||
{conditions}
|
||||
WHERE
|
||||
bom_item.parent = '{bom}' and bom_item.parenttype='BOM'
|
||||
|
||||
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom))
|
||||
|
||||
@@ -495,3 +495,10 @@ erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry
|
||||
erpnext.patches.v10_0.update_territory_and_customer_group
|
||||
erpnext.patches.v10_0.update_warehouse_address_details
|
||||
erpnext.patches.v10_0.update_reserved_qty_for_purchase_order
|
||||
erpnext.patches.v10_0.update_hub_connector_domain
|
||||
erpnext.patches.v10_0.set_student_party_type
|
||||
erpnext.patches.v10_0.update_project_in_sle
|
||||
erpnext.patches.v10_0.fix_reserved_qty_for_sub_contract
|
||||
erpnext.patches.v10_0.taxes_issue_with_pos
|
||||
erpnext.patches.v10_0.set_qty_in_transactions_based_on_serial_no_input
|
||||
erpnext.patches.v10_0.show_leaves_of_all_department_members_in_calendar
|
||||
|
||||
31
erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
Normal file
31
erpnext/patches/v10_0/fix_reserved_qty_for_sub_contract.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.stock.utils import get_bin
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("stock", "doctype", "bin")
|
||||
frappe.reload_doc("buying", "doctype", "purchase_order_item_supplied")
|
||||
for d in frappe.db.sql("""
|
||||
select distinct rm_item_code, reserve_warehouse
|
||||
from `tabPurchase Order Item Supplied`
|
||||
where docstatus=1 and reserve_warehouse is not null and reserve_warehouse != ''"""):
|
||||
|
||||
try:
|
||||
bin_doc = get_bin(d[0], d[1])
|
||||
bin_doc.update_reserved_qty_for_sub_contracting()
|
||||
except:
|
||||
pass
|
||||
|
||||
for d in frappe.db.sql("""select distinct item_code, source_warehouse
|
||||
from `tabProduction Order Item`
|
||||
where docstatus=1 and transferred_qty > required_qty
|
||||
and source_warehouse is not null and source_warehouse != ''""", as_list=1):
|
||||
|
||||
try:
|
||||
bin_doc = get_bin(d[0], d[1])
|
||||
bin_doc.update_reserved_qty_for_production()
|
||||
except:
|
||||
pass
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("stock", "doctype", "stock_settings")
|
||||
|
||||
ss = frappe.get_doc("Stock Settings")
|
||||
ss.set_qty_in_transactions_based_on_serial_no_input = 1
|
||||
|
||||
if ss.default_warehouse \
|
||||
and not frappe.db.exists("Warehouse", ss.default_warehouse):
|
||||
ss.default_warehouse = None
|
||||
|
||||
if ss.stock_uom and not frappe.db.exists("UOM", ss.stock_uom):
|
||||
ss.stock_uom = None
|
||||
|
||||
ss.flags.ignore_mandatory = True
|
||||
ss.save()
|
||||
7
erpnext/patches/v10_0/set_student_party_type.py
Normal file
7
erpnext/patches/v10_0/set_student_party_type.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
if not frappe.db.exists("Party Type", "Student"):
|
||||
party = frappe.new_doc("Party Type")
|
||||
party.party_type = "Student"
|
||||
party.save()
|
||||
@@ -0,0 +1,5 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("hr", "doctype", "hr_settings")
|
||||
frappe.db.set_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar", 1)
|
||||
26
erpnext/patches/v10_0/taxes_issue_with_pos.py
Normal file
26
erpnext/patches/v10_0/taxes_issue_with_pos.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for d in frappe.get_all('Sales Invoice', fields=["name"],
|
||||
filters = {'is_pos':1, 'docstatus': 1, 'creation': ('>', '2018-04-23')}):
|
||||
doc = frappe.get_doc('Sales Invoice', d.name)
|
||||
if (not doc.taxes and doc.taxes_and_charges and doc.pos_profile and doc.outstanding_amount != 0 and
|
||||
frappe.db.get_value('POS Profile', doc.pos_profile, 'taxes_and_charges', cache=True) == doc.taxes_and_charges):
|
||||
|
||||
doc.append_taxes_from_master()
|
||||
doc.calculate_taxes_and_totals()
|
||||
for d in doc.taxes:
|
||||
d.db_update()
|
||||
|
||||
doc.db_update()
|
||||
|
||||
delete_gle_for_voucher(doc.name)
|
||||
doc.make_gl_entries(repost_future_gle=False)
|
||||
|
||||
def delete_gle_for_voucher(voucher_no):
|
||||
frappe.db.sql("""delete from `tabGL Entry` where voucher_no = %(voucher_no)s""",
|
||||
{'voucher_no': voucher_no})
|
||||
9
erpnext/patches/v10_0/update_hub_connector_domain.py
Normal file
9
erpnext/patches/v10_0/update_hub_connector_domain.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
if frappe.db.table_exists("Data Migration Connector"):
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabData Migration Connector`
|
||||
SET hostname = 'https://hubmarket.org'
|
||||
WHERE connector_name = 'Hub Connector'
|
||||
""")
|
||||
15
erpnext/patches/v10_0/update_project_in_sle.py
Normal file
15
erpnext/patches/v10_0/update_project_in_sle.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
for doctype in ['Sales Invoice', 'Delivery Note', 'Stock Entry']:
|
||||
frappe.db.sql(""" update
|
||||
`tabStock Ledger Entry` sle, `tab{0}` parent_doc
|
||||
set
|
||||
sle.project = parent_doc.project
|
||||
where
|
||||
sle.voucher_no = parent_doc.name and sle.voucher_type = %s and sle.project is null
|
||||
and parent_doc.project is not null and parent_doc.project != ''""".format(doctype), doctype)
|
||||
@@ -2,6 +2,7 @@ import frappe
|
||||
from frappe import _
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc('stock', 'doctype', 'item')
|
||||
language = frappe.get_single("System Settings").language
|
||||
|
||||
if language and language.startswith('en'): return
|
||||
|
||||
@@ -1119,6 +1119,36 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "total_consumed_material_cost",
|
||||
"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": "Total Consumed Material Cost (via Stock Entry)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@@ -1285,7 +1315,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 4,
|
||||
"modified": "2017-12-10 08:40:46.843201",
|
||||
"modified": "2018-03-22 11:44:38.723507",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Projects",
|
||||
"name": "Project",
|
||||
|
||||
@@ -75,7 +75,7 @@ class Project(Document):
|
||||
sum = 0
|
||||
for task in self.tasks:
|
||||
if task.task_weight > 0:
|
||||
sum = sum + task.task_weight
|
||||
sum = flt(sum + task.task_weight, task.precision('task_weight'))
|
||||
if sum > 0 and sum != 1:
|
||||
frappe.throw(_("Total of all task weights should be 1. Please adjust weights of all Project tasks accordingly"))
|
||||
|
||||
|
||||
@@ -106,7 +106,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
|
||||
if(
|
||||
this.frm.fields_dict["payment_terms_template"]
|
||||
this.frm.docstatus < 2
|
||||
&& this.frm.fields_dict["payment_terms_template"]
|
||||
&& this.frm.fields_dict["payment_schedule"]
|
||||
&& this.frm.doc.payment_terms_template
|
||||
&& !this.frm.doc.payment_schedule.length
|
||||
@@ -400,7 +401,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
item.serial_no = valid_serial_nos.join('\n');
|
||||
|
||||
refresh_field("serial_no", item.name, item.parentfield);
|
||||
if(!doc.is_return) {
|
||||
if(!doc.is_return && cint(user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
|
||||
frappe.model.set_value(item.doctype, item.name,
|
||||
"qty", valid_serial_nos.length / item.conversion_factor);
|
||||
frappe.model.set_value(item.doctype, item.name, "stock_qty", valid_serial_nos.length);
|
||||
@@ -1093,6 +1094,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
me.in_apply_price_list = false;
|
||||
}
|
||||
}
|
||||
}).always(() => {
|
||||
me.in_apply_price_list = false;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -105,6 +105,12 @@ $.extend(erpnext.utils, {
|
||||
}
|
||||
},
|
||||
|
||||
get_party_name: function(party_type) {
|
||||
var dict = {'Customer': 'customer_name', 'Supplier': 'supplier_name', 'Employee': 'employee_name',
|
||||
'Member': 'member_name'};
|
||||
return dict[party_type];
|
||||
},
|
||||
|
||||
copy_value_in_all_row: function(doc, dt, dn, table_fieldname, fieldname) {
|
||||
var d = locals[dt][dn];
|
||||
if(d[fieldname]){
|
||||
|
||||
@@ -319,7 +319,8 @@ frappe.ui.form.ItemQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
|
||||
["parent", "=", $(e.target).attr("data-fieldname")],
|
||||
["attribute_value", "like", e.target.value + "%"]
|
||||
],
|
||||
fields: ["attribute_value"]
|
||||
fields: ["attribute_value"],
|
||||
parent: "Item"
|
||||
},
|
||||
callback: function(r) {
|
||||
if (r.message) {
|
||||
|
||||
@@ -10,7 +10,7 @@ def validate_gstin_for_india(doc, method):
|
||||
|
||||
if doc.gstin:
|
||||
doc.gstin = doc.gstin.upper()
|
||||
if doc.gstin != "NA":
|
||||
if doc.gstin not in ["NA", "na"]:
|
||||
p = re.compile("[0-9]{2}[a-zA-Z]{5}[0-9]{4}[a-zA-Z]{1}[1-9A-Za-z]{1}[Z]{1}[0-9a-zA-Z]{1}")
|
||||
if not p.match(doc.gstin):
|
||||
frappe.throw(_("Invalid GSTIN or Enter NA for Unregistered"))
|
||||
@@ -64,7 +64,7 @@ def get_itemised_tax_breakup_data(doc):
|
||||
def set_place_of_supply(doc, method):
|
||||
if not frappe.get_meta('Address').has_field('gst_state'): return
|
||||
|
||||
if doc.doctype == "Sales Invoice":
|
||||
if doc.doctype in ("Sales Invoice", "Delivery Note"):
|
||||
address_name = doc.shipping_address_name or doc.customer_address
|
||||
elif doc.doctype == "Purchase Invoice":
|
||||
address_name = doc.shipping_address or doc.supplier_address
|
||||
|
||||
@@ -23,7 +23,7 @@ class Gstr1Report(object):
|
||||
posting_date,
|
||||
base_grand_total,
|
||||
base_rounded_total,
|
||||
customer_gstin,
|
||||
COALESCE(NULLIF(customer_gstin,''), NULLIF(billing_address_gstin, '')) as customer_gstin,
|
||||
place_of_supply,
|
||||
ecommerce_gstin,
|
||||
reverse_charge,
|
||||
@@ -109,8 +109,8 @@ class Gstr1Report(object):
|
||||
customers = frappe.get_all("Customer", filters={"customer_type": self.customer_type})
|
||||
|
||||
if self.filters.get("type_of_business") == "B2B":
|
||||
conditions += " and invoice_type != 'Export' and is_return != 1 and customer in ('{0}')".\
|
||||
format("', '".join([frappe.db.escape(c.name) for c in customers]))
|
||||
conditions += """ and ifnull(invoice_type, '') != 'Export' and is_return != 1
|
||||
and customer in ('{0}')""".format("', '".join([frappe.db.escape(c.name) for c in customers]))
|
||||
|
||||
if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"):
|
||||
b2c_limit = frappe.db.get_single_value('GSt Settings', 'b2c_limit')
|
||||
@@ -144,7 +144,17 @@ class Gstr1Report(object):
|
||||
""" % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1)
|
||||
|
||||
for d in items:
|
||||
self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, d.base_net_amount)
|
||||
item_details = {}
|
||||
item_details[d.item_code] = d.base_net_amount
|
||||
|
||||
if d.parent in self.invoice_items:
|
||||
parent_dict = self.invoice_items[d.parent]
|
||||
if d.item_code in parent_dict:
|
||||
item_details[d.item_code] += parent_dict[d.item_code]
|
||||
else:
|
||||
item_details.update(parent_dict)
|
||||
|
||||
self.invoice_items[d.parent] = item_details
|
||||
|
||||
def get_items_based_on_tax_rate(self):
|
||||
self.tax_details = frappe.db.sql("""
|
||||
|
||||
@@ -84,7 +84,7 @@ class Gstr2Report(Gstr1Report):
|
||||
conditions += opts[1]
|
||||
|
||||
if self.filters.get("type_of_business") == "B2B":
|
||||
conditions += "and invoice_type != 'Export' and is_return != 1 "
|
||||
conditions += "and ifnull(invoice_type, '') != 'Export' and is_return != 1 "
|
||||
|
||||
elif self.filters.get("type_of_business") == "CDNR":
|
||||
conditions += """ and is_return = 1 """
|
||||
|
||||
@@ -316,7 +316,7 @@ def make_address(args, is_primary_address=1):
|
||||
return address
|
||||
|
||||
def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters):
|
||||
customer = frappe.db.escape(filters.get('customer'))
|
||||
customer = filters.get('customer')
|
||||
return frappe.db.sql("""
|
||||
select `tabContact`.name from `tabContact`, `tabDynamic Link`
|
||||
where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s
|
||||
|
||||
@@ -65,6 +65,10 @@ frappe.ui.form.on("Sales Order Item", {
|
||||
});
|
||||
|
||||
erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
|
||||
onload: function(doc, dt, dn) {
|
||||
this._super();
|
||||
},
|
||||
|
||||
refresh: function(doc, dt, dn) {
|
||||
var me = this;
|
||||
this._super();
|
||||
@@ -96,14 +100,14 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
|
||||
if (this.frm.has_perm("submit")) {
|
||||
// close
|
||||
if(flt(doc.per_delivered, 2) < 100 || flt(doc.per_billed) < 100) {
|
||||
if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) {
|
||||
this.frm.add_custom_button(__('Close'),
|
||||
function() { me.close_sales_order() }, __("Status"))
|
||||
}
|
||||
}
|
||||
|
||||
// delivery note
|
||||
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
||||
if(flt(doc.per_delivered, 6) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) {
|
||||
this.frm.add_custom_button(__('Delivery'),
|
||||
function() { me.make_delivery_note_based_on_delivery_date(); }, __("Make"));
|
||||
this.frm.add_custom_button(__('Production Order'),
|
||||
@@ -113,20 +117,20 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
}
|
||||
|
||||
// sales invoice
|
||||
if(flt(doc.per_billed, 2) < 100) {
|
||||
if(flt(doc.per_billed, 6) < 100) {
|
||||
this.frm.add_custom_button(__('Invoice'),
|
||||
function() { me.make_sales_invoice() }, __("Make"));
|
||||
}
|
||||
|
||||
// material request
|
||||
if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1
|
||||
&& flt(doc.per_delivered, 2) < 100) {
|
||||
&& flt(doc.per_delivered, 6) < 100) {
|
||||
this.frm.add_custom_button(__('Material Request'),
|
||||
function() { me.make_material_request() }, __("Make"));
|
||||
}
|
||||
|
||||
// make purchase order
|
||||
if(flt(doc.per_delivered, 2) < 100 && allow_purchase) {
|
||||
if(flt(doc.per_delivered, 6) < 100 && allow_purchase) {
|
||||
this.frm.add_custom_button(__('Purchase Order'),
|
||||
function() { me.make_purchase_order() }, __("Make"));
|
||||
}
|
||||
@@ -229,6 +233,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
{fieldtype:'Data', fieldname:'sales_order_item', reqd: 1,
|
||||
label: __('Sales Order Item'), hidden:1}
|
||||
],
|
||||
data: r.message,
|
||||
get_data: function() {
|
||||
return r.message
|
||||
}
|
||||
|
||||
@@ -360,6 +360,7 @@ class SalesOrder(SellingController):
|
||||
where production_item=%s and sales_order=%s and sales_order_item = %s and docstatus<2''', (i.item_code, self.name, i.name))[0][0])
|
||||
if pending_qty:
|
||||
items.append(dict(
|
||||
name= i.name,
|
||||
item_code= i.item_code,
|
||||
bom = bom,
|
||||
warehouse = i.warehouse,
|
||||
|
||||
@@ -6,15 +6,15 @@ frappe.listview_settings['Sales Order'] = {
|
||||
return [__("Closed"), "green", "status,=,Closed"];
|
||||
|
||||
} else if (doc.order_type !== "Maintenance"
|
||||
&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
||||
&& flt(doc.per_delivered, 6) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
||||
// to bill & overdue
|
||||
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"];
|
||||
|
||||
} else if (doc.order_type !== "Maintenance"
|
||||
&& flt(doc.per_delivered, 2) < 100 && doc.status!=="Closed") {
|
||||
&& flt(doc.per_delivered, 6) < 100 && doc.status!=="Closed") {
|
||||
// not delivered
|
||||
|
||||
if(flt(doc.per_billed, 2) < 100) {
|
||||
if(flt(doc.per_billed, 6) < 100) {
|
||||
// not delivered & not billed
|
||||
|
||||
return [__("To Deliver and Bill"), "orange",
|
||||
@@ -26,14 +26,14 @@ frappe.listview_settings['Sales Order'] = {
|
||||
"per_delivered,<,100|per_billed,=,100|status,!=,Closed"];
|
||||
}
|
||||
|
||||
} else if ((doc.order_type === "Maintenance" || flt(doc.per_delivered, 2) == 100)
|
||||
&& flt(doc.per_billed, 2) < 100 && doc.status!=="Closed") {
|
||||
} else if ((doc.order_type === "Maintenance" || flt(doc.per_delivered, 6) == 100)
|
||||
&& flt(doc.per_billed, 6) < 100 && doc.status!=="Closed") {
|
||||
|
||||
// to bill
|
||||
return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Closed"];
|
||||
|
||||
} else if((doc.order_type === "Maintenance" || flt(doc.per_delivered, 2) == 100)
|
||||
&& flt(doc.per_billed, 2) == 100 && doc.status!=="Closed") {
|
||||
} else if((doc.order_type === "Maintenance" || flt(doc.per_delivered, 6) == 100)
|
||||
&& flt(doc.per_billed, 6) == 100 && doc.status!=="Closed") {
|
||||
|
||||
return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Closed"];
|
||||
}
|
||||
|
||||
@@ -774,7 +774,7 @@ class POSCart {
|
||||
});
|
||||
this.numpad.reset_value();
|
||||
} else {
|
||||
const item_code = this.selected_item.attr('data-item-code');
|
||||
const item_code = unescape(this.selected_item.attr('data-item-code'));
|
||||
const field = this.selected_item.active_field;
|
||||
const value = this.numpad.get_value();
|
||||
|
||||
@@ -819,7 +819,7 @@ class POSCart {
|
||||
}
|
||||
|
||||
update_item(item) {
|
||||
const $item = this.$cart_items.find(`[data-item-code="${item.item_code}"]`);
|
||||
const $item = this.$cart_items.find(`[data-item-code="${escape(item.item_code)}"]`);
|
||||
|
||||
if(item.qty > 0) {
|
||||
const is_stock_item = this.get_item_details(item.item_code).is_stock_item;
|
||||
@@ -841,7 +841,7 @@ class POSCart {
|
||||
const rate = format_currency(item.rate, this.frm.doc.currency);
|
||||
const indicator_class = (!is_stock_item || item.actual_qty >= item.qty) ? 'green' : 'red';
|
||||
return `
|
||||
<div class="list-item indicator ${indicator_class}" data-item-code="${item.item_code}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
|
||||
<div class="list-item indicator ${indicator_class}" data-item-code="${escape(item.item_code)}" title="Item: ${item.item_name} Available Qty: ${item.actual_qty}">
|
||||
<div class="item-name list-item__content list-item__content--flex-1.5 ellipsis">
|
||||
${item.item_name}
|
||||
</div>
|
||||
@@ -883,18 +883,18 @@ class POSCart {
|
||||
}
|
||||
|
||||
exists(item_code) {
|
||||
let $item = this.$cart_items.find(`[data-item-code="${item_code}"]`);
|
||||
let $item = this.$cart_items.find(`[data-item-code="${escape(item_code)}"]`);
|
||||
return $item.length > 0;
|
||||
}
|
||||
|
||||
highlight_item(item_code) {
|
||||
const $item = this.$cart_items.find(`[data-item-code="${item_code}"]`);
|
||||
const $item = this.$cart_items.find(`[data-item-code="${escape(item_code)}"]`);
|
||||
$item.addClass('highlight');
|
||||
setTimeout(() => $item.removeClass('highlight'), 1000);
|
||||
}
|
||||
|
||||
scroll_to_item(item_code) {
|
||||
const $item = this.$cart_items.find(`[data-item-code="${item_code}"]`);
|
||||
const $item = this.$cart_items.find(`[data-item-code="${escape(item_code)}"]`);
|
||||
if ($item.length === 0) return;
|
||||
const scrollTop = $item.offset().top - this.$cart_items.offset().top + this.$cart_items.scrollTop();
|
||||
this.$cart_items.animate({ scrollTop });
|
||||
@@ -909,7 +909,7 @@ class POSCart {
|
||||
'[data-action="increment"], [data-action="decrement"]', function() {
|
||||
const $btn = $(this);
|
||||
const $item = $btn.closest('.list-item[data-item-code]');
|
||||
const item_code = $item.attr('data-item-code');
|
||||
const item_code = unescape($item.attr('data-item-code'));
|
||||
const action = $btn.attr('data-action');
|
||||
|
||||
if(action === 'increment') {
|
||||
@@ -932,7 +932,7 @@ class POSCart {
|
||||
this.$cart_items.on('change', '.quantity input', function() {
|
||||
const $input = $(this);
|
||||
const $item = $input.closest('.list-item[data-item-code]');
|
||||
const item_code = $item.attr('data-item-code');
|
||||
const item_code = unescape($item.attr('data-item-code'));
|
||||
events.on_field_change(item_code, 'qty', flt($input.val()));
|
||||
});
|
||||
|
||||
@@ -1200,7 +1200,7 @@ class POSItems {
|
||||
var me = this;
|
||||
this.wrapper.on('click', '.pos-item-wrapper', function() {
|
||||
const $item = $(this);
|
||||
const item_code = $item.attr('data-item-code');
|
||||
const item_code = unescape($item.attr('data-item-code'));
|
||||
me.events.update_cart(item_code, 'qty', '+1');
|
||||
});
|
||||
}
|
||||
@@ -1226,7 +1226,7 @@ class POSItems {
|
||||
const item_title = item_name || item_code;
|
||||
|
||||
const template = `
|
||||
<div class="pos-item-wrapper image-view-item" data-item-code="${item_code}">
|
||||
<div class="pos-item-wrapper image-view-item" data-item-code="${escape(item_code)}">
|
||||
<div class="image-view-header">
|
||||
<div>
|
||||
<a class="grey list-id" data-name="${item_code}" title="${item_title}">
|
||||
|
||||
@@ -49,6 +49,7 @@ def get_items(start, page_length, price_list, item_group, search_value="", pos_p
|
||||
where
|
||||
i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1
|
||||
and i.item_group in (select name from `tabItem Group` where lft >= {lft} and rgt <= {rgt})
|
||||
and ifnull(i.end_of_life, curdate()) >= curdate()
|
||||
and {condition}
|
||||
limit {start}, {page_length}""".format(start=start,
|
||||
page_length=page_length, lft=lft, rgt=rgt, condition=condition),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user