408 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			408 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| frappe.provide('frappe.ui.form');
 | |
| 
 | |
| frappe.ui.form.ItemQuickEntryForm = class ItemQuickEntryForm extends frappe.ui.form.QuickEntryForm {
 | |
| 	constructor(doctype, after_insert) {
 | |
| 		super(doctype, after_insert);
 | |
| 	}
 | |
| 
 | |
| 	render_dialog() {
 | |
| 		this.mandatory = this.get_variant_fields().concat(this.mandatory);
 | |
| 		this.mandatory = this.mandatory.concat(this.get_attributes_fields());
 | |
| 		this.check_naming_series_based_on();
 | |
| 		super.render_dialog();
 | |
| 		this.init_post_render_dialog_operations();
 | |
| 		this.preset_fields_for_template();
 | |
| 		this.dialog.$wrapper.find('.edit-full').text(__('Edit in full page for more options like assets, serial nos, batches etc.'))
 | |
| 	}
 | |
| 
 | |
| 	check_naming_series_based_on() {
 | |
| 		if (frappe.defaults.get_default("item_naming_by") === "Naming Series") {
 | |
| 			this.mandatory = this.mandatory.filter(d => d.fieldname !== "item_code");
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	init_post_render_dialog_operations() {
 | |
| 		this.dialog.fields_dict.attribute_html.$wrapper.append(frappe.render_template("item_quick_entry"));
 | |
| 		this.init_for_create_variant_trigger();
 | |
| 		this.init_for_item_template_trigger();
 | |
| 		// explicitly hide manufacturing fields as hidden not working.
 | |
| 		this.toggle_manufacturer_fields();
 | |
| 		this.dialog.get_field("item_template").df.hidden = 1;
 | |
| 		this.dialog.get_field("item_template").refresh();
 | |
| 	}
 | |
| 
 | |
| 	register_primary_action() {
 | |
| 		var me = this;
 | |
| 		this.dialog.set_primary_action(__('Save'), function() {
 | |
| 			if (me.dialog.working) return;
 | |
| 
 | |
| 			var data = me.dialog.get_values();
 | |
| 			var variant_values = {};
 | |
| 
 | |
| 			if (me.dialog.fields_dict.create_variant.$input.prop("checked")) {
 | |
| 				variant_values = me.get_variant_doc();
 | |
| 				if (!Object.keys(variant_values).length) {
 | |
| 					data = null;
 | |
| 				}
 | |
| 				variant_values.stock_uom = me.template_doc.stock_uom;
 | |
| 				variant_values.item_group = me.template_doc.item_group;
 | |
| 			}
 | |
| 
 | |
| 			if (data) {
 | |
| 				me.dialog.working = true;
 | |
| 				var values = me.update_doc();
 | |
| 				//patch for manufacturer type variants as extend is overwriting it.
 | |
| 				if (variant_values['variant_based_on'] == "Manufacturer") {
 | |
| 					values['variant_based_on'] = "Manufacturer";
 | |
| 				}
 | |
| 				$.extend(variant_values, values);
 | |
| 				me.insert(variant_values);
 | |
| 			}
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	insert(variant_values) {
 | |
| 		let me = this;
 | |
| 		return new Promise(resolve => {
 | |
| 			frappe.call({
 | |
| 				method: "frappe.client.insert",
 | |
| 				args: {
 | |
| 					doc: variant_values
 | |
| 				},
 | |
| 				callback: function(r) {
 | |
| 					me.dialog.hide();
 | |
| 					// delete the old doc
 | |
| 					frappe.model.clear_doc(me.dialog.doc.doctype, me.dialog.doc.name);
 | |
| 					me.dialog.doc = r.message;
 | |
| 					if (frappe._from_link) {
 | |
| 						frappe.ui.form.update_calling_link(me.dialog.doc);
 | |
| 					} else {
 | |
| 						if (me.after_insert) {
 | |
| 							me.after_insert(me.dialog.doc);
 | |
| 						} else {
 | |
| 							me.open_form_if_not_list();
 | |
| 						}
 | |
| 					}
 | |
| 				},
 | |
| 				error: function() {
 | |
| 					me.open_doc();
 | |
| 				},
 | |
| 				always: function() {
 | |
| 					me.dialog.working = false;
 | |
| 					resolve(me.dialog.doc);
 | |
| 				},
 | |
| 				freeze: true
 | |
| 			});
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	open_doc() {
 | |
| 		this.dialog.hide();
 | |
| 		this.update_doc();
 | |
| 		if (this.dialog.fields_dict.create_variant.$input.prop("checked")) {
 | |
| 			var template = this.dialog.fields_dict.item_template.input.value;
 | |
| 			if (template)
 | |
| 				frappe.set_route("Form", this.doctype, template);
 | |
| 		} else {
 | |
| 			frappe.set_route('Form', this.doctype, this.doc.name);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	get_variant_fields() {
 | |
| 		var variant_fields = [{
 | |
| 			fieldname: "create_variant",
 | |
| 			fieldtype: "Check",
 | |
| 			label: __("Create Variant")
 | |
| 		},
 | |
| 		{
 | |
| 			fieldname: 'item_template',
 | |
| 			label: __('Item Template'),
 | |
| 			reqd: 0,
 | |
| 			fieldtype: 'Link',
 | |
| 			options: "Item",
 | |
| 			get_query: function() {
 | |
| 				return {
 | |
| 					filters: {
 | |
| 						"has_variants": 1
 | |
| 					}
 | |
| 				};
 | |
| 			}
 | |
| 		}];
 | |
| 
 | |
| 		return variant_fields;
 | |
| 	}
 | |
| 
 | |
| 	get_manufacturing_fields() {
 | |
| 		this.manufacturer_fields = [{
 | |
| 			fieldtype: 'Link',
 | |
| 			options: 'Manufacturer',
 | |
| 			label: 'Manufacturer',
 | |
| 			fieldname: "manufacturer",
 | |
| 			hidden: 1,
 | |
| 			reqd: 0
 | |
| 		}, {
 | |
| 			fieldtype: 'Data',
 | |
| 			label: 'Manufacturer Part Number',
 | |
| 			fieldname: 'manufacturer_part_no',
 | |
| 			hidden: 1,
 | |
| 			reqd: 0
 | |
| 		}];
 | |
| 		return this.manufacturer_fields;
 | |
| 	}
 | |
| 
 | |
| 	get_attributes_fields() {
 | |
| 		var attribute_fields = [{
 | |
| 			fieldname: 'attribute_html',
 | |
| 			fieldtype: 'HTML'
 | |
| 		}]
 | |
| 
 | |
| 		attribute_fields = attribute_fields.concat(this.get_manufacturing_fields());
 | |
| 		return attribute_fields;
 | |
| 	}
 | |
| 
 | |
| 	init_for_create_variant_trigger() {
 | |
| 		var me = this;
 | |
| 
 | |
| 		this.dialog.fields_dict.create_variant.$input.on("click", function() {
 | |
| 			me.preset_fields_for_template();
 | |
| 			me.init_post_template_trigger_operations(false, [], true);
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	preset_fields_for_template() {
 | |
| 		var for_variant = this.dialog.get_value('create_variant');
 | |
| 
 | |
| 		// setup template field, seen and mandatory if variant
 | |
| 		let template_field = this.dialog.get_field("item_template");
 | |
| 		template_field.df.reqd = for_variant;
 | |
| 		template_field.set_value('');
 | |
| 		template_field.df.hidden = !for_variant;
 | |
| 		template_field.refresh();
 | |
| 
 | |
| 		// hide properties for variant
 | |
| 		['item_code', 'item_name', 'item_group', 'stock_uom'].forEach((d) => {
 | |
| 			let f = this.dialog.get_field(d);
 | |
| 			f.df.hidden = for_variant;
 | |
| 			f.refresh();
 | |
| 		});
 | |
| 
 | |
| 		this.dialog.get_field('attribute_html').toggle(false);
 | |
| 
 | |
| 		// non mandatory for variants
 | |
| 		['item_code', 'stock_uom', 'item_group'].forEach((d) => {
 | |
| 			let f = this.dialog.get_field(d);
 | |
| 			f.df.reqd = !for_variant;
 | |
| 			f.refresh();
 | |
| 		});
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	init_for_item_template_trigger() {
 | |
| 		var me = this;
 | |
| 
 | |
| 		me.dialog.fields_dict["item_template"].df.onchange = () => {
 | |
| 			var template = me.dialog.fields_dict.item_template.input.value;
 | |
| 			me.template_doc = null;
 | |
| 			if (template) {
 | |
| 				frappe.call({
 | |
| 					method: "frappe.client.get",
 | |
| 					args: {
 | |
| 						doctype: "Item",
 | |
| 						name: template
 | |
| 					},
 | |
| 					callback: function(r) {
 | |
| 						me.template_doc = r.message;
 | |
| 						me.is_manufacturer = false;
 | |
| 
 | |
| 						if (me.template_doc.variant_based_on === "Manufacturer") {
 | |
| 							me.init_post_template_trigger_operations(true, [], true);
 | |
| 						} else {
 | |
| 
 | |
| 							me.init_post_template_trigger_operations(false, me.template_doc.attributes, false);
 | |
| 							me.render_attributes(me.template_doc.attributes);
 | |
| 						}
 | |
| 					}
 | |
| 				});
 | |
| 			} else {
 | |
| 				me.dialog.get_field('attribute_html').toggle(false);
 | |
| 				me.init_post_template_trigger_operations(false, [], true);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	init_post_template_trigger_operations(is_manufacturer, attributes, attributes_flag) {
 | |
| 		this.attributes = attributes;
 | |
| 		this.attribute_values = {};
 | |
| 		this.attributes_count = attributes.length;
 | |
| 
 | |
| 		this.dialog.fields_dict.attribute_html.$wrapper.find(".attributes").empty();
 | |
| 		this.is_manufacturer = is_manufacturer;
 | |
| 		this.toggle_manufacturer_fields();
 | |
| 		this.dialog.fields_dict.attribute_html.$wrapper.find(".attributes").toggleClass("hide-control", attributes_flag);
 | |
| 		this.dialog.fields_dict.attribute_html.$wrapper.find(".attributes-header").toggleClass("hide-control", attributes_flag);
 | |
| 	}
 | |
| 
 | |
| 	toggle_manufacturer_fields() {
 | |
| 		var me = this;
 | |
| 		$.each(this.manufacturer_fields, function(i, dialog_field) {
 | |
| 			me.dialog.get_field(dialog_field.fieldname).df.hidden = !me.is_manufacturer;
 | |
| 			me.dialog.get_field(dialog_field.fieldname).df.reqd = dialog_field.fieldname == 'manufacturer' ? me.is_manufacturer : false;
 | |
| 			me.dialog.get_field(dialog_field.fieldname).refresh();
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	initiate_render_attributes() {
 | |
| 		this.dialog.fields_dict.attribute_html.$wrapper.find(".attributes").empty();
 | |
| 		this.render_attributes(this.attributes);
 | |
| 	}
 | |
| 
 | |
| 	render_attributes(attributes) {
 | |
| 		var me = this;
 | |
| 
 | |
| 		this.dialog.get_field('attribute_html').toggle(true);
 | |
| 
 | |
| 		$.each(attributes, function(index, row) {
 | |
| 			var desc = "";
 | |
| 			var fieldtype = "Data";
 | |
| 			if (row.numeric_values) {
 | |
| 				fieldtype = "Float";
 | |
| 				desc = "Min Value: " + row.from_range + " , Max Value: " + row.to_range + ", in Increments of: " + row.increment;
 | |
| 			}
 | |
| 
 | |
| 			me.init_make_control(fieldtype, row);
 | |
| 			me[row.attribute].set_value(me.attribute_values[row.attribute] || "");
 | |
| 			me[row.attribute].$wrapper.toggleClass("has-error", me.attribute_values[row.attribute] ? false : true);
 | |
| 
 | |
| 			// Set Label explicitly as make_control is not displaying label
 | |
| 			$(me[row.attribute].label_area).text(__(row.attribute));
 | |
| 
 | |
| 			if (desc) {
 | |
| 				$(repl(`<p class="help-box small text-muted hidden-xs">%(desc)s</p>`, {
 | |
| 					"desc": desc
 | |
| 				})).insertAfter(me[row.attribute].input_area);
 | |
| 			}
 | |
| 
 | |
| 			if (!row.numeric_values) {
 | |
| 				me.init_awesomplete_for_attribute(row);
 | |
| 			} else {
 | |
| 				me[row.attribute].$input.on("change", function() {
 | |
| 					me.attribute_values[row.attribute] = $(this).val();
 | |
| 					$(this).closest(".frappe-control").toggleClass("has-error", $(this).val() ? false : true);
 | |
| 				});
 | |
| 			}
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	init_make_control(fieldtype, row) {
 | |
| 		this[row.attribute] = frappe.ui.form.make_control({
 | |
| 			df: {
 | |
| 				"fieldtype": fieldtype,
 | |
| 				"label": row.attribute,
 | |
| 				"fieldname": row.attribute,
 | |
| 				"options": row.options || ""
 | |
| 			},
 | |
| 			parent: $(this.dialog.fields_dict.attribute_html.wrapper).find(".attributes"),
 | |
| 			only_input: false
 | |
| 		});
 | |
| 		this[row.attribute].make_input();
 | |
| 	}
 | |
| 
 | |
| 	init_awesomplete_for_attribute(row) {
 | |
| 		var me = this;
 | |
| 
 | |
| 		this[row.attribute].input.awesomplete = new Awesomplete(this[row.attribute].input, {
 | |
| 			minChars: 0,
 | |
| 			maxItems: 99,
 | |
| 			autoFirst: true,
 | |
| 			list: [],
 | |
| 		});
 | |
| 
 | |
| 		this[row.attribute].$input.on('input', function(e) {
 | |
| 			frappe.call({
 | |
| 				method: "frappe.client.get_list",
 | |
| 				args: {
 | |
| 					doctype: "Item Attribute Value",
 | |
| 					filters: [
 | |
| 						["parent", "=", $(e.target).attr("data-fieldname")],
 | |
| 						["attribute_value", "like", e.target.value + "%"]
 | |
| 					],
 | |
| 					fields: ["attribute_value"],
 | |
| 					parent: "Item Attribute"
 | |
| 				},
 | |
| 				callback: function(r) {
 | |
| 					if (r.message) {
 | |
| 						e.target.awesomplete.list = r.message.map(function(d) {
 | |
| 							return d.attribute_value;
 | |
| 						});
 | |
| 					}
 | |
| 				}
 | |
| 			});
 | |
| 		}).on('focus', function(e) {
 | |
| 			$(e.target).val('').trigger('input');
 | |
| 		}).on("awesomplete-close", function (e) {
 | |
| 			me.attribute_values[$(e.target).attr("data-fieldname")] = e.target.value;
 | |
| 			$(e.target).closest(".frappe-control").toggleClass("has-error", e.target.value ? false : true);
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	get_variant_doc() {
 | |
| 		var me = this;
 | |
| 		var variant_doc = {};
 | |
| 		var attribute = this.validate_mandatory_attributes();
 | |
| 
 | |
| 		if (Object.keys(attribute).length) {
 | |
| 			frappe.call({
 | |
| 				method: "erpnext.controllers.item_variant.create_variant_doc_for_quick_entry",
 | |
| 				args: {
 | |
| 					"template": me.dialog.fields_dict.item_template.$input.val(),
 | |
| 					args: attribute
 | |
| 				},
 | |
| 				async: false,
 | |
| 				callback: function(r) {
 | |
| 					if (Object.prototype.toString.call(r.message) == "[object Object]") {
 | |
| 						variant_doc = r.message;
 | |
| 					} else {
 | |
| 						var msgprint_dialog = frappe.msgprint(__("Item Variant {0} already exists with same attributes", [repl('<a class="strong variant-click" data-item-code="%(item)s" \
 | |
| 								>%(item)s</a>', {
 | |
| 								item: r.message
 | |
| 							})]));
 | |
| 
 | |
| 						msgprint_dialog.$wrapper.find(".variant-click").on("click", function() {
 | |
| 							msgprint_dialog.hide();
 | |
| 							me.dialog.hide();
 | |
| 							if (frappe._from_link) {
 | |
| 								frappe._from_link.set_value($(this).attr("data-item-code"));
 | |
| 							} else {
 | |
| 								frappe.set_route('Form', "Item", $(this).attr("data-item-code"));
 | |
| 							}
 | |
| 						});
 | |
| 					}
 | |
| 				}
 | |
| 			})
 | |
| 		}
 | |
| 		return variant_doc;
 | |
| 	}
 | |
| 
 | |
| 	validate_mandatory_attributes() {
 | |
| 		var me = this;
 | |
| 		var attribute = {};
 | |
| 		var mandatory = [];
 | |
| 
 | |
| 		$.each(this.attributes, function(index, attr) {
 | |
| 			var value = me.attribute_values[attr.attribute] || "";
 | |
| 			if (value) {
 | |
| 				attribute[attr.attribute] = attr.numeric_values ? flt(value) : value;
 | |
| 			} else {
 | |
| 				mandatory.push(attr.attribute);
 | |
| 			}
 | |
| 		})
 | |
| 
 | |
| 		if (this.is_manufacturer) {
 | |
| 			$.each(this.manufacturer_fields, function(index, field) {
 | |
| 				attribute[field.fieldname] = me.dialog.fields_dict[field.fieldname].input.value;
 | |
| 			});
 | |
| 		}
 | |
| 		return attribute;
 | |
| 	}
 | |
| };
 |