summaryrefslogtreecommitdiff
path: root/src/services/waybills
diff options
context:
space:
mode:
Diffstat (limited to 'src/services/waybills')
-rw-r--r--src/services/waybills/WaybillForm.tsx86
-rw-r--r--src/services/waybills/WaybillPanel.tsx42
-rw-r--r--src/services/waybills/index.ts27
3 files changed, 155 insertions, 0 deletions
diff --git a/src/services/waybills/WaybillForm.tsx b/src/services/waybills/WaybillForm.tsx
new file mode 100644
index 0000000..c11ab9e
--- /dev/null
+++ b/src/services/waybills/WaybillForm.tsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import { Form, FormikProps } from 'formik';
+import _ from 'lodash';
+import moment from 'moment';
+import Input from '../../components/Input';
+import Button from '../../components/Button';
+import Select from '../../components/Select';
+import Paper from '../../components/Paper';
+import hooks from '../../hooks/useAPIClient';
+
+
+const mapper = (item: any) => ({ key: item._id, label: item.name });
+
+
+const WaybillForm: React.FC<FormikProps<any>> = ({ setFieldValue, values }) => {
+ const { data: products } = hooks.products.useList();
+ const { data: contractors } = hooks.contractors.useList();
+
+ if (!values.date) setFieldValue('date', moment().format('YYYY-MM-DD'));
+ if (!values.contractorId && contractors?.length) setFieldValue('contractorId', contractors[0]._id);
+
+ const handleAddRecord = () => setFieldValue('records', [...values.records, {
+ productId: _.map(products, '_id').reduce((acc, id) => {
+ return acc || (!_.map(values.records, 'productId').includes(id) && id);
+ }, false),
+ price: '',
+ quantity: 1,
+ }]);
+
+ const handleRemoveRecord = (index: number) => () => {
+ const records = [...values.records];
+ records.splice(index, 1);
+ setFieldValue('records', records);
+ };
+
+ return (
+ <Form id="form">
+ <Select
+ name="contractorId"
+ label="Контрагент"
+ options={contractors?.map(mapper)}
+ />
+ <div className="grid grid-cols-2">
+ <Select
+ name="operation"
+ label="Операция"
+ options={[
+ { key: 'in', label: 'Приход' },
+ { key: 'out', label: 'Расход' },
+ ]}
+ />
+ <Input name="date" type="date" label="Дата" />
+ </div>
+ {values.records.map((record: any, index: number) => (
+ <Paper variant="outlined" className="my-4 md:mx-4" key={`${index}-${record.productId}`}>
+ <Select
+ name={`records.${index}.productId`}
+ label="Товар"
+ options={products?.map(mapper)}
+ required
+ />
+ <div className="grid grid-cols-3">
+ <Input
+ name={`records.${index}.price`}
+ type="number"
+ label="Цена"
+ required
+ />
+ <Input
+ name={`records.${index}.quantity`}
+ type="number"
+ label="Количество"
+ required
+ />
+ <div className="flex justify-end items-end">
+ <Button onClick={handleRemoveRecord(index)} size="sm" variant="outlined">Удалить</Button>
+ </div>
+ </div>
+ </Paper>
+ ))}
+ <Button onClick={handleAddRecord} variant="outlined" size="sm">Добавить товар</Button>
+ </Form>
+ );
+};
+
+export default WaybillForm;
diff --git a/src/services/waybills/WaybillPanel.tsx b/src/services/waybills/WaybillPanel.tsx
new file mode 100644
index 0000000..101a871
--- /dev/null
+++ b/src/services/waybills/WaybillPanel.tsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import Button from '../../components/Button';
+import { patch, baseURL } from '../../requests';
+import { PanelProps } from '../../containers/Service/ServiceContext';
+
+
+const WaybillPanel: React.FC<PanelProps> = ({ item, mutate }) => {
+ const history = useHistory();
+
+ const handleChangeStatus = (status: any) => patch(`/waybills/${item._id}`, { status })
+ .then(() => {
+ history.push('/waybills');
+ mutate({ ...item, status });
+ });
+
+ const handlePrint = () => window.open(`${baseURL}/spreadsheets/${item._id}`, '_blank');
+
+ const handleExecute = () => handleChangeStatus('executed');
+ const handleCancel = () => handleChangeStatus('cancelled');
+
+ const executed = item.status === 'executed';
+
+ return (
+ <div className="lg:m-4 p-4 flex flex-col lg:pl-16 lg:border-l">
+ <div className="grid lg:grid-cols-2">
+ <Button route={`/contractors/${item.contractorId}`} variant="outlined">
+ Перейти к контрагенту
+ </Button>
+ <Button onClick={handlePrint} variant="outlined">
+ Печать
+ </Button>
+ <span className="text-lg text-center mt-4">Итоговая сумма: ${item.total}</span>
+ <Button onClick={executed ? handleCancel : handleExecute} size="lg">
+ {executed ? 'Откатить' : 'Провести'}
+ </Button>
+ </div>
+ </div>
+ );
+};
+
+export default WaybillPanel;
diff --git a/src/services/waybills/index.ts b/src/services/waybills/index.ts
new file mode 100644
index 0000000..f8a4be6
--- /dev/null
+++ b/src/services/waybills/index.ts
@@ -0,0 +1,27 @@
+import Form from './WaybillForm';
+import Panel from './WaybillPanel';
+import { waybillStatusNames, operationNames } from '../constants';
+
+const service = {
+ route: 'waybills',
+ name: 'Накладные',
+ nameSingular: 'Накладная',
+ tableFields: [
+ {
+ key: 'status',
+ label: 'Статус',
+ transform: (status: 'waiting' | 'executed' | 'cancelled') => waybillStatusNames[status],
+ },
+ { key: 'operation', label: 'Операция', transform: (op: 'in' | 'out') => operationNames[op] },
+ { key: 'total', label: 'Сумма' },
+ { key: 'contractor.name', label: 'Контрагент' },
+ ],
+ default: {
+ operation: 'in',
+ records: [],
+ },
+ Form,
+ Panel,
+};
+
+export default service;