Merge branch 'develop'

This commit is contained in:
Nabin Hait 2017-05-16 13:39:42 +05:30
commit 3bd15fb19e
57 changed files with 919 additions and 313 deletions

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals
import frappe
__version__ = '8.0.26'
__version__ = '8.0.27'
def get_default_company(user=None):
'''Get default company for user'''

View File

@ -147,6 +147,7 @@ frappe.ui.form.on('Payment Entry', {
var currency_field = (frm.doc.payment_type=="Receive") ? "paid_from_account_currency" : "paid_to_account_currency"
frm.set_df_property("total_allocated_amount", "options", currency_field);
frm.set_df_property("unallocated_amount", "options", currency_field);
frm.set_df_property("party_balance", "options", currency_field);
frm.set_currency_labels(["total_amount", "outstanding_amount", "allocated_amount"],
party_account_currency, "references");

View File

@ -285,9 +285,10 @@ def get_pricing_rules(args):
def filter_pricing_rules(args, pricing_rules):
# filter for qty
stock_qty = args.get('qty') * args.get('conversion_factor', 1)
if pricing_rules:
pricing_rules = filter(lambda x: (flt(args.get("qty"))>=flt(x.min_qty)
and (flt(args.get("qty"))<=x.max_qty if x.max_qty else True)), pricing_rules)
pricing_rules = filter(lambda x: (flt(stock_qty)>=flt(x.min_qty)
and (flt(stock_qty)<=x.max_qty if x.max_qty else True)), pricing_rules)
# add variant_of property in pricing rule
for p in pricing_rules:

View File

@ -5,6 +5,9 @@
from __future__ import unicode_literals
import unittest
import frappe
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
class TestPricingRule(unittest.TestCase):
def test_pricing_rule_for_discount(self):
@ -203,3 +206,46 @@ class TestPricingRule(unittest.TestCase):
details = get_item_details(args)
self.assertEquals(details.get("discount_percentage"), 17.5)
def test_pricing_rule_for_stock_qty(self):
frappe.db.sql("delete from `tabPricing Rule`")
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
"apply_on": "Item Code",
"item_code": "_Test Item",
"selling": 1,
"price_or_discount": "Discount Percentage",
"price": 0,
"min_qty": 5,
"max_qty": 7,
"discount_percentage": 17.5,
"company": "_Test Company"
}
frappe.get_doc(test_record.copy()).insert()
if not frappe.db.get_value('UOM Conversion Detail',
{'parent': '_Test Item', 'uom': 'box'}):
item = frappe.get_doc('Item', '_Test Item')
item.append('uoms', {
'uom': 'Box',
'conversion_factor': 5
})
item.save(ignore_permissions=True)
# With pricing rule
so = make_sales_order(item_code="_Test Item", qty=1, uom="Box", do_not_submit=True)
so.items[0].price_list_rate = 100
so.submit()
so = frappe.get_doc('Sales Order', so.name)
self.assertEquals(so.items[0].discount_percentage, 17.5)
self.assertEquals(so.items[0].rate, 82.5)
# Without pricing rule
so = make_sales_order(item_code="_Test Item", qty=2, uom="Box", do_not_submit=True)
so.items[0].price_list_rate = 100
so.submit()
so = frappe.get_doc('Sales Order', so.name)
self.assertEquals(so.items[0].discount_percentage, 0)
self.assertEquals(so.items[0].rate, 100)

View File

@ -49,29 +49,37 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
if(doc.docstatus===0) {
cur_frm.add_custom_button(__('Purchase Order'), function() {
var me = this;
this.frm.add_custom_button(__('Purchase Order'), function() {
erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
source_doctype: "Purchase Order",
target: me.frm,
setters: {
supplier: me.frm.doc.supplier || undefined,
},
get_query_filters: {
supplier: cur_frm.doc.supplier || undefined,
docstatus: 1,
status: ["!=", "Closed"],
per_billed: ["<", 99.99],
company: cur_frm.doc.company
company: me.frm.doc.company
}
})
}, __("Get items from"));
cur_frm.add_custom_button(__('Purchase Receipt'), function() {
this.frm.add_custom_button(__('Purchase Receipt'), function() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_invoice",
source_doctype: "Purchase Receipt",
target: me.frm,
date_field: "posting_date",
setters: {
supplier: me.frm.doc.supplier || undefined,
},
get_query_filters: {
supplier: cur_frm.doc.supplier || undefined,
docstatus: 1,
status: ["!=", "Closed"],
company: cur_frm.doc.company
company: me.frm.doc.company
}
})
}, __("Get items from"));
@ -120,7 +128,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
hide_fields(this.frm.doc);
if(cint(this.frm.doc.is_paid)) {
if(!this.frm.doc.company) {
cur_frm.set_value("is_paid", 0)
this.frm.set_value("is_paid", 0)
msgprint(__("Please specify Company to proceed"));
}
}

View File

@ -112,33 +112,43 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
},
sales_order_btn: function() {
this.$sales_order_btn = cur_frm.add_custom_button(__('Sales Order'),
var me = this;
this.$sales_order_btn = this.frm.add_custom_button(__('Sales Order'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_sales_invoice",
source_doctype: "Sales Order",
target: me.frm,
setters: {
customer: me.frm.doc.customer || undefined,
},
get_query_filters: {
docstatus: 1,
status: ["!=", "Closed"],
per_billed: ["<", 99.99],
customer: cur_frm.doc.customer || undefined,
company: cur_frm.doc.company
company: me.frm.doc.company
}
})
}, __("Get items from"));
},
delivery_note_btn: function() {
this.$delivery_note_btn = cur_frm.add_custom_button(__('Delivery Note'),
var me = this;
this.$delivery_note_btn = this.frm.add_custom_button(__('Delivery Note'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice",
source_doctype: "Delivery Note",
target: me.frm,
date_field: "posting_date",
setters: {
company: me.frm.doc.company
},
get_query: function() {
var filters = {
company: cur_frm.doc.company
docstatus: 1,
};
if(cur_frm.doc.customer) filters["customer"] = cur_frm.doc.customer;
if(me.frm.doc.customer) filters["customer"] = me.frm.doc.customer;
return {
query: "erpnext.controllers.queries.get_delivery_notes_to_be_billed",
filters: filters

View File

@ -52,7 +52,7 @@ class SalesInvoice(SellingController):
def validate(self):
super(SalesInvoice, self).validate()
self.validate_posting_time()
self.validate_auto_set_posting_time()
self.so_dn_required()
self.validate_proj_cust()
self.validate_with_previous_doc()
@ -378,6 +378,12 @@ class SalesInvoice(SellingController):
def add_remarks(self):
if not self.remarks: self.remarks = 'No Remarks'
def validate_auto_set_posting_time(self):
# Don't auto set the posting date and time if invoice is amended
if self.is_new() and self.amended_from:
self.set_posting_time = 1
self.validate_posting_time()
def so_dn_required(self):
"""check in manage account if sales order / delivery note required or not."""

View File

@ -78,8 +78,16 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
make_menu_list: function () {
var me = this;
this.page.clear_menu();
// for mobile
this.page.add_menu_item(__("Pay"), function () {
me.validate();
me.update_paid_amount_status(true);
me.create_invoice();
me.make_payment();
}).addClass('visible-xs');
this.page.add_menu_item(__("New Sales Invoice"), function () {
me.save_previous_entry();
me.create_new();
@ -788,7 +796,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
add_customer: function() {
this.frm.doc.customer = "";
this.update_customer(true)
this.update_customer(true);
this.numeric_keypad.show();
},
update_customer: function (new_customer) {

View File

@ -153,30 +153,37 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
},
add_from_mappers: function() {
cur_frm.add_custom_button(__('Material Request'),
var me = this;
this.frm.add_custom_button(__('Material Request'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
source_doctype: "Material Request",
target: me.frm,
setters: {
company: me.frm.doc.company
},
get_query_filters: {
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99],
company: cur_frm.doc.company
}
})
}, __("Add items from"));
cur_frm.add_custom_button(__('Supplier Quotation'),
this.frm.add_custom_button(__('Supplier Quotation'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.supplier_quotation.supplier_quotation.make_purchase_order",
source_doctype: "Supplier Quotation",
target: me.frm,
setters: {
company: me.frm.doc.company
},
get_query_filters: {
docstatus: 1,
status: ["!=", "Stopped"],
company: cur_frm.doc.company
}
})
}, __("Add items from"));

View File

@ -48,7 +48,7 @@ frappe.ui.form.on("Request for Quotation",{
});
});
}
},
make_suppplier_quotation: function(frm) {
@ -124,24 +124,28 @@ frappe.ui.form.on("Request for Quotation Supplier",{
erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.extend({
refresh: function() {
var me = this;
this._super();
if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(__('Material Request'),
this.frm.add_custom_button(__('Material Request'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_request_for_quotation",
source_doctype: "Material Request",
target: me.frm,
setters: {
company: me.frm.doc.company
},
get_query_filters: {
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99],
company: cur_frm.doc.company
per_ordered: ["<", 99.99]
}
})
}, __("Get items from"));
// Get items from open Material Requests based on supplier
cur_frm.add_custom_button(__('Possible Supplier'), function() {
this.frm.add_custom_button(__('Possible Supplier'), function() {
// Create a dialog window for the user to pick their supplier
var d = new frappe.ui.Dialog({
title: __('Select Possible Supplier'),
@ -150,32 +154,35 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
{fieldname: 'ok_button', fieldtype:'Button', label:'Get Items from Material Requests'},
]
});
// On the user clicking the ok button
d.fields_dict.ok_button.input.onclick = function() {
var btn = d.fields_dict.ok_button.input;
var v = d.get_values();
if(v) {
$(btn).set_working();
erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_item_from_material_requests_based_on_supplier",
source_name: v.supplier,
target: me.frm,
setters: {
company: me.frm.doc.company
},
get_query_filters: {
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99],
company: cur_frm.doc.company
per_ordered: ["<", 99.99]
}
});
$(btn).done_working();
d.hide();
}
}
}
d.show();
}, __("Get items from"));
}
},

View File

@ -14,6 +14,7 @@ frappe.ui.form.on('Suppier Quotation', {
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
refresh: function() {
var me = this;
this._super();
if (this.frm.doc.docstatus === 1) {
cur_frm.add_custom_button(__("Purchase Order"), this.make_purchase_order,
@ -24,18 +25,21 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
}
else if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(__('Material Request'),
this.frm.add_custom_button(__('Material Request'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_supplier_quotation",
source_doctype: "Material Request",
target: me.frm,
setters: {
company: me.frm.doc.company
},
get_query_filters: {
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99],
company: cur_frm.doc.company
per_ordered: ["<", 99.99]
}
})
}, __("Get items from"));

View File

@ -46,8 +46,8 @@ status_map = {
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["Return", "eval:self.is_return==1 and self.docstatus==1"],
["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1 and self.is_return==0"],
["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
["Credit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
["Cancelled", "eval:self.docstatus==2"],
@ -56,8 +56,8 @@ status_map = {
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["Return", "eval:self.is_return==1 and self.docstatus==1"],
["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"],
["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1 and self.is_return==0"],
["Paid", "eval:self.outstanding_amount<=0 and self.docstatus==1 and self.is_return==0"],
["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"],
["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"],
["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"],
["Cancelled", "eval:self.docstatus==2"],
@ -119,7 +119,8 @@ class StatusUpdater(Document):
self.status = s[0]
break
elif s[1].startswith("eval:"):
if frappe.safe_eval(s[1][5:], None, { "self": self.as_dict(), "getdate": getdate, "nowdate": nowdate }):
if frappe.safe_eval(s[1][5:], None, { "self": self.as_dict(), "getdate": getdate,
"nowdate": nowdate, "get_value": frappe.db.get_value }):
self.status = s[0]
break
elif getattr(self, s[1])():

View File

@ -465,6 +465,8 @@ class calculate_taxes_and_totals(object):
payment.base_amount = flt(payment.amount * self.doc.conversion_rate)
paid_amount += payment.amount
base_paid_amount += payment.base_amount
elif not self.doc.is_return:
self.doc.set('payments', [])
self.doc.paid_amount = flt(paid_amount, self.doc.precision("paid_amount"))
self.doc.base_paid_amount = flt(base_paid_amount, self.doc.precision("base_paid_amount"))

View File

@ -0,0 +1,73 @@
from __future__ import unicode_literals
import unittest
import frappe
import random, json
import frappe.utils
from frappe.utils import nowdate
from frappe.model import mapper
from frappe.test_runner import make_test_records
class TestMapper(unittest.TestCase):
def test_map_docs(self):
'''Test mapping of multiple source docs on a single target doc'''
make_test_records("Item")
items = frappe.get_all("Item", fields = ["name", "item_code"], filters = {'is_sales_item': 1, 'has_variants': 0})
customers = frappe.get_all("Customer")
if items and customers:
# Make source docs (quotations) and a target doc (sales order)
customer = random.choice(customers).name
qtn1, item_list_1 = self.make_quotation(items, customer)
qtn2, item_list_2 = self.make_quotation(items, customer)
so, item_list_3 = self.make_sales_order()
# Map source docs to target with corresponding mapper method
method = "erpnext.selling.doctype.quotation.quotation.make_sales_order"
updated_so = mapper.map_docs(method, json.dumps([qtn1.name, qtn2.name]), so)
# Assert that all inserted items are present in updated sales order
src_items = item_list_1 + item_list_2 + item_list_3
self.assertEqual(set([d.item_code for d in src_items]),
set([d.item_code for d in updated_so.items]))
def get_random_items(self, items, limit):
'''Get a number of random items from a list of given items'''
random_items = []
for i in range(0, limit):
random_items.append(random.choice(items))
return random_items
def make_quotation(self, items, customer):
item_list = self.get_random_items(items, 3)
qtn = frappe.get_doc({
"doctype": "Quotation",
"quotation_to": "Customer",
"customer": customer,
"order_type": "Sales"
})
for item in item_list:
qtn.append("items", {"qty": "2", "item_code": item.item_code})
qtn.submit()
return qtn, item_list
def make_sales_order(self):
item = frappe.get_doc({
"base_amount": 1000.0,
"base_rate": 100.0,
"description": "CPU",
"doctype": "Sales Order Item",
"item_code": "_Test Item Home Desktop 100",
"item_name": "CPU",
"parentfield": "items",
"qty": 10.0,
"rate": 100.0,
"warehouse": "_Test Warehouse - _TC",
"stock_uom": "_Test UOM",
"conversion_factor": 1.0,
"uom": "_Test UOM"
})
so = frappe.get_doc(frappe.get_test_records('Sales Order')[0])
so.insert(ignore_permissions=True)
return so, [item]

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

View File

@ -8,7 +8,7 @@ You can manage multiple incoming and outgoing Email Accounts in ERPNext. There h
ERPNext will create templates for a bunch of email accounts by default. Not all of them are enabled. To enable them, you must set your account details.
There are 2 types of email accounts, outgoing and incoming. Outgoing email accounts use an SMTP service to send emails and emails are retrived from your inbox using a POP service. Most email providers such as GMail, Outlook or Yahoo provide these services.
There are 2 types of email accounts, outgoing and incoming. Outgoing email accounts use an SMTP service to send emails and emails are retrived from your inbox using a IMAP or POP service. Most email providers such as GMail, Outlook or Yahoo provide these services.
<img class="screenshot" alt="Defining Criteria" src="{{docs_base_url}}/assets/img/setup/email/email-account-list.png">
@ -28,7 +28,7 @@ To setup an incoming Email Account, check on **Enable Incoming** and set your PO
### How ERPNext handles replies
In ERPNext when you send an email to a contact like a customer, the sender will be the user who sent the email. In the **Reply-To** property, the Email Address will be of the default incoming account (like `replies@yourcompany.com`). ERPNext will automatically extract these emails from the incoming account and tag it to the relvant communication
In ERPNext when you send an email to a contact like a customer, the sender will be the user who sent the email. In the **Reply-To** property, the Email Address will be of the default incoming account (like `replies@yourcompany.com`). ERPNext will automatically extract these emails from the incoming account and tag it to the relevant communication
### Notification for unreplied messages

View File

@ -0,0 +1,30 @@
#Setting up Stripe
To setup Stripe,
`Explore > Integrations > Stripe Settings`
#### Setup Stripe
To enable Stripe payment service, you need to configure parameters like Publishable Key, Secret Key
<img class="screenshot" alt="Razorpay Settings" src="{{docs_base_url}}/assets/img/setup/integrations/stripe_setting.png">
On enabling service, the system will create Payment Gateway record and Account head in chart of account with account type as Bank.
<img class="screenshot" alt="Stripe COA" src="{{docs_base_url}}/assets/img/setup/integrations/stripe_coa.png">
Also it will create Payment Gateway Account entry. Payment Gateway Account is configuration hub from this you can set account head from existing COA, default Payment Request email body template.
<img class="screenshot" alt="Payment Gateway Account" src="{{docs_base_url}}/assets/img/setup/integrations/payment_gateway_account_stripe.png">
After configuring Payment Gateway Account your system is able to accept online payments.
####Supporting transaction currencies
"AED", "ALL", "ANG", "ARS", "AUD", "AWG", "BBD", "BDT", "BIF", "BMD", "BND",
"BOB", "BRL", "BSD", "BWP", "BZD", "CAD", "CHF", "CLP", "CNY", "COP", "CRC", "CVE", "CZK", "DJF",
"DKK", "DOP", "DZD", "EGP", "ETB", "EUR", "FJD", "FKP", "GBP", "GIP", "GMD", "GNF", "GTQ", "GYD",
"HKD", "HNL", "HRK", "HTG", "HUF", "IDR", "ILS", "INR", "ISK", "JMD", "JPY", "KES", "KHR", "KMF",
"KRW", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "MAD", "MDL", "MNT", "MOP", "MRO", "MUR", "MVR",
"MWK", "MXN", "MYR", "NAD", "NGN", "NIO", "NOK", "NPR", "NZD", "PAB", "PEN", "PGK", "PHP", "PKR",
"PLN", "PYG", "QAR", "RUB", "SAR", "SBD", "SCR", "SEK", "SGD", "SHP", "SLL", "SOS", "STD", "SVC",
"SZL", "THB", "TOP", "TTD", "TWD", "TZS", "UAH", "UGX", "USD", "UYU", "UZS", "VND", "VUV", "WST",
"XAF", "XOF", "XPF", "YER", "ZAR"

View File

@ -16,7 +16,15 @@ frappe.ui.form.on("Vehicle Log", {
}
})
}
if(frm.doc.docstatus == 1) {
frm.add_custom_button(__('Expense Claim'), function() {
frm.events.expense_claim(frm)
}, __("Make"));
frm.page.set_inner_btn_group_as_primary(__("Make"));
}
},
expense_claim: function(frm){
frappe.call({
method: "erpnext.hr.doctype.vehicle_log.vehicle_log.make_expense_claim",

View File

@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "naming_series:",
@ -12,6 +13,7 @@
"editable_grid": 1,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -41,6 +43,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -71,6 +74,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -101,6 +105,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -131,6 +136,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -159,6 +165,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -187,6 +194,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -216,6 +224,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -245,6 +254,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -274,6 +284,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -303,6 +314,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -332,6 +344,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -361,6 +374,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -390,6 +404,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -419,6 +434,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -447,6 +463,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -477,6 +494,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -506,6 +524,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -519,7 +538,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Service_Details",
"label": "Service Details",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@ -535,6 +554,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -565,64 +585,7 @@
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_20",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.docstatus==1",
"fieldname": "expense_claim",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Make Expense Claim",
"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,
@ -652,17 +615,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-02-17 16:53:17.975663",
"modified": "2017-05-15 13:17:59.575317",
"modified_by": "Administrator",
"module": "HR",
"name": "Vehicle Log",

View File

@ -33,10 +33,13 @@ erpnext.maintenance.MaintenanceSchedule = frappe.ui.form.Controller.extend({
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_schedule",
source_doctype: "Sales Order",
target: me.frm,
setters: {
customer: me.frm.doc.customer || undefined,
order_type: me.frm.doc.order_type,
},
get_query_filters: {
docstatus: 1,
order_type: me.frm.doc.order_type,
customer: me.frm.doc.customer || undefined,
company: me.frm.doc.company
}
});

View File

@ -27,41 +27,53 @@ erpnext.maintenance.MaintenanceVisit = frappe.ui.form.Controller.extend({
refresh: function() {
frappe.dynamic_link = {doc: this.frm.doc, fieldname: 'customer', doctype: 'Customer'}
var me = this;
if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(__('Maintenance Schedule'),
this.frm.add_custom_button(__('Maintenance Schedule'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.maintenance.doctype.maintenance_schedule.maintenance_schedule.make_maintenance_visit",
source_doctype: "Maintenance Schedule",
target: me.frm,
setters: {
customer: me.frm.doc.customer || undefined,
},
get_query_filters: {
docstatus: 1,
customer: cur_frm.doc.customer || undefined,
company: cur_frm.doc.company
company: me.frm.doc.company
}
})
}, __("Get items from"));
cur_frm.add_custom_button(__('Warranty Claim'),
this.frm.add_custom_button(__('Warranty Claim'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.support.doctype.warranty_claim.warranty_claim.make_maintenance_visit",
source_doctype: "Warranty Claim",
target: me.frm,
date_field: "complaint_date",
setters: {
customer: me.frm.doc.customer || undefined,
},
get_query_filters: {
status: ["in", "Open, Work in Progress"],
customer: cur_frm.doc.customer || undefined,
company: cur_frm.doc.company
company: me.frm.doc.company
}
})
}, __("Get items from"));
cur_frm.add_custom_button(__('Sales Order'),
this.frm.add_custom_button(__('Sales Order'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_maintenance_visit",
source_doctype: "Sales Order",
target: me.frm,
setters: {
customer: me.frm.doc.customer || undefined,
},
get_query_filters: {
docstatus: 1,
order_type: cur_frm.doc.order_type,
customer: cur_frm.doc.customer || undefined,
company: cur_frm.doc.company
company: me.frm.doc.company,
order_type: me.frm.doc.order_type,
}
})
}, __("Get items from"));

View File

@ -33,9 +33,7 @@ frappe.ui.form.on("BOM", {
});
}
if(frm.doc.docstatus==2) {
// show duplicate button when BOM is cancelled,
// its not very intuitive
if(frm.doc.docstatus!=0) {
frm.add_custom_button(__("Duplicate"), function() {
frm.copy_doc();
});

View File

@ -393,4 +393,6 @@ erpnext.patches.v7_2.stock_uom_in_selling
erpnext.patches.v8_0.revert_manufacturers_table_from_item
erpnext.patches.v8_0.disable_instructor_role
erpnext.patches.v8_0.merge_student_batch_and_student_group
erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding
erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice

View File

@ -1,7 +1,5 @@
import frappe
def execute():
frappe.reload_doc('schools', 'doctype', 'student_batch_student')
frappe.reload_doc('schools', 'doctype', 'student_group_student')
frappe.db.sql("update `tabStudent Batch Student` set active=1")
frappe.db.sql("update `tabStudent Group Student` set active=1")

View File

@ -0,0 +1,23 @@
# 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 dt, status in [["Sales Invoice", "Credit Note Issued"], ["Purchase Invoice", "Debit Note Issued"]]:
invoices = frappe.db.sql("""
select name
from `tab{0}`
where
status = %s
and outstanding_amount < 0
and docstatus=1
and is_return=0
""".format(dt), status)
for inv in invoices:
return_inv = frappe.db.sql("""select name from `tab{0}`
where is_return=1 and return_against=%s and docstatus=1""".format(dt), inv[0])
if not return_inv:
frappe.db.sql("update `tab{0}` set status='Paid' where name = %s".format(dt), inv[0])

View File

@ -0,0 +1,15 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doctype('Sales Invoice')
frappe.db.sql("""
delete from
`tabSales Invoice Payment`
where
parent in (select name from `tabSales Invoice` where is_pos = 0)
""")

View File

@ -216,9 +216,19 @@ class Project(Document):
# duplicated project
dependency_map = {}
for task in self.tasks:
name, depends_on_tasks = frappe.db.get_value(
'Task', { "subject": task.title, "project": self.copied_from }, ['name', 'depends_on_tasks']
_task = frappe.db.get_value(
'Task',
{"subject": task.title, "project": self.copied_from},
['name', 'depends_on_tasks'],
as_dict=True
)
if _task is None:
continue
name = _task.name
depends_on_tasks = _task.depends_on_tasks
depends_on_tasks = [x for x in depends_on_tasks.split(',') if x]
dependency_map[task.title] = [ x['subject'] for x in frappe.get_list(
'Task Depends On', {"parent": name}, ['subject'])]

View File

@ -270,6 +270,11 @@ body[data-route="pos"] .item-cart-items {
border: 1px solid #d1d8dd;
border-top: none;
}
@media (max-width: 767px) {
body[data-route="pos"] .item-cart-items {
height: 30vh;
}
}
body[data-route="pos"] .no-items-message {
min-height: 200px;
display: flex;

View File

@ -594,6 +594,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
paid_amount += data.amount;
base_paid_amount += data.base_amount;
})
} else if(!this.frm.doc.is_return){
this.frm.doc.payments = [];
}
this.frm.doc.paid_amount = flt(paid_amount, precision("paid_amount"));

View File

@ -114,63 +114,68 @@ erpnext.utils.map_current_doc = function(opts) {
}
}
var _map = function() {
// remove first item row if empty
if($.isArray(cur_frm.doc.items) && cur_frm.doc.items.length > 0) {
// remove first item row if empty
if(!cur_frm.doc.items[0].item_code) {
cur_frm.doc.items = cur_frm.doc.items.splice(1);
}
// find the doctype of the items table
var items_doctype = frappe.meta.get_docfield(cur_frm.doctype, 'items').options;
// find the link fieldname from items table for the given
// source_doctype
var link_fieldname = null;
frappe.get_meta(items_doctype).fields.forEach(function(d) {
frappe.get_meta(items_doctype).fields.forEach(function(d) {
if(d.options===opts.source_doctype) link_fieldname = d.fieldname; });
// search in existing items if the source_name is already set and full qty fetched
var already_set = false;
var item_qty_map = {};
$.each(cur_frm.doc.items, function(i, d) {
if(d[link_fieldname]==opts.source_name) {
already_set = true;
if (item_qty_map[d.item_code])
item_qty_map[d.item_code] += flt(d.qty);
else
item_qty_map[d.item_code] = flt(d.qty);
}
});
if(already_set) {
frappe.model.with_doc(opts.source_doctype, opts.source_name, function(r) {
var source_doc = frappe.model.get_doc(opts.source_doctype, opts.source_name);
$.each(source_doc.items || [], function(i, row) {
if(row.qty > flt(item_qty_map[row.item_code])) {
already_set = false;
return false;
}
})
})
if(already_set) {
frappe.msgprint(__("You have already selected items from {0} {1}",
[opts.source_doctype, opts.source_name]));
return;
}
$.each(cur_frm.doc.items, function(i, d) {
opts.source_name.forEach(function(src) {
if(d[link_fieldname]==src) {
already_set = true;
if (item_qty_map[d.item_code])
item_qty_map[d.item_code] += flt(d.qty);
else
item_qty_map[d.item_code] = flt(d.qty);
}
});
});
if(already_set) {
opts.source_name.forEach(function(src) {
frappe.model.with_doc(opts.source_doctype, src, function(r) {
var source_doc = frappe.model.get_doc(opts.source_doctype, src);
$.each(source_doc.items || [], function(i, row) {
if(row.qty > flt(item_qty_map[row.item_code])) {
already_set = false;
return false;
}
})
})
if(already_set) {
frappe.msgprint(__("You have already selected items from {0} {1}",
[opts.source_doctype, src]));
return;
}
})
}
}
return frappe.call({
// Sometimes we hit the limit for URL length of a GET request
// as we send the full target_doc. Hence this is a POST request.
type: "POST",
method: opts.method,
method: 'frappe.model.mapper.map_docs',
args: {
"source_name": opts.source_name,
"target_doc": cur_frm.doc
"method": opts.method,
"source_names": opts.source_name,
"target_doc": cur_frm.doc,
},
callback: function(r) {
if(!r.exc) {
@ -181,29 +186,26 @@ erpnext.utils.map_current_doc = function(opts) {
});
}
if(opts.source_doctype) {
var d = new frappe.ui.Dialog({
title: __("Get From ") + __(opts.source_doctype),
fields: [
{
fieldtype: "Link",
label: __(opts.source_doctype),
fieldname: opts.source_doctype,
options: opts.source_doctype,
get_query: opts.get_query,
reqd:1
},
]
var d = new frappe.ui.form.MultiSelectDialog({
doctype: opts.source_doctype,
target: opts.target,
date_field: opts.date_field || undefined,
setters: opts.setters,
get_query: opts.get_query,
action: function(selections, args) {
let values = selections;
if(values.length === 0){
frappe.msgprint(__("Please select Quotations"))
return;
}
opts.source_name = values;
opts.setters = args;
d.dialog.hide();
_map();
},
});
d.set_primary_action(__('Get Items'), function() {
var values = d.get_values();
if(!values)
return;
opts.source_name = values[opts.source_doctype];
d.hide();
_map();
})
d.show();
} else if(opts.source_name) {
opts.source_name = [opts.source_name];
_map();
}
}

View File

@ -321,6 +321,10 @@ body[data-route="pos"] {
overflow: auto;
border: 1px solid @border-color;
border-top: none;
@media (max-width: @screen-xs) {
height: 30vh;
}
}
.no-items-message {

View File

@ -14,6 +14,7 @@
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -43,6 +44,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -73,6 +75,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -101,6 +104,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -130,6 +134,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -159,6 +164,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -188,6 +194,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -218,6 +225,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -247,6 +255,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -288,7 +297,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2017-04-12 20:40:53.542488",
"modified": "2017-05-12 15:39:15.542274",
"modified_by": "Administrator",
"module": "Schools",
"name": "Program",

View File

@ -6,20 +6,27 @@ frappe.ui.form.on("Student Group Creation Tool", "refresh", function(frm) {
doc:frm.doc
})
});
frappe.realtime.on("student_group_creation_progress", function(data) {
if(data.progress) {
frappe.hide_msgprint(true);
frappe.show_progress(__("Creating student groups"), data.progress[0],data.progress[1]);
}
});
});
frappe.ui.form.on("Student Group Creation Tool", "get_courses", function(frm) {
frm.set_value("courses",[]);
frappe.call({
method: "get_courses",
doc:frm.doc,
callback: function(r) {
if(r.message) {
frm.set_value("courses", r.message);
if (frm.doc.academic_year && frm.doc.program) {
frappe.call({
method: "get_courses",
doc:frm.doc,
callback: function(r) {
if(r.message) {
frm.set_value("courses", r.message);
}
}
}
})
})
}
});
frappe.ui.form.on("Student Group Creation Tool", "onload", function(frm){

View File

@ -1,5 +1,6 @@
{
"allow_copy": 1,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@ -9,18 +10,23 @@
"doctype": "DocType",
"document_type": "",
"editable_grid": 0,
"engine": "InnoDB",
"fields": [
{
"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": 0,
"in_standard_filter": 0,
"label": "Academic Year",
"length": 0,
"no_copy": 0,
@ -30,6 +36,7 @@
"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,
@ -37,16 +44,21 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Leave blank if you make students groups per year",
"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,
@ -56,23 +68,28 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"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": "get_courses",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Get Courses",
"length": 0,
"no_copy": 0,
@ -81,6 +98,7 @@
"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,
@ -88,16 +106,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@ -105,6 +127,7 @@
"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,
@ -112,17 +135,21 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "Leave blank if you wish to fetch all courses for selected academic term",
"columns": 0,
"description": "",
"fieldname": "program",
"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": "Program",
"length": 0,
"no_copy": 0,
@ -132,6 +159,39 @@
"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,
"description": "Leave unchecked if you don't want to consider batch while making course based groups. ",
"fieldname": "separate_groups",
"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": "Separate course based Group for every Batch",
"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,
@ -139,16 +199,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
@ -156,6 +220,7 @@
"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,
@ -163,16 +228,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "courses",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Courses",
"length": 0,
"no_copy": 0,
@ -182,6 +251,7 @@
"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,
@ -189,17 +259,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 1,
"hide_toolbar": 1,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2016-07-25 06:40:46.107131",
"modified": "2017-05-15 12:43:32.317942",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Group Creation Tool",
@ -230,7 +300,9 @@
"quick_entry": 0,
"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
}

View File

@ -9,40 +9,63 @@ from frappe.model.document import Document
class StudentGroupCreationTool(Document):
def get_courses(self):
if self.program:
courses = frappe.db.sql("""select course, course_code, parent as program, "student_group_name"
from `tabProgram Course` where academic_term= %s and parent= %s""",
(self.academic_term, self.program), as_dict=1)
group_list = []
batches = frappe.db.sql('''select name as batch from `tabStudent Batch Name`''', as_dict=1)
for batch in batches:
group_list.append({"group_based_on":"Batch", "batch":batch.batch})
courses = frappe.db.sql('''select course, course_name from `tabProgram Course` where parent=%s''',
(self.program), as_dict=1)
if self.separate_groups:
from itertools import product
course_list = product(courses,batches)
for course in course_list:
temp_dict = {}
temp_dict.update({"group_based_on":"Course"})
temp_dict.update(course[0])
temp_dict.update(course[1])
group_list.append(temp_dict)
else:
courses = frappe.db.sql("""select course, course_code, parent as program, "student_group_name"
from `tabProgram Course` where academic_term= %s""",
self.academic_term, as_dict=1)
for course in courses:
course.update({"group_based_on":"Course"})
group_list.append(course)
for d in courses:
if d.course_code:
d.student_group_name = d.course_code + "-" + self.academic_year
else:
d.student_group_name = None
for group in group_list:
if group.get("group_based_on") == "Batch":
student_group_name = self.program + "/" + group.get("batch") + "/" + (self.academic_term if self.academic_term else self.academic_year)
group.update({"student_group_name": student_group_name})
elif group.get("group_based_on") == "Course":
student_group_name = group.get("course") + "/" + self.program + ("/" + group.get("batch") if group.get("batch") else "") + "/" + (self.academic_term if self.academic_term else self.academic_year)
group.update({"student_group_name": student_group_name})
return courses
return group_list
def create_student_groups(self):
if not self.courses:
frappe.throw(_("""No Student Groups created."""))
l = len(self.courses)
for d in self.courses:
if not d.course:
frappe.throw(_("""Course is mandatory in row {0}""".format(d.idx)))
if not d.student_group_name:
frappe.throw(_("""Student Group Name is mandatory in row {0}""".format(d.idx)))
if d.group_based_on == "Course" and not d.course:
frappe.throw(_("""Course is mandatory in row {0}""".format(d.idx)))
if d.group_based_on == "Batch" and not d.batch:
frappe.throw(_("""Batch is mandatory in row {0}""".format(d.idx)))
frappe.publish_realtime('student_group_creation_progress', {"progress": [d.idx, l]}, user=frappe.session.user)
student_group = frappe.new_doc("Student Group")
student_group.group_name = d.student_group_name
student_group.student_group_name = d.student_group_name
student_group.group_based_on = d.group_based_on
student_group.program = self.program
student_group.course = d.course
student_group.max_strength = d.max_strength
student_group.batch = d.batch
student_group.academic_term = self.academic_term
student_group.academic_year = self.academic_year
student_group.save()
frappe.msgprint(_("Student Groups created."))
frappe.msgprint(_("{0} Student Groups created.".format(l)))

View File

@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@ -9,18 +10,54 @@
"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": "group_based_on",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Group Based On",
"length": 0,
"no_copy": 0,
"options": "\nBatch\nCourse",
"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": "course",
"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": "Course",
"length": 0,
"no_copy": 0,
@ -30,32 +67,7 @@
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "course_code",
"fieldtype": "Read Only",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Course Code",
"length": 0,
"no_copy": 0,
"options": "course.course_code",
"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,
@ -63,16 +75,51 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "batch",
"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": "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": "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,
@ -80,6 +127,7 @@
"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,
@ -87,16 +135,20 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "student_group_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Student Group Name",
"length": 0,
"no_copy": 0,
@ -105,6 +157,7 @@
"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,
@ -112,16 +165,51 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "course_code",
"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": "Course Code",
"length": 0,
"no_copy": 0,
"options": "course.course_name",
"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,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "max_strength",
"fieldtype": "Int",
"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": "Max Strength",
"length": 0,
"no_copy": 0,
@ -130,6 +218,7 @@
"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,
@ -137,17 +226,17 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-25 06:40:49.000588",
"modified": "2017-05-15 14:18:23.435415",
"modified_by": "Administrator",
"module": "Schools",
"name": "Student Group Creation Tool Course",
@ -157,7 +246,9 @@
"quick_entry": 0,
"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
}

View File

@ -38,7 +38,7 @@ def execute(filters=None):
def get_columns(filters):
columns = [
_("Student Group") + ":Link/Student Batch:250",
_("Student Group") + ":Link/Student Group:250",
_("Student Group Strength") + "::170",
_("Present") + "::90",
_("Absent") + "::90",

View File

@ -42,18 +42,23 @@ erpnext.selling.InstallationNote = frappe.ui.form.Controller.extend({
},
refresh: function() {
var me = this;
if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(__('From Delivery Note'),
this.frm.add_custom_button(__('From Delivery Note'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_installation_note",
source_doctype: "Delivery Note",
target: me.frm,
date_field: "posting_date",
setters: {
customer: me.frm.doc.customer || undefined,
},
get_query_filters: {
docstatus: 1,
status: ["not in", ["Stopped", "Closed"]],
per_installed: ["<", 99.99],
customer: cur_frm.doc.customer || undefined,
company: cur_frm.doc.company
company: me.frm.doc.company
}
})
}, "fa fa-download", "btn-default"

View File

@ -25,6 +25,8 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
refresh: function(doc, dt, dn) {
this._super(doc, dt, dn);
var me = this;
if(doc.docstatus == 1 && doc.status!=='Lost') {
cur_frm.add_custom_button(__('Make Sales Order'),
cur_frm.cscript['Make Sales Order']);
@ -36,17 +38,24 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
}
if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(__('Opportunity'),
this.frm.add_custom_button(__('Opportunity'),
function() {
var setters = {};
if(me.frm.doc.customer) {
setters.customer = me.frm.doc.customer || undefined;
} else if (me.frm.doc.lead) {
setters.lead = me.frm.doc.lead || undefined;
}
erpnext.utils.map_current_doc({
method: "erpnext.crm.doctype.opportunity.opportunity.make_quotation",
source_doctype: "Opportunity",
target: me.frm,
setters: setters,
get_query_filters: {
status: ["not in", ["Lost", "Closed"]],
enquiry_type: cur_frm.doc.order_type,
customer: cur_frm.doc.customer || undefined,
lead: cur_frm.doc.lead || undefined,
company: cur_frm.doc.company
company: me.frm.doc.company,
// cannot set enquiry_type as setter, as the fieldname is order_type
enquiry_type: me.frm.doc.order_type,
}
})
}, __("Get items from"), "btn-default");

View File

@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "naming_series:",
@ -12,6 +13,7 @@
"editable_grid": 1,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -41,6 +43,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@ -71,6 +74,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -102,6 +106,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -134,6 +139,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@ -166,6 +172,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@ -198,6 +205,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@ -226,6 +234,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -255,6 +264,7 @@
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -287,6 +297,7 @@
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -320,6 +331,7 @@
"width": "150px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -352,6 +364,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -384,6 +397,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -415,6 +429,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -444,6 +459,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -474,6 +490,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -506,6 +523,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -534,6 +552,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -562,6 +581,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -591,6 +611,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -620,6 +641,7 @@
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -649,6 +671,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -677,6 +700,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -710,6 +734,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -740,6 +765,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -769,6 +795,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -801,6 +828,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -834,6 +862,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -862,6 +891,7 @@
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -894,6 +924,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -923,6 +954,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -953,6 +985,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -981,6 +1014,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1011,6 +1045,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1036,13 +1071,14 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "40px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1070,6 +1106,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1100,6 +1137,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1132,6 +1170,7 @@
"width": "100px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1159,6 +1198,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1189,6 +1229,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1218,6 +1259,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1248,6 +1290,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1279,6 +1322,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1306,6 +1350,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1336,6 +1381,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1363,6 +1409,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1394,6 +1441,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1423,6 +1471,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1450,6 +1499,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1481,6 +1531,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1508,6 +1559,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1537,6 +1589,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -1567,6 +1620,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1598,6 +1652,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1628,6 +1683,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1656,6 +1712,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1685,6 +1742,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1714,6 +1772,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1744,6 +1803,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1776,6 +1836,7 @@
"width": "200px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1808,6 +1869,7 @@
"width": "200px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1840,6 +1902,7 @@
"width": "200px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1869,6 +1932,7 @@
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1901,6 +1965,7 @@
"width": "200px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@ -1933,6 +1998,7 @@
"width": "200px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -1964,6 +2030,7 @@
"width": "200px"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -1995,6 +2062,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2026,6 +2094,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2056,6 +2125,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -2085,6 +2155,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@ -2116,6 +2187,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@ -2147,6 +2219,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2175,6 +2248,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2204,6 +2278,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@ -2234,6 +2309,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2265,6 +2341,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2296,6 +2373,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@ -2327,6 +2405,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2356,6 +2435,7 @@
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2388,6 +2468,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2418,6 +2499,7 @@
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@ -2448,19 +2530,19 @@
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-shopping-cart",
"idx": 82,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
"modified": "2017-02-20 13:22:18.466192",
"modified": "2017-05-15 13:05:39.469590",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",

View File

@ -102,7 +102,7 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
target.run_method("calculate_taxes_and_totals")
def update_item(obj, target, source_parent):
target.stock_qty = flt(obj.qty) * flt(obj.conversion_factor)
target.stock_qty = flt(obj.qty) * flt(obj.conversion_factor)
doclist = get_mapped_doc("Quotation", source_name, {
"Quotation": {

View File

@ -136,12 +136,15 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.quotation.quotation.make_sales_order",
source_doctype: "Quotation",
target: me.frm,
setters: {
customer: me.frm.doc.customer || undefined,
order_type: me.frm.doc.order_type,
},
get_query_filters: {
company: me.frm.doc.company,
docstatus: 1,
status: ["!=", "Lost"],
order_type: me.frm.doc.order_type,
customer: me.frm.doc.customer || undefined,
company: me.frm.doc.company
}
})
}, __("Get items from"));

View File

@ -529,8 +529,8 @@ def make_sales_order(**args):
"item_code": args.item or args.item_code or "_Test Item",
"warehouse": args.warehouse,
"qty": args.qty or 10,
"rate": args.rate or 100,
"conversion_factor": 1.0,
"uom": args.uom or None,
"rate": args.rate or 100
})
if not args.do_not_save:

View File

@ -163,6 +163,10 @@ erpnext.SalesFunnel = Class.extend({
draw_legend: function(x_mid, y_mid, width, height, title) {
var context = this.elements.context;
if(y_mid == 0) {
y_mid = 7;
}
// draw line
context.beginPath();
context.moveTo(x_mid, y_mid);

View File

@ -8,6 +8,7 @@ from frappe.utils import cstr
from frappe import msgprint, throw, _
from frappe.model.document import Document
from frappe.model.naming import parse_naming_series
from frappe.permissions import get_doctypes_with_read
class NamingSeriesNotSetError(frappe.ValidationError): pass
@ -136,8 +137,9 @@ class NamingSeries(Document):
def get_current(self, arg=None):
"""get series current"""
if self.prefix:
prefix = self.parse_naming_series()
self.current_value = frappe.db.get_value("Series",
self.prefix.split('.')[0], "current", order_by = "name")
prefix, "current", order_by = "name")
def insert_series(self, series):
"""insert series if missing"""
@ -146,7 +148,7 @@ class NamingSeries(Document):
def update_series_start(self):
if self.prefix:
prefix = self.prefix.split('.')[0]
prefix = self.parse_naming_series()
self.insert_series(prefix)
frappe.db.sql("update `tabSeries` set current = %s where name = %s",
(self.current_value, prefix))
@ -154,6 +156,17 @@ class NamingSeries(Document):
else:
msgprint(_("Please select prefix first"))
def parse_naming_series(self):
parts = self.prefix.split('.')
# If series contain date format like INV.YYYY.MM.#####
if len(parts) > 2:
del parts[-1] # Removed ### from the series
prefix = parse_naming_series(parts)
else:
prefix = parts[0]
return prefix
def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True):
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
if naming_series:

View File

@ -79,7 +79,7 @@
"bold": 1,
"collapsible": 0,
"columns": 0,
"description": "Only leaf nodes are allowed in transaction",
"description": "",
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
@ -478,4 +478,4 @@
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
}
}

View File

@ -119,13 +119,16 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_delivery_note",
source_doctype: "Sales Order",
target: me.frm,
setters: {
customer: me.frm.doc.customer || undefined,
},
get_query_filters: {
docstatus: 1,
status: ["!=", "Closed"],
per_delivered: ["<", 99.99],
company: me.frm.doc.company,
project: me.frm.doc.project || undefined,
customer: me.frm.doc.customer || undefined,
company: me.frm.doc.company
}
})
}, __("Get items from"));

View File

@ -65,7 +65,8 @@ frappe.ui.form.on("Item", {
frm.page.set_inner_btn_group_as_primary(__("Make"));
}
if (frm.doc.variant_of) {
frm.set_intro(__("This Item is a Variant of {0} (Template). Attributes will be copied over from the template unless 'No Copy' is set", [frm.doc.variant_of]), true);
frm.set_intro(__("This Item is a Variant of {0} (Template). Attributes will be copied over from the template unless 'No Copy' is set",
[frm.doc.variant_of]), true);
}
if (frappe.defaults.get_default("item_naming_by")!="Naming Series" || frm.doc.variant_of) {
@ -96,6 +97,8 @@ frappe.ui.form.on("Item", {
}
frappe.set_route('Form', 'Item', new_item.name);
});
frm.trigger('make_variant_fields_read_only');
},
validate: function(frm){
@ -106,6 +109,16 @@ frappe.ui.form.on("Item", {
refresh_field("image_view");
},
make_variant_fields_read_only: function(frm) {
if(frm.doc.variant_of) {
frm.meta.fields.forEach(function(df) {
if (!df.no_copy) {
frm.toggle_enable(df.fieldname, false);
}
});
}
},
is_fixed_asset: function(frm) {
if (frm.doc.is_fixed_asset) {
frm.set_value("is_stock_item", 0);

View File

@ -513,6 +513,39 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:!doc.__islocal",
"description": "",
"fieldname": "tolerance",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow over delivery or receipt upto this percent",
"length": 0,
"no_copy": 0,
"oldfieldname": "tolerance",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@ -800,39 +833,6 @@
"unique": 0,
"width": "50%"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_stock_item",
"description": "",
"fieldname": "tolerance",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow over delivery or receipt upto this percent",
"length": 0,
"no_copy": 0,
"oldfieldname": "tolerance",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
@ -3143,7 +3143,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 1,
"modified": "2017-05-03 09:55:11.624283",
"modified": "2017-05-15 11:49:47.525859",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@ -86,6 +86,7 @@ class Item(WebsiteGenerator):
self.validate_has_variants()
self.validate_attributes()
self.validate_variant_attributes()
self.copy_variant_attributes()
self.validate_website_image()
self.make_thumbnail()
self.validate_fixed_asset()
@ -616,7 +617,9 @@ class Item(WebsiteGenerator):
template_item.save()
def update_variants(self):
if self.has_variants and not self.flags.dont_update_variants:
if self.flags.dont_update_variants:
return
if self.has_variants:
updated = []
variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name })
for d in variants:
@ -625,7 +628,7 @@ class Item(WebsiteGenerator):
variant.save()
updated.append(d.item_code)
if updated:
frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
frappe.msgprint(_("Item Variants {0} updated").format(", ".join(updated)))
def validate_has_variants(self):
if not self.has_variants and frappe.db.get_value("Item", self.name, "has_variants"):
@ -670,6 +673,12 @@ class Item(WebsiteGenerator):
validate_item_variant_attributes(self, args)
def copy_variant_attributes(self):
'''Copy attributes from template (if they have been changed before saving)'''
if self.variant_of:
template = frappe.get_doc('Item', self.variant_of)
copy_attributes_to_variant(template, self)
def get_timeline_data(doctype, name):
'''returns timeline data based on stock ledger entry'''
out = {}

View File

@ -95,16 +95,19 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
}
if (this.frm.doc.docstatus===0) {
cur_frm.add_custom_button(__('Sales Order'),
this.frm.add_custom_button(__('Sales Order'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_material_request",
source_doctype: "Sales Order",
target: me.frm,
setters: {
company: me.frm.doc.company
},
get_query_filters: {
docstatus: 1,
status: ["!=", "Closed"],
per_delivered: ["<", 99.99],
company: cur_frm.doc.company
}
})
}, __("Get items from"));

View File

@ -1,13 +1,14 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
$.extend(cur_frm.cscript, {
refresh: function() {
cur_frm.add_custom_button(__("Add / Edit Prices"), function() {
frappe.ui.form.on("Price List", {
refresh: function(frm) {
let me = this;
frm.add_custom_button(__("Add / Edit Prices"), function() {
frappe.route_options = {
"price_list": cur_frm.doc.name
"price_list": frm.doc.name
};
frappe.set_route("Report", "Item Price");
}, "fa fa-money");
}
});
});

View File

@ -43,6 +43,7 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
},
refresh: function() {
var me = this;
this._super();
if(this.frm.doc.docstatus===1) {
this.show_stock_ledger();
@ -53,17 +54,20 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
if(!this.frm.doc.is_return && this.frm.doc.status!="Closed") {
if(this.frm.doc.docstatus==0) {
cur_frm.add_custom_button(__('Purchase Order'),
this.frm.add_custom_button(__('Purchase Order'),
function() {
erpnext.utils.map_current_doc({
method: "erpnext.buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
source_doctype: "Purchase Order",
target: me.frm,
setters: {
supplier: me.frm.doc.supplier || undefined,
},
get_query_filters: {
supplier: cur_frm.doc.supplier || undefined,
docstatus: 1,
status: ["!=", "Closed"],
per_received: ["<", 99.99],
company: cur_frm.doc.company
company: me.frm.doc.company
}
})
}, __("Get items from"));

View File

@ -2,6 +2,7 @@
import frappe
from erpnext.utilities.activation import get_level
from frappe.utils import cstr
def update_doctypes():
for d in frappe.db.sql("""select df.parent, df.fieldname
@ -26,7 +27,7 @@ def get_site_info(site_info):
company = company[0][0] if company else None
if company:
domain = frappe.db.get_value('Company', company, 'domain')
domain = frappe.db.get_value('Company', cstr(company), 'domain')
return {
'company': company,

View File

@ -18,6 +18,10 @@ class TransactionBase(StatusUpdater):
frappe.db.get_value("Notification Control", None, dt + "_message"))
def validate_posting_time(self):
# set Edit Posting Date and Time to 1 while data import
if frappe.flags.in_import:
self.set_posting_time = 1
if not getattr(self, 'set_posting_time', None):
now = now_datetime()
self.posting_date = now.strftime('%Y-%m-%d')