mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-25 16:04:46 +00:00
moved directory structure
This commit is contained in:
1
selling/doctype/quotation/__init__.py
Normal file
1
selling/doctype/quotation/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from __future__ import unicode_literals
|
||||
340
selling/doctype/quotation/quotation.js
Normal file
340
selling/doctype/quotation/quotation.js
Normal file
@@ -0,0 +1,340 @@
|
||||
// ERPNext - web based ERP (http://erpnext.com)
|
||||
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Module CRM
|
||||
cur_frm.cscript.tname = "Quotation Item";
|
||||
cur_frm.cscript.fname = "quotation_details";
|
||||
cur_frm.cscript.other_fname = "other_charges";
|
||||
cur_frm.cscript.sales_team_fname = "sales_team";
|
||||
|
||||
// =====================================================================================
|
||||
wn.require('erpnext/selling/doctype/sales_common/sales_common.js');
|
||||
wn.require('erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js');
|
||||
wn.require('erpnext/utilities/doctype/sms_control/sms_control.js');
|
||||
wn.require('erpnext/setup/doctype/notification_control/notification_control.js');
|
||||
wn.require('erpnext/support/doctype/communication/communication.js');
|
||||
|
||||
// ONLOAD
|
||||
// ===================================================================================
|
||||
cur_frm.cscript.onload = function(doc, cdt, cdn) {
|
||||
if(!doc.quotation_to) hide_field(['customer','customer_address','contact_person','customer_name','lead', 'lead_name', 'address_display', 'contact_display', 'contact_mobile', 'contact_email', 'territory', 'customer_group']);
|
||||
if(!doc.price_list_name) set_multiple(cdt,cdn,{price_list_name:sys_defaults.price_list_name});
|
||||
if(!doc.status) set_multiple(cdt,cdn,{status:'Draft'});
|
||||
if(!doc.transaction_date) set_multiple(cdt,cdn,{transaction_date:get_today()});
|
||||
if(!doc.conversion_rate) set_multiple(cdt,cdn,{conversion_rate:'1.00'});
|
||||
if(!doc.currency && sys_defaults.currency) set_multiple(cdt,cdn,{currency:sys_defaults.currency});
|
||||
if(!doc.price_list_currency) set_multiple(cdt, cdn, {price_list_currency: doc.currency, plc_conversion_rate: 1});
|
||||
|
||||
if(!doc.company && sys_defaults.company) set_multiple(cdt,cdn,{company:sys_defaults.company});
|
||||
if(!doc.fiscal_year && sys_defaults.fiscal_year) set_multiple(cdt,cdn,{fiscal_year:sys_defaults.fiscal_year});
|
||||
|
||||
if(doc.quotation_to) {
|
||||
if(doc.quotation_to == 'Customer') {
|
||||
hide_field(['lead', 'lead_name', 'organization']);
|
||||
}
|
||||
else if (doc.quotation_to == 'Lead') {
|
||||
hide_field(['customer','customer_address','contact_person', 'customer_name','contact_display', 'customer_group']);
|
||||
}
|
||||
}
|
||||
cur_frm.cscript.make_communication_body();
|
||||
}
|
||||
|
||||
cur_frm.cscript.onload_post_render = function(doc, dt, dn) {
|
||||
var callback = function(doc, dt, dn) {
|
||||
// defined in sales_common.js
|
||||
cur_frm.cscript.update_item_details(doc, dt, dn);
|
||||
}
|
||||
cur_frm.cscript.hide_price_list_currency(doc, dt, dn, callback);
|
||||
}
|
||||
|
||||
// hide - unhide fields based on lead or customer..
|
||||
// =======================================================================================================================
|
||||
cur_frm.cscript.lead_cust_show = function(doc,cdt,cdn){
|
||||
hide_field(['lead', 'lead_name','customer','customer_address','contact_person',
|
||||
'customer_name','address_display','contact_display','contact_mobile','contact_email',
|
||||
'territory','customer_group', 'organization']);
|
||||
if(doc.quotation_to == 'Lead') unhide_field(['lead']);
|
||||
else if(doc.quotation_to == 'Customer') unhide_field(['customer']);
|
||||
|
||||
doc.lead = doc.lead_name = doc.customer = doc.customer_name = doc.customer_address = doc.contact_person = doc.address_display = doc.contact_display = doc.contact_mobile = doc.contact_email = doc.territory = doc.customer_group = doc.organization = "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================ hide - unhide fields on basis of quotation to either lead or customer ===============================
|
||||
cur_frm.cscript.quotation_to = function(doc,cdt,cdn){
|
||||
cur_frm.cscript.lead_cust_show(doc,cdt,cdn);
|
||||
}
|
||||
|
||||
|
||||
// REFRESH
|
||||
// ===================================================================================
|
||||
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
|
||||
|
||||
cur_frm.clear_custom_buttons();
|
||||
|
||||
if (!cur_frm.cscript.is_onload) cur_frm.cscript.hide_price_list_currency(doc, cdt, cdn);
|
||||
|
||||
|
||||
if(doc.docstatus == 1 && doc.status!='Order Lost') {
|
||||
cur_frm.add_custom_button('Make Sales Order', cur_frm.cscript['Make Sales Order']);
|
||||
cur_frm.add_custom_button('Set as Lost', cur_frm.cscript['Declare Order Lost']);
|
||||
cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
|
||||
}
|
||||
|
||||
erpnext.hide_naming_series();
|
||||
|
||||
if(doc.customer || doc.lead) $(cur_frm.fields_dict.contact_section.row.wrapper).toggle(true);
|
||||
else $(cur_frm.fields_dict.contact_section.row.wrapper).toggle(false);
|
||||
|
||||
if (!doc.__islocal) cur_frm.cscript.render_communication_list(doc, cdt, cdn);
|
||||
}
|
||||
|
||||
|
||||
//customer
|
||||
cur_frm.cscript.customer = function(doc,dt,dn) {
|
||||
var pl = doc.price_list_name;
|
||||
var callback = function(r,rt) {
|
||||
var doc = locals[cur_frm.doctype][cur_frm.docname];
|
||||
cur_frm.refresh();
|
||||
if (pl != doc.price_list_name) cur_frm.cscript.price_list_name(doc, dt, dn);
|
||||
}
|
||||
|
||||
if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name),
|
||||
'get_default_customer_address', '', callback);
|
||||
if(doc.customer) unhide_field(['customer_address','contact_person','territory', 'customer_group']);
|
||||
}
|
||||
|
||||
cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc,dt,dn) {
|
||||
if(doc.customer) get_server_fields('get_customer_address', JSON.stringify({
|
||||
customer: doc.customer,
|
||||
address: doc.customer_address,
|
||||
contact: doc.contact_person
|
||||
}),'', doc, dt, dn, 1);
|
||||
}
|
||||
|
||||
cur_frm.fields_dict.customer_address.on_new = function(dn) {
|
||||
locals['Address'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
|
||||
locals['Address'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
|
||||
}
|
||||
|
||||
cur_frm.fields_dict.contact_person.on_new = function(dn) {
|
||||
locals['Contact'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
|
||||
locals['Contact'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) {
|
||||
return 'SELECT name,address_line1,city FROM tabAddress WHERE customer = "'+ doc.customer +'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
|
||||
return 'SELECT name,CONCAT(first_name," ",ifnull(last_name,"")) As FullName,department,designation FROM tabContact WHERE customer = "'+ doc.customer +'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
|
||||
}
|
||||
|
||||
//lead
|
||||
cur_frm.fields_dict['lead'].get_query = function(doc,cdt,cdn){
|
||||
return 'SELECT `tabLead`.name, `tabLead`.lead_name FROM `tabLead` WHERE `tabLead`.%(key)s LIKE "%s" ORDER BY `tabLead`.`name` ASC LIMIT 50';
|
||||
}
|
||||
|
||||
cur_frm.cscript.lead = function(doc, cdt, cdn) {
|
||||
if(doc.lead) {
|
||||
get_server_fields('get_lead_details', doc.lead,'', doc, cdt, cdn, 1);
|
||||
unhide_field('territory');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// =====================================================================================
|
||||
cur_frm.fields_dict['enq_no'].get_query = function(doc,cdt,cdn){
|
||||
var cond='';
|
||||
var cond1='';
|
||||
if(doc.order_type) cond = 'ifnull(`tabOpportunity`.enquiry_type, "") = "'+doc.order_type+'" AND';
|
||||
if(doc.customer) cond1 = '`tabOpportunity`.customer = "'+doc.customer+'" AND';
|
||||
else if(doc.lead) cond1 = '`tabOpportunity`.lead = "'+doc.lead+'" AND';
|
||||
|
||||
return repl('SELECT `tabOpportunity`.`name` FROM `tabOpportunity` WHERE `tabOpportunity`.`docstatus` = 1 AND `tabOpportunity`.status = "Submitted" AND %(cond)s %(cond1)s `tabOpportunity`.`name` LIKE "%s" ORDER BY `tabOpportunity`.`name` ASC LIMIT 50', {cond:cond, cond1:cond1});
|
||||
}
|
||||
|
||||
// Make Sales Order
|
||||
// =====================================================================================
|
||||
cur_frm.cscript['Make Sales Order'] = function() {
|
||||
var doc = cur_frm.doc;
|
||||
|
||||
if (doc.docstatus == 1) {
|
||||
var n = createLocal("Sales Order");
|
||||
$c('dt_map', args={
|
||||
'docs':compress_doclist([locals["Sales Order"][n]]),
|
||||
'from_doctype':'Quotation',
|
||||
'to_doctype':'Sales Order',
|
||||
'from_docname':doc.name,
|
||||
'from_to_list':"[['Quotation', 'Sales Order'], ['Quotation Item', 'Sales Order Item'],['Sales Taxes and Charges','Sales Taxes and Charges'], ['Sales Team', 'Sales Team'], ['TC Detail', 'TC Detail']]"
|
||||
}, function(r,rt) {
|
||||
loaddoc("Sales Order", n);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//pull enquiry details
|
||||
cur_frm.cscript.pull_enquiry_detail = function(doc,cdt,cdn){
|
||||
|
||||
var callback = function(r,rt){
|
||||
if(r.message){
|
||||
doc.quotation_to = r.message;
|
||||
|
||||
if(doc.quotation_to == 'Lead') {
|
||||
unhide_field('lead');
|
||||
}
|
||||
else if(doc.quotation_to == 'Customer') {
|
||||
unhide_field(['customer','customer_address','contact_person','territory','customer_group']);
|
||||
}
|
||||
refresh_many(['quotation_details','quotation_to','customer','customer_address','contact_person','lead','lead_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group','order_type']);
|
||||
}
|
||||
}
|
||||
|
||||
$c_obj(make_doclist(doc.doctype, doc.name),'pull_enq_details','',callback);
|
||||
|
||||
}
|
||||
|
||||
// declare order lost
|
||||
//-------------------------
|
||||
cur_frm.cscript['Declare Order Lost'] = function(){
|
||||
var qtn_lost_dialog;
|
||||
|
||||
set_qtn_lost_dialog = function(doc,cdt,cdn){
|
||||
qtn_lost_dialog = new Dialog(400,400,'Add Quotation Lost Reason');
|
||||
qtn_lost_dialog.make_body([
|
||||
['HTML', 'Message', '<div class="comment">Please add quotation lost reason</div>'],
|
||||
['Text', 'Quotation Lost Reason'],
|
||||
['HTML', 'Response', '<div class = "comment" id="update_quotation_dialog_response"></div>'],
|
||||
['HTML', 'Add Reason', '<div></div>']
|
||||
]);
|
||||
|
||||
var add_reason_btn1 = $a($i(qtn_lost_dialog.widgets['Add Reason']), 'button', 'button');
|
||||
add_reason_btn1.innerHTML = 'Add';
|
||||
add_reason_btn1.onclick = function(){ qtn_lost_dialog.add(); }
|
||||
|
||||
var add_reason_btn2 = $a($i(qtn_lost_dialog.widgets['Add Reason']), 'button', 'button');
|
||||
add_reason_btn2.innerHTML = 'Cancel';
|
||||
$y(add_reason_btn2,{marginLeft:'4px'});
|
||||
add_reason_btn2.onclick = function(){ qtn_lost_dialog.hide();}
|
||||
|
||||
qtn_lost_dialog.onshow = function() {
|
||||
qtn_lost_dialog.widgets['Quotation Lost Reason'].value = '';
|
||||
$i('update_quotation_dialog_response').innerHTML = '';
|
||||
}
|
||||
|
||||
qtn_lost_dialog.add = function() {
|
||||
// sending...
|
||||
$i('update_quotation_dialog_response').innerHTML = 'Processing...';
|
||||
var arg = strip(qtn_lost_dialog.widgets['Quotation Lost Reason'].value);
|
||||
var call_back = function(r,rt) {
|
||||
if(r.message == 'true'){
|
||||
$i('update_quotation_dialog_response').innerHTML = 'Done';
|
||||
qtn_lost_dialog.hide();
|
||||
}
|
||||
}
|
||||
if(arg) $c_obj(make_doclist(cur_frm.doc.doctype, cur_frm.doc.name),'declare_order_lost',arg,call_back);
|
||||
else msgprint("Please add Quotation lost reason");
|
||||
}
|
||||
}
|
||||
|
||||
if(!qtn_lost_dialog){
|
||||
set_qtn_lost_dialog(doc,cdt,cdn);
|
||||
}
|
||||
qtn_lost_dialog.show();
|
||||
}
|
||||
|
||||
//===================== Quotation to validation - either customer or lead mandatory ====================
|
||||
cur_frm.cscript.quot_to_validate = function(doc,cdt,cdn){
|
||||
|
||||
if(doc.quotation_to == 'Lead'){
|
||||
|
||||
if(!doc.lead){
|
||||
alert("Lead is mandatory.");
|
||||
validated = false;
|
||||
}
|
||||
}
|
||||
else if(doc.quotation_to == 'Customer'){
|
||||
if(!doc.customer){
|
||||
alert("Customer is mandatory.");
|
||||
validated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===================validation function =================================
|
||||
|
||||
cur_frm.cscript.validate = function(doc,cdt,cdn){
|
||||
cur_frm.cscript.recalculate_values(doc, cdt, cdn);
|
||||
cur_frm.cscript.quot_to_validate(doc,cdt,cdn);
|
||||
}
|
||||
|
||||
//================ Last Quoted Price and Last Sold Price suggestion ======================
|
||||
cur_frm.fields_dict['quotation_details'].grid.get_field('item_code').get_query= function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
var cond = (doc.order_type == 'Maintenance') ? " and item.is_service_item = 'Yes'" : " and item.is_sales_item = 'Yes'";
|
||||
if(doc.customer) {
|
||||
var export_rate_field = wn.meta.get_docfield(cdt, 'export_rate', cdn);
|
||||
var precision = (export_rate_field && export_rate_field.fieldtype) === 'Float' ? 6 : 2;
|
||||
return repl("\
|
||||
select \
|
||||
item.name, \
|
||||
( \
|
||||
select concat('Last Quote @ ', q.currency, ' ', \
|
||||
format(q_item.export_rate, %(precision)s)) \
|
||||
from `tabQuotation` q, `tabQuotation Item` q_item \
|
||||
where \
|
||||
q.name = q_item.parent \
|
||||
and q_item.item_code = item.name \
|
||||
and q.docstatus = 1 \
|
||||
and q.customer = \"%(cust)s\" \
|
||||
order by q.transaction_date desc \
|
||||
limit 1 \
|
||||
) as quote_rate, \
|
||||
( \
|
||||
select concat('Last Sale @ ', si.currency, ' ', \
|
||||
format(si_item.basic_rate, %(precision)s)) \
|
||||
from `tabSales Invoice` si, `tabSales Invoice Item` si_item \
|
||||
where \
|
||||
si.name = si_item.parent \
|
||||
and si_item.item_code = item.name \
|
||||
and si.docstatus = 1 \
|
||||
and si.customer = \"%(cust)s\" \
|
||||
order by si.voucher_date desc \
|
||||
limit 1 \
|
||||
) as sales_rate, \
|
||||
item.item_name, item.description \
|
||||
from `tabItem` item \
|
||||
where \
|
||||
item.%(key)s like \"%s\" \
|
||||
%(cond)s \
|
||||
limit 25", {
|
||||
cust: doc.customer,
|
||||
cond: cond,
|
||||
precision: precision
|
||||
});
|
||||
} else {
|
||||
return repl("SELECT name, item_name, description FROM `tabItem` item WHERE item.%(key)s LIKE '%s' %(cond)s ORDER BY item.item_code DESC LIMIT 50", {cond:cond});
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
|
||||
var args = {
|
||||
type: 'Quotation',
|
||||
doctype: 'Quotation'
|
||||
}
|
||||
cur_frm.cscript.notify(doc, args);
|
||||
}
|
||||
355
selling/doctype/quotation/quotation.py
Normal file
355
selling/doctype/quotation/quotation.py
Normal file
@@ -0,0 +1,355 @@
|
||||
# ERPNext - web based ERP (http://erpnext.com)
|
||||
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Please edit this list and import only required elements
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, load_json
|
||||
from webnotes.model import db_exists
|
||||
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
|
||||
from webnotes.model.doclist import getlist, copy_doclist
|
||||
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
|
||||
from webnotes import session, form, is_testing, msgprint, errprint
|
||||
|
||||
set = webnotes.conn.set
|
||||
sql = webnotes.conn.sql
|
||||
get_value = webnotes.conn.get_value
|
||||
in_transaction = webnotes.conn.in_transaction
|
||||
convert_to_lists = webnotes.conn.convert_to_lists
|
||||
|
||||
# -----------------------------------------------------------------------------------------
|
||||
|
||||
from utilities.transaction_base import TransactionBase
|
||||
|
||||
class DocType(TransactionBase):
|
||||
def __init__(self, doc, doclist=[]):
|
||||
self.doc = doc
|
||||
self.doclist = doclist
|
||||
self.tname = 'Quotation Item'
|
||||
self.fname = 'quotation_details'
|
||||
|
||||
# Autoname
|
||||
# ---------
|
||||
def autoname(self):
|
||||
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
|
||||
|
||||
|
||||
# DOCTYPE TRIGGER FUNCTIONS
|
||||
# ==============================================================================
|
||||
|
||||
# Pull Opportunity Details
|
||||
# --------------------
|
||||
def pull_enq_details(self):
|
||||
self.doclist = self.doc.clear_table(self.doclist, 'quotation_details')
|
||||
get_obj('DocType Mapper', 'Opportunity-Quotation').dt_map('Opportunity', 'Quotation', self.doc.enq_no, self.doc, self.doclist, "[['Opportunity', 'Quotation'],['Opportunity Item', 'Quotation Item']]")
|
||||
|
||||
self.get_adj_percent()
|
||||
|
||||
return self.doc.quotation_to
|
||||
|
||||
# Get contact person details based on customer selected
|
||||
# ------------------------------------------------------
|
||||
def get_contact_details(self):
|
||||
return get_obj('Sales Common').get_contact_details(self,0)
|
||||
|
||||
|
||||
|
||||
# QUOTATION DETAILS TRIGGER FUNCTIONS
|
||||
# ================================================================================
|
||||
|
||||
# Get Item Details
|
||||
# -----------------
|
||||
def get_item_details(self, args=None):
|
||||
import json
|
||||
args = args and json.loads(args) or {}
|
||||
if args.get('item_code'):
|
||||
return get_obj('Sales Common').get_item_details(args, self)
|
||||
else:
|
||||
obj = get_obj('Sales Common')
|
||||
for doc in self.doclist:
|
||||
if doc.fields.get('item_code'):
|
||||
arg = {
|
||||
'item_code': doc.fields.get('item_code'),
|
||||
'income_account': doc.fields.get('income_account'),
|
||||
'cost_center': doc.fields.get('cost_center'),
|
||||
'warehouse': doc.fields.get('warehouse')
|
||||
}
|
||||
res = obj.get_item_details(arg, self) or {}
|
||||
for r in res:
|
||||
if not doc.fields.get(r):
|
||||
doc.fields[r] = res[r]
|
||||
|
||||
# Re-calculates Basic Rate & amount based on Price List Selected
|
||||
# --------------------------------------------------------------
|
||||
def get_adj_percent(self, arg=''):
|
||||
get_obj('Sales Common').get_adj_percent(self)
|
||||
|
||||
|
||||
|
||||
|
||||
# OTHER CHARGES TRIGGER FUNCTIONS
|
||||
# ====================================================================================
|
||||
|
||||
# Get Tax rate if account type is TAX
|
||||
# -----------------------------------
|
||||
def get_rate(self,arg):
|
||||
return get_obj('Sales Common').get_rate(arg)
|
||||
|
||||
# Load Default Charges
|
||||
# ----------------------------------------------------------
|
||||
def load_default_taxes(self):
|
||||
self.doclist = get_obj('Sales Common').load_default_taxes(self)
|
||||
|
||||
# Pull details from other charges master (Get Sales Taxes and Charges Master)
|
||||
# ----------------------------------------------------------
|
||||
def get_other_charges(self):
|
||||
self.doclist = get_obj('Sales Common').get_other_charges(self)
|
||||
|
||||
|
||||
# GET TERMS AND CONDITIONS
|
||||
# ====================================================================================
|
||||
def get_tc_details(self):
|
||||
return get_obj('Sales Common').get_tc_details(self)
|
||||
|
||||
|
||||
# VALIDATE
|
||||
# ==============================================================================================
|
||||
|
||||
# Amendment date is necessary if document is amended
|
||||
# --------------------------------------------------
|
||||
def validate_mandatory(self):
|
||||
if self.doc.amended_from and not self.doc.amendment_date:
|
||||
msgprint("Please Enter Amendment Date")
|
||||
raise Exception
|
||||
|
||||
# Fiscal Year Validation
|
||||
# ----------------------
|
||||
def validate_fiscal_year(self):
|
||||
get_obj('Sales Common').validate_fiscal_year(self.doc.fiscal_year,self.doc.transaction_date,'Quotation Date')
|
||||
|
||||
# Does not allow same item code to be entered twice
|
||||
# -------------------------------------------------
|
||||
def validate_for_items(self):
|
||||
chk_dupl_itm = []
|
||||
for d in getlist(self.doclist,'quotation_details'):
|
||||
if [cstr(d.item_code),cstr(d.description)] in chk_dupl_itm:
|
||||
msgprint("Item %s has been entered twice. Please change description atleast to continue" % d.item_code)
|
||||
raise Exception
|
||||
else:
|
||||
chk_dupl_itm.append([cstr(d.item_code),cstr(d.description)])
|
||||
|
||||
|
||||
#do not allow sales item in maintenance quotation and service item in sales quotation
|
||||
#-----------------------------------------------------------------------------------------------
|
||||
def validate_order_type(self):
|
||||
if self.doc.order_type in ['Maintenance', 'Service']:
|
||||
for d in getlist(self.doclist, 'quotation_details'):
|
||||
is_service_item = sql("select is_service_item from `tabItem` where name=%s", d.item_code)
|
||||
is_service_item = is_service_item and is_service_item[0][0] or 'No'
|
||||
|
||||
if is_service_item == 'No':
|
||||
msgprint("You can not select non service item "+d.item_code+" in Maintenance Quotation")
|
||||
raise Exception
|
||||
else:
|
||||
for d in getlist(self.doclist, 'quotation_details'):
|
||||
is_sales_item = sql("select is_sales_item from `tabItem` where name=%s", d.item_code)
|
||||
is_sales_item = is_sales_item and is_sales_item[0][0] or 'No'
|
||||
|
||||
if is_sales_item == 'No':
|
||||
msgprint("You can not select non sales item "+d.item_code+" in Sales Quotation")
|
||||
raise Exception
|
||||
|
||||
#--------------Validation For Last Contact Date-----------------
|
||||
# ====================================================================================================================
|
||||
def set_last_contact_date(self):
|
||||
#if not self.doc.contact_date_ref:
|
||||
#self.doc.contact_date_ref=self.doc.contact_date
|
||||
#self.doc.last_contact_date=self.doc.contact_date_ref
|
||||
if self.doc.contact_date_ref and self.doc.contact_date_ref != self.doc.contact_date:
|
||||
if getdate(self.doc.contact_date_ref) < getdate(self.doc.contact_date):
|
||||
self.doc.last_contact_date=self.doc.contact_date_ref
|
||||
else:
|
||||
msgprint("Contact Date Cannot be before Last Contact Date")
|
||||
raise Exception
|
||||
#set(self.doc, 'contact_date_ref',self.doc.contact_date)
|
||||
|
||||
|
||||
# Validate
|
||||
# --------
|
||||
def validate(self):
|
||||
self.validate_fiscal_year()
|
||||
self.validate_mandatory()
|
||||
self.set_last_contact_date()
|
||||
self.validate_order_type()
|
||||
self.validate_for_items()
|
||||
sales_com_obj = get_obj('Sales Common')
|
||||
sales_com_obj.check_active_sales_items(self)
|
||||
sales_com_obj.validate_max_discount(self,'quotation_details') #verify whether rate is not greater than max_discount
|
||||
sales_com_obj.check_conversion_rate(self)
|
||||
|
||||
# Get total in words
|
||||
dcc = TransactionBase().get_company_currency(self.doc.company)
|
||||
self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total)
|
||||
self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export)
|
||||
|
||||
def on_update(self):
|
||||
# Add to calendar
|
||||
if self.doc.contact_date and self.doc.contact_date_ref != self.doc.contact_date:
|
||||
if self.doc.contact_by:
|
||||
self.add_calendar_event()
|
||||
set(self.doc, 'contact_date_ref',self.doc.contact_date)
|
||||
|
||||
# Set Quotation Status
|
||||
set(self.doc, 'status', 'Draft')
|
||||
|
||||
# subject for follow
|
||||
self.doc.subject = '[%(status)s] To %(customer)s worth %(currency)s %(grand_total)s' % self.doc.fields
|
||||
|
||||
|
||||
# Add to Calendar
|
||||
# ====================================================================================================================
|
||||
def add_calendar_event(self):
|
||||
desc=''
|
||||
user_lst =[]
|
||||
if self.doc.customer:
|
||||
if self.doc.contact_person:
|
||||
desc = 'Contact '+cstr(self.doc.contact_person)
|
||||
else:
|
||||
desc = 'Contact customer '+cstr(self.doc.customer)
|
||||
elif self.doc.lead:
|
||||
if self.doc.lead_name:
|
||||
desc = 'Contact '+cstr(self.doc.lead_name)
|
||||
else:
|
||||
desc = 'Contact lead '+cstr(self.doc.lead)
|
||||
desc = desc+ '.By : ' + cstr(self.doc.contact_by)
|
||||
|
||||
if self.doc.to_discuss:
|
||||
desc = desc+' To Discuss : ' + cstr(self.doc.to_discuss)
|
||||
|
||||
ev = Document('Event')
|
||||
ev.description = desc
|
||||
ev.event_date = self.doc.contact_date
|
||||
ev.event_hour = '10:00'
|
||||
ev.event_type = 'Private'
|
||||
ev.ref_type = 'Opportunity'
|
||||
ev.ref_name = self.doc.name
|
||||
ev.save(1)
|
||||
|
||||
user_lst.append(self.doc.owner)
|
||||
|
||||
chk = sql("select t1.name from `tabProfile` t1, `tabSales Person` t2 where t2.email_id = t1.name and t2.name=%s",self.doc.contact_by)
|
||||
if chk:
|
||||
user_lst.append(chk[0][0])
|
||||
|
||||
for d in user_lst:
|
||||
ch = addchild(ev, 'event_individuals', 'Event User', 0)
|
||||
ch.person = d
|
||||
ch.save(1)
|
||||
|
||||
#update enquiry
|
||||
#------------------
|
||||
def update_enquiry(self, flag):
|
||||
prevdoc=''
|
||||
for d in getlist(self.doclist, 'quotation_details'):
|
||||
if d.prevdoc_docname:
|
||||
prevdoc = d.prevdoc_docname
|
||||
|
||||
if prevdoc:
|
||||
if flag == 'submit': #on submit
|
||||
sql("update `tabOpportunity` set status = 'Quotation Sent' where name = %s", prevdoc)
|
||||
elif flag == 'cancel': #on cancel
|
||||
sql("update `tabOpportunity` set status = 'Open' where name = %s", prevdoc)
|
||||
elif flag == 'order lost': #order lost
|
||||
sql("update `tabOpportunity` set status = 'Opportunity Lost' where name=%s", prevdoc)
|
||||
elif flag == 'order confirm': #order confirm
|
||||
sql("update `tabOpportunity` set status='Order Confirmed' where name=%s", prevdoc)
|
||||
|
||||
# declare as order lost
|
||||
#-------------------------
|
||||
def declare_order_lost(self,arg):
|
||||
chk = sql("select t1.name from `tabSales Order` t1, `tabSales Order Item` t2 where t2.parent = t1.name and t1.docstatus=1 and t2.prevdoc_docname = %s",self.doc.name)
|
||||
if chk:
|
||||
msgprint("Sales Order No. "+cstr(chk[0][0])+" is submitted against this Quotation. Thus 'Order Lost' can not be declared against it.")
|
||||
raise Exception
|
||||
else:
|
||||
set(self.doc, 'status', 'Order Lost')
|
||||
set(self.doc, 'order_lost_reason', arg)
|
||||
self.update_enquiry('order lost')
|
||||
return 'true'
|
||||
|
||||
#check if value entered in item table
|
||||
#--------------------------------------
|
||||
def check_item_table(self):
|
||||
if not getlist(self.doclist, 'quotation_details'):
|
||||
msgprint("Please enter item details")
|
||||
raise Exception
|
||||
|
||||
# ON SUBMIT
|
||||
# =========================================================================
|
||||
def on_submit(self):
|
||||
self.check_item_table()
|
||||
if not self.doc.amended_from:
|
||||
set(self.doc, 'message', 'Quotation: '+self.doc.name+' has been sent')
|
||||
else:
|
||||
set(self.doc, 'message', 'Quotation has been amended. New Quotation no:'+self.doc.name)
|
||||
|
||||
# Check for Approving Authority
|
||||
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self)
|
||||
|
||||
# Set Quotation Status
|
||||
set(self.doc, 'status', 'Submitted')
|
||||
|
||||
#update enquiry status
|
||||
self.update_enquiry('submit')
|
||||
|
||||
|
||||
# ON CANCEL
|
||||
# ==========================================================================
|
||||
def on_cancel(self):
|
||||
set(self.doc, 'message', 'Quotation: '+self.doc.name+' has been cancelled')
|
||||
|
||||
#update enquiry status
|
||||
self.update_enquiry('cancel')
|
||||
|
||||
set(self.doc,'status','Cancelled')
|
||||
|
||||
|
||||
# SEND SMS
|
||||
# =============================================================================
|
||||
def send_sms(self):
|
||||
if not self.doc.customer_mobile_no:
|
||||
msgprint("Please enter customer mobile no")
|
||||
elif not self.doc.message:
|
||||
msgprint("Please enter the message you want to send")
|
||||
else:
|
||||
msgprint(get_obj("SMS Control", "SMS Control").send_sms([self.doc.contact_mobile,], self.doc.message))
|
||||
|
||||
# Print other charges
|
||||
# ===========================================================================
|
||||
def print_other_charges(self,docname):
|
||||
print_lst = []
|
||||
for d in getlist(self.doclist,'other_charges'):
|
||||
lst1 = []
|
||||
lst1.append(d.description)
|
||||
lst1.append(d.total)
|
||||
print_lst.append(lst1)
|
||||
return print_lst
|
||||
|
||||
def update_followup_details(self):
|
||||
sql("delete from `tabCommunication Log` where parent = '%s'"%self.doc.name)
|
||||
for d in getlist(self.doclist, 'follow_up'):
|
||||
d.save()
|
||||
1275
selling/doctype/quotation/quotation.txt
Normal file
1275
selling/doctype/quotation/quotation.txt
Normal file
File diff suppressed because it is too large
Load Diff
44
selling/doctype/quotation/quotation_list.js
Normal file
44
selling/doctype/quotation/quotation_list.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// render
|
||||
wn.doclistviews['Quotation'] = wn.views.ListView.extend({
|
||||
init: function(d) {
|
||||
this._super(d)
|
||||
this.fields = this.fields.concat([
|
||||
"`tabQuotation`.quotation_to",
|
||||
"`tabQuotation`.lead_name",
|
||||
"`tabQuotation`.customer_name",
|
||||
"`tabQuotation`.currency",
|
||||
"ifnull(`tabQuotation`.grand_total_export,0) as grand_total_export",
|
||||
"`tabQuotation`.transaction_date",
|
||||
]);
|
||||
this.stats = this.stats.concat(['status', 'quotation_to', 'company']);
|
||||
},
|
||||
|
||||
prepare_data: function(data) {
|
||||
this._super(data);
|
||||
if(data.quotation_to == 'Lead') {
|
||||
data.quotation_name = repl('[%(quotation_to)s] %(lead_name)s', data);
|
||||
} else {
|
||||
data.quotation_name = repl('[%(quotation_to)s] %(customer_name)s', data);
|
||||
}
|
||||
},
|
||||
|
||||
columns: [
|
||||
{width: '3%', content: 'check'},
|
||||
{width: '5%', content:'avatar'},
|
||||
{width: '3%', content:'docstatus'},
|
||||
{width: '15%', content:'name'},
|
||||
{width: '44%', content:'quotation_name+tags', css: {color:'#222'}},
|
||||
{
|
||||
width: '18%',
|
||||
content: function(parent, data) {
|
||||
$(parent).html(data.currency + ' ' + fmt_money(data.grand_total_export))
|
||||
},
|
||||
css: {'text-align':'right'}
|
||||
},
|
||||
{width: '12%', content:'transaction_date',
|
||||
css: {'text-align': 'right', 'color':'#777'},
|
||||
title: "Quotation Date", type: "date"}
|
||||
]
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user