Send 2 different types of mails using mailchimp - mailchimp

I have a set of internal users for my project. Admin can activate/deactivate them. I want to send them a mail saying "your account has been deactivated" when their account is deactivated by admin. Similarly they should receive a mail saying "your account has been activated" when admin activates their account. How can I do this?
I am trying by creating 2 separate lists in mailchimp and two separate campaigns. but when I'm writing mailchimps credentials in my development.js with 2 separate list ids and then trying to get it in my javascript file,it is getting undefined (checked by console.log)..
Is there a way to do it by just single campaign/list?
Here's my development.js code of mailchimp credentials:
mailchimp: {
api_key: "***************-***",
list_id1: "*********", //internal users
list_id2: "*********" //internal deactivated users
},
my user.helper.js
const config = require('../../config/environment');
const Mailchimp = require('mailchimp-api-3');
const mailchimp = new Mailchimp(config.mailchimp.api_key);
exports.addToDeactivatedList = function (email, name) {
console.log(mailchimp.list_id1);
mailchimp.members.create(config.mailchimp.list_id1, {
email_address: email,
merge_fields: {
FNAME: name
},
status: 'subscribed'
}).then(user => { }).catch(e => {
console.log("deactivate list me add ho gya");
})
}
exports.addToActivatedList = function (email, name) {
console.log(mailchimp.list_id2);
mailchimp.members.create(config.mailchimp.list_id2, {
email_address: email,
merge_fields: {
FNAME: name
},
status: 'subscribed'
}).then(user => { }).catch(e => {
console.log("activate list me add ho gya");
})
}
and my user.controller.js (selective part only)
var helper = require('./user.helper');
.
.
if(req.body.status != user.status){
(req.body.status == "active") ? helper.addToActivatedList(user.email, user.name) : helper.addToDeactivatedList(user.email, user.name);
}
All the help will be appreciated. THANKS

I'd try to put everyone in the same list, and then create segments based on that list. After that, create a campaign based on that segment.
You could for instance create a custom list attribute that records wether or not an account is activated and create a segment based on that attribute. The campaign should then be based on that segment.
Perhaps also record the date an account has been activated or deactivated by the admin in another custom attribute and use that to check if a user already had an activation/deactivation mail.

MailChimp offers a feature for situations like this called automations. Automations allow you to send individual emails to subscribers when an event is triggered. So instead of creating separate campaigns every time a user is activated or deactivated, you can use just two automations and a single list.
Whether a user is active or not can be tracked with list merge fields. To do this, you'll need to add a new text merge field to your list. Let's name the field label 'Active'. Uncheck the 'Visible' checkbox so the user can't see it, and name your merge field something like 'ACTIVE'. You can use values like yes/no or true/false to identify the users by their active status.
Next, create your automations, one for activated users and one for deactivated users. You can set a trigger to send the email when a list field value is changed. So just make each of your two automations send the emails when the 'Active' list field values change to either 'yes' or 'no'.
Then all you need to do with the API is subscribe users to a single list whenever their accounts are activated or deactivated. Just make sure the new 'ACTIVE' merge field is set to 'yes' or 'no' when you do this, and any addresses already subscribed will be updated with the new value. So your mailchimp.members.create() would look something like this, based on the example from here:
mailchimp.members.create(<list_id>, {
email_address: <user_email>,
merge_fields: {
FNAME: name,
ACTIVE: 'yes' //Or 'no' if being used for deactivated users
},
status: 'subscribed'
})

Related

Stripe Subscription:Customer Creation

I am working on stripe subscription integration in my Spring Boot application. I am able to successfully redirect user to the checkout page and process the payment. I am working on the no-code application and the business model of my app is to charge the customer for each project created. Each time the user process the payment I am saving the customer-id and subscription-id in the database of the project but in order to subscribe to the same customer for the next project I have to create a new customer in the Stripe account and then the same flow continues. So, is it possible to subscribe the same customer for a new project without creating the customer in the stripe account?
I don't see why not. You just need to pass the existing customer Id when creating a checkout session.
That's what I'm doing:
If a user doesn't have a stripe customer created, I create one and store the customer id against my internal user id (I also send the user id in the customer metadata to stripe, so it's easy to correlate them, as they may use different email addresses for payment).
If a customer already exists for the current user, I just use that one.
I'm using typescript, the concept is the same:
// uid is my internal user id
const customerId = getOrCreateCustomer(uid);
const newSession: StripeType.Checkout.SessionCreateParams = {
customer: customerId,
mode: 'subscription',
payment_method_types: ['card'],
customer_update: {
address: 'auto',
name: 'auto',
shipping: 'auto',
},
subscription_data: {
metadata: { uid }, // store uid in subscription metadata as well
},
line_items: [
{
price: priceId,
quantity: 1,
}
],
success_url: successUrl,
cancel_url: cancelUrl,
};

Yii2: How to avoid required fields in a view?

I have a view about holidays where a user uses a form to choose a place to travel and a hotel. It has two models: HolidaysPlaces and HolidaysHotels.
The user have to fill the form in this order using the view:
The user completes the fields called Place and City (related with the HolidaysPlaces model).
The user checked a checkbox if he/she wants to choose a hotel. It able a field called Hotel (related with HolidaysHotels model).
The user completes that field.
The user press a Create button.
The controller receives and saves both models.
But the problem is when the user doesn't select the checkbox (number 2 of the list): The Hotel fieldis still required (with the red asterisk as defined in its model file). So the Create button doesn't work in this case.
How can I disabled the required feature?
Add a scenario for this case in your HolidaysHotels model, and include only the fields that you want checked.
Example: If you have 3 fields name, date and age that are required, create a scenario for two only, and set the scenario in the controller. Only those two fields will be checked.
In model:
public function scenarios(){
$scenarios = parent::scenarios();
$scenarios['create'] = ['name', 'date'];
return $scenarios;
}
In controller:
$holiday = new HolidayHotels();
$holiday->scenario = 'create';
To know more about scenarios: http://www.yiiframework.com/doc-2.0/guide-structure-models.html#scenarios
You can add some condition based validation in your model rules. Here is the snippet for both client and server validation. You can many conditions inside the function block.
['field-1', 'required', 'when' => function ($model) {
return $model->check_box == '1';
}, 'whenClient' => "function (attribute, value) {
return $('#checkbox-id').is(':checked') ';
}"],
The easiest way to solve it is to send the model with empty strings. Then the controller checks if the strings are empty. If so, the model is not saved. Else, it is saved.
It was the only way that works for me.

HapiJS Catbox: How to search a key using some value's fields as search criteria?

In my app when a user is authenticated, I store his session data (including his email) in the server cache, and I create a sessionId that I use as the key.
When a user is deleted from the database, I want to check if he was logged in, that is, if there is a session in the cache that comes from his account, so I can drop that entry from the server cache too.
The problem is that the sessionId is not part of the User model, so I have to lookup his entry from the cache using his email, get the associated key, and drop the entry. Is that possible ?
Thanks in advance.
Catbox is just a key/value store and it doesn't look like there is a way to iterate through cache items like you want and find a user by another property. You need to know the key. You can either make the key the users' email or store sessionId in the database in another table.
You might be doing more work than you have to for session management. Yar is a hapi plugin that provides session management for you. Invalidating a session is pretty simple as well.
When the user logs out use yar.reset() to clear out the session.
Hapi-auth-cookie is another plugin for cookie-based session management.
I finally created a pre that return all the sessionIds associated to the account to be deleted, so I can delete them normally with server.cache.drop(key, cb). Error handling removed for brevity.
function currentSessionIds(request, reply) {
const sessionIds = [];
User.findOne({ _id: request.params.id }, (err, user) => {
const cacheDB = request.server.app.sessionsCache._cache.connection.settings.partition;
MongoClient.connect(`mongodb://host:port/${cacheDB}`, (err, db) => {
db.collection('sessions').find({ 'value.account.email': user.email }, { _id: 1 }).toArray((err, sessions) => {
sessions.forEach(session => sessionIds.push(session._id));
reply(sessionIds);
});
});
});
}
But of course this solution is too tied to mongodb and the way catbox-mongodb strategy store the data. If they change it my function is down.

How to manage new Breeze entities which are aggregate roots?

I have a domain model which has a Customer, which in turn has 1 Address (1:1) and 1 or more Phone numers (1:M).
Customer has user supplied PK (a string), while Address and Phone use identity column (server generated).
I am struggling in trying to understand how to manage Breeze entity creation for a "Add new Customer" screen.
The form on the screen allows user to enter Customer, Address, and Phone data.
I am using Durandal and Knockout so my "customeradd.js" viewmodel looks something like this:
// -- snip ---
var customer = ko.observable(),
hasChanges = ko.computed(function () {
return datacontext.hasChanges();
});
var vm = {
hasChanges: hasChanges,
customer: customer,
activate: activate
};
return vm;
function activate() {
customer(datacontext.createCustomer());
}
// -- snip ---
and my "/services/datacontext.js" :
// -- snip ---
breeze.NamingConvention.camelCase.setAsDefault();
var manager = new breeze.EntityManager(config.remoteServiceName);
var hasChanges = ko.observable(false);
manager.hasChangesChanged.subscribe(function (eventArgs) {
hasChanges(eventArgs.hasChanges);
});
function createVehicle() {
return manager.createEntity("Customer");
}
// -- snip ---
My questions are following:
Once I create a Customer, do I need to create Address and list of Phones and add them to Customer entity before making it a KO observable? Or is this done automatically by createEntity() method?
How do I create a Customer but without having to specify the Id? If I set the key to null or '', Breeze complains ("Error: Cannot attach an object to an EntityManager without first setting its key or setting its entityType 'AutoGeneratedKeyType' property to something other than 'None'"). However, if I generate the temp key (using either breeze.core.getUuid() or something else), then it shows up in my Id form field, and I really want the end user to specify it....Do I have to resort to extending the entity with extra field and then do the swapping and validation before saving (I don't like this idea at all)? Is there a better way?
In order to enable/disable buttons on my form I am tracking if there are changes in EntityManager. But every time entity is created, it is automatically in 'added' state so hasChanges is true. What I want is for changes to be picked up only if user edits the form (and therefore makes changes to underlaying entity). What is the best way to approach this?
BTW, I have seen this recommendation to register custom constructor for entity (I have already implemented it but I am still not clear how to let user supply their own id and to flag entity as modified only when user edits it...)
I realize this has been up for a while, but here are my thoughts (in case anyone comes looking).
If you use the entityManager to create your customerl and everything is specified correctly in the metadata, you can just create the customer and add phone numbers/addresses as needed. Breeze automatically makes an entity's properties observable (if specified correctly and if breeze knows that KO is being used)
If you can only do it the way that you say, then you are stuck. Ideally, you would have a user-entered ID which is NOT the key (though you could still force it to be unique) and a database-generated key, which Breeze will manage behind the scenes (assigning a negative key until it is saved to the data store, then updating the key and all related keys without any input from you).
if you use the 2nd approach for answer 2, then your buttons can easily be enabled and disabled using ko data-binding. When you create the entity, save its value to the viewmodel (custSource). Then you can add to the save button the data-bind="disable: custSource == Customer(), enable: custSource != Customer()". (You might need to play around with the syntax -- I haven't tested that part yet)
I don't think you need a custom constructor unless you are doing something different from what I understand.
PS. you should be aware that I believe Breeze wants Knockout defined as 'ko', while Durandal definitely expects it to be 'knockout', so you will probably need a 'map' property in your require.config
I think you could solve some of your problems by taking a slightly different approach to your entity creation. Here's your current approach:
Create a customer entity
User modifies that entity
Save the changes
Instead, try this:
User enters customer information
Create and save the customer entity
I realize that this doesn't really answer your questions, but I've found the second approach to be much easier to implement. Just have the user enter all the information you need to create a customer, and then supply those values to createEntity.
customeradd.js
// -- snip ---
var vm = {
customerId: ko.observable(),
address: ko.observable(""),
phoneNumbers: ko.observableArray([]),
submit: submit
};
return vm;
function submit() {
datacontext.createCustomer(
vm.customerId(),
vm.address(),
vm.phoneNumbers());
}
// -- snip ---
/services/datacontext.js
// -- snip ---
/**
* Creates a new customer.
* #param {int} id - The customer's id number.
* #param {string} address - The customer's address.
* #param {string[]} phoneNumbers - An array of the customer's phone numbers.
*/
function createCustomer(id, address, phoneNumbers) {
return manager.createEntity("Customer",
{
id: id,
address: address,
phoneNumber: phoneNumbers
});
}
// -- snip ---

Adding a custom field to Magento's subscription module

The newsletter subscription module in Magento has only one field (email) by default. After I add an extra field to the form (say country), how can I get the form data to show up in the Magento back-end and be sent as an email to a preset recipient? Thanks.
If you want to add some custom fields for Magento newsletter subscriber (for example subscriber_name), you should do the following:
Add new column for newsletter_subscriber table
Add text input to newsletter template
Create observer for newsletter_subscriber_save_before event
In the observer you can get your custom field's value from request and assign it to subscriber's object:
public function newsletterSubscriberSave(Varien_Event_Observer $observer)
{
$subscriber = $observer->getEvent()->getSubscriber();
$name = Mage::app()->getRequest()->getParam('subscriber_name');
$subscriber->setSubscriberName($name);
return $this;
}
UPDATE:
Here is the detailed article explaining how to add Country field
Also, I have created a free module, it is available on the GitHub
There are a few things that you need to take care of to make this work:
Add a new column for your data to the appropriate database table
Make sure that Magento saves your new field to the database
Present the data in the admin backend
Record the data when you get a new newsletter subscription
Here's how you can do all those things:
Ad. 1)
Using phpMyAdmin, MySQL command line, or whatever is your preferred DB manipulation method, add a new column "country" as, say, varchar(100) to the newsletter_subscriber table.
Ad. 2)
Magento will automatically give you access to the new field through the getCountry() and setCountry() methods on the Mage_Newsletter_Model_Subscriber object. The only thing it won't do is save your field back to the DB after it has been changed with code somewhere in the system. To get it saved you need to modify _prepareSave(Mage_Newsletter_Model_Subscriber $subscriber) function found in Mage_Newsletter_Model_Mysql4_Subscriber (app/code/core/Mage/Newsletter/Model/Mysql4/Subscriber.php). Be sure to make a local copy of the file first and not modify the core file. Here's what you need to add:
protected function _prepareSave(Mage_Newsletter_Model_Subscriber $subscriber)
{
$data = array();
$data['customer_id'] = $subscriber->getCustomerId();
$data['store_id'] = $subscriber->getStoreId()?$subscriber->getStoreId():0;
$data['subscriber_status'] = $subscriber->getStatus();
$data['subscriber_email'] = $subscriber->getEmail();
$data['subscriber_confirm_code'] = $subscriber->getCode();
//ADD A NEW FIELD START
//note that the string index for the $data array
//must match the name of the column created in step 1
$data['country'] = $subscriber->getCountry();
//ADD A NEW FIELD END
(...)
}
Ad. 3)
You will need to modify (a local copy of) the file app/code/core/Mage/Adminhtml/Block/Newsletter/Subscriber/Grid.php. The method you are looking for is called _prepareColumns(). In there you will see a series of calls to $this->addColumn(). You need to add a corresponding call for your "Country" field with the following code:
$this->addColumn('country', array(
'header' => Mage::helper('newsletter')->__('Country'),
//the index must match the name of the column created in step 1
'index' => 'country',
'default' => '----'
));
If you want the field to appear at the end of the grid (as the last column) add it as the last call, otherwise, squeeze it between the existing calls exactly where you want it to end up in the admin.
Ad. 4)
This is a part I did not have to do in my customization of the Magento newsletter, so it will be mostly theoretical. The subscription occurs in the controller located at app/code/core/Mage/Newsletter/controllers/SubscriberController.php. Here's the code of the newAction method with my proposed changes:
public function newAction()
{
if ($this->getRequest()->isPost() && $this->getRequest()->getPost('email')) {
$session = Mage::getSingleton('core/session');
$email = (string) $this->getRequest()->getPost('email');
try {
if (!Zend_Validate::is($email, 'EmailAddress')) {
Mage::throwException($this->__('Please enter a valid email address'));
}
$status = Mage::getModel('newsletter/subscriber')->subscribe($email);
if ($status == Mage_Newsletter_Model_Subscriber::STATUS_NOT_ACTIVE) {
$session->addSuccess($this->__('Confirmation request has been sent'));
}
else {
$session->addSuccess($this->__('Thank you for your subscription'));
}
//ADD COUNTRY INFO START
//at this point we may safly assume that subscription record was created
//let's retrieve this record and add the additional data to it
$subscriber = Mage::getModel('newsletter/subscriber')->loadByEmail($email);
//assuming that the input's id is "country"
$subscriber->setCountry((string) $this->getRequest()->getPost('country'));
//don't forget to save the subscriber!
$subscriber->save();
//ADD COUNTRY INFO END
}
catch (Mage_Core_Exception $e) {
$session->addException($e, $this->__('There was a problem with the subscription: %s', $e->getMessage()));
}
catch (Exception $e) {
$session->addException($e, $this->__('There was a problem with the subscription'));
}
}
$this->_redirectReferer();
}
Going through the above steps should take care of the most part of your problem. Let me know how that last part worked out, as I did not have a chance to test it.
Once you have your additional field in the Subscriber object you can do whatever you want with it. I did not really get what you mean by
be sent as an email to a preset recipient
If you can explain that I will try to help you out with this part too.
Edit - how to send a mail when someone subscribes
Just add the following code to the controller after the part which adds country to a subscriber object.
$mail = new Zend_Mail();
$mail->setBodyHtml("New subscriber: $email <br /><br />Country: ".$this->getRequest()->getPost('country'));
$mail->setFrom("youremail#email.com")
->addTo("admin#mysite.com")
->setSubject("Your Subject here");
$mail->send();
Adding to the accepted answer, you can also get away with this a little easier if you're adding a date, datetime, or timestamp-type column.
In my case, I wanted to add a "Subscribed at Date" to my grid. To do this, I wrote my upgrade script, column type being TIMESTAMP and the default value being CURRENT_TIMESTAMP. This way, when the row is added, the current date/time is recorded.
Then, all you have to do is add your block customizations. I'd suggest doing it by extending Magento's grid block rather than doing the local codepool override though. This way, you only need to override _prepareColumns();
Old thread but if someone has the same question, there is a free extension, that adds fields for gender, firstname and lastname and makes it available in the backend grid for export via xml/csv: http://www.magentocommerce.com/magento-connect/extended-newsletter-subscription-for-guests.html
Perhaps you can extend the code to fit your needs.
This is a warning for anyone who's installed the Ebizmarts_MailChimp extension.
It's a great extension. But it adds subscriber_firstname and subscriber_lastname to the newsletter_subscriber table.
If you intend to create these fields, you should either "require" the Ebizmarts_MailChimp extension or check the fields don't exist before your extension creates them.
In the opposite, where you've created them and want to install the the Ebizmarts_MailChimp extension after you've created these fields, you will have to comment out the addColumn code for these two fields during installation.

Resources