diff --git a/headless-commerce/README.adoc b/headless-commerce/README.adoc new file mode 100644 index 000000000..1fef6b4d0 --- /dev/null +++ b/headless-commerce/README.adoc @@ -0,0 +1,3 @@ + +The files in this directory are used as templates for the ant create-component target, + +please do not modify them without understanding the effect that it will have on that build target. \ No newline at end of file diff --git a/headless-commerce/api/headless-commerce.rest.xml b/headless-commerce/api/headless-commerce.rest.xml new file mode 100644 index 000000000..f791b9cec --- /dev/null +++ b/headless-commerce/api/headless-commerce.rest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/headless-commerce/build.gradle b/headless-commerce/build.gradle new file mode 100644 index 000000000..0056e3fb9 --- /dev/null +++ b/headless-commerce/build.gradle @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +dependencies { + //Examples of compile-time and runtime dependencies + + //pluginLibsCompile 'junit:junit-dep:4.10' + //pluginLibsRuntime 'junit:junit-dep:4.10' +} + +task install { + doLast { + // Install logic for this plugin + } +} + +task uninstall { + doLast { + // uninstall logic for this plugin + } +} diff --git a/headless-commerce/config/HeadlessCommerceUiLabels.xml b/headless-commerce/config/HeadlessCommerceUiLabels.xml new file mode 100644 index 000000000..6b127d138 --- /dev/null +++ b/headless-commerce/config/HeadlessCommerceUiLabels.xml @@ -0,0 +1,52 @@ + + + + + + HeadlessCommerce Application + HeadlessCommerce应用程序 + HeadlessCommerce應用程式 + + + OFBiz: HeadlessCommerce + OFBiz: HeadlessCommerce + + + Part of the Apache OFBiz Family of Open Source Software + Un modulo della famiglia di software open source Apache OFBiz + 开源软件OFBiz的组成部分 + 開源軟體OFBiz的組成部分 + + + You are not allowed to view this page. + 不允许你浏览这个页面。 + 不允許您檢視這個頁面. + + + State [${stateCode}] does not in country [${countryCode}] + + + Invalid country [${countryCode}] + + + Access denied. Invalid user. + + + diff --git a/headless-commerce/data/HeadlessCommerceDemoData.xml b/headless-commerce/data/HeadlessCommerceDemoData.xml new file mode 100644 index 000000000..b76e67e05 --- /dev/null +++ b/headless-commerce/data/HeadlessCommerceDemoData.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/headless-commerce/data/HeadlessCommerceSecurityGroupDemoData.xml b/headless-commerce/data/HeadlessCommerceSecurityGroupDemoData.xml new file mode 100644 index 000000000..2ac611fa3 --- /dev/null +++ b/headless-commerce/data/HeadlessCommerceSecurityGroupDemoData.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + diff --git a/headless-commerce/data/HeadlessCommerceSecurityPermissionSeedData.xml b/headless-commerce/data/HeadlessCommerceSecurityPermissionSeedData.xml new file mode 100644 index 000000000..fef790a8d --- /dev/null +++ b/headless-commerce/data/HeadlessCommerceSecurityPermissionSeedData.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + diff --git a/headless-commerce/data/HeadlessCommerceTypeData.xml b/headless-commerce/data/HeadlessCommerceTypeData.xml new file mode 100644 index 000000000..b76e67e05 --- /dev/null +++ b/headless-commerce/data/HeadlessCommerceTypeData.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/headless-commerce/entitydef/entitymodel.xml b/headless-commerce/entitydef/entitymodel.xml new file mode 100644 index 000000000..adba0b411 --- /dev/null +++ b/headless-commerce/entitydef/entitymodel.xml @@ -0,0 +1,31 @@ + + + + + + + + Entity of HeadlessCommerce Component + None + + + + \ No newline at end of file diff --git a/headless-commerce/ofbiz-component.xml b/headless-commerce/ofbiz-component.xml new file mode 100644 index 000000000..4ef2d97f9 --- /dev/null +++ b/headless-commerce/ofbiz-component.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/headless-commerce/servicedef/services.xml b/headless-commerce/servicedef/services.xml new file mode 100644 index 000000000..e2c85bd51 --- /dev/null +++ b/headless-commerce/servicedef/services.xml @@ -0,0 +1,249 @@ + + + + + HeadlessCommerce Services + + 1.0 + + + + + Contains true if the if the requesting user is valid. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To get the customer's shipping addresses + + + + + + + + + + + + + + + + + + + + + + + + + + To create the postal address with purpose + + + + + + + + + + + + + To update the postal address and to add a purpose + + + + + + + + + + + + + + To remove the the party contact mech + + + + + + creates credit card, gift card, eft account + + + + + + + + + + + + + + + + + + + + + + + + + updates credit card, gift card, eft account + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + delete payment method(credit card, giftt card, EFT account) + + + + + + \ No newline at end of file diff --git a/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/common/CommonUtil.java b/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/common/CommonUtil.java new file mode 100644 index 000000000..90dc79c52 --- /dev/null +++ b/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/common/CommonUtil.java @@ -0,0 +1,34 @@ +package org.apache.ofbiz.hc.api.common; + +import org.apache.ofbiz.base.util.UtilValidate; +import org.apache.ofbiz.entity.Delegator; +import org.apache.ofbiz.entity.GenericEntityException; +import org.apache.ofbiz.entity.GenericValue; +import org.apache.ofbiz.entity.util.EntityQuery; +import org.apache.ofbiz.hc.api.customer.CustomerServices; + +public class CommonUtil { + public static final String MODULE = CommonUtil.class.getName(); + + public static GenericValue getProductStore (Delegator delegator, String webSiteId) throws GenericEntityException { + if (UtilValidate.isNotEmpty(webSiteId)) { + GenericValue webSite = EntityQuery.use(delegator).from("WebSite").where("webSiteId", webSiteId).queryOne(); + if (webSite != null) { + String productStoreId = webSite.getString("productStoreId"); + if (UtilValidate.isNotEmpty(productStoreId)) { + return EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).queryOne(); + } + } + } + return null; + } + public static boolean isValidCutomer (Delegator delegator, GenericValue userLogin, String customerPartyId) throws GenericEntityException { + if (UtilValidate.isNotEmpty(customerPartyId) && userLogin != null && customerPartyId.equalsIgnoreCase(userLogin.getString("partyId"))) { + GenericValue partyRole = EntityQuery.use(delegator).from("PartyRole").where("partyId", customerPartyId, "roleTypeId", "CUSTOMER").queryOne(); + if (partyRole != null) { + return true; + } + } + return false; + } +} diff --git a/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/customer/CustomerHelper.java b/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/customer/CustomerHelper.java new file mode 100644 index 000000000..fb44cb843 --- /dev/null +++ b/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/customer/CustomerHelper.java @@ -0,0 +1,125 @@ +package org.apache.ofbiz.hc.api.customer; + +import jdk.nashorn.internal.runtime.logging.DebugLogger; +import org.apache.ofbiz.base.util.Debug; +import org.apache.ofbiz.base.util.UtilMisc; +import org.apache.ofbiz.base.util.UtilProperties; +import org.apache.ofbiz.base.util.UtilValidate; +import org.apache.ofbiz.entity.Delegator; +import org.apache.ofbiz.entity.GenericEntityException; +import org.apache.ofbiz.entity.GenericValue; +import org.apache.ofbiz.entity.condition.EntityCondition; +import org.apache.ofbiz.entity.condition.EntityOperator; +import org.apache.ofbiz.entity.util.EntityQuery; +import org.apache.ofbiz.party.party.PartyHelper; +import org.apache.ofbiz.service.GenericServiceException; +import org.apache.ofbiz.service.LocalDispatcher; +import org.apache.ofbiz.service.ServiceUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CustomerHelper { + public static final String MODULE = CustomerServices.class.getName(); + + public static Map getLoyaltyPoints(LocalDispatcher dispatcher, String customerPartyId, GenericValue userLogin) throws GenericServiceException { + Map loyaltyPointMap = new HashMap<>(); + if (UtilValidate.isNotEmpty(customerPartyId)) { + //TODO: Need to make it configurable + int monthsToInclude = 12; + Map result = dispatcher.runSync("getOrderedSummaryInformation", + UtilMisc.toMap("partyId", customerPartyId, "roleTypeId", "PLACING_CUSTOMER", + "orderTypeId", "SALES_ORDER", "statusId", "ORDER_COMPLETED", "monthsToInclude", monthsToInclude, "userLogin", userLogin)); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return null; + } + loyaltyPointMap.put("points", result.get("totalSubRemainingAmount")); + loyaltyPointMap.put("totalOrders", result.get("totalOrders")); + loyaltyPointMap.put("monthsToInclude", monthsToInclude); + } + return loyaltyPointMap; + } + public static List> prepareContactMechPurposeList(Delegator delegator, List partyContactMechPurposes) throws GenericEntityException { + List> contactMechPurposes = new ArrayList<>(); + for (GenericValue partyContactMechPurpose : partyContactMechPurposes) { + Map purposeMap = new HashMap<>(); + GenericValue contactMechPurposeType = EntityQuery.use(delegator).from("ContactMechPurposeType").where("contactMechPurposeTypeId", partyContactMechPurpose.getString("contactMechPurposeTypeId")).queryOne(); + purposeMap.put("contactMechPurposeTypeId", contactMechPurposeType.getString("contactMechPurposeTypeId")); + purposeMap.put("description", contactMechPurposeType.getString("description")); + contactMechPurposes.add(purposeMap); + } + return contactMechPurposes; + } + public static List> getPartyContactLists(Delegator delegator, String customerPartyId) throws GenericEntityException { + List> subscriptionList = new ArrayList<>(); + List contactListPartyList = EntityQuery.use(delegator).from("ContactListParty").where("partyId", customerPartyId).orderBy("-fromDate").queryList(); + for (GenericValue contactListParty : contactListPartyList) { + Map infoMap = new HashMap<>(); + GenericValue contactList = EntityQuery.use(delegator).from("ContactList").where("contactListId", contactListParty.getString("contactListId")).queryOne(); + GenericValue statusItem = EntityQuery.use(delegator).from("StatusItem").where("statusId", contactListParty.getString("statusId")).queryOne(); + GenericValue emailContactMech = EntityQuery.use(delegator).select("infoString").from("ContactMech").where("contactMechId", contactListParty.getString("preferredContactMechId"), "contactMechTypeId", "EMAIL_ADDRESS").queryOne(); + infoMap.put("contactListId", contactList.getString("contactListId")); + infoMap.put("email", emailContactMech.getString("infoString")); + infoMap.put("contactListName", contactList.getString("contactListName")); + infoMap.put("description", contactList.getString("description")); + infoMap.put("fromDate", contactListParty.getString("fromDate")); + infoMap.put("thruDate", contactListParty.getString("thruDate")); + infoMap.put("status", UtilMisc.toMap("statusId", statusItem.getString("statusId"), + "description", statusItem.getString("description"), "statusCode", statusItem.getString("statusCode"))); + subscriptionList.add(infoMap); + } + return subscriptionList; + } + public static List> getPartyCommunications(Delegator delegator, String customerPartyId, boolean showReceived, boolean showSent) throws GenericEntityException { + List> communications = new ArrayList<>(); + EntityCondition condition = null; + if (showReceived && showSent) { + condition = EntityCondition.makeCondition( + EntityCondition.makeCondition("partyIdTo", customerPartyId), + EntityOperator.OR, + EntityCondition.makeCondition("partyIdFrom", customerPartyId)); + } else if (showReceived) { + condition = EntityCondition.makeCondition("partyIdTo", customerPartyId); + } else if (showSent) { + condition = EntityCondition.makeCondition("partyIdFrom", customerPartyId); + } + + List communicationEvents = EntityQuery.use(delegator).from("CommunicationEvent").where(condition).orderBy("-entryDate").queryList(); + for (GenericValue communicationEvent : communicationEvents) { + Map infoMap = new HashMap<>(); + String fromPartyName = PartyHelper.getPartyName(delegator, communicationEvent.getString("partyIdFrom"), true) ; + String toPartyName = PartyHelper.getPartyName(delegator, communicationEvent.getString("partyIdTo"), true) ; + infoMap.put("communicationEventId", communicationEvent.getString("communicationEventId")); + infoMap.put("fromPartyName", fromPartyName); + infoMap.put("toPartyName", toPartyName); + infoMap.put("subject", communicationEvent.getString("subject")); + infoMap.put("entryDate", communicationEvent.getString("entryDate")); + infoMap.put("content", communicationEvent.getString("content")); + communications.add(infoMap); + } + return communications; + } + public static String getGeoId(Delegator delegator, String geoCode, String geoTypeId) throws GenericEntityException { + if (UtilValidate.isNotEmpty(geoCode)) { + GenericValue geo = EntityQuery.use(delegator).from("Geo").where("abbreviation", geoCode, "geoTypeId", geoTypeId).queryOne(); + if (geo != null) { + return geo.getString("geoId"); + } + } + return null; + } + public static boolean isValidGeoAssoc(Delegator delegator, String countryGeoId, String stateGeoId) throws GenericEntityException { + if (UtilValidate.isNotEmpty(countryGeoId) && UtilValidate.isNotEmpty(stateGeoId)) { + GenericValue regionGeo = EntityQuery.use(delegator).from("GeoAssocAndGeoToWithState"). + where("geoIdFrom", countryGeoId, "geoAssocTypeId", "REGIONS", "geoId", stateGeoId).queryFirst(); + if (regionGeo != null) { + return true; + } + } + return false; + } +} + diff --git a/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/customer/CustomerServices.java b/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/customer/CustomerServices.java new file mode 100644 index 000000000..bebd07ace --- /dev/null +++ b/headless-commerce/src/main/java/org.apache.ofbiz.hc/api/customer/CustomerServices.java @@ -0,0 +1,1002 @@ +package org.apache.ofbiz.hc.api.customer; + +import org.apache.ofbiz.accounting.payment.PaymentWorker; +import org.apache.ofbiz.base.util.Debug; +import org.apache.ofbiz.base.util.GeneralException; +import org.apache.ofbiz.base.util.UtilGenerics; +import org.apache.ofbiz.base.util.UtilMisc; +import org.apache.ofbiz.base.util.UtilProperties; +import org.apache.ofbiz.base.util.UtilValidate; +import org.apache.ofbiz.base.util.string.FlexibleStringExpander; +import org.apache.ofbiz.common.login.LoginServices; +import org.apache.ofbiz.entity.Delegator; +import org.apache.ofbiz.entity.GenericEntityException; +import org.apache.ofbiz.entity.GenericValue; +import org.apache.ofbiz.entity.util.EntityQuery; +import org.apache.ofbiz.entity.util.EntityUtilProperties; +import org.apache.ofbiz.hc.api.common.CommonUtil; +import org.apache.ofbiz.party.contact.ContactHelper; +import org.apache.ofbiz.security.SecurityUtil; +import org.apache.ofbiz.service.DispatchContext; +import org.apache.ofbiz.service.GenericServiceException; +import org.apache.ofbiz.service.LocalDispatcher; +import org.apache.ofbiz.service.ModelService; +import org.apache.ofbiz.service.ServiceUtil; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Collectors; + +public class CustomerServices { + public static final String MODULE = CustomerServices.class.getName(); + public static final String RESOURCE = "PartyUiLabels"; + public static final String SECRESOURCE = "SecurityextUiLabels"; + + public static Map getPasswordHint(DispatchContext ctx, Map context) { + Delegator delegator = ctx.getDelegator(); + Locale locale = (Locale) context.get("locale"); + String userLoginId = (String) context.get("username"); + Map result = ServiceUtil.returnSuccess(); + String passwordHint = null; + + try { + String usernameLowercase = EntityUtilProperties.getPropertyValue("security", "username.lowercase", delegator); + if (UtilValidate.isNotEmpty(userLoginId) && "true".equals(usernameLowercase)) { + userLoginId = userLoginId.toLowerCase(locale); + } + + GenericValue supposedUserLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne(); + if (supposedUserLogin != null) { + passwordHint = supposedUserLogin.getString("passwordHint"); + result.put("username", userLoginId); + result.put("passwordHint", passwordHint); + } + if (supposedUserLogin == null || UtilValidate.isEmpty(passwordHint)) { + // the Username was not found or there was no hint for the Username + String errMsg = UtilProperties.getMessage(SECRESOURCE, "loginevents.no_password_hint_specified_try_password_emailed", locale); + Debug.logError(errMsg, MODULE); + return ServiceUtil.returnError(errMsg); + } + } catch (GenericEntityException gee) { + Debug.logWarning(gee, "", MODULE); + return ServiceUtil.returnError(gee.getMessage()); + } + return result; + } + public static Map sendResetPasswordEmail(DispatchContext ctx, Map context) { + Delegator delegator = ctx.getDelegator(); + LocalDispatcher dispatcher = ctx.getDispatcher(); + Locale locale = (Locale) context.get("locale"); + String userLoginId = (String) context.get("username"); + String productStoreId = null; + String webSiteId = (String) context.get("webSiteId"); + String defaultScreenLocation = "component://securityext/widget/EmailSecurityScreens.xml#PasswordEmail"; + + try { + GenericValue productStore = CommonUtil.getProductStore(delegator, webSiteId); + if (UtilValidate.isNotEmpty(productStore)) { + productStoreId = productStore.getString("productStoreId"); + } + // test if user exist and is active + GenericValue userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", userLoginId).queryOne(); + if (userLogin == null || "N".equals(userLogin.getString("enabled"))) { + Debug.logError("userlogin unknown or disabled " + userLogin, SECRESOURCE); + //giving a "sent email to associated email-address" response, to suppress feedback on in-/valid usernames + return ServiceUtil.returnError(UtilProperties.getMessage(SECRESOURCE, + "loginevents.new_password_sent_check_email", locale)); + } + + // check login is associated to a party + GenericValue userParty = userLogin.getRelatedOne("Party", false); + if (userParty == null) { + return ServiceUtil.returnError(UtilProperties.getMessage(SECRESOURCE, + "loginevents.username_not_found_reenter", locale)); + } + + // check there is an email to send to + List contactMechs = UtilGenerics.cast(ContactHelper.getContactMechByPurpose(userParty, "PRIMARY_EMAIL", false)); + if (UtilValidate.isEmpty(contactMechs)) { + // the email was not found + return ServiceUtil.returnError(UtilProperties.getMessage(SECRESOURCE, + "loginevents.no_primary_email_address_set_contact_customer_service", locale)); + } + String emails = contactMechs.stream() + .map(email -> email.getString("infoString")) + .collect(Collectors.joining(",")); + + //Generate a JWT with default retention time + String jwtToken = SecurityUtil.generateJwtToAuthenticateUserLogin(delegator, userLoginId); + + // get the ProductStore email settings + GenericValue productStoreEmail = null; + try { + productStoreEmail = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", + productStoreId, "emailType", "PRDS_PWD_RETRIEVE").queryOne(); + } catch (GenericEntityException e) { + Debug.logError(e, "Problem getting ProductStoreEmailSetting", MODULE); + } + + String bodyScreenLocation = null; + if (productStoreEmail != null) { + bodyScreenLocation = productStoreEmail.getString("bodyScreenLocation"); + } + if (UtilValidate.isEmpty(bodyScreenLocation)) { + bodyScreenLocation = defaultScreenLocation; + } + + // set the needed variables in new context + Map bodyParameters = new HashMap<>(); + bodyParameters.put("token", jwtToken); + bodyParameters.put("locale", locale); + bodyParameters.put("userLogin", userLogin); + bodyParameters.put("productStoreId", productStoreId); + + Map serviceContext = new HashMap<>(); + serviceContext.put("bodyScreenUri", bodyScreenLocation); + serviceContext.put("bodyParameters", bodyParameters); + serviceContext.put("webSiteId", webSiteId); + if (productStoreEmail != null) { + serviceContext.put("subject", productStoreEmail.getString("subject")); + serviceContext.put("sendFrom", productStoreEmail.get("fromAddress")); + serviceContext.put("sendCc", productStoreEmail.get("ccAddress")); + serviceContext.put("sendBcc", productStoreEmail.get("bccAddress")); + serviceContext.put("contentType", productStoreEmail.get("contentType")); + } else { + GenericValue emailTemplateSetting = EntityQuery.use(delegator).from("EmailTemplateSetting").where("emailTemplateSettingId", + "EMAIL_PASSWORD").cache().queryOne(); + if (emailTemplateSetting != null) { + String subject = emailTemplateSetting.getString("subject"); + subject = FlexibleStringExpander.expandString(subject, UtilMisc.toMap("userLoginId", userLoginId)); + serviceContext.put("subject", subject); + serviceContext.put("sendFrom", emailTemplateSetting.get("fromAddress")); + } else { + serviceContext.put("subject", UtilProperties.getMessage(SECRESOURCE, "loginservices.password_reminder_subject", + UtilMisc.toMap("userLoginId", userLoginId), locale)); + serviceContext.put("sendFrom", EntityUtilProperties.getPropertyValue("general", + "defaultFromEmailAddress", delegator)); + } + } + serviceContext.put("sendTo", emails); + serviceContext.put("partyId", userParty.getString("partyId")); + + Map result = dispatcher.runSync("sendMailHiddenInLogFromScreen", serviceContext); + if (!ServiceUtil.isSuccess(result)) { + String errorMessage = ServiceUtil.getErrorMessage(result); + Map messageMap = UtilMisc.toMap("errorMessage", errorMessage); + Debug.logError(errorMessage, MODULE); + return ServiceUtil.returnError(UtilProperties.getMessage(SECRESOURCE, + "loginevents.error_unable_email_password_contact_customer_service_errorwas", + messageMap, locale)); + } + } catch (GeneralException e) { + Debug.logWarning(e, "", MODULE); + return ServiceUtil.returnError(UtilProperties.getMessage(SECRESOURCE, + "loginevents.error_unable_email_password_contact_customer_service", locale)); + } + return ServiceUtil.returnSuccess(UtilProperties.getMessage(SECRESOURCE, + "loginevents.new_password_sent_check_email", locale)); + } + public static Map changePassword(DispatchContext dctx, Map context) { + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + + try { + Map serviceContext = dctx.getModelService("updatePassword").makeValid(context, ModelService.IN_PARAM); + serviceContext.put("userLoginId", userLogin.getString("userLoginId")); + serviceContext.put("userLogin", userLogin); + Map result = dispatcher.runSync("updatePassword", serviceContext); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } catch (GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + + public static Map createCustomer(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + Map result; + Map serviceCtx; + String webSiteId = (String) context.get("webSiteId"); + String firstName = (String) context.get("firstName"); + String middleName = (String) context.get("middleName"); + String lastName = (String) context.get("lastName"); + String emailAddress = (String) context.get("emailAddress"); + String username = (String) context.get("username"); + String password = (String) context.get("password"); + String confirmPassword = (String) context.get("confirmPassword"); + String passwordHint = (String) context.get("passwordHint"); + Map shippingAddress = UtilGenerics.cast(context.get("shippingAddress")); + Map mobilePhone = UtilGenerics.cast(context.get("mobilePhone")); + List errorList; + GenericValue productStore = null; + + try { + result = dispatcher.runSync("validateCreateCustomer", context); + if (!ServiceUtil.isSuccess(result)) { + errorList = UtilGenerics.cast(result.get("errorMessageList")); + Debug.logError("parameter validation exception", errorList.toString()); + return ServiceUtil.returnError(errorList); + } + GenericValue system = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", "system").queryOne(); + + //fetching product store + if (UtilValidate.isNotEmpty(webSiteId)) { + productStore = CommonUtil.getProductStore(delegator, webSiteId); + } + + //checking lowercase settings + boolean usernameLowercase = Boolean.parseBoolean(EntityUtilProperties.getPropertyValue("security", "username.lowercase", "false", delegator)); + boolean passwordLowercase = Boolean.parseBoolean(EntityUtilProperties.getPropertyValue("security", "password.lowercase", "false", delegator)); + username = usernameLowercase ? username.toLowerCase(): username; + password = passwordLowercase ? password.toLowerCase(): password; + confirmPassword = passwordLowercase ? confirmPassword.toLowerCase(): confirmPassword; + + //create userlogin + serviceCtx = dctx.getModelService("createPersonAndUserLogin").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("userLoginId", username); + serviceCtx.put("currentPassword", password); + serviceCtx.put("currentPasswordVerify", confirmPassword); + serviceCtx.put("passwordHint", passwordHint); + result = dispatcher.runSync("createPersonAndUserLogin", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + GenericValue createdUserLogin = (GenericValue) result.get("newUserLogin"); + String userPartyId = (String) result.get("partyId"); + + //Assigning customer role + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("roleTypeId", "CUSTOMER"); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyRole", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + + //shipping address + if (UtilValidate.isNotEmpty(shippingAddress)) { + String countryGeoId; + String stateProvinceGeoId = null; + GenericValue countryGeo = EntityQuery.use(delegator).from("Geo").where("geoTypeId", "COUNTRY", "abbreviation", shippingAddress.get("country")).queryFirst(); + countryGeoId = UtilValidate.isNotEmpty(countryGeo) ? countryGeo.getString("geoId") : null; + + if (UtilValidate.isNotEmpty(shippingAddress.get("state"))) { + GenericValue regionGeo = EntityQuery.use(delegator).from("GeoAssocAndGeoToWithState"). + where("geoIdFrom", countryGeoId, "geoAssocTypeId", "REGIONS", "geoCode", shippingAddress.get("state")).queryFirst(); + stateProvinceGeoId = UtilValidate.isEmpty(regionGeo) ? regionGeo.getString("geoId") : null; + } + + serviceCtx.clear(); + serviceCtx = dctx.getModelService("createPartyPostalAddress").makeValid(shippingAddress, ModelService.IN_PARAM); + serviceCtx.put("toName", firstName + " " + middleName + " " + lastName); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("stateProvinceGeoId", stateProvinceGeoId); + serviceCtx.put("countryGeoId", countryGeoId); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyPostalAddress", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + String contactMechId = (String) result.get("contactMechId"); + + //create the shipping location + serviceCtx.clear(); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("contactMechId", contactMechId); + serviceCtx.put("contactMechPurposeTypeId", "SHIPPING_LOCATION"); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + + //also consider this address the general correspondence address + serviceCtx.clear(); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("contactMechId", contactMechId); + serviceCtx.put("contactMechPurposeTypeId", "GENERAL_LOCATION"); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + + + //mobile phone + if (UtilValidate.isNotEmpty(mobilePhone)) { + serviceCtx.clear(); + serviceCtx = dctx.getModelService("createPartyTelecomNumber").makeValid(mobilePhone, ModelService.IN_PARAM); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyTelecomNumber", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + String contactMechId = (String) result.get("contactMechId"); + serviceCtx.clear(); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("contactMechId", contactMechId); + serviceCtx.put("contactMechPurposeTypeId", "PHONE_MOBILE"); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + + //email address + if (UtilValidate.isNotEmpty(emailAddress)) { + serviceCtx.clear(); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("emailAddress", emailAddress); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyEmailAddress", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + String contactMechId = (String) result.get("contactMechId"); + serviceCtx.clear(); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("contactMechId", contactMechId); + serviceCtx.put("contactMechPurposeTypeId", "PRIMARY_EMAIL"); + serviceCtx.put("userLogin", createdUserLogin); + result = dispatcher.runSync("createPartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + + GenericValue person = EntityQuery.use(delegator).from("Person").where("partyId", userPartyId).queryOne(); + if (productStore != null) { + //Associate to Product Store + String productStoreId = productStore.getString("productStoreId"); + serviceCtx.clear(); + serviceCtx.put("partyId", userPartyId); + serviceCtx.put("roleTypeId", "CUSTOMER"); + serviceCtx.put("productStoreId", productStoreId); + serviceCtx.put("userLogin", system); + result = dispatcher.runSync("createProductStoreRole", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + + //send off the registration email + if (UtilValidate.isNotEmpty(emailAddress)) { + GenericValue productStoreEmailSetting = EntityQuery.use(delegator).from("ProductStoreEmailSetting").where("productStoreId", productStoreId, "emailType", "PRDS_CUST_REGISTER").queryFirst(); + if (productStoreEmailSetting != null) { + serviceCtx.clear(); + Map bodyParameters = new HashMap<>(); + bodyParameters.put("person", person); + serviceCtx.put("bodyParameters", bodyParameters); + serviceCtx.put("sendTo", emailAddress); + serviceCtx.put("subject", productStoreEmailSetting.getString("subject")); + serviceCtx.put("sendFrom", productStoreEmailSetting.getString("fromAddress")); + serviceCtx.put("sendCc", productStoreEmailSetting.getString("ccAddress")); + serviceCtx.put("sendBcc", productStoreEmailSetting.getString("bccAddress")); + serviceCtx.put("contentType", productStoreEmailSetting.getString("contentType")); + serviceCtx.put("bodyScreenUri", productStoreEmailSetting.getString("bodyScreenLocation")); + serviceCtx.put("emailType", "PRDS_CUST_REGISTER"); + dispatcher.runAsync("sendMailFromScreen", serviceCtx); + } + } + } + + //assign security group to manage profile + if (createdUserLogin != null) { + serviceCtx.clear(); + serviceCtx.put("userLoginId", createdUserLogin.getString("userLoginId")); + serviceCtx.put("groupId", "ECOMMERCE_CUSTOMER"); + serviceCtx.put("userLogin", system); + result = dispatcher.runSync("addUserLoginToSecurityGroup", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + + } catch (GenericServiceException | GenericEntityException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + + public static Map validateCreateCustomer(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + Locale locale = (Locale) context.get("locale"); + String emailAddress = (String) context.get("emailAddress"); + String username = (String) context.get("username"); + String password = (String) context.get("password"); + String passwordHint = (String) context.get("passwordHint"); + String confirmPassword = (String) context.get("confirmPassword"); + Map shippingAddress = UtilGenerics.cast(context.get("shippingAddress")); + Map mobilePhone = UtilGenerics.cast(context.get("mobilePhone")); + List errorList = new ArrayList<>(); + + try { + if (!UtilValidate.isEmail(emailAddress)) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyEmailAddressNotFormattedCorrectly", locale)); + } + if (UtilValidate.isNotEmpty(shippingAddress)) { + if (UtilValidate.isEmpty(shippingAddress.get("address1"))) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyAddressLine1MissingError", locale)); + } + if (UtilValidate.isEmpty(shippingAddress.get("city"))) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyCityMissing", locale)); + } + if (UtilValidate.isEmpty(shippingAddress.get("postalCode"))) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyZipCodeMissing", locale)); + } + if (UtilValidate.isEmpty(shippingAddress.get("country"))) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyCountryMissing", locale)); + } + String country = shippingAddress.get("country"); + String state = shippingAddress.get("state"); + if ("USA".equals(country) && UtilValidate.isEmpty(state)) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyStateInUsMissing", locale)); + } + if ("CAN".equals(country) && UtilValidate.isEmpty(state)) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyStateInCanadaMissing", locale)); + } + GenericValue countryGeo = EntityQuery.use(delegator).from("Geo").where("geoTypeId", "COUNTRY", "abbreviation", country).queryFirst(); + if (UtilValidate.isNotEmpty(country) && countryGeo == null) { + errorList.add(UtilProperties.getMessage("HeadlessCommerceUiLabels", "HCInvalidCountryCode", + UtilMisc.toMap("countryCode", country), locale)); + } + if (countryGeo != null && UtilValidate.isNotEmpty(state)) { + GenericValue regionGeo = EntityQuery.use(delegator).from("GeoAssocAndGeoToWithState"). + where("geoIdFrom", countryGeo.getString("geoId"), "geoAssocTypeId", "REGIONS", "geoCode", state).queryFirst(); + if (UtilValidate.isEmpty(regionGeo)) { + // if given state is not associated with country then return error. + errorList.add(UtilProperties.getMessage("HeadlessCommerceUiLabels", "HCCountrysStateIsNotValid", + UtilMisc.toMap("stateCode", state, "countryCode", country), locale)); + } + } + + } + if (UtilValidate.isNotEmpty(mobilePhone) && UtilValidate.isEmpty(mobilePhone.get("contactNumber"))) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyContactNumberMissing", locale)); + } + if (!password.equals(confirmPassword)) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyPasswordMatchError", locale)); + } + + GenericValue existingUser = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", username).queryOne(); + if (existingUser != null) { + errorList.add(UtilProperties.getMessage("PartyUiLabels", "PartyUserNameInUse", locale)); + } + + //Check the password, etc for validity + GenericValue newUserLogin = delegator.makeValue("UserLogin"); + newUserLogin.set("userLoginId", username); + newUserLogin.set("currentPassword", password); + newUserLogin.set("passwordHint", passwordHint); + LoginServices.checkNewPassword(newUserLogin, null, password, confirmPassword, passwordHint, errorList, true, locale); + + } catch (GenericEntityException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + if (UtilValidate.isNotEmpty(errorList)) { + return ServiceUtil.returnError(errorList); + } + return ServiceUtil.returnSuccess(); + } + public static Map getCustomer(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + Map response = ServiceUtil.returnSuccess(); + + try { + GenericValue person = EntityQuery.use(delegator).from("Person").where("partyId", customerPartyId).queryFirst(); + if (person != null) { + response.put("customerPartyId", customerPartyId); + Map personalInformationMap = new HashMap<>(); + personalInformationMap.put("personalTitle", person.getString("personalTitle")); + personalInformationMap.put("firstName", person.getString("firstName")); + personalInformationMap.put("middleName", person.getString("middleName")); + personalInformationMap.put("lastName", person.getString("lastName")); + personalInformationMap.put("suffix", person.getString("suffix")); + personalInformationMap.put("userName", userLogin.getString("userLoginId")); + response.put("personalInformation", personalInformationMap); + response.put("loyaltyPoints", CustomerHelper.getLoyaltyPoints(dispatcher, customerPartyId, userLogin)); + } + } catch (GenericEntityException | GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return response; + } + public static Map getPartyPaymentMethods(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + String customerPartyId = (String) context.get("customerPartyId"); + String showOldStr = (String) context.get("showOld"); + Map result = ServiceUtil.returnSuccess(); + List> paymentMethods = new ArrayList<>(); + + try { + boolean showOld = "true".equals(showOldStr); + List> paymentMethodValueMaps = PaymentWorker.getPartyPaymentMethodValueMaps(delegator, customerPartyId, showOld); + for (Map paymentMethodValueMap : paymentMethodValueMaps) { + Map infoMap = new HashMap<>(); + GenericValue paymentMethod = UtilGenerics.cast(paymentMethodValueMap.get("paymentMethod")); + infoMap.put("paymentMethodId", paymentMethod.getString("paymentMethodId")); + infoMap.put("description", paymentMethod.getString("description")); + infoMap.put("fromDate", paymentMethod.getString("fromDate")); + infoMap.put("thruDate", paymentMethod.getString("thruDate")); + + //payment method type + Map paymentMethodTypeMap = new HashMap<>(); + GenericValue paymentMethodType = EntityQuery.use(delegator).from("PaymentMethodType").where("paymentMethodTypeId", paymentMethod.getString("paymentMethodTypeId")).queryOne(); + paymentMethodTypeMap.put("paymentMethodTypeId", paymentMethodType.getString("paymentMethodTypeId")); + paymentMethodTypeMap.put("description", paymentMethodType.getString("description")); + infoMap.put("paymentMethodType", paymentMethodTypeMap); + + if (UtilValidate.isNotEmpty(paymentMethodValueMap.get("creditCard"))) { + GenericValue creditCard = UtilGenerics.cast(paymentMethodValueMap.get("creditCard")); + infoMap.put("companyNameOnCard", creditCard.getString("companyNameOnCard")); + infoMap.put("titleOnCard", creditCard.getString("titleOnCard")); + infoMap.put("firstNameOnCard", creditCard.getString("firstNameOnCard")); + infoMap.put("middleNameOnCard", creditCard.getString("middleNameOnCard")); + infoMap.put("lastNameOnCard", creditCard.getString("lastNameOnCard")); + infoMap.put("suffixOnCard", creditCard.getString("suffixOnCard")); + infoMap.put("cardNumber", creditCard.getString("cardNumber")); + infoMap.put("expireDate", creditCard.getString("expireDate")); + } else if (UtilValidate.isNotEmpty(paymentMethodValueMap.get("giftCard"))) { + GenericValue giftCard = UtilGenerics.cast(paymentMethodValueMap.get("giftCard")); + infoMap.put("cardNumber", giftCard.getString("cardNumber")); + infoMap.put("expireDate", giftCard.getString("expireDate")); + + } else if (UtilValidate.isNotEmpty(paymentMethodValueMap.get("eftAccount"))) { + GenericValue eftAccount = UtilGenerics.cast(paymentMethodValueMap.get("eftAccount")); + infoMap.put("bankName", eftAccount.getString("bankName")); + infoMap.put("routingNumber", eftAccount.getString("routingNumber")); + infoMap.put("accountType", eftAccount.getString("accountType")); + infoMap.put("accountNumber", eftAccount.getString("accountNumber")); + infoMap.put("nameOnAccount", eftAccount.getString("nameOnAccount")); + infoMap.put("companyNameOnAccount", eftAccount.getString("companyNameOnAccount")); + } + paymentMethods.add(infoMap); + } + } catch (GenericEntityException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + result.put("paymentMethods", paymentMethods); + return result; + } + public static Map getCustomerPostalAddress(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + String customerPartyId = (String) context.get("customerPartyId"); + List> addresses = new ArrayList<>(); + + try { + List partyContactDetails = EntityQuery.use(delegator).from("PartyContactDetailByPurpose") + .where("partyId", customerPartyId, "contactMechTypeId", "POSTAL_ADDRESS", "contactMechPurposeTypeId", "SHIPPING_LOCATION") + .filterByDate() + .queryList(); + for (GenericValue partyContactDetail : partyContactDetails) { + Map addressMap = new HashMap<>(); + addressMap.put("address1", partyContactDetail.getString("address1")); + addressMap.put("address2", partyContactDetail.getString("address2")); + addressMap.put("city", partyContactDetail.getString("city")); + addressMap.put("postalCode", partyContactDetail.getString("postalCode")); + Map stateInfoMap = new HashMap<>(); + Map countryInfoMap = new HashMap<>(); + GenericValue state = EntityQuery.use(delegator).from("Geo").where("geoId", partyContactDetail.getString("stateProvinceGeoId")).queryOne(); + if (state != null) { + stateInfoMap.put("stateProvinceGeoId", state.getString("geoId")); + stateInfoMap.put("stateName", state.getString("geoName")); + stateInfoMap.put("stateCode", state.getString("abbreviation")); + addressMap.put("state", stateInfoMap); + } + GenericValue country = EntityQuery.use(delegator).from("Geo").where("geoId", partyContactDetail.getString("countryGeoId")).queryOne(); + if (country != null) { + countryInfoMap.put("countryGeoId", country.getString("geoId")); + countryInfoMap.put("countryName", country.getString("geoName")); + countryInfoMap.put("countryCode", country.getString("abbreviation")); + addressMap.put("country", countryInfoMap); + } + addresses.add(addressMap); + } + + } catch (GenericEntityException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + Map result = ServiceUtil.returnSuccess(); + result.put("addresses", addresses); + return result; + } + public static Map createUpdateCustomerPostalAddress(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + Locale locale = (Locale) context.get("locale"); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + String stateCode = (String) context.get("stateCode"); + String countryCode = (String) context.get("countryCode"); + String contactMechPurposeTypeId = "SHIPPING_LOCATION"; + String contactMechId = (String) context.get("contactMechId"); + String address1 = (String) context.get("address1"); + Map serviceCtx = new HashMap<>(); + Map result = new HashMap<>(); + + try { + String countryGeoId = CustomerHelper.getGeoId(delegator, countryCode, "COUNTRY"); + String stateProvinceGeoId = null; + if (UtilValidate.isNotEmpty(stateCode)) { + stateProvinceGeoId = CustomerHelper.getGeoId(delegator, stateCode, "STATE"); + if (!CustomerHelper.isValidGeoAssoc(delegator, countryGeoId, stateProvinceGeoId)) { + String errorMessage = UtilProperties.getMessage("HeadlessCommerceUiLabels", "HCCountrysStateIsNotValid", + UtilMisc.toMap("stateCode", stateCode, "countryCode", countryCode), locale); + Debug.logError(errorMessage, MODULE); + return ServiceUtil.returnError(errorMessage); + } + } + if (UtilValidate.isNotEmpty(contactMechId)) { + //update postal address and purpose + if (UtilValidate.isNotEmpty(address1)) { + serviceCtx = dctx.getModelService("updatePartyPostalAddress").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("stateProvinceGeoId", stateProvinceGeoId); + serviceCtx.put("countryGeoId", countryGeoId); + serviceCtx.put("userLogin", userLogin); + result = dispatcher.runSync("updatePartyPostalAddress", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + if (UtilValidate.isNotEmpty(contactMechPurposeTypeId)) { + GenericValue partyContactMechPurpose = EntityQuery.use(delegator).from("PartyContactMechPurpose").where("partyId", customerPartyId, + "contactMechId", contactMechId, "contactMechPurposeTypeId", contactMechPurposeTypeId).filterByDate().queryFirst(); + if (partyContactMechPurpose == null) { + serviceCtx.clear(); + result.clear(); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("contactMechId", contactMechId); + serviceCtx.put("contactMechPurposeTypeId", contactMechPurposeTypeId); + serviceCtx.put("userLogin", userLogin); + result = dispatcher.runSync("createPartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } + } else { + //create postal address with purpose + serviceCtx = dctx.getModelService("createPartyPostalAddress").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("stateProvinceGeoId", stateProvinceGeoId); + serviceCtx.put("countryGeoId", countryGeoId); + serviceCtx.put("contactMechPurposeTypeId", contactMechPurposeTypeId); + serviceCtx.put("userLogin", userLogin); + result = dispatcher.runSync("createPartyPostalAddress", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } catch (GenericEntityException | GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map removeCustomerContactMechAndPurpose(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + String contactMechPurposeTypeId = (String) context.get("contactMechPurposeTypeId"); + String contactMechId = (String) context.get("contactMechId"); + + try { + if (UtilValidate.isNotEmpty(contactMechPurposeTypeId)) { + //expiring party contact mech purpose only + GenericValue partyContactMech = EntityQuery.use(delegator).from("PartyContactMechPurpose").where("partyId", customerPartyId, "contactMechId", contactMechId, + "contactMechPurposeTypeId", contactMechPurposeTypeId).filterByDate().queryFirst(); + if (partyContactMech != null) { + Map serviceCtx = dctx.getModelService("expirePartyContactMechPurpose").makeValid(partyContactMech, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("userLogin", userLogin); + Map result = dispatcher.runSync("expirePartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } else { + //expiring party contact mech only + Map serviceCtx = dctx.getModelService("deletePartyContactMech").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + Map result = dispatcher.runSync("deletePartyContactMech", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } catch (GenericEntityException | GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map createUpdateCustomerTelecomNumber(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + String contactMechPurposeTypeId = (String) context.get("contactMechPurposeTypeId"); + String contactMechId = (String) context.get("contactMechId"); + String contactNumber = (String) context.get("contactNumber"); + Map serviceCtx = new HashMap<>(); + Map result = new HashMap<>(); + + + try { + if (UtilValidate.isNotEmpty(contactMechId)) { + //upate telecom number and purpose + if (UtilValidate.isNotEmpty(contactNumber)) { + serviceCtx = dctx.getModelService("updatePartyTelecomNumber").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + result = dispatcher.runSync("updatePartyTelecomNumber", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + if (UtilValidate.isNotEmpty(contactMechPurposeTypeId)) { + GenericValue partyContactMechPurpose = EntityQuery.use(delegator).from("PartyContactMechPurpose").where("partyId", customerPartyId, + "contactMechId", contactMechId, "contactMechPurposeTypeId", contactMechPurposeTypeId).filterByDate().queryFirst(); + if (partyContactMechPurpose == null) { + serviceCtx.clear(); + result.clear(); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("contactMechId", contactMechId); + serviceCtx.put("contactMechPurposeTypeId", contactMechPurposeTypeId); + serviceCtx.put("userLogin", userLogin); + result = dispatcher.runSync("createPartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } + } else { + //create telecom number with purpose + serviceCtx = dctx.getModelService("createPartyTelecomNumber").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + result = dispatcher.runSync("createPartyTelecomNumber", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } catch (GenericEntityException | GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map createUpdateCustomerEmailAddress(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + String contactMechPurposeTypeId = (String) context.get("contactMechPurposeTypeId"); + String contactMechId = (String) context.get("contactMechId"); + String emailAddress = (String) context.get("emailAddress"); + Map serviceCtx = new HashMap<>(); + Map result = new HashMap<>(); + + + try { + if (UtilValidate.isNotEmpty(contactMechId)) { + //update email address + if (UtilValidate.isNotEmpty(emailAddress)) { + serviceCtx = dctx.getModelService("updatePartyEmailAddress").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + result = dispatcher.runSync("updatePartyEmailAddress", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + if (UtilValidate.isNotEmpty(contactMechPurposeTypeId)) { + GenericValue partyContactMechPurpose = EntityQuery.use(delegator).from("PartyContactMechPurpose").where("partyId", customerPartyId, + "contactMechId", contactMechId, "contactMechPurposeTypeId", contactMechPurposeTypeId).filterByDate().queryFirst(); + if (partyContactMechPurpose == null) { + serviceCtx.clear(); + result.clear(); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("contactMechId", contactMechId); + serviceCtx.put("contactMechPurposeTypeId", contactMechPurposeTypeId); + serviceCtx.put("userLogin", userLogin); + result = dispatcher.runSync("createPartyContactMechPurpose", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } + } else { + //create email address + serviceCtx = dctx.getModelService("createPartyEmailAddress").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + result = dispatcher.runSync("createPartyEmailAddress", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } catch (GenericEntityException | GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map createUpdateCustomerContactMech(DispatchContext dctx, Map context) { + LocalDispatcher dispatcher = dctx.getDispatcher(); + String customerPartyId = (String) context.get("customerPartyId"); + String contactMechId = (String) context.get("contactMechId"); + String infoString = (String) context.get("infoString"); + + try { + if (UtilValidate.isNotEmpty(contactMechId)) { + //update contact mech + if (UtilValidate.isNotEmpty(infoString)) { + Map serviceCtx = dctx.getModelService("updatePartyContactMech").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + Map result = dispatcher.runSync("updatePartyContactMech", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } else { + //create email address + Map serviceCtx = dctx.getModelService("createPartyContactMech").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + Map result = dispatcher.runSync("createPartyContactMech", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } catch (GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map createUpdateCustomerPaymentMethod(DispatchContext dctx, Map context) { + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + Map creditCard = UtilGenerics.cast(context.get("creditCard")); + Map giftCard = UtilGenerics.cast(context.get("giftCard")); + Map eftAccount = UtilGenerics.cast(context.get("eftAccount")); + Map address = UtilGenerics.cast(context.get("address")); + + try { + if (UtilValidate.isNotEmpty(creditCard)) { + String paymentMethodId = (String) creditCard.get("paymentMethodId"); + String serviceName = UtilValidate.isNotEmpty(paymentMethodId) ? "updateCreditCard" : "createCreditCard"; + Map serviceCtx = dctx.getModelService(serviceName).makeValid(creditCard, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("userLogin", userLogin); + Map result = dispatcher.runSync(serviceName, serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + paymentMethodId = (String) result.get("paymentMethodId"); + if (UtilValidate.isNotEmpty(address) && UtilValidate.isEmpty(address.get("contactMechId"))) { + serviceCtx.clear(); + result.clear(); + serviceCtx = dctx.getModelService("createPartyPostalAddress").makeValid(address, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("paymentMethodId", paymentMethodId); + serviceCtx.put("contactMechPurposeTypeId", "BILLING_LOCATION"); + serviceCtx.put("userLogin", userLogin); + result = dispatcher.runSync("createPartyPostalAddress", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } else if (UtilValidate.isNotEmpty(giftCard)) { + String paymentMethodId = (String) giftCard.get("paymentMethodId"); + String serviceName = UtilValidate.isNotEmpty(paymentMethodId) ? "updateGiftCard" : "createGiftCard"; + Map serviceCtx = dctx.getModelService(serviceName).makeValid(giftCard, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("userLogin", userLogin); + Map result = dispatcher.runSync(serviceName, serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } else if (UtilValidate.isNotEmpty(eftAccount)) { + String paymentMethodId = (String) eftAccount.get("paymentMethodId"); + String serviceName = UtilValidate.isNotEmpty(paymentMethodId) ? "updateEftAccount" : "createEftAccount"; + Map serviceCtx = dctx.getModelService(serviceName).makeValid(eftAccount, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("userLogin", userLogin); + Map result = dispatcher.runSync(serviceName, serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } + } catch (GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map deleteCustomerPaymentMethod(DispatchContext dctx, Map context) { + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + + try { + Map serviceCtx = dctx.getModelService("deletePaymentMethod").makeValid(context, ModelService.IN_PARAM); + serviceCtx.put("partyId", customerPartyId); + serviceCtx.put("userLogin", userLogin); + Map result = dispatcher.runSync("deletePaymentMethod", serviceCtx); + if (!ServiceUtil.isSuccess(result)) { + Debug.logError(ServiceUtil.getErrorMessage(result), MODULE); + return ServiceUtil.returnError(ServiceUtil.getErrorMessage(result)); + } + } catch (GenericServiceException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + return ServiceUtil.returnSuccess(); + } + public static Map validateCustomer(DispatchContext dctx, Map context) { + Delegator delegator = dctx.getDelegator(); + Locale locale = (Locale) context.get("locale"); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + String customerPartyId = (String) context.get("customerPartyId"); + Map result = ServiceUtil.returnSuccess(); + try { + if (!CommonUtil.isValidCutomer(delegator, userLogin, customerPartyId)) { + String errorMessage = UtilProperties.getMessage("HeadlessCommerceUiLabels", "HCAccessDeniedInvalidUser", locale); + result = ServiceUtil.returnError(errorMessage); + result.put("hasPermission", false); + Debug.logError(errorMessage, MODULE); + return result; + } + } catch (GenericEntityException e) { + Debug.logError(e, MODULE); + return ServiceUtil.returnError(e.getMessage()); + } + + result.put("hasPermission", true); + return result; + } +} diff --git a/headless-commerce/testdef/HeadlessCommerceTests.xml b/headless-commerce/testdef/HeadlessCommerceTests.xml new file mode 100644 index 000000000..de385c4b4 --- /dev/null +++ b/headless-commerce/testdef/HeadlessCommerceTests.xml @@ -0,0 +1,26 @@ + + + + + + + \ No newline at end of file diff --git a/headless-commerce/webapp/headless-commerce/WEB-INF/controller.xml b/headless-commerce/webapp/headless-commerce/WEB-INF/controller.xml new file mode 100644 index 000000000..385c4067c --- /dev/null +++ b/headless-commerce/webapp/headless-commerce/WEB-INF/controller.xml @@ -0,0 +1,47 @@ + + + + + + + + HeadlessCommerce Component Site Configuration File + + + + + + + + + + + + \ No newline at end of file diff --git a/headless-commerce/webapp/headless-commerce/WEB-INF/web.xml b/headless-commerce/webapp/headless-commerce/WEB-INF/web.xml new file mode 100644 index 000000000..d2796fca9 --- /dev/null +++ b/headless-commerce/webapp/headless-commerce/WEB-INF/web.xml @@ -0,0 +1,96 @@ + + + + + Apache OFBiz - HeadlessCommerce Component + HeadlessCommerce Component of the Apache OFBiz Project + + + + A unique name used to identify/recognize the local dispatcher for the Service Engine + localDispatcherNameheadless-commerce + + + The Name of the Entity Delegator to use, defined in entityengine.xml + entityDelegatorNamedefault + + + The location of the main-decorator screen to use for this webapp; referred to as a context variable in screen def XML files. + mainDecoratorLocation + component://headless-commerce/widget/CommonScreens.xml + + + Remove unnecessary whitespace from HTML output. + compressHTML + false + + + + ControlFilter + ControlFilter + org.apache.ofbiz.webapp.control.ControlFilter + + allowedPaths + /error:/control:/select:/index.html:/index.jsp:/default.html:/default.jsp:/images + + redirectPath/control/main + + + ContextFilter + ContextFilter + org.apache.ofbiz.webapp.control.ContextFilter + + + SameSiteFilter + SameSiteFilter + org.apache.ofbiz.webapp.control.SameSiteFilter + + ControlFilter/* + ContextFilter/* + SameSiteFilter/* + + org.apache.ofbiz.webapp.control.ControlEventListener + org.apache.ofbiz.webapp.control.LoginEventListener + + + + + Main Control Servlet + ControlServlet + ControlServlet + org.apache.ofbiz.webapp.control.ControlServlet + 1 + + ControlServlet/control/* + + + 60 + + + + index.jsp + index.html + index.htm + + diff --git a/headless-commerce/webapp/headless-commerce/index.jsp b/headless-commerce/webapp/headless-commerce/index.jsp new file mode 100644 index 000000000..4ea7d0c8b --- /dev/null +++ b/headless-commerce/webapp/headless-commerce/index.jsp @@ -0,0 +1,20 @@ +<%-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--%> + +<%response.sendRedirect("control/main");%> \ No newline at end of file diff --git a/headless-commerce/widget/CommonScreens.xml b/headless-commerce/widget/CommonScreens.xml new file mode 100644 index 000000000..45c4a78ec --- /dev/null +++ b/headless-commerce/widget/CommonScreens.xml @@ -0,0 +1,67 @@ + + + + + + +
+ + + + + + + + + + + + + + + +
+
+ + +
+ + + + + +
+ + + + + + + + + +
+
+
+
+
+
+
\ No newline at end of file diff --git a/headless-commerce/widget/HeadlessCommerceScreens.xml b/headless-commerce/widget/HeadlessCommerceScreens.xml new file mode 100644 index 000000000..ebd3940d5 --- /dev/null +++ b/headless-commerce/widget/HeadlessCommerceScreens.xml @@ -0,0 +1,38 @@ + + + + + + +
+ + + + + + + + + +
+
+ +
\ No newline at end of file