diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 9831a14ef..b854e8eff 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -1747,6 +1747,194 @@ + + invoices + + + errors + + + invalidro + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + invalidvendor + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + fields + + + date + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + invoice_number + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + is_credit_memo + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + ro_number + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + vendor + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + labels + + + new + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + joblines diff --git a/client/src/components/invoice-enter-modal/invoice-enter-modal.component.jsx b/client/src/components/invoice-enter-modal/invoice-enter-modal.component.jsx index 387290e7f..bbccfd0d5 100644 --- a/client/src/components/invoice-enter-modal/invoice-enter-modal.component.jsx +++ b/client/src/components/invoice-enter-modal/invoice-enter-modal.component.jsx @@ -1,4 +1,4 @@ -import { Modal, Form, Input, InputNumber } from "antd"; +import { Modal, Form, Input, Switch, DatePicker, AutoComplete } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; import ResetForm from "../form-items-formatted/reset-form-item.component"; @@ -8,26 +8,95 @@ export default function InvoiceEnterModalComponent({ invoice, handleCancel, handleSubmit, - form + form, + handleRoAutoComplete, + roAutoCompleteOptions, + handleVendorAutoComplete, + vendorAutoCompleteOptions }) { const { t } = useTranslation(); const { getFieldDecorator, isFieldsTouched, resetFields } = form; + console.log("invoice", invoice); return ( {isFieldsTouched() ? : null}
- {JSON.stringify(invoice)} + + {getFieldDecorator("jobid", { + rules: [ + { + required: true, + pattern: new RegExp( + "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" + ), + message: t("invoices.errors.invalidro") + } + ] + })( + { + console.log("props", props); + }} + /> + )} + + + {getFieldDecorator("vendorid", { + rules: [ + { + required: true, + pattern: new RegExp( + "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" + ), + message: t("invoices.errors.invalidvendor") + } + ] + })( + + )} + +
+ + {getFieldDecorator( + "invoice_number", + {} + )()} + + + {getFieldDecorator("date", {})()} + + + {getFieldDecorator("is_credit_memo", { + initialValue: false, + valuePropName: "checked" + })()} + +
+ { // // {getFieldDecorator("line_desc", { diff --git a/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx b/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx index 5526af420..32bcd0b0c 100644 --- a/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx +++ b/client/src/components/invoice-enter-modal/invoice-enter-modal.container.jsx @@ -1,6 +1,6 @@ import { Form, notification } from "antd"; -import React from "react"; -import { useMutation } from "react-apollo"; +import React, { useState } from "react"; +import { useQuery } from "react-apollo"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -11,6 +11,8 @@ import { import { toggleModalVisible } from "../../redux/modals/modals.actions"; import { selectInvoiceEnterModal } from "../../redux/modals/modals.selectors"; import InvoiceEnterModalComponent from "./invoice-enter-modal.component"; +import { SEARCH_RO_AUTOCOMPLETE } from "../../graphql/jobs.queries"; +import { SEARCH_VENDOR_AUTOCOMPLETE } from "../../graphql/vendors.queries"; const mapStateToProps = createStructuredSelector({ invoiceEnterModal: selectInvoiceEnterModal @@ -25,12 +27,34 @@ function InvoiceEnterModalContainer({ form }) { const { t } = useTranslation(); - // const [insertJobLine] = useMutation(INSERT_NEW_JOB_LINE); - // const [updateJobLine] = useMutation(UPDATE_JOB_LINE); + + const roSearchState = useState(""); + const [roSearch, setRoSearch] = roSearchState; + const handleRoAutoComplete = e => { + setRoSearch(e); + }; + const { data: RoAutoCompleteData } = useQuery(SEARCH_RO_AUTOCOMPLETE, { + fetchPolicy: "network-only", + variables: { search: `%${roSearch}%` }, + skip: !roSearch + }); + + const vendorSearchState = useState(""); + const [vendorSearch, setVendorSearch] = vendorSearchState; + const handleVendorAutoComplete = e => { + setVendorSearch(e); + }; + const { data: VendorAutoCompleteData } = useQuery( + SEARCH_VENDOR_AUTOCOMPLETE, + { + fetchPolicy: "network-only", + variables: { search: `%${vendorSearch}%` }, + skip: !vendorSearch + } + ); const handleSubmit = e => { e.preventDefault(); - form.validateFieldsAndScroll((err, values) => { if (err) { notification["error"]({ @@ -39,6 +63,7 @@ function InvoiceEnterModalContainer({ }); } if (!err) { + console.log("values", values); alert("Closing this modal."); toggleModalVisible(); // if (!jobLineEditModal.context.id) { @@ -100,6 +125,33 @@ function InvoiceEnterModalContainer({ handleSubmit={handleSubmit} handleCancel={handleCancel} form={form} + handleRoAutoComplete={handleRoAutoComplete} + roAutoCompleteOptions={ + RoAutoCompleteData + ? RoAutoCompleteData.jobs.reduce((acc, value) => { + acc.push({ + value: value.id, + text: `${value.ro_number || ""} | ${value.ownr_ln || + ""} ${value.ownr_fn || ""} | ${value.vehicle.v_model_yr || + ""} ${value.vehicle.v_make_desc || ""} ${value.vehicle + .v_model_desc || ""}` + }); + return acc; + }, []) + : null + } + handleVendorAutoComplete={handleVendorAutoComplete} + vendorAutoCompleteOptions={ + VendorAutoCompleteData + ? VendorAutoCompleteData.vendors.reduce((acc, value) => { + acc.push({ + value: value.id, + text: `${value.name || ""}` + }); + return acc; + }, []) + : null + } /> ); } diff --git a/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx b/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx index 6dbe28a0a..7f29af510 100644 --- a/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx +++ b/client/src/components/jobs-detail-pli/jobs-detail-pli.component.jsx @@ -5,6 +5,7 @@ import { toggleModalVisible, setModalContext } from "../../redux/modals/modals.actions"; +import { Button } from "antd"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -24,7 +25,7 @@ export default connect( }) { return (
-
{ setInvoiceEnterContext({ actions: { refetch: null }, @@ -35,7 +36,7 @@ export default connect( }} > Enter Invoice -
+
); }); diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js index ba32b39ab..f402d6278 100644 --- a/client/src/graphql/jobs.queries.js +++ b/client/src/graphql/jobs.queries.js @@ -333,3 +333,20 @@ export const UPDATE_JOB_STATUS = gql` } } `; + +export const SEARCH_RO_AUTOCOMPLETE = gql` + query SEARCH_RO_AUTOCOMPLETE($search: String!) { + jobs(where: { ro_number: { _ilike: $search } }) { + id + ownr_fn + ownr_ln + ro_number + vehicle { + id + v_make_desc + v_model_desc + v_model_yr + } + } + } +`; diff --git a/client/src/graphql/vendors.queries.js b/client/src/graphql/vendors.queries.js index 4cf45ebd6..bf61bc670 100644 --- a/client/src/graphql/vendors.queries.js +++ b/client/src/graphql/vendors.queries.js @@ -76,3 +76,14 @@ export const QUERY_ALL_VENDORS_FOR_ORDER = gql` } } `; + +export const SEARCH_VENDOR_AUTOCOMPLETE = gql` + query SEARCH_VENDOR_AUTOCOMPLETE($search: String!) { + vendors(where: { name: { _ilike: $search } }) { + name + discount + id + cost_center + } + } +`; diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index abee6521b..8bc222578 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -144,6 +144,22 @@ "required": "This field is required. " } }, + "invoices": { + "errors": { + "invalidro": "Not a valid RO.", + "invalidvendor": "Not a valid vendor." + }, + "fields": { + "date": "Invoice Date", + "invoice_number": "Invoice Number", + "is_credit_memo": "Credit Memo?", + "ro_number": "RO Number", + "vendor": "Vendor" + }, + "labels": { + "new": "New Invoice" + } + }, "joblines": { "actions": { "new": "New Line" diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index b5a22f871..accf712d2 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -144,6 +144,22 @@ "required": "Este campo es requerido." } }, + "invoices": { + "errors": { + "invalidro": "", + "invalidvendor": "" + }, + "fields": { + "date": "", + "invoice_number": "", + "is_credit_memo": "", + "ro_number": "", + "vendor": "" + }, + "labels": { + "new": "" + } + }, "joblines": { "actions": { "new": "" diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index df942272d..ca3ce145a 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -144,6 +144,22 @@ "required": "Ce champ est requis." } }, + "invoices": { + "errors": { + "invalidro": "", + "invalidvendor": "" + }, + "fields": { + "date": "", + "invoice_number": "", + "is_credit_memo": "", + "ro_number": "", + "vendor": "" + }, + "labels": { + "new": "" + } + }, "joblines": { "actions": { "new": ""