menu

SiteGenesis / Server-side JS / Source: app_storefront_controllers/cartridge/controllers/GiftRegistry.js

'use strict';

/**
 * Controller for gift registry business logic.
 *
 * @module  controllers/GiftRegistry
 */

/* API Includes */
var giftRegistryType = require('dw/customer/ProductList').TYPE_GIFT_REGISTRY;
var GiftCertProductListItem = require('dw/customer/ProductListItem').TYPE_GIFT_CERTIFICATE;
var ProductListMgr = require('dw/customer/ProductListMgr');
var Transaction = require('dw/system/Transaction');
var URLUtils = require('dw/web/URLUtils');

/* Script Modules */
var app = require('~/cartridge/scripts/app');
var guard = require('~/cartridge/scripts/guard');

var Content = app.getModel('Content');
var ProductList = app.getModel('ProductList');
var Form = app.getModel('Form');

/**
 * Renders a list of gift registries associated with the current customer.
 * Clears the productlists form and gets the product lists associated with a customer. Gets the
 * myaccount-giftregistry content asset, updates the page metadata and renders the registry list
 * page (account/giftregistry/registrylist template).
 */
function start() {
    var accountGiftRegistry = Content.get('myaccount-giftregistry');
    var pageMeta = require('~/cartridge/scripts/meta');
    var productLists = ProductListMgr.getProductLists(customer, giftRegistryType);
    var productListsForm = Form.get('productlists');
    var productListItems = productListsForm.get('items');

    pageMeta.update(accountGiftRegistry);

    Form.get(productListsForm).clear();
    productListItems.copyFrom(productLists);

    app.getView({
        ContinueURL: URLUtils.https('GiftRegistry-SubmitForm')
    }).render('account/giftregistry/registrylist');
}

/**
 * Controls the form submission that is required to access gift registry actions.
 */
function submitForm() {
    Form.get('giftregistry').handleAction({
        addToCart: function (form) {
            var cart = app.getModel('Cart').goc();

            if (form.items.triggeredAction.parent.object.type === GiftCertProductListItem) {
                response.redirect(URLUtils.https('GiftCert-Purchase'));
            } else {
                var renderInfo = cart.addProductToCart();

                if (renderInfo.template === 'checkout/cart/cart') {
                    app.getView('Cart', {
                        Basket: cart
                    }).render(renderInfo.template);
                } else if (renderInfo.format === 'ajax') {
                    app.getView('Cart', {
                        cart: cart,
                        BonusDiscountLineItem: renderInfo.newBonusDiscountLineItem
                    }).render(renderInfo.template);
                } else {
                    response.redirect(URLUtils.url('Cart-Show'));
                }

            }
        },

        create: createOne,

        confirm: confirm,

        deleteItem: function (form, action) {
            var productListItem = action.object;
            var productList = ProductList.get(productListItem.list);

            productList.removeItem(productListItem);

            showRegistry({ProductList: productList.object});
        },

        public: function (form, action) {
            var productListItem = action.object;
            productListItem.setPublic(productListItem.public);
        },

        search: function (form, action) {
            var CSRFProtection = require('dw/web/CSRFProtection');

            if (!CSRFProtection.validateRequest()) {
                if (request.httpParameterMap.format.stringValue === 'ajax') {
                    app.getModel('Customer').logout();
                    let r = require('~/cartridge/scripts/util/Response');
                    r.renderJSON({
                        error: 'CSRF Token Mismatch'
                    });
                    return null;
                } else {
                    app.getModel('Customer').logout();
                    app.getView().render('csrf/csrffailed');
                    return null;
                }
            }

            var productLists = ProductList.search(action.parent.simple, giftRegistryType);

            app.getView({ProductLists: productLists}).render('account/giftregistry/giftregistryresults');
        },

        setParticipants: setParticipants,

        setBeforeAfterAddresses: handleRegistryAddresses,

        setPublic: function (form, action) {
            var productList = action.object;
            setProductListPublic(productList, true);
        },

        setPrivate: function (form, action) {
            var productList = action.object;
            setProductListPublic(productList, false);
        },

        updateItem: function (form, action) {
            var productList = ProductList.get(action.object.list);
            productList.updateItem(form.items);

            showRegistry({ProductList: productList.object});
        },

        addGiftCertificate: function (form) {
            var productList = ProductList.get(form.object);

            Transaction.wrap(function () {
                productList.createGiftCertificateItem();
            });

            showRegistry({ProductList: productList.object});
        },

        navPurchases: function (form) {
            var productList = ProductList.get(form.object);
            app.getView({
                ProductList: productList.object
            }).render('account/giftregistry/purchases');
        },

        navEvent: function (form) {
            var productList = ProductList.get(form.object);
            editParticipant(productList.object, form);
        },

        navShipping: function(form) {
            var productList = ProductList.get(form.object);
            editEventAddresses(productList.object, form);
        },

        navRegistry: function(form) {
            var productList = ProductList.get(form.object);
            showRegistry({
                ProductList: productList.object
            });
        }
    });
}

/**
 * Adds a product to the gift registry. The product must either be a Product object, or is identified by its
 * product ID using the dictionary key ProductID or, if empty, uses the HTTP parameter "pid".
 */
function addProduct() {
    var params = request.httpParameterMap;
    var productId = params.pid.stringValue;
    var ProductModel = app.getModel('Product');
    var product;
    var productList;
    var productLists;
    var qtyProductLists;

    if (productId) {
        product = ProductModel.get(productId);
    } else {
        throw 'Product ID required but not provided.';
    }

    productLists = ProductListMgr.getProductLists(customer, giftRegistryType);
    qtyProductLists = productLists.size();

    if (productLists && qtyProductLists) {
        if (qtyProductLists === 1) {
            productList = ProductList.get(productLists.iterator().next());
            productList.addProduct(product.object);
        } else {
            selectOne();
            return;
        }
    } else {
        createOne();
        return;
    }

    showRegistry({
        ProductList: productList.object
    });
}


/**
 * Initiates the creation of a gift registry entry in three stages:
 *     1) Specify event participants
 *     2) Specify pre- and post-event addresses
 *     3) Confirm Gift Registry details
 * Renders the event participant page (account/giftregistry/eventparticipant template).
 */
function createOne() {
    var giftRegistryForm = Form.get('giftregistry');
    var participant = giftRegistryForm.get('event.participant');
    var profile = customer.profile;

    giftRegistryForm.clear();

    participant.setValue('firstName', profile.firstName);
    participant.setValue('lastName', profile.lastName);
    participant.setValue('email', profile.email);

    app.getView().render('account/giftregistry/eventparticipant');
}

/**
 * Event handler for gift registry addresses.
 * Checks the last triggered action and handles them depending on the formId associated with the triggered action.
 * If the formId is:
 * - __back__ - calls the {@link module:controllers/GiftRegistry~start|start} function
 * - __confirm__ - if there are no addresses in the customer address book, sets a flag to indicate the
 * before event shipping address is new. Calls the {@link module:controllers/GiftRegistry~setParticipants|setParticipants} function.
 * @FIXME Doesn't appear to ever be called.
 */
function eventParticipant() {
    var currentForms = session.forms;
    // TODO this should be some redirect
    var TriggeredAction = request.triggeredFormAction;
    if (TriggeredAction !== null) {
        if (TriggeredAction.formId === 'back') {
            start();
            return;
        } else if (TriggeredAction.formId === 'confirm') {
            if (customer.profile.addressBook.addresses.size() === 0) {
                currentForms.giftregistry.eventaddress.beforeEventAddress.value = 'newaddress';
            }

            setParticipants();
        }
    }
}

/**
 * Renders the gift registry addresses page (account/giftregistry/addresses template).
 */
function setParticipants() {
    app.getView().render('account/giftregistry/addresses');
}

/**
 * Renders the gift registry confirmation page (account/giftregistry/giftregistryconfirmation template).
 */
function handleRegistryAddresses() {
    app.getView().render('account/giftregistry/giftregistryconfirmation');
}

/**
 * Selects a gift registry from a list of gift registries that are found by the registry search.
 * Called by {@link module:controllers/GiftRegistry~addProduct}.
 */
function selectOne() {
    var currentForms = session.forms;
    var ProductLists = ProductListMgr.getProductLists(customer, giftRegistryType);

    Form.get(currentForms.productlists.items).copyFrom(ProductLists);

    app.getView().render('account/giftregistry/registryselect');
}

/**
 * Makes a ProductList public or private
 *
 * @param {dw.customer.ProductList} productList
 * @param {Boolean} isPublic - true to make public; false to make private
 */
function setProductListPublic (productList, isPublic) {
    var productListWrapper = ProductList.get(productList);
    productListWrapper.setPublic(isPublic);

    showRegistry({ProductList: productListWrapper.object});
}

/**
 * Provides actions to edit a gift registry event.
 */
function selectProductListInteraction() {
    // TODO this should end in a redirect
    var TriggeredAction = request.triggeredFormAction;
    if (TriggeredAction !== null) {
        if (TriggeredAction.formId === 'select') {

            //TODO : jshint -> 'ProductList' is defined but never used.
            //var ProductList = TriggeredAction.object;
            // TODO interaction continue not supported anymore
            // where to continue now?
            return;
        }
    }

    // TODO what to render otherwise?
}

/**
 * Clears the giftregistry form and prepopulates event and participant information from the current ProductListModel.
 * Calls the {@link module:controllers/GiftRegistry~showEditParticipantForm|showEditParticipantForm} function.
 */
function editParticipant(productList, giftRegistryForm) {
    var eventForm = app.getForm(giftRegistryForm.event);
    var participantForm = app.getForm(giftRegistryForm.event.participant);
    var coParticipantForm =  app.getForm(giftRegistryForm.event.coParticipant);

    eventForm.clear();
    participantForm.clear();
    coParticipantForm.clear();

    eventForm.copyFrom(productList);
    participantForm.copyFrom(productList.registrant);

    if (productList.coRegistrant) {
        coParticipantForm.copyFrom(productList.coRegistrant);
    }

    app.getForm(giftRegistryForm.event.eventaddress.states).setValue('state', productList.eventState);
    app.getForm(giftRegistryForm.event.eventaddress).setValue('country', productList.eventCountry);

    // Renders the event participant page (account/giftregistry/eventparticipant template).
    app.getView({
        ProductList: productList,
        ContinueURL: URLUtils.https('GiftRegistry-EditEvent')
    }).render('account/giftregistry/eventparticipant');
}

function editEvent() {
    Form.get('giftregistry').handleAction({
        setParticipants: function (form) {
            var productList = ProductList.get(form.object);

            Transaction.wrap(function () {
                app.getForm(form.event).copyTo(productList.object);
                app.getForm(form.event.participant).copyTo(productList.object.registrant);
                productList.object.setEventState(form.event.eventaddress.states.state.value);
                productList.object.setEventCountry(form.event.eventaddress.country.value);

                if (form.event.coParticipant.firstName.value || form.event.coParticipant.lastName.value) {
                    if (!productList.object.coRegistrant) {
                        productList.object.createCoRegistrant();
                    }
                    app.getForm(form.event.coParticipant).copyTo(productList.object.coRegistrant);
                }
            });

            showRegistry({
                ProductList: productList.object
            });
        },

        navPurchases: function (form) {
            var productList = ProductList.get(form.object);
            app.getView({
                ProductList: productList.object
            }).render('account/giftregistry/purchases');
        },

        navEvent: function (form) {
            var productList = ProductList.get(form.object);
            editParticipant(productList.object, form);
        },

        navShipping: function(form) {
            var productList = ProductList.get(form.object);
            editEventAddresses(productList.object, form);
        },

        navRegistry: function(form) {
            var productList = ProductList.get(form.object);
            showRegistry({
                ProductList: productList.object
            });
        },

        setBeforeAfterAddresses: function(form) {
            var assignEventAddresses = require('app_storefront_core/cartridge/scripts/account/giftregistry/AssignEventAddresses');
            var productList = ProductList.get(form.object);

            Transaction.wrap(function () {
                assignEventAddresses.assignEventAddresses({
                    ProductList: productList.object,
                    Customer: customer,
                    GiftRegistryForm: form
                });
            });

            showRegistry({
                ProductList: productList.object
            });

        }

    })
}

function editEventAddresses(productList, eventAddressForm) {
    app.getForm(eventAddressForm.eventaddress).clear();
    if (productList.shippingAddress) {
        app.getForm(eventAddressForm.eventaddress.addressBeforeEvent).copyFrom(productList.shippingAddress);
        app.getForm(eventAddressForm.eventaddress.addressBeforeEvent.states).setValue('state', productList.shippingAddress.stateCode);
    }

    if (productList.postEventShippingAddress) {
        app.getForm(eventAddressForm.eventaddress.addressAfterEvent).copyFrom(productList.postEventShippingAddress);
        app.getForm(eventAddressForm.eventaddress.addressAfterEvent.states).setValue('state', productList.postEventShippingAddress.stateCode);
    }

    app.getView({
        ProductList: productList,
        ContinueURL: URLUtils.https('GiftRegistry-EditEvent')
    }).render('account/giftregistry/addresses');
}

/**
 * Renders a gift registry details page (account/giftregistry/registry template) and provides basic actions such as item updates and publishing.
 * @param {Object} pdict
 */
function showRegistry(pdict) {
    var ProductList = pdict.ProductList;

    Form.get('giftregistry').copyFrom(ProductList);
    Form.get('giftregistry.event').copyFrom(ProductList);

    app.getView({
        Status: null,
        ProductList: ProductList,
        ContinueURL: URLUtils.https('GiftRegistry-SubmitForm')
    }).render('account/giftregistry/registry');
}

/**
 * Looks up a gift registry by its public UUID. If the customer is authenticated, it calls
 * the {@link module:controllers/GiftRegistry~showRegistry|showRegistry} function. If the customer
 * is not authenticated, it calls calls the {@link module:controllers/Account~show|Account
 * controller show function}.
 */
function showRegistryByID() {
    var currentHttpParameterMap = request.httpParameterMap;
    var productList;

    if (!customer.authenticated) {
        response.redirect(URLUtils.https('Account-Show'));
        return;
    }

    productList = ProductListMgr.getProductList(currentHttpParameterMap.ProductListID.value);

    if (!productList) {
        start();
        return;
    }

    if (productList.owner.profile.customerNo === customer.profile.customerNo) {
        showRegistry({
            ProductList: productList
        });
        return;
    }
}

/**
 * Handles the confirm action for the giftregistry form. Checks to makes sure the before and after
 * event addresses do not already exist in the customer profile. If the addresses are duplicates,
 * calls the {@link module:controllers/GiftRegistry~setParticipants|setParticipants} function.
 * If they are not duplicates, calls the AssignEventAddresses.js script to assign the event addresses
 * to the product list and then calls the {@link module:controllers/GiftRegistry~showRegistry|showRegistry} function.
 *
 * @transaction
 * @returns {Object} JSON object indicating an error occurred in the AssignEventAddresses.js script.
 */
function confirm() {
    var giftRegistryForm = Form.get('giftregistry');
    var dwProductList = Transaction.wrap(function () {
        return ProductListMgr.createProductList(customer, giftRegistryType);
    });
    var productList = ProductList.get(dwProductList);

    Transaction.wrap(function () {
        var assignEventAddresses = require('app_storefront_core/cartridge/scripts/account/giftregistry/AssignEventAddresses');
        var eventForm = Form.get('giftregistry.event');
        var participantForm = Form.get('giftregistry.event.participant');

        eventForm.copyTo(productList.object);
        productList.createRegistrant();
        participantForm.copyTo(productList.object.registrant);
        productList.setEventState(giftRegistryForm.getValue('event.eventaddress.states.state'));

        assignEventAddresses.assignEventAddresses({
            ProductList: productList.object,
            Customer: customer,
            GiftRegistryForm: giftRegistryForm.object
        });
    });

    showRegistry({ProductList: productList.object});
}

/**
 * Deletes a gift registry. Only the logged-in owner of the gift registry can delete it.
 *
 * @secure
 */
// Used 'deleteList' rather than 'delete' as the latter is a reserved word in Javascript
function deleteList() {
    var params = request.httpParameterMap;
    var productList = ProductList.get(params.ProductListID.value);
    productList.remove();

    start();
}


/**
 * Creates a gift registry. Calls the {@link module:controllers/GiftRegistry~createOne|createOne} function.
 */
function create() {
    createOne();
}

//TODO :jshint ->  'updateAll' is defined but never used.
// function updateAll() {
//     var currentForms = session.forms;

//     // TODO do in a single transaction
//     for (var i = 0; i < currentForms.giftregistry.items.length; i++) {
//         var item = currentForms.giftregistry.items[i];
//         if (!Form.get(item).copyTo(item.object)) {
//             return {
//                 error: true
//             };
//         }
//     }
// }


/**
 * Web exposed methods
 */

/**
 * Creates a gift registry.
 * @see module:controllers/GiftRegistry~start
 */
exports.Create = guard.ensure(['get', 'https'], create);

/**
 * Deletes a gift registry.
 * @see module:controllers/GiftRegistry~confirmation
 */
exports.Delete = guard.ensure(['get', 'https'], deleteList);

/**
 * Event handler for editing of gift registry.
 * @see module:controllers/GiftRegistry~editEvent
 */
exports.EditEvent = guard.ensure(['post', 'https'], editEvent);

/**
 * Event handler for gift registry addresses.
 * @see module:controllers/GiftRegistry~eventParticipant
 */
exports.EventParticipant = guard.ensure(['post', 'https'], eventParticipant);

/**
 * Provides actions to edit a gift registry event.
 * @see module:controllers/GiftRegistry~selectProductListInteraction
 */
exports.SelectProductListInteraction = guard.ensure(['post', 'https'], selectProductListInteraction);

/**
 * Looks up a gift registry by its public UUID.
 * @see module:controllers/GiftRegistry~showRegistryByID
 */
exports.ShowRegistryByID = guard.ensure(['get', 'https'], showRegistryByID);

/**
 * Controls the login that is required to access gift registry actions.
 * @see module:controllers/GiftRegistry~submitForm
 */
exports.SubmitForm = guard.ensure(['post', 'https', 'loggedIn'], submitForm);

/**
 * Renders a list of gift registries associated with the current customer.
 * @see module:controllers/GiftRegistry~start
 */
exports.Start = guard.ensure(['get', 'https', 'loggedIn'], start, {scope: 'giftregistry'});

/**
 * Adds a product to the gift registry.
 * @see module:controllers/GiftRegistry~addProduct
 */
exports.AddProduct = guard.ensure(['get', 'https', 'loggedIn'], addProduct);

/**
 * Renders the gift registry details page.
 * @see module:controllers/GiftRegistry~showRegistry
 */
exports.ShowRegistry = showRegistry;