diff --git a/.env.example b/.env.example index 0bdf027..6868e6a 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,8 @@ VUE_APP_I18N_FALLBACK_LOCALE=en VUE_APP_CACHE_MAX_AGE=3600 VUE_APP_VIEW_SIZE=10 VUE_APP_PERMISSION_ID= -VUE_APP_DEFAULT_LOG_LEVEL="error" \ No newline at end of file +VUE_APP_DEFAULT_LOG_LEVEL="error" +VUE_APP_RULE_ENUMS={"FILTER":"ENTCT_FILTER","SORT":"ENTCT_SORT_BY","QUEUE":{"id":"OIP_QUEUE","code":"facilityId"},"SHIPPING_METHOD":{"id":"OIP_SHIP_METH_TYPE","code":"shipmentMethodTypeId"},"PRIORITY":{"id":"OIP_PRIORITY","code":"priority"},"PROMISE_DATE":{"id":"OIP_PROMISE_DATE","code":"promiseDaysCutoff"},"SALES_CHANNEL":{"id":"OIP_SALES_CHANNEL","code":"salesChannelEnumId"},"SHIP_BY":{"id":"OSP_SHIP_BY","code":"shipBeforeDate"},"SHIP_AFTER":{"id":"OSP_SHIP_AFTER","code":"shipAfterDate"},"ORDER_DATE":{"id":"OSP_ORDER_DATE","code":"orderDate"},"SHIPPING_METHOD_SORT":{"id":"OSP_SHIP_METH","code":"deliveryDays"}} +VUE_APP_RULE_FILTER_ENUMS={"FACILITY_GROUP":{"id":"IIP_FACILITY_GROUP","code":"facilityGroupId"},"PROXIMITY":{"id":"IIP_PROXIMITY","code":"distance"},"BRK_SAFETY_STOCK":{"id":"IIP_BRK_SFTY_STOCK","code":"brokeringSafetyStock"},"MEASUREMENT_SYSTEM":{"id":"IIP_MSMNT_SYSTEM","code":"measurementSystem"}} +VUE_APP_RULE_SORT_ENUMS={"PROXIMITY":{"id":"ISP_PROXIMITY","code":"distance"},"INV_BALANCE":{"id":"ISP_INV_BAL","code":"inventoryForAllocation"},"CUSTOMER_SEQ":{"id":"ISP_CUST_SEQ","code":"facilitySequence"}} +VUE_APP_RULE_ACTION_ENUMS={"AUTO_CANCEL_DAYS":{"id":"ORA_AUTO_CANCEL_DATE","code":"ADD_AUTO_CANCEL_DATE"},"NEXT_RULE":{"id":"ORA_NEXT_RULE","code":"NEXT_RULE"},"MOVE_TO_QUEUE":{"id":"ORA_MV_TO_QUEUE","code":"MOVE_TO_QUEUE"}} \ No newline at end of file diff --git a/src/components/AddInventoryFilterOptionsModal.vue b/src/components/AddInventoryFilterOptionsModal.vue new file mode 100644 index 0000000..6ef5206 --- /dev/null +++ b/src/components/AddInventoryFilterOptionsModal.vue @@ -0,0 +1,34 @@ + + + diff --git a/src/components/AddInventorySortOptionsModal.vue b/src/components/AddInventorySortOptionsModal.vue new file mode 100644 index 0000000..873d0ac --- /dev/null +++ b/src/components/AddInventorySortOptionsModal.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/router/index.ts b/src/router/index.ts index 163ee06..9b65a9a 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -43,8 +43,9 @@ const routes: Array = [ props: true }, { - path: "brokering/query", - component: () => import("@/views/BrokeringQuery.vue") + path: "brokering/:routingGroupId/:orderRoutingId/rules", + component: () => import("@/views/BrokeringQuery.vue"), + props: true }, { path: "settings", diff --git a/src/services/RoutingService.ts b/src/services/RoutingService.ts index f7d2acf..84f5953 100644 --- a/src/services/RoutingService.ts +++ b/src/services/RoutingService.ts @@ -1,4 +1,7 @@ import api from "@/api" +import logger from "@/logger"; +import store from "@/store"; +import { hasError, showToast } from "@/utils"; const fetchRoutingGroups = async (payload: any): Promise => { return api({ @@ -24,8 +27,65 @@ const fetchOrderRoutings = async (payload: any): Promise => { }); } +const createRoutingRule = async (payload: any): Promise => { + let routingRuleId = ''; + try { + const resp = await api({ + url: "rules", + method: "POST", + data: payload + }) + + if(!hasError(resp) && resp?.data.routingRuleId) { + routingRuleId = resp.data.routingRuleId + } + } catch(err) { + showToast("Failed to create new rule") + logger.error(err) + } + + return routingRuleId +} + +const fetchRoutingRules = async (payload: any): Promise => { + return api({ + url: `routings/${payload.orderRoutingId}/rules`, + method: "GET", + query: payload + }); +} + +const fetchRoutingFilters = async (payload: any): Promise => { + return api({ + url: `routings/${payload.orderRoutingId}/filter-conditions`, + method: "GET", + query: payload + }); +} + +const fetchRuleConditions = async (payload: any): Promise => { + return api({ + url: `rules/${payload.routingRuleId}/condition`, + method: "GET", + query: payload + }); +} + +const fetchRuleActions = async (payload: any): Promise => { + return api({ + url: `rules/${payload.routingRuleId}/actions`, + method: "GET", + query: payload + }); +} + export const OrderRoutingService = { createRoutingGroup, + createRoutingRule, fetchOrderRoutings, - fetchRoutingGroups + fetchRoutingFilters, + fetchRoutingGroups, + fetchRoutingRules, + fetchRuleActions, + fetchRuleConditions } \ No newline at end of file diff --git a/src/services/UtilService.ts b/src/services/UtilService.ts index 0a59366..299fa5c 100644 --- a/src/services/UtilService.ts +++ b/src/services/UtilService.ts @@ -8,6 +8,15 @@ const fetchEnums = async (payload: any): Promise => { }); } +const fetchFacilities = async (payload: any): Promise => { + return api({ + url: "facilities", + method: "GET", + params: payload + }); +} + export const UtilService = { - fetchEnums + fetchEnums, + fetchFacilities } \ No newline at end of file diff --git a/src/store/modules/orderRouting/OrderRoutingState.ts b/src/store/modules/orderRouting/OrderRoutingState.ts index 38e7251..9c6d1b2 100644 --- a/src/store/modules/orderRouting/OrderRoutingState.ts +++ b/src/store/modules/orderRouting/OrderRoutingState.ts @@ -1,7 +1,16 @@ +import { RouteFilter } from "@/types"; + export default interface OrderRoutingState { groups: Array; // runs routes: Array; - rule: Array; + rules: Array; currentGroupId: string; currentRouteId: string; + currentRouteFilters: { + [key: string]: { // conditionTypeEnumId as key + [key: string]: RouteFilter // enumCode/fieldName as key + } + }; + ruleConditions: {}; + ruleActions: {} } \ No newline at end of file diff --git a/src/store/modules/orderRouting/actions.ts b/src/store/modules/orderRouting/actions.ts index f21c163..d1ccee6 100644 --- a/src/store/modules/orderRouting/actions.ts +++ b/src/store/modules/orderRouting/actions.ts @@ -5,6 +5,7 @@ import { OrderRoutingService } from "@/services/RoutingService" import { hasError, showToast, sortSequence } from "@/utils" import * as types from './mutation-types' import logger from "@/logger" +import { RouteFilter } from "@/types" const actions: ActionTree = { async fetchOrderRoutingGroups({ commit }) { @@ -77,7 +78,136 @@ const actions: ActionTree = { } commit(types.ORDER_ROUTINGS_UPDATED, orderRoutings) - } + }, + + async fetchRoutingRules({ commit }, orderRoutingId) { + let routingRules = [] as any; + // filter groups on the basis of productStoreId + const payload = { + orderRoutingId + } + + try { + const resp = await OrderRoutingService.fetchRoutingRules(payload); + + if(!hasError(resp) && resp.data.length) { + routingRules = resp.data + } else { + throw resp.data + } + } catch(err) { + logger.error(err); + } + + if(routingRules.length) { + routingRules = sortSequence(routingRules) + } + + commit(types.ORDER_ROUTING_RULES_UPDATED, routingRules) + }, + + async fetchRoutingFilters({ commit }, orderRoutingId) { + let routingFilters = [] as any; + // filter groups on the basis of productStoreId + const payload = { + orderRoutingId + } + + try { + const resp = await OrderRoutingService.fetchRoutingFilters(payload); + + if(!hasError(resp) && resp.data.length) { + routingFilters = resp.data.reduce((filters: any, filter: RouteFilter) => { + if(filters[filter.conditionTypeEnumId]) { + filters[filter.conditionTypeEnumId][filter.fieldName] = filter + } else { + filters[filter.conditionTypeEnumId] = { + [filter.fieldName]: filter + } + } + return filters + }, {}) + } else { + throw resp.data + } + } catch(err) { + logger.error(err); + } + + const sortEnum = JSON.parse(process.env?.VUE_APP_RULE_ENUMS as string)["SORT"] as any + + // As we only need to add support of reordering for sortBy filter + if(routingFilters[sortEnum]?.length) { + routingFilters[sortEnum] = sortSequence(routingFilters[sortEnum]) + } + + commit(types.ORDER_ROUTING_FILTERS_UPDATED, routingFilters) + }, + + async fetchRuleConditions({ commit }, routingRuleId) { + let ruleConditions = [] as any; + // filter groups on the basis of productStoreId + const payload = { + routingRuleId + } + + try { + const resp = await OrderRoutingService.fetchRuleConditions(payload); + + if(!hasError(resp) && resp.data.length) { + ruleConditions = resp.data + } else { + throw resp.data + } + } catch(err) { + logger.error(err); + } + + // const sortEnum = JSON.parse(process.env?.VUE_APP_RULE_ENUMS as string)["SORT"] as any + + // // As we only need to add support of reordering for sortBy filter + // if(routingFilters[sortEnum]?.length) { + // routingFilters[sortEnum] = sortSequence(routingFilters[sortEnum]) + // } + + commit(types.ORDER_ROUTING_RULE_CONDITIONS_UPDATED, ruleConditions) + }, + + async fetchRuleActions({ commit }, routingRuleId) { + let ruleActions = {} as any; + const payload = { + routingRuleId + } + + try { + const resp = await OrderRoutingService.fetchRuleActions(payload); + + if(!hasError(resp) && resp.data.length) { + ruleActions = resp.data.reduce((actions: any, action: any) => { + // considering that only one value for an action is available + actions[action.actionTypeEnumId] = action + return actions + }, {}) + } else { + throw resp.data + } + } catch(err) { + logger.error(err); + } + + // const sortEnum = JSON.parse(process.env?.VUE_APP_RULE_ENUMS as string)["SORT"] as any + + // // As we only need to add support of reordering for sortBy filter + // if(routingFilters[sortEnum]?.length) { + // routingFilters[sortEnum] = sortSequence(routingFilters[sortEnum]) + // } + + commit(types.ORDER_ROUTING_RULE_ACTIONS_UPDATED, ruleActions) + }, + + async setCurrentOrderRoutingId({ commit }, payload) { + commit(types.ORDER_ROUTING_CURRENT_ROUTE_UPDATED, payload) + }, } export default actions; \ No newline at end of file diff --git a/src/store/modules/orderRouting/getters.ts b/src/store/modules/orderRouting/getters.ts index 85a27fd..d52948a 100644 --- a/src/store/modules/orderRouting/getters.ts +++ b/src/store/modules/orderRouting/getters.ts @@ -1,7 +1,7 @@ import { GetterTree } from "vuex" import OrderRoutingState from "./OrderRoutingState" import RootState from "@/store/RootState" -import { Group } from "@/types" +import { Group, Route } from "@/types" const getters: GetterTree = { getRoutingGroups(state) { @@ -10,9 +10,25 @@ const getters: GetterTree = { getOrderRoutings(state) { return state.routes }, + getRoutingRules(state) { + return state.rules + }, getCurrentRoutingGroup(state) { const currentRoutingGroup = state.groups?.find((group: Group) => group.routingGroupId === state.currentGroupId) return currentRoutingGroup ? currentRoutingGroup : {} + }, + getCurrentOrderRouting(state) { + const orderRouting = state.routes?.find((route: Route) => route.orderRoutingId === state.currentRouteId) + return orderRouting ? orderRouting : {} + }, + getCurrentRouteFilters(state) { + return state.currentRouteFilters + }, + getRuleConditions(state) { + return JSON.parse(JSON.stringify(state.ruleConditions)) + }, + getRuleActions(state) { + return JSON.parse(JSON.stringify(state.ruleActions)) } } diff --git a/src/store/modules/orderRouting/index.ts b/src/store/modules/orderRouting/index.ts index 275bf06..b554efd 100644 --- a/src/store/modules/orderRouting/index.ts +++ b/src/store/modules/orderRouting/index.ts @@ -10,9 +10,12 @@ const orderRoutingModule: Module = { state: { groups: [], routes: [], - rule: [], + rules: [], currentGroupId: '', // choosing only to save id and not whole object, as when updating the state we don't need to care updating the state on two different places - currentRouteId: '' + currentRouteId: '', + currentRouteFilters: {}, + ruleConditions: {}, + ruleActions: {} }, getters, actions, diff --git a/src/store/modules/orderRouting/mutation-types.ts b/src/store/modules/orderRouting/mutation-types.ts index 4515191..447da3d 100644 --- a/src/store/modules/orderRouting/mutation-types.ts +++ b/src/store/modules/orderRouting/mutation-types.ts @@ -1,6 +1,9 @@ export const SN_ORDER_ROUTING = "orderRouting" export const ORDER_ROUTING_GROUPS_UPDATED = SN_ORDER_ROUTING + "/GROUPS_UPDATED" export const ORDER_ROUTINGS_UPDATED = SN_ORDER_ROUTING + "/ROUTES_UPDATED" -export const ORDER_ROUTING_RULE_UPDATED = SN_ORDER_ROUTING + "/RULE_UPDATED" +export const ORDER_ROUTING_RULES_UPDATED = SN_ORDER_ROUTING + "/RULE_UPDATED" export const ORDER_ROUTING_CURRENT_GROUP_UPDATED = SN_ORDER_ROUTING + "/CURRENT_GROUP_UPDATED" -export const ORDER_ROUTING_CURRENT_ROUTE_UPDATED = SN_ORDER_ROUTING + "/CURRENT_ROUTE_UPDATED" \ No newline at end of file +export const ORDER_ROUTING_CURRENT_ROUTE_UPDATED = SN_ORDER_ROUTING + "/CURRENT_ROUTE_UPDATED" +export const ORDER_ROUTING_FILTERS_UPDATED = SN_ORDER_ROUTING + "/FILTERS_UPDATED" +export const ORDER_ROUTING_RULE_CONDITIONS_UPDATED = SN_ORDER_ROUTING + "/RULE_CONDITIONS_UPDATED" +export const ORDER_ROUTING_RULE_ACTIONS_UPDATED = SN_ORDER_ROUTING + "/RULE_ACTIONS_UPDATED" \ No newline at end of file diff --git a/src/store/modules/orderRouting/mutations.ts b/src/store/modules/orderRouting/mutations.ts index 1667a59..6ce1f3d 100644 --- a/src/store/modules/orderRouting/mutations.ts +++ b/src/store/modules/orderRouting/mutations.ts @@ -9,14 +9,23 @@ const mutations: MutationTree = { [types.ORDER_ROUTINGS_UPDATED](state, payload) { state.routes = payload }, - [types.ORDER_ROUTING_RULE_UPDATED](state, payload) { - state.rule = payload + [types.ORDER_ROUTING_RULES_UPDATED](state, payload) { + state.rules = payload }, [types.ORDER_ROUTING_CURRENT_GROUP_UPDATED](state, groupId) { state.currentGroupId = groupId }, [types.ORDER_ROUTING_CURRENT_ROUTE_UPDATED](state, routeId) { state.currentRouteId = routeId + }, + [types.ORDER_ROUTING_FILTERS_UPDATED](state, payload) { + state.currentRouteFilters = payload + }, + [types.ORDER_ROUTING_RULE_CONDITIONS_UPDATED](state, payload) { + state.ruleConditions = payload + }, + [types.ORDER_ROUTING_RULE_ACTIONS_UPDATED](state, payload) { + state.ruleActions = payload } } export default mutations; \ No newline at end of file diff --git a/src/store/modules/util/UtilState.ts b/src/store/modules/util/UtilState.ts index 60076be..5f7ae5d 100644 --- a/src/store/modules/util/UtilState.ts +++ b/src/store/modules/util/UtilState.ts @@ -5,5 +5,6 @@ export default interface UtilState { [key: string]: { [key: string]: Enumeration } - } + }; + facilities: object; } \ No newline at end of file diff --git a/src/store/modules/util/actions.ts b/src/store/modules/util/actions.ts index 0445f74..298d6cc 100644 --- a/src/store/modules/util/actions.ts +++ b/src/store/modules/util/actions.ts @@ -8,8 +8,10 @@ import { UtilService } from "@/services/UtilService" import { EnumerationAndType } from "@/types" const actions: ActionTree = { - async fetchEnums({ commit }, payload) { - let enums = {} + async fetchEnums({ commit, state }, payload) { + let enums = { + ...state.enums + } try { const resp = await UtilService.fetchEnums(payload); @@ -24,13 +26,36 @@ const actions: ActionTree = { } } return enumerations - }, {}) + }, enums) } } catch(err) { logger.error('error', err) } commit(types.UTIL_ENUMS_UPDATED, enums) + }, + + async fetchFacilities({ commit }) { + let facilities = {} + + const payload = { + parentTypeId: "VIRTUAL_FACILITY" + } + + try { + const resp = await UtilService.fetchFacilities(payload); + + if(!hasError(resp) && resp.data.length) { + facilities = resp.data.reduce((facilities: any, facility: any) => { + facilities[facility.facilityId] = facility + return facilities + }, {}) + } + } catch(err) { + logger.error('error', err) + } + + commit(types.UTIL_FACILITIES_UPDATED, facilities) } } diff --git a/src/store/modules/util/getters.ts b/src/store/modules/util/getters.ts index 39918ab..7dd9bba 100644 --- a/src/store/modules/util/getters.ts +++ b/src/store/modules/util/getters.ts @@ -2,6 +2,13 @@ import { GetterTree } from "vuex" import UtilState from "./UtilState" import RootState from "@/store/RootState" -const getters: GetterTree = {} +const getters: GetterTree = { + getEnums(state) { + return state.enums + }, + getFacilities(state) { + return state.facilities + } +} export default getters; \ No newline at end of file diff --git a/src/store/modules/util/index.ts b/src/store/modules/util/index.ts index 6ca9e4a..40e881f 100644 --- a/src/store/modules/util/index.ts +++ b/src/store/modules/util/index.ts @@ -9,6 +9,7 @@ const utilModule: Module = { namespaced: true, state: { enums: {}, + facilities: {} }, getters, actions, diff --git a/src/store/modules/util/mutation-types.ts b/src/store/modules/util/mutation-types.ts index 6bc0c05..c3933fe 100644 --- a/src/store/modules/util/mutation-types.ts +++ b/src/store/modules/util/mutation-types.ts @@ -1,2 +1,3 @@ export const SN_UTIL = "util" -export const UTIL_ENUMS_UPDATED = SN_UTIL + "/ENUMS_UPDATED" \ No newline at end of file +export const UTIL_ENUMS_UPDATED = SN_UTIL + "/ENUMS_UPDATED" +export const UTIL_FACILITIES_UPDATED = SN_UTIL + "/FACILITIES_UPDATED" \ No newline at end of file diff --git a/src/store/modules/util/mutations.ts b/src/store/modules/util/mutations.ts index 6157429..7a06ea8 100644 --- a/src/store/modules/util/mutations.ts +++ b/src/store/modules/util/mutations.ts @@ -5,6 +5,9 @@ import * as types from "./mutation-types" const mutations: MutationTree = { [types.UTIL_ENUMS_UPDATED](state, payload) { state.enums = payload + }, + [types.UTIL_FACILITIES_UPDATED](state, payload) { + state.facilities = payload } } export default mutations; \ No newline at end of file diff --git a/src/types/index.ts b/src/types/index.ts index b314955..a216dee 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -50,10 +50,23 @@ type Rule = { lastUpdatedStamp: string } +type RouteFilter = { + orderRoutingId: string, + conditionSeqId: string, + conditionTypeEnumId: string, + fieldName: string, + operator: string, + fieldValue: string, + sequenceNum: number, + createdDate: string, + lastUpdatedStamp: string +} + export { Enumeration, EnumerationAndType, Group, Route, + RouteFilter, Rule } \ No newline at end of file diff --git a/src/views/BrokeringQuery.vue b/src/views/BrokeringQuery.vue index b5988c5..2e732f1 100644 --- a/src/views/BrokeringQuery.vue +++ b/src/views/BrokeringQuery.vue @@ -4,8 +4,8 @@