Compare commits

...

14 Commits

Author SHA1 Message Date
Patrick Fic
e770232e1d Removed uneeded imports. 2021-07-08 11:45:43 -07:00
Patrick Fic
afd745917d IO-1230 remove sort on export logs for ro num 2021-07-08 11:34:39 -07:00
Patrick Fic
aa8e12ef58 IO-1248 IO-1247 Resolve nulls in system & payment search update. 2021-07-08 11:33:02 -07:00
Patrick Fic
41bbda7bcf IO-12424 Delete line to mark as removed. 2021-07-08 11:17:51 -07:00
Patrick Fic
f19289362d IO-1249 Adjust reconciliation window sizing. 2021-07-08 11:12:58 -07:00
Patrick Fic
1360a73028 IO-1245 Change Address 1 2021-07-07 16:30:05 -07:00
Patrick Fic
e9cda93898 IO-1245 Resolve QB Consistency Issue 2021-07-07 15:04:56 -07:00
Patrick Fic
2c1f5a9f34 IO-1241 Supplement Merge with discarded changes. 2021-07-06 09:45:02 -07:00
Patrick Fic
17dcc2efd8 IO-1239 Resolve extra lines on glass claim export 2021-07-05 10:35:45 -07:00
Patrick Fic
3391d7d3f4 Merged in hotfix/2021-07-02 (pull request #127)
IO-1231 Resolve dates not saving on job close.

Approved-by: Patrick Fic
2021-07-02 20:13:40 +00:00
Patrick Fic
bccb5e353b IO-1231 Resolve dates not saving on job close. 2021-07-02 13:13:19 -07:00
Patrick Fic
8e05105917 Merged in hotfix/2021-06-30 (pull request #125)
Hotfix/2021 06 30
2021-06-30 20:46:41 +00:00
Patrick Fic
81babca775 Landing page update. 2021-06-30 13:44:46 -07:00
Patrick Fic
fe8dd2a920 Landing page updates. 2021-06-30 13:44:26 -07:00
23 changed files with 255 additions and 149 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project version="1.2" be_version="2.7.1">
<babeledit_project be_version="2.7.1" version="1.2">
<!--
BabelEdit project file

View File

@@ -45,7 +45,7 @@ export default function GlobalSearch() {
<span>{`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${
job.v_model_desc || ""
}`}</span>
<span>{`${job.clm_no}`}</span>
<span>{`${job.clm_no || ""}`}</span>
</Space>
</Link>
),
@@ -91,8 +91,8 @@ export default function GlobalSearch() {
vehicle.v_make_desc || ""
} ${vehicle.v_model_desc || ""}`}
</span>
<span>{vehicle.plate_no}</span>
<span> {vehicle.v_vin}</span>
<span>{vehicle.plate_no || ""}</span>
<span> {vehicle.v_vin || ""}</span>
</Space>
</Link>
),
@@ -108,10 +108,11 @@ export default function GlobalSearch() {
label: (
<Link to={`/manage/jobs/${payment.job.id}`}>
<Space size="small" split={<Divider type="vertical" />}>
<span>{payment.paymentnum}</span>
<span>{payment.job.ro_number}</span>
<span>{payment.job.memo}</span>
<span>{payment.job.amount}</span>
<span>{payment.job.transactionid}</span>
<span>{payment.memo || ""}</span>
<span>{payment.amount || ""}</span>
<span>{payment.transactionid || ""}</span>
</Space>
</Link>
),

View File

@@ -295,18 +295,18 @@ export function JobLinesComponent({
onClick={async () => {
await deleteJobLine({
variables: { joblineId: record.id },
update(cache) {
cache.modify({
id: cache.identify(job),
fields: {
joblines(existingJobLines, { readField }) {
return existingJobLines.filter(
(jlRef) => record.id !== readField("id", jlRef)
);
},
},
});
},
// update(cache) {
// cache.modify({
// id: cache.identify(job),
// fields: {
// joblines(existingJobLines, { readField }) {
// return existingJobLines.filter(
// (jlRef) => record.id !== readField("id", jlRef)
// );
// },
// },
// });
// },
});
await axios.post("/job/totalsssu", {
id: job.id,

View File

@@ -1,4 +1,4 @@
import { Checkbox, PageHeader, Table } from "antd";
import { Checkbox, Table, Typography } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -21,6 +21,7 @@ export default function JobReconciliationBillsTable({
title: t("billlines.fields.line_desc"),
dataIndex: "line_desc",
key: "line_desc",
width: "35%",
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
sortOrder:
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
@@ -29,6 +30,8 @@ export default function JobReconciliationBillsTable({
title: t("billlines.labels.from"),
dataIndex: "from",
key: "from",
width: "20%",
ellipsis: true,
render: (text, record) =>
`${record.bill.vendor && record.bill.vendor.name} / ${
record.bill.invoice_number
@@ -57,7 +60,7 @@ export default function JobReconciliationBillsTable({
),
},
{
title: t("billlines.fields.quantity"),
title: t("joblines.fields.part_qty"),
dataIndex: "quantity",
key: "quantity",
sorter: (a, b) => a.quantity - b.quantity,
@@ -86,10 +89,12 @@ export default function JobReconciliationBillsTable({
};
return (
<PageHeader title={t("bills.labels.bills")}>
<div>
<Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title>
<Table
pagination={false}
scroll={{ y: "40vh", x: true }}
size="small"
scroll={{ y: "80vh", x: true }}
columns={columns}
rowKey="id"
dataSource={invoiceLineData}
@@ -99,6 +104,6 @@ export default function JobReconciliationBillsTable({
selectedRowKeys: selectedLines,
}}
/>
</PageHeader>
</div>
);
}

View File

@@ -22,21 +22,23 @@ export default function JobReconciliationModalComponent({ job, bills }) {
);
return (
<div>
<Row gutter={[16, 16]}>
<Col span={12}>
<JobReconciliationPartsTable
jobLineData={jobLineData}
jobLineState={jobLineState}
/>
</Col>
<Col span={12}>
<JobReconciliationBillsTable
invoiceLineData={invoiceLineData}
billLineState={billLineState}
/>
</Col>
</Row>
<div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
<div style={{ flex: 1 }}>
<Row gutter={8}>
<Col span={12}>
<JobReconciliationPartsTable
jobLineData={jobLineData}
jobLineState={jobLineState}
/>
</Col>
<Col span={12}>
<JobReconciliationBillsTable
invoiceLineData={invoiceLineData}
billLineState={billLineState}
/>
</Col>
</Row>
</div>
<Row>
<JobReconciliationTotals
jobLines={jobLineData}

View File

@@ -0,0 +1,12 @@
.imex-reconciliation-modal {
top: 20px;
.ant-modal-content {
height: 95vh;
display: flex;
flex-direction: column;
.ant-modal-body {
display: flex;
flex: 1;
}
}
}

View File

@@ -10,6 +10,7 @@ import { selectReconciliation } from "../../redux/modals/modals.selectors";
import JobReconciliationModalComponent from "./job-reconciliation-modal.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import AlertComponent from "../alert/alert.component";
import "./job-reconciliation-modal.styles.scss";
const mapStateToProps = createStructuredSelector({
reconciliationModal: selectReconciliation,
@@ -38,23 +39,23 @@ function JobReconciliationModalContainer({
return (
<Modal
title={t("jobs.labels.reconciliationheader")}
width={"90%"}
width={"95%"}
visible={visible}
okText={t("general.actions.close")}
onOk={handleCancel}
onCancel={handleCancel}
cancelButtonProps={{ display: "none" }}
destroyOnClose
className="imex-reconciliation-modal"
>
<LoadingSpinner loading={loading}>
{error && <AlertComponent message={error.message} type="error" />}
{data && (
<JobReconciliationModalComponent
job={data && data.jobs_by_pk}
bills={data && data.bills}
/>
)}
</LoadingSpinner>
{loading && <LoadingSpinner loading={loading} />}
{error && <AlertComponent message={error.message} type="error" />}
{data && (
<JobReconciliationModalComponent
job={data && data.jobs_by_pk}
bills={data && data.bills}
/>
)}
</Modal>
);
}

View File

@@ -1,4 +1,4 @@
import { PageHeader, Table } from "antd";
import { Table, Typography } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -102,11 +102,13 @@ export default function JobReconcilitionPartsTable({
};
return (
<PageHeader title={t("jobs.labels.lines")}>
<div>
<Typography.Title level={4}>{t("jobs.labels.lines")}</Typography.Title>
<Table
pagination={false}
columns={columns}
scroll={{ y: "40vh", x: true }}
size="small"
scroll={{ y: "80vh", x: true }}
rowKey="id"
dataSource={jobLineData}
onChange={handleTableChange}
@@ -122,6 +124,6 @@ export default function JobReconcilitionPartsTable({
<div style={{ fontStyle: "italic", margin: "4px" }}>
{t("jobs.labels.reconciliation.removedpartsstrikethrough")}
</div>
</PageHeader>
</div>
);
}

View File

@@ -0,0 +1,57 @@
import { DownCircleFilled } from "@ant-design/icons";
import { useMutation } from "@apollo/client";
import { Button, Dropdown, Menu, notification } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { UPDATE_JOB_STATUS } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminStatus);
export function JobsAdminStatus({ bodyshop, job }) {
const { t } = useTranslation();
const [mutationUpdateJobstatus] = useMutation(UPDATE_JOB_STATUS);
const updateJobStatus = (status) => {
mutationUpdateJobstatus({
variables: { jobId: job.id, status: status },
})
.then((r) => {
notification["success"]({ message: t("jobs.successes.save") });
// refetch();
})
.catch((error) => {
notification["error"]({ message: t("jobs.errors.saving") });
});
};
const statusmenu = (
<Menu
onClick={(e) => {
updateJobStatus(e.key);
}}
>
{bodyshop.md_ro_statuses.statuses.map((item) => (
<Menu.Item key={item}>{item}</Menu.Item>
))}
</Menu>
);
return (
<Dropdown overlay={statusmenu} trigger={["click"]} key="changestatus">
<Button shape="round">
<span>{job.status}</span>
<DownCircleFilled />
</Button>
</Dropdown>
);
}

View File

@@ -11,6 +11,7 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
query: GET_ALL_JOBLINES_BY_PK,
variables: { id: jobId },
});
const existingLines = _.cloneDeep(existingLinesFromDb);
const linesToInsert = [];
const linesToUpdate = [];
@@ -19,11 +20,14 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
const matchingIndex = existingLines.findIndex(
(eL) => eL.unq_seq === newLine.unq_seq
);
//Should do a check to make sure there is only 1 matching unq sequence number.
if (matchingIndex >= 0) {
//Found a relevant matching line. Add it to lines to update.
linesToUpdate.push({
id: existingLines[matchingIndex].id,
newData: newLine,
newData: { ...newLine, removed: false },
});
//Splice out item we found for performance.

View File

@@ -31,11 +31,14 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
title: t("jobs.fields.vehicle"),
dataIndex: "vehicleid",
key: "vehicleid",
render: (text, record) => (
<Link to={`/manage/vehicles/${record.vehicleid}`}>
{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc}`}
</Link>
),
render: (text, record) =>
record.vehicleid ? (
<Link to={`/manage/vehicles/${record.vehicleid}`}>
{`${record.v_model_yr} ${record.v_make_desc} ${record.v_model_desc}`}
</Link>
) : (
t("jobs.errors.novehicle")
),
},
{
title: t("jobs.fields.clm_no"),

View File

@@ -23,19 +23,6 @@ export const GET_ALL_JOBLINES_BY_PK = gql`
notes
location
tax_part
parts_order_lines {
id
parts_order {
id
order_number
order_date
user_email
vendor {
id
name
}
}
}
}
}
`;
@@ -228,7 +215,11 @@ export const generateJobLinesUpdatesForInvoicing = (joblines) => {
export const DELETE_JOB_LINE_BY_PK = gql`
mutation DELETE_JOB_LINE_BY_PK($joblineId: uuid!) {
delete_joblines_by_pk(id: $joblineId) {
update_joblines_by_pk(
pk_columns: { id: $joblineId }
_set: { removed: true }
) {
removed
id
}
}

View File

@@ -36,6 +36,7 @@ export const GLOBAL_SEARCH_QUERY = gql`
search_payments(args: { search: $search }) {
id
amount
paymentnum
job {
ro_number
id

View File

@@ -81,48 +81,52 @@ export default class Home extends React.Component {
dataSource={Banner00DataSource}
isMobile={this.state.isMobile}
/>,
// <Content4
// id="Content4_0"
// key="Content4_0"
// dataSource={Content40DataSource}
// isMobile={this.state.isMobile}
// />,
<Content1
id="Content1_0"
key="Content1_0"
dataSource={Content10DataSource}
isMobile={this.state.isMobile}
/>,
<Content0
id="Content0_0"
key="Content0_0"
dataSource={Content00DataSource}
isMobile={this.state.isMobile}
/>,
<Pricing2
id="Pricing2_0"
key="Pricing2_0"
dataSource={Pricing20DataSource}
isMobile={this.state.isMobile}
/>,
// <Pricing1
// id="Pricing1_1"
// key="Pricing1_1"
// dataSource={Pricing11DataSource}
// isMobile={this.state.isMobile}
// />,
// <Content3
// id="Content3_0"
// key="Content3_0"
// dataSource={Content30DataSource}
// isMobile={this.state.isMobile}
// />,
// <Content12
// id="Content12_0"
// key="Content12_0"
// dataSource={Content120DataSource}
// isMobile={this.state.isMobile}
// />,
...(process.env.NODE_ENV !== "production"
? [
// <Content4
// id="Content4_0"
// key="Content4_0"
// dataSource={Content40DataSource}
// isMobile={this.state.isMobile}
// />,
<Content1
id="Content1_0"
key="Content1_0"
dataSource={Content10DataSource}
isMobile={this.state.isMobile}
/>,
<Content0
id="Content0_0"
key="Content0_0"
dataSource={Content00DataSource}
isMobile={this.state.isMobile}
/>,
<Pricing2
id="Pricing2_0"
key="Pricing2_0"
dataSource={Pricing20DataSource}
isMobile={this.state.isMobile}
/>,
// <Pricing1
// id="Pricing1_1"
// key="Pricing1_1"
// dataSource={Pricing11DataSource}
// isMobile={this.state.isMobile}
// />,
// <Content3
// id="Content3_0"
// key="Content3_0"
// dataSource={Content30DataSource}
// isMobile={this.state.isMobile}
// />,
// <Content12
// id="Content12_0"
// key="Content12_0"
// dataSource={Content120DataSource}
// isMobile={this.state.isMobile}
// />,
]
: []),
<Footer1
id="Footer1_0"
key="Footer1_0"

View File

@@ -12,7 +12,6 @@ import AlertComponent from "../../components/alert/alert.component";
import { QUERY_EXPORT_LOG_PAGINATED } from "../../graphql/accounting.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -79,12 +78,10 @@ export function ExportLogsPageComponent({ bodyshop }) {
title: t("jobs.fields.ro_number"),
dataIndex: "ro_number",
key: "ro_number",
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
sortOrder: sortcolumn === "ro_number" && sortorder,
render: (text, record) =>
record.job && (
<Link to={"/manage/jobs/" + record.job && record.job.id}>
<Link to={`/manage/jobs/${record.job.id}`}>
{(record.job && record.job.ro_number) || t("general.labels.na")}
</Link>
),

View File

@@ -15,6 +15,8 @@ import JobAdminOwnerReassociate from "../../components/jobs-admin-owner-reassoci
import JobsAdminUnvoid from "../../components/jobs-admin-unvoid/jobs-admin-unvoid.component";
import JobAdminVehicleReassociate from "../../components/jobs-admin-vehicle-reassociate/jobs-admin-vehicle-reassociate.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import JobsAdminStatus from "../../components/jobs-admin-change-status/jobs-admin-change.status.component";
import NotFound from "../../components/not-found/not-found.component";
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import { GET_JOB_BY_PK } from "../../graphql/jobs.queries";
@@ -96,6 +98,7 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader }) {
<JobsAdminDeleteIntake job={data ? data.jobs_by_pk : {}} />
<JobsAdminMarkReexport job={data ? data.jobs_by_pk : {}} />
<JobsAdminUnvoid job={data ? data.jobs_by_pk : {}} />
<JobsAdminStatus job={data ? data.jobs_by_pk : {}} />
</Space>
</Card>
</Col>

View File

@@ -42,9 +42,26 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
setLoading(true);
const result = await client.mutate({
mutation: generateJobLinesUpdatesForInvoicing(values.joblines),
});
if (result.errors) {
return; // Abandon the rest of the close.
}
const closeResult = await closeJob({
variables: {
jobId: job.id,
job: {
status: bodyshop.md_ro_statuses.default_invoiced || "",
date_invoiced: new Date(),
actual_in: values.actual_in,
actual_completion: values.actual_completion,
actual_delivery: values.actual_delivery,
},
},
refetchQueries: ["QUERY_JOB_CLOSE_DETAILS"],
awaitRefetchQueries: true,
});
if (!result.errors) {
notification["success"]({ message: t("jobs.successes.save") });
// form.resetFields();
@@ -56,18 +73,6 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
});
return; // Abandon the rest of the close.
}
form.resetFields();
form.resetFields();
const closeResult = await closeJob({
variables: {
jobId: job.id,
job: {
status: bodyshop.md_ro_statuses.default_invoiced || "",
date_invoiced: new Date(),
},
},
});
if (!closeResult.errors) {
setLoading(false);
@@ -84,6 +89,8 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
}),
});
}
form.resetFields();
form.resetFields();
setLoading(false);
};

View File

@@ -1441,11 +1441,11 @@
"name": "ImEX Online",
"status": "System Status"
},
"slogan": "The future of shop management systems. "
"slogan": "A whole new kind of shop management system."
},
"hero": {
"button": "Learn More",
"title": "Bringing the future to the collision repair process."
"button": "Coming Soon",
"title": "A whole new kind of shop management system."
},
"labels": {
"features": "Features",

View File

@@ -0,0 +1 @@
[]

View File

@@ -0,0 +1,11 @@
- args:
cascade: false
read_only: false
sql: "CREATE OR REPLACE FUNCTION public.search_payments(search text)\n RETURNS
SETOF payments\n LANGUAGE plpgsql\n STABLE\nAS $function$\n\nBEGIN\n if search
= '' then\n return query select * from payments ;\n else \n return query
SELECT\n p.*\nFROM\n payments p, jobs j\nWHERE\np.jobid = j.id AND\n(\nsearch
<% p.paymentnum OR\nsearch <% j.ownr_fn OR\nsearch <% j.ownr_ln OR\nsearch <%
j.ownr_co_nm OR\nsearch <% j.ro_number OR\n search <% (p.payer) OR\n search
<% (p.transactionid) OR\n search <% (p.memo));\n end if;\n\n\tEND\n$function$;"
type: run_sql

View File

@@ -288,7 +288,7 @@ const generateInvoiceQbxml = (
});
// console.log("Done creating hash", JSON.stringify(invoiceLineHash));
if (!hasMapaLine) {
if (!hasMapaLine && jobs_by_pk.job_totals.rates.mapa.total.amount > 0) {
console.log("Adding MAPA Line Manually.");
const mapaAccountName = responsibilityCenters.defaults.profits.MAPA;
@@ -313,7 +313,7 @@ const generateInvoiceQbxml = (
}
}
if (!hasMashLine) {
if (!hasMashLine && jobs_by_pk.job_totals.rates.mash.total.amount > 0) {
console.log("Adding MASH Line Manually.");
const mashAccountName = responsibilityCenters.defaults.profits.MASH;
@@ -424,9 +424,11 @@ const generateInvoiceQbxml = (
TxnDate: moment(jobs_by_pk.date_invoiced).format("YYYY-MM-DD"),
RefNumber: jobs_by_pk.ro_number,
ShipAddress: {
Addr1: `${jobs_by_pk.ownr_fn || ""} ${jobs_by_pk.ownr_ln || ""} ${
jobs_by_pk.ownr_co_nm || ""
}`,
Addr1: jobs_by_pk.ownr_co_nm
? jobs_by_pk.ownr_co_nm.substring(0, 30)
: `${`${jobs_by_pk.ownr_ln || ""} ${
jobs_by_pk.ownr_fn || ""
}`.substring(0, 30)}`,
Addr2: jobs_by_pk.ownr_addr1,
Addr3: jobs_by_pk.ownr_addr2,
City: jobs_by_pk.ownr_city,

View File

@@ -17,12 +17,13 @@ exports.generateOwnerTier = (jobs_by_pk, isThreeTier, twotierpref) => {
if (isThreeTier) {
//It's always gonna be the owner now. Same as 2 tier by name
return jobs_by_pk.ownr_co_nm
? `${jobs_by_pk.ownr_co_nm} - ${jobs_by_pk.ownr_ln || ""} ${
jobs_by_pk.ownr_fn || ""
} #${jobs_by_pk.owner.accountingid || ""}`
: `${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""} #${
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
jobs_by_pk.owner.accountingid || ""
}`;
}`
: `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`.substring(
0,
30
)} #${jobs_by_pk.owner.accountingid || ""}`;
} else {
//What's the 2 tier pref?
if (twotierpref === "source") {
@@ -31,12 +32,12 @@ exports.generateOwnerTier = (jobs_by_pk, isThreeTier, twotierpref) => {
} else {
//Same as 3 tier
return jobs_by_pk.ownr_co_nm
? `${jobs_by_pk.ownr_co_nm} - ${jobs_by_pk.ownr_ln || ""} ${
jobs_by_pk.ownr_fn || ""
} #${jobs_by_pk.owner.accountingid || ""}`
: `${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""} #${
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
jobs_by_pk.owner.accountingid || ""
}`;
}`
: `${`${jobs_by_pk.ownr_ln || ""} ${
jobs_by_pk.ownr_fn || ""
}`.substring(0, 30)} #${jobs_by_pk.owner.accountingid || ""}`;
}
}
};

View File

@@ -57,6 +57,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
ownerid
ownr_ln
ownr_fn
ownr_co_nm
ownr_addr1
ownr_addr2
ownr_zip