diff --git a/src/components/Menu.vue b/src/components/Menu.vue index b18b1000..2b3bfa86 100644 --- a/src/components/Menu.vue +++ b/src/components/Menu.vue @@ -68,7 +68,7 @@ export default defineComponent({ url: "/draft", iosIcon: createOutline, mdIcon: createOutline, - childRoutes: ["/draft/", "/bulkUpload"], + childRoutes: ["/draft/", "/bulkUpload", "/hard-count"], meta: { permissionId: "APP_DRAFT_VIEW" } diff --git a/src/locales/en.json b/src/locales/en.json index 2707d5b6..3c59b012 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -15,6 +15,7 @@ "Added product to count": "Added product to count", "App": "App", "Assigned count": "Assigned count", + "Auto assign to stores": "Auto assign to stores", "Average variance": "Average variance", "Are you sure you want to change the time zone to?": "Are you sure you want to change the time zone to {timeZoneId}?", "Are you sure you want to download the cycle counts?": "Are you sure you want to download the cycle counts?", @@ -64,6 +65,7 @@ "Cycle count": "Cycle count", "Cycle count cancelled successfully.": "Cycle count cancelled successfully.", "Cycle count not found": "Cycle count not found", + "Cycle counts created successfully.": "Cycle counts created successfully.", "Current on hand": "Current on hand", "Defaults to 'Draft'": "Defaults to 'Draft'", "Due date": "Due date", @@ -102,6 +104,8 @@ "Failed to complete cycle count": "Failed to complete cycle count", "Failed to cancel uploaded cycle count.": "Failed to cancel uploaded cycle count.", "Failed to create cycle count": "Failed to create cycle count", + "Failed to create cycle counts.": "Failed to create cycle counts.", + "Failed to create cycle counts due to missing association of facilities.": "Failed to create cycle counts due to missing association of facilities.", "Failed to add product to count": "Failed to add product to count", "Failed to add products to count, as some products are not found.": "Failed to add products to count, as some products are not found.", "Failed to change the cycle count status": "Failed to change the cycle count status", @@ -121,9 +125,14 @@ "Force scan": "Force scan", "Go to Launchpad": "Go to Launchpad", "Go to OMS": "Go to OMS", + "Group": "Group", + "Hard Count": "Hard Count", + "HARD COUNT": "HARD COUNT", + "Hard counts are used when conducting large scale full counts at facilities. Products are not added to hard counts before they’re assigned. Facilities will count everything they have in stock. Anything they don’t count will defaulted to 0 on hand.": "Hard counts are used when conducting large scale full counts at facilities. Products are not added to hard counts before they’re assigned. Facilities will count everything they have in stock. Anything they don’t count will defaulted to 0 on hand.", "If a file includes multiple facilities, a count is created for every facility. All items with no facility location will be added to the same count.": "If a file includes multiple facilities, a count is created for every facility. All items with no facility location will be added to the same count.", "Import CSV": "Import CSV", "Import Error": "Import Error", + "Individual": "Individual", "In stock": "In stock", "inventory variance": "inventory variance", "Instance Url": "Instance Url", @@ -235,6 +244,7 @@ "Scanned quantity": "Scanned quantity", "selected": "selected", "Select": "Select", + "Search facilities": "Search facilities", "Select fields": "Select fields", "Select store": "Select store", "Select the following columns from the uploaded CSV": "Select the following columns from the uploaded CSV", @@ -245,8 +255,10 @@ "Searching on SKU": "Searching on SKU", "Secondary": "Secondary", "secondary identifier": "secondary identifier", + "Select a facility group to hard count": "Select a facility group to hard count", "Select all the required fields to continue": "Select all the required fields to continue", "Select date": "Select date", + "Select facilities to hard count": "Select facilities to hard count", "Select the column containing products": "Select the column containing products", "Secondary product ID": "Secondary product ID", "Select facility": "Select facility", diff --git a/src/router/index.ts b/src/router/index.ts index 7ca0a198..3e42de8e 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -19,6 +19,7 @@ import Closed from "@/views/Closed.vue"; import StorePermissions from "@/views/StorePermissions.vue"; import Settings from "@/views/Settings.vue"; import BulkUpload from "@/views/BulkUpload.vue" +import HardCount from "@/views/HardCount.vue" // Defining types for the meta values declare module 'vue-router' { @@ -107,6 +108,15 @@ const routes: Array = [ permissionId: "APP_DRAFT_VIEW" } }, + { + path: '/hard-count', + name: 'HardCount', + component: HardCount, + beforeEnter: authGuard, + meta: { + permissionId: "APP_DRAFT_VIEW" + } + }, { path: "/draft/:inventoryCountImportId", name: "DraftDetail", diff --git a/src/services/UtilService.ts b/src/services/UtilService.ts index 6cece1fd..fb7591a4 100644 --- a/src/services/UtilService.ts +++ b/src/services/UtilService.ts @@ -1,4 +1,5 @@ -import { api } from '@/adapter'; +import api, {client} from '@/api'; +import store from '@/store'; const fetchVarianceReasons = async (payload: any): Promise => { return api({ @@ -16,7 +17,62 @@ function getOrdinalSuffix(day: any) { return 'th'; } +const fetchFacilities = async (payload: any): Promise => { + return api({ + url: "facilities", + method: "GET", + params: payload + }) +} + +const createBulkCycleCounts = async (payload: any): Promise => { + return api({ + url: "cycleCounts/bulk", + method: "POST", + data: payload + }) +} + +const fetchFacilityGroups = async (payload: any): Promise => { + const token = store.getters["user/getUserToken"] + const url = store.getters["user/getBaseUrl"] + const baseURL = url.startsWith('http') ? url.includes('/rest/s1/inventory-cycle-count') ? url.replace("inventory-cycle-count", "available-to-promise") : `${url}/rest/s1/available-to-promise/` : `https://${url}.hotwax.io/rest/s1/available-to-promise/`; + + return client({ + url: "facilityGroups", + baseURL, + method: "GET", + params: payload, + headers: { + "api_key": token, + "Content-Type": "application/json" + } + }) +} + +const fetchGroupFacilities = async (payload: any): Promise => { + const token = store.getters["user/getUserToken"] + const url = store.getters["user/getBaseUrl"] + + const baseURL = url.startsWith('http') ? url.includes('/rest/s1/inventory-cycle-count') ? url.replace("inventory-cycle-count", "available-to-promise") : `${url}/rest/s1/available-to-promise/` : `https://${url}.hotwax.io/rest/s1/available-to-promise/`; + + return client({ + url: `facilityGroups/${payload.facilityGroupId}/facilities`, + baseURL, + method: "GET", + params: payload, + headers: { + "api_key": token, + "Content-Type": "application/json" + } + }) +} + export const UtilService = { + createBulkCycleCounts, + fetchFacilities, + fetchFacilityGroups, + fetchGroupFacilities, fetchVarianceReasons, getOrdinalSuffix } \ No newline at end of file diff --git a/src/store/index.ts b/src/store/index.ts index 888039f2..0ef093e6 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -7,6 +7,7 @@ import actions from "./actions"; import userModule from "./modules/user"; import productModule from "./modules/product"; import countModule from "./modules/count"; +import utilModule from "./modules/util"; import { setPermissions } from "@/authorization" @@ -32,6 +33,7 @@ const store = createStore({ user: userModule, product: productModule, count: countModule, + util: utilModule, }, }) diff --git a/src/store/modules/user/actions.ts b/src/store/modules/user/actions.ts index d80c990e..69cf6d28 100644 --- a/src/store/modules/user/actions.ts +++ b/src/store/modules/user/actions.ts @@ -182,6 +182,7 @@ const actions: ActionTree = { } } catch(err) { logger.error("Failed to fetch facilities") + throw err } // Updating current facility with a default first facility when fetching facilities on login @@ -210,7 +211,7 @@ const actions: ActionTree = { facility.productStore = resp.data[0] } } catch(err) { - logger.error("Failed to fetch facilities for product store") + logger.error("Failed to fetch product stores for facility") } } @@ -250,7 +251,7 @@ const actions: ActionTree = { productStores = Object.values(productStoresResp) } } catch(err) { - logger.error("Failed to fetch facilities") + logger.error("Failed to fetch product stores") } // Updating current facility with a default first facility when fetching facilities on login diff --git a/src/store/modules/util/UtilState.ts b/src/store/modules/util/UtilState.ts new file mode 100644 index 00000000..d7343019 --- /dev/null +++ b/src/store/modules/util/UtilState.ts @@ -0,0 +1,3 @@ +export default interface UtilState { + facilityGroups: any; +} \ No newline at end of file diff --git a/src/store/modules/util/actions.ts b/src/store/modules/util/actions.ts new file mode 100644 index 00000000..d50e68ca --- /dev/null +++ b/src/store/modules/util/actions.ts @@ -0,0 +1,28 @@ +import { ActionTree } from 'vuex' +import RootState from '@/store/RootState' +import * as types from './mutation-types' +import { hasError } from '@/utils'; +import logger from '@/logger' +import { UtilService } from '@/services/UtilService' +import UtilState from './UtilState'; + +const actions: ActionTree = { + + async fetchFacilityGroups ( { commit }) { + let facilityGroups = []; + + try { + const resp = await UtilService.fetchFacilityGroups({ pageSize: 200 }) + if(!hasError(resp)) { + facilityGroups = resp.data; + } else { + throw resp + } + } catch(err) { + logger.error("Failed to fetch facility groups", err) + } + commit(types.UTIL_FACILITY_GROUPS_UPDATED, facilityGroups); + } +} + +export default actions; \ No newline at end of file diff --git a/src/store/modules/util/getters.ts b/src/store/modules/util/getters.ts new file mode 100644 index 00000000..2a0620bb --- /dev/null +++ b/src/store/modules/util/getters.ts @@ -0,0 +1,10 @@ +import { GetterTree } from "vuex"; +import RootState from "../../RootState"; +import UtilState from "./UtilState"; + +const getters: GetterTree = { + getFacilityGroups(state) { + return state.facilityGroups + } +}; +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 new file mode 100644 index 00000000..1f2c29d7 --- /dev/null +++ b/src/store/modules/util/index.ts @@ -0,0 +1,18 @@ +import actions from './actions' +import getters from './getters' +import mutations from './mutations' +import { Module } from 'vuex' +import RootState from '../../RootState' +import UtilState from './UtilState' + +const utilModule: Module = { + namespaced: true, + state: { + facilityGroups: [] + }, + getters, + actions, + mutations, +} + +export default utilModule; \ No newline at end of file diff --git a/src/store/modules/util/mutation-types.ts b/src/store/modules/util/mutation-types.ts new file mode 100644 index 00000000..709680ea --- /dev/null +++ b/src/store/modules/util/mutation-types.ts @@ -0,0 +1,2 @@ +export const SN_UTIL = 'util' +export const UTIL_FACILITY_GROUPS_UPDATED = SN_UTIL + '/FACILITY_GROUPS_UPDATED' \ No newline at end of file diff --git a/src/store/modules/util/mutations.ts b/src/store/modules/util/mutations.ts new file mode 100644 index 00000000..1a244474 --- /dev/null +++ b/src/store/modules/util/mutations.ts @@ -0,0 +1,10 @@ +import { MutationTree } from 'vuex' +import * as types from './mutation-types' +import UtilState from './UtilState'; + +const mutations: MutationTree = { + [types.UTIL_FACILITY_GROUPS_UPDATED] (state, payload) { + state.facilityGroups = payload + } +} +export default mutations; \ No newline at end of file diff --git a/src/views/Assigned.vue b/src/views/Assigned.vue index 8f66647e..f28fbbaf 100644 --- a/src/views/Assigned.vue +++ b/src/views/Assigned.vue @@ -22,6 +22,7 @@ +

{{ translate("HARD COUNT") }}

{{ count.countImportName }}

{{ count.inventoryCountImportId }}

diff --git a/src/views/AssignedDetail.vue b/src/views/AssignedDetail.vue index d66b4022..6a97af4b 100644 --- a/src/views/AssignedDetail.vue +++ b/src/views/AssignedDetail.vue @@ -18,6 +18,7 @@