diff --git a/.gitignore b/.gitignore index fe7c402dc..3fbb87926 100644 --- a/.gitignore +++ b/.gitignore @@ -113,3 +113,6 @@ firebase/.env !.elasticbeanstalk/*.cfg.yml !.elasticbeanstalk/*.global.yml logs/oAuthClient-log.log + + +.node-persist/** \ No newline at end of file diff --git a/firebase/readme.md b/firebase/readme.md index c7a2bae6b..70f865aff 100644 --- a/firebase/readme.md +++ b/firebase/readme.md @@ -1,3 +1,3 @@ Must set the environment variables using: -firebase functions:config:set auth.graphql_endpoint="https://db.development.bodyshop.app/v1/graphql" auth.hasura_secret_admin_key="Dev-BodyShopApp!" +firebase functions:config:set auth.graphql_endpoint="https://db.dev.bodyshop.app/v1/graphql" auth.hasura_secret_admin_key="Dev-BodyShopApp!" diff --git a/hasura/config.yaml b/hasura/config.yaml index ee9b6394b..fe93f9198 100644 --- a/hasura/config.yaml +++ b/hasura/config.yaml @@ -1,5 +1,5 @@ version: 2 -endpoint: https://db.development.bodyshop.app +endpoint: https://db.dev.bodyshop.app admin_secret: Dev-BodyShopApp! metadata_directory: metadata actions: diff --git a/hasura/metadata/functions.yaml b/hasura/metadata/functions.yaml index 28b0a5c33..3ef10184a 100644 --- a/hasura/metadata/functions.yaml +++ b/hasura/metadata/functions.yaml @@ -1,30 +1,30 @@ - function: - schema: public name: search_bills -- function: schema: public +- function: name: search_cccontracts -- function: schema: public +- function: name: search_dms_vehicles -- function: schema: public +- function: name: search_exportlog -- function: schema: public +- function: name: search_inventory -- function: schema: public +- function: name: search_jobs -- function: schema: public +- function: name: search_owners -- function: schema: public +- function: name: search_payments -- function: schema: public +- function: name: search_phonebook -- function: schema: public +- function: name: search_vehicles + schema: public diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index 74da59587..601107f21 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -1,6 +1,6 @@ - table: - schema: public name: allocations + schema: public object_relationships: - name: employee using: @@ -69,6 +69,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: jobline: job: @@ -81,8 +82,8 @@ - active: _eq: true - table: - schema: public name: appointments + schema: public object_relationships: - name: bodyshop using: @@ -176,6 +177,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -186,8 +188,8 @@ - active: _eq: true - table: - schema: public name: associations + schema: public object_relationships: - name: bodyshop using: @@ -228,8 +230,8 @@ _eq: X-Hasura-User-Id check: null - table: - schema: public name: audit_trail + schema: public object_relationships: - name: bill using: @@ -265,7 +267,6 @@ - bodyshopid - jobid - billid - backend_only: false select_permissions: - role: user permission: @@ -289,8 +290,8 @@ - active: _eq: true - table: - schema: public name: available_jobs + schema: public object_relationships: - name: bodyshop using: @@ -383,6 +384,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -393,8 +395,8 @@ - active: _eq: true - table: - schema: public name: billlines + schema: public object_relationships: - name: bill using: @@ -408,8 +410,8 @@ foreign_key_constraint_on: column: billlineid table: - schema: public name: inventory + schema: public insert_permissions: - role: user permission: @@ -499,6 +501,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bill: job: @@ -511,8 +514,8 @@ - active: _eq: true - table: - schema: public name: bills + schema: public object_relationships: - name: job using: @@ -526,43 +529,43 @@ foreign_key_constraint_on: column: billid table: - schema: public name: audit_trail + schema: public - name: billlines using: foreign_key_constraint_on: column: billid table: - schema: public name: billlines + schema: public - name: documents using: foreign_key_constraint_on: column: billid table: - schema: public name: documents + schema: public - name: exportlogs using: foreign_key_constraint_on: column: billid table: - schema: public name: exportlog + schema: public - name: inventories using: foreign_key_constraint_on: column: consumedbybillid table: - schema: public name: inventory + schema: public - name: parts_orders using: foreign_key_constraint_on: column: returnfrombill table: - schema: public name: parts_orders + schema: public insert_permissions: - role: user permission: @@ -658,6 +661,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: _and: - job: @@ -672,163 +676,163 @@ - exported: _eq: false - table: - schema: public name: bodyshops + schema: public array_relationships: - name: appointments using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: appointments + schema: public - name: associations using: foreign_key_constraint_on: column: shopid table: - schema: public name: associations + schema: public - name: audit_trails using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: audit_trail + schema: public - name: available_jobs using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: available_jobs + schema: public - name: conversations using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: conversations + schema: public - name: counters using: foreign_key_constraint_on: column: shopid table: - schema: public name: counters + schema: public - name: courtesycars using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: courtesycars + schema: public - name: csiinvites using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: csi + schema: public - name: csiquestions using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: csiquestions + schema: public - name: dms_vehicles using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: dms_vehicles + schema: public - name: documents using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: documents + schema: public - name: email_audit_trails using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: email_audit_trail + schema: public - name: employees using: foreign_key_constraint_on: column: shopid table: - schema: public name: employees + schema: public - name: exportlogs using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: exportlog + schema: public - name: inventories using: foreign_key_constraint_on: column: shopid table: - schema: public name: inventory + schema: public - name: jobs using: foreign_key_constraint_on: column: shopid table: - schema: public name: jobs + schema: public - name: owners using: foreign_key_constraint_on: column: shopid table: - schema: public name: owners + schema: public - name: phonebooks using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: phonebook + schema: public - name: timetickets using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: timetickets + schema: public - name: transitions using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: transitions + schema: public - name: vehicles using: foreign_key_constraint_on: column: shopid table: - schema: public name: vehicles + schema: public - name: vendors using: foreign_key_constraint_on: column: bodyshopid table: - schema: public name: vendors + schema: public select_permissions: - role: user permission: @@ -1015,8 +1019,8 @@ _eq: true check: null - table: - schema: public name: cccontracts + schema: public object_relationships: - name: courtesycar using: @@ -1188,6 +1192,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: courtesycar: bodyshop: @@ -1199,8 +1204,8 @@ - active: _eq: true - table: - schema: public name: conversations + schema: public object_relationships: - name: bodyshop using: @@ -1211,15 +1216,15 @@ foreign_key_constraint_on: column: conversationid table: - schema: public name: job_conversations + schema: public - name: messages using: foreign_key_constraint_on: column: conversationid table: - schema: public name: messages + schema: public insert_permissions: - role: user permission: @@ -1282,15 +1287,15 @@ _eq: true check: null - table: - schema: public name: counters + schema: public object_relationships: - name: bodyshop using: foreign_key_constraint_on: shopid - table: - schema: public name: courtesycars + schema: public object_relationships: - name: bodyshop using: @@ -1301,8 +1306,8 @@ foreign_key_constraint_on: column: courtesycarid table: - schema: public name: cccontracts + schema: public insert_permissions: - role: user permission: @@ -1422,6 +1427,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -1432,8 +1438,8 @@ - active: _eq: true - table: - schema: public name: csi + schema: public object_relationships: - name: bodyshop using: @@ -1536,8 +1542,8 @@ _eq: true check: null - table: - schema: public name: csiquestions + schema: public object_relationships: - name: bodyshop using: @@ -1548,8 +1554,8 @@ foreign_key_constraint_on: column: questionset table: - schema: public name: csi + schema: public insert_permissions: - role: user permission: @@ -1611,8 +1617,8 @@ _eq: true check: null - table: - schema: public name: dms_vehicles + schema: public object_relationships: - name: bodyshop using: @@ -1637,7 +1643,6 @@ - make - model - bodyshopid - backend_only: false select_permissions: - role: user permission: @@ -1682,6 +1687,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -1692,8 +1698,8 @@ - active: _eq: true - table: - schema: public name: documents + schema: public object_relationships: - name: bill using: @@ -1815,6 +1821,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: _or: - job: @@ -1835,8 +1842,8 @@ - active: _eq: true - table: - schema: public name: email_audit_trail + schema: public object_relationships: - name: bodyshop using: @@ -1871,7 +1878,6 @@ - id - jobid - noteid - backend_only: false select_permissions: - role: user permission: @@ -1922,8 +1928,8 @@ _eq: true check: null - table: - schema: public name: employee_vacation + schema: public object_relationships: - name: employee using: @@ -1948,7 +1954,6 @@ - employeeid - start - end - backend_only: false select_permissions: - role: user permission: @@ -1993,6 +1998,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: employee: bodyshop: @@ -2004,8 +2010,8 @@ - active: _eq: true - table: - schema: public name: employees + schema: public object_relationships: - name: bodyshop using: @@ -2019,50 +2025,50 @@ foreign_key_constraint_on: column: employeeid table: - schema: public name: allocations + schema: public - name: employee_vacations using: foreign_key_constraint_on: column: employeeid table: - schema: public name: employee_vacation + schema: public - name: jobsByEmployeeBody using: foreign_key_constraint_on: column: employee_body table: - schema: public name: jobs + schema: public - name: jobsByEmployeeCsr using: foreign_key_constraint_on: column: employee_csr table: - schema: public name: jobs + schema: public - name: jobsByEmployeePrep using: foreign_key_constraint_on: column: employee_prep table: - schema: public name: jobs + schema: public - name: jobsByEmployeeRefinish using: foreign_key_constraint_on: column: employee_refinish table: - schema: public name: jobs + schema: public - name: timetickets using: foreign_key_constraint_on: column: employeeid table: - schema: public name: timetickets + schema: public insert_permissions: - role: user permission: @@ -2152,6 +2158,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -2162,8 +2169,8 @@ - active: _eq: true - table: - schema: public name: exportlog + schema: public object_relationships: - name: bill using: @@ -2203,7 +2210,6 @@ - message - bodyshopid - useremail - backend_only: false select_permissions: - role: user permission: @@ -2229,8 +2235,8 @@ _eq: true allow_aggregations: true - table: - schema: public name: inventory + schema: public object_relationships: - name: bill using: @@ -2271,7 +2277,6 @@ - quantity - shopid - updated_at - backend_only: false select_permissions: - role: user permission: @@ -2331,6 +2336,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -2341,11 +2347,11 @@ - active: _eq: true - table: - schema: public name: ioevents -- table: schema: public +- table: name: job_conversations + schema: public object_relationships: - name: conversation using: @@ -2407,6 +2413,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: conversation: bodyshop: @@ -2418,8 +2425,8 @@ - active: _eq: true - table: - schema: public name: joblines + schema: public object_relationships: - name: job using: @@ -2430,29 +2437,29 @@ foreign_key_constraint_on: column: joblineid table: - schema: public name: allocations + schema: public - name: billlines using: foreign_key_constraint_on: column: joblineid table: - schema: public name: billlines + schema: public - name: inventories using: foreign_key_constraint_on: column: joblineid table: - schema: public name: inventory + schema: public - name: parts_order_lines using: foreign_key_constraint_on: column: job_line_id table: - schema: public name: parts_order_lines + schema: public insert_permissions: - role: user permission: @@ -2692,6 +2699,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: job: bodyshop: @@ -2703,18 +2711,18 @@ - active: _eq: true - table: - schema: public name: joblines_status + schema: public object_relationships: - name: job using: manual_configuration: - remote_table: - schema: public - name: jobs - insertion_order: null column_mapping: jobid: id + insertion_order: null + remote_table: + name: jobs + schema: public select_permissions: - role: user permission: @@ -2734,18 +2742,18 @@ - active: _eq: true - table: - schema: public name: jobs + schema: public object_relationships: - name: bill using: manual_configuration: - remote_table: - schema: public - name: bills - insertion_order: null column_mapping: id: jobid + insertion_order: null + remote_table: + name: bills + schema: public - name: bodyshop using: foreign_key_constraint_on: shopid @@ -2776,157 +2784,157 @@ foreign_key_constraint_on: column: jobid table: - schema: public name: appointments + schema: public - name: audit_trails using: foreign_key_constraint_on: column: jobid table: - schema: public name: audit_trail + schema: public - name: available_jobs using: foreign_key_constraint_on: column: jobid table: - schema: public name: available_jobs + schema: public - name: bills using: foreign_key_constraint_on: column: jobid table: - schema: public name: bills + schema: public - name: cccontracts using: foreign_key_constraint_on: column: jobid table: - schema: public name: cccontracts + schema: public - name: csiinvites using: foreign_key_constraint_on: column: jobid table: - schema: public name: csi + schema: public - name: documents using: foreign_key_constraint_on: column: jobid table: - schema: public name: documents + schema: public - name: email_audit_trails using: foreign_key_constraint_on: column: jobid table: - schema: public name: email_audit_trail + schema: public - name: exportlogs using: foreign_key_constraint_on: column: jobid table: - schema: public name: exportlog + schema: public - name: ious using: foreign_key_constraint_on: column: iouparent table: - schema: public name: jobs + schema: public - name: job_conversations using: foreign_key_constraint_on: column: jobid table: - schema: public name: job_conversations + schema: public - name: joblines using: foreign_key_constraint_on: column: jobid table: - schema: public name: joblines + schema: public - name: joblines_status using: manual_configuration: - remote_table: - schema: public - name: joblines_status - insertion_order: null column_mapping: id: jobid + insertion_order: null + remote_table: + name: joblines_status + schema: public - name: mixdata using: foreign_key_constraint_on: column: jobid table: - schema: public name: mixdata + schema: public - name: notes using: foreign_key_constraint_on: column: jobid table: - schema: public name: notes + schema: public - name: parts_orders using: foreign_key_constraint_on: column: jobid table: - schema: public name: parts_orders + schema: public - name: payments using: foreign_key_constraint_on: column: jobid table: - schema: public name: payments + schema: public - name: relatedjobs_child using: foreign_key_constraint_on: column: childjob table: - schema: public name: relatedjobs + schema: public - name: relatedjobs_parent using: foreign_key_constraint_on: column: parentjob table: - schema: public name: relatedjobs + schema: public - name: scoreboards using: foreign_key_constraint_on: column: jobid table: - schema: public name: scoreboard + schema: public - name: timetickets using: foreign_key_constraint_on: column: jobid table: - schema: public name: timetickets + schema: public - name: transitions using: foreign_key_constraint_on: column: jobid table: - schema: public name: transitions + schema: public insert_permissions: - role: user permission: @@ -3745,6 +3753,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -3754,9 +3763,42 @@ _eq: X-Hasura-User-Id - active: _eq: true + event_triggers: + - name: jobs_arms + definition: + enable_manual: false + insert: + columns: '*' + update: + columns: + - actual_delivery + - scheduled_delivery + - scheduled_completion + - actual_completion + - date_scheduled + - clm_total + - suspended + - date_open + - job_totals + - converted + - employee_body + - ro_number + - actual_in + - scheduled_in + retry_conf: + interval_sec: 10 + num_retries: 0 + timeout_sec: 60 + webhook_from_env: HASURA_API_URL + request_transform: + method: POST + query_params: {} + template_engine: Kriti + url: '{{$base_url}}/record-handler/arms' + version: 2 - table: - schema: public name: masterdata + schema: public select_permissions: - role: anonymous permission: @@ -3771,8 +3813,8 @@ - value filter: {} - table: - schema: public name: messages + schema: public object_relationships: - name: conversation using: @@ -3862,6 +3904,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: conversation: bodyshop: @@ -3873,8 +3916,8 @@ - active: _eq: true - table: - schema: public name: mixdata + schema: public object_relationships: - name: job using: @@ -3902,7 +3945,6 @@ - updated_at - id - jobid - backend_only: false select_permissions: - role: user permission: @@ -3951,8 +3993,8 @@ _eq: X-Hasura-User-Id check: null - table: - schema: public name: notes + schema: public object_relationships: - name: job using: @@ -4033,6 +4075,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: job: bodyshop: @@ -4044,8 +4087,8 @@ - active: _eq: true - table: - schema: public name: owners + schema: public object_relationships: - name: bodyshop using: @@ -4056,8 +4099,8 @@ foreign_key_constraint_on: column: ownerid table: - schema: public name: jobs + schema: public insert_permissions: - role: user permission: @@ -4167,6 +4210,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -4177,8 +4221,8 @@ - active: _eq: true - table: - schema: public name: parts_order_lines + schema: public object_relationships: - name: jobline using: @@ -4286,6 +4330,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: parts_order: job: @@ -4298,8 +4343,8 @@ - active: _eq: true - table: - schema: public name: parts_orders + schema: public object_relationships: - name: bill using: @@ -4322,8 +4367,8 @@ foreign_key_constraint_on: column: orderid table: - schema: public name: parts_order_lines + schema: public insert_permissions: - role: user permission: @@ -4411,6 +4456,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: job: bodyshop: @@ -4422,8 +4468,8 @@ - active: _eq: true - table: - schema: public name: payments + schema: public object_relationships: - name: job using: @@ -4434,8 +4480,8 @@ foreign_key_constraint_on: column: paymentid table: - schema: public name: exportlog + schema: public insert_permissions: - role: user permission: @@ -4522,6 +4568,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: job: bodyshop: @@ -4533,8 +4580,8 @@ - active: _eq: true - table: - schema: public name: phonebook + schema: public object_relationships: - name: bodyshop using: @@ -4570,7 +4617,6 @@ - phone2 - fax - category - backend_only: false select_permissions: - role: user permission: @@ -4638,6 +4684,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -4648,8 +4695,8 @@ - active: _eq: true - table: - schema: public name: relatedjobs + schema: public object_relationships: - name: childjob_rel using: @@ -4686,7 +4733,6 @@ - updated_at - parentjob - childjob - backend_only: false select_permissions: - role: user permission: @@ -4749,6 +4795,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: _or: - parentjob_rel: @@ -4770,8 +4817,8 @@ - active: _eq: true - table: - schema: public name: scoreboard + schema: public object_relationships: - name: job using: @@ -4795,7 +4842,6 @@ - painthrs - bodyhrs - date - backend_only: false select_permissions: - role: user permission: @@ -4839,6 +4885,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: job: bodyshop: @@ -4850,8 +4897,8 @@ - active: _eq: true - table: - schema: public name: timetickets + schema: public object_relationships: - name: bodyshop using: @@ -4953,6 +5000,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -4963,8 +5011,8 @@ - active: _eq: true - table: - schema: public name: transitions + schema: public object_relationships: - name: bodyshop using: @@ -4997,7 +5045,6 @@ - type - updated_at - value - backend_only: false select_permissions: - role: user permission: @@ -5050,75 +5097,75 @@ _eq: X-Hasura-User-Id check: {} - table: - schema: public name: users + schema: public object_relationships: - name: employee using: manual_configuration: - remote_table: - schema: public - name: employees - insertion_order: null column_mapping: email: user_email + insertion_order: null + remote_table: + name: employees + schema: public array_relationships: - name: associations using: foreign_key_constraint_on: column: useremail table: - schema: public name: associations + schema: public - name: audit_trails using: foreign_key_constraint_on: column: useremail table: - schema: public name: audit_trail + schema: public - name: email_audit_trails using: foreign_key_constraint_on: column: useremail table: - schema: public name: email_audit_trail + schema: public - name: exportlogs using: foreign_key_constraint_on: column: useremail table: - schema: public name: exportlog + schema: public - name: messages using: foreign_key_constraint_on: column: userid table: - schema: public name: messages + schema: public - name: notes using: foreign_key_constraint_on: column: created_by table: - schema: public name: notes + schema: public - name: partsOrdersByOrderedby using: foreign_key_constraint_on: column: orderedby table: - schema: public name: parts_orders + schema: public - name: parts_orders using: foreign_key_constraint_on: column: user_email table: - schema: public name: parts_orders + schema: public insert_permissions: - role: user permission: @@ -5158,8 +5205,8 @@ _eq: X-Hasura-User-Id check: null - table: - schema: public name: vehicles + schema: public object_relationships: - name: bodyshop using: @@ -5170,8 +5217,8 @@ foreign_key_constraint_on: column: vehicleid table: - schema: public name: jobs + schema: public insert_permissions: - role: user permission: @@ -5294,6 +5341,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: @@ -5304,8 +5352,8 @@ - active: _eq: true - table: - schema: public name: vendors + schema: public object_relationships: - name: bodyshop using: @@ -5316,15 +5364,15 @@ foreign_key_constraint_on: column: vendorid table: - schema: public name: bills + schema: public - name: parts_orders using: foreign_key_constraint_on: column: vendorid table: - schema: public name: parts_orders + schema: public insert_permissions: - role: user permission: @@ -5423,6 +5471,7 @@ delete_permissions: - role: user permission: + backend_only: false filter: bodyshop: associations: diff --git a/package.json b/package.json index 6dcb3e985..1ac8aac79 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "moment-timezone": "^0.5.34", "multer": "^1.4.5-lts.1", "node-mailjet": "^5.1.0", + "node-persist": "^3.1.0", "node-quickbooks": "^2.0.39", "nodemailer": "^6.7.7", "phone": "^3.1.23", diff --git a/server.js b/server.js index 50640e365..e6cbb7e5c 100644 --- a/server.js +++ b/server.js @@ -210,7 +210,7 @@ app.post("/qbo/payments", fb.validateFirebaseIdToken, qbo.payments); var data = require("./server/data/data"); app.post("/data/ah", data.autohouse); -app.post("/data/arms", data.arms); +app.post("/record-handler/arms", data.arms); var taskHandler = require("./server/tasks/tasks"); app.post("/taskHandler", taskHandler.taskHandler); @@ -238,6 +238,7 @@ app.get("/", async function (req, res) { res.status(200).send("Access Forbidden."); }); + server.listen(port, (error) => { if (error) throw error; logger.log( diff --git a/server/data/arms.js b/server/data/arms.js index 1a24c7b0a..5dd7840c6 100644 --- a/server/data/arms.js +++ b/server/data/arms.js @@ -3,7 +3,7 @@ const queries = require("../graphql-client/queries"); const Dinero = require("dinero.js"); const moment = require("moment-timezone"); const fs = require("fs"); - +const storage = require("node-persist"); const _ = require("lodash"); const logger = require("../utils/logger"); require("dotenv").config({ @@ -13,6 +13,7 @@ require("dotenv").config({ ), }); const soap = require("soap"); +const { sendServerEmail } = require("../email/sendemail"); const entegralEndpoint = process.env.NODE_ENV === "production" @@ -24,11 +25,858 @@ const uuid = require("uuid").v4; const momentFormat = "yyyy-MM-DDTHH:mm:ss.SSS"; +function pollFunc(fn, timeout, interval) { + var startTime = new Date().getTime(); + (interval = interval || 1000), (canPoll = true); + + (function p() { + canPoll = + timeout === 0 ? true : new Date().getTime() - startTime <= timeout; + if (fn() && canPoll) { + // ensures the function exucutes + setTimeout(p, interval); + } + })(); +} + +pollFunc(getEntegralShopData, 0, 5 * 60 * 1000); //Set the metadata to refresh every 5 minutes. + +async function getEntegralShopData() { + const { bodyshops } = await client.request(queries.GET_ENTEGRAL_SHOPS); + await storage.init({ logging: true }); + logger.log("set-entegral-shops-local-storage", "DEBUG", "API", null, null); + await storage.setItem("entegralShops", bodyshops); + return true; //Continue execution. +} + exports.default = async (req, res) => { //Query for the List of Bodyshop Clients. - logger.log("arms-start", "DEBUG", "api", null, null); - const { bodyshops } = await client.request(queries.GET_ENTEGRAL_SHOPS); + const job = req.body.event.data.new; + logger.log("arms-job-update", "DEBUG", "api", job.id, null); + let allEntegralShops = await storage.getItem("entegralShops"); + + if (!allEntegralShops) { + await getEntegralShopData(); + allEntegralShops = await storage.getItem("entegralShops"); + } + + //Is this job part of an entegral shop? + const bodyshop = allEntegralShops.find((b) => b.id === job.shopid); + if (!bodyshop) { + //This job is not for entegral based shops. + + res.sendStatus(200); + return; + } + + if (process.env.NODE_ENV === "PRODUCTION") { + res.sendStatus(200); + return; + } + //TODO: Check if an update should even be sent. + if (false) { + res.sendStatus(200); + return; + } + + try { + const transId = uuid(); // Can this actually be the job id? + let obj = { + RqUID: transId, + DocumentInfo: { + BMSVer: "4.0.0", + DocumentType: "RO", + DocumentVerCode: "EM", + DocumentVerNum: GetSupplementNumber(job.joblines), //TODO Get Supplement Number + DocumentStatus: GetDocumentstatus(job, bodyshop), + CreateDateTime: moment().format(momentFormat), + TransmitDateTime: moment().format(momentFormat), // Omitted from ARMS docs + }, + EventInfo: { + AssignmentEvent: { + CreateDateTime: + job.asgn_date && moment(job.asgn_date).format(momentFormat), + }, + // EstimateEvent: { + // UploadDateTime: moment().format(momentFormat), + // }, + RepairEvent: { + CreatedDateTime: (job.date_open + ? moment(job.date_open).tz(bodyshop.timezone) + : moment() + ).format(momentFormat), + ArrivalDateTime: + job.actual_in && + moment(job.actual_in).tz(bodyshop.timezone).format(momentFormat), + ArrivalOdometerReading: job.kmin, + TargetCompletionDateTime: + job.scheduled_completion && + moment(job.scheduled_completion) + .tz(bodyshop.timezone) + .format(momentFormat), + ActualCompletionDateTime: + job.actual_completion && + moment(job.actual_completion) + .tz(bodyshop.timezone) + .format(momentFormat), + ActualPickUpDateTime: + job.actual_delivery && + moment(job.actual_delivery) + .tz(bodyshop.timezone) + .format(momentFormat), + CloseDateTime: + job.date_exported && + moment(job.date_exported) + .tz(bodyshop.timezone) + .format(momentFormat), + }, + }, + RepairOrderHeader: { + AdminInfo: { + InsuranceCompany: { + Party: { + OrgInfo: { + CompanyName: job.ins_co_nm, + IDInfo: { + IDQualifierCode: "US", + //IDNum: 44, // ** Not sure where to get this entegral ID from? + }, + // Communications: [ + // { + // CommQualifier: "WA", + // Address: { + // Address1: job.ins_addr1, + // Address2: job.ins_addr2, + // City: job.ins_city, + // StateProvince: job.ins_st, + // PostalCode: job.ins_zip, + // CountryCode: job.ins_ctry, + // }, + // }, + // { + // CommQualifier: "WP", + // CommPhone: job.ins_ph1, + // }, + // { + // CommQualifier: "WF", + // CommPhone: job.ins_ph2, + // }, + // ], + }, + // ContactInfo: { + // ContactJobTitle: "Adjuster", + // ContactName: { + // FirstName: job.est_ct_fn, + // LastName: job.est_ct_ln, + // }, + // }, + }, + }, + // InsuranceAgent: { + // Party: { + // OrgInfo: { + // CompanyName: "Nationwide Insurance", + // Communications: { + // CommQualifier: "WP", + // CommPhone: "714-5551212", + // }, + // }, + // ContactInfo: { + // ContactJobTitle: "Insurance Agent", + // ContactName: { + // FirstName: "Paul", + // LastName: "White", + // }, + // }, + // }, + // }, + // Insured: { + // Party: { + // PersonInfo: { + // PersonName: { + // FirstName: job.insd_fn, + // LastName: job.insd_ln, + // }, + // }, + // }, + // }, + Owner: { + Party: { + PersonInfo: { + PersonName: { + FirstName: job.ownr_fn, + LastName: job.ownr_ln, + }, + // Communications: [ + // { + // CommQualifier: "HA", + // Address: { + // Address1: job.ownr_addr1, + + // City: job.ownr_city, + // StateProvince: job.ownr_st, + // PostalCode: job.ownr_zip, + // CountryCode: job.ownr_ctry, + // }, + // }, + // { + // CommQualifier: "HP", + // CommPhone: job.ownr_ph1, + // }, + // { + // CommQualifier: "WP", + // CommPhone: job.ownr_ph2, + // }, + // { + // CommQualifier: "CP", + // CommPhone: job.ownr_ph1, + // }, + // { + // CommQualifier: "EM", + // CommEmail: job.ownr_ea, + // }, + // ], + }, + }, + }, + // Claimant: { + // Party: { + // PersonInfo: { + // PersonName: { + // FirstName: job.clm_ct_fn, + // LastName: job.clm_ct_ln, + // }, + // }, + // }, + // OwnerInd: true, + // }, + // Estimator: { + // Party: { + // PersonInfo: { + // PersonName: { + // FirstName: job.est_ct_fn, + // LastName: job.est_ct_ln, + // }, + // // IDInfo: { + // // IDQualifierCode: "US", + // // IDNum: 2941, + // // }, + // }, + // }, + // }, + RepairFacility: { + Party: { + OrgInfo: { + CompanyName: + process.env.NODE_ENV === "production" + ? bodyshop.shopname + : "IMEX Test Shop", + IDInfo: { + IDQualifierCode: "US", + IDNum: bodyshop.entegral_id, + }, + }, + }, + }, + }, + RepairOrderIDs: { + RepairOrderNum: job.ro_number, + // VendorCode: "C", + // EstimateDocumentID: "1223HJ76", + }, + RepairOrderType: "DirectRepairProgram", //Need to get from Entegral + //ReferralSourceType: "Yellow Pages", + VehicleInfo: { + VINInfo: { + VIN: { + VINNum: job.v_vin, + }, + }, + License: { + LicensePlateNum: job.plate_no, + }, + VehicleDesc: { + //ProductionDate: "2009-10", + ModelYear: + parseInt(job.v_model_yr) < 1900 + ? parseInt(job.v_model_yr) < + moment().tz(bodyshop.timezone).format("YY") + ? `20${job.v_model_yr}` + : `19${job.v_model_yr}` + : job.v_model_yr, + MakeDesc: job.v_make_desc, + ModelName: job.v_model_desc, + }, + // Paint: { + // Exterior: { + // Color: { + // ColorName: job.v_color, + // // OEMColorCode: "1M3", + // }, + // }, + // }, + // Body: { + // BodyStyle: "2 Door Convertible", + // Trim: { + // TrimCode: "1B3", + // }, + // }, + // Condition: { + // DrivableInd: job.driveable ? "Y" : "N", + // }, + }, + ClaimInfo: { + ClaimNum: job.clm_no, + PolicyInfo: { + PolicyNum: job.policy_no, + }, + LossInfo: { + Facts: { + LossDateTime: + job.loss_date && + moment(job.loss_date) + .tz(bodyshop.timezone) + .format(momentFormat), + LossDescCode: "Collision", + PrimaryPOI: { + POICode: job.area_of_damage && job.area_of_damage.impact1, + }, + SecondaryPOI: { + POICode: job.area_of_damage && job.area_of_damage.impact2, + }, + }, + TotalLossInd: job.tlos_ind, + }, + }, + }, + ProfileInfo: { + ProfileName: "ImEX", + RateInfo: [ + { + RateType: "PA", + RateDesc: "Parts Tax", + TaxInfo: { + TaxType: "LS", + TaxableInd: true, + TaxTierInfo: { + TierNum: 1, + Percentage: job.parts_tax_rates.PAN.prt_tax_rt * 100, //TODO Find the best place to take the tax rates for parts. + }, + }, + }, + { + RateType: "LA", + RateDesc: "Labor Tax", + TaxInfo: { + TaxType: "LS", + TaxableInd: true, + TaxTierInfo: { + TierNum: 1, + Percentage: job.parts_tax_rates.PAN.prt_tax_rt * 100, //TODO Find the best place to take the tax rates for labor. + }, + }, + }, + { + RateType: "LAB", + RateDesc: "Body Labor", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_lab, + }, + }, + { + RateType: "LAS", + RateDesc: "Structural Labor", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_las, + }, + }, + { + RateType: "LAR", + RateDesc: "Refinish Labor", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_lar, + }, + }, + { + RateType: "LAG", + RateDesc: "Glass Labor", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_lag, + }, + }, + { + RateType: "LAF", + RateDesc: "Frame Labor", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_laf, + }, + }, + { + RateType: "LAM", + RateDesc: "Mechancial Labor", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_lam, + }, + }, + { + RateType: "LAU", + RateDesc: "User Defined Labor", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_lau, + }, + }, + { + RateType: "MAPA", + RateDesc: "Paint Materials", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_mapa, + ThresholdAmt: 0, + }, + MaterialCalcSettings: { + CalcMethodCode: 2, + CalcMaxAmt: 9999.99, //TODO Find threshold amts. + }, + }, + { + RateType: "MASH", + RateDesc: "Shop Materials", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_mash, + }, + MaterialCalcSettings: { + CalcMethodCode: 4, + CalcMaxAmt: 9999.99, //TODO Find threshold amounts. + }, + }, + { + RateType: "MAHW", + RateDesc: "Hazardous Wastes Removal", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_mahw, + }, + MaterialCalcSettings: { + //Todo Capture Calc Settings + CalcMethodCode: 2, + CalcMaxAmt: 10, + }, + }, + { + RateType: "MA2S", + RateDesc: "Two Stage Paint", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_ma2s, + }, + MaterialCalcSettings: { + CalcMethodCode: 1, + CalcMaxAmt: 999999.99, + }, + }, + { + RateType: "MA2T", + RateDesc: "Two Tone Paint", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_ma2t, + }, + MaterialCalcSettings: { + CalcMethodCode: 1, + CalcMaxAmt: 999999.99, + }, + }, + { + RateType: "MA3S", + RateDesc: "Three Stage Paint", + RateTierInfo: { + TierNum: 1, + Rate: job.rate_ma3s, + }, + MaterialCalcSettings: { + CalcMethodCode: 1, + CalcMaxAmt: 999999.99, + }, + }, + ], + }, + //StorageDuration: 17, + RepairTotalsInfo: { + LaborTotalsInfo: [ + { + TotalType: "LAB", + TotalTypeDesc: "Body Labor", + TotalHours: job.job_totals.rates.lab.hours, + TotalAmt: Dinero(job.job_totals.rates.lab.total).toFormat("0.00"), + }, + { + TotalType: "LAF", + TotalTypeDesc: "Frame Labor", + TotalHours: job.job_totals.rates.laf.hours, + TotalAmt: Dinero(job.job_totals.rates.laf.total).toFormat("0.00"), + }, + { + TotalType: "LAM", + TotalTypeDesc: "Mechanical Labor", + TotalHours: job.job_totals.rates.lam.hours, + TotalAmt: Dinero(job.job_totals.rates.lam.total).toFormat("0.00"), + }, + { + TotalType: "LAR", + TotalTypeDesc: "Refinish Labor", + TotalHours: job.job_totals.rates.lar.hours, + TotalAmt: Dinero(job.job_totals.rates.lar.total).toFormat("0.00"), + }, + ], + PartsTotalsInfo: [ + { + TotalType: "PAA", + TotalTypeDesc: "Aftermarket Parts", + TotalAmt: Dinero( + job.job_totals.parts.parts.list.PAA && + job.job_totals.parts.parts.list.PAA.total + ).toFormat("0.00"), + }, + { + TotalType: "PAC", + TotalTypeDesc: "Re-Chromed Parts", + TotalAmt: Dinero( + job.job_totals.parts.parts.list.PAC && + job.job_totals.parts.parts.list.PAC.total + ).toFormat("0.00"), + }, + { + TotalType: "PAG", + TotalTypeDesc: "Glass Parts", + TotalAmt: Dinero( + job.job_totals.parts.parts.list.PAG && + job.job_totals.parts.parts.list.PAG.total + ).toFormat("0.00"), + }, + { + TotalType: "PAL", + TotalTypeDesc: "LKQ/Used Parts", + TotalAmt: Dinero( + job.job_totals.parts.parts.list.PAL && + job.job_totals.parts.parts.list.PAL.total + ).toFormat("0.00"), + }, + { + TotalType: "PAM", + TotalTypeDesc: "Remanufactured Parts", + TotalAmt: Dinero( + job.job_totals.parts.parts.list.PAM && + job.job_totals.parts.parts.list.PAM.total + ).toFormat("0.00"), + }, + { + TotalType: "PAN", + TotalTypeDesc: "New Parts", + TotalAmt: Dinero( + job.job_totals.parts.parts.list.PAN && + job.job_totals.parts.parts.list.PAN.total + ).toFormat("0.00"), + }, + { + TotalType: "PAR", + TotalTypeDesc: "Recored Parts", + TotalAmt: Dinero( + job.job_totals.parts.parts.list.PAR && + job.job_totals.parts.parts.list.PAR.total + ).toFormat("0.00"), + }, + ], + OtherChargesTotalsInfo: [ + { + TotalType: "OTSL", + TotalTypeDesc: "Sublet", + TotalAmt: Dinero(job.job_totals.parts.sublets.total).toFormat( + "0.00" + ), + }, + { + TotalType: "MAPA", + TotalTypeDesc: "Paint Materials", + TotalAmt: Dinero(job.job_totals.rates.mapa.total).toFormat("0.00"), + }, + { + TotalType: "MASH", + TotalTypeDesc: "Shop Materials", + TotalAmt: Dinero(job.job_totals.rates.mash.total).toFormat("0.00"), + }, + // { + // TotalType: "MAHW", + // TotalTypeDesc: "Hazardous Wastes Removal", + // TotalAmt: Dinero(job.job_totals.rates.mahw.total).toFormat( + // 0.0 + // ), + // }, + { + TotalType: "OTST", + TotalTypeDesc: "Storage", + TotalAmt: Dinero(job.job_totals.additional.storage).toFormat( + "0.00" + ), + }, + { + TotalType: "OTTW", + TotalTypeDesc: "Towing", + TotalAmt: Dinero(job.job_totals.additional.towing).toFormat("0.00"), + }, + { + TotalType: "OTAC", + TotalTypeDesc: "Additional Charges", + TotalAmt: Dinero( + job.job_totals.additional.additionalCosts + ).toFormat("0.00"), + }, + ], + SummaryTotalsInfo: [ + { + TotalType: "TOT", + TotalSubType: "TT", + TotalTypeDesc: "Gross Total", + TotalAmt: Dinero(job.job_totals.totals.total_repairs).toFormat( + "0.00" + ), + }, + { + TotalType: "TOT", + TotalSubType: "T2", + TotalTypeDesc: "Net Total", + TotalAmt: Dinero(job.job_totals.totals.subtotal).toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "SM", + TotalTypeDesc: "Supplement Total", + TotalAmt: job.cieca_ttl + ? job.cieca_ttl.data.supp_amt + : Dinero().toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "F7", + TotalTypeDesc: "Sales Tax", + TotalAmt: Dinero(job.job_totals.totals.state_tax).toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "GST", + TotalTypeDesc: "GST Tax", + TotalAmt: Dinero(job.job_totals.totals.federal_tax).toFormat( + "0.00" + ), + }, + { + TotalType: "TOT", + TotalSubType: "D8", + TotalTypeDesc: "Bottom Line Discount", + TotalAmt: Dinero(job.job_totals.additional.adjustments).toFormat( + "0.00" + ), + }, + { + TotalType: "TOT", + TotalSubType: "D2", + TotalTypeDesc: "Deductible", + TotalAmt: Dinero({ + amount: Math.round((job.ded_amt || 0) * 100), + }).toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "BTR", + TotalTypeDesc: "Betterment", + TotalAmt: Dinero( + job.job_totals.totals.custPayable.dep_taxes + ).toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "AA", + TotalTypeDesc: "Appearance Allowance", + TotalAmt: Dinero().toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "DEPOSIT", + TotalTypeDesc: "Deposit", + TotalAmt: Dinero().toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "INS", + TotalTypeDesc: "Insurance Pay", + TotalAmt: Dinero(job.job_totals.totals.total_repairs) + .subtract(Dinero(job.job_totals.totals.custPayable.total)) + .toFormat("0.00"), + }, + { + TotalType: "TOT", + TotalSubType: "CUST", + TotalTypeDesc: "Customer Pay", + TotalAmt: Dinero(job.job_totals.totals.custPayable.total).toFormat( + "0.00" + ), + }, + ], + // RepairTotalsType: 1, + }, + // RepairLabor: { + // LaborAllocations: { + // LaborAllocation: [ + // { + // LaborAllocationUUID: + // "426cce3a-efa7-44d9-b76e-50b9102c4198", + // LaborType: "LAB", + // Technician: { + // Employee: { + // PersonInfo: { + // PersonName: { + // FirstName: "Jose", + // LastName: "Gonzalez", + // }, + // IDInfo: { + // IDQualifierCode: "US", + // IDNum: 2987, + // }, + // }, + // }, + // }, + // AllocatedHours: 3.5, + // }, + // { + // LaborAllocationUUID: + // "426cce3a-efa7-44d9-b76e-50b9102c4199", + // LaborType: "LAR", + // Technician: { + // Employee: { + // PersonInfo: { + // PersonName: { + // FirstName: "Rcardo", + // LastName: "Himenez", + // }, + // IDInfo: { + // IDQualifierCode: "US", + // IDNum: 2989, + // }, + // }, + // }, + // }, + // AllocatedHours: 5.5, + // }, + // ], + // }, + // }, + ProductionStatus: { + ProductionStage: { + ProductionStageCode: GetProductionStageCode(job, bodyshop), + ProductionStageDateTime: moment() + .tz(bodyshop.timezone) + .format(momentFormat), + // ProductionStageStatusComment: + // "Going to be painted this afternoon", + }, + RepairStatus: { + RepairStatusCode: GetRepairStatusCode(job), + RepairStatusDateTime: moment() + .tz(bodyshop.timezone) + .format(momentFormat), + // RepairStatusMemo: "Waiting on back ordered parts", + }, + }, + // RepairOrderNotes: { + // RepairOrderNote: { + // LineSequenceNum: 1, + // Note: "Revision Requested : approved--but needs est separated.8/22/2008 11:58:53 AM", + // CreateDateTime: "2008-08-22T11:58:53", + // AuthoredBy: { + // FirstName: { + // "#text": "Elizabeth/FirstName>", + // LastName: "Unis", + // }, + // }, + // RepairOrderNote: { + // LineSequenceNum: 2, + // Note: "Approved : 8/26/2008 12:21:08 PM", + // CreateDateTime: "2008-08-26T12:21:08", + // AuthoredBy: { + // FirstName: { + // "#text": "Elizabeth/FirstName>", + // LastName: "Unis", + // }, + // }, + // }, + // }, + // }, + }; + + deleteNullKeys(obj); + + try { + const entegralSoapClient = await soap.createClientAsync( + entegralEndpoint, + { + ignoredNamespaces: true, + wsdl_options: { + // useEmptyTag: true, + }, + wsdl_headers: { + Authorization: `Basic ${new Buffer.from( + `${process.env.ENTEGRAL_USER}:${process.env.ENTEGRAL_PASSWORD}` + ).toString("base64")}`, + }, + } + ); + + entegralSoapClient.setSecurity( + new soap.BasicAuthSecurity( + process.env.ENTEGRAL_USER, + process.env.ENTEGRAL_PASSWORD + ) + ); + + const entegralResponse = + await entegralSoapClient.RepairOrderFolderAddRqAsync( + obj, + function (err, result, rawResponse, soapHeader, rawRequest) { + fs.writeFileSync(`./logs/arms-request.xml`, rawRequest); + fs.writeFileSync(`./logs/arms-response.xml`, rawResponse); + + if (err) { + sendServerEmail({ + subject: `ARMS Update Failed: ${bodyshop.shopname} - ${job.ro_number}`, + text: `Error: ${JSON.stringify(error)}`, + }); + } + + res.status(200).json(err || result); + } + ); + + const [result, rawResponse, , rawRequest] = entegralResponse; + } catch (error) { + fs.writeFileSync(`./logs/${xmlObj.filename}`, xmlObj.xml); + console.log(error); + } + } catch (error) { + logger.log("arms-failed-job", "ERROR", "api", job.shopid, { + job: JSON.stringify({ id: job.id, ro_number: job.ro_number }), + }); + } + + res.sendStatus(200); + return; const allErrors = []; try { for (const bodyshop of bodyshops) { @@ -42,772 +890,6 @@ exports.default = async (req, res) => { }); const jobsToPush = []; - jobs.forEach((job) => { - const transId = uuid(); // Can this actually be the job id? - - let obj = { - RqUID: transId, - DocumentInfo: { - BMSVer: "4.0.0", - DocumentType: "RO", - DocumentVerCode: "EM", - DocumentVerNum: GetSupplementNumber(job.joblines), //TODO Get Supplement Number - DocumentStatus: GetDocumentstatus(job, bodyshop), - CreateDateTime: moment().format(momentFormat), - TransmitDateTime: moment().format(momentFormat), // Omitted from ARMS docs - }, - EventInfo: { - AssignmentEvent: { - CreateDateTime: - job.asgn_date && moment(job.asgn_date).format(momentFormat), - }, - // EstimateEvent: { - // UploadDateTime: moment().format(momentFormat), - // }, - RepairEvent: { - CreatedDateTime: (job.date_open - ? moment(job.date_open).tz(bodyshop.timezone) - : moment() - ).format(momentFormat), - ArrivalDateTime: - job.actual_in && - moment(job.actual_in) - .tz(bodyshop.timezone) - .format(momentFormat), - ArrivalOdometerReading: job.kmin, - TargetCompletionDateTime: - job.scheduled_completion && - moment(job.scheduled_completion) - .tz(bodyshop.timezone) - .format(momentFormat), - ActualCompletionDateTime: - job.actual_completion && - moment(job.actual_completion) - .tz(bodyshop.timezone) - .format(momentFormat), - ActualPickUpDateTime: - job.actual_delivery && - moment(job.actual_delivery) - .tz(bodyshop.timezone) - .format(momentFormat), - CloseDateTime: - job.date_exported && - moment(job.date_exported) - .tz(bodyshop.timezone) - .format(momentFormat), - }, - }, - RepairOrderHeader: { - AdminInfo: { - InsuranceCompany: { - Party: { - OrgInfo: { - CompanyName: job.ins_co_nm, - IDInfo: { - IDQualifierCode: "US", - IDNum: 44, // ** Not sure where to get this entegral ID from? - }, - // Communications: [ - // { - // CommQualifier: "WA", - // Address: { - // Address1: job.ins_addr1, - // Address2: job.ins_addr2, - // City: job.ins_city, - // StateProvince: job.ins_st, - // PostalCode: job.ins_zip, - // CountryCode: job.ins_ctry, - // }, - // }, - // { - // CommQualifier: "WP", - // CommPhone: job.ins_ph1, - // }, - // { - // CommQualifier: "WF", - // CommPhone: job.ins_ph2, - // }, - // ], - }, - // ContactInfo: { - // ContactJobTitle: "Adjuster", - // ContactName: { - // FirstName: job.est_ct_fn, - // LastName: job.est_ct_ln, - // }, - // }, - }, - }, - // InsuranceAgent: { - // Party: { - // OrgInfo: { - // CompanyName: "Nationwide Insurance", - // Communications: { - // CommQualifier: "WP", - // CommPhone: "714-5551212", - // }, - // }, - // ContactInfo: { - // ContactJobTitle: "Insurance Agent", - // ContactName: { - // FirstName: "Paul", - // LastName: "White", - // }, - // }, - // }, - // }, - // Insured: { - // Party: { - // PersonInfo: { - // PersonName: { - // FirstName: job.insd_fn, - // LastName: job.insd_ln, - // }, - // }, - // }, - // }, - Owner: { - Party: { - PersonInfo: { - PersonName: { - FirstName: job.ownr_fn, - LastName: job.ownr_ln, - }, - // Communications: [ - // { - // CommQualifier: "HA", - // Address: { - // Address1: job.ownr_addr1, - - // City: job.ownr_city, - // StateProvince: job.ownr_st, - // PostalCode: job.ownr_zip, - // CountryCode: job.ownr_ctry, - // }, - // }, - // { - // CommQualifier: "HP", - // CommPhone: job.ownr_ph1, - // }, - // { - // CommQualifier: "WP", - // CommPhone: job.ownr_ph2, - // }, - // { - // CommQualifier: "CP", - // CommPhone: job.ownr_ph1, - // }, - // { - // CommQualifier: "EM", - // CommEmail: job.ownr_ea, - // }, - // ], - }, - }, - }, - // Claimant: { - // Party: { - // PersonInfo: { - // PersonName: { - // FirstName: job.clm_ct_fn, - // LastName: job.clm_ct_ln, - // }, - // }, - // }, - // OwnerInd: true, - // }, - // Estimator: { - // Party: { - // PersonInfo: { - // PersonName: { - // FirstName: job.est_ct_fn, - // LastName: job.est_ct_ln, - // }, - // // IDInfo: { - // // IDQualifierCode: "US", - // // IDNum: 2941, - // // }, - // }, - // }, - // }, - RepairFacility: { - Party: { - OrgInfo: { - CompanyName: - process.env.NODE_ENV === "production" - ? bodyshop.shopname - : "IMEX Test Shop", - IDInfo: { - IDQualifierCode: "US", - IDNum: bodyshop.entegral_id, - }, - }, - }, - }, - }, - RepairOrderIDs: { - RepairOrderNum: job.ro_number, - // VendorCode: "C", - // EstimateDocumentID: "1223HJ76", - }, - RepairOrderType: "DirectRepairProgram", //Need to get from Entegral - //ReferralSourceType: "Yellow Pages", - VehicleInfo: { - VINInfo: { - VIN: { - VINNum: job.v_vin, - }, - }, - License: { - LicensePlateNum: job.plate_no, - }, - VehicleDesc: { - //ProductionDate: "2009-10", - ModelYear: - parseInt(job.v_model_yr) < 1900 - ? parseInt(job.v_model_yr) < - moment().tz(bodyshop.timezone).format("YY") - ? `20${job.v_model_yr}` - : `19${job.v_model_yr}` - : job.v_model_yr, - MakeDesc: job.v_make_desc, - ModelName: job.v_model_desc, - }, - // Paint: { - // Exterior: { - // Color: { - // ColorName: job.v_color, - // // OEMColorCode: "1M3", - // }, - // }, - // }, - // Body: { - // BodyStyle: "2 Door Convertible", - // Trim: { - // TrimCode: "1B3", - // }, - // }, - // Condition: { - // DrivableInd: job.driveable ? "Y" : "N", - // }, - }, - ClaimInfo: { - ClaimNum: job.clm_no, - PolicyInfo: { - PolicyNum: job.policy_no, - }, - LossInfo: { - Facts: { - LossDateTime: - job.loss_date && - moment(job.loss_date) - .tz(bodyshop.timezone) - .format(momentFormat), - LossDescCode: "Collision", - PrimaryPOI: { - POICode: job.area_of_damage && job.area_of_damage.impact1, - }, - SecondaryPOI: { - POICode: job.area_of_damage && job.area_of_damage.impact2, - }, - }, - TotalLossInd: job.tlos_ind, - }, - }, - }, - ProfileInfo: { - ProfileName: "ImEX", - RateInfo: [ - { - RateType: "PA", - RateDesc: "Parts Tax", - TaxInfo: { - TaxType: "LS", - TaxableInd: true, - TaxTierInfo: { - TierNum: 1, - Percentage: job.parts_tax_rates.PAN.prt_tax_rt * 100, //TODO Find the best place to take the tax rates for parts. - }, - }, - }, - { - RateType: "LA", - RateDesc: "Labor Tax", - TaxInfo: { - TaxType: "LS", - TaxableInd: true, - TaxTierInfo: { - TierNum: 1, - Percentage: job.parts_tax_rates.PAN.prt_tax_rt * 100, //TODO Find the best place to take the tax rates for labor. - }, - }, - }, - { - RateType: "LAB", - RateDesc: "Body Labor", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_lab, - }, - }, - { - RateType: "LAS", - RateDesc: "Structural Labor", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_las, - }, - }, - { - RateType: "LAR", - RateDesc: "Refinish Labor", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_lar, - }, - }, - { - RateType: "LAG", - RateDesc: "Glass Labor", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_lag, - }, - }, - { - RateType: "LAF", - RateDesc: "Frame Labor", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_laf, - }, - }, - { - RateType: "LAM", - RateDesc: "Mechancial Labor", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_lam, - }, - }, - { - RateType: "LAU", - RateDesc: "User Defined Labor", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_lau, - }, - }, - { - RateType: "MAPA", - RateDesc: "Paint Materials", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_mapa, - ThresholdAmt: 0, - }, - MaterialCalcSettings: { - CalcMethodCode: 2, - CalcMaxAmt: 9999.99, //TODO Find threshold amts. - }, - }, - { - RateType: "MASH", - RateDesc: "Shop Materials", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_mash, - }, - MaterialCalcSettings: { - CalcMethodCode: 4, - CalcMaxAmt: 9999.99, //TODO Find threshold amounts. - }, - }, - { - RateType: "MAHW", - RateDesc: "Hazardous Wastes Removal", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_mahw, - }, - MaterialCalcSettings: { - //Todo Capture Calc Settings - CalcMethodCode: 2, - CalcMaxAmt: 10, - }, - }, - { - RateType: "MA2S", - RateDesc: "Two Stage Paint", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_ma2s, - }, - MaterialCalcSettings: { - CalcMethodCode: 1, - CalcMaxAmt: 999999.99, - }, - }, - { - RateType: "MA2T", - RateDesc: "Two Tone Paint", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_ma2t, - }, - MaterialCalcSettings: { - CalcMethodCode: 1, - CalcMaxAmt: 999999.99, - }, - }, - { - RateType: "MA3S", - RateDesc: "Three Stage Paint", - RateTierInfo: { - TierNum: 1, - Rate: job.rate_ma3s, - }, - MaterialCalcSettings: { - CalcMethodCode: 1, - CalcMaxAmt: 999999.99, - }, - }, - ], - }, - //StorageDuration: 17, - RepairTotalsInfo: { - LaborTotalsInfo: [ - { - TotalType: "LAB", - TotalTypeDesc: "Body Labor", - TotalHours: job.job_totals.rates.lab.hours, - TotalAmt: Dinero(job.job_totals.rates.lab.total).toFormat( - "0.00" - ), - }, - { - TotalType: "LAF", - TotalTypeDesc: "Frame Labor", - TotalHours: job.job_totals.rates.laf.hours, - TotalAmt: Dinero(job.job_totals.rates.laf.total).toFormat( - "0.00" - ), - }, - { - TotalType: "LAM", - TotalTypeDesc: "Mechanical Labor", - TotalHours: job.job_totals.rates.lam.hours, - TotalAmt: Dinero(job.job_totals.rates.lam.total).toFormat( - "0.00" - ), - }, - { - TotalType: "LAR", - TotalTypeDesc: "Refinish Labor", - TotalHours: job.job_totals.rates.lar.hours, - TotalAmt: Dinero(job.job_totals.rates.lar.total).toFormat( - "0.00" - ), - }, - ], - PartsTotalsInfo: [ - { - TotalType: "PAA", - TotalTypeDesc: "Aftermarket Parts", - TotalAmt: Dinero( - job.job_totals.parts.parts.list.PAA && - job.job_totals.parts.parts.list.PAA.total - ).toFormat("0.00"), - }, - { - TotalType: "PAC", - TotalTypeDesc: "Re-Chromed Parts", - TotalAmt: Dinero( - job.job_totals.parts.parts.list.PAC && - job.job_totals.parts.parts.list.PAC.total - ).toFormat("0.00"), - }, - { - TotalType: "PAG", - TotalTypeDesc: "Glass Parts", - TotalAmt: Dinero( - job.job_totals.parts.parts.list.PAG && - job.job_totals.parts.parts.list.PAG.total - ).toFormat("0.00"), - }, - { - TotalType: "PAL", - TotalTypeDesc: "LKQ/Used Parts", - TotalAmt: Dinero( - job.job_totals.parts.parts.list.PAL && - job.job_totals.parts.parts.list.PAL.total - ).toFormat("0.00"), - }, - { - TotalType: "PAM", - TotalTypeDesc: "Remanufactured Parts", - TotalAmt: Dinero( - job.job_totals.parts.parts.list.PAM && - job.job_totals.parts.parts.list.PAM.total - ).toFormat("0.00"), - }, - { - TotalType: "PAN", - TotalTypeDesc: "New Parts", - TotalAmt: Dinero( - job.job_totals.parts.parts.list.PAN && - job.job_totals.parts.parts.list.PAN.total - ).toFormat("0.00"), - }, - { - TotalType: "PAR", - TotalTypeDesc: "Recored Parts", - TotalAmt: Dinero( - job.job_totals.parts.parts.list.PAR && - job.job_totals.parts.parts.list.PAR.total - ).toFormat("0.00"), - }, - ], - OtherChargesTotalsInfo: [ - { - TotalType: "OTSL", - TotalTypeDesc: "Sublet", - TotalAmt: Dinero(job.job_totals.parts.sublets.total).toFormat( - "0.00" - ), - }, - { - TotalType: "MAPA", - TotalTypeDesc: "Paint Materials", - TotalAmt: Dinero(job.job_totals.rates.mapa.total).toFormat( - "0.00" - ), - }, - { - TotalType: "MASH", - TotalTypeDesc: "Shop Materials", - TotalAmt: Dinero(job.job_totals.rates.mash.total).toFormat( - "0.00" - ), - }, - // { - // TotalType: "MAHW", - // TotalTypeDesc: "Hazardous Wastes Removal", - // TotalAmt: Dinero(job.job_totals.rates.mahw.total).toFormat( - // 0.0 - // ), - // }, - { - TotalType: "OTST", - TotalTypeDesc: "Storage", - TotalAmt: Dinero(job.job_totals.additional.storage).toFormat( - "0.00" - ), - }, - { - TotalType: "OTTW", - TotalTypeDesc: "Towing", - TotalAmt: Dinero(job.job_totals.additional.towing).toFormat( - "0.00" - ), - }, - { - TotalType: "OTAC", - TotalTypeDesc: "Additional Charges", - TotalAmt: Dinero( - job.job_totals.additional.additionalCosts - ).toFormat("0.00"), - }, - ], - SummaryTotalsInfo: [ - { - TotalType: "TOT", - TotalSubType: "TT", - TotalTypeDesc: "Gross Total", - TotalAmt: Dinero( - job.job_totals.totals.total_repairs - ).toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "T2", - TotalTypeDesc: "Net Total", - TotalAmt: Dinero(job.job_totals.totals.subtotal).toFormat( - "0.00" - ), - }, - { - TotalType: "TOT", - TotalSubType: "SM", - TotalTypeDesc: "Supplement Total", - TotalAmt: job.cieca_ttl - ? job.cieca_ttl.data.supp_amt - : Dinero().toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "F7", - TotalTypeDesc: "Sales Tax", - TotalAmt: Dinero(job.job_totals.totals.state_tax).toFormat( - "0.00" - ), - }, - { - TotalType: "TOT", - TotalSubType: "GST", - TotalTypeDesc: "GST Tax", - TotalAmt: Dinero(job.job_totals.totals.federal_tax).toFormat( - "0.00" - ), - }, - { - TotalType: "TOT", - TotalSubType: "D8", - TotalTypeDesc: "Bottom Line Discount", - TotalAmt: Dinero( - job.job_totals.additional.adjustments - ).toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "D2", - TotalTypeDesc: "Deductible", - TotalAmt: Dinero({ - amount: Math.round((job.ded_amt || 0) * 100), - }).toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "BTR", - TotalTypeDesc: "Betterment", - TotalAmt: Dinero( - job.job_totals.totals.custPayable.dep_taxes - ).toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "AA", - TotalTypeDesc: "Appearance Allowance", - TotalAmt: Dinero().toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "DEPOSIT", - TotalTypeDesc: "Deposit", - TotalAmt: Dinero().toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "INS", - TotalTypeDesc: "Insurance Pay", - TotalAmt: Dinero(job.job_totals.totals.total_repairs) - .subtract(Dinero(job.job_totals.totals.custPayable.total)) - .toFormat("0.00"), - }, - { - TotalType: "TOT", - TotalSubType: "CUST", - TotalTypeDesc: "Customer Pay", - TotalAmt: Dinero( - job.job_totals.totals.custPayable.total - ).toFormat("0.00"), - }, - ], - // RepairTotalsType: 1, - }, - // RepairLabor: { - // LaborAllocations: { - // LaborAllocation: [ - // { - // LaborAllocationUUID: - // "426cce3a-efa7-44d9-b76e-50b9102c4198", - // LaborType: "LAB", - // Technician: { - // Employee: { - // PersonInfo: { - // PersonName: { - // FirstName: "Jose", - // LastName: "Gonzalez", - // }, - // IDInfo: { - // IDQualifierCode: "US", - // IDNum: 2987, - // }, - // }, - // }, - // }, - // AllocatedHours: 3.5, - // }, - // { - // LaborAllocationUUID: - // "426cce3a-efa7-44d9-b76e-50b9102c4199", - // LaborType: "LAR", - // Technician: { - // Employee: { - // PersonInfo: { - // PersonName: { - // FirstName: "Rcardo", - // LastName: "Himenez", - // }, - // IDInfo: { - // IDQualifierCode: "US", - // IDNum: 2989, - // }, - // }, - // }, - // }, - // AllocatedHours: 5.5, - // }, - // ], - // }, - // }, - ProductionStatus: { - ProductionStage: { - ProductionStageCode: GetProductionStageCode(job, bodyshop), - ProductionStageDateTime: moment() - .tz(bodyshop.timezone) - .format(momentFormat), - // ProductionStageStatusComment: - // "Going to be painted this afternoon", - }, - RepairStatus: { - RepairStatusCode: GetRepairStatusCode(job), - RepairStatusDateTime: moment() - .tz(bodyshop.timezone) - .format(momentFormat), - // RepairStatusMemo: "Waiting on back ordered parts", - }, - }, - // RepairOrderNotes: { - // RepairOrderNote: { - // LineSequenceNum: 1, - // Note: "Revision Requested : approved--but needs est separated.8/22/2008 11:58:53 AM", - // CreateDateTime: "2008-08-22T11:58:53", - // AuthoredBy: { - // FirstName: { - // "#text": "Elizabeth/FirstName>", - // LastName: "Unis", - // }, - // }, - // RepairOrderNote: { - // LineSequenceNum: 2, - // Note: "Approved : 8/26/2008 12:21:08 PM", - // CreateDateTime: "2008-08-26T12:21:08", - // AuthoredBy: { - // FirstName: { - // "#text": "Elizabeth/FirstName>", - // LastName: "Unis", - // }, - // }, - // }, - // }, - // }, - }; - - deleteNullKeys(obj); - jobsToPush.push(obj); - }); - if (erroredJobs.length > 0) { logger.log("arms-failed-jobs", "ERROR", "api", bodyshop.id, { count: erroredJobs.length, @@ -887,6 +969,7 @@ exports.default = async (req, res) => { }; function GetSupplementNumber(joblines) { + if (!joblines) return 0; const max = _.max( joblines.map((jl) => parseInt((jl.line_ind || "0").replace(/[^\d.-]/g, ""))) ); diff --git a/server/utils/logger.js b/server/utils/logger.js index 0dae8af18..e6694c8e5 100644 --- a/server/utils/logger.js +++ b/server/utils/logger.js @@ -5,7 +5,7 @@ const logger = new graylog2.graylog({ }); function log(message, type, user, record, object) { - if (type !== "ioevent" && type !== "DEBUG") + if (type !== "ioevent") console.log(message, { type, env: process.env.NODE_ENV || "development", diff --git a/yarn.lock b/yarn.lock index 7164116d2..c4f61cfb2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2715,6 +2715,11 @@ node-mailjet@^5.1.0: json-bigint "^1.0.0" url-join "^4.0.0" +node-persist@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/node-persist/-/node-persist-3.1.0.tgz#9d4b03950bba70d37d13d3d3551840e25fd17e09" + integrity sha512-/j+fd/u71wNgKf3V2bx4tnDm+3GvLnlCuvf2MXbJ3wern+67IAb6zN9Leu1tCWPlPNZ+v1hLSibVukkPK2HqJw== + node-quickbooks@^2.0.39: version "2.0.39" resolved "https://registry.yarnpkg.com/node-quickbooks/-/node-quickbooks-2.0.39.tgz#a2534d24063e8a0cea5bb80c66b0727c1c942081"