From 119d0b2839bf6d33a99fd0b17e80c68ff6012adf Mon Sep 17 00:00:00 2001 From: elforjani13 <39470382+elforjani13@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:33:43 +0200 Subject: [PATCH] feat: Vendor Credit note. --- src/config/sidebarMenu.js | 2 +- .../VendorCreditNoteDeleteAlert.js | 57 ++++++++ src/containers/AlertsContainer/registered.js | 2 + .../VendorCreditNoteFloatingActions.js | 110 ++++++++++++++++ .../CreditNoteForm/VendorCreditNoteForm.js | 111 ++++++++++++++++ .../VendorCreditNoteForm.schema.js | 44 +++++++ .../VendorCreditNoteFormFooter.js | 38 ++++++ .../VendorCreditNoteFormHeader.js | 44 +++++++ .../VendorCreditNoteFormHeaderFields.js | 124 ++++++++++++++++++ .../VendorCreditNoteFormPage.js | 21 +++ .../VendorCreditNoteFormProvider.js | 68 ++++++++++ .../VendorCreditNoteItemsEntriesEditor.js | 38 ++++++ .../CreditNotes/CreditNoteForm/utils.js | 118 +++++++++++++++++ .../VendorsCreditNoteActionsBar.js | 114 ++++++++++++++++ .../VendorsCreditNoteDataTable.js | 112 ++++++++++++++++ .../VendorsCreditNoteEmptyStatus.js | 29 ++++ .../VendorsCreditNoteListProvider.js | 27 ++++ .../VendorsCreditNoteViewTabs.js | 46 +++++++ .../VendorsCreditNotesList.js | 54 ++++++++ .../CreditNotesLanding/components.js | 88 +++++++++++++ .../withVendorsCreditNotes.js | 24 ++++ .../CreditNotes/VendorCreditNotesAlerts.js | 15 +++ .../Sales/CreditNotes/CreditNotesAlerts.js | 2 +- .../CreditNotesActionsBar.js | 2 +- .../CreditNotesLanding/CreditNotesList.js | 12 +- src/containers/Settings/withSettings.js | 1 + src/routes/dashboard.js | 43 ++++++ src/store/reducers.js | 2 + src/store/types.js | 4 +- .../vendorsCreditNotes.actions.js | 14 ++ .../vendorsCreditNotes.reducer.js | 34 +++++ .../vendorsCreditNotes.selector.js | 24 ++++ .../vendorsCreditNotes.type.js | 5 + src/style/pages/VendorsCreditNote/List.scss | 20 +++ .../pages/VendorsCreditNote/PageForm.scss | 49 +++++++ 35 files changed, 1488 insertions(+), 10 deletions(-) create mode 100644 src/containers/Alerts/VendorCeditNotes/VendorCreditNoteDeleteAlert.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.schema.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooter.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeader.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormHeaderFields.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormPage.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormProvider.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteItemsEntriesEditor.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNoteForm/utils.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteActionsBar.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteDataTable.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteEmptyStatus.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteListProvider.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNoteViewTabs.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/VendorsCreditNotesList.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/components.js create mode 100644 src/containers/Purchases/CreditNotes/CreditNotesLanding/withVendorsCreditNotes.js create mode 100644 src/containers/Purchases/CreditNotes/VendorCreditNotesAlerts.js create mode 100644 src/store/vendorsCreditNotes/vendorsCreditNotes.actions.js create mode 100644 src/store/vendorsCreditNotes/vendorsCreditNotes.reducer.js create mode 100644 src/store/vendorsCreditNotes/vendorsCreditNotes.selector.js create mode 100644 src/store/vendorsCreditNotes/vendorsCreditNotes.type.js create mode 100644 src/style/pages/VendorsCreditNote/List.scss create mode 100644 src/style/pages/VendorsCreditNote/PageForm.scss diff --git a/src/config/sidebarMenu.js b/src/config/sidebarMenu.js index 66e5c7a7f..928d37eb0 100644 --- a/src/config/sidebarMenu.js +++ b/src/config/sidebarMenu.js @@ -260,7 +260,7 @@ export default [ }, { text: , - href: '/credit-notes', + href: '/vendors-credit-notes', }, { text: , diff --git a/src/containers/Alerts/VendorCeditNotes/VendorCreditNoteDeleteAlert.js b/src/containers/Alerts/VendorCeditNotes/VendorCreditNoteDeleteAlert.js new file mode 100644 index 000000000..25e935099 --- /dev/null +++ b/src/containers/Alerts/VendorCeditNotes/VendorCreditNoteDeleteAlert.js @@ -0,0 +1,57 @@ +import React from 'react'; +import intl from 'react-intl-universal'; +import { FormattedMessage as T, FormattedHTMLMessage } from 'components'; +import { Intent, Alert } from '@blueprintjs/core'; +import { AppToaster } from 'components'; + +import withAlertStoreConnect from 'containers/Alert/withAlertStoreConnect'; +import withAlertActions from 'containers/Alert/withAlertActions'; +import withDrawerActions from 'containers/Drawer/withDrawerActions'; + +import { compose } from 'utils'; + +/** + * Vendor Credit note delete alert. + */ +function VendorCreditNoteDeleteAlert({ + name, + + // #withAlertStoreConnect + isOpen, + payload: { vendorCrditNoteId }, + + // #withAlertActions + closeAlert, + + // #withDrawerActions + closeDrawer, +}) { + // handle cancel delete credit note alert. + const handleCancelDeleteAlert = () => { + closeAlert(name); + }; + const handleConfirmCreditNoteDelete = () => {}; + + return ( + } + confirmButtonText={} + icon="trash" + intent={Intent.DANGER} + isOpen={isOpen} + onCancel={handleCancelDeleteAlert} + onConfirm={handleConfirmCreditNoteDelete} + // loading={isLoading} + > +

+ +

+
+ ); +} + +export default compose( + withAlertStoreConnect(), + withAlertActions, + withDrawerActions, +)(VendorCreditNoteDeleteAlert); diff --git a/src/containers/AlertsContainer/registered.js b/src/containers/AlertsContainer/registered.js index dd7327daf..bbab107a3 100644 --- a/src/containers/AlertsContainer/registered.js +++ b/src/containers/AlertsContainer/registered.js @@ -18,6 +18,7 @@ import UsersAlerts from '../Preferences/Users/UsersAlerts'; import CurrenciesAlerts from '../Preferences/Currencies/CurrenciesAlerts'; import RolesAlerts from '../Preferences/Users/Roles/RolesAlerts'; import CreditNotesAlerts from '../Sales/CreditNotes/CreditNotesAlerts'; +import VendorCreditNotesAlerts from '../Purchases/CreditNotes/VendorCreditNotesAlerts'; export default [ ...AccountsAlerts, @@ -40,4 +41,5 @@ export default [ ...CurrenciesAlerts, ...RolesAlerts, ...CreditNotesAlerts, + ...VendorCreditNotesAlerts, ]; diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.js new file mode 100644 index 000000000..a8f0121f4 --- /dev/null +++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFloatingActions.js @@ -0,0 +1,110 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { useFormikContext } from 'formik'; +import { + Intent, + Button, + ButtonGroup, + Popover, + PopoverInteractionKind, + Position, + Menu, + MenuItem, +} from '@blueprintjs/core'; +import { If, Icon, FormattedMessage as T } from 'components'; +import { CLASSES } from 'common/classes'; +import classNames from 'classnames'; +import { useVendorCreditNoteFormContext } from './VendorCreditNoteFormProvider'; + +/** + * Purchases Credit note floating actions. + */ +export default function VendorCreditNoteFloatingActions() { + const history = useHistory(); + + // Formik context. + const { resetForm, submitForm, isSubmitting } = useFormikContext(); + + // Credit note form context. + const { setSubmitPayload } = useVendorCreditNoteFormContext(); + + // Handle cancel button click. + const handleCancelBtnClick = (event) => { + history.goBack(); + }; + + const handleClearBtnClick = (event) => { + resetForm(); + }; + + return ( +
+ {/* ----------- Save And Open ----------- */} + +
+ ); +} diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js new file mode 100644 index 000000000..735efceb2 --- /dev/null +++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.js @@ -0,0 +1,111 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { Formik, Form } from 'formik'; +import { Intent } from '@blueprintjs/core'; +import intl from 'react-intl-universal'; +import { sumBy, omit, isEmpty } from 'lodash'; +import classNames from 'classnames'; +import { CLASSES } from 'common/classes'; +import { + CreateCreditNoteFormSchema, + EditCreditNoteFormSchema, +} from './VendorCreditNoteForm.schema'; + +import VendorCreditNoteFormHeader from './VendorCreditNoteFormHeader'; +import VendorCreditNoteItemsEntriesEditor from './VendorCreditNoteItemsEntriesEditor'; +import VendorCreditNoteFormFooter from './VendorCreditNoteFormFooter'; +import VendorCreditNoteFloatingActions from './VendorCreditNoteFloatingActions'; +import { useVendorCreditNoteFormContext } from './VendorCreditNoteFormProvider'; + +import { AppToaster } from 'components'; + +import { compose, safeSumBy } from 'utils'; +import { + defaultVendorsCreditNote, + filterNonZeroEntries, + transformToEditForm, + transformFormValuesToRequest, +} from './utils'; +import withCurrentOrganization from 'containers/Organization/withCurrentOrganization'; + +/** + * Vendor Credit note form. + */ +function VendorCreditNoteForm({ + // #withCurrentOrganization + organization: { base_currency }, +}) { + const history = useHistory(); + // Vendor Credit note form context. + const { bill } = useVendorCreditNoteFormContext(); + + // Initial values. + const initialValues = React.useMemo( + () => ({ + ...(!isEmpty(bill) + ? { + ...transformToEditForm(bill), + currency_code: base_currency, + } + : { + ...defaultVendorsCreditNote, + currency_code: base_currency, + }), + }), + [], + ); + + // Handle form submit. + const handleSubmit = (values, { setSubmitting, setErrors, resetForm }) => { + const entries = filterNonZeroEntries(values.entries); + const totalQuantity = safeSumBy(entries, 'quantity'); + + if (totalQuantity === 0) { + AppToaster.show({ + message: intl.get('quantity_cannot_be_zero_or_empty'), + intent: Intent.DANGER, + }); + setSubmitting(false); + return; + } + + const form = {}; + + // Handle the request success. + const onSuccess = (response) => {}; + + // Handle the request error. + const onError = ({ + response: { + data: { errors }, + }, + }) => {}; + }; + + return ( +
+ +
+ + + + + +
+
+ ); +} + +export default compose(withCurrentOrganization())(VendorCreditNoteForm); diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.schema.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.schema.js new file mode 100644 index 000000000..29773cb98 --- /dev/null +++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteForm.schema.js @@ -0,0 +1,44 @@ +import * as Yup from 'yup'; +import intl from 'react-intl-universal'; +import { DATATYPES_LENGTH } from 'common/dataTypes'; +import { isBlank } from 'utils'; + +const getSchema = Yup.object().shape({ + vendor_id: Yup.number().required().label(intl.get('vendor_name_')), + bill_date: Yup.date().required().label(intl.get('bill_date_')), + due_date: Yup.date().required().label(intl.get('due_date_')), + bill_number: Yup.string() + .max(DATATYPES_LENGTH.STRING) + .label(intl.get('bill_number_')), + reference_no: Yup.string().nullable().min(1).max(DATATYPES_LENGTH.STRING), + note: Yup.string() + .trim() + .min(1) + .max(DATATYPES_LENGTH.TEXT) + .label(intl.get('note')), + open: Yup.boolean(), + entries: Yup.array().of( + Yup.object().shape({ + quantity: Yup.number() + .nullable() + .max(DATATYPES_LENGTH.INT_10) + .when(['rate'], { + is: (rate) => rate, + then: Yup.number().required(), + }), + rate: Yup.number().nullable().max(DATATYPES_LENGTH.INT_10), + item_id: Yup.number() + .nullable() + .when(['quantity', 'rate'], { + is: (quantity, rate) => !isBlank(quantity) && !isBlank(rate), + then: Yup.number().required(), + }), + total: Yup.number().nullable(), + discount: Yup.number().nullable().min(0).max(DATATYPES_LENGTH.INT_10), + description: Yup.string().nullable().max(DATATYPES_LENGTH.TEXT), + }), + ), +}); + +export const CreateCreditNoteFormSchema = getSchema; +export const EditCreditNoteFormSchema = getSchema; diff --git a/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooter.js b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooter.js new file mode 100644 index 000000000..ea4ee2d99 --- /dev/null +++ b/src/containers/Purchases/CreditNotes/CreditNoteForm/VendorCreditNoteFormFooter.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { FastField } from 'formik'; +import { FormGroup, TextArea } from '@blueprintjs/core'; +import { FormattedMessage as T } from 'components'; +import { CLASSES } from 'common/classes'; +import { Row, Col, Postbox } from 'components'; +import { inputIntent } from 'utils'; +import classNames from 'classnames'; + +/** + * Vendor Credit note form footer. + */ +export default function VendorCreditNoteFormFooter() { + return ( +
+ } + defaultOpen={false} + > + + + + {({ field, meta: { error, touched } }) => ( + } + className={'form-group--note'} + intent={inputIntent({ error, touched })} + > +