How to create Filter Doctype

@kid1194 how 4 emails are added in email group member when 2 address have Mumbai in it as city.


In this out of 5 address top 3 have indore in it as city and rest 2 has mumbai.
But here it added 4.

And they are not having the right ones.
What can I do? is it something wrong with how I stored data or is it something else?

@Devershi_Vashistha The filtration is done by frappe. I check whether the filter field is not empty so I add it to the filtration list.

Give this code a try, I’ve added more checks.
And please check the console log.
In console log:

  • Filters: the filter list for both doctypes
  • Data: the data returned by both doctypes
  • Existing: the existing data in Email Group Member doctype
frappe.ui.form.on("Filter", {
    refresh: function(frm) {
        if (!frm.is_new()) {
            frm.add_custom_button('Apply Filter', () => frm.trigger('add_filtered_emails'));
            frm.change_custom_button_type('Apply Filter', null, 'success');
        }
    },
    add_filtered_emails: function(frm) {
        var doc = frm.doc;
        var email_group = doc.email_group;
        var emails = [];
        let filter_1 = {};
        let filter_2 = {};
        if (doc.country) filter_1.country = doc.country;
        if (doc.city) filter_1.city = doc.city;
        if (doc.intent) filter_2.intent = doc.intent;
        if (doc.package) filter_2.package = doc.package;
        if (doc.start_date && doc.end_date) {
            filter_2.datetime = [
                'between',
                [doc.start_date + ' 00:00:00', doc.end_date + ' 00:00:00']
            ];
        } else if (doc.start_date) {
            filter_2.datetime = ['>=', doc.start_date + ' 00:00:00'];
        } else if (doc.end_date) {
            filter_2.datetime = ['<=', doc.end_date + ' 00:00:00'];
        }
        let p1 = frappe.db.get_list('Address', {
            fields: ['email_id'],
            filters: filter_1
        });
        let p2 = frappe.db.get_list('Session History Collection', {
            fields: ['email'],
            filters: filter_2
        });
        console.log('Filters', filter_1, filter_2);
        Promise.all([p1, p2])
        .then(vals => {
            console.log('Data', vals);
            $.each(vals, function(i, data) {
                $.each(data, function(i, v) {
                    var email = v.email_id || v.email;
                    if (email && emails.indexOf(email) < 0) emails.push(email);
                });
            });
            frappe.db.get_list('Email Group Member', {
                fields: ['email'],
                filters: {
                    email: ['in', emails]
                }
            }).then(data => {
                console.log('Existing', data);
                if (data.length) {
                    $.each(data, function(i, v) {
                        if (v.email) {
                            let idx = emails.indexOf(v.email);
                            if (idx >= 0) emails.splice(idx, 1);
                        }
                    });
                }
                let added = [];
                let result = [];
                $.each(emails, function(i, v) {
                    if (added.indexOf(v) < 0) {
                        added.push(v);
                        frappe.db.insert({
                            doctype: 'Email Group Member',
                            email_group: email_group,
                            email: v,
                        }).then(d => {
                            result.push(d);
                        });
                    }
                });
                
                // for debugging purpose only
                console.log(
                    'Total existing members: ' + data.length,
                    'Total filtered emails: ' + emails.length,
                    'Total inserted emails: ' + result.length
                );
            });
        });
    }
});

Hi @kid1194 I am now understanding the problem a bit as it is getting the emails from session history collection doctype as when I removed some entries form the doctype those emails where then not present in the email group member when I tried again.
But why is it getting emails from session history collection when I have only entered city field and all other fields are empty?

@Devershi_Vashistha Ok, now I see where the problem is. Give me a minute.

@Devershi_Vashistha Check this.

frappe.ui.form.on("Filter", {
    refresh: function(frm) {
        if (!frm.is_new()) {
            frm.add_custom_button('Apply Filter', () => frm.trigger('add_filtered_emails'));
            frm.change_custom_button_type('Apply Filter', null, 'success');
        }
    },
    add_filtered_emails: function(frm) {
        var doc = frm.doc;
        var email_group = doc.email_group;
        var emails = [];
        let filter_1 = {};
        let filter_2 = {};
        if (doc.country) filter_1.country = doc.country;
        if (doc.city) filter_1.city = doc.city;
        if (doc.intent) filter_2.intent = doc.intent;
        if (doc.package) filter_2.package = doc.package;
        if (doc.start_date && doc.end_date) {
            filter_2.datetime = [
                'between',
                [doc.start_date + ' 00:00:00', doc.end_date + ' 00:00:00']
            ];
        } else if (doc.start_date) {
            filter_2.datetime = ['>=', doc.start_date + ' 00:00:00'];
        } else if (doc.end_date) {
            filter_2.datetime = ['<=', doc.end_date + ' 00:00:00'];
        }
        var p = [];
        if (Object.keys(filter_1).length) {
            p.push(frappe.db.get_list('Address', {
                fields: ['email_id'],
                filters: filter_1
            }));
        }
        if (Object.keys(filter_2).length) {
            p.push(frappe.db.get_list('Session History Collection', {
                fields: ['email'],
                filters: filter_2
            }));
        }
        console.log('Filters', filter_1, filter_2);
        if (!p.length) return;
        (p.length > 1 ? Promise.all(p) : p[0])
        .then(vals => {
            if (p.length === 1) vals = [vals];
            console.log('Data', vals);
            $.each(vals, function(i, data) {
                $.each(data, function(i, v) {
                    var email = v.email_id || v.email;
                    if (email && emails.indexOf(email) < 0) emails.push(email);
                });
            });
            if (!emails.length) return false;
            frappe.db.get_list('Email Group Member', {
                fields: ['email'],
                filters: {
                    email: ['in', emails]
                }
            }).then(data => {
                console.log('Existing', data);
                if (data.length) {
                    $.each(data, function(i, v) {
                        if (v.email) {
                            let idx = emails.indexOf(v.email);
                            if (idx >= 0) emails.splice(idx, 1);
                        }
                    });
                }
                if (!emails.length) return false;
                let added = [];
                let result = [];
                $.each(emails, function(i, v) {
                    if (added.indexOf(v) < 0) {
                        added.push(v);
                        frappe.db.insert({
                            doctype: 'Email Group Member',
                            email_group: email_group,
                            email: v,
                        }).then(d => {
                            result.push(d);
                        });
                    }
                });
                
                // for debugging purpose only
                console.log(
                    'Total existing members: ' + data.length,
                    'Total filtered emails: ' + emails.length,
                    'Total inserted emails: ' + result.length
                );
            });
        });
    }
});

@kid1194 if we add no filters can we have all emails and if we add a filter then emails of that specific filter must only be added.

@Devershi_Vashistha Right now it is supposed to work with at least one filter but not without any…

It checks if any of the Address filters exist, then it gets the emails from Address and the same is for Session History Collection. Otherwise it doesn’t do anything.

Oh ok.

@Devershi_Vashistha Is it now working as expected?

@kid1194 no, still there are errors.


what does this mean?

@Devershi_Vashistha I think that the problem is inserting using Promise in a loop. The loop continues without waiting for the Promise.

I’ll try to find a way then I’ll get back to you.

@Devershi_Vashistha I hope that this one works.

frappe.ui.form.on("Filter", {
    refresh: function(frm) {
        if (!frm.is_new()) {
            frm.add_custom_button('Apply Filter', () => frm.trigger('add_filtered_emails'));
            frm.change_custom_button_type('Apply Filter', null, 'success');
        }
    },
    add_filtered_emails: function(frm) {
        var doc = frm.doc;
        var email_group = doc.email_group;
        var emails = [];
        let filter_1 = {};
        let filter_2 = {};
        if (doc.country) filter_1.country = doc.country;
        if (doc.city) filter_1.city = doc.city;
        if (doc.intent) filter_2.intent = doc.intent;
        if (doc.package) filter_2.package = doc.package;
        if (doc.start_date && doc.end_date) {
            filter_2.datetime = [
                'between',
                [doc.start_date + ' 00:00:00', doc.end_date + ' 00:00:00']
            ];
        } else if (doc.start_date) {
            filter_2.datetime = ['>=', doc.start_date + ' 00:00:00'];
        } else if (doc.end_date) {
            filter_2.datetime = ['<=', doc.end_date + ' 00:00:00'];
        }
        let p = [];
        if (Object.keys(filter_1).length) {
            p.push(frappe.db.get_list('Address', {
                fields: ['email_id'],
                filters: filter_1
            }));
        }
        if (Object.keys(filter_2).length) {
            p.push(frappe.db.get_list('Session History Collection', {
                fields: ['email'],
                filters: filter_2
            }));
        }
        console.log('Filters', filter_1, filter_2);
        if (!p.length) return;
        (p.length > 1 ? Promise.all(p) : p[0])
        .then(vals => {
            if (p.length === 1) vals = [vals];
            console.log('Data', vals);
            $.each(vals, function(i, data) {
                $.each(data, function(i, v) {
                    var email = v.email_id || v.email;
                    if (email && emails.indexOf(email) < 0) emails.push(email);
                });
            });
            if (!emails.length) return;
            return frappe.db.get_list('Email Group Member', {
                fields: ['email'],
                filters: {
                    email: ['in', emails]
                }
            });
        }).then(data => {
            console.log('Existing', data);
            if (data.length) {
                $.each(data, function(i, v) {
                    if (v.email) {
                        let idx = emails.indexOf(v.email);
                        if (idx >= 0) emails.splice(idx, 1);
                    }
                });
            }
            if (!emails.length) return false;
            console.log(
                'Total existing members: ' + data.length,
                'Total filtered emails: ' + emails.length
            );
            var chunks = [];
            if (emails.length > 200) {
                for (var i = 0, l = emails.length; i < l; i += 200) {
                    chunks.push(emails.slice(i, i + 200));
                }
            } else chunks.push(emails);
            for (var i = 0, l = chunks.length; i < l; i++) {
                var added = [];
                for (var x = 0, y = chunks[i].length; x < y; x++) {
                    added.push({
                        doctype: 'Email Group Member',
                        email_group: email_group,
                        email: chunks[i].shift(),
                    });
                }
                frappe.call({
    				method: "frappe.client.insert_many",
    				type: 'POST',
    				args: {docs: added.slice()},
    				callback: r => {
    					console.log('Total inserted emails: ' + r.message.length);
    				}
    			});
            }
        });
    }
});

Hi, @kid1194 it shows this.
33

@Devershi_Vashistha My last resort.

frappe.ui.form.on("Filter", {
    refresh: function(frm) {
        if (!frm.is_new()) {
            frm.add_custom_button('Apply Filter', () => frm.trigger('add_filtered_emails'));
            frm.change_custom_button_type('Apply Filter', null, 'success');
        }
    },
    add_filtered_emails: function(frm) {
        var doc = frm.doc;
        var email_group = doc.email_group;
        var emails = [];
        let filter_1 = {};
        let filter_2 = {};
        if (doc.country) filter_1.country = doc.country;
        if (doc.city) filter_1.city = doc.city;
        if (doc.intent) filter_2.intent = doc.intent;
        if (doc.package) filter_2.package = doc.package;
        if (doc.start_date && doc.end_date) {
            filter_2.datetime = [
                'between',
                [doc.start_date + ' 00:00:00', doc.end_date + ' 00:00:00']
            ];
        } else if (doc.start_date) {
            filter_2.datetime = ['>=', doc.start_date + ' 00:00:00'];
        } else if (doc.end_date) {
            filter_2.datetime = ['<=', doc.end_date + ' 00:00:00'];
        }
        let p = [];
        if (Object.keys(filter_1).length) {
            p.push(frappe.db.get_list('Address', {
                fields: ['email_id'],
                filters: filter_1
            }));
        }
        if (Object.keys(filter_2).length) {
            p.push(frappe.db.get_list('Session History Collection', {
                fields: ['email'],
                filters: filter_2
            }));
        }
        console.log('Filters', filter_1, filter_2);
        if (!p.length) return;
        (p.length > 1 ? Promise.all(p) : p[0])
        .then(vals => {
            if (p.length === 1) vals = [vals];
            console.log('Data', vals);
            $.each(vals, function(i, data) {
                $.each(data, function(i, v) {
                    var email = v.email_id || v.email;
                    if (email && emails.indexOf(email) < 0) emails.push(email);
                });
            });
            if (!emails.length) return;
            frappe.db.get_list('Email Group Member', {
                fields: ['email'],
                filters: {
                    email: ['in', emails]
                }
            }).then(data => {
                console.log('Existing', data);
                if (data.length) {
                    $.each(data, function(i, v) {
                        if (v.email) {
                            let idx = emails.indexOf(v.email);
                            if (idx >= 0) emails.splice(idx, 1);
                        }
                    });
                }
                if (!emails.length) return false;
                console.log(
                    'Total existing members: ' + data.length,
                    'Total filtered emails: ' + emails.length
                );
                var chunks = [];
                if (emails.length > 200) {
                    for (var i = 0, l = emails.length; i < l; i += 200) {
                        chunks.push(emails.slice(i, i + 200));
                    }
                } else chunks.push(emails);
                for (var i = 0, l = chunks.length; i < l; i++) {
                    var added = [];
                    for (var x = 0, y = chunks[i].length; x < y; x++) {
                        added.push({
                            doctype: 'Email Group Member',
                            email_group: email_group,
                            email: chunks[i].shift(),
                        });
                    }
                    frappe.call({
        				method: "frappe.client.insert_many",
        				type: 'POST',
        				args: {docs: added.slice()},
        				callback: r => {
        					console.log('Total inserted emails: ' + r.message.length);
        				}
        			});
                }
            });
        });
    }
});

Hey @kid1194 if possible can we please connect for a min in a meet, it will be a lot easier to debug the problem.

@kid1194 so current problem is like this.
there are 3 address with country India.
image
Here it shows 3 but only add 2. So why is it happening?

@Devershi_Vashistha Because there are 2 existing members, one is a duplicate, so only two to add.
Check the doctype to see if the emails in the group are correct…

@kid1194 Thank you so much.
It is working fine.
Sorry to have bothered you so much but thank you it helped me greatly.

1 Like

@Devershi_Vashistha Anytime buddy. Also, sorry for dragging you through all these posts to get the right code for you.

This is the code after the console messages removed (for production use).

frappe.ui.form.on("Filter", {
    refresh: function(frm) {
        if (!frm.is_new()) {
            frm.add_custom_button(__('Apply Filter'), () => frm.trigger('add_filtered_emails'));
            frm.change_custom_button_type(__('Apply Filter'), null, 'success');
        }
    },
    add_filtered_emails: function(frm) {
        var doc = frm.doc;
        var email_group = doc.email_group;
        var emails = [];
        let address_filters = {};
        let session_filters = {};
        if (doc.country) address_filters.country = doc.country;
        if (doc.city) address_filters.city = doc.city;
        if (doc.intent) session_filters.intent = doc.intent;
        if (doc.package) session_filters.package = doc.package;
        if (doc.start_date && doc.end_date) {
            session_filters.datetime = [
                'between',
                [doc.start_date + ' 00:00:00', doc.end_date + ' 00:00:00']
            ];
        } else if (doc.start_date) {
            session_filters.datetime = ['>=', doc.start_date + ' 00:00:00'];
        } else if (doc.end_date) {
            session_filters.datetime = ['<=', doc.end_date + ' 00:00:00'];
        }
        let promises = [];
        if (Object.keys(address_filters).length) {
            promises.push(frappe.db.get_list('Address', {
                fields: ['email_id'],
                filters: address_filters
            }));
        }
        if (Object.keys(session_filters).length) {
            promises.push(frappe.db.get_list('Session History Collection', {
                fields: ['email'],
                filters: session_filters
            }));
        }
        if (!promises.length) return;
        (promises.length > 1 ? Promise.all(promises) : promises[0])
        .then(vals => {
            if (promises.length === 1) vals = [vals];
            $.each(vals, function(i, data) {
                $.each(data, function(i, v) {
                    var email = v.email_id || v.email;
                    if (email && emails.indexOf(email) < 0) emails.push(email);
                });
            });
            if (!emails.length) return;
            frappe.db.get_list('Email Group Member', {
                fields: ['email'],
                filters: {
                    email: ['in', emails]
                }
            }).then(data => {
                if (data.length) {
                    $.each(data, function(i, v) {
                        if (v.email) {
                            let idx = emails.indexOf(v.email);
                            if (idx >= 0) emails.splice(idx, 1);
                        }
                    });
                }
                if (!emails.length) return false;
                var chunks = [];
                if (emails.length > 200) {
                    for (var n = 0, len = emails.length; n < len; n += 200) {
                        chunks.push(emails.slice(n, n + 200));
                    }
                } else chunks.push(emails);
                for (var i = 0, l = chunks.length; i < l; i++) {
                    var docsList = [];
                    for (var x = 0, m = chunks[i].length; x < m; x++) {
                        docsList.push({
                            doctype: 'Email Group Member',
                            email_group: email_group,
                            email: chunks[i].shift(),
                        });
                    }
                    frappe.call({
        				method: "frappe.client.insert_many",
        				type: 'POST',
        				args: {docs: docsList.slice()}
        			});
                }
            });
        });
    }
});

@kid1194 Ok thank you.