[mapper] purchase cycle

This commit is contained in:
Nabin Hait
2013-07-05 15:23:47 +05:30
parent 44935e4608
commit eb883ee7a3
21 changed files with 390 additions and 823 deletions

View File

@@ -1,125 +0,0 @@
[
{
"creation": "2010-08-08 17:09:34",
"docstatus": 0,
"modified": "2013-02-18 13:41:16",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Table Mapper Detail",
"name": "__common__",
"parent": "Material Request-Purchase Order",
"parentfield": "table_mapper_details",
"parenttype": "DocType Mapper"
},
{
"doctype": "Field Mapper Detail",
"name": "__common__",
"parent": "Material Request-Purchase Order",
"parentfield": "field_mapper_details",
"parenttype": "DocType Mapper"
},
{
"doctype": "DocType Mapper",
"from_doctype": "Material Request",
"module": "Buying",
"name": "__common__",
"ref_doc_submitted": 1,
"to_doctype": "Purchase Order"
},
{
"doctype": "DocType Mapper",
"name": "Material Request-Purchase Order"
},
{
"checking_operator": "=",
"doctype": "Field Mapper Detail",
"from_field": "company",
"map": "Yes",
"match_id": 0,
"to_field": "company"
},
{
"doctype": "Field Mapper Detail",
"from_field": "parenttype",
"map": "Yes",
"match_id": 1,
"to_field": "prevdoc_doctype"
},
{
"doctype": "Field Mapper Detail",
"from_field": "parent",
"map": "Yes",
"match_id": 1,
"to_field": "prevdoc_docname"
},
{
"doctype": "Field Mapper Detail",
"from_field": "name",
"map": "Yes",
"match_id": 1,
"to_field": "prevdoc_detail_docname"
},
{
"doctype": "Field Mapper Detail",
"from_field": "uom",
"map": "Yes",
"match_id": 1,
"to_field": "stock_uom"
},
{
"doctype": "Field Mapper Detail",
"from_field": "eval:flt(1)",
"map": "Yes",
"match_id": 1,
"to_field": "conversion_factor"
},
{
"doctype": "Field Mapper Detail",
"from_field": "eval:flt(obj.qty) - flt(obj.ordered_qty)",
"map": "Yes",
"match_id": 1,
"to_field": "stock_qty"
},
{
"doctype": "Field Mapper Detail",
"from_field": "eval:flt(obj.qty) - flt(obj.ordered_qty)",
"map": "Yes",
"match_id": 1,
"to_field": "qty"
},
{
"doctype": "Field Mapper Detail",
"from_field": "schedule_date",
"map": "Yes",
"match_id": 1,
"to_field": "schedule_date"
},
{
"checking_operator": ">=",
"doctype": "Field Mapper Detail",
"from_field": "transaction_date",
"map": "No",
"match_id": 0,
"to_field": "transaction_date"
},
{
"doctype": "Table Mapper Detail",
"from_table": "Material Request",
"match_id": 0,
"reference_key": "prevdoc_docname",
"to_table": "Purchase Order",
"validation_logic": "docstatus = 1"
},
{
"doctype": "Table Mapper Detail",
"from_field": "indent_details",
"from_table": "Material Request Item",
"match_id": 1,
"reference_doctype_key": "prevdoc_doctype",
"to_field": "po_details",
"to_table": "Purchase Order Item",
"validation_logic": "qty > ifnull(ordered_qty,0) and docstatus =1"
}
]

View File

@@ -1,90 +0,0 @@
[
{
"creation": "2012-08-06 20:02:53",
"docstatus": 0,
"modified": "2013-02-18 13:41:13",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Table Mapper Detail",
"name": "__common__",
"parent": "Material Request-Supplier Quotation",
"parentfield": "table_mapper_details",
"parenttype": "DocType Mapper"
},
{
"doctype": "Field Mapper Detail",
"name": "__common__",
"parent": "Material Request-Supplier Quotation",
"parentfield": "field_mapper_details",
"parenttype": "DocType Mapper"
},
{
"doctype": "DocType Mapper",
"from_doctype": "Material Request",
"module": "Buying",
"name": "__common__",
"ref_doc_submitted": 1,
"to_doctype": "Supplier Quotation"
},
{
"doctype": "DocType Mapper",
"name": "Material Request-Supplier Quotation"
},
{
"checking_operator": "=",
"doctype": "Field Mapper Detail",
"from_field": "company",
"map": "Yes",
"match_id": 0,
"to_field": "company"
},
{
"doctype": "Field Mapper Detail",
"from_field": "parenttype",
"map": "Yes",
"match_id": 1,
"to_field": "prevdoc_doctype"
},
{
"doctype": "Field Mapper Detail",
"from_field": "parent",
"map": "Yes",
"match_id": 1,
"to_field": "prevdoc_docname"
},
{
"doctype": "Field Mapper Detail",
"from_field": "name",
"map": "Yes",
"match_id": 1,
"to_field": "prevdoc_detail_docname"
},
{
"checking_operator": ">=",
"doctype": "Field Mapper Detail",
"from_field": "transaction_date",
"map": "No",
"match_id": 0,
"to_field": "transaction_date"
},
{
"doctype": "Table Mapper Detail",
"from_table": "Material Request",
"match_id": 0,
"reference_key": "prevdoc_docname",
"to_table": "Supplier Quotation",
"validation_logic": "docstatus = 1"
},
{
"doctype": "Table Mapper Detail",
"from_field": "indent_details",
"from_table": "Material Request Item",
"match_id": 1,
"reference_doctype_key": "prevdoc_doctype",
"to_field": "quotation_items",
"to_table": "Supplier Quotation Item",
"validation_logic": "docstatus =1"
}
]

View File

@@ -1,98 +0,0 @@
[
{
"creation": "2011-05-20 10:07:55",
"docstatus": 0,
"modified": "2013-02-20 18:20:27",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Table Mapper Detail",
"name": "__common__",
"parent": "Sales Order-Material Request",
"parentfield": "table_mapper_details",
"parenttype": "DocType Mapper"
},
{
"doctype": "Field Mapper Detail",
"name": "__common__",
"parent": "Sales Order-Material Request",
"parentfield": "field_mapper_details",
"parenttype": "DocType Mapper"
},
{
"doctype": "DocType Mapper",
"from_doctype": "Sales Order",
"module": "Buying",
"name": "__common__",
"ref_doc_submitted": 1,
"to_doctype": "Material Request"
},
{
"doctype": "DocType Mapper",
"name": "Sales Order-Material Request"
},
{
"checking_operator": ">=",
"doctype": "Field Mapper Detail",
"from_field": "transaction_date",
"map": "No",
"match_id": 0,
"to_field": "transaction_date"
},
{
"doctype": "Field Mapper Detail",
"from_field": "eval:\"Purchase\"",
"map": "Yes",
"match_id": 0,
"to_field": "material_request_type"
},
{
"checking_operator": "=",
"doctype": "Field Mapper Detail",
"from_field": "company",
"map": "Yes",
"match_id": 0,
"to_field": "company"
},
{
"doctype": "Field Mapper Detail",
"from_field": "parent",
"map": "Yes",
"match_id": 1,
"to_field": "sales_order_no"
},
{
"doctype": "Field Mapper Detail",
"from_field": "stock_uom",
"map": "Yes",
"match_id": 1,
"to_field": "uom"
},
{
"doctype": "Field Mapper Detail",
"from_field": "reserved_warehouse",
"map": "Yes",
"match_id": 1,
"to_field": "warehouse"
},
{
"doctype": "Table Mapper Detail",
"from_field": "sales_order_details",
"from_table": "Sales Order Item",
"match_id": 1,
"reference_doctype_key": "prevdoc_doctype",
"reference_key": "prevdoc_detail_docname",
"to_field": "indent_details",
"to_table": "Material Request Item",
"validation_logic": "docstatus=1"
},
{
"doctype": "Table Mapper Detail",
"from_table": "Sales Order",
"match_id": 0,
"reference_key": "prevdoc_docname",
"to_table": "Material Request",
"validation_logic": "docstatus = 1"
}
]

View File

@@ -30,15 +30,46 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if(doc.docstatus == 1 && doc.status != 'Stopped'){
cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']);
if(flt(doc.per_received, 2) < 100) cur_frm.add_custom_button('Make Purchase Receipt', cur_frm.cscript['Make Purchase Receipt']);
if(flt(doc.per_billed, 2) < 100) cur_frm.add_custom_button('Make Invoice', cur_frm.cscript['Make Purchase Invoice']);
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100) cur_frm.add_custom_button('Stop', cur_frm.cscript['Stop Purchase Order']);
if(flt(doc.per_received, 2) < 100)
cur_frm.add_custom_button('Make Purchase Receipt', this.make_purchase_receipt);
if(flt(doc.per_billed, 2) < 100)
cur_frm.add_custom_button('Make Invoice', this.make_purchase_invoice);
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100)
cur_frm.add_custom_button('Stop', cur_frm.cscript['Stop Purchase Order']);
}
if(doc.docstatus == 1 && doc.status == 'Stopped')
cur_frm.add_custom_button('Unstop Purchase Order', cur_frm.cscript['Unstop Purchase Order']);
cur_frm.add_custom_button('Unstop Purchase Order',
cur_frm.cscript['Unstop Purchase Order']);
},
get_items: function() {
wn.model.map_current_doc({
method: "stock.doctype.material_request.material_request.make_purchase_order",
source_name: cur_frm.doc.indent_no,
})
},
make_purchase_receipt: function() {
wn.model.open_mapped_doc({
method: "buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
source_name: cur_frm.doc.name
})
},
make_purchase_invoice: function() {
wn.model.open_mapped_doc({
method: "buying.doctype.purchase_order.purchase_order.make_purchase_invoice",
source_name: cur_frm.doc.name
})
},
get_supplier_quotation_items: function() {
wn.model.map_current_doc({
method: "buying.doctype.supplier_quotation.supplier_quotation.make_purchase_order",
source_name: cur_frm.doc.supplier_quotation,
})
}
});
// for backward compatibility: combine new and previous states
@@ -70,58 +101,14 @@ cur_frm.fields_dict['indent_no'].get_query = function(doc) {
ORDER BY `name` DESC LIMIT 50';
}
//========================= Get Last Purhase Rate =====================================
cur_frm.cscript.get_last_purchase_rate = function(doc, cdt, cdn){
$c_obj(make_doclist(doc.doctype, doc.name), 'get_last_purchase_rate', '',
function(r, rt) {
refresh_field(cur_frm.cscript.fname);
var doc = locals[cdt][cdn];
cur_frm.cscript.calc_amount( doc, 2);
}
);
$c_obj(make_doclist(doc.doctype, doc.name), 'get_last_purchase_rate', '', function(r, rt) {
refresh_field(cur_frm.cscript.fname);
var doc = locals[cdt][cdn];
cur_frm.cscript.calc_amount( doc, 2);
});
}
cur_frm.cscript.get_items = function(doc, dt, dn) {
wn.model.map_current_doc({
method: "stock.doctype.material_request.material_request.make_purchase_order",
source_name: cur_frm.doc.indent_no,
})
}
cur_frm.cscript['Make Purchase Receipt'] = function() {
n = wn.model.make_new_doc_and_get_name('Purchase Receipt');
$c('dt_map', args={
'docs':wn.model.compress([locals['Purchase Receipt'][n]]),
'from_doctype': cur_frm.doc.doctype,
'to_doctype':'Purchase Receipt',
'from_docname':cur_frm.doc.name,
'from_to_list':"[['Purchase Order','Purchase Receipt'],['Purchase Order Item','Purchase Receipt Item'],['Purchase Taxes and Charges','Purchase Taxes and Charges']]"
}, function(r,rt) {
loaddoc('Purchase Receipt', n);
}
);
}
//========================== Make Purchase Invoice =====================================================
cur_frm.cscript['Make Purchase Invoice'] = function() {
n = wn.model.make_new_doc_and_get_name('Purchase Invoice');
$c('dt_map', {
'docs':wn.model.compress([locals['Purchase Invoice'][n]]),
'from_doctype':cur_frm.doc.doctype,
'to_doctype':'Purchase Invoice',
'from_docname': cur_frm.doc.name,
'from_to_list':"[['Purchase Order','Purchase Invoice'],['Purchase Order Item','Purchase Invoice Item'],['Purchase Taxes and Charges','Purchase Taxes and Charges']]"
}, function(r,rt) {
loaddoc('Purchase Invoice', n);
}
);
}
// Stop PURCHASE ORDER
// ==================================================================================================
cur_frm.cscript['Stop Purchase Order'] = function() {
var doc = cur_frm.doc;
var check = confirm("Do you really want to STOP " + doc.name);
@@ -133,8 +120,6 @@ cur_frm.cscript['Stop Purchase Order'] = function() {
}
}
// Unstop PURCHASE ORDER
// ==================================================================================================
cur_frm.cscript['Unstop Purchase Order'] = function() {
var doc = cur_frm.doc;
var check = confirm("Do you really want to UNSTOP " + doc.name);
@@ -146,7 +131,6 @@ cur_frm.cscript['Unstop Purchase Order'] = function() {
}
}
//****************** For print sales order no and date*************************
cur_frm.pformat.indent_no = function(doc, cdt, cdn){
//function to make row of table

View File

@@ -71,17 +71,11 @@ class DocType(BuyingController):
def get_bin_details(self, arg = ''):
return get_obj(dt='Purchase Common').get_bin_details(arg)
def get_supplier_quotation_items(self):
if self.doc.supplier_quotation:
get_obj("DocType Mapper", "Supplier Quotation-Purchase Order").dt_map("Supplier Quotation",
"Purchase Order", self.doc.supplier_quotation, self.doc, self.doclist,
"""[['Supplier Quotation', 'Purchase Order'],
['Supplier Quotation Item', 'Purchase Order Item'],
['Purchase Taxes and Charges', 'Purchase Taxes and Charges']]""")
for d in getlist(self.doclist, 'po_details'):
if d.prevdoc_detail_docname and not d.schedule_date:
d.schedule_date = webnotes.conn.get_value("Material Request Item",
d.prevdoc_detail_docname, "schedule_date")
def get_schedule_dates(self):
for d in getlist(self.doclist, 'po_details'):
if d.prevdoc_detail_docname and not d.schedule_date:
d.schedule_date = webnotes.conn.get_value("Material Request Item",
d.prevdoc_detail_docname, "schedule_date")
def get_last_purchase_rate(self):
get_obj('Purchase Common').get_last_purchase_rate(self)
@@ -205,4 +199,84 @@ class DocType(BuyingController):
pass
def get_rate(self,arg):
return get_obj('Purchase Common').get_rate(arg,self)
return get_obj('Purchase Common').get_rate(arg,self)
@webnotes.whitelist()
def make_purchase_receipt(source_name, target_doclist=None):
from webnotes.model.mapper import get_mapped_doclist
def set_missing_values(source, target):
bean = webnotes.bean(target)
bean.run_method("set_missing_values")
def update_item(obj, target, source_parent):
target.conversion_factor = 1
target.qty = flt(obj.qty) - flt(obj.received_qty)
target.stock_qty = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.conversion_factor)
target.import_amount = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.import_rate)
target.amount = (flt(obj.qty) - flt(obj.received_qty)) * flt(obj.purchase_rate)
doclist = get_mapped_doclist("Purchase Order", source_name, {
"Purchase Order": {
"doctype": "Purchase Receipt",
"validation": {
"docstatus": ["=", 1],
}
},
"Purchase Order Item": {
"doctype": "Purchase Receipt Item",
"field_map": {
"name": "prevdoc_detail_docname",
"parent": "prevdoc_docname",
"parenttype": "prevdoc_doctype",
},
"postprocess": update_item,
"condition": lambda doc: doc.received_qty < doc.qty
},
"Purchase Taxes and Charges": {
"doctype": "Purchase Taxes and Charges",
}
}, target_doclist, set_missing_values)
return [d.fields for d in doclist]
@webnotes.whitelist()
def make_purchase_invoice(source_name, target_doclist=None):
from webnotes.model.mapper import get_mapped_doclist
def set_missing_values(source, target):
bean = webnotes.bean(target)
bean.run_method("set_missing_values")
bean.run_method("set_supplier_defaults")
def update_item(obj, target, source_parent):
target.conversion_factor = 1
target.qty = (flt(obj.amount) - flt(obj.billed_amt)) / flt(obj.purchase_rate)
target.import_amount = (flt(obj.amount) - flt(obj.billed_amt)) / \
flt(source_parent.conversion_rate)
target.amount = flt(obj.amount) - flt(obj.billed_amt)
doclist = get_mapped_doclist("Purchase Order", source_name, {
"Purchase Order": {
"doctype": "Purchase Invoice",
"validation": {
"docstatus": ["=", 1],
}
},
"Purchase Order Item": {
"doctype": "Purchase Invoice Item",
"field_map": {
"name": "po_detail",
"parent": "purchase_order",
"purchase_rate": "rate"
},
"postprocess": update_item,
"condition": lambda doc: doc.amount==0 or doc.billed_amt < doc.amount
},
"Purchase Taxes and Charges": {
"doctype": "Purchase Taxes and Charges",
}
}, target_doclist, set_missing_values)
return [d.fields for d in doclist]

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:39",
"docstatus": 0,
"modified": "2013-07-04 18:10:21",
"modified": "2013-07-05 13:02:52",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -267,7 +267,7 @@
"fieldtype": "Float",
"hidden": 0,
"label": "Exchange Rate",
"no_copy": 1,
"no_copy": 0,
"oldfieldname": "conversion_rate",
"oldfieldtype": "Currency",
"print_hide": 1,

View File

@@ -19,9 +19,38 @@ from __future__ import unicode_literals
import unittest
import webnotes
import webnotes.defaults
from webnotes.utils import cint
class TestPurchaseOrder(unittest.TestCase):
def test_make_purchase_receipt(self):
from buying.doctype.purchase_order.purchase_order import make_purchase_receipt
po = webnotes.bean(copy=test_records[0]).insert()
self.assertRaises(webnotes.ValidationError, make_purchase_receipt,
po.doc.name)
po = webnotes.bean("Purchase Order", po.doc.name)
po.submit()
pr = make_purchase_receipt(po.doc.name)
self.assertEquals(pr[0]["doctype"], "Purchase Receipt")
self.assertEquals(len(pr), len(test_records[0]))
def test_make_purchase_invocie(self):
from buying.doctype.purchase_order.purchase_order import make_purchase_invoice
po = webnotes.bean(copy=test_records[0]).insert()
self.assertRaises(webnotes.ValidationError, make_purchase_invoice,
po.doc.name)
po = webnotes.bean("Purchase Order", po.doc.name)
po.submit()
pi = make_purchase_invoice(po.doc.name)
self.assertEquals(pi[0]["doctype"], "Purchase Invoice")
self.assertEquals(len(pi), len(test_records[0]))
def test_subcontracting(self):
po = webnotes.bean(copy=test_records[0])
po.insert()

View File

@@ -28,33 +28,28 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
this._super();
if (this.frm.doc.docstatus === 1) {
cur_frm.add_custom_button("Make Purchase Order", cur_frm.cscript.make_purchase_order);
cur_frm.add_custom_button("Make Purchase Order", this.make_purchase_order);
}
},
get_items: function() {
wn.model.map_current_doc({
method: "stock.doctype.material_request.material_request.make_supplier_quotation",
source_name: cur_frm.doc.indent_no,
})
},
make_purchase_order: function() {
wn.model.open_mapped_doc({
method: "buying.doctype.supplier_quotation.supplier_quotation.make_purchase_order",
source_name: cur_frm.doc.name
})
}
});
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.buying.SupplierQuotationController({frm: cur_frm}));
cur_frm.cscript.make_purchase_order = function() {
var new_po_name = wn.model.make_new_doc_and_get_name("Purchase Order");
$c("dt_map", {
"docs": wn.model.compress([locals['Purchase Order'][new_po_name]]),
"from_doctype": cur_frm.doc.doctype,
"to_doctype": "Purchase Order",
"from_docname": cur_frm.doc.name,
"from_to_list": JSON.stringify([['Supplier Quotation', 'Purchase Order'],
['Supplier Quotation Item', 'Purchase Order Item'],
['Purchase Taxes and Charges', 'Purchase Taxes and Charges']]),
}, function(r, rt) { loaddoc("Purchase Order", new_po_name) });
}
cur_frm.cscript.uom = function(doc, cdt, cdn) {
// no need to trigger updation of stock uom, as this field doesn't exist in supplier quotation
}

View File

@@ -58,3 +58,41 @@ class DocType(BuyingController):
pc.validate_for_items(self)
pc.get_prevdoc_date(self)
pc.validate_reference_value(self)
@webnotes.whitelist()
def make_purchase_order(source_name, target_doclist=None):
from webnotes.model.mapper import get_mapped_doclist
def set_missing_values(source, target):
bean = webnotes.bean(target)
bean.run_method("set_missing_values")
bean.run_method("get_schedule_dates")
def update_item(obj, target, source_parent):
target.conversion_factor = 1
doclist = get_mapped_doclist("Supplier Quotation", source_name, {
"Supplier Quotation": {
"doctype": "Purchase Order",
"validation": {
"docstatus": ["=", 1],
}
},
"Supplier Quotation Item": {
"doctype": "Purchase Order Item",
"field_map": {
"name": "supplier_quotation_item",
"parent": "supplier_quotation",
"uom": "stock_uom",
"prevdoc_detail_docname": "prevdoc_detail_docname",
"prevdoc_doctype": "prevdoc_doctype",
"prevdoc_docname": "prevdoc_docname",
},
"postprocess": update_item
},
"Purchase Taxes and Charges": {
"doctype": "Purchase Taxes and Charges",
},
}, target_doclist, set_missing_values)
return [d.fields for d in doclist]