/**
  * Get Tax History processor
  *
  * <p>{@sample.xml ../../../doc/avalara-connector.xml.sample avalara:get-tax-history}
  *
  * @param docId The original document's type, such as Sales Invoice or Purchase Invoice.
  * @param companyCode Client application company reference code. If docId is specified, this is
  *     not needed.
  * @param docType The document type specifies the category of the document and affects how the
  *     document is treated after a tax calculation; see {@link AvalaraDocumentType} for more
  *     information about the specific document types.
  * @param docCode The internal reference code used by the client application.
  * @param detailLevel Specifies the level of detail to return. See {@link DetailLevelType}.
  * @return The {@link GetTaxHistoryResult}
  * @throws AvalaraRuntimeException
  */
 @Processor
 public GetTaxHistoryResult getTaxHistory(
     @Optional String docId,
     String companyCode,
     AvalaraDocumentType docType,
     @Optional String docCode,
     DetailLevelType detailLevel) {
   return (GetTaxHistoryResult)
       apiClient.sendTaxRequestToAvalara(
           TaxRequestType.GetTaxHistory,
           mom.unmap(
               new MapBuilder()
                   .with("docId", docId)
                   .with("companyCode", companyCode)
                   .with("docType", docType.toDocumentType())
                   .with("docCode", docCode)
                   .with("detailLevel", detailLevel.toAvalaraDetailLevel())
                   .build(),
               GetTaxHistoryRequest.class));
 }
  /**
   * Adjust Tax processor.
   *
   * <p>The Get Tax operation calculates tax for one or more invoiced items and displays details
   * describing the calculation of tax for each line item.
   *
   * <p>{@sample.xml ../../../doc/avalara-connector.xml.sample avalara:adjust-tax}
   *
   * @param companyCode Client application company reference code
   * @param adjustmentReason The reason for this tax adjustment.
   * @param adjustmentDescription A description of a tax adjustment.
   * @param docType The document type specifies the category of the document and affects how the
   *     document is treated after a tax calculation; see {@link AvalaraDocumentType} for more
   *     information about the specific document types.
   * @param docCode The internal reference code used by the client application.
   * @param docDate Date of invoice, purchase order, etc.
   * @param salespersonCode The client application salesperson reference code.
   * @param customerCode Client application customer reference code
   * @param customerUsageType Client application customer or usage type. CustomerUsageType
   *     determines the exempt status of the transaction based on the exemption tax rules for the
   *     jurisdictions involved. CustomerUsageType may also be set at the line item level.
   *     <p>The standard values for the CustomerUsageType (A-L).<br>
   *     A Federal Government<br>
   *     B State/Local Govt.<br>
   *     C Tribal Government<br>
   *     D Foreign Diplomat<br>
   *     E Charitable Organization<br>
   *     F Religious/Education<br>
   *     G Resale<br>
   *     H Agricultural Production<br>
   *     I Industrial Prod/Mfg.<br>
   *     J Direct Pay Permit<br>
   *     K Direct Mail<br>
   *     L - Other
   * @param discount The discount amount to apply to the document. The string represents a {@link
   *     BigDecimal}.
   * @param purchaseOrderNo Purchase order identifier. PurchaseOrderNo is required for single use
   *     exemption certificates to match the order and invoice with the certificate.
   * @param exemptionNo Exemption number used for this transaction
   * @param originCode Code that refers one of the address of the baseAddress collection. It has to
   *     be the same code of one of the address's addressCode. It represents the origin address.
   * @param destinationCode Code that refers one of the address of the baseAddress collection. It
   *     has to be the same code of one of the address's addressCode. It represents the destination
   *     address.
   * @param baseAddresses Collection of physical addresses that will be referred to as the
   *     destination or origination of 1 or more invoice line entries
   * @param lines Collection of invoice lines requiring tax calculation
   * @param detailLevel Specifies the level of tax detail to return
   * @param referenceCode For returns (see {@link AvalaraDocumentType}), refers to the {@link
   *     AdjustTaxRequest} of the original invoice.
   * @param locationCode Location Code value. It is Also referred to as a Store Location, Outlet Id,
   *     or Outlet code is a number assigned by the State which identifies a Store location. Some
   *     state returns require taxes are broken out separately for Store Locations.
   * @param commit Commit flag. If Commit is set to true, tax for the transaction is saved, posted
   *     and committed as tax document.
   * @param batchCode The batchCode value.
   * @param taxOverride Indicates to apply tax override to the document.
   * @param currencyCode It is 3 character ISO 4217 currency code.
   * @param serviceMode This is only supported by AvaLocal servers. It provides the ability to
   *     controls whether tax is calculated locally or remotely when using an AvaLocal server. The
   *     default is Automatic which calculates locally unless remote is necessary for non-local
   *     addresses.
   * @param paymentDate The date on which payment was made.
   * @param exchangeRate The exchange rate value. The string represents a {@link BigDecimal}
   * @param exchangeRateEffDate The exchange rate effective date value.
   * @return The {@link AdjustTaxResult}
   * @throws AvalaraRuntimeException
   */
  @Processor
  public AdjustTaxResult adjustTax(
      int adjustmentReason,
      String adjustmentDescription,
      String companyCode,
      AvalaraDocumentType docType,
      @Optional String docCode,
      XMLGregorianCalendar docDate,
      @Optional String salespersonCode,
      String customerCode,
      @Optional String customerUsageType,
      String discount,
      @Optional String purchaseOrderNo,
      @Optional String exemptionNo,
      String originCode,
      String destinationCode,
      List<Map<String, Object>> baseAddresses,
      List<Map<String, Object>> lines,
      DetailLevelType detailLevel,
      @Optional String referenceCode,
      @Optional String locationCode,
      @Default("false") boolean commit,
      @Optional String batchCode,
      @Optional Map<String, Object> taxOverride,
      @Optional String currencyCode,
      @Default("AUTOMATIC") ServiceModeType serviceMode,
      XMLGregorianCalendar paymentDate,
      String exchangeRate,
      XMLGregorianCalendar exchangeRateEffDate) {
    BigDecimal discountDecimal = discount == null ? null : new BigDecimal(discount);
    BigDecimal exchangeRateDecimal = exchangeRate == null ? null : new BigDecimal(exchangeRate);

    Map<String, Object> addresses = null;
    if (baseAddresses != null && !baseAddresses.isEmpty()) {
      addresses = new HashMap<String, Object>();
      addresses.put("baseAddress", baseAddresses);
    }

    Map<String, Object> mapLines = null;
    if (lines != null && !lines.isEmpty()) {
      mapLines = new HashMap<String, Object>();
      mapLines.put("line", lines);
    }
    GetTaxRequest getTaxRequest =
        (GetTaxRequest)
            mom.unmap(
                new MapBuilder()
                    .with("companyCode", companyCode)
                    .with("docType", docType.toDocumentType())
                    .with("docCode", docCode)
                    .with("docDate", docDate)
                    .with("salespersonCode", salespersonCode)
                    .with("customerCode", customerCode)
                    .with("customerUsageType", customerUsageType)
                    .with("discount", discountDecimal)
                    .with("purchaseOrderNo", purchaseOrderNo)
                    .with("exemptionNo", exemptionNo)
                    .with("originCode", originCode)
                    .with("destinationCode", destinationCode)
                    .with("addresses", addresses)
                    .with("lines", mapLines)
                    .with("detailLevel", detailLevel.toAvalaraDetailLevel())
                    .with("referenceCode", referenceCode)
                    .with("locationCode", locationCode)
                    .with("commit", commit)
                    .with("batchCode", batchCode)
                    .with("taxOverride", taxOverride)
                    .with("currencyCode", currencyCode)
                    .with("serviceMode", serviceMode.toAvalaraServiceMode())
                    .with("paymentDate", paymentDate)
                    .with("exchangeRate", exchangeRateDecimal)
                    .with("exchangeRateEffDate", exchangeRateEffDate)
                    .build(),
                GetTaxRequest.class);

    return apiClient.sendTaxRequestToAvalara(
        TaxRequestType.AdjustTax,
        mom.unmap(
            new MapBuilder()
                .with("adjustmentReason", adjustmentReason)
                .with("adjustmentDescription", adjustmentDescription)
                .with("getTaxRequest", getTaxRequest)
                .build(),
            AdjustTaxRequest.class));
  }