{
  "_class" : "hudson.model.FreeStyleBuild",
  "actions" : [
    {
      "_class" : "hudson.model.CauseAction",
      "causes" : [
        {
          "_class" : "hudson.triggers.TimerTrigger$TimerTriggerCause",
          "shortDescription" : "Started by timer"
        }
      ]
    },
    {
      
    },
    {
      "_class" : "hudson.plugins.git.util.BuildData",
      "buildsByBranchName" : {
        "refs/remotes/origin/dev" : {
          "_class" : "hudson.plugins.git.util.Build",
          "buildNumber" : 741,
          "buildResult" : None,
          "marked" : {
            "SHA1" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
            "branch" : [
              {
                "SHA1" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
                "name" : "refs/remotes/origin/dev"
              }
            ]
          },
          "revision" : {
            "SHA1" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
            "branch" : [
              {
                "SHA1" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
                "name" : "refs/remotes/origin/dev"
              }
            ]
          }
        }
      },
      "lastBuiltRevision" : {
        "SHA1" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
        "branch" : [
          {
            "SHA1" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
            "name" : "refs/remotes/origin/dev"
          }
        ]
      },
      "remoteUrls" : [
        "https://github.com/younex1/erp-nuxt-frontend.git"
      ],
      "scmName" : ""
    },
    {
      
    },
    {
      
    },
    {
      "_class" : "org.jenkinsci.plugins.displayurlapi.actions.RunDisplayAction"
    }
  ],
  "artifacts" : [
    
  ],
  "building" : False,
  "description" : None,
  "displayName" : "#741",
  "duration" : 70605,
  "estimatedDuration" : 71602,
  "executor" : None,
  "fullDisplayName" : "build-logship-frontend #741",
  "id" : "741",
  "inProgress" : False,
  "keepLog" : False,
  "number" : 741,
  "queueId" : 5746,
  "result" : "SUCCESS",
  "timestamp" : 1789776000766,
  "url" : "https://jenkins.younex.de/job/build-logship-frontend/741/",
  "builtOn" : "",
  "changeSet" : {
    "_class" : "hudson.plugins.git.GitChangeSetList",
    "items" : [
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/utils/amazonAds/importInvoice.ts",
          "server/utils/amazonAds/parseInvoicePdf.ts",
          "server/utils/amazonAds/adsApi.ts",
          "server/api/accounting/amazon-ads/import.post.ts",
          "reference/test-scripts/amazon-fee-parse.mjs",
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/utils/amazonAds/types.ts",
          "server/api/accounting/amazon-ads/invoices.get.ts",
          "nuxt.config.ts",
          "server/api/accounting/amazon-ads/upload.post.ts",
          "server/api/accounting/amazon-ads/status.get.ts",
          "server/utils/amazonAds/parseSellerFeeInvoicePdf.ts",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "9e5d44b9cb79373965ffd173001cf1268e6d3889",
        "timestamp" : 1789723068000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: book seller fee invoices (Tax Document Library PDFs) next to Ads invoices\u000a\u000aAmazon offers no API for the seller fee invoices in Europe (the SP-API Invoices\u000aAPI is Brazil-only, no report type covers them), so the PDFs downloaded from\u000aSeller Central are dropped on the existing Amazon invoices page.\u000a\u000a- parseSellerFeeInvoicePdf.ts: text-layer parser (kind 'fee'), one line per fee\u000a  type with its own VAT rate; runs before the Ads parser in the upload route\u000a- vendor resolved by the issuer's VAT id, created under org * on first import\u000a- own charge (AMAZON_FEE_CHARGE_ID, default 1000009 \"Amazon Gebühren\"), tax per\u000a  line rate; credit notes are listed but not importable yet\u000a- list route checks bookings across the Ads vendor and all fee vendors\u000a- page: Type / Aussteller / Empfänger columns, second charge selector\u000a",
        "date" : "2026-09-18 11:17:48 +0200",
        "id" : "9e5d44b9cb79373965ffd173001cf1268e6d3889",
        "msg" : "Amazon invoices: book seller fee invoices (Tax Document Library PDFs) next to Ads invoices",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "nuxt.config.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/upload.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/parseInvoicePdf.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/import.post.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/amazonAds/parseSellerFeeInvoicePdf.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/status.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/adsApi.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/types.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/importInvoice.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          },
          {
            "editType" : "add",
            "file" : "reference/test-scripts/amazon-fee-parse.mjs"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/offers/conditions/index.post.ts",
          "server/utils/offers/quotePdf.ts",
          "app/pages/partners/partners/[id]/edit.vue",
          "server/utils/offers/quoteConfirmation.ts",
          "app/components/offers/QuoteModal.vue",
          "app/components/offers/ForecastModal.vue",
          "app/composables/useOfferQuote.ts",
          "server/utils/offers/forecastPdf.ts",
          "server/api/offers/forecast/preview.post.ts",
          "server/utils/offers/offerConditions.ts",
          "app/pages/users/leads/[id]/edit.vue",
          "server/api/offers/quote/send.post.ts",
          "server/api/offers/forecast/send.post.ts",
          "app/assets/langs/shared.js",
          "app/composables/useOfferForecast.ts"
        ],
        "commitId" : "08ca7d5f074a1d4399860ffe4859350839a41e06",
        "timestamp" : 1789726519000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Offers: custom forecast modal (scenarios, editable positions, PDF/send) + editable quote validity\u000a\u000aCustom forecast (\"Individuelle Prognose\"): standalone cost forecast for leads and\u000apartners, opened from a new \"Prognose\" button on both pages and from the quote\u000amodal's forecast card (seeded from the live quote form). Seeds from the saved\u000acustom forecast, else the saved quote conditions, else list prices. Every\u000aposition can be switched off, relabelled and re-priced (per order with factor or\u000a% share, or per month), own positions added, up to 4 volume scenarios side by\u000aside (3+ print landscape), display toggles for calculation column, unit prices,\u000asubtotals, cost per order, yearly total and disclaimer. Save as draft\u000a(offer_conditions.forecast), download, or e-mail with record attachment and\u000aactivity. Client computes, server only renders.\u000a\u000aQuote validity: \"Gültig (Tage)\" and \"Gültig bis\" pair in the quote modal, default\u000a7 days from now. One server resolver (resolveQuoteValidity) drives the PDF, the\u000ae-mail text, the activity, the saved conditions and the confirmation link expiry.\u000a",
        "date" : "2026-09-18 12:15:19 +0200",
        "id" : "08ca7d5f074a1d4399860ffe4859350839a41e06",
        "msg" : "Offers: custom forecast modal (scenarios, editable positions, PDF/send) + editable quote validity",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          },
          {
            "editType" : "add",
            "file" : "app/components/offers/ForecastModal.vue"
          },
          {
            "editType" : "add",
            "file" : "server/api/offers/forecast/preview.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/offers/quoteConfirmation.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/offers/quotePdf.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/offers/quote/send.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/components/offers/QuoteModal.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/users/leads/[id]/edit.vue"
          },
          {
            "editType" : "add",
            "file" : "server/api/offers/forecast/send.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/offers/offerConditions.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/partners/partners/[id]/edit.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/composables/useOfferQuote.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/offers/conditions/index.post.ts"
          },
          {
            "editType" : "add",
            "file" : "app/composables/useOfferForecast.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/offers/forecastPdf.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/accounting/amazon-ads/booking.get.ts",
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/utils/amazonAds/importInvoice.ts",
          "app/assets/langs/shared.js",
          "server/api/accounting/amazon-ads/invoices.get.ts"
        ],
        "commitId" : "7c40ce743ed6563a2b58c00f358be5d811025e38",
        "timestamp" : 1789729923000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: document details, paid vs created status, Lexoffice reset, pinned actions\u000a\u000a- \"Beleg in\" column (org · vendor) + details dialog per created AP invoice\u000a  (new booking.get.ts: header, payment/Lexoffice state, lines with charge + tax)\u000a- status no longer says \"Verbucht\" for a merely created document: \"Beleg erstellt\u000a  · Zahlung offen\" until iDempiere has the invoice allocated to a payment\u000a  (IsPaid) → \"Bezahlt\"; separate counters\u000a- Lexoffice reset for selected rows and from the details dialog (shared\u000a  /api/invoices/lexoffice-reset), with a confirm that the voucher in Lexoffice\u000a  is not deleted\u000a- actions column pinned right, status/document columns moved left, API notice\u000a  collapsed by default, PDF icon fixed (ti-pdf)\u000a",
        "date" : "2026-09-18 13:12:03 +0200",
        "id" : "7c40ce743ed6563a2b58c00f358be5d811025e38",
        "msg" : "Amazon invoices: document details, paid vs created status, Lexoffice reset, pinned actions",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/amazon-ads/booking.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/importInvoice.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/utils/amazonAds/importInvoice.ts",
          "server/api/invoices/so.get.ts",
          "server/utils/amazonAds/parseSellerFeeInvoicePdf.ts",
          "app/pages/sales/invoices/index.vue",
          "server/api/accounting/opos/index.get.ts",
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/utils/amazonAds/types.ts",
          "server/api/accounting/amazon-ads/invoices.get.ts"
        ],
        "commitId" : "8aac736389fbef7e2d88535f9f39bc7b296c4eb9",
        "timestamp" : 1789731297000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: recognise fee credit notes and book them as AP CreditMemo\u000a\u000a- parser: \"STEUERGUTSCHRIFT\" template (Gutschriftennummer, Ausstellungsdatum /\u000a  Zeitraum der Gutschrift), amounts with the sign before the currency\u000a  (\"-EUR 2.61\"), \"Ursprüngliche Rechnungsnummer\" → originalInvoiceNo\u000a- import: credit notes become a vendor credit memo — doctype DocBaseType APC\u000a  (AP CreditMemo) with positive amounts, reference to the original invoice in\u000a  the description; no longer refused\u000a- OPOS + /sales/invoices: doctype 1000006 counts as customer-side only when the\u000a  partner is flagged IsCustomer, so genuine vendor credit memos stay on the\u000a  payables side (existing customer credit notes unchanged)\u000a",
        "date" : "2026-09-18 13:34:57 +0200",
        "id" : "8aac736389fbef7e2d88535f9f39bc7b296c4eb9",
        "msg" : "Amazon invoices: recognise fee credit notes and book them as AP CreditMemo",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/parseSellerFeeInvoicePdf.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/types.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/importInvoice.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/sales/invoices/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "server/api/invoices/so.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/opos/index.get.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/components/AgGrid/AgCopyEmail.vue",
          "app/components/AgGrid/AgDialPhone.vue",
          "app/pages/users/leads/index.vue",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "9779bba8ea83bac8745a1d1a8386e89c2a9a1135",
        "timestamp" : 1789731297000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Leads list: dial icon aligned to the right edge, copy button on the e-mail column\u000a\u000a- AgDialPhone: number stays left, only the dial button is pushed to the right\u000a  (shared renderer — also applies to the users / external users lists)\u000a- new AgCopyEmail cell renderer: copy-to-clipboard button with check-mark\u000a  feedback, does not start the inline editor\u000a",
        "date" : "2026-09-18 13:34:57 +0200",
        "id" : "9779bba8ea83bac8745a1d1a8386e89c2a9a1135",
        "msg" : "Leads list: dial icon aligned to the right edge, copy button on the e-mail column",
        "paths" : [
          {
            "editType" : "add",
            "file" : "app/components/AgGrid/AgCopyEmail.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/components/AgGrid/AgDialPhone.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/users/leads/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/components/dashboard/RecentCallsCard.vue",
          "app/components/telephony/BlacklistControl.vue",
          "server/api/telephony/blacklist.post.ts",
          "server/api/telephony/blacklist.get.ts",
          "app/components/DialButton.vue",
          "server/utils/telephony/blacklist.ts",
          "server/api/telephony/blacklist.delete.ts"
        ],
        "commitId" : "c8fb1add4aec93b10d32265652cff746fddd349b",
        "timestamp" : 1789732626000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Recent calls card: blacklist control moved into the number popover, with live status and unblock\u000a\u000a- no per-row block button any more (it cost a column of width); clicking the\u000a  number opens the popover, which now shows the FreePBX blacklist status and\u000a  either \"Nummer sperren\" (two-step confirm) or \"gesperrt · Entsperren\"\u000a- new TelephonyBlacklistControl, used inside the dial popover (DialButton\u000a  show-blacklist) and in the card's own popover for sessions that cannot dial\u000a- server: blacklist status read via AMI DBGet (one session for the ≤ 10 numbers\u000a  of a page), unblock via DBDel; GET + DELETE /api/telephony/blacklist. An\u000a  unexpected AMI error is \"status unknown\", never a false \"not blocked\"\u000a- blocked numbers are marked red with a ban icon in the list\u000a",
        "date" : "2026-09-18 13:57:06 +0200",
        "id" : "c8fb1add4aec93b10d32265652cff746fddd349b",
        "msg" : "Recent calls card: blacklist control moved into the number popover, with live status and unblock",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/utils/telephony/blacklist.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/telephony/blacklist.delete.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/telephony/blacklist.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/components/DialButton.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/components/dashboard/RecentCallsCard.vue"
          },
          {
            "editType" : "add",
            "file" : "app/components/telephony/BlacklistControl.vue"
          },
          {
            "editType" : "edit",
            "file" : "server/api/telephony/blacklist.post.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/utils/amazonAds/parseSellerFeeInvoicePdf.ts",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "b2d24d604b14700496f0d0ebc1f53dd8a3358015",
        "timestamp" : 1789732626000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: recognise the 2025 fee-invoice template, label the charge boxes as import settings\u000a\u000a- parser: 2025 labels (Rechnungsnr, Name des Anbieters / Verkaeufers, Adresse /\u000a  UStID des Anbieters) plus a label-independent fallback for supplier name and\u000a  VAT id, so the next rename by Amazon does not break recognition\u000a- page: the two charge selectors are grouped as \"Import-Einstellung · Kostenart\u000a  für neue Belege (kein Filter)\" with an explanatory tooltip\u000a",
        "date" : "2026-09-18 13:57:06 +0200",
        "id" : "b2d24d604b14700496f0d0ebc1f53dd8a3358015",
        "msg" : "Amazon invoices: recognise the 2025 fee-invoice template, label the charge boxes as import settings",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/parseSellerFeeInvoicePdf.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/api/accounting/amazon-ads/invoices.get.ts",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "7b3ffcb02f1a492cae8e96636728f270a769594e",
        "timestamp" : 1789733700000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: quick filters, optional date range, collapsed import settings, square upload box\u000a\u000a- quick-filter chips with counts: Typ (Ads / Gebühren / Gutschriften), Beleg\u000a  (ohne / erstellt / bezahlt), Lexoffice (noch nicht hochgeladen / hochgeladen);\u000a  totals follow the filter (\"1 von 3\")\u000a- no date filter by default; the optional invoice-date range sits behind a quiet\u000a  \"Zeitraum\" button, reloads on change, and an upload widens it so new invoices\u000a  are never hidden. The Ads API call keeps a bounded 12-month window server-side\u000a- the two cost-type selectors are collapsed behind \"Import-Einstellungen\" with a\u000a  one-line summary and an info box (what they do, why two, not a filter, when to\u000a  change); the panel opens by itself when a cost type is missing\u000a- upload area is a square drop box on the right with drag feedback and keyboard\u000a  support\u000a",
        "date" : "2026-09-18 14:15:00 +0200",
        "id" : "7b3ffcb02f1a492cae8e96636728f270a769594e",
        "msg" : "Amazon invoices: quick filters, optional date range, collapsed import settings, square upload box",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/api/accounting/amazon-ads/booking.get.ts",
          "server/api/accounting/amazon-ads/invoices.get.ts",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "786df63b6cc3a86132f1f9a056fec00574c6943a",
        "timestamp" : 1789734174000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: show voided documents properly, match them by POReference\u000a\u000a- a voided invoice row names its Storno document (\"Storniert #<id> · erneut\u000a  importierbar\"), opens its details (banner + link to iDempiere's reversal\u000a  document, no Lexoffice reset), has its own row tint, a \"Storno-Beleg\" action,\u000a  a \"Storniert\" quick-filter chip and a counter; it no longer counts as\u000a  \"Ohne Beleg (neu)\"\u000a- list route: documents are matched to the Amazon invoice by POReference (full\u000a  number) instead of DocumentNo — the void rename '<no>-VOID-<id>' is truncated\u000a  to the 30-char column ('DE-AEU-2025-2978769' → 'DE-AEU-2025-29787-VOID-…'),\u000a  so a voided document was not recognised; reversal documents are flagged and\u000a  listed after the original\u000a",
        "date" : "2026-09-18 14:22:54 +0200",
        "id" : "786df63b6cc3a86132f1f9a056fec00574c6943a",
        "msg" : "Amazon invoices: show voided documents properly, match them by POReference",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/booking.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/accounting/amazon-ads/document.get.ts",
          "reference/ci/deploy-production.sh",
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/api/accounting/amazon-ads/invoices.get.ts",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "bcd4de9387b784591e675d94d2d83cd354b63cb6",
        "timestamp" : 1789737288000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: iDempiere is the source of truth for booked invoices, PDFs from the document attachment\u000a\u000aThe page's list lived only in data/amazon-ads.db, which was missing from the\u000adeploy script's preserve list — every deploy wiped it, so booked invoices\u000avanished from the page (the documents themselves were never affected).\u000a\u000a- list route: every Amazon invoice that HAS a document is rebuilt from iDempiere\u000a  (AP documents of the Amazon vendors, found by vendor flag + name; key =\u000a  POReference; kind from the vendor, credit note from the doctype, period from\u000a  the description). The local store only adds uploads that are not imported yet\u000a  plus parsed details / PDF cache\u000a- document route: without a local copy the ORIGINAL PDF attached to the\u000a  iDempiere document is served (&cInvoiceId=); the page passes the document id\u000a- rows rebuilt from iDempiere are labelled (Quelle \"iDempiere\", PDF \"Anhang\");\u000a  a voided one asks for the PDF to be uploaded again before re-import\u000a- deploy script: amazon-ads.db + data/amazon-ads/ added to the preserve lists\u000a  (must be pasted into the Jenkins job to take effect)\u000a",
        "date" : "2026-09-18 15:14:48 +0200",
        "id" : "bcd4de9387b784591e675d94d2d83cd354b63cb6",
        "msg" : "Amazon invoices: iDempiere is the source of truth for booked invoices, PDFs from the document attachment",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/document.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          },
          {
            "editType" : "edit",
            "file" : "reference/ci/deploy-production.sh"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/accounting/amazon-ads/upload.post.ts",
          "server/utils/amazonAds/invoiceStore.ts",
          "server/api/accounting/amazon-ads/document.get.ts",
          "server/api/accounting/amazon-ads/status.get.ts",
          "server/api/accounting/amazon-ads/import.post.ts",
          "server/api/accounting/amazon-ads/void.post.ts",
          "server/api/accounting/amazon-ads/invoices.get.ts"
        ],
        "commitId" : "bcd159169e2557be05d88bbad7d54b88e7c038cf",
        "timestamp" : 1789741744000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: store uploads in the iDempiere table CUST_AmazonInvoiceInbox (PDF in Strapi)\u000a\u000a- new invoiceStore.ts: one async storage API with two backends — the iDempiere\u000a  table (row via REST, PDF attached in Strapi) and, only as a fallback when the\u000a  table is not reachable, the old SQLite file\u000a- upload / list / import / void / document routes use it; the upload route reads\u000a  the multipart body once and retries with a refreshed token\u000a- rows still in the SQLite file are moved over when the page loads (bounded,\u000a  idempotent, fail-soft; imported rows keep their PDF on the c_invoice document,\u000a  pending rows get their PDF uploaded to Strapi). A run where nothing can be\u000a  written pauses for 10 minutes instead of retrying on every load, and rows that\u000a  are not in the table yet stay visible and importable from the local file\u000a- status/list responses report the active backend\u000a",
        "date" : "2026-09-18 16:29:04 +0200",
        "id" : "bcd159169e2557be05d88bbad7d54b88e7c038cf",
        "msg" : "Amazon invoices: store uploads in the iDempiere table CUST_AmazonInvoiceInbox (PDF in Strapi)",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/void.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/import.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/document.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/amazonAds/invoiceStore.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/status.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/upload.post.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/accounting/amazon-ads/invoices.get.ts"
        ],
        "commitId" : "f5a4b95955cba38382c3ac8c7cc1ffae1e2654e7",
        "timestamp" : 1789742168000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: keep inbox rows consistent with iDempiere's documents (self-heal)\u000a\u000aOn each list load an inbox row whose document exists but is not linked (imported\u000aon another host / before the table existed) gets status 'imported' + the link;\u000aa row that still points to a voided or missing document is released. Bounded,\u000afail-soft, idempotent — the page itself reads the documents and never depends on it.\u000a",
        "date" : "2026-09-18 16:36:08 +0200",
        "id" : "f5a4b95955cba38382c3ac8c7cc1ffae1e2654e7",
        "msg" : "Amazon invoices: keep inbox rows consistent with iDempiere's documents (self-heal)",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/components/accounting/BankLineMatchModal.vue",
          "server/utils/bankReconciliationSuggestions.ts",
          "app/components/accounting/banking/BankReconcilePanel.vue",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "d6003a7b7ccaba8faa27e1d466fff5d221e8dd67",
        "timestamp" : 1789742659000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Bank reconciliation: suggestions need at least 2 matching criteria, fuzzy names, date signal, score ranking\u000a\u000a- a candidate is only suggested when at least 2 of 4 criteria match: document\u000a  number, amount, partner (IBAN or name count as one) and date. On the current\u000a  33 open statements all 47 old invoice suggestions rested on a single signal\u000a- new date signal: statement line date −5 … +60 days around the invoice date\u000a- fuzzy partner names: umlauts spelled out, accents stripped, legal forms and\u000a  filler words ignored, prefix matches, brand word, brand inside run-together\u000a  text or the remittance text (\"AMAZON PAYMENTS EUROPE S.C.A.\" matches \"Amazon EU\u000a  S.à r.l., Niederlassung Deutschland\"; \"Deutsche Bank\" does not match\u000a  \"Deutsche Post\")\u000a- ranking by score, best first (doc no. 50 · amount 30 · IBAN 25 / name 10–25 ·\u000a  date closeness 0–15); up to 8 candidates per line\u000a- match dialog: top 3 + \"weitere anzeigen\", date chip, n/4 criteria, best-match\u000a  marker, top candidate preselected; list pill shows \"+n\" and a criteria tooltip\u000a",
        "date" : "2026-09-18 16:44:19 +0200",
        "id" : "d6003a7b7ccaba8faa27e1d466fff5d221e8dd67",
        "msg" : "Bank reconciliation: suggestions need at least 2 matching criteria, fuzzy names, date signal, score ranking",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          },
          {
            "editType" : "edit",
            "file" : "server/utils/bankReconciliationSuggestions.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/components/accounting/banking/BankReconcilePanel.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/components/accounting/BankLineMatchModal.vue"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/api/accounting/amazon-ads/invoices.get.ts"
        ],
        "commitId" : "6e71fb22714beae7d74a7a44353b11faad234015",
        "timestamp" : 1789743036000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: report the PDF as available when it sits on the iDempiere document\u000a\u000aRows migrated from the local file (and rows rebuilt from documents) carry no file\u000aof their own — their original PDF is the document's attachment. The list flagged\u000athem as \"no PDF\" although the link works; they now show \"Anhang\".\u000a",
        "date" : "2026-09-18 16:50:36 +0200",
        "id" : "6e71fb22714beae7d74a7a44353b11faad234015",
        "msg" : "Amazon invoices: report the PDF as available when it sits on the iDempiere document",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "app/pages/accounting/amazon-ads-invoices/index.vue",
          "server/api/accounting/amazon-ads/import.post.ts",
          "app/assets/langs/shared.js"
        ],
        "commitId" : "87678796cc3032e2763f178f8e4731c10c6ed9b2",
        "timestamp" : 1789744764000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: confirm every import with the cost type shown, no remembered cost types\u000a\u000a12 fee invoices were booked to \"Werbekosten\": the page remembered the last\u000aselection of each cost-type box in the browser and a stale value silently\u000aoverrode the correct default.\u000a\u000a- cost types are no longer stored in the browser (old keys are removed); every\u000a  page load starts from the server defaults (Ads → Werbekosten, fees/credit notes\u000a  → Amazon Gebühren); a deviation is flagged (amber summary, reset to default)\u000a- every import goes through a confirmation dialog that groups the invoices by\u000a  type, shows the cost type each group will be booked to (changeable there, the\u000a  default is marked, a deviation is highlighted) and lists already booked ones as\u000a  skipped. It opens on \"Ausgewählte importieren\" and right after an upload\u000a  (\"jetzt importieren\" / \"Später\")\u000a- the import result names the cost type that was used per invoice\u000a",
        "date" : "2026-09-18 17:19:24 +0200",
        "id" : "87678796cc3032e2763f178f8e4731c10c6ed9b2",
        "msg" : "Amazon invoices: confirm every import with the cost type shown, no remembered cost types",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/import.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/accounting/amazon-ads-invoices/index.vue"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/accounting/amazon-ads/invoices.get.ts"
        ],
        "commitId" : "267e7becbfac41d14dbd209d510b958cf7628124",
        "timestamp" : 1789745316000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: match documents by the full number in the description (POReference is 20 chars)\u000a\u000aThe first credit-memo import showed that POReference cannot carry the key: the\u000acolumn is 20 chars, so 'DE-CN-AEU-2026-134720' (21) is stored as\u000a'DE-CN-AEU-2026-13472' — the new AP CreditMemo was not recognised as the credit\u000anote's document and the self-heal released its inbox row ('voided').\u000a\u000aThe importer's description starts with the FULL Amazon number on every document\u000a(active, voided rename, iDempiere's reversal), so that is the primary match key\u000anow; DocumentNo / POReference remain the fallback for documents not created by\u000athe importer. No double booking was possible — the importer's duplicate guard\u000achecks the full DocumentNo.\u000a",
        "date" : "2026-09-18 17:28:36 +0200",
        "id" : "267e7becbfac41d14dbd209d510b958cf7628124",
        "msg" : "Amazon invoices: match documents by the full number in the description (POReference is 20 chars)",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon-ads/invoices.get.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/utils/amazonAds/importInvoice.ts"
        ],
        "commitId" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
        "timestamp" : 1789745741000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Amazon invoices: book the exact VAT from the PDF when a line-level purchase tax exists\u000a\u000aAmazon rounds the VAT down (74,66 × 19 % → 14,18), iDempiere half-up (14,19); with\u000athe document-level \"19% Mwst.\" the VAT is recomputed at completion, so 3 of 15\u000adocuments ended up one cent above the Amazon total.\u000a\u000aiDempiere keeps a manually entered line TaxAmt on purchase documents whose tax\u000arate is NOT document level. The importer now prefers such a rate (purchase,\u000aIsDocumentLevel = N) and writes the VAT from the PDF on each line (per-line VAT\u000afor fee invoices, proportional for Ads campaigns, remainder on the largest line).\u000aWithout such a rate nothing changes — except that a difference between the booked\u000atotal and the Amazon document is now reported as a warning instead of going unnoticed.\u000a",
        "date" : "2026-09-18 17:35:41 +0200",
        "id" : "cc0ff592b5ae3cc181da2058102242fd926336b5",
        "msg" : "Amazon invoices: book the exact VAT from the PDF when a line-level purchase tax exists",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/utils/amazonAds/importInvoice.ts"
          }
        ]
      }
    ],
    "kind" : "git"
  },
  "culprits" : [
    {
      "absoluteUrl" : "https://jenkins.younex.de/user/info",
      "fullName" : "info"
    }
  ]
}