Compare commits

...

11 Commits

Author SHA1 Message Date
Allan Carr
59db305cb8 IO-2186 Production Over Time
Add new report requested by Loewen Body Shop
2023-02-23 11:14:00 -08:00
Patrick Fic
fea69fe3a5 Add payment response object. 2023-02-22 08:15:58 -08:00
Patrick Fic
43e4ff911e Merged in release/2023-02-17 (pull request #679)
Release/2023 02 17
2023-02-17 23:39:24 +00:00
Allan Carr
ae4cff98e7 IO-2175 Category Dropdown Clear
Allow for clear and correct for Select allowClear sending undefined and convert that to null. Overload UndefinedtoNull to have an array of keys
2023-02-16 17:26:57 -08:00
Allan Carr
3650cacb51 IO-2173 Job Line Discount
Correct for when new line is added with no part
2023-02-16 17:23:09 -08:00
Patrick Fic
c2bf6841e1 Documentation updates. 2023-02-14 15:05:09 -08:00
Allan Carr
f41b94d16d Merge branch 'release/2023-02-17' of https://bitbucket.org/snaptsoft/bodyshop into release/2023-02-17 2023-02-14 11:32:21 -08:00
Allan Carr
24da0207e5 IO-2173 Client Fusion - Job Line Discount not allowed
Adjust client job-line-upsert-modal to allow for discounts as markups were only allowed before. Convert prt_dsmk_p over to prt_dsmk_m on save of modal for both markup/discount for handling and viewing
2023-02-14 11:30:09 -08:00
Patrick Fic
bf34765e6b Additional Hasura Indexes. 2023-02-13 11:21:59 -08:00
Patrick Fic
4c98a347f5 Additional indexes for performance improvements. 2023-02-13 10:37:10 -08:00
Patrick Fic
840e760619 Merged in release/2023-02-10 (pull request #675)
Release/2023 02 10
2023-02-10 23:34:55 +00:00
62 changed files with 195 additions and 19 deletions

View File

@@ -1,14 +1,3 @@
Yarn Dependency Management:
To force upgrades for some packages:
yarn upgrade-interactive --latest
To Start Hasura CLI:
npx hasura console
Migrating to Staging:
npx hasura migrate apply --endpoint https://db.imex.online/ --admin-secret 'Production-ImEXOnline!@#'
npx hasura migrate apply --endpoint https://db.test.bodyshop.app/ --admin-secret 'Test-ImEXOnlineBySnaptSoftware!'
NGROK TEsting:
./ngrok.exe http http://localhost:4000 -host-header="localhost:4000"
@@ -21,4 +10,4 @@ hasura migrate apply --version "1620771761757" --skip-execution --endpoint https
hasura migrate status --endpoint https://db.imex.online/ --admin-secret 'Production-ImEXOnline!@#'
Generate the license file:
$ generate-license-file --input package.json --output third-party-licenses.txt --overwrite
$ generate-license-file --input package.json --output third-party-licenses.txt --overwrite

View File

@@ -289,7 +289,7 @@ export function JobLinesUpsertModalComponent({
name="prt_dsmk_p"
initialValue={0}
>
<InputNumber precision={0} min={0} max={100} />
<InputNumber precision={0} min={-100} max={100} />
</Form.Item>
<Form.Item
label={t("joblines.fields.tax_part")}

View File

@@ -13,6 +13,7 @@ import { selectJobLineEditModal } from "../../redux/modals/modals.selectors";
import UndefinedToNull from "../../utils/undefinedtonull";
import JobLinesUpdsertModal from "./job-lines-upsert-modal.component";
import Axios from "axios";
import Dinero from "dinero.js";
const mapStateToProps = createStructuredSelector({
jobLineEditModal: selectJobLineEditModal,
});
@@ -40,7 +41,15 @@ function JobLinesUpsertModalContainer({
manual_line: !(
jobLineEditModal.context && jobLineEditModal.context.id
),
...UndefinedToNull(values),
...UndefinedToNull({
...values,
prt_dsmk_m: Dinero({
amount: Math.round((values.act_price || 0) * 100),
})
.percentage(Math.abs(values.prt_dsmk_p || 0))
.multiply(values.prt_dsmk_p >= 0 ? 1 : -1)
.toFormat(0.0),
}),
},
],
},
@@ -68,7 +77,15 @@ function JobLinesUpsertModalContainer({
const r = await updateJobLine({
variables: {
lineId: jobLineEditModal.context.id,
line: values,
line: {
...values,
prt_dsmk_m: Dinero({
amount: Math.round(values.act_price * 100),
})
.percentage(Math.abs(values.prt_dsmk_p || 0))
.multiply(values.prt_dsmk_p >= 0 ? 1 : -1)
.toFormat(0.0),
},
},
refetchQueries: ["GET_LINE_TICKET_BY_PK"],
});

View File

@@ -256,7 +256,7 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
</FormRow>
<FormRow header={t("jobs.forms.other")}>
<Form.Item label={t("jobs.fields.category")} name="category">
<Select disabled={jobRO}>
<Select disabled={jobRO} allowClear>
{bodyshop.md_categories.map((s) => (
<Select.Option key={s} value={s}>
{s}

View File

@@ -51,6 +51,7 @@ import JobAuditTrail from "../../components/job-audit-trail/job-audit-trail.comp
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { insertAuditTrail } from "../../redux/application/application.actions";
import JobsDocumentsLocalGallery from "../../components/jobs-documents-local-gallery/jobs-documents-local-gallery.container";
import UndefinedToNull from "../../utils/undefinedtonull";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -96,7 +97,7 @@ export function JobsDetailPage({
variables: {
jobId: job.id,
job: {
...values,
...UndefinedToNull(values, ["alt_transport", "category", "referral_source"]),
parts_tax_rates: {
...job.parts_tax_rates,
...values.parts_tax_rates,

View File

@@ -2485,6 +2485,7 @@
"production_by_target_date": "Production by Target Date",
"production_by_technician": "Production by Technician",
"production_by_technician_one": "Production filtered by Technician",
"production_over_time": "Production Level over Time",
"psr_by_make": "Percent of Sales by Vehicle Make",
"purchase_return_ratio_grouped_by_vendor_detail": "Purchase & Return Ratio by Vendor (Detail)",
"purchase_return_ratio_grouped_by_vendor_summary": "Purchase & Return Ratio by Vendor (Summary)",

View File

@@ -2485,6 +2485,7 @@
"production_by_target_date": "",
"production_by_technician": "",
"production_by_technician_one": "",
"production_over_time": "",
"psr_by_make": "",
"purchase_return_ratio_grouped_by_vendor_detail": "",
"purchase_return_ratio_grouped_by_vendor_summary": "",

View File

@@ -2485,6 +2485,7 @@
"production_by_target_date": "",
"production_by_technician": "",
"production_by_technician_one": "",
"production_over_time": "",
"psr_by_make": "",
"purchase_return_ratio_grouped_by_vendor_detail": "",
"purchase_return_ratio_grouped_by_vendor_summary": "",

View File

@@ -1841,6 +1841,20 @@ export const TemplateList = (type, context) => {
},
group: "purchases",
},
production_over_time: {
title: i18n.t("reportcenter.templates.production_over_time"),
subject: i18n.t(
"reportcenter.templates.production_over_time"
),
key: "production_over_time",
//idtype: "vendor",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.actual_in"),
},
group: "jobs",
},
}
: {}),
...(!type || type === "courtesycarcontract"

View File

@@ -1,6 +1,10 @@
export default function UndefinedToNull(obj) {
export default function UndefinedToNull(obj, keys) {
Object.keys(obj).forEach((key) => {
if (keys && keys.indexOf(key) >= 0) {
if (obj[key] === undefined) obj[key] = null;
} else {
if (obj[key] === undefined) obj[key] = null;
}
});
return obj;
}

View File

@@ -4502,6 +4502,62 @@
_eq: X-Hasura-User-Id
- active:
_eq: true
- table:
name: payment_response
schema: public
object_relationships:
- name: bodyshop
using:
foreign_key_constraint_on: bodyshopid
- name: job
using:
foreign_key_constraint_on: jobid
- name: payment
using:
foreign_key_constraint_on: paymentid
insert_permissions:
- role: user
permission:
check:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
columns:
- amount
- bodyshopid
- declinereason
- ext_paymentid
- jobid
- paymentid
- response
- successful
select_permissions:
- role: user
permission:
columns:
- successful
- response
- amount
- declinereason
- ext_paymentid
- bodyshopid
- id
- jobid
- paymentid
filter:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
- table:
name: payments
schema: public

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."jobs_idx_date_open";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "jobs_idx_date_open" on
"public"."jobs" using btree ("date_open");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."jobs_idx_date_invoiced";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "jobs_idx_date_invoiced" on
"public"."jobs" using btree ("date_invoiced");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_bills_vendorid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_bills_vendorid" on
"public"."bills" using btree ("vendorid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_parts_orders_vendorid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_parts_orders_vendorid" on
"public"."parts_orders" using btree ("vendorid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_ccc_jobid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_ccc_jobid" on
"public"."cccontracts" using btree ("jobid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_ccc_courtesycarid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_ccc_courtesycarid" on
"public"."cccontracts" using btree ("courtesycarid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_jobs_actual_completion";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_jobs_actual_completion" on
"public"."jobs" using btree ("actual_completion");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_jobs_actual_in";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_jobs_actual_in" on
"public"."jobs" using btree ("actual_in");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_jobs_employee_csr";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_jobs_employee_csr" on
"public"."jobs" using btree ("employee_csr");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_jobs_body_csr";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_jobs_body_csr" on
"public"."jobs" using btree ("employee_body");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_jobs_employee_refinish";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_jobs_employee_refinish" on
"public"."jobs" using btree ("employee_refinish");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_timetickets_employeeid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_timetickets_employeeid" on
"public"."timetickets" using btree ("employeeid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_timetickets_cost_center";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_timetickets_cost_center" on
"public"."timetickets" using btree ("cost_center");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_scoreboard_jobid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_scoreboard_jobid" on
"public"."scoreboard" using btree ("jobid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_scoreboard_date";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_scoreboard_date" on
"public"."scoreboard" using btree ("date");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_payments_date";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_payments_date" on
"public"."payments" using btree ("date");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."exportlog_createdat";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "exportlog_createdat" on
"public"."exportlog" using btree ("created_at");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_transitions_jobid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_transitions_jobid" on
"public"."transitions" using btree ("jobid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_transitions_start";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_transitions_start" on
"public"."transitions" using btree ("start");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_transitions_end";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_transitions_end" on
"public"."transitions" using btree ("end");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_audit_bodyshopid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_audit_bodyshopid" on
"public"."audit_trail" using btree ("bodyshopid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_audit_jobid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_audit_jobid" on
"public"."audit_trail" using btree ("jobid");

View File

@@ -0,0 +1 @@
DROP INDEX IF EXISTS "public"."idx_audit_billid";

View File

@@ -0,0 +1,2 @@
CREATE INDEX "idx_audit_billid" on
"public"."audit_trail" using btree ("billid");

View File

@@ -0,0 +1,11 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- CREATE INDEX idx_phonebook_firstname ON public.phonebook USING gin (firstname public.gin_trgm_ops);
-- CREATE INDEX idx_phonebook_lastname ON public.phonebook USING gin (lastname public.gin_trgm_ops);
-- CREATE INDEX idx_phonebook_company ON public.phonebook USING gin (company public.gin_trgm_ops);
-- CREATE INDEX idx_phonebook_address1 ON public.phonebook USING gin (address1 public.gin_trgm_ops);
-- CREATE INDEX idx_phonebook_phone1 ON public.phonebook USING gin (phone1 public.gin_trgm_ops);
-- CREATE INDEX idx_phonebook_phone2 ON public.phonebook USING gin (phone2 public.gin_trgm_ops);
-- CREATE INDEX idx_phonebook_email ON public.phonebook USING gin (email public.gin_trgm_ops);
-- CREATE INDEX idx_phonebook_category ON public.phonebook USING gin (category public.gin_trgm_ops);
-- CREATE INDEX idx_vendor_name ON public.vendors USING gin (name public.gin_trgm_ops);

View File

@@ -0,0 +1,9 @@
CREATE INDEX idx_phonebook_firstname ON public.phonebook USING gin (firstname public.gin_trgm_ops);
CREATE INDEX idx_phonebook_lastname ON public.phonebook USING gin (lastname public.gin_trgm_ops);
CREATE INDEX idx_phonebook_company ON public.phonebook USING gin (company public.gin_trgm_ops);
CREATE INDEX idx_phonebook_address1 ON public.phonebook USING gin (address1 public.gin_trgm_ops);
CREATE INDEX idx_phonebook_phone1 ON public.phonebook USING gin (phone1 public.gin_trgm_ops);
CREATE INDEX idx_phonebook_phone2 ON public.phonebook USING gin (phone2 public.gin_trgm_ops);
CREATE INDEX idx_phonebook_email ON public.phonebook USING gin (email public.gin_trgm_ops);
CREATE INDEX idx_phonebook_category ON public.phonebook USING gin (category public.gin_trgm_ops);
CREATE INDEX idx_vendor_name ON public.vendors USING gin (name public.gin_trgm_ops);

View File

@@ -0,0 +1 @@
DROP TABLE "public"."payment_response";

View File

@@ -0,0 +1,2 @@
CREATE TABLE "public"."payment_response" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "bodyshopid" uuid NOT NULL, "jobid" uuid, "paymentid" uuid, "successful" boolean NOT NULL DEFAULT false, "ext_paymentid" text NOT NULL, "amount" numeric NOT NULL, "declinereason" text, "response" jsonb NOT NULL DEFAULT jsonb_build_object(), PRIMARY KEY ("id") , FOREIGN KEY ("bodyshopid") REFERENCES "public"."bodyshops"("id") ON UPDATE cascade ON DELETE cascade, FOREIGN KEY ("jobid") REFERENCES "public"."jobs"("id") ON UPDATE cascade ON DELETE cascade, FOREIGN KEY ("paymentid") REFERENCES "public"."payments"("id") ON UPDATE cascade ON DELETE cascade);
CREATE EXTENSION IF NOT EXISTS pgcrypto;

View File

@@ -28,7 +28,7 @@ exports.sendServerEmail = async function ({ subject, text }) {
transporter.sendMail(
{
from: `ImEX Online API - ${process.env.NODE_ENV} <noreply@imex.online>`,
to: ["patrick@snapt.ca"],
to: ["patrick@imexsystems.ca"],
subject: subject,
text: text,
ses: {