UNPKG

@accounter/server

Version:
1,238 lines 46.8 kB
import { GraphQLError } from 'graphql'; import { CountryCode, Currency, DocumentType } from '../../../shared/enums.js'; import { formatCurrency, hashStringToInt } from '../../../shared/helpers/index.js'; import { CloudinaryProvider } from '../../app-providers/cloudinary.js'; import { GreenInvoiceClientProvider } from '../../app-providers/green-invoice-client.js'; import { ChargesProvider } from '../../charges/providers/charges.provider.js'; import { DocumentsProvider } from '../../documents/providers/documents.provider.js'; import { IssuedDocumentsProvider } from '../../documents/providers/issued-documents.provider.js'; import { validateClientIntegrations } from '../../financial-entities/helpers/clients.helper.js'; import { ClientsProvider } from '../../financial-entities/providers/clients.provider.js'; export function normalizeGreenInvoiceDocumentType(rawType) { if (!rawType) { return DocumentType.Unprocessed; } if (typeof rawType === 'string' && rawType.startsWith('_')) { const int = parseInt(rawType.replace('_', '')); if (Number.isInteger(int)) { rawType = int; } } switch (rawType) { case 20: // חשבון / אישור תשלום return DocumentType.Invoice; case 300: // חשבונית עסקה return DocumentType.Proforma; case 305: // חשבונית מס return DocumentType.Invoice; case 320: // חשבונית מס\קבלה return DocumentType.InvoiceReceipt; case 330: // חשבונית זיכוי return DocumentType.CreditInvoice; case 400: // קבלה return DocumentType.Receipt; case 405: // קבלה על תרומה return DocumentType.Unprocessed; default: console.log(`Got a new document type from Green Invoice: ${rawType}`); return DocumentType.Unprocessed; } } export function getGreenInvoiceDocumentType(documentType) { switch (documentType) { case DocumentType.Invoice: return '_305'; case DocumentType.Proforma: return '_300'; case DocumentType.InvoiceReceipt: return '_320'; case DocumentType.CreditInvoice: return '_330'; case DocumentType.Receipt: return '_400'; default: throw new Error(`Unsupported document type: ${documentType}`); } } export function getTypeFromGreenInvoiceDocument(documentType) { switch (documentType) { case '_305': return DocumentType.Invoice; case '_300': return DocumentType.Proforma; case '_320': return DocumentType.InvoiceReceipt; case '_330': return DocumentType.CreditInvoice; case '_400': return DocumentType.Receipt; default: throw new Error(`Unsupported document type: ${documentType}`); } } export function getDocumentNameFromGreenInvoiceType(documentType) { switch (documentType) { case '_305': return 'Tax Invoice'; case '_300': return 'Proforma Invoice'; case '_320': return 'Invoice / Receipt'; case '_330': return 'Credit Note'; case '_400': return 'Receipt'; default: throw new Error(`Unsupported document type: ${documentType}`); } } export function getGreenInvoiceDocumentLanguage(language) { switch (language) { case 'HEBREW': return 'he'; case 'ENGLISH': return 'en'; default: throw new Error(`Unsupported document language: ${language}`); } } export function getLanguageFromGreenInvoiceDocument(lang) { switch (lang) { case 'he': return 'HEBREW'; case 'en': return 'ENGLISH'; default: throw new Error(`Unsupported document language: ${lang}`); } } export function getGreenInvoiceDocumentVatType(vatType) { switch (vatType) { case 'DEFAULT': return '_0'; case 'EXEMPT': return '_1'; case 'MIXED': return '_2'; default: throw new Error(`Unsupported VAT type: ${vatType}`); } } export function getVatTypeFromGreenInvoiceDocument(vatType) { switch (vatType) { case '_0': return 'DEFAULT'; case '_1': return 'EXEMPT'; case '_2': return 'MIXED'; default: throw new Error(`Unsupported VAT type: ${vatType}`); } } export function getGreenInvoiceDocumentDiscountType(discountType) { switch (discountType) { case 'PERCENTAGE': return 'percentage'; case 'SUM': return 'sum'; default: throw new Error(`Unsupported discount type: ${discountType}`); } } export function getGreenInvoiceDocumentPaymentType(type) { switch (type) { case 'TAX_DEDUCTION': return 'NEGATIVE_1'; case 'CASH': return '_1'; case 'CHEQUE': return '_2'; case 'CREDIT_CARD': return '_3'; case 'WIRE_TRANSFER': return '_4'; case 'PAYPAL': return '_5'; case 'OTHER_DEDUCTION': return '_9'; case 'PAYMENT_APP': return '_10'; case 'OTHER': return '_11'; default: throw new Error(`Unsupported payment type: ${type}`); } } export function getTypeFromGreenInvoiceDocumentPayment(type) { switch (type) { case 'NEGATIVE_1': return 'TAX_DEDUCTION'; case '_1': return 'CASH'; case '_2': return 'CHEQUE'; case '_3': return 'CREDIT_CARD'; case '_4': return 'WIRE_TRANSFER'; case '_5': return 'PAYPAL'; case '_9': return 'OTHER_DEDUCTION'; case '_10': return 'PAYMENT_APP'; case '_11': return 'OTHER'; default: throw new Error(`Unsupported payment type: ${type}`); } } // export function getGreenInvoiceDocumentPaymentSubType( // subType: GreenInvoicePaymentSubType, // ): query_getDocument_payment_items_subType { // switch (subType) { // case 'BITCOIN': // return '_1'; // case 'BUYME_VOUCHER': // return '_7'; // case 'ETHEREUM': // return '_6'; // case 'GIFT_CARD': // return '_4'; // case 'MONEY_EQUAL': // return '_2'; // case 'NII_EMPLOYEE_DEDUCTION': // return '_5'; // case 'PAYONEER': // return '_8'; // case 'V_CHECK': // return '_3'; // default: // throw new Error(`Unsupported payment sub-type: ${subType}`); // } // } // export function getSubTypeFromGreenInvoiceDocumentPayment( // subType: query_getDocument_payment_items_subType, // ): GreenInvoicePaymentSubType { // switch (subType) { // case '_1': // return 'BITCOIN'; // case '_7': // return 'BUYME_VOUCHER'; // case '_6': // return 'ETHEREUM'; // case '_4': // return 'GIFT_CARD'; // case '_2': // return 'MONEY_EQUAL'; // case '_5': // return 'NII_EMPLOYEE_DEDUCTION'; // case '_8': // return 'PAYONEER'; // case '_3': // return 'V_CHECK'; // default: // throw new Error(`Unsupported payment sub-type: ${subType}`); // } // } // export function getGreenInvoiceDocumentPaymentAppType( // appType: GreenInvoicePaymentAppType, // ): query_getDocument_payment_items_appType { // switch (appType) { // case 'APPLE_PAY': // return '_6'; // case 'BIT': // return '_1'; // case 'CULO': // return '_4'; // case 'GOOGLE_PAY': // return '_5'; // case 'PAYBOX': // return '_3'; // case 'PAY_BY_PEPPER': // return '_2'; // default: // throw new Error(`Unsupported payment app type: ${appType}`); // } // } // export function getPaymentAppTypeFromGreenInvoiceDocument( // appType: query_getDocument_payment_items_appType, // ): GreenInvoicePaymentAppType { // switch (appType) { // case '_6': // return 'APPLE_PAY'; // case '_1': // return 'BIT'; // case '_4': // return 'CULO'; // case '_5': // return 'GOOGLE_PAY'; // case '_3': // return 'PAYBOX'; // case '_2': // return 'PAY_BY_PEPPER'; // default: // throw new Error(`Unsupported payment app type: ${appType}`); // } // } export function getGreenInvoiceDocumentPaymentCardType(cardType) { switch (cardType) { case 'AMERICAN_EXPRESS': return '_4'; case 'DINERS': return '_5'; case 'ISRACARD': return '_1'; case 'MASTERCARD': return '_3'; // case 'UNKNOWN': // return '_0'; // TODO: why is this not supported? case 'VISA': return '_2'; default: throw new Error(`Unsupported payment card type: ${cardType}`); } } export function getCardTypeFromGreenInvoiceDocumentPayment(cardType) { switch (cardType) { case '_4': return 'AMERICAN_EXPRESS'; case '_5': return 'DINERS'; case '_1': return 'ISRACARD'; case '_3': return 'MASTERCARD'; // case '_0': // TODO: why is this not supported? // return 'UNKNOWN'; case '_2': return 'VISA'; default: throw new Error(`Unsupported payment card type: ${cardType}`); } } // export function getGreenInvoiceDocumentPaymentDealType( // dealType: GreenInvoicePaymentDealType, // ): query_getDocument_payment_items_dealType { // switch (dealType) { // case 'CREDIT': // return '_3'; // case 'DEFERRED': // return '_4'; // case 'OTHER': // return '_5'; // case 'PAYMENTS': // return '_2'; // case 'RECURRING': // return '_6'; // case 'STANDARD': // return '_1'; // default: // throw new Error(`Unsupported payment deal type: ${dealType}`); // } // } // export function getDealTypeFromGreenInvoiceDocumentPayment( // dealType: query_getDocument_payment_items_dealType, // ): GreenInvoicePaymentDealType { // switch (dealType) { // case '_3': // return 'CREDIT'; // case '_4': // return 'DEFERRED'; // case '_5': // return 'OTHER'; // case '_2': // return 'PAYMENTS'; // case '_6': // return 'RECURRING'; // case '_1': // return 'STANDARD'; // default: // throw new Error(`Unsupported payment deal type: ${dealType}`); // } // } export function getGreenInvoiceDocumentLinkType(linkType) { switch (linkType) { case 'CANCEL': return 'CANCEL'; case 'LINK': return 'LINK'; default: throw new Error(`Unsupported link type: ${linkType}`); } } export function convertCurrencyToGreenInvoice(currency) { switch (currency) { case Currency.Aud: return 'AUD'; case Currency.Cad: return 'CAD'; case Currency.Eur: return 'EUR'; case Currency.Gbp: return 'GBP'; case Currency.Ils: return 'ILS'; case Currency.Jpy: return 'JPY'; case Currency.Sek: return 'SEK'; case Currency.Usd: return 'USD'; case Currency.Eth: case Currency.Grt: case Currency.Usdc: throw new Error(`Crypto currency (${currency}) is not supported`); default: throw new Error(`Unsupported currency: ${currency}`); } } export function greenInvoiceCountryToCountryCode(country) { const greenInvoiceToCountryCodeMap = { AD: CountryCode.Andorra, AE: CountryCode['United Arab Emirates (the)'], AF: CountryCode.Afghanistan, AG: CountryCode['Antigua and Barbuda'], AI: CountryCode.Anguilla, AL: CountryCode.Albania, AM: CountryCode.Armenia, AO: CountryCode.Angola, AQ: CountryCode.Antarctica, AR: CountryCode.Argentina, AS: CountryCode['American Samoa'], AT: CountryCode.Austria, AU: CountryCode.Australia, AW: CountryCode.Aruba, AX: CountryCode['Åland Islands'], AZ: CountryCode.Azerbaijan, BA: CountryCode['Bosnia and Herzegovina'], BB: CountryCode.Barbados, BD: CountryCode.Bangladesh, BE: CountryCode.Belgium, BF: CountryCode['Burkina Faso'], BG: CountryCode.Bulgaria, BH: CountryCode.Bahrain, BI: CountryCode.Burundi, BJ: CountryCode.Benin, BL: CountryCode['Saint Barthélemy'], BM: CountryCode.Bermuda, BN: CountryCode['Brunei Darussalam'], BO: CountryCode['Bolivia (Plurinational State of)'], BQ: CountryCode['Bonaire, Sint Eustatius and Saba'], BR: CountryCode.Brazil, BS: CountryCode['Bahamas (the)'], BT: CountryCode.Bhutan, BV: CountryCode['Bouvet Island'], BW: CountryCode.Botswana, BY: CountryCode.Belarus, BZ: CountryCode.Belize, CA: CountryCode.Canada, CC: CountryCode['Cocos (Keeling) Islands (the)'], CD: CountryCode['Congo (the Democratic Republic of the)'], CF: CountryCode['Central African Republic (the)'], CG: CountryCode['Congo (the)'], CH: CountryCode.Switzerland, CI: CountryCode["Côte d'Ivoire"], CK: CountryCode['Cook Islands (the)'], CL: CountryCode.Chile, CM: CountryCode.Cameroon, CN: CountryCode.China, CO: CountryCode.Colombia, CR: CountryCode['Costa Rica'], CU: CountryCode.Cuba, CV: CountryCode['Cabo Verde'], CW: CountryCode.Curaçao, CX: CountryCode['Christmas Island'], CY: CountryCode.Cyprus, CZ: CountryCode.Czechia, DE: CountryCode.Germany, DJ: CountryCode.Djibouti, DK: CountryCode.Denmark, DM: CountryCode.Dominica, DO: CountryCode['Dominican Republic (the)'], DZ: CountryCode.Algeria, EC: CountryCode.Ecuador, EE: CountryCode.Estonia, EG: CountryCode.Egypt, EH: CountryCode['Western Sahara'], ER: CountryCode.Eritrea, ES: CountryCode.Spain, ET: CountryCode.Ethiopia, FI: CountryCode.Finland, FJ: CountryCode.Fiji, FK: CountryCode['Falkland Islands (the) [Malvinas]'], FM: CountryCode['Micronesia (Federated States of)'], FO: CountryCode['Faroe Islands (the)'], FR: CountryCode.France, GA: CountryCode.Gabon, GB: CountryCode['United Kingdom of Great Britain and Northern Ireland (the)'], GD: CountryCode.Grenada, GE: CountryCode.Georgia, GF: CountryCode['French Guiana'], GG: CountryCode.Guernsey, GH: CountryCode.Ghana, GI: CountryCode.Gibraltar, GL: CountryCode.Greenland, GM: CountryCode['Gambia (the)'], GN: CountryCode.Guinea, GP: CountryCode.Guadeloupe, GQ: CountryCode['Equatorial Guinea'], GR: CountryCode.Greece, GS: CountryCode['South Georgia and the South Sandwich Islands'], GT: CountryCode.Guatemala, GU: CountryCode.Guam, GW: CountryCode['Guinea-Bissau'], GY: CountryCode.Guyana, HK: CountryCode['Hong Kong'], HM: CountryCode['Heard Island and McDonald Islands'], HN: CountryCode.Honduras, HR: CountryCode.Croatia, HT: CountryCode.Haiti, HU: CountryCode.Hungary, ID: CountryCode.Indonesia, IE: CountryCode.Ireland, IL: CountryCode.Israel, IM: CountryCode['Isle of Man'], IN: CountryCode.India, IO: CountryCode['British Indian Ocean Territory (the)'], IQ: CountryCode.Iraq, IR: CountryCode['Iran (Islamic Republic of)'], IS: CountryCode.Iceland, IT: CountryCode.Italy, JE: CountryCode.Jersey, JM: CountryCode.Jamaica, JO: CountryCode.Jordan, JP: CountryCode.Japan, KE: CountryCode.Kenya, KG: CountryCode.Kyrgyzstan, KH: CountryCode.Cambodia, KI: CountryCode.Kiribati, KM: CountryCode['Comoros (the)'], KN: CountryCode['Saint Kitts and Nevis'], KP: CountryCode["Korea (the Democratic People's Republic of)"], KR: CountryCode['Korea (the Republic of)'], KW: CountryCode.Kuwait, KY: CountryCode['Cayman Islands (the)'], KZ: CountryCode.Kazakhstan, LA: CountryCode["Lao People's Democratic Republic (the)"], LB: CountryCode.Lebanon, LC: CountryCode['Saint Lucia'], LI: CountryCode.Liechtenstein, LK: CountryCode['Sri Lanka'], LR: CountryCode.Liberia, LS: CountryCode.Lesotho, LT: CountryCode.Lithuania, LU: CountryCode.Luxembourg, LV: CountryCode.Latvia, LY: CountryCode.Libya, MA: CountryCode.Morocco, MC: CountryCode.Monaco, MD: CountryCode['Moldova (the Republic of)'], ME: CountryCode.Montenegro, MF: CountryCode['Saint Martin (French part)'], MG: CountryCode.Madagascar, MH: CountryCode['Marshall Islands (the)'], MK: CountryCode['Republic of North Macedonia'], ML: CountryCode.Mali, MM: CountryCode.Myanmar, MN: CountryCode.Mongolia, MO: CountryCode.Macao, MP: CountryCode['Northern Mariana Islands (the)'], MQ: CountryCode.Martinique, MR: CountryCode.Mauritania, MS: CountryCode.Montserrat, MT: CountryCode.Malta, MU: CountryCode.Mauritius, MV: CountryCode.Maldives, MW: CountryCode.Malawi, MX: CountryCode.Mexico, MY: CountryCode.Malaysia, MZ: CountryCode.Mozambique, NA: CountryCode.Namibia, NC: CountryCode['New Caledonia'], NE: CountryCode['Niger (the)'], NF: CountryCode['Norfolk Island'], NG: CountryCode.Nigeria, NI: CountryCode.Nicaragua, NL: CountryCode['Netherlands (the)'], NO: CountryCode.Norway, NP: CountryCode.Nepal, NR: CountryCode.Nauru, NU: CountryCode.Niue, NZ: CountryCode['New Zealand'], OM: CountryCode.Oman, PA: CountryCode.Panama, PE: CountryCode.Peru, PF: CountryCode['French Polynesia'], PG: CountryCode['Papua New Guinea'], PH: CountryCode['Philippines (the)'], PK: CountryCode.Pakistan, PL: CountryCode.Poland, PM: CountryCode['Saint Pierre and Miquelon'], PN: CountryCode.Pitcairn, PR: CountryCode['Puerto Rico'], PS: CountryCode['Palestine, State of'], PT: CountryCode.Portugal, PW: CountryCode.Palau, PY: CountryCode.Paraguay, QA: CountryCode.Qatar, RE: CountryCode.Réunion, RO: CountryCode.Romania, RS: CountryCode.Serbia, RU: CountryCode['Russian Federation (the)'], RW: CountryCode.Rwanda, SA: CountryCode['Saudi Arabia'], SB: CountryCode['Solomon Islands'], SC: CountryCode.Seychelles, SD: CountryCode['Sudan (the)'], SE: CountryCode.Sweden, SG: CountryCode.Singapore, SH: CountryCode['Saint Helena, Ascension and Tristan da Cunha'], SI: CountryCode.Slovenia, SJ: CountryCode['Svalbard and Jan Mayen'], SK: CountryCode.Slovakia, SL: CountryCode['Sierra Leone'], SM: CountryCode['San Marino'], SN: CountryCode.Senegal, SO: CountryCode.Somalia, SR: CountryCode.Suriname, SS: CountryCode['South Sudan'], ST: CountryCode['Sao Tome and Principe'], SV: CountryCode['El Salvador'], SX: CountryCode['Sint Maarten (Dutch part)'], SY: CountryCode['Syrian Arab Republic'], SZ: CountryCode.Eswatini, TC: CountryCode['Turks and Caicos Islands (the)'], TD: CountryCode.Chad, TF: CountryCode['French Southern Territories (the)'], TG: CountryCode.Togo, TH: CountryCode.Thailand, TJ: CountryCode.Tajikistan, TK: CountryCode.Tokelau, TL: CountryCode['Timor-Leste'], TM: CountryCode.Turkmenistan, TN: CountryCode.Tunisia, TO: CountryCode.Tonga, TR: CountryCode.Turkey, TT: CountryCode['Trinidad and Tobago'], TV: CountryCode.Tuvalu, TW: CountryCode['Taiwan (Province of China)'], TZ: CountryCode['Tanzania, United Republic of'], UA: CountryCode.Ukraine, UG: CountryCode.Uganda, UM: CountryCode['United States Minor Outlying Islands (the)'], US: CountryCode['United States of America (the)'], UY: CountryCode.Uruguay, UZ: CountryCode.Uzbekistan, VA: CountryCode['Holy See (the)'], VC: CountryCode['Saint Vincent and the Grenadines'], VE: CountryCode['Venezuela (Bolivarian Republic of)'], VG: CountryCode['Virgin Islands (British)'], VI: CountryCode['Virgin Islands (U.S.)'], VN: CountryCode['Viet Nam'], VU: CountryCode.Vanuatu, WF: CountryCode['Wallis and Futuna'], WS: CountryCode.Samoa, YE: CountryCode.Yemen, YT: CountryCode.Mayotte, ZA: CountryCode['South Africa'], ZM: CountryCode.Zambia, ZW: CountryCode.Zimbabwe, }; if (country === 'XK') { // TODO: remove this once green invoice adds Kosovo to their list return CountryCode.Serbia; } const code = greenInvoiceToCountryCodeMap[country]; if (code) { return code; } throw new Error(`Unsupported Green Invoice country: ${country}`); } export function countryCodeToGreenInvoiceCountry(countryCode) { const countryCodeToGreenInvoiceMap = { [CountryCode.Afghanistan]: 'AF', [CountryCode['Åland Islands']]: 'AX', [CountryCode.Albania]: 'AL', [CountryCode.Algeria]: 'DZ', [CountryCode['American Samoa']]: 'AS', [CountryCode.Andorra]: 'AD', [CountryCode.Angola]: 'AO', [CountryCode.Anguilla]: 'AI', [CountryCode.Antarctica]: 'AQ', [CountryCode['Antigua and Barbuda']]: 'AG', [CountryCode.Argentina]: 'AR', [CountryCode.Armenia]: 'AM', [CountryCode.Aruba]: 'AW', [CountryCode.Australia]: 'AU', [CountryCode.Austria]: 'AT', [CountryCode.Azerbaijan]: 'AZ', [CountryCode['Bahamas (the)']]: 'BS', [CountryCode.Bahrain]: 'BH', [CountryCode.Bangladesh]: 'BD', [CountryCode.Barbados]: 'BB', [CountryCode.Belarus]: 'BY', [CountryCode.Belgium]: 'BE', [CountryCode.Belize]: 'BZ', [CountryCode.Benin]: 'BJ', [CountryCode.Bermuda]: 'BM', [CountryCode.Bhutan]: 'BT', [CountryCode['Bolivia (Plurinational State of)']]: 'BO', [CountryCode['Bonaire, Sint Eustatius and Saba']]: 'BQ', [CountryCode['Bosnia and Herzegovina']]: 'BA', [CountryCode.Botswana]: 'BW', [CountryCode['Bouvet Island']]: 'BV', [CountryCode.Brazil]: 'BR', [CountryCode['British Indian Ocean Territory (the)']]: 'IO', [CountryCode['Brunei Darussalam']]: 'BN', [CountryCode.Bulgaria]: 'BG', [CountryCode['Burkina Faso']]: 'BF', [CountryCode.Burundi]: 'BI', [CountryCode['Cabo Verde']]: 'CV', [CountryCode.Cambodia]: 'KH', [CountryCode.Cameroon]: 'CM', [CountryCode.Canada]: 'CA', [CountryCode['Cayman Islands (the)']]: 'KY', [CountryCode['Central African Republic (the)']]: 'CF', [CountryCode.Chad]: 'TD', [CountryCode.Chile]: 'CL', [CountryCode.China]: 'CN', [CountryCode['Christmas Island']]: 'CX', [CountryCode['Cocos (Keeling) Islands (the)']]: 'CC', [CountryCode.Colombia]: 'CO', [CountryCode['Comoros (the)']]: 'KM', [CountryCode['Congo (the Democratic Republic of the)']]: 'CD', [CountryCode['Congo (the)']]: 'CG', [CountryCode['Cook Islands (the)']]: 'CK', [CountryCode['Costa Rica']]: 'CR', [CountryCode.Croatia]: 'HR', [CountryCode.Cuba]: 'CU', [CountryCode.Curaçao]: 'CW', [CountryCode.Cyprus]: 'CY', [CountryCode.Czechia]: 'CZ', [CountryCode["Côte d'Ivoire"]]: 'CI', [CountryCode.Denmark]: 'DK', [CountryCode.Djibouti]: 'DJ', [CountryCode.Dominica]: 'DM', [CountryCode['Dominican Republic (the)']]: 'DO', [CountryCode.Ecuador]: 'EC', [CountryCode.Egypt]: 'EG', [CountryCode['El Salvador']]: 'SV', [CountryCode['Equatorial Guinea']]: 'GQ', [CountryCode.Eritrea]: 'ER', [CountryCode.Estonia]: 'EE', [CountryCode.Eswatini]: 'SZ', [CountryCode.Ethiopia]: 'ET', [CountryCode['Falkland Islands (the) [Malvinas]']]: 'FK', [CountryCode['Faroe Islands (the)']]: 'FO', [CountryCode.Fiji]: 'FJ', [CountryCode.Finland]: 'FI', [CountryCode.France]: 'FR', [CountryCode['French Guiana']]: 'GF', [CountryCode['French Polynesia']]: 'PF', [CountryCode['French Southern Territories (the)']]: 'TF', [CountryCode.Gabon]: 'GA', [CountryCode['Gambia (the)']]: 'GM', [CountryCode.Georgia]: 'GE', [CountryCode.Germany]: 'DE', [CountryCode.Ghana]: 'GH', [CountryCode.Gibraltar]: 'GI', [CountryCode.Greece]: 'GR', [CountryCode.Greenland]: 'GL', [CountryCode.Grenada]: 'GD', [CountryCode.Guadeloupe]: 'GP', [CountryCode.Guam]: 'GU', [CountryCode.Guatemala]: 'GT', [CountryCode.Guernsey]: 'GG', [CountryCode.Guinea]: 'GN', [CountryCode['Guinea-Bissau']]: 'GW', [CountryCode.Guyana]: 'GY', [CountryCode.Haiti]: 'HT', [CountryCode['Heard Island and McDonald Islands']]: 'HM', [CountryCode['Holy See (the)']]: 'VA', [CountryCode.Honduras]: 'HN', [CountryCode['Hong Kong']]: 'HK', [CountryCode.Hungary]: 'HU', [CountryCode.Iceland]: 'IS', [CountryCode.India]: 'IN', [CountryCode.Indonesia]: 'ID', [CountryCode['Iran (Islamic Republic of)']]: 'IR', [CountryCode.Iraq]: 'IQ', [CountryCode.Ireland]: 'IE', [CountryCode['Isle of Man']]: 'IM', [CountryCode.Israel]: 'IL', [CountryCode.Italy]: 'IT', [CountryCode.Jamaica]: 'JM', [CountryCode.Japan]: 'JP', [CountryCode.Jersey]: 'JE', [CountryCode.Jordan]: 'JO', [CountryCode.Kazakhstan]: 'KZ', [CountryCode.Kenya]: 'KE', [CountryCode.Kiribati]: 'KI', [CountryCode["Korea (the Democratic People's Republic of)"]]: 'KP', [CountryCode['Korea (the Republic of)']]: 'KR', [CountryCode.Kuwait]: 'KW', [CountryCode.Kyrgyzstan]: 'KG', [CountryCode["Lao People's Democratic Republic (the)"]]: 'LA', [CountryCode.Latvia]: 'LV', [CountryCode.Lebanon]: 'LB', [CountryCode.Lesotho]: 'LS', [CountryCode.Liberia]: 'LR', [CountryCode.Libya]: 'LY', [CountryCode.Liechtenstein]: 'LI', [CountryCode.Lithuania]: 'LT', [CountryCode.Luxembourg]: 'LU', [CountryCode.Macao]: 'MO', [CountryCode.Madagascar]: 'MG', [CountryCode.Malawi]: 'MW', [CountryCode.Malaysia]: 'MY', [CountryCode.Maldives]: 'MV', [CountryCode.Mali]: 'ML', [CountryCode.Malta]: 'MT', [CountryCode['Marshall Islands (the)']]: 'MH', [CountryCode.Martinique]: 'MQ', [CountryCode.Mauritania]: 'MR', [CountryCode.Mauritius]: 'MU', [CountryCode.Mayotte]: 'YT', [CountryCode.Mexico]: 'MX', [CountryCode['Micronesia (Federated States of)']]: 'FM', [CountryCode['Moldova (the Republic of)']]: 'MD', [CountryCode.Monaco]: 'MC', [CountryCode.Mongolia]: 'MN', [CountryCode.Montenegro]: 'ME', [CountryCode.Montserrat]: 'MS', [CountryCode.Morocco]: 'MA', [CountryCode.Mozambique]: 'MZ', [CountryCode.Myanmar]: 'MM', [CountryCode.Namibia]: 'NA', [CountryCode.Nauru]: 'NR', [CountryCode.Nepal]: 'NP', [CountryCode['Netherlands (the)']]: 'NL', [CountryCode['New Caledonia']]: 'NC', [CountryCode['New Zealand']]: 'NZ', [CountryCode.Nicaragua]: 'NI', [CountryCode['Niger (the)']]: 'NE', [CountryCode.Nigeria]: 'NG', [CountryCode.Niue]: 'NU', [CountryCode['Norfolk Island']]: 'NF', [CountryCode['Northern Mariana Islands (the)']]: 'MP', [CountryCode.Norway]: 'NO', [CountryCode.Oman]: 'OM', [CountryCode.Pakistan]: 'PK', [CountryCode.Palau]: 'PW', [CountryCode['Palestine, State of']]: 'PS', [CountryCode.Panama]: 'PA', [CountryCode['Papua New Guinea']]: 'PG', [CountryCode.Paraguay]: 'PY', [CountryCode.Peru]: 'PE', [CountryCode['Philippines (the)']]: 'PH', [CountryCode.Pitcairn]: 'PN', [CountryCode.Poland]: 'PL', [CountryCode.Portugal]: 'PT', [CountryCode['Puerto Rico']]: 'PR', [CountryCode.Qatar]: 'QA', [CountryCode['Republic of North Macedonia']]: 'MK', [CountryCode.Romania]: 'RO', [CountryCode['Russian Federation (the)']]: 'RU', [CountryCode.Rwanda]: 'RW', [CountryCode.Réunion]: 'RE', [CountryCode['Saint Barthélemy']]: 'BL', [CountryCode['Saint Helena, Ascension and Tristan da Cunha']]: 'SH', [CountryCode['Saint Kitts and Nevis']]: 'KN', [CountryCode['Saint Lucia']]: 'LC', [CountryCode['Saint Martin (French part)']]: 'MF', [CountryCode['Saint Pierre and Miquelon']]: 'PM', [CountryCode['Saint Vincent and the Grenadines']]: 'VC', [CountryCode.Samoa]: 'WS', [CountryCode['San Marino']]: 'SM', [CountryCode['Sao Tome and Principe']]: 'ST', [CountryCode['Saudi Arabia']]: 'SA', [CountryCode.Senegal]: 'SN', [CountryCode.Serbia]: 'RS', [CountryCode.Seychelles]: 'SC', [CountryCode['Sierra Leone']]: 'SL', [CountryCode.Singapore]: 'SG', [CountryCode['Sint Maarten (Dutch part)']]: 'SX', [CountryCode.Slovakia]: 'SK', [CountryCode.Slovenia]: 'SI', [CountryCode['Solomon Islands']]: 'SB', [CountryCode.Somalia]: 'SO', [CountryCode['South Africa']]: 'ZA', [CountryCode['South Georgia and the South Sandwich Islands']]: 'GS', [CountryCode['South Sudan']]: 'SS', [CountryCode.Spain]: 'ES', [CountryCode['Sri Lanka']]: 'LK', [CountryCode['Sudan (the)']]: 'SD', [CountryCode.Suriname]: 'SR', [CountryCode['Svalbard and Jan Mayen']]: 'SJ', [CountryCode.Sweden]: 'SE', [CountryCode.Switzerland]: 'CH', [CountryCode['Syrian Arab Republic']]: 'SY', [CountryCode['Taiwan (Province of China)']]: 'TW', [CountryCode.Tajikistan]: 'TJ', [CountryCode['Tanzania, United Republic of']]: 'TZ', [CountryCode.Thailand]: 'TH', [CountryCode['Timor-Leste']]: 'TL', [CountryCode.Togo]: 'TG', [CountryCode.Tokelau]: 'TK', [CountryCode.Tonga]: 'TO', [CountryCode['Trinidad and Tobago']]: 'TT', [CountryCode.Tunisia]: 'TN', [CountryCode.Turkey]: 'TR', [CountryCode.Turkmenistan]: 'TM', [CountryCode['Turks and Caicos Islands (the)']]: 'TC', [CountryCode.Tuvalu]: 'TV', [CountryCode.Uganda]: 'UG', [CountryCode.Ukraine]: 'UA', [CountryCode['United Arab Emirates (the)']]: 'AE', [CountryCode['United Kingdom of Great Britain and Northern Ireland (the)']]: 'GB', [CountryCode['United States Minor Outlying Islands (the)']]: 'UM', [CountryCode['United States of America (the)']]: 'US', [CountryCode.Uruguay]: 'UY', [CountryCode.Uzbekistan]: 'UZ', [CountryCode.Vanuatu]: 'VU', [CountryCode['Venezuela (Bolivarian Republic of)']]: 'VE', [CountryCode['Viet Nam']]: 'VN', [CountryCode['Virgin Islands (British)']]: 'VG', [CountryCode['Virgin Islands (U.S.)']]: 'VI', [CountryCode['Wallis and Futuna']]: 'WF', [CountryCode['Western Sahara']]: 'EH', [CountryCode.Yemen]: 'YE', [CountryCode.Zambia]: 'ZM', [CountryCode.Zimbabwe]: 'ZW', }; const greenInvoiceCountry = countryCodeToGreenInvoiceMap[countryCode]; if (greenInvoiceCountry) { return greenInvoiceCountry; } throw new Error(`Unsupported country code: ${countryCode}`); } export function greenInvoiceToDocumentStatus(greenInvoiceStatus) { switch (greenInvoiceStatus) { case 0: return 'OPEN'; case 1: return 'CLOSED'; case 2: return 'MANUALLY_CLOSED'; case 3: return 'CANCELLED_BY_OTHER_DOC'; case 4: return 'CANCELLED'; default: throw new Error(`Unsupported Green Invoice document status: ${greenInvoiceStatus}`); } } export async function getLinkedDocuments(injector, externalDocumentId) { const greenInvoiceDocument = await injector .get(GreenInvoiceClientProvider) .documentLoader.load(externalDocumentId); if (!greenInvoiceDocument?.linkedDocuments) { return null; } const linkedDocuments = greenInvoiceDocument.linkedDocuments.filter(Boolean); if (!linkedDocuments.length) { return null; } const linkedDocumentsIds = []; await Promise.all(linkedDocuments.map(async (linkedDocument) => { const issuedDocument = await injector .get(IssuedDocumentsProvider) .getIssuedDocumentsByExternalIdLoader.load(linkedDocument.id); if (!issuedDocument?.id) { throw new GraphQLError(`Linked document with ID ${linkedDocument.id} not found in issued documents`); } linkedDocumentsIds.push(issuedDocument.id); })); return linkedDocumentsIds; } export async function insertNewDocumentFromGreenInvoice(injector, greenInvoiceDoc, ownerId, preDictatedChargeId) { const documentType = normalizeGreenInvoiceDocumentType(greenInvoiceDoc.type); const isOwnerCreditor = greenInvoiceDoc.amount > 0 && documentType !== DocumentType.CreditInvoice; const links = await injector.get(GreenInvoiceClientProvider).getDocumentLinks(greenInvoiceDoc.id); if (!links) { throw new GraphQLError(`No links found for Green Invoice document ID: ${greenInvoiceDoc.id}`); } const fileUrl = links.en ?? links.origin; try { // generate preview image via cloudinary const imagePromise = injector.get(CloudinaryProvider).uploadInvoiceToCloudinary(fileUrl); // Get matching business const clientPromise = greenInvoiceDoc.client.id ? injector .get(ClientsProvider) .getClientByGreenInvoiceIdLoader.load(greenInvoiceDoc.client.id) : Promise.resolve(null); const linkedDocumentsPromise = getLinkedDocuments(injector, greenInvoiceDoc.id); const fileHashPromise = async () => { try { // Before creating rawDocument const fileResponse = await fetch(fileUrl); if (!fileResponse.ok) { // Handle error, maybe log and continue with null hash throw new Error(`Failed to fetch file from GreenInvoice: ${fileUrl}`); } const fileContent = await fileResponse.text(); const fileHash = hashStringToInt(fileContent).toString(); return fileHash; } catch (error) { console.error('Error fetching file for hash calculation:', error); return null; } }; const [{ imageUrl }, client, linkedDocumentIds, fileHash] = await Promise.all([ imagePromise, clientPromise, linkedDocumentsPromise, fileHashPromise(), ]); let chargeId = preDictatedChargeId || null; // if linked documents exist, use the first one to get the charge ID if (!chargeId && linkedDocumentIds?.length) { const linkedDocId = linkedDocumentIds[0]; const document = await injector .get(DocumentsProvider) .getDocumentsByIdLoader.load(linkedDocId); if (document?.charge_id) { chargeId = document.charge_id; } } let charge = undefined; if (chargeId) { charge = await injector.get(ChargesProvider).getChargeByIdLoader.load(chargeId); if (!charge) { throw new Error(`Charge with ID ${chargeId} not found`); } } else { // Generate new parent charge let userDescription = 'Green Invoice generated charge'; const income = greenInvoiceDoc.income; if (income && income.length > 0 && income[0].description && income[0].description !== '') { userDescription = income .filter(item => item?.description) .map(item => item.description) .join(', '); } else if (greenInvoiceDoc.description && greenInvoiceDoc.description !== '') { userDescription = greenInvoiceDoc.description; } charge = await injector.get(ChargesProvider).generateCharge({ ownerId, userDescription, type: 'COMMON', }); if (!charge) { throw new Error('Failed to generate charge'); } chargeId = charge.id; } const counterpartyId = client?.business_id ?? null; // insert document const rawDocument = { ownerId: charge.owner_id, image: imageUrl, file: fileUrl, documentType, serialNumber: greenInvoiceDoc.number, date: greenInvoiceDoc.documentDate, amount: greenInvoiceDoc.amount, currencyCode: formatCurrency(greenInvoiceDoc.currency), vat: greenInvoiceDoc.vat, chargeId, vatReportDateOverride: null, noVatAmount: null, creditorId: isOwnerCreditor ? ownerId : counterpartyId, debtorId: isOwnerCreditor ? counterpartyId : ownerId, allocationNumber: null, // TODO: add allocation number from GreenInvoice API exchangeRateOverride: null, fileHash, remarks: greenInvoiceDoc.remarks || null, description: greenInvoiceDoc.description || null, }; const newDocumentResponse = await injector .get(DocumentsProvider) .insertDocuments({ documents: [rawDocument] }); if (!newDocumentResponse || newDocumentResponse.length === 0) { throw new Error('Failed to insert document'); } const newDocument = newDocumentResponse[0]; // insert issued document await injector .get(IssuedDocumentsProvider) .insertIssuedDocuments({ issuedDocuments: [ { ownerId: newDocument.owner_id, externalId: greenInvoiceDoc.id, id: newDocument.id, status: greenInvoiceToDocumentStatus(greenInvoiceDoc.status), linkedDocumentIds, }, ], }) .catch(e => { console.error('Failed to insert issued document', e); throw new GraphQLError(`Failed to insert issued document for Green Invoice ID: ${greenInvoiceDoc.id}`); }); return newDocument; } catch (e) { throw new GraphQLError(`Error adding Green Invoice document: ${e}\n\n${JSON.stringify(greenInvoiceDoc, null, 2)}`); } } export async function getGreenInvoiceDocuments(injector, recursive = false) { const documents = []; async function getDocuments(page = 1) { const data = await injector.get(GreenInvoiceClientProvider).searchDocuments({ input: { pageSize: 100, sort: 'creationDate', page }, }); if (!data?.items) { if (!recursive) { throw new GraphQLError('Failed to fetch documents'); } return; } documents.push(...data.items.filter(item => item !== null)); if (data.items.length < 100) { return; } if (recursive) { await getDocuments(page + 1); } } await getDocuments(); return documents; } export async function convertDocumentInputIntoGreenInvoiceInput(initialInput, injector) { let client = undefined; if (initialInput.client) { const clientInfo = await injector .get(ClientsProvider) .getClientByIdLoader.load(initialInput.client.id); if (!clientInfo) { throw new GraphQLError(`Client with business ID ${initialInput.client.id} not found`); } let greenInvoiceId; try { greenInvoiceId = validateClientIntegrations(clientInfo.integrations ?? {}).greenInvoiceId ?? null; } catch (error) { console.error('Failed to validate client integrations', error); throw new GraphQLError(`Client with business ID ${initialInput.client.id} has invalid integrations`); } if (!greenInvoiceId) { throw new GraphQLError(`Client with business ID ${initialInput.client.id} not found in Green Invoice`); } const greenInvoiceClient = await injector .get(GreenInvoiceClientProvider) .clientLoader.load(greenInvoiceId); if (!greenInvoiceClient) { throw new GraphQLError(`Green Invoice client with ID ${greenInvoiceId} not found`); } const emails = ['ap@the-guild.dev']; // TODO: remove hardcoded email const inputEmails = initialInput.client?.emails?.filter(Boolean) ?? []; if (inputEmails.length) { emails.push(...inputEmails); } else { emails.push(...(greenInvoiceClient.emails ?? [])); } client = { id: greenInvoiceClient.id, country: countryCodeToGreenInvoiceCountry(initialInput.client.country), name: initialInput.client.name, phone: initialInput.client.phone, taxId: initialInput.client.taxId, self: false, address: initialInput.client.address, city: initialInput.client.city, zip: initialInput.client.zipCode, fax: initialInput.client.fax, mobile: initialInput.client.mobile, emails, }; } // clean input by converting to writeable and removing unwanted properties const cleanedInput = { ...initialInput }; delete cleanedInput.language; const input = { ...cleanedInput, currency: convertCurrencyToGreenInvoice(initialInput.currency), type: getGreenInvoiceDocumentType(initialInput.type), lang: getGreenInvoiceDocumentLanguage(initialInput.language), vatType: getGreenInvoiceDocumentVatType(initialInput.vatType ?? 'DEFAULT'), discount: initialInput.discount ? { ...initialInput.discount, type: getGreenInvoiceDocumentDiscountType(initialInput.discount.type), } : undefined, client, income: initialInput.income?.map(income => ({ ...income, currency: convertCurrencyToGreenInvoice(income.currency), vatType: getGreenInvoiceDocumentVatType(income.vatType ?? 'DEFAULT'), })) ?? [], payment: initialInput.payment?.map(payment => ({ ...payment, type: getGreenInvoiceDocumentPaymentType(payment.type), subType: undefined, appType: undefined, cardType: payment.cardType ? getGreenInvoiceDocumentPaymentCardType(payment.cardType) : undefined, dealType: undefined, currency: convertCurrencyToGreenInvoice(payment.currency), })), linkedDocumentIds: initialInput.linkedDocumentIds?.length ? [...initialInput.linkedDocumentIds] : undefined, linkType: initialInput.linkType ? getGreenInvoiceDocumentLinkType(initialInput.linkType) : undefined, }; return input; } export async function convertGreenInvoiceDocumentToDocumentDraft(greenInvoiceDocument, injector) { const client = await (greenInvoiceDocument.client?.id ? injector .get(ClientsProvider) .getClientByGreenInvoiceIdLoader.load(greenInvoiceDocument.client?.id) : Promise.resolve(undefined)); return { ...greenInvoiceDocument, client, currency: greenInvoiceDocument.currency, income: greenInvoiceDocument.income?.filter(Boolean).map(income => ({ ...income, currency: income.currency, vatType: getVatTypeFromGreenInvoiceDocument(income.vatType), })), language: getLanguageFromGreenInvoiceDocument(greenInvoiceDocument.lang), payment: greenInvoiceDocument.payment?.filter(Boolean).map(payment => ({ ...payment, appType: undefined, cardType: payment?.cardType ? getCardTypeFromGreenInvoiceDocumentPayment(payment.cardType) : undefined, currency: payment.currency, dealType: undefined, subType: undefined, type: getTypeFromGreenInvoiceDocumentPayment(payment.type), })), type: getTypeFromGreenInvoiceDocument(greenInvoiceDocument.type), vatType: getVatTypeFromGreenInvoiceDocument(greenInvoiceDocument.vatType), }; } //# sourceMappingURL=green-invoice.helper.js.map