// PayJoe-compatible short codes for Amazon fee / transaction types, used in the // lexoffice CSV Verwendungszweck so that lexoffice "Buchungsregeln" (automatic // categorisation rules keyed on the purpose text) can be written once per fee // type and keep matching across every export — exactly the way a PayJoe-fed // bookkeeping is set up (`AMA-SG-DE-SubFe`, `AMA-BG-DE-`, `AUSZ-DE-`). // // Source: PayJoe's own Amazon documentation ("von PayJoe fest vorgegebene // Transaktionen" + "Amazon Gebühren" abbreviation table, copied verbatim). The // keys are Amazon's report-style names; the Finances API sometimes uses slightly // different spellings, so `amazonFeeCode()` normalises before looking up and // falls back to a PayJoe-style consonant abbreviation for anything unknown. export const AMAZON_FEE_CODES: Record = { 'A2ZGuaranteeRecovery': '2ZGRNTRC', 'AGSGlobalInboundTransportation': 'GSGLBLNB', 'A-to-z Guarantee Refund': 'AtoZRefu', 'Adjustment': 'DJSTMNT', 'Adjustment for financial transaction': 'DJSTMNTF', 'AmazonFees': 'MZNFS', 'Amazon service fee for EPR Pay on Behalf - ES - Pa': 'MZNSRVC4', 'Amazon service fee for EPR Pay on Behalf - FR - Ch': 'MZNSRV10', 'Amazon service fee for EPR Pay on Behalf - FR - El': 'MZNSRVCF', 'Amazon service fee for EPR Pay on Behalf - FR - Fu': 'MZNSRVC2', 'Amazon service fee for EPR Pay on Behalf - FR - Pa': 'MZNSRVC6', 'Amazon service fee for EPR Pay on Behalf - FR - Oi': 'MZNSRVC9', 'Amazon service fee for EPR Pay on Behalf - FR - TY': 'MZNSRVC3', 'Amazon service fee for EPR Pay on Behalf - GB - Pa': 'MZNSRVC5', 'BalanceAdjustment': 'BalAdj', 'BuyerRecharge': 'BuyRe', 'Capacity reservation fee': 'CPCTYRSR', 'Coupon Performance Based Fee': 'CPNPRFRM', 'CRETURN_WRONG_ITEM': 'CRTRNWRN', 'Chargeback': 'ChargeBk', 'ChargeBackRecovery': 'CHRGBCKR', 'Chargeback Refund': 'ChrgBkRe', 'CommissionCorrection': 'CMMSSNCR', 'COMPENSATED_CLAWBACK': 'CMPNSTDC', 'Cost of Advertising': 'CoAdv', 'Coupon Participation Fee': 'CPNPRTCP', 'CouponParticipationFee': 'CPNPRTC1', 'CouponPerformanceFee': 'CPNPRFR3', 'CouponRedemptionFee': 'CPNRDMPT', 'CS_ERROR_ITEMS': 'CSErrIt', 'CS_ERROR_NON_ITEMIZED': 'CSErrNIt', 'Current Reserve Amount': 'CurrReAm', 'Deal Participation Fee': 'DLPRTCPT', 'DealParticipationFee': 'DLPRTCP1', 'DealPerformanceFee': 'DLPRFRM1', 'Deal Performance Based Fee': 'DLPRFRMN', 'DebtAdjustment': 'DBTDJSTM', 'DebtCreation': 'DBTCRTN', 'DebtPaymentLevel2Failure': 'DePaL2Fa', 'Digital Services Fee': 'DGTLSRVC', 'Digital Services Fee Adjustment': 'DGTLSRV1', 'DisposalComplete - Reversal': 'DSPSLCMP', 'DisbursementCorrection': 'DisbCorr', 'DisposalComplete': 'DispComp', 'Eco-contribution for EPR Pay on Behalf - FR - Chem': 'CCNTRB10', 'Eco-contribution for EPR Pay on Behalf - ES - Pack': 'CCNTRBT4', 'Eco-contribution for EPR Pay on Behalf - FR - Elec': 'CCNTRBTN', 'Eco-contribution for EPR Pay on Behalf - FR - Furn': 'CCNTRBT2', 'Eco-contribution for EPR Pay on Behalf - FR - Pack': 'CCNTRBT6', 'Eco-contribution for EPR Pay on Behalf - FR - TYRE': 'CCNTRBT3', 'Eco-contribution for EPR Pay on Behalf - FR - Oils': 'CCNTRBT9', 'Eco-contribution for EPR Pay on Behalf - GB - Pack': 'CCNTRBT5', 'EPR Pay on Behalf eco-contribution': 'PRPYNBHL', 'EPR Pay on Behalf Fee - Battery': 'PRPYNB14', 'EPR Pay on Behalf Fee - Construction Unknown': 'PRPYNB13', 'EPR Pay on Behalf Fee - Chemicals': 'PRPYNBH7', 'EPR Pay on Behalf Fee - Do-it-yourself (DIY)': 'PRPYNB15', 'EPR Pay on Behalf Fee - EEE': 'PRPYNBH3', 'EPR Pay on Behalf Fee - Electrical and Electronic': 'PRPYNB17', 'EPR Pay on Behalf Fee - Furniture': 'PRPYNBH4', 'EPR Pay on Behalf Fee - Packaging and Printed Pape': 'PRPYNB16', 'EPR Pay on Behalf Fee - Oils': 'PRPYNBH8', 'EPR Pay on Behalf Fee - Sports': 'PRPYNBH9', 'EPR Pay on Behalf Fee - PACKAGING_AND_PRINTED_PAPE': 'PRPYNB12', 'EPR Pay on Behalf Fee - TEXTILE': 'PRPYNBH6', 'EPR Pay on Behalf Fee - Tobacco': 'PRPYNB11', 'EPR Pay on Behalf Fee - Toys': 'PRPYNBH2', 'EPR Pay on Behalf Fee - TYRE': 'PRPYNB10', 'EPR Pay on Behalf service fee': 'PRPYNBH1', 'EPR Pay on Behalf Fee - Packaging': 'PRPYNBH5', 'Failed Disbursement': 'FailDisb', 'FBA Customer Returns Fee (Non-Apparel and Non-Shoe)': 'FBCSTMR2', 'FBA Customer Return Per Unit Fee': 'FBCSTMR3', 'FBAFees': 'FBAFees', 'FBAFees - Correction': 'FBFSCRRC', 'FBAFees - Reversal': 'FBFSRVRS', 'FBA fulfilment fee per unit': 'FBFLFLM2', 'FBA fulfilment fee per unit - Correction': 'FBFLFLM1', 'FBA fulfilment fee per unit - Reversal': 'FBFLFLMN', 'FBA International Freight Duties and Taxes Charge': 'FBNTRNT1', 'FBA International Freight Shipping Charge Adjustment': 'FBNTRNT2', 'FBA Inventory Reimbursement - Customer Return': 'FBAIRCR', 'FBA Inventory Reimbursement - Customer Service Issue': 'FBAIRCSI', 'FBA Inventory Reimbursement - Damaged': 'FBNVNTRY', 'FBA Inventory Reimbursement - Damaged:Warehouse': 'FBAIRDW', 'FBA Inventory Reimbursement - Fee Correction': 'FBNVNTR1', 'FBA Inventory Reimbursement - Lost': 'FBNVNTR2', 'FBA Inventory Reimbursement - Return Adjustment': 'FBNVNTR3', 'FBA Inventory Storage Fee': 'FBNVNTR4', 'FBA Inventory Storage Fee - Correction': 'FBNVNTR5', 'FBA Inventory Storage Fee - Reversal': 'FBNVNTR6', 'FBACustomerReturn': 'FBCSTMRR', 'FBACustomerReturnPerUnitFee': 'FBCSTMR1', 'FBAInboundTransportationFee': 'FBNBNDTR', 'FBA Long Term Storage Fee': 'FBLNGTRM', 'FBA Long Term Storage Fee - Reversal': 'FBLNGTR1', 'FBA Pick & Pack Fee': 'FBAPCKPCK', 'FBA Prep Fee': 'FBPRPF', 'FBAInboundTransportationProgramFee': 'FBNBNDT1', 'FBAPerUnitFulfillmentFee': 'FBPRNT', 'FBA Inbound Placement Service Fee': 'FBNBNDPL', 'FBATryBeforeYouBuyMultitierPerUnitFee': 'FBTRYBFR', 'FBA Removal Order': 'FBRMVLRD', 'Fee Adjustment': 'FDJSTMNT', 'FREE_REPLACEMENT_REFUND_ITEMS': 'FRRPLCM1', 'FREE_REPLACEMENT_REFUND_NON_ITEMIZED': 'FRRPLCMN', 'GuaranteeClaim': 'GteeClm', 'Goodwill Concession': 'GDWLLCNC', 'Imaging Services': 'MGNGSRV1', 'Imaging Services Fee': 'MGNGSRVC', 'Inbound Defect Fee - Amazon barcode missing': 'NBNDDFCT', 'Inbound Transportation Charge': 'InbTraCh', 'Inbound Transportation Fee': 'NBNDTRNS', 'INBOUND_CARRIER_DAMAGE': 'InbCarDa', 'INCORRECT_FEES_ITEMS': 'IncorFeIt', 'INCORRECT_FEES_NON_ITEMIZED': 'IncFeNIt', 'Inventory Placement Service Fee': 'NVNTRYPL', 'Inventory Storage Overage Fee': 'NVNTRYST', 'Legal or Compliance Adjustment': 'LGLRCMPL', 'Lightning Deal Fee': 'LighDeFe', 'LightningDealFee': 'LGHTNNGD', 'Liquidations': 'LQDTNS', 'Liquidations Adjustments': 'LQDTNSDJ', 'LiquidationsFee': 'LQDTNSF', 'LocalizationOrderComplete': 'LCLZTNRD', 'Lq': 'Lq', 'LqAdj': 'LqAdj', 'LqAdjFee': 'LqAdjFee', 'LqFee': 'LqFee', 'MaunualDisbursement': 'MNLDSBRS', 'Manual Processing Fee': 'ManProFe', 'Manual Processing Fee Reimbursement': 'MNLPRCSS', 'MarketplaceFacilitatorVAT': 'MRKTPLCF', 'MDotComRevenueCorrection': 'MDCReCor', 'Micro Deposit': 'MCRDPST', 'Micro Deposit (Failed)': 'MCRDPSTF', 'MiscAdjustment': 'MSCDJSTM', 'MISSING_FROM_INBOUND': 'MisFrInb', 'MISSING_FROM_INBOUND_CLAWBACK': 'MSSNGFRM', 'MktFaVat': 'MktFaVat', 'MULTICHANNEL_ORDER_DAMAGED': 'MuChOrDa', 'MULTICHANNEL_ORDER_LATE': 'MLTCHNNL', 'MULTICHANNEL_ORDER_LOST': 'MulOrdLo', 'Non-Amazon': 'NNMZN', 'NonSubscriptionFeeAdj': 'NSubFeAd', 'OrderCancellationCharge': 'RDRCNCLL', 'Order_Retrocharge': 'RDRRTRCH', 'Other': 'Other', 'other-transaction': 'THRTRNS2', 'Overpaid Fees Adjustment': 'VRPDFSDJ', 'Paid Services Fee': 'PDSRVCSF', 'PaidServicesFee': 'PDSRVCS1', 'Payable to Amazon': 'PayaTAma', 'PAYMENT_RETRACTION_ITEMS': 'PYMNTRTR', 'Performance credits': 'PRFRMNCC', 'Referral Fee Adjustment': 'RFRRLFDJ', 'Policy violation': 'PLCYVLTN', 'PostageAdjustment': 'PSTGDJST', 'Premium Services Fee': 'PRMMSRVC', 'PREPFEE_REFUND': 'PrepfRef', 'Promotion Adjustment': 'PRMTNDJS', 'Promotion Fee': 'PRMTNF', 'PromotionFee': 'PRMTNF1', 'Previous Reserve Amount Balance': 'PrReAmBa', 'PRIME_WARDROBE_REIMBURSEMENT': 'PRMWRDRB', 'RE_EVALUATION': 'REEvalu', 'RefundCommission': 'RFNDCMMS', 'Refund for Advertiser': 'RFNDFRDV', 'Refund_Retrocharge': 'RFNDRTRC', 'Refund Reimbursal': 'RFNDRMBR', 'REMOVAL_ORDER_DAMAGED': 'RemOrdDa', 'REMOVAL_ORDER_LOST': 'RemOrdLo', 'RemovalComplete': 'RemCompl', 'Reservation fee': 'RSRVTNF', 'Retrocharge': 'RetChar', 'RetrochargeReversal': 'RTRCHRGR', 'ReturnPostageBilling': 'RetPosBi', 'REVERSAL_REIMBURSEMENT': 'RevReimb', 'Review Enrollment Fee': 'RVWNRLLM', 'SAFE-T reimbursement': 'SAFE-T', 'SellerPoweredCouponPayment': 'SLLRPWRD', 'SellerReviewEnrollmentPayment': 'SLLRRVWN', 'Seller Rewards': 'SLLRRWRD', 'ServiceFee': 'ServFe', 'ShipmentSettle': 'SHPMNTST', 'Shipping label purchase': 'ShiLaPur', 'Shipping label purchase for return': 'SHPPNGLB', 'ShippingServices': 'ShipServ', 'ShippingServicesRefund': 'ShiSerRe', 'Storage Fee': 'StorFe', 'StorageRenewalBilling': 'StoRenBi', 'StorageRenewalBilling - Correction': 'STRGRNW1', 'StorageRenewalBilling - Reversal': 'STRGRNWL', 'Subscription Fee': 'SubFe', 'SubscriptionFeeCorrection': 'SubFeCor', 'Subscription Fee Refund - Balance Adjustment': 'SBSCRPT1', 'Subscription Fee Refund To Credit Card': 'SBSCRPTN', 'Subscription Fee - Reversal': 'SBSCRPT2', 'Successful charge': 'SucChar', 'Tax Adjustment': 'TXDJSTMN', 'Tax': 'Tax', 'Taxes on Digital Services Fee Adjustment': 'TXSNDGTL', 'Tax Withholding Reimbursement': 'TXWTHHLD', 'TBYB Customer Return Fee': 'TBYBCSTM', 'TBYB Order Payment': 'TBYBRDRP', 'TBYB Trial Shipment': 'TBYBTRLS', 'Transfers': 'TRNSFRS', 'Transfer of funds unsuccessful': 'TrOFuUns', 'TrialShipment': 'TRLSHPMN', 'Unplanned Service Fee - Barcode label missing': 'UnpServFe', 'Unplanned service fee - Amazon barcode missing': 'NPLNNDSR', 'VatFilingCharge': 'VTFLNGCH', 'VAT/GST refund for Seller Fees': 'VTGSTRFN', 'VatRegistrationCharge': 'VTRGSTRT', 'VineFee': 'VineFee', 'Vine Enrollment Fee': 'VNNRLLMN', 'WAREHOUSE_DAMAGE': 'WarehDam', 'WAREHOUSE_DAMAGE_EXCEPTION': 'WaHDamEx', 'WAREHOUSE_LOST': 'WRHSLST', 'WAREHOUSE_LOST_MANUAL': 'WaHLoMan', 'WarehousePrep': 'WarHPrep', 'WarehousePrep - Correction': 'WRHSPRPC', 'WarehousePrep - Reversal': 'WRHSPRPR' } // Finances-API spellings that differ from the report-style names above. // (The Finances API's ServiceFeeEventList / AdjustmentEventList use these.) const FINANCES_API_ALIASES: Record = { 'Subscription': 'Subscription Fee', 'SubscriptionFee': 'Subscription Fee', 'ProductAds': 'Cost of Advertising', 'Advertising': 'Cost of Advertising', 'CHARGE': 'Cost of Advertising', 'Commission': 'AmazonFees', 'FBAPerUnitFulfillmentFee': 'FBAPerUnitFulfillmentFee', 'ShippingHB': 'FBA fulfilment fee per unit', 'ReturnPostageBilling_RestockingFee': 'ReturnPostageBilling', 'ReturnPostageBilling_Postage': 'ReturnPostageBilling' } const normalizeKey = (value: string) => String(value || '').toLowerCase().replace(/[^a-z0-9]+/g, '') let normalizedIndex: Map | null = null const getNormalizedIndex = () => { if (!normalizedIndex) { normalizedIndex = new Map() for (const [name, code] of Object.entries(AMAZON_FEE_CODES)) { const key = normalizeKey(name) if (!normalizedIndex.has(key)) normalizedIndex.set(key, code) } } return normalizedIndex } // PayJoe-style fallback for names not in the table: drop vowels/punctuation // and cut to 8 chars ("Adjustment" -> "DJSTMNT" is exactly how PayJoe builds them). const abbreviate = (value: string): string => { const cleaned = String(value || '').replace(/[^A-Za-z0-9]+/g, '') if (!cleaned) return 'OTHER' const consonants = cleaned.replace(/[aeiouAEIOU]/g, '') const base = consonants.length >= 4 ? consonants : cleaned return base.toUpperCase().substring(0, 8) } // Look up the short code for a fee/transaction type name. Tries an exact match, // then a Finances-API alias, then a punctuation/case-insensitive match, then the // abbreviation fallback — never returns an empty string. export const amazonFeeCode = (name: string): string => { const raw = String(name || '').trim() if (!raw) return 'OTHER' if (AMAZON_FEE_CODES[raw]) return AMAZON_FEE_CODES[raw] const alias = FINANCES_API_ALIASES[raw] if (alias && AMAZON_FEE_CODES[alias]) return AMAZON_FEE_CODES[alias] // "ReturnPostageBilling_Postage" style: try the part before the first underscore too. const stem = raw.split('_')[0] if (stem !== raw && AMAZON_FEE_CODES[stem]) return AMAZON_FEE_CODES[stem] const hit = getNormalizedIndex().get(normalizeKey(raw)) || getNormalizedIndex().get(normalizeKey(stem)) if (hit) return hit return abbreviate(raw) } // Marketplace suffix used in the PayJoe purpose codes: "Amazon.de" -> "DE", // "Amazon.co.uk" -> "CO.UK", "Amazon.com" -> "COM", "Amazon.com.mx" -> "COM.MX". export const amazonMarketplaceCode = (marketplaceName: string, fallback = 'DE'): string => { const name = String(marketplaceName || '').trim().toLowerCase() if (!name) return fallback const m = name.match(/amazon\.([a-z.]+)/) if (m && m[1]) return m[1].toUpperCase() return fallback }