Refactored how in house invoices are created IO-460

This commit is contained in:
Patrick Fic
2021-01-08 11:40:32 -08:00
parent 3ca416c5cf
commit 6f96bcfa7e
15 changed files with 323 additions and 41 deletions

View File

@@ -183,7 +183,10 @@ function BillEnterModalContainer({
0, 0,
}} }}
> >
<BillFormContainer form={form} /> <BillFormContainer
form={form}
disableInvNumber={billEnterModal.context.disableInvNumber}
/>
</Form> </Form>
</Modal> </Modal>
); );

View File

@@ -39,6 +39,7 @@ export function BillFormComponent({
responsibilityCenters, responsibilityCenters,
loadLines, loadLines,
billEdit, billEdit,
disableInvNumber,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const client = useApolloClient(); const client = useApolloClient();
@@ -142,7 +143,15 @@ export function BillFormComponent({
}), }),
]} ]}
> >
<Input disabled={disabled} /> <Input disabled={disabled || disableInvNumber} />
</Form.Item>
<Form.Item
// label={t("bills.fields.isinhouse")}
style={{ display: "none" }}
name="isinhouse"
valuePropName="checked"
>
<Switch />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("bills.fields.date")} label={t("bills.fields.date")}
@@ -193,7 +202,6 @@ export function BillFormComponent({
> >
<CurrencyInput min={0} /> <CurrencyInput min={0} />
</Form.Item> </Form.Item>
<Form.Item label={t("bills.fields.allpartslocation")} name="location"> <Form.Item label={t("bills.fields.allpartslocation")} name="location">
<Select style={{ width: "10rem" }} disabled={disabled}> <Select style={{ width: "10rem" }} disabled={disabled}>
{bodyshop.md_parts_locations.map((loc, idx) => ( {bodyshop.md_parts_locations.map((loc, idx) => (

View File

@@ -11,7 +11,13 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
}); });
export function BillFormContainer({ bodyshop, form, billEdit, disabled }) { export function BillFormContainer({
bodyshop,
form,
billEdit,
disabled,
disableInvNumber,
}) {
const { data: VendorAutoCompleteData } = useQuery(SEARCH_VENDOR_AUTOCOMPLETE); const { data: VendorAutoCompleteData } = useQuery(SEARCH_VENDOR_AUTOCOMPLETE);
const [loadLines, { data: lineData }] = useLazyQuery( const [loadLines, { data: lineData }] = useLazyQuery(
@@ -29,6 +35,7 @@ export function BillFormContainer({ bodyshop, form, billEdit, disabled }) {
loadLines={loadLines} loadLines={loadLines}
lineData={lineData ? lineData.joblines : []} lineData={lineData ? lineData.joblines : []}
responsibilityCenters={bodyshop.md_responsibility_centers || null} responsibilityCenters={bodyshop.md_responsibility_centers || null}
disableInvNumber={disableInvNumber}
/> />
); );
} }

View File

@@ -81,6 +81,7 @@ export default function PartsOrderModalComponent({
> >
<Input /> <Input />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("parts_orders.fields.act_price")} label={t("parts_orders.fields.act_price")}
key={`${index}act_price`} key={`${index}act_price`}

View File

@@ -1,29 +1,31 @@
import { useMutation, useQuery } from "@apollo/react-hooks"; import { useMutation, useQuery } from "@apollo/react-hooks";
import { Form, Modal, notification } from "antd"; import { Form, Modal, notification } from "antd";
import moment from "moment";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { INSERT_NEW_BILL } from "../../graphql/bills.queries"; import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries"; import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries";
import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries"; import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries";
import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries"; import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries";
import { setEmailOptions } from "../../redux/email/email.actions"; import { setEmailOptions } from "../../redux/email/email.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions"; import {
setModalContext,
toggleModalVisible,
} from "../../redux/modals/modals.actions";
import { selectPartsOrder } from "../../redux/modals/modals.selectors"; import { selectPartsOrder } from "../../redux/modals/modals.selectors";
import { import {
selectBodyshop, selectBodyshop,
selectCurrentUser, selectCurrentUser,
} from "../../redux/user/user.selectors"; } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import PartsOrderModalComponent from "./parts-order-modal.component";
import RenderTemplate, { import RenderTemplate, {
displayTemplateInWindow, displayTemplateInWindow,
} from "../../utils/RenderTemplate"; } from "../../utils/RenderTemplate";
import moment from "moment";
import { TemplateList } from "../../utils/TemplateConstants"; import { TemplateList } from "../../utils/TemplateConstants";
import { logImEXEvent } from "../../firebase/firebase.utils"; import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import PartsOrderModalComponent from "./parts-order-modal.component";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser, currentUser: selectCurrentUser,
@@ -34,6 +36,8 @@ const mapStateToProps = createStructuredSelector({
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setEmailOptions: (e) => dispatch(setEmailOptions(e)), setEmailOptions: (e) => dispatch(setEmailOptions(e)),
toggleModalVisible: () => dispatch(toggleModalVisible("partsOrder")), toggleModalVisible: () => dispatch(toggleModalVisible("partsOrder")),
setBillEnterContext: (context) =>
dispatch(setModalContext({ context: context, modal: "billEnter" })),
}); });
export function PartsOrderModalContainer({ export function PartsOrderModalContainer({
@@ -42,6 +46,7 @@ export function PartsOrderModalContainer({
currentUser, currentUser,
bodyshop, bodyshop,
setEmailOptions, setEmailOptions,
setBillEnterContext,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -68,7 +73,6 @@ export function PartsOrderModalContainer({
const [insertPartOrder] = useMutation(INSERT_NEW_PARTS_ORDERS); const [insertPartOrder] = useMutation(INSERT_NEW_PARTS_ORDERS);
const [updateJobLines] = useMutation(UPDATE_JOB_LINE_STATUS); const [updateJobLines] = useMutation(UPDATE_JOB_LINE_STATUS);
const [insertBill] = useMutation(INSERT_NEW_BILL);
const handleFinish = async (values) => { const handleFinish = async (values) => {
logImEXEvent("parts_order_insert"); logImEXEvent("parts_order_insert");
@@ -113,37 +117,37 @@ export function PartsOrderModalContainer({
}); });
if (values.vendorid === bodyshop.inhousevendorid) { if (values.vendorid === bodyshop.inhousevendorid) {
logImEXEvent("parts_order_inhouse_invoice"); setBillEnterContext({
actions: { refetch: refetch },
let invoiceToPost = { context: {
vendorid: bodyshop.inhousevendorid, disableInvNumber: true,
isinhouse: true, job: { id: jobId },
jobid: jobId, bill: {
total: 0, vendorid: bodyshop.inhousevendorid,
invoice_number: "ih", invoice_number: "ih",
federal_tax_rate: bodyshop.bill_tax_rates.federal_tax_rate || 0, isinhouse: true,
state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate || 0, date: new moment(),
local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate || 0, billlines: values.parts_order_lines.data.map((p) => {
billlines: { return {
data: values.parts_order_lines.data.map((p) => { joblineid: p.job_line_id,
return { actual_price: p.act_price,
joblineid: p.job_line_id, actual_cost: p.act_price,
actual_price: p.act_price, line_desc: p.line_desc,
actual_cost: p.act_price, line_remarks: p.line_remarks,
line_desc: p.line_desc, part_type: p.part_type,
line_remarks: p.line_remarks, quantity: p.quantity || 1,
quantity: p.quantity || 1, applicable_taxes: {
cost_center: local: false,
bodyshop.md_responsibility_centers.defaults.costs.PAO || state: p.tax_part,
"Other*", federal: true,
}; },
}), };
}),
},
}, },
};
await insertBill({
variables: { bill: invoiceToPost },
}); });
toggleModalVisible();
return;
} }
if (refetch) refetch(); if (refetch) refetch();

View File

@@ -22,6 +22,7 @@ export const GET_JOB_LINES_BY_PK = gql`
status status
notes notes
location location
tax_part
parts_order_lines { parts_order_lines {
id id
parts_order { parts_order {

View File

@@ -0,0 +1,5 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."parts_order_lines" DROP COLUMN "part_type";
type: run_sql

View File

@@ -0,0 +1,5 @@
- args:
cascade: false
read_only: false
sql: ALTER TABLE "public"."parts_order_lines" ADD COLUMN "part_type" text NULL;
type: run_sql

View File

@@ -0,0 +1,40 @@
- args:
role: user
table:
name: parts_order_lines
schema: public
type: drop_insert_permission
- args:
permission:
check:
parts_order:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- act_price
- backordered_eta
- backordered_on
- created_at
- db_price
- id
- job_line_id
- line_desc
- line_remarks
- oem_partno
- orderid
- quantity
- status
- updated_at
set: {}
role: user
table:
name: parts_order_lines
schema: public
type: create_insert_permission

View File

@@ -0,0 +1,41 @@
- args:
role: user
table:
name: parts_order_lines
schema: public
type: drop_insert_permission
- args:
permission:
check:
parts_order:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- act_price
- backordered_eta
- backordered_on
- created_at
- db_price
- id
- job_line_id
- line_desc
- line_remarks
- oem_partno
- orderid
- part_type
- quantity
- status
- updated_at
set: {}
role: user
table:
name: parts_order_lines
schema: public
type: create_insert_permission

View File

@@ -0,0 +1,41 @@
- args:
role: user
table:
name: parts_order_lines
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- act_price
- backordered_eta
- backordered_on
- created_at
- db_price
- id
- job_line_id
- line_desc
- line_remarks
- oem_partno
- orderid
- quantity
- status
- updated_at
computed_fields: []
filter:
parts_order:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
role: user
table:
name: parts_order_lines
schema: public
type: create_select_permission

View File

@@ -0,0 +1,42 @@
- args:
role: user
table:
name: parts_order_lines
schema: public
type: drop_select_permission
- args:
permission:
allow_aggregations: false
columns:
- act_price
- backordered_eta
- backordered_on
- created_at
- db_price
- id
- job_line_id
- line_desc
- line_remarks
- oem_partno
- orderid
- part_type
- quantity
- status
- updated_at
computed_fields: []
filter:
parts_order:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
role: user
table:
name: parts_order_lines
schema: public
type: create_select_permission

View File

@@ -0,0 +1,40 @@
- args:
role: user
table:
name: parts_order_lines
schema: public
type: drop_update_permission
- args:
permission:
columns:
- act_price
- backordered_eta
- backordered_on
- created_at
- db_price
- id
- job_line_id
- line_desc
- line_remarks
- oem_partno
- orderid
- quantity
- status
- updated_at
filter:
parts_order:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
set: {}
role: user
table:
name: parts_order_lines
schema: public
type: create_update_permission

View File

@@ -0,0 +1,41 @@
- args:
role: user
table:
name: parts_order_lines
schema: public
type: drop_update_permission
- args:
permission:
columns:
- act_price
- backordered_eta
- backordered_on
- created_at
- db_price
- id
- job_line_id
- line_desc
- line_remarks
- oem_partno
- orderid
- part_type
- quantity
- status
- updated_at
filter:
parts_order:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
set: {}
role: user
table:
name: parts_order_lines
schema: public
type: create_update_permission

View File

@@ -3241,6 +3241,7 @@ tables:
- line_remarks - line_remarks
- oem_partno - oem_partno
- orderid - orderid
- part_type
- quantity - quantity
- status - status
- updated_at - updated_at
@@ -3259,6 +3260,7 @@ tables:
- line_remarks - line_remarks
- oem_partno - oem_partno
- orderid - orderid
- part_type
- quantity - quantity
- status - status
- updated_at - updated_at
@@ -3288,6 +3290,7 @@ tables:
- line_remarks - line_remarks
- oem_partno - oem_partno
- orderid - orderid
- part_type
- quantity - quantity
- status - status
- updated_at - updated_at