{
  "_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" : 789,
          "buildResult" : None,
          "marked" : {
            "SHA1" : "9c167356f4e9867112526be82c45d0877188ded6",
            "branch" : [
              {
                "SHA1" : "9c167356f4e9867112526be82c45d0877188ded6",
                "name" : "refs/remotes/origin/dev"
              }
            ]
          },
          "revision" : {
            "SHA1" : "9c167356f4e9867112526be82c45d0877188ded6",
            "branch" : [
              {
                "SHA1" : "9c167356f4e9867112526be82c45d0877188ded6",
                "name" : "refs/remotes/origin/dev"
              }
            ]
          }
        }
      },
      "lastBuiltRevision" : {
        "SHA1" : "9c167356f4e9867112526be82c45d0877188ded6",
        "branch" : [
          {
            "SHA1" : "9c167356f4e9867112526be82c45d0877188ded6",
            "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" : "#789",
  "duration" : 67321,
  "estimatedDuration" : 66220,
  "executor" : None,
  "fullDisplayName" : "build-logship-frontend #789",
  "id" : "789",
  "inProgress" : False,
  "keepLog" : False,
  "number" : 789,
  "queueId" : 5976,
  "result" : "SUCCESS",
  "timestamp" : 1793840400164,
  "url" : "https://jenkins.younex.de/view/all/job/build-logship-frontend/789/",
  "builtOn" : "",
  "changeSet" : {
    "_class" : "hudson.plugins.git.GitChangeSetList",
    "items" : [
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/invoices/lexoffice-queue/[id].get.ts",
          "server/api/invoices/lexoffice-queue/[id]/action.post.ts",
          "server/utils/lexofficeInvoiceUpload.ts",
          "app/pages/sales/invoices/index.vue",
          ".claude/rules/accounting/lexoffice.md",
          "app/components/sales/LexofficeUploadQueuePill.vue",
          "server/api/invoices/lexoffice-queue/index.get.ts",
          "server/plugins/lexoffice-upload-queue.ts",
          "app/composables/useLexofficeUploadQueue.ts",
          "server/api/invoices/lexoffice-queue/index.post.ts",
          "server/api/invoices/lexoffice-upload.post.ts",
          "server/utils/lexofficeUploadQueue.ts",
          "server/utils/lexofficeClient.ts",
          "app/assets/langs/shared.js",
          "app/components/sales/LexofficeUploadQueueModal.vue"
        ],
        "commitId" : "e3e3489ed35d4ed072f1bf68e02ce589587298dd",
        "timestamp" : 1793818080000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Lexoffice: bulk invoice upload as a persistent server-side job queue\u000a\u000aThe browser-driven loop (70 sequential requests, no error handling) aborted the whole run on one\u000afailed request, an expired session or a closed tab, and left no record of what had been uploaded.\u000aBulk uploads now create a job in a local SQLite queue (data/lexoffice-uploads.db) that a Nitro\u000aworker (PM2 instance 0) processes 3 invoices at a time; the run survives tab close, navigation,\u000asession expiry and process restarts.\u000a\u000a- server/utils/lexofficeInvoiceUpload.ts: per-invoice core shared by the sync route and the queue;\u000a  never throws, persists voucher id / file id as soon as they exist so a retry attaches to the same\u000a  voucher or only writes the marker; no plain file drop after a voucher exists (made duplicates);\u000a  marker write retried 3x, \"uploaded but not marked\" is repaired without re-upload.\u000a- server/utils/lexofficeUploadQueue.ts + server/api/invoices/lexoffice-queue/*: job + item tables,\u000a  claim via UPDATE ... RETURNING, transient errors (429/5xx/timeout/network) re-queued with backoff\u000a  up to 4 attempts, permanent ones listed as failed with retry on demand; pause / resume / cancel /\u000a  retry-failed; session token first, service token on 401, otherwise job paused (auth); crash\u000a  recovery on boot, old jobs purged after 30 days.\u000a- server/plugins/lexoffice-upload-queue.ts: arms the worker, recovery + periodic kick.\u000a- lexofficeClient: 120 s timeout per call, network errors retried, LexofficeError with status.\u000a- UI: useLexofficeUploadQueue composable, progress modal (bar, rate/ETA, counters, in-flight\u000a  steps, activity, errors tab, per-invoice log, actions) and a header pill that re-attaches to the\u000a  running job after a reload; invoice list bulk upload starts a job and refreshes on finish.\u000a- Translations (en/de/es) and the accounting/lexoffice recipe updated.\u000a",
        "date" : "2026-11-04 19:48:00 +0100",
        "id" : "e3e3489ed35d4ed072f1bf68e02ce589587298dd",
        "msg" : "Lexoffice: bulk invoice upload as a persistent server-side job queue",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "server/utils/lexofficeClient.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/invoices/lexoffice-queue/[id]/action.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/invoices/lexoffice-upload.post.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/lexofficeInvoiceUpload.ts"
          },
          {
            "editType" : "add",
            "file" : "app/components/sales/LexofficeUploadQueuePill.vue"
          },
          {
            "editType" : "edit",
            "file" : "app/assets/langs/shared.js"
          },
          {
            "editType" : "edit",
            "file" : "app/pages/sales/invoices/index.vue"
          },
          {
            "editType" : "add",
            "file" : "server/api/invoices/lexoffice-queue/[id].get.ts"
          },
          {
            "editType" : "edit",
            "file" : ".claude/rules/accounting/lexoffice.md"
          },
          {
            "editType" : "add",
            "file" : "app/composables/useLexofficeUploadQueue.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/invoices/lexoffice-queue/index.get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/lexofficeUploadQueue.ts"
          },
          {
            "editType" : "add",
            "file" : "app/components/sales/LexofficeUploadQueueModal.vue"
          },
          {
            "editType" : "add",
            "file" : "server/plugins/lexoffice-upload-queue.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/invoices/lexoffice-queue/index.post.ts"
          }
        ]
      },
      {
        "_class" : "hudson.plugins.git.GitChangeSet",
        "affectedPaths" : [
          "server/api/accounting/ebay/orders-check.get.ts",
          "server/utils/marketplaceInvoiceGenerate.ts",
          "server/api/accounting/marketplace-recon/bank-accounts.get.ts",
          "server/utils/marketplaceSettlementPayments.ts",
          "server/api/accounting/marketplace-recon/jobs/index.get.ts",
          "server/api/accounting/marketplace-recon/settings.put.ts",
          "server/api/accounting/amazon/orders-check.get.ts",
          "server/api/accounting/marketplace-recon/health.get.ts",
          "server/utils/marketplaceOrdersCheck.ts",
          ".claude/rules/accounting/marketplace-recon.md",
          "server/api/accounting/marketplace-recon/settings.get.ts",
          "server/plugins/marketplace-recon.ts",
          "app/pages/accounting/marketplace-dashboard.vue",
          "server/api/accounting/marketplace-recon/clearing-account.post.ts",
          "app/composables/useMarketplaceRecon.ts",
          "server/api/accounting/marketplace-recon/jobs/index.post.ts",
          "server/api/accounting/marketplace-recon/sources.get.ts",
          "server/utils/marketplaceReconJob.ts",
          "app/composables/menu/admin/accounting.ts",
          "server/api/accounting/marketplace-recon/jobs/[id].get.ts",
          "server/api/accounting/marketplace-recon/jobs/[id]/action.post.ts"
        ],
        "commitId" : "9c167356f4e9867112526be82c45d0877188ded6",
        "timestamp" : 1793825484000,
        "author" : {
          "absoluteUrl" : "https://jenkins.younex.de/user/info",
          "fullName" : "info"
        },
        "authorEmail" : "info@younex.de",
        "comment" : "Marktplatz-Abgleich dashboard: one server job for the Amazon/eBay month-end routine\u000a\u000a- /accounting/marketplace-dashboard: health cards per order source and month (nightly\u000a  background check), run panel with date range + step toggles, step timeline, findings\u000a  grid, run history, clearing-account settings\u000a- job engine server/utils/marketplaceReconJob.ts (SQLite data/marketplace-recon.db,\u000a  worker on PM2 instance 0): check -> import missing -> fix date/amount -> generate\u000a  invoices -> Lexoffice queue -> settlement payments; dry run plans every step\u000a- shared check core marketplaceOrdersCheck.ts used by both orders-check routes\u000a  (rows now carry Lexoffice status, neutral fields + legacy aliases)\u000a- settlement payments: AR Receipt per invoiced order on a per-source clearing bank\u000a  account, dated on the posting day; eBay SALE amounts are net of fees -> gross =\u000a  totalFeeBasisAmount or net + fee rows\u000a- recipe .claude/rules/accounting/marketplace-recon.md\u000a",
        "date" : "2026-11-04 21:51:24 +0100",
        "id" : "9c167356f4e9867112526be82c45d0877188ded6",
        "msg" : "Marktplatz-Abgleich dashboard: one server job for the Amazon/eBay month-end routine",
        "paths" : [
          {
            "editType" : "edit",
            "file" : "app/composables/menu/admin/accounting.ts"
          },
          {
            "editType" : "add",
            "file" : "app/composables/useMarketplaceRecon.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/sources.get.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/ebay/orders-check.get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/settings.get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/jobs/index.get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/marketplaceInvoiceGenerate.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/marketplaceOrdersCheck.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/jobs/[id].get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/settings.put.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/jobs/[id]/action.post.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/clearing-account.post.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/health.get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/plugins/marketplace-recon.ts"
          },
          {
            "editType" : "add",
            "file" : "app/pages/accounting/marketplace-dashboard.vue"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/jobs/index.post.ts"
          },
          {
            "editType" : "edit",
            "file" : "server/api/accounting/amazon/orders-check.get.ts"
          },
          {
            "editType" : "add",
            "file" : "server/utils/marketplaceReconJob.ts"
          },
          {
            "editType" : "add",
            "file" : "server/api/accounting/marketplace-recon/bank-accounts.get.ts"
          },
          {
            "editType" : "add",
            "file" : ".claude/rules/accounting/marketplace-recon.md"
          },
          {
            "editType" : "add",
            "file" : "server/utils/marketplaceSettlementPayments.ts"
          }
        ]
      }
    ],
    "kind" : "git"
  },
  "culprits" : [
    {
      "absoluteUrl" : "https://jenkins.younex.de/user/info",
      "fullName" : "info"
    }
  ]
}