Automatisches Senden des täglichen Square-Verkaufs-Zusammenfassungsberichts per Microsoft Outlook

Fortgeschritten

Dies ist ein CRM-Bereich Automatisierungsworkflow mit 15 Nodes. Hauptsächlich werden If, Code, SplitOut, HttpRequest, ConvertToFile und andere Nodes verwendet. Automatisches Senden des täglichen Square-Verkaufs-Zusammenfassungsberichts per Microsoft Outlook

Voraussetzungen
  • Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
  "meta": {
    "instanceId": "d6e2f2f655b1125bbcac14a4cac6d2e46c7a150e927f85fc96fdca1a6dc39e0e",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "c68fc3de-a2b2-49b5-8e83-958a959a6948",
      "name": "Square-Standorte abrufen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1040,
        544
      ],
      "parameters": {
        "url": "https://connect.squareup.com/v2/locations",
        "options": {},
        "sendHeaders": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "n1GRrdbh899dbLYB",
          "name": "Square Header Auth"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a0db025a-e0a2-43cc-bf27-3931e272d2f7",
      "name": "Standorte in Liste umwandeln",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1264,
        544
      ],
      "parameters": {
        "include": "selectedOtherFields",
        "options": {},
        "fieldToSplitOut": "locations",
        "fieldsToInclude": "id"
      },
      "typeVersion": 1
    },
    {
      "id": "74cb6901-8f88-4ecd-b099-098b71a467b1",
      "name": "Standorte ohne Verkäufe ignorieren",
      "type": "n8n-nodes-base.if",
      "position": [
        1760,
        544
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "498f5fab-6930-4e89-9fbe-0d67671da8d2",
              "operator": {
                "type": "array",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.orders }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2b585476-811b-49fe-add8-e5c99c46c5b9",
      "name": "Verkäufe von Square abrufen",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1520,
        544
      ],
      "parameters": {
        "url": "https://connect.squareup.com/v2/orders/search",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"location_ids\": [\"{{ $json.locations.id }}\"],\n  \"query\": {\n    \"filter\": {\n      \"state_filter\": {\n        \"states\": [\"COMPLETED\"]\n      },\n      \"date_time_filter\": {\n        \"created_at\": {\n          \"start_at\": \"{{ $('Schedule Trigger').item.json.timestamp.toDateTime().minus(1, 'days').format('yyyy-MM-dd') }}T00:00:00-05:00\",\n          \"end_at\": \"{{ $('Schedule Trigger').item.json.timestamp.toDateTime().minus(1, 'days').format('yyyy-MM-dd') }}T23:59:59-05:00\"\n        }\n      }\n    }\n  },\n  \"limit\": 1000,\n  \"return_entries\": false\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "n1GRrdbh899dbLYB",
          "name": "Square Header Auth"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "ca230503-4d53-421e-a0aa-7529b6f5c33b",
      "name": "Verkaufsberichte zusammenstellen",
      "type": "n8n-nodes-base.code",
      "position": [
        2048,
        544
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Date and Location Metadata\nconst date = $('Schedule Trigger').item.json.timestamp.split('T')[0];\nconst location_id = $json.orders[0].location_id || null;\nconst location_name = $('Get Square Locations').item.json.locations.find(locations => locations.id === location_id)?.name;\n\n// Our Result Variables\nlet total_money = 0;\nlet total_tax = 0;\nlet total_discount = 0;\nlet total_tip = 0;\nlet total_returns = 0;\nlet cash_rounding = 0;\n\nlet cash_tender = 0;\nlet card_tender = 0;\nlet gift_card_tender = 0;\nlet other_tender = 0;\nlet fees = 0;\n\n// Loop Through Each Order\nfor (const sale of $json.orders) {\n\n    // Add the sales, taxes, discounts and tips\n    total_money += sale.total_money?.amount || 0;\n    total_tax += sale.total_tax_money?.amount || 0;\n    total_discount += -(sale.total_discount_money?.amount || 0);\n    total_tip += sale.total_tip_money?.amount || 0;\n    if (sale.rounding_adjustment) {\n      cash_rounding += sale.rounding_adjustment.amount_money?.amount || 0;\n    }\n\n  \n    if (sale.return_amounts) {\n      // If there are returns, subtract from sales totals and add to return amount total\n      total_money -= sale.return_amounts?.total_money?.amount || 0;\n      total_tax -= sale.return_amounts?.tax_money?.amount || 0;\n      total_discount -= sale.return_amounts?.discount_money?.amount || 0;\n      total_tip -= sale.return_amounts?.tip_money?.amount || 0;\n  \n      total_returns += -(sale.return_amounts?.total_money?.amount || 0);\n      total_returns -= -(sale.return_amounts?.tax_money?.amount || 0);\n      total_returns -= -(sale.return_amounts?.tip_money?.amount || 0);\n      total_returns -= -(sale.return_amounts?.discount_money?.amount || 0);\n  \n      // If an array of refunds is provided\n      for (const refund of sale.refunds || []) {\n        const transaction_id = refund.transaction_id;\n      \n        // Look for the original sale this refund refers to\n        const original_sale = $json.orders.find(original =>\n          original.id && transaction_id && original.id.includes(transaction_id)\n        );\n      \n        if (original_sale) {\n          if (original_sale.rounding_adjustment) {\n            const amount = original_sale.rounding_adjustment.amount_money?.amount || 0;\n            cash_rounding -= amount;\n            total_returns += amount;\n          }\n      \n          if (original_sale.tenders) {\n            for (const tender of original_sale.tenders) {\n              if (tender.id === refund.tender_id) {\n                const amount = refund.amount_money?.amount || 0;\n                if (tender.type === 'CARD') card_tender -= amount;\n                else if (tender.type === 'CASH') cash_tender -= amount;\n                else if (tender.type === 'SQUARE_GIFT_CARD') gift_card_tender -= amount;\n                else other_tender -= amount;\n      \n                if (refund.processing_fee_money && tender.id === refund.tender_id) {\n                  fees -= refund.processing_fee_money.amount || 0;\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  \n    if (sale.tenders) {\n      for (const tender of sale.tenders) {\n        const amount = tender.amount_money?.amount || 0;\n        if (tender.type === 'CARD') card_tender += amount;\n        else if (tender.type === 'CASH') cash_tender += amount;\n        else if (tender.type === 'SQUARE_GIFT_CARD') gift_card_tender += amount;\n        else other_tender += amount;\n  \n        if (tender.processing_fee_money) {\n          fees -= tender.processing_fee_money.amount || 0;\n        }\n      }\n    }\n  \n}\n\n// Final computed values\nconst net_sales = total_money - total_tip - total_tax - cash_rounding;\nconst gross_sales = net_sales - total_discount - total_returns;\nconst net_total = cash_tender + card_tender + gift_card_tender + other_tender + fees;\n\nreturn {\n  json: {\n    date,\n    location_id,\n    location_name,\n    gross_sales: gross_sales / 100.0,\n    total_returns: total_returns / 100.0,\n    total_discount: total_discount / 100.0,\n    net_sales: net_sales / 100.0,\n    total_tax: total_tax / 100.0,\n    total_tip: total_tip / 100.0,\n    cash_rounding: cash_rounding / 100.0,\n    total_payments_collected: total_money / 100.0,\n    cash: cash_tender / 100.0,\n    card: card_tender / 100.0,\n    gift_card: gift_card_tender / 100.0,\n    other: other_tender / 100.0,\n    fees: fees / 100.0,\n    net_total: net_total / 100.0,\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "5f149d75-0a97-497c-8def-1d578a8d9fb3",
      "name": "Notiz",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        0
      ],
      "parameters": {
        "width": 660,
        "height": 1440,
        "content": "## Automatically Send Square Summary Report for Yesterday's Sales via Microsoft Outlook\n\n## What It Does  \nThis workflow automatically connects to the Square API and generates a daily sales summary report for all your Square locations. The report matches the figures displayed in **Square Dashboard > Reports > Sales Summary**.\n\nIt's designed to run daily and pull the previous day's sales into a CSV file, which is then sent to a manager/finance team for analysis.\n\nThis workflow builds on my previous template, which allows users to automatically pull data from the Square API into n8n for processing. (See here: https://n8n.io/workflows/6358)\n\n## Prerequisites  \nTo use this workflow, you'll need:\n- A Square API credential (configured as a Header Auth credential)\n- A Microsoft Outlook credential\n\n## How to Set Up Square Credentials:  \n- Go to **Credentials > Create New**  \n- Choose **Header Auth**  \n- Set the **Name** to `Authorization`  \n- Set the **Value** to your Square Access Token (e.g., `Bearer <your-api-key>`)\n\n## How It Works  \n1. **Trigger:** The workflow runs every day at 4:00 AM  \n2. **Fetch Locations:** An HTTP request retrieves all Square locations linked to your account  \n3. **Fetch Orders:** For each location, an HTTP request pulls completed orders for the specified report_date  \n4. **Filter Empty Locations:** Locations with no sales are ignored  \n5. **Aggregate Sales Data:** A Code node processes the order data and produces a summary identical to Square’s built-in Sales Summary report  \n6. **Create CSV File:** A CSV file is created containing the relevant data  \n7. **Send Email:** An email is sent to the chosen third party  \n\n## Example Use Cases  \n- Automatically send Square sales data to management to improve the quality of planning and scheduling decisions  \n- Automatically send data to an external third party, such as a landlord or agent, who is paid via commission  \n- Automatically send data to a bookkeeper for entry into QuickBooks  \n\n## How to Use  \n- Configure both HTTP Request nodes to use your Square API credential  \n- Set the workflow to **Active** so it runs automatically  \n- Enter the email address of the person you want to send the report to and update the message body  \n- If you want to remove the n8n attribution, you can do so in the last node  \n\n## Customization Options  \n- Add pagination to handle locations with more than 1,000 orders per day\n- Instead of a daily summary, you can modify this workflow to produce a weekly summary once a week  \n\n## Why It's Useful  \nThis workflow saves time, reduces manual report pulling from Square, and enables smarter automation around sales data — whether for operations, finance, or performance monitoring.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9372abca-8e5e-4852-8aa1-be7c811b1317",
      "name": "Notiz1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        352
      ],
      "parameters": {
        "color": 5,
        "height": 420,
        "content": "## Trigger  \n- This workflow runs every day at 8:00 AM.  \n- Each day, it pulls the previous day's sales data from Square.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7c501a7c-e000-4949-b408-cb76716752cf",
      "name": "Notiz2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        960,
        352
      ],
      "parameters": {
        "color": 5,
        "width": 460,
        "height": 420,
        "content": "## Get Square Locations and Process Each One Separately  \n- This HTTP node connects to the Square Locations API to fetch all your locations.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e4071c89-b71b-41d1-9c0d-a5d03bdf7aab",
      "name": "Notiz3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        352
      ],
      "parameters": {
        "color": 5,
        "height": 420,
        "content": "## Get Sales from Square  \n- This HTTP node retrieves all orders for the given location on the specified date."
      },
      "typeVersion": 1
    },
    {
      "id": "82226c69-8d34-4ee2-b781-8840c2371984",
      "name": "Notiz4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1984,
        352
      ],
      "parameters": {
        "color": 5,
        "height": 420,
        "content": "## Compile a Report for Each Location  \n- This code node calculates totals for each location.  \n- Please ensure the numbers match EXACTLY with the Square Sales Summary Dashboard.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "40878fe8-40f8-4076-880d-f59e7a895bed",
      "name": "Zeitplan-Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        784,
        544
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "8756248b-7a1d-48d0-a237-9b888520114a",
      "name": "Notiz5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2240,
        352
      ],
      "parameters": {
        "color": 5,
        "height": 420,
        "content": "## Convert the Square Sales Summary into a CSV File \n"
      },
      "typeVersion": 1
    },
    {
      "id": "7c78db77-adb2-4331-b11b-d50519ec894e",
      "name": "Verkaufszusammenfassung in CSV-Datei konvertieren",
      "type": "n8n-nodes-base.convertToFile",
      "position": [
        2320,
        544
      ],
      "parameters": {
        "options": {
          "fileName": "=sales_report_{{ $('Schedule Trigger').item.json.timestamp }}.csv"
        },
        "binaryPropertyName": "sales_report"
      },
      "typeVersion": 1.1
    },
    {
      "id": "0cf921ca-0140-4ba5-bb96-88a2ebccac3c",
      "name": "Notiz6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2512,
        352
      ],
      "parameters": {
        "color": 5,
        "height": 420,
        "content": "## Send the Report to the Finance Team / Manager"
      },
      "typeVersion": 1
    },
    {
      "id": "509dee6d-39af-45a5-b2c8-d72a47c960bb",
      "name": "Bericht senden",
      "type": "n8n-nodes-base.microsoftOutlook",
      "position": [
        2576,
        544
      ],
      "webhookId": "d3b5fd42-a7ac-4b58-a810-5a91528a5ddb",
      "parameters": {
        "subject": "=Your Square Sales Report for {{ $('Schedule Trigger').item.json['Readable date'].split(',')[0] }}",
        "bodyContent": "<p>Hello User,</p>|<p>Please see the attached report containing yesterday's sales!</p><p>Best,<br> An Efficient Person</p>",
        "toRecipients": "user@example.com",
        "additionalFields": {
          "bodyContentType": "html"
        }
      },
      "typeVersion": 2
    }
  ],
  "pinData": {},
  "connections": {
    "40878fe8-40f8-4076-880d-f59e7a895bed": {
      "main": [
        [
          {
            "node": "c68fc3de-a2b2-49b5-8e83-958a959a6948",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c68fc3de-a2b2-49b5-8e83-958a959a6948": {
      "main": [
        [
          {
            "node": "a0db025a-e0a2-43cc-bf27-3931e272d2f7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ca230503-4d53-421e-a0aa-7529b6f5c33b": {
      "main": [
        [
          {
            "node": "7c78db77-adb2-4331-b11b-d50519ec894e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2b585476-811b-49fe-add8-e5c99c46c5b9": {
      "main": [
        [
          {
            "node": "74cb6901-8f88-4ecd-b099-098b71a467b1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a0db025a-e0a2-43cc-bf27-3931e272d2f7": {
      "main": [
        [
          {
            "node": "2b585476-811b-49fe-add8-e5c99c46c5b9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "74cb6901-8f88-4ecd-b099-098b71a467b1": {
      "main": [
        [
          {
            "node": "ca230503-4d53-421e-a0aa-7529b6f5c33b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7c78db77-adb2-4331-b11b-d50519ec894e": {
      "main": [
        [
          {
            "node": "509dee6d-39af-45a5-b2c8-d72a47c960bb",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Häufig gestellte Fragen

Wie verwende ich diesen Workflow?

Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.

Für welche Szenarien ist dieser Workflow geeignet?

Fortgeschritten - Kundenbeziehungsmanagement

Ist es kostenpflichtig?

Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.

Workflow-Informationen
Schwierigkeitsgrad
Fortgeschritten
Anzahl der Nodes15
Kategorie1
Node-Typen8
Schwierigkeitsbeschreibung

Für erfahrene Benutzer, mittelkomplexe Workflows mit 6-15 Nodes

Externe Links
Auf n8n.io ansehen

Diesen Workflow teilen

Kategorien

Kategorien: 34