diff --git a/packages/apps/purchase/src/api/purchase-request-line-api.js b/packages/apps/purchase/src/api/purchase-request-line-api.js
index 19079848b..3b7bd0fcc 100644
--- a/packages/apps/purchase/src/api/purchase-request-line-api.js
+++ b/packages/apps/purchase/src/api/purchase-request-line-api.js
@@ -16,22 +16,49 @@
* along with this program. If not, see .
*/
-import {createStandardSearch} from '@axelor/aos-mobile-core';
+import {
+ createStandardSearch,
+ getSearchCriterias,
+} from '@axelor/aos-mobile-core';
-const createPurchaseRequestLineCriteria = purchaseRequestId => {
- return [
+const createPurchaseRequestLineCriteria = ({
+ searchValue,
+ purchaseRequestId,
+ newProduct,
+}) => {
+ const criterias = [
+ getSearchCriterias('purchase_purchaseRequestLine', searchValue),
{
fieldName: 'purchaseRequest.id',
operator: '=',
value: purchaseRequestId,
},
];
+
+ if (newProduct != null) {
+ criterias.push({
+ fieldName: 'newProduct',
+ operator: '=',
+ value: newProduct,
+ });
+ }
+
+ return criterias;
};
-export async function searchPurchaseRequestLine({page = 0, purchaseRequestId}) {
+export async function searchPurchaseRequestLine({
+ page = 0,
+ searchValue,
+ purchaseRequestId,
+ newProduct,
+}) {
return createStandardSearch({
model: 'com.axelor.apps.purchase.db.PurchaseRequestLine',
- criteria: createPurchaseRequestLineCriteria(purchaseRequestId),
+ criteria: createPurchaseRequestLineCriteria({
+ searchValue,
+ purchaseRequestId,
+ newProduct,
+ }),
fieldKey: 'purchase_purchaseRequestLine',
sortKey: 'purchase_purchaseRequestLine',
page,
diff --git a/packages/apps/purchase/src/components/atoms/RequestLineCard/RequestLineCard.tsx b/packages/apps/purchase/src/components/atoms/RequestLineCard/RequestLineCard.tsx
new file mode 100644
index 000000000..f28fa6eba
--- /dev/null
+++ b/packages/apps/purchase/src/components/atoms/RequestLineCard/RequestLineCard.tsx
@@ -0,0 +1,78 @@
+/*
+ * Axelor Business Solutions
+ *
+ * Copyright (C) 2024 Axelor ().
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import React, {useMemo} from 'react';
+import {StyleSheet} from 'react-native';
+import {
+ ObjectCard,
+ TextUnit,
+ usePriceFormat,
+ useThemeColor,
+} from '@axelor/aos-mobile-ui';
+
+interface RequestLineCardProps {
+ style?: any;
+ productName?: string;
+ unit?: string;
+ qty?: string;
+ newProduct?: boolean;
+}
+
+const RequestLineCard = ({
+ style,
+ productName,
+ unit,
+ qty,
+ newProduct,
+}: RequestLineCardProps) => {
+ const priceFormat = usePriceFormat();
+ const Colors = useThemeColor();
+
+ const borderStyle = useMemo(() => {
+ if (newProduct) {
+ return getStyles(Colors.plannedColor.background)?.border;
+ }
+ }, [Colors.plannedColor.background, newProduct]);
+
+ return (
+
+ ),
+ },
+ ],
+ }}
+ />
+ );
+};
+
+const getStyles = (color: string) =>
+ StyleSheet.create({
+ border: {borderLeftWidth: 7, borderLeftColor: color},
+ });
+
+export default RequestLineCard;
diff --git a/packages/apps/purchase/src/components/atoms/RequestSeeLinesButton/RequestSeeLinesButton.tsx b/packages/apps/purchase/src/components/atoms/RequestSeeLinesButton/RequestSeeLinesButton.tsx
index b0a30bcac..90ddd27ea 100644
--- a/packages/apps/purchase/src/components/atoms/RequestSeeLinesButton/RequestSeeLinesButton.tsx
+++ b/packages/apps/purchase/src/components/atoms/RequestSeeLinesButton/RequestSeeLinesButton.tsx
@@ -18,7 +18,11 @@
import React, {useMemo} from 'react';
import {StyleSheet, TouchableOpacity, View} from 'react-native';
-import {useSelector, useTranslator} from '@axelor/aos-mobile-core';
+import {
+ useNavigation,
+ useSelector,
+ useTranslator,
+} from '@axelor/aos-mobile-core';
import {
Card,
Icon,
@@ -30,6 +34,7 @@ import {
const RequestSeeLinesButton = () => {
const I18n = useTranslator();
const Colors = useThemeColor();
+ const navigation = useNavigation();
const styles = useMemo(
() => getStyles(Colors.secondaryColor.background),
@@ -42,7 +47,7 @@ const RequestSeeLinesButton = () => {
return (
{}}
+ onPress={() => navigation.navigate('RequestLineListScreen')}
disabled={totalPurchaseRequestLine === 0}
activeOpacity={0.9}>
diff --git a/packages/apps/purchase/src/components/atoms/index.ts b/packages/apps/purchase/src/components/atoms/index.ts
index a9335ea63..2e97a14c8 100644
--- a/packages/apps/purchase/src/components/atoms/index.ts
+++ b/packages/apps/purchase/src/components/atoms/index.ts
@@ -17,6 +17,7 @@
*/
export {default as DropdownRequestCharacteristics} from './DropdownRequestCharacteristics/DropdownRequestCharacteristics';
-export {default as RequestSeeLinesButton} from './RequestSeeLinesButton/RequestSeeLinesButton';
export {default as RequestCard} from './RequestCard/RequestCard';
export {default as RequestHeader} from './RequestHeader/RequestHeader';
+export {default as RequestLineCard} from './RequestLineCard/RequestLineCard';
+export {default as RequestSeeLinesButton} from './RequestSeeLinesButton/RequestSeeLinesButton';
diff --git a/packages/apps/purchase/src/components/molecules/RequestDropdownCards/RequestDropdownCards.tsx b/packages/apps/purchase/src/components/molecules/RequestDropdownCards/RequestDropdownCards.tsx
index f73044bde..8a952564a 100644
--- a/packages/apps/purchase/src/components/molecules/RequestDropdownCards/RequestDropdownCards.tsx
+++ b/packages/apps/purchase/src/components/molecules/RequestDropdownCards/RequestDropdownCards.tsx
@@ -21,7 +21,7 @@ import {useTranslator} from '@axelor/aos-mobile-core';
import {DropdownCardSwitch} from '@axelor/aos-mobile-ui';
import {DropdownRequestCharacteristics} from '../../atoms';
-const RequestDropdownCards = ({style}: {style: any}) => {
+const RequestDropdownCards = ({style}: {style?: any}) => {
const I18n = useTranslator();
return (
diff --git a/packages/apps/purchase/src/i18n/en.json b/packages/apps/purchase/src/i18n/en.json
index f1ceeee02..316e62af9 100644
--- a/packages/apps/purchase/src/i18n/en.json
+++ b/packages/apps/purchase/src/i18n/en.json
@@ -1,6 +1,7 @@
{
"Purchase_Purchase": "Purchase",
"Purchase_InternalRequests": "Internal requests",
+ "Purchase_InternalRequest": "Internal request",
"Purchase_Status_Draft": "Draft",
"Purchase_Status_Requested": "Requested",
"Purchase_Status_Accepted": "Accepted",
@@ -17,6 +18,9 @@
"Purchase_Accept": "Accept",
"Purchase_Refuse": "Refuse",
"Purchase_NoInformationAvailable": "No information available",
+ "Purchase_AddProduct": "Add product",
+ "Purchase_NewProduct": "New product",
+ "Purchase_ExistingProduct": "Existing product",
"Purchase_SliceAction_SearchPurchaseRequest": "search purchase request",
"Purchase_SliceAction_SearchSupplier": "search supplier",
"Purchase_SliceAction_GetPurchaseRequest": "get purchase request",
diff --git a/packages/apps/purchase/src/i18n/fr.json b/packages/apps/purchase/src/i18n/fr.json
index fbe342b34..7516def42 100644
--- a/packages/apps/purchase/src/i18n/fr.json
+++ b/packages/apps/purchase/src/i18n/fr.json
@@ -1,6 +1,7 @@
{
"Purchase_Purchase": "Achats",
"Purchase_InternalRequests": "Demandes internes",
+ "Purchase_InternalRequest": "Demande interne",
"Purchase_Status_Draft": "Brouillon",
"Purchase_Status_Requested": "Demandée",
"Purchase_Status_Accepted": "Acceptée",
@@ -17,6 +18,9 @@
"Purchase_Accept": "Accepter",
"Purchase_Refuse": "Refuser",
"Purchase_NoInformationAvailable": "Aucune information disponible",
+ "Purchase_AddProduct": "Ajouter un produit",
+ "Purchase_NewProduct": "Nouveau produit",
+ "Purchase_ExistingProduct": "Produit existant",
"Purchase_SliceAction_SearchPurchaseRequest": "recherche sur les demandes d'achat",
"Purchase_SliceAction_SearchSupplier": "recherche sur les fournisseurs",
"Purchase_SliceAction_GetPurchaseRequest": "récupération de la demande d'achat",
diff --git a/packages/apps/purchase/src/models/objectFields.ts b/packages/apps/purchase/src/models/objectFields.ts
index efb18d96c..b7330b598 100644
--- a/packages/apps/purchase/src/models/objectFields.ts
+++ b/packages/apps/purchase/src/models/objectFields.ts
@@ -32,4 +32,11 @@ export const purchase_modelAPI: ObjectFields = {
purchase_supplier: schemaContructor.object({
simpleFullName: schemaContructor.string(),
}),
+ purchase_purchaseRequestLine: schemaContructor.object({
+ product: schemaContructor.subObject(),
+ productTitle: schemaContructor.string(),
+ unit: schemaContructor.subObject(),
+ quantity: schemaContructor.string(),
+ newProduct: schemaContructor.boolean(),
+ }),
};
diff --git a/packages/apps/purchase/src/models/searchFields.ts b/packages/apps/purchase/src/models/searchFields.ts
index 321ca825a..0b2e9dd8a 100644
--- a/packages/apps/purchase/src/models/searchFields.ts
+++ b/packages/apps/purchase/src/models/searchFields.ts
@@ -21,4 +21,5 @@ import {SearchFields} from '@axelor/aos-mobile-core';
export const purchase_searchFields: SearchFields = {
purchase_purchaseRequest: ['purchaseRequestSeq', 'company.name'],
purchase_supplier: ['simpleFullName'],
+ purchase_purchaseRequestLine: ['product.fullName', 'productTitle'],
};
diff --git a/packages/apps/purchase/src/models/typeObjects.ts b/packages/apps/purchase/src/models/typeObjects.ts
index 01d06fb03..cf78f693a 100644
--- a/packages/apps/purchase/src/models/typeObjects.ts
+++ b/packages/apps/purchase/src/models/typeObjects.ts
@@ -64,4 +64,25 @@ export const purchase_typeObjects: ModuleSelections = [
},
},
},
+ {
+ modelName: 'com.axelor.apps.purchase.db.PurchaseRequestLine',
+ fields: {
+ newProduct: {
+ content: [
+ {
+ key: 'NewProduct',
+ value: true,
+ title: 'Purchase_NewProduct',
+ color: 'plannedColor',
+ },
+ {
+ key: 'ExistingProduct',
+ value: false,
+ title: 'Purchase_ExistingProduct',
+ color: 'secondaryColor',
+ },
+ ],
+ },
+ },
+ },
];
diff --git a/packages/apps/purchase/src/screens/RequestLineListScreen.tsx b/packages/apps/purchase/src/screens/RequestLineListScreen.tsx
new file mode 100644
index 000000000..0b6808d2a
--- /dev/null
+++ b/packages/apps/purchase/src/screens/RequestLineListScreen.tsx
@@ -0,0 +1,100 @@
+/*
+ * Axelor Business Solutions
+ *
+ * Copyright (C) 2024 Axelor ().
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import React, {useMemo, useState} from 'react';
+import {ChipSelect, Screen} from '@axelor/aos-mobile-ui';
+import {
+ SearchListView,
+ useSelector,
+ useTranslator,
+ useTypeHelpers,
+ useTypes,
+} from '@axelor/aos-mobile-core';
+import {RequestHeader, RequestLineCard} from '../components';
+import {searchPurchaseRequestLine} from '../features/purchaseRequestLineSlice';
+
+const RequestLineListScreen = () => {
+ const I18n = useTranslator();
+ const {PurchaseRequestLine} = useTypes();
+ const {getSelectionItems} = useTypeHelpers();
+
+ const {purchaseRequest} = useSelector(
+ state => state.purchase_purchaseRequest,
+ );
+ const {
+ loadingPurchaseRequestLines,
+ moreLoadingPurchaseRequestLine,
+ isListEndPurchaseRequestLine,
+ purchaseRequestLineList,
+ } = useSelector(state => state.purchase_purchaseRequestLine);
+
+ const [selectedStatus, setSelectedStatus] = useState([]);
+
+ const statusList = useMemo(
+ () => getSelectionItems(PurchaseRequestLine?.newProduct, selectedStatus),
+ [PurchaseRequestLine?.newProduct, getSelectionItems, selectedStatus],
+ );
+
+ const sliceFunctionData = useMemo(
+ () => ({
+ purchaseRequestId: purchaseRequest.id,
+ newProduct: selectedStatus[0]?.value,
+ }),
+ [purchaseRequest.id, selectedStatus],
+ );
+
+ return (
+
+ }
+ actionList={[
+ {
+ iconName: 'plus',
+ title: I18n.t('Purchase_AddProduct'),
+ onPress: () => {},
+ },
+ ]}
+ chipComponent={
+
+ }
+ expandableFilter={false}
+ searchPlaceholder={I18n.t('Base_Search')}
+ list={purchaseRequestLineList}
+ loading={loadingPurchaseRequestLines}
+ moreLoading={moreLoadingPurchaseRequestLine}
+ isListEnd={isListEndPurchaseRequestLine}
+ sliceFunction={searchPurchaseRequestLine}
+ sliceFunctionData={sliceFunctionData}
+ renderListItem={({item}) => (
+
+ )}
+ />
+
+ );
+};
+
+export default RequestLineListScreen;
diff --git a/packages/apps/purchase/src/screens/index.ts b/packages/apps/purchase/src/screens/index.ts
index 940f41765..64fb44dfa 100644
--- a/packages/apps/purchase/src/screens/index.ts
+++ b/packages/apps/purchase/src/screens/index.ts
@@ -17,6 +17,7 @@
*/
import RequestDetailsScreen from './RequestDetailsScreen';
+import RequestLineListScreen from './RequestLineListScreen';
import RequestListScreen from './RequestListScreen';
export default {
@@ -29,13 +30,21 @@ export default {
isUsableOnShortcut: true,
},
RequestDetailsView: {
- title: 'Purchase_Request',
+ title: 'Purchase_InternalRequest',
component: RequestDetailsScreen,
options: {
shadedHeader: false,
},
},
+ RequestLineListScreen: {
+ title: 'Purchase_InternalRequest',
+ component: RequestLineListScreen,
+ options: {
+ shadedHeader: false,
+ },
+ },
};
export {RequestDetailsScreen};
export {RequestListScreen};
+export {RequestLineListScreen};