Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ import { ReplenishmentStagingLocationScreen } from './screens/Replenishment/Repl
import Transfer from './screens/Transfer';
import Transfers from './screens/Transfers';
import TransferDetails from './screens/TransfersDetails';
import CreateTransferEntryScreen from './screens/CreateTransfer/CreateTransferEntryScreen';
import CreateTransferItemListScreen from './screens/CreateTransfer/CreateTransferItemListScreen';
import CreateTransferQuantityScreen from './screens/CreateTransfer/CreateTransferQuantityScreen';
import CreateTransferDestinationScreen from './screens/CreateTransfer/CreateTransferDestinationScreen';
import CreateTransferCompleteScreen from './screens/CreateTransfer/CreateTransferCompleteScreen';
import ViewAvailableItem from './screens/ViewAvailableItem';
import ApiClient from './utils/ApiClient';
import Theme from './utils/Theme';
Expand Down Expand Up @@ -270,6 +275,31 @@ class Main extends Component<Props, State> {
/>
<Stack.Screen name="AdjustStock" component={AdjustStock} options={{ title: 'Adjust Stock' }} />
<Stack.Screen name="Transfer" component={Transfer} options={{ title: 'Transfer' }} />
<Stack.Screen
name="CreateTransferEntry"
component={CreateTransferEntryScreen}
options={{ title: 'Create Transfer' }}
/>
<Stack.Screen
name="CreateTransferItemList"
component={CreateTransferItemListScreen}
options={{ title: 'Transfer Items' }}
/>
<Stack.Screen
name="CreateTransferQuantity"
component={CreateTransferQuantityScreen}
options={{ title: 'Transfer Quantity' }}
/>
<Stack.Screen
name="CreateTransferDestination"
component={CreateTransferDestinationScreen}
options={{ title: 'Transfer Destination' }}
/>
<Stack.Screen
name="CreateTransferComplete"
component={CreateTransferCompleteScreen}
options={{ title: 'Complete Transfer' }}
/>
<Stack.Screen
name="ShipmentDetails"
component={ShipItemDetails}
Expand Down
35 changes: 35 additions & 0 deletions src/apis/createTransfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { StockTransferPayload } from '../screens/CreateTransfer/types';
import apiClient from '../utils/ApiClient';

export function getStockTransferCandidates(facilityId: string) {
return apiClient.get(`/stockTransfers/candidates?location.id=${encodeURIComponent(facilityId)}`);
}

export function lookupBarcodeProduct(code: string) {
return apiClient.get(`/barcodes/${encodeURIComponent(code)}`);
}

export function lookupLocationByCode(code: string) {
return apiClient.get(`/locations/${encodeURIComponent(code)}`);
}

export function searchDestinationBins(searchTerm: string) {
const term = encodeURIComponent(searchTerm || '');
return apiClient.get(
`/internalLocations/search?searchTerm=${term}` +
'&locationTypeCode=BIN_LOCATION&locationTypeCode=INTERNAL' +
'&ignoreActivityCodes=RECEIVE_STOCK'
);
}

export function postStockTransfer(payload: StockTransferPayload) {
return apiClient.post('/stockTransfers', payload);
}

export function getStockTransferById(id: string) {
return apiClient.get(`/stockTransfers/${encodeURIComponent(id)}`);
}

export function putStockTransfer(id: string, body: any) {
return apiClient.put(`/stockTransfers/${encodeURIComponent(id)}`, body);
}
1 change: 1 addition & 0 deletions src/apis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './transfers';
export * from './others';
export * from './picking';
export * from './pua';
export * from './createTransfer';
79 changes: 69 additions & 10 deletions src/components/SearchButton/searchProviders.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Location from '../../data/location/Location';
import Product from '../../data/product/Product';
import { searchDestinationBinsAction, searchProductOrLocationAction } from '../../redux/actions/createTransfer';
import { searchInternalLocations } from '../../redux/actions/locations';
import { searchProductGloballyAction } from '../../redux/actions/products';

Expand Down Expand Up @@ -47,29 +48,75 @@ function createProductAction(term: string, callback: SearchCallback) {
);
}

function locationToSearchResult(item: Location): SearchResult {
return {
id: item.id,
label: item.locationNumber || item.name,
subtitle: item.name,
value: item.locationNumber
};
}

function handleLocationSearchResponse(
response: SearchResponse<Location>,
callback: SearchCallback,
failureMessage: string
) {
if (response?.error) {
callback({ error: response.errorMessage || failureMessage });
return;
}
callback({ results: (response?.data || []).map(locationToSearchResult) });
}

function createLocationAction(term: string, callback: SearchCallback) {
return searchInternalLocations(
term,
null,
(response: SearchResponse<Location>) => {
(response: SearchResponse<Location>) =>
handleLocationSearchResponse(response, callback, 'Failed to search locations.'),
true
);
}

function createProductOrLocationAction(term: string, callback: SearchCallback) {
return searchProductOrLocationAction(
term,
(response: { products?: Product[]; locations?: Location[]; error?: boolean; errorMessage?: string }) => {
if (response?.error) {
callback({ error: response.errorMessage || 'Failed to search locations.' });
callback({ error: response.errorMessage || 'Failed to search.' });
return;
}

callback({
results: (response?.data || []).map((item) => ({
id: item.id,
label: item.locationNumber || item.name,
subtitle: item.name,
value: item.locationNumber
}))
});
const productResults: SearchResult[] = (response?.products || []).map((item) => ({
id: `product:${item.id}`,
label: item.productCode || item.name,
subtitle: `Product · ${item.name}`,
value: item.productCode
}));

const locationResults: SearchResult[] = (response?.locations || []).map((item) => ({
id: `location:${item.id}`,
label: item.locationNumber || item.name,
subtitle: `Bin · ${item.name}`,
value: item.locationNumber
}));

callback({ results: [...productResults, ...locationResults] });
},
true
);
}

function createDestinationBinAction(term: string, callback: SearchCallback) {
return searchDestinationBinsAction(
term,
(response: SearchResponse<Location>) =>
handleLocationSearchResponse(response, callback, 'Failed to search destination bins.'),
true
);
}

export const searchProviders = {
product: {
title: 'Search Product',
Expand All @@ -88,6 +135,18 @@ export const searchProviders = {
placeholder: 'Search by name or number...',
inputLabel: 'Container ID',
createAction: createLocationAction
},
destinationBin: {
title: 'Search Destination Bin',
placeholder: 'Search by name or number...',
inputLabel: 'Destination Bin',
createAction: createDestinationBinAction
},
productOrLocation: {
title: 'Search Product or Bin',
placeholder: 'Product or bin code...',
inputLabel: 'Product or Bin',
createAction: createProductOrLocationAction
}
};

Expand Down
68 changes: 68 additions & 0 deletions src/redux/actions/createTransfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export const GET_STOCK_TRANSFER_CANDIDATES = 'CREATE_TRANSFER/GET_CANDIDATES';
export const LOOKUP_TRANSFER_BARCODE = 'CREATE_TRANSFER/LOOKUP_BARCODE';
export const LOOKUP_LOCATION_BY_CODE = 'CREATE_TRANSFER/LOOKUP_LOCATION';
export const SEARCH_PRODUCT_OR_LOCATION = 'CREATE_TRANSFER/SEARCH_PRODUCT_OR_LOCATION';
export const SEARCH_DESTINATION_BINS = 'CREATE_TRANSFER/SEARCH_DESTINATION_BINS';
export const SUBMIT_CREATE_TRANSFER = 'CREATE_TRANSFER/SUBMIT';
export const COMPLETE_CREATE_TRANSFER = 'CREATE_TRANSFER/COMPLETE';

type Callback<T = any> = (data: T) => void;

export function getStockTransferCandidatesAction(facilityId: string, callback: Callback, suppressLoading?: boolean) {
return {
type: GET_STOCK_TRANSFER_CANDIDATES,
payload: { facilityId },
callback,
suppressLoading
};
}

export function lookupTransferBarcodeAction(code: string, callback: Callback) {
return {
type: LOOKUP_TRANSFER_BARCODE,
payload: { code },
callback
};
}

export function lookupLocationByCodeAction(code: string, callback: Callback) {
return {
type: LOOKUP_LOCATION_BY_CODE,
payload: { code },
callback
};
}

export function searchProductOrLocationAction(searchTerm: string, callback: Callback, suppressLoading?: boolean) {
return {
type: SEARCH_PRODUCT_OR_LOCATION,
payload: { searchTerm },
callback,
suppressLoading
};
}

export function searchDestinationBinsAction(searchTerm: string, callback: Callback, suppressLoading?: boolean) {
return {
type: SEARCH_DESTINATION_BINS,
payload: { searchTerm },
callback,
suppressLoading
};
}

export function submitCreateTransferAction(payload: any, callback: Callback) {
return {
type: SUBMIT_CREATE_TRANSFER,
payload,
callback
};
}

export function completeCreateTransferAction(transferId: string, callback: Callback) {
return {
type: COMPLETE_CREATE_TRANSFER,
payload: { transferId },
callback
};
}
Loading