IO-256 Begin QBO Changes for Individual code mapping on receivables.

This commit is contained in:
Patrick Fic
2021-09-23 16:22:59 -07:00
parent e95cf0a026
commit 186f6101ff
6 changed files with 573 additions and 744 deletions

View File

@@ -12,10 +12,10 @@
"@openreplay/tracker-assist": "^3.1.1",
"@openreplay/tracker-graphql": "^3.0.0",
"@openreplay/tracker-redux": "^3.0.0",
"@sentry/react": "^6.13.0",
"@sentry/tracing": "^6.13.0",
"@stripe/react-stripe-js": "^1.4.0",
"@stripe/stripe-js": "^1.17.1",
"@sentry/react": "^6.13.2",
"@sentry/tracing": "^6.13.2",
"@stripe/react-stripe-js": "^1.5.0",
"@stripe/stripe-js": "^1.18.0",
"@tanem/react-nprogress": "^3.0.79",
"antd": "^4.16.13",
"apollo-link-logger": "^2.0.0",
@@ -27,10 +27,10 @@
"env-cmd": "^10.1.0",
"exifr": "^7.1.3",
"firebase": "^9.0.2",
"graphql": "^15.5.3",
"i18next": "^21.0.0",
"graphql": "^15.6.0",
"i18next": "^21.0.2",
"i18next-browser-languagedetector": "^6.1.2",
"jsoneditor": "^9.5.4",
"jsoneditor": "^9.5.6",
"jsreport-browser-client-dist": "^1.3.0",
"libphonenumber-js": "^1.9.34",
"logrocket": "^2.0.0",
@@ -59,13 +59,13 @@
"react-scripts": "^4.0.3",
"react-sublime-video": "^0.2.5",
"react-virtualized": "^9.22.3",
"recharts": "^2.1.3",
"recharts": "^2.1.4",
"redux": "^4.1.1",
"redux-persist": "^6.0.0",
"redux-saga": "^1.1.3",
"redux-state-sync": "^3.1.2",
"reselect": "^4.0.0",
"sass": "^1.41.1",
"sass": "^1.42.1",
"socket.io-client": "^4.2.0",
"styled-components": "^5.3.1",
"subscriptions-transport-ws": "^0.9.18",

View File

@@ -2178,14 +2178,14 @@
estree-walker "^1.0.1"
picomatch "^2.2.2"
"@sentry/browser@6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.13.0.tgz#fddcf1997d47c166a86494a6ea594f4cc60e773d"
integrity sha512-Eh0k2qYhqWiEP3N04AwSrpl4VRD0pzt6SRgJxgiGzSvBT43EOjyNQ3xzMylAechfjSCTWmzZMvwcgT5fNM9cuw==
"@sentry/browser@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.13.2.tgz#8b731ecf8c3cdd92a4b6893a26f975fd5844056d"
integrity sha512-bkFXK4vAp2UX/4rQY0pj2Iky55Gnwr79CtveoeeMshoLy5iDgZ8gvnLNAz7om4B9OQk1u7NzLEa4IXAmHTUyag==
dependencies:
"@sentry/core" "6.13.0"
"@sentry/types" "6.13.0"
"@sentry/utils" "6.13.0"
"@sentry/core" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
tslib "^1.9.3"
"@sentry/cli@^1.68.0":
@@ -2200,69 +2200,69 @@
progress "^2.0.3"
proxy-from-env "^1.1.0"
"@sentry/core@6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.13.0.tgz#35df709bb5c1979cc05a4dd0bbe8b15fb973ad6f"
integrity sha512-Aw0ljRJx5tq4w6ZXxvcu2Lr9NwD+MJ1SLL5+oB1hh4OlcOJ7OLwDjtJ3+ZOwp75GCAp7phh4+s/Sql6roX3Lpw==
"@sentry/core@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.13.2.tgz#2ce164f81667aa89cd116f807d772b4718434583"
integrity sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ==
dependencies:
"@sentry/hub" "6.13.0"
"@sentry/minimal" "6.13.0"
"@sentry/types" "6.13.0"
"@sentry/utils" "6.13.0"
"@sentry/hub" "6.13.2"
"@sentry/minimal" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
tslib "^1.9.3"
"@sentry/hub@6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.13.0.tgz#076a5f9b6d0efb8c1832820e3eecd5e24b5e1706"
integrity sha512-BmKgrTyotF008KPfFt1ySyFg0AAMf/ha9Bz9Rmi+usSJjnOLsObzBJQNAozp4Cu6i1kGvj1/R+ymPCD61Gqozw==
"@sentry/hub@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.13.2.tgz#ebc66fd55c96c7686a53ffd3521b6a63f883bb79"
integrity sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A==
dependencies:
"@sentry/types" "6.13.0"
"@sentry/utils" "6.13.0"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
tslib "^1.9.3"
"@sentry/minimal@6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.13.0.tgz#276fc0ee5355954c2a9d9292d914988391f8a1e1"
integrity sha512-eJQs44sGY2wFuVDznHMDeShR+ZbnM/KS+T5753nJ4QtMqCNTiG9WDlNXAxwFJ6Q3DORtaxcWHyFZdOMUusJiZQ==
"@sentry/minimal@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.13.2.tgz#de3ecc62b9463bf56ccdbcf4c75f7ea1aeeebc11"
integrity sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw==
dependencies:
"@sentry/hub" "6.13.0"
"@sentry/types" "6.13.0"
"@sentry/hub" "6.13.2"
"@sentry/types" "6.13.2"
tslib "^1.9.3"
"@sentry/react@^6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.13.0.tgz#110aada56a5f952b63f8ce94ce0c71792bcffd4a"
integrity sha512-Pkkq2YQn7uvqHX+OvoGrd9Nq0ixrQyixm2SI0BjptDXkZ6AqlI+fhhP8Mm+ezBgPT9WqO2+BUW/YivyTjVYwHg==
"@sentry/react@^6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.13.2.tgz#481f1549b1509b4d94eb943934ebeba6430a1a8f"
integrity sha512-aLkWyn697LTcmK1PPnUg5UJcyBUPoI68motqgBY53SIYDAwOeYNUQt2aanDuOTY5aE2PdnJwU48klA8vuYkoRQ==
dependencies:
"@sentry/browser" "6.13.0"
"@sentry/minimal" "6.13.0"
"@sentry/types" "6.13.0"
"@sentry/utils" "6.13.0"
"@sentry/browser" "6.13.2"
"@sentry/minimal" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
hoist-non-react-statics "^3.3.2"
tslib "^1.9.3"
"@sentry/tracing@^6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.13.0.tgz#3d9fac18c2d6829ba14178729d4a7ac770462e3e"
integrity sha512-nTY8UnVK6OUh4ocONtphoaK3WXBZqw0HOFyFpBSzhldo4O1jLad1OEkz8vAxrIE9sXPmLWta5CtKq6PIaFwQSg==
"@sentry/tracing@^6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.13.2.tgz#512389ba459f48ae75e14f1528ab062dc46e4956"
integrity sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw==
dependencies:
"@sentry/hub" "6.13.0"
"@sentry/minimal" "6.13.0"
"@sentry/types" "6.13.0"
"@sentry/utils" "6.13.0"
"@sentry/hub" "6.13.2"
"@sentry/minimal" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
tslib "^1.9.3"
"@sentry/types@6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.13.0.tgz#a8ad870c6ecb407cbe9ca883b0688bacb30daacf"
integrity sha512-04ZVmz4txuI3w1KS81eByppvvMfOINj7jZYnO5zX/S3cjHiOpAJiZkN/k9tTi1Ua3td8bEkQLB6Cxrq9MSiH3Q==
"@sentry/types@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.13.2.tgz#8388d5b92ea8608936e7aae842801dc90e0184e6"
integrity sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg==
"@sentry/utils@6.13.0":
version "6.13.0"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.13.0.tgz#c75647890a5a9dfdb3df321517aa4886c8715b03"
integrity sha512-e82DBwjYqWkNmafIkHnbqirK4t7WCmqCGaoo1Et6vTRCBS4GthWvS6EzaozY7EKs/TzsfIiDdTLGTbYMQOq9Zw==
"@sentry/utils@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.13.2.tgz#fb8010e7b67cc8c084d8067d64ef25289269cda5"
integrity sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w==
dependencies:
"@sentry/types" "6.13.0"
"@sentry/types" "6.13.2"
tslib "^1.9.3"
"@sentry/webpack-plugin@^1.17.1":
@@ -2291,17 +2291,17 @@
resolved "https://registry.yarnpkg.com/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz#03ecc29279e3c0c832f6185a5bfa3497858ac8ca"
integrity sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==
"@stripe/react-stripe-js@^1.4.0":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.4.1.tgz#884d59286fff00ba77389b32c045516f65d7a340"
integrity sha512-FjcVrhf72+9fUL3Lz3xi02ni9tzH1A1x6elXlr6tvBDgSD55oPJuodoP8eC7xTnBIKq0olF5uJvgtkJyDCdzjA==
"@stripe/react-stripe-js@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.5.0.tgz#7e4d80077e88e1f2c1f10ac255f2838d7c9488c2"
integrity sha512-A7+bNeb0O/kw3JdtMeiB6frokPcks5obi+TIjuFRXUMZ5o/o1Qe7eLgLnsb0KOO/g3KJqNCpHiYcKCLESZJJbQ==
dependencies:
prop-types "^15.7.2"
"@stripe/stripe-js@^1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.17.1.tgz#afcb7e86d0b05d1a7af53af89111abd2e8d437ae"
integrity sha512-c9MyDvdi5Xou0j0JPNy86NebtTDfh9o62Ifuzx6GSm2YO0oedBpy51WSyOue2L8Fb+mqESS5gd6mGVEIPUnXsA==
"@stripe/stripe-js@^1.18.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.18.0.tgz#687268d7cd68b44b92b86300d7c7f2a6e4df0b98"
integrity sha512-yBRHAMKHnF3kbzv0tpKB82kSow43wW5qXLK8ofg3V9NaaCyObSTO7wJfktWAtG/NBgkJOdUL+pV8dHBj0qvDkQ==
"@surma/rollup-plugin-off-main-thread@^1.1.1":
version "1.4.2"
@@ -2472,41 +2472,41 @@
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803"
integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==
"@types/d3-color@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.0.2.tgz#53f2d6325f66ee79afd707c05ac849e8ae0edbb0"
integrity sha512-WVx6zBiz4sWlboCy7TCgjeyHpNjMsoF36yaagny1uXfbadc9f+5BeBf7U+lRmQqY3EHbGQpP8UdW8AC+cywSwQ==
"@types/d3-color@^2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-2.0.3.tgz#8bc4589073c80e33d126345542f588056511fe82"
integrity sha512-+0EtEjBfKEDtH9Rk3u3kLOUXM5F+iZK+WvASPb0MhIZl8J8NUvGeZRwKCXl+P3HkYx5TdU4YtcibpqHkSR9n7w==
"@types/d3-interpolate@^3.0.0":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc"
integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==
"@types/d3-interpolate@^2.0.0":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-2.0.2.tgz#78eddf7278b19e48e8652603045528d46897aba0"
integrity sha512-lElyqlUfIPyWG/cD475vl6msPL4aMU7eJvx1//Q177L8mdXoVPFl1djIESF2FKnc0NyaHvQlJpWwKJYwAhUoCw==
dependencies:
"@types/d3-color" "*"
"@types/d3-color" "^2"
"@types/d3-path@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.0.tgz#939e3a784ae4f80b1fde8098b91af1776ff1312b"
integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==
"@types/d3-path@^2":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-2.0.1.tgz#ca03dfa8b94d8add97ad0cd97e96e2006b4763cb"
integrity sha512-6K8LaFlztlhZO7mwsZg7ClRsdLg3FJRzIIi6SZXDWmmSJc2x8dd2VkESbLXdk3p8cuvz71f36S0y8Zv2AxqvQw==
"@types/d3-scale@^4.0.0":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.1.tgz#fbe8238e2eff27af577d2b7d0b933ae50a546970"
integrity sha512-GDuXcRcR6mKcpUVMhPNttpOzHi2dP6YcDqLZYSZHgwTZ+sfCa8e9q0VEBwZomblAPNMYpVqxojnSyIEb4s/Pwg==
"@types/d3-scale@^3.0.0":
version "3.3.2"
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-3.3.2.tgz#18c94e90f4f1c6b1ee14a70f14bfca2bd1c61d06"
integrity sha512-gGqr7x1ost9px3FvIfUMi5XA/F/yAf4UkUDtdQhpH92XCT0Oa7zkkRzY61gPVJq+DxpHn/btouw5ohWkbBsCzQ==
dependencies:
"@types/d3-time" "*"
"@types/d3-time" "^2"
"@types/d3-shape@^3.0.0":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.0.2.tgz#4b1ca4ddaac294e76b712429726d40365cd1e8ca"
integrity sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw==
"@types/d3-shape@^2.0.0":
version "2.1.3"
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-2.1.3.tgz#35d397b9e687abaa0de82343b250b9897b8cacf3"
integrity sha512-HAhCel3wP93kh4/rq+7atLdybcESZ5bRHDEZUojClyZWsRuEMo3A52NGYJSh48SxfxEU6RZIVbZL2YFZ2OAlzQ==
dependencies:
"@types/d3-path" "*"
"@types/d3-path" "^2"
"@types/d3-time@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819"
integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==
"@types/d3-time@^2":
version "2.1.1"
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-2.1.1.tgz#743fdc821c81f86537cbfece07093ac39b4bc342"
integrity sha512-9MVYlmIgmRR31C5b4FVSWtuMmBHh2mOWQYfl7XAYOa8dsnb7iEmUmRSWSFgXFtkjxO65d7hTUHQC+RhR/9IWFg==
"@types/eslint@^7.2.6":
version "7.28.0"
@@ -5000,76 +5000,76 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
"d3-array@2 - 3", "d3-array@2.10.0 - 3":
version "3.0.4"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.0.4.tgz#60550bcc9818be9ace88d269ccd97038fc399b55"
integrity sha512-ShFl90cxNqDaSynDF/Bik/kTzISqePqU3qo2fv6kSJEvF7y7tDCDpcU6WiT01rPO6zngZnrvJ/0j4q6Qg+5EQg==
d3-array@2, d3-array@^2.3.0:
version "2.12.1"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81"
integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==
dependencies:
internmap "1 - 2"
internmap "^1.0.0"
d3-array@^1.2.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
"d3-color@1 - 3":
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.0.1.tgz#03316e595955d1fcd39d9f3610ad41bb90194d0a"
integrity sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw==
"d3-color@1 - 2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e"
integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==
"d3-format@1 - 3":
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.0.1.tgz#e41b81b2ab79277141ec1404aa5d05001da64084"
integrity sha512-hdL7+HBIohpgfolhBxr1KX47VMD6+vVD/oEFrxk5yhmzV2prk99EkFKYpXuhVkFpTgHdJ6/4bYcjdLPPXV4tIA==
"d3-format@1 - 2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767"
integrity sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA==
"d3-interpolate@1.2.0 - 3", d3-interpolate@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
"d3-interpolate@1.2.0 - 2", d3-interpolate@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163"
integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==
dependencies:
d3-color "1 - 3"
d3-color "1 - 2"
"d3-path@1 - 3":
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e"
integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==
"d3-path@1 - 2":
version "2.0.0"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-2.0.0.tgz#55d86ac131a0548adae241eebfb56b4582dd09d8"
integrity sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA==
d3-polygon@^1.0.3:
version "1.0.6"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.6.tgz#0bf8cb8180a6dc107f518ddf7975e12abbfbd38e"
integrity sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==
d3-scale@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.1.tgz#c65aa7a357e4f58954a66e1edacc712bab4b1034"
integrity sha512-akUAsUujCFnw6Sf1dF7y/FXTxz+VvEIOB3ValKtLhNrzFp8q5wPO3VCAmsbCLJWRTxyJCZDoooodjOI1plFqlw==
d3-scale@^3.0.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-3.3.0.tgz#28c600b29f47e5b9cd2df9749c206727966203f3"
integrity sha512-1JGp44NQCt5d1g+Yy+GeOnZP7xHo0ii8zsQp6PGzd+C1/dl0KGsp9A7Mxwp+1D1o4unbTTxVdU/ZOIEBoeZPbQ==
dependencies:
d3-array "2.10.0 - 3"
d3-format "1 - 3"
d3-interpolate "1.2.0 - 3"
d3-time "2.1.1 - 3"
d3-time-format "2 - 4"
d3-array "^2.3.0"
d3-format "1 - 2"
d3-interpolate "1.2.0 - 2"
d3-time "^2.1.1"
d3-time-format "2 - 3"
d3-shape@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.0.1.tgz#9ccdfb28fd9b0d12f2d8aec234cd5c4a9ea27931"
integrity sha512-HNZNEQoDhuCrDWEc/BMbF/hKtzMZVoe64TvisFLDp2Iyj0UShB/E6/lBsLlJTfBMbYgftHj90cXJ0SEitlE6Xw==
d3-shape@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-2.1.0.tgz#3b6a82ccafbc45de55b57fcf956c584ded3b666f"
integrity sha512-PnjUqfM2PpskbSLTJvAzp2Wv4CZsnAgTfcVRTwW03QR3MkXF8Uo7B1y/lWkAsmbKwuecto++4NlsYcvYpXpTHA==
dependencies:
d3-path "1 - 3"
d3-path "1 - 2"
"d3-time-format@2 - 4":
version "4.0.0"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.0.0.tgz#930ded86a9de761702344760d8a25753467f28b7"
integrity sha512-nzaCwlj+ZVBIlFuVOT1RmU+6xb/7D5IcnhHzHQcBgS/aTa5K9fWZNN5LCXA27LgF5WxoSNJqKBbLcGMtM6Ca6A==
dependencies:
d3-time "1 - 3"
"d3-time@1 - 3", "d3-time@2.1.1 - 3":
"d3-time-format@2 - 3":
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975"
integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-3.0.0.tgz#df8056c83659e01f20ac5da5fdeae7c08d5f1bb6"
integrity sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==
dependencies:
d3-array "2 - 3"
d3-time "1 - 2"
"d3-time@1 - 2", d3-time@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.1.1.tgz#e9d8a8a88691f4548e68ca085e5ff956724a6682"
integrity sha512-/eIQe/eR4kCQwq7yxi7z4c6qEXf2IYGcjoWB5OOQy4Tq9Uv39/947qlDcN2TLkiTzQWzvnsuYPB9TrWaNfipKQ==
dependencies:
d3-array "2"
d@1, d@^1.0.1:
version "1.0.1"
@@ -6736,10 +6736,10 @@ graphql-tag@^2.12.3:
dependencies:
tslib "^2.1.0"
graphql@^15.5.3:
version "15.5.3"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.3.tgz#c72349017d5c9f5446a897fe6908b3186db1da00"
integrity sha512-sM+jXaO5KinTui6lbK/7b7H/Knj9BpjGxZ+Ki35v7YbUJxxdBCUqNM0h3CRVU1ZF9t5lNiBzvBCSYPvIwxPOQA==
graphql@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.6.0.tgz#e69323c6a9780a1a4b9ddf7e35ca8904bb04df02"
integrity sha512-WJR872Zlc9hckiEPhXgyUftXH48jp2EjO5tgBBOyNMRJZ9fviL2mJBD6CAysk6N5S0r9BTs09Qk39nnJBkvOXQ==
growly@^1.3.0:
version "1.3.0"
@@ -7093,10 +7093,10 @@ i18next-browser-languagedetector@^6.1.2:
dependencies:
"@babel/runtime" "^7.14.6"
i18next@^21.0.0:
version "21.0.0"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.0.0.tgz#ad730aced7df552515c92b318d16d847c6270612"
integrity sha512-17A00z5ASuOJkPUNSUMaZcfL3zOm2qYiN8UBIYhNYNmPbPrcP+IfabGEFEICv8CCStr/cbjF0Jk/IXNX9hj3ZA==
i18next@^21.0.2:
version "21.0.2"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.0.2.tgz#a394cbd0cc1879a9ad7a4a979a222d12033022cc"
integrity sha512-cSjRitffS1xm90YgPFTaqut89Y4Oc2i4aiCmAuhxHPryYdKzSIGl1YSv8PzlW+UPFOKRIUCOYZ5Rn+aUXKq/qQ==
dependencies:
"@babel/runtime" "^7.12.0"
@@ -7292,10 +7292,10 @@ internal-slot@^1.0.3:
has "^1.0.3"
side-channel "^1.0.4"
"internmap@1 - 2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
internmap@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95"
integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==
invariant@^2.2.4:
version "2.2.4"
@@ -8327,10 +8327,10 @@ json5@^2.1.2:
dependencies:
minimist "^1.2.5"
jsoneditor@^9.5.4:
version "9.5.5"
resolved "https://registry.yarnpkg.com/jsoneditor/-/jsoneditor-9.5.5.tgz#3275b4b327d51c5d6d30e386d326bed4da012a0b"
integrity sha512-q0bnZF8eyM+pXHfQGkI0ATZWI974eeWVLun3nRl4QP1uvaMlc2w9R5UkPerWcHmuX+p0EQLOw/IOWmRT1qHqHQ==
jsoneditor@^9.5.6:
version "9.5.6"
resolved "https://registry.yarnpkg.com/jsoneditor/-/jsoneditor-9.5.6.tgz#b2abca2aeb34bb5291025d0eeddcb2845e0d90a9"
integrity sha512-smu4CKCOeJiizGGGYQ7ZAvCclnuJP7gX/wcoHw/DWiJMUZq+3KjJNDhYnVTRgi+Zk0UlPngA4egmuJre/H2mXg==
dependencies:
ace-builds "^1.4.12"
ajv "^6.12.6"
@@ -11783,18 +11783,18 @@ recharts-scale@^0.4.4:
dependencies:
decimal.js-light "^2.4.1"
recharts@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.1.3.tgz#f7e82b274a569ca3c9665570bd6d4e78a0e8f24e"
integrity sha512-M0i8x+NKI2Bu/DTGm0LH3FzOhk0YJ4dmBY43YX/KIV82CXfkwkJ07obkje8yJbjdKMjEPZnS5K0XdP6VLx/hPw==
recharts@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.1.4.tgz#8d21750e3bb01a909e01ebe5573c48d813c25287"
integrity sha512-ZKaLgUo4g84FhIiLeRq0uWMqe5GTjjJk+5fxmIt2H4cn279QZCMEsuVFmBqYedJcmX1URYEII5qb9pOppr5fJA==
dependencies:
"@types/d3-interpolate" "^3.0.0"
"@types/d3-scale" "^4.0.0"
"@types/d3-shape" "^3.0.0"
"@types/d3-interpolate" "^2.0.0"
"@types/d3-scale" "^3.0.0"
"@types/d3-shape" "^2.0.0"
classnames "^2.2.5"
d3-interpolate "^3.0.0"
d3-scale "^4.0.0"
d3-shape "^3.0.0"
d3-interpolate "^2.0.0"
d3-scale "^3.0.0"
d3-shape "^2.0.0"
eventemitter3 "^4.0.1"
lodash "^4.17.19"
react-is "16.10.2"
@@ -12258,10 +12258,10 @@ sass-loader@^10.0.5:
schema-utils "^3.0.0"
semver "^7.3.2"
sass@^1.41.1:
version "1.41.1"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.41.1.tgz#bca5bed2154192779c29f48fca9c644c60c38d98"
integrity sha512-vIjX7izRxw3Wsiez7SX7D+j76v7tenfO18P59nonjr/nzCkZuoHuF7I/Fo0ZRZPKr88v29ivIdE9BqGDgQD/Nw==
sass@^1.42.1:
version "1.42.1"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.42.1.tgz#5ab17bebc1cb1881ad2e0c9a932c66ad64e441e2"
integrity sha512-/zvGoN8B7dspKc5mC6HlaygyCBRvnyzzgD5khiaCfglWztY99cYoiTUksVx11NlnemrcfH5CEaCpsUKoW0cQqg==
dependencies:
chokidar ">=3.0.0 <4.0.0"

View File

@@ -0,0 +1,378 @@
const DineroQbFormat = require("./accounting-constants").DineroQbFormat;
const Dinero = require("dinero.js");
const logger = require("../utils/logger");
module.exports = function ({
bodyshop,
jobs_by_pk,
qbo = false,
items,
taxCodes,
}) {
const InvoiceLineAdd = [];
const responsibilityCenters = bodyshop.md_responsibility_centers;
const invoiceLineHash = {}; //The hash of cost and profit centers based on the center name.
//Determine if there are MAPA and MASH lines already on the estimate.
//If there are, don't do anything extra (mitchell estimate)
//Otherwise, calculate them and add them to the default MAPA and MASH centers.
let hasMapaLine = false;
let hasMashLine = false;
//Create the invoice lines mapping.
jobs_by_pk.joblines.map((jobline) => {
if (jobline.db_ref === "936008") {
//If either of these DB REFs change, they also need to change in job-totals/job-costing calculations.
hasMapaLine = true;
}
if (jobline.db_ref === "936007") {
hasMashLine = true;
}
//Parts Lines Mappings.
if (jobline.profitcenter_part && jobline.act_price) {
let DineroAmount = Dinero({
amount: Math.round(jobline.act_price * 100),
}).multiply(jobline.part_qty || 1);
if (jobline.prt_dsmk_p && jobline.prt_dsmk_p !== 0) {
// console.log("Have a part discount", jobline);
DineroAmount = DineroAmount.add(
DineroAmount.percentage(Math.abs(jobline.prt_dsmk_p || 0)).multiply(
jobline.prt_dsmk_p > 0 ? 1 : -1
)
);
}
const account = responsibilityCenters.profits.find(
(i) => jobline.profitcenter_part.toLowerCase() === i.name.toLowerCase()
);
if (!account) {
logger.log(
"qbxml-receivables-no-account",
"warn",
null,
jobline.id,
null
);
throw new Error(
`A matching account does not exist for the part allocation. Center: ${jobline.profitcenter_part}`
);
}
if (qbo) {
//Do the mapping as per QBO.
//Determine the Tax code grouping.
//Going to always assume that we need to apply GST.
const taxAccountCode = findTaxCode(
{
local: false,
federal: "true",
state: jobline.tax_part,
},
bodyshop.md_responsibility_centers.sales_tax_codes
);
//GST/PST BC is what comes in, need to find the tax rate reference.
const QboTaxId = taxCodes[taxAccountCode];
if (!invoiceLineHash[account.name]) invoiceLineHash[account.name] = {};
if (!invoiceLineHash[account.name][QboTaxId]) {
invoiceLineHash[account.name][QboTaxId] = {
DetailType: "SalesItemLineDetail",
Amount: DineroAmount,
SalesItemLineDetail: {
ItemRef: {
value: items[account.accountitem],
},
TaxCodeRef: {
value: QboTaxId,
},
Qty: 1,
},
};
} else {
invoiceLineHash[account.name][QboTaxId].Amount =
invoiceLineHash[account.name][QboTaxId].Amount.add(DineroAmount);
}
} else {
if (!invoiceLineHash[account.name]) {
invoiceLineHash[account.name] = {
ItemRef: { FullName: account.accountitem },
Desc: account.accountdesc,
Quantity: 1, //jobline.part_qty,
Amount: DineroAmount, //.toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
};
} else {
invoiceLineHash[account.name].Amount =
invoiceLineHash[account.name].Amount.add(DineroAmount);
}
}
}
//End Parts line mappings.
// Labor Lines
if (jobline.profitcenter_labor && jobline.mod_lb_hrs) {
const DineroAmount = Dinero({
amount: Math.round(
jobs_by_pk[`rate_${jobline.mod_lbr_ty.toLowerCase()}`] * 100
),
}).multiply(jobline.mod_lb_hrs);
const account = responsibilityCenters.profits.find(
(i) => jobline.profitcenter_labor.toLowerCase() === i.name.toLowerCase()
);
if (!account) {
throw new Error(
`A matching account does not exist for the labor allocation. Center: ${jobline.profitcenter_labor}`
);
}
if (qbo) {
//Do some QBO Stuff.
} else {
if (!invoiceLineHash[account.name]) {
invoiceLineHash[account.name] = {
ItemRef: { FullName: account.accountitem },
Desc: account.accountdesc,
Quantity: 1, // jobline.mod_lb_hrs,
Amount: DineroAmount,
//Amount: DineroAmount.toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
};
} else {
invoiceLineHash[account.name].Amount =
invoiceLineHash[account.name].Amount.add(DineroAmount);
}
}
}
});
if (!hasMapaLine && jobs_by_pk.job_totals.rates.mapa.total.amount > 0) {
// console.log("Adding MAPA Line Manually.");
const mapaAccountName = responsibilityCenters.defaults.profits.MAPA;
const mapaAccount = responsibilityCenters.profits.find(
(c) => c.name === mapaAccountName
);
if (mapaAccount) {
if (qbo) {
//Add QBO MAPA
} else {
InvoiceLineAdd.push({
ItemRef: { FullName: mapaAccount.accountitem },
Desc: mapaAccount.accountdesc,
Quantity: 1,
Amount: Dinero(jobs_by_pk.job_totals.rates.mapa.total).toFormat(
DineroQbFormat
),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
} else {
//console.log("NO MAPA ACCOUNT FOUND!!");
}
}
if (!hasMashLine && jobs_by_pk.job_totals.rates.mash.total.amount > 0) {
// console.log("Adding MASH Line Manually.");
const mashAccountName = responsibilityCenters.defaults.profits.MASH;
const mashAccount = responsibilityCenters.profits.find(
(c) => c.name === mashAccountName
);
if (mashAccount) {
if (qbo) {
//do some QBO
} else {
InvoiceLineAdd.push({
ItemRef: { FullName: mashAccount.accountitem },
Desc: mashAccount.accountdesc,
Quantity: 1,
Amount: Dinero(jobs_by_pk.job_totals.rates.mash.total).toFormat(
DineroQbFormat
),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
} else {
// console.log("NO MASH ACCOUNT FOUND!!");
}
}
//Convert the hash to an array.
Object.keys(invoiceLineHash).forEach((key) => {
Object.keys(invoiceLineHash[key]).forEach((key2) => {
InvoiceLineAdd.push({
...invoiceLineHash[key][key2],
Amount: invoiceLineHash[key][key2].Amount.toFormat(DineroQbFormat),
});
});
});
//Add Towing, storage and adjustment lines.
if (jobs_by_pk.towing_payable && jobs_by_pk.towing_payable !== 0) {
if (qbo) {
// do qbo
} else {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["TOW"]
).accountitem,
},
Desc: "Towing",
Quantity: 1,
Amount: Dinero({
amount: Math.round((jobs_by_pk.towing_payable || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
}
if (jobs_by_pk.storage_payable && jobs_by_pk.storage_payable !== 0) {
if (qbo) {
// do qbo
} else {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["TOW"]
).accountitem,
},
Desc: "Storage",
Quantity: 1,
Amount: Dinero({
amount: Math.round((jobs_by_pk.storage_payable || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
}
if (
jobs_by_pk.adjustment_bottom_line &&
jobs_by_pk.adjustment_bottom_line !== 0
) {
if (qbo) {
// do qbo
} else {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["PAO"]
).accountitem,
},
Desc: "Adjustment",
Quantity: 1,
Amount: Dinero({
amount: Math.round((jobs_by_pk.adjustment_bottom_line || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
}
//Add tax lines
const job_totals = jobs_by_pk.job_totals;
const federal_tax = Dinero(job_totals.totals.federal_tax);
const state_tax = Dinero(job_totals.totals.state_tax);
const local_tax = Dinero(job_totals.totals.local_tax);
if (federal_tax.getAmount() > 0) {
if (qbo) {
// do qbo
} else {
InvoiceLineAdd.push({
ItemRef: {
FullName:
bodyshop.md_responsibility_centers.taxes.federal.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.federal.accountdesc,
Amount: federal_tax.toFormat(DineroQbFormat),
});
}
}
if (state_tax.getAmount() > 0) {
if (qbo) {
// do qbo
} else {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.state.accountdesc,
Amount: state_tax.toFormat(DineroQbFormat),
});
}
}
if (local_tax.getAmount() > 0) {
if (qbo) {
// do qbo
} else {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.local.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.local.accountdesc,
Amount: local_tax.toFormat(DineroQbFormat),
});
}
}
//Region Specific
const { ca_bc_pvrt } = jobs_by_pk;
if (ca_bc_pvrt) {
if (qbo) {
// do qbo
} else {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
},
Desc: "PVRT",
Amount: Dinero({ amount: (ca_bc_pvrt || 0) * 100 }).toFormat(
DineroQbFormat
),
});
}
}
return InvoiceLineAdd;
};
const findTaxCode = ({ local, state, federal }, taxcode) => {
const t = taxcode.filter(
(t) =>
!!t.local === !!local &&
!!t.state === !!state &&
!!t.federal === !!federal
);
if (t.length === 1) {
return t[0].code;
} else if (t.length > 1) {
return "Multiple Tax Codes Match";
} else {
return "No Tax Code Matches";
}
};

View File

@@ -16,6 +16,7 @@ const {
setNewRefreshToken,
} = require("./qbo-callback");
const OAuthClient = require("intuit-oauth");
const CreateInvoiceLines = require("../qb-receivables-lines");
const GraphQLClient = require("graphql-request").GraphQLClient;
const { generateOwnerTier } = require("../qbxml/qbxml-utils");
@@ -348,321 +349,34 @@ async function QueryMetaData(oauthClient, req) {
async function InsertInvoice(oauthClient, req, job, bodyshop, parentTierRef) {
const { items, taxCodes } = await QueryMetaData(oauthClient, req);
const InvoiceLineAdd = [];
const responsibilityCenters = bodyshop.md_responsibility_centers;
const invoiceLineHash = {}; //The hash of cost and profit centers based on the center name.
//Determine if there are MAPA and MASH lines already on the estimate.
//If there are, don't do anything extra (mitchell estimate)
//Otherwise, calculate them and add them to the default MAPA and MASH centers.
let hasMapaLine = false;
let hasMashLine = false;
//Create the invoice lines mapping.
job.joblines.map((jobline) => {
//Parts Lines
if (jobline.db_ref === "936008") {
//If either of these DB REFs change, they also need to change in job-totals/job-costing calculations.
hasMapaLine = true;
}
if (jobline.db_ref === "936007") {
hasMashLine = true;
}
if (jobline.profitcenter_part && jobline.act_price) {
let DineroAmount = Dinero({
amount: Math.round(jobline.act_price * 100),
}).multiply(jobline.part_qty || 1);
if (jobline.prt_dsmk_p && jobline.prt_dsmk_p !== 0) {
// console.log("Have a part discount", jobline);
DineroAmount = DineroAmount.add(
DineroAmount.percentage(jobline.prt_dsmk_p || 0)
);
}
const account = responsibilityCenters.profits.find(
(i) => jobline.profitcenter_part.toLowerCase() === i.name.toLowerCase()
);
if (!account) {
logger.log(
"qbxml-receivables-no-account",
"warn",
null,
jobline.id,
null
);
throw new Error(
`A matching account does not exist for the part allocation. Center: ${jobline.profitcenter_part}`
);
}
if (!invoiceLineHash[account.name]) {
invoiceLineHash[account.name] = {
ItemRef: { FullName: account.accountitem },
Desc: account.accountdesc,
Quantity: 1, //jobline.part_qty,
Amount: DineroAmount, //.toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
};
} else {
invoiceLineHash[account.name].Amount =
invoiceLineHash[account.name].Amount.add(DineroAmount);
}
}
// Labor Lines
if (jobline.profitcenter_labor && jobline.mod_lb_hrs) {
const DineroAmount = Dinero({
amount: Math.round(
job[`rate_${jobline.mod_lbr_ty.toLowerCase()}`] * 100
),
}).multiply(jobline.mod_lb_hrs);
const account = responsibilityCenters.profits.find(
(i) => jobline.profitcenter_labor.toLowerCase() === i.name.toLowerCase()
);
if (!account) {
throw new Error(
`A matching account does not exist for the labor allocation. Center: ${jobline.profitcenter_labor}`
);
}
if (!invoiceLineHash[account.name]) {
invoiceLineHash[account.name] = {
ItemRef: { FullName: account.accountitem },
Desc: account.accountdesc,
Quantity: 1, // jobline.mod_lb_hrs,
Amount: DineroAmount,
//Amount: DineroAmount.toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
};
} else {
invoiceLineHash[account.name].Amount =
invoiceLineHash[account.name].Amount.add(DineroAmount);
}
}
const InvoiceLineAdd = CreateInvoiceLines({
bodyshop,
jobs_by_pk: job,
qbo: true,
items,
taxCodes,
});
// console.log("Done creating hash", JSON.stringify(invoiceLineHash));
if (!hasMapaLine && job.job_totals.rates.mapa.total.amount > 0) {
// console.log("Adding MAPA Line Manually.");
const mapaAccountName = responsibilityCenters.defaults.profits.MAPA;
const mapaAccount = responsibilityCenters.profits.find(
(c) => c.name === mapaAccountName
);
if (mapaAccount) {
InvoiceLineAdd.push({
ItemRef: { FullName: mapaAccount.accountitem },
Desc: mapaAccount.accountdesc,
Quantity: 1,
Amount: Dinero(job.job_totals.rates.mapa.total).toFormat(
DineroQbFormat
),
SalesTaxCodeRef: {
FullName: "E",
},
});
} else {
//console.log("NO MAPA ACCOUNT FOUND!!");
}
}
if (!hasMashLine && job.job_totals.rates.mash.total.amount > 0) {
// console.log("Adding MASH Line Manually.");
const mashAccountName = responsibilityCenters.defaults.profits.MASH;
const mashAccount = responsibilityCenters.profits.find(
(c) => c.name === mashAccountName
);
if (mashAccount) {
InvoiceLineAdd.push({
ItemRef: { FullName: mashAccount.accountitem },
Desc: mashAccount.accountdesc,
Quantity: 1,
Amount: Dinero(job.job_totals.rates.mash.total).toFormat(
DineroQbFormat
),
SalesTaxCodeRef: {
FullName: "E",
},
});
} else {
// console.log("NO MASH ACCOUNT FOUND!!");
}
}
//Convert the hash to an array.
Object.keys(invoiceLineHash).forEach((key) => {
InvoiceLineAdd.push({
...invoiceLineHash[key],
Amount: invoiceLineHash[key].Amount.toFormat(DineroQbFormat),
});
});
//Add Towing, storage and adjustment lines.
if (job.towing_payable && job.towing_payable !== 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["TOW"]
).accountitem,
},
Desc: "Towing",
Quantity: 1,
Amount: Dinero({
amount: Math.round((job.towing_payable || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
if (job.storage_payable && job.storage_payable !== 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["TOW"]
).accountitem,
},
Desc: "Storage",
Quantity: 1,
Amount: Dinero({
amount: Math.round((job.storage_payable || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
if (job.adjustment_bottom_line && job.adjustment_bottom_line !== 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["PAO"]
).accountitem,
},
Desc: "Adjustment",
Quantity: 1,
Amount: Dinero({
amount: Math.round((job.adjustment_bottom_line || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
//Add tax lines
const job_totals = job.job_totals;
const federal_tax = Dinero(job_totals.totals.federal_tax);
const state_tax = Dinero(job_totals.totals.state_tax);
const local_tax = Dinero(job_totals.totals.local_tax);
if (federal_tax.getAmount() > 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.federal.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.federal.accountdesc,
Amount: federal_tax.toFormat(DineroQbFormat),
});
}
if (state_tax.getAmount() > 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.state.accountdesc,
Amount: state_tax.toFormat(DineroQbFormat),
});
}
if (local_tax.getAmount() > 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.local.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.local.accountdesc,
Amount: local_tax.toFormat(DineroQbFormat),
});
}
//Region Specific
const { ca_bc_pvrt } = job;
if (ca_bc_pvrt) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
},
Desc: "PVRT",
Amount: Dinero({ amount: (ca_bc_pvrt || 0) * 100 }).toFormat(
DineroQbFormat
),
});
}
//map each invoice line to the correct style for QBO.
const invoiceObj = {
Line: [
{
DetailType: "SalesItemLineDetail",
Amount: 100,
SalesItemLineDetail: {
// ItemRef: {
// // name: "Services",
// value: "16",
// },
TaxCodeRef: {
value: "2",
},
Qty: 1,
UnitPrice: 100,
},
},
],
// Line: InvoiceLineAdd.map((i) => {
// return {
// Line: [
// {
// DetailType: "SalesItemLineDetail",
// Amount: i.Amount,
// Amount: 100,
// SalesItemLineDetail: {
// ItemRef: {
// //name: "Services",
// value: items[i.ItemRef.FullName],
// // name: "Services",
// value: "1",
// },
// TaxCodeRef: {
// value: "2",
// },
// // TaxCodeRef: {
// // value: "2",
// // },
// Qty: 1,
// UnitPrice: 100,
// },
// };
// }),
TxnTaxDetail: {
TaxLine: [
{
DetailType: "TaxLineDetail",
// },
// ],
Line: InvoiceLineAdd,
TaxLineDetail: {
NetAmountTaxable: 100,
TaxPercent: 7,
TaxRateRef: {
value: "16",
},
PercentBased: true,
},
},
],
},
CustomerRef: {
value: parentTierRef.Id,
},

View File

@@ -7,6 +7,7 @@ const moment = require("moment");
var builder = require("xmlbuilder2");
const QbXmlUtils = require("./qbxml-utils");
const logger = require("../../utils/logger");
const CreateInvoiceLines = require("../qb-receivables-lines");
require("dotenv").config({
path: path.resolve(
@@ -227,273 +228,8 @@ const generateInvoiceQbxml = (
twoTierPref
) => {
//Build the Invoice XML file.
const InvoiceLineAdd = [];
const responsibilityCenters = bodyshop.md_responsibility_centers;
const invoiceLineHash = {}; //The hash of cost and profit centers based on the center name.
//Determine if there are MAPA and MASH lines already on the estimate.
//If there are, don't do anything extra (mitchell estimate)
//Otherwise, calculate them and add them to the default MAPA and MASH centers.
let hasMapaLine = false;
let hasMashLine = false;
//Create the invoice lines mapping.
jobs_by_pk.joblines.map((jobline) => {
//Parts Lines
if (jobline.db_ref === "936008") {
//If either of these DB REFs change, they also need to change in job-totals/job-costing calculations.
hasMapaLine = true;
}
if (jobline.db_ref === "936007") {
hasMashLine = true;
}
if (jobline.profitcenter_part && jobline.act_price) {
let DineroAmount = Dinero({
amount: Math.round(jobline.act_price * 100),
}).multiply(jobline.part_qty || 1);
if (jobline.prt_dsmk_p && jobline.prt_dsmk_p !== 0) {
// console.log("Have a part discount", jobline);
DineroAmount = DineroAmount.add(
DineroAmount.percentage(Math.abs(jobline.prt_dsmk_p || 0)).multiply(
jobline.prt_dsmk_p > 0 ? 1 : -1
)
);
}
const account = responsibilityCenters.profits.find(
(i) => jobline.profitcenter_part.toLowerCase() === i.name.toLowerCase()
);
if (!account) {
logger.log(
"qbxml-receivables-no-account",
"warn",
null,
jobline.id,
null
);
throw new Error(
`A matching account does not exist for the part allocation. Center: ${jobline.profitcenter_part}`
);
}
if (!invoiceLineHash[account.name]) {
invoiceLineHash[account.name] = {
ItemRef: { FullName: account.accountitem },
Desc: account.accountdesc,
Quantity: 1, //jobline.part_qty,
Amount: DineroAmount, //.toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
};
} else {
invoiceLineHash[account.name].Amount =
invoiceLineHash[account.name].Amount.add(DineroAmount);
}
}
// Labor Lines
if (jobline.profitcenter_labor && jobline.mod_lb_hrs) {
const DineroAmount = Dinero({
amount: Math.round(
jobs_by_pk[`rate_${jobline.mod_lbr_ty.toLowerCase()}`] * 100
),
}).multiply(jobline.mod_lb_hrs);
const account = responsibilityCenters.profits.find(
(i) => jobline.profitcenter_labor.toLowerCase() === i.name.toLowerCase()
);
if (!account) {
throw new Error(
`A matching account does not exist for the labor allocation. Center: ${jobline.profitcenter_labor}`
);
}
if (!invoiceLineHash[account.name]) {
invoiceLineHash[account.name] = {
ItemRef: { FullName: account.accountitem },
Desc: account.accountdesc,
Quantity: 1, // jobline.mod_lb_hrs,
Amount: DineroAmount,
//Amount: DineroAmount.toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
};
} else {
invoiceLineHash[account.name].Amount =
invoiceLineHash[account.name].Amount.add(DineroAmount);
}
}
});
// console.log("Done creating hash", JSON.stringify(invoiceLineHash));
if (!hasMapaLine && jobs_by_pk.job_totals.rates.mapa.total.amount > 0) {
// console.log("Adding MAPA Line Manually.");
const mapaAccountName = responsibilityCenters.defaults.profits.MAPA;
const mapaAccount = responsibilityCenters.profits.find(
(c) => c.name === mapaAccountName
);
if (mapaAccount) {
InvoiceLineAdd.push({
ItemRef: { FullName: mapaAccount.accountitem },
Desc: mapaAccount.accountdesc,
Quantity: 1,
Amount: Dinero(jobs_by_pk.job_totals.rates.mapa.total).toFormat(
DineroQbFormat
),
SalesTaxCodeRef: {
FullName: "E",
},
});
} else {
//console.log("NO MAPA ACCOUNT FOUND!!");
}
}
if (!hasMashLine && jobs_by_pk.job_totals.rates.mash.total.amount > 0) {
// console.log("Adding MASH Line Manually.");
const mashAccountName = responsibilityCenters.defaults.profits.MASH;
const mashAccount = responsibilityCenters.profits.find(
(c) => c.name === mashAccountName
);
if (mashAccount) {
InvoiceLineAdd.push({
ItemRef: { FullName: mashAccount.accountitem },
Desc: mashAccount.accountdesc,
Quantity: 1,
Amount: Dinero(jobs_by_pk.job_totals.rates.mash.total).toFormat(
DineroQbFormat
),
SalesTaxCodeRef: {
FullName: "E",
},
});
} else {
// console.log("NO MASH ACCOUNT FOUND!!");
}
}
//Convert the hash to an array.
Object.keys(invoiceLineHash).forEach((key) => {
InvoiceLineAdd.push({
...invoiceLineHash[key],
Amount: invoiceLineHash[key].Amount.toFormat(DineroQbFormat),
});
});
//Add Towing, storage and adjustment lines.
if (jobs_by_pk.towing_payable && jobs_by_pk.towing_payable !== 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["TOW"]
).accountitem,
},
Desc: "Towing",
Quantity: 1,
Amount: Dinero({
amount: Math.round((jobs_by_pk.towing_payable || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
if (jobs_by_pk.storage_payable && jobs_by_pk.storage_payable !== 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["TOW"]
).accountitem,
},
Desc: "Storage",
Quantity: 1,
Amount: Dinero({
amount: Math.round((jobs_by_pk.storage_payable || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
if (
jobs_by_pk.adjustment_bottom_line &&
jobs_by_pk.adjustment_bottom_line !== 0
) {
InvoiceLineAdd.push({
ItemRef: {
FullName: responsibilityCenters.profits.find(
(c) => c.name === responsibilityCenters.defaults.profits["PAO"]
).accountitem,
},
Desc: "Adjustment",
Quantity: 1,
Amount: Dinero({
amount: Math.round((jobs_by_pk.adjustment_bottom_line || 0) * 100),
}).toFormat(DineroQbFormat),
SalesTaxCodeRef: {
FullName: "E",
},
});
}
//Add tax lines
const job_totals = jobs_by_pk.job_totals;
const federal_tax = Dinero(job_totals.totals.federal_tax);
const state_tax = Dinero(job_totals.totals.state_tax);
const local_tax = Dinero(job_totals.totals.local_tax);
if (federal_tax.getAmount() > 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.federal.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.federal.accountdesc,
Amount: federal_tax.toFormat(DineroQbFormat),
});
}
if (state_tax.getAmount() > 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.state.accountdesc,
Amount: state_tax.toFormat(DineroQbFormat),
});
}
if (local_tax.getAmount() > 0) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.local.accountitem,
},
Desc: bodyshop.md_responsibility_centers.taxes.local.accountdesc,
Amount: local_tax.toFormat(DineroQbFormat),
});
}
//Region Specific
const { ca_bc_pvrt } = jobs_by_pk;
if (ca_bc_pvrt) {
InvoiceLineAdd.push({
ItemRef: {
FullName: bodyshop.md_responsibility_centers.taxes.state.accountitem,
},
Desc: "PVRT",
Amount: Dinero({ amount: (ca_bc_pvrt || 0) * 100 }).toFormat(
DineroQbFormat
),
});
}
const InvoiceLineAdd = CreateInvoiceLines({ bodyshop, jobs_by_pk });
const invoiceQbxmlObj = {
QBXML: {

View File

@@ -120,6 +120,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
profitcenter_part
db_ref
prt_dsmk_p
tax_part
}
}
bodyshops(where: {associations: {active: {_eq: true}}}) {