[{"data":1,"prerenderedAt":3020},["ShallowReactive",2],{"doc:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal":3,"surround:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal":2985,"ancestors:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal":2994,"children:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal":2999,"related:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal":3000},{"id":4,"title":5,"body":6,"dateModified":2952,"datePublished":2952,"description":2953,"extension":2954,"faq":2955,"keyword":2964,"kind":2965,"meta":2966,"navigation":101,"path":2975,"seo":2976,"slug":2979,"stem":2980,"topics":2981,"type":2983,"__hash__":2984},"docs\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal\u002Findex.md","Build a Supplier Payment Run Proposal",{"type":7,"value":8,"toc":2941},"minimark",[9,24,29,58,61,65,532,535,539,546,988,995,1192,1196,1199,1526,1529,1638,1642,1645,2524,2548,2830,2834,2869,2873,2876,2880,2886,2892,2898,2904,2908,2937],[10,11,12,13,17,18,23],"p",{},"Paying suppliers is usually done in ",[14,15,16],"em",{},"runs"," — weekly or twice a month — and each run starts with a proposal: which invoices to pay this time, how much in total, and what is being held back and why. Accounts payable assembles it from the open invoice listing, a finance manager reviews and approves it, and only then are the payments released. Done by hand in a spreadsheet it is a filtering exercise with traps: an invoice that falls due two days after this run but before the next one gets paid late; a 2% early-payment discount expires unnoticed; a supplier's credit note is forgotten and they are overpaid; a disputed invoice slips through. This page builds the proposal with pandas from an open-invoices export, applies those rules explicitly, fits the run to the cash available, and writes a workbook that an approver can check quickly. It belongs to ",[19,20,22],"a",{"href":21},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002F","Building Finance and Operations Reports",".",[25,26,28],"h2",{"id":27},"prerequisites","Prerequisites",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl\n","bash","",[37,38,39],"code",{"__ignoreMap":35},[40,41,44,48,52,55],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"sMTad","pip",[40,49,51],{"class":50},"srMev"," install",[40,53,54],{"class":50}," pandas",[40,56,57],{"class":50}," openpyxl\n",[10,59,60],{},"The input is an export of open payables — one row per invoice or credit note with supplier, due date, amount, payment terms and an on-hold flag for disputed items — plus a supplier sheet with bank details. Any purchase ledger can produce something similar. This run is paid on Friday 2 October 2026 and the next run is on Friday 16 October.",[25,62,64],{"id":63},"step-1-load-and-work-out-discount-deadlines","Step 1 — Load and work out discount deadlines",[30,66,70],{"className":67,"code":68,"language":69,"meta":35,"style":35},"language-python shiki shiki-themes github-light github-dark-high-contrast","import re\nimport pandas as pd\n\nap = pd.read_excel(\"ap_open_items.xlsx\", sheet_name=\"Open items\")\nsuppliers = pd.read_excel(\"ap_open_items.xlsx\", sheet_name=\"Suppliers\")\nPAY_DATE, NEXT_RUN = pd.Timestamp(\"2026-10-02\"), pd.Timestamp(\"2026-10-16\")\n\ndef discount_terms(terms):\n    m = re.match(r\"(\\d+(?:\\.\\d+)?)\u002F(\\d+) net \\d+\", str(terms))\n    return (float(m.group(1)) \u002F 100, int(m.group(2))) if m else (0.0, None)\n\nterms = ap[\"Terms\"].map(discount_terms)\nap[\"Disc %\"] = [t[0] for t in terms]\nap[\"Disc deadline\"] = [d + pd.Timedelta(days=t[1]) if t[1] else pd.NaT for d, t in zip(ap[\"Invoice date\"], terms)]\nap = ap.merge(suppliers, on=\"Supplier\", how=\"left\")\nprint(ap[[\"Supplier\", \"Document\", \"Due date\", \"Amount\", \"Terms\", \"Disc deadline\"]].to_string(index=False))\n","python",[37,71,72,82,96,103,133,156,185,190,203,272,332,337,354,388,454,484],{"__ignoreMap":35},[40,73,74,78],{"class":42,"line":43},[40,75,77],{"class":76},"s-kum","import",[40,79,81],{"class":80},"skGVy"," re\n",[40,83,85,87,90,93],{"class":42,"line":84},2,[40,86,77],{"class":76},[40,88,89],{"class":80}," pandas ",[40,91,92],{"class":76},"as",[40,94,95],{"class":80}," pd\n",[40,97,99],{"class":42,"line":98},3,[40,100,102],{"emptyLinePlaceholder":101},true,"\n",[40,104,106,109,112,115,118,121,125,127,130],{"class":42,"line":105},4,[40,107,108],{"class":80},"ap ",[40,110,111],{"class":76},"=",[40,113,114],{"class":80}," pd.read_excel(",[40,116,117],{"class":50},"\"ap_open_items.xlsx\"",[40,119,120],{"class":80},", ",[40,122,124],{"class":123},"sa561","sheet_name",[40,126,111],{"class":76},[40,128,129],{"class":50},"\"Open items\"",[40,131,132],{"class":80},")\n",[40,134,136,139,141,143,145,147,149,151,154],{"class":42,"line":135},5,[40,137,138],{"class":80},"suppliers ",[40,140,111],{"class":76},[40,142,114],{"class":80},[40,144,117],{"class":50},[40,146,120],{"class":80},[40,148,124],{"class":123},[40,150,111],{"class":76},[40,152,153],{"class":50},"\"Suppliers\"",[40,155,132],{"class":80},[40,157,159,163,165,168,171,174,177,180,183],{"class":42,"line":158},6,[40,160,162],{"class":161},"sP0c6","PAY_DATE",[40,164,120],{"class":80},[40,166,167],{"class":161},"NEXT_RUN",[40,169,170],{"class":76}," =",[40,172,173],{"class":80}," pd.Timestamp(",[40,175,176],{"class":50},"\"2026-10-02\"",[40,178,179],{"class":80},"), pd.Timestamp(",[40,181,182],{"class":50},"\"2026-10-16\"",[40,184,132],{"class":80},[40,186,188],{"class":42,"line":187},7,[40,189,102],{"emptyLinePlaceholder":101},[40,191,193,196,200],{"class":42,"line":192},8,[40,194,195],{"class":76},"def",[40,197,199],{"class":198},"s_Opv"," discount_terms",[40,201,202],{"class":80},"(terms):\n",[40,204,206,209,211,214,217,220,223,226,229,233,236,238,241,244,246,249,251,253,255,258,260,262,264,266,269],{"class":42,"line":205},9,[40,207,208],{"class":80},"    m ",[40,210,111],{"class":76},[40,212,213],{"class":80}," re.match(",[40,215,216],{"class":76},"r",[40,218,219],{"class":50},"\"",[40,221,222],{"class":161},"(\\d",[40,224,225],{"class":76},"+",[40,227,228],{"class":161},"(?:",[40,230,232],{"class":231},"s_b0D","\\.",[40,234,235],{"class":161},"\\d",[40,237,225],{"class":76},[40,239,240],{"class":161},")",[40,242,243],{"class":76},"?",[40,245,240],{"class":161},[40,247,248],{"class":50},"\u002F",[40,250,222],{"class":161},[40,252,225],{"class":76},[40,254,240],{"class":161},[40,256,257],{"class":50}," net ",[40,259,235],{"class":161},[40,261,225],{"class":76},[40,263,219],{"class":50},[40,265,120],{"class":80},[40,267,268],{"class":161},"str",[40,270,271],{"class":80},"(terms))\n",[40,273,275,278,281,284,287,290,293,295,298,300,303,305,308,311,314,317,320,322,325,327,330],{"class":42,"line":274},10,[40,276,277],{"class":76},"    return",[40,279,280],{"class":80}," (",[40,282,283],{"class":161},"float",[40,285,286],{"class":80},"(m.group(",[40,288,289],{"class":161},"1",[40,291,292],{"class":80},")) ",[40,294,248],{"class":76},[40,296,297],{"class":161}," 100",[40,299,120],{"class":80},[40,301,302],{"class":161},"int",[40,304,286],{"class":80},[40,306,307],{"class":161},"2",[40,309,310],{"class":80},"))) ",[40,312,313],{"class":76},"if",[40,315,316],{"class":80}," m ",[40,318,319],{"class":76},"else",[40,321,280],{"class":80},[40,323,324],{"class":161},"0.0",[40,326,120],{"class":80},[40,328,329],{"class":161},"None",[40,331,132],{"class":80},[40,333,335],{"class":42,"line":334},11,[40,336,102],{"emptyLinePlaceholder":101},[40,338,340,343,345,348,351],{"class":42,"line":339},12,[40,341,342],{"class":80},"terms ",[40,344,111],{"class":76},[40,346,347],{"class":80}," ap[",[40,349,350],{"class":50},"\"Terms\"",[40,352,353],{"class":80},"].map(discount_terms)\n",[40,355,357,360,363,366,368,371,374,376,379,382,385],{"class":42,"line":356},13,[40,358,359],{"class":80},"ap[",[40,361,362],{"class":50},"\"Disc %\"",[40,364,365],{"class":80},"] ",[40,367,111],{"class":76},[40,369,370],{"class":80}," [t[",[40,372,373],{"class":161},"0",[40,375,365],{"class":80},[40,377,378],{"class":76},"for",[40,380,381],{"class":80}," t ",[40,383,384],{"class":76},"in",[40,386,387],{"class":80}," terms]\n",[40,389,391,393,396,398,400,403,405,408,411,413,416,418,421,423,426,428,430,432,435,437,440,442,445,448,451],{"class":42,"line":390},14,[40,392,359],{"class":80},[40,394,395],{"class":50},"\"Disc deadline\"",[40,397,365],{"class":80},[40,399,111],{"class":76},[40,401,402],{"class":80}," [d ",[40,404,225],{"class":76},[40,406,407],{"class":80}," pd.Timedelta(",[40,409,410],{"class":123},"days",[40,412,111],{"class":76},[40,414,415],{"class":80},"t[",[40,417,289],{"class":161},[40,419,420],{"class":80},"]) ",[40,422,313],{"class":76},[40,424,425],{"class":80}," t[",[40,427,289],{"class":161},[40,429,365],{"class":80},[40,431,319],{"class":76},[40,433,434],{"class":80}," pd.NaT ",[40,436,378],{"class":76},[40,438,439],{"class":80}," d, t ",[40,441,384],{"class":76},[40,443,444],{"class":161}," zip",[40,446,447],{"class":80},"(ap[",[40,449,450],{"class":50},"\"Invoice date\"",[40,452,453],{"class":80},"], terms)]\n",[40,455,457,459,461,464,467,469,472,474,477,479,482],{"class":42,"line":456},15,[40,458,108],{"class":80},[40,460,111],{"class":76},[40,462,463],{"class":80}," ap.merge(suppliers, ",[40,465,466],{"class":123},"on",[40,468,111],{"class":76},[40,470,471],{"class":50},"\"Supplier\"",[40,473,120],{"class":80},[40,475,476],{"class":123},"how",[40,478,111],{"class":76},[40,480,481],{"class":50},"\"left\"",[40,483,132],{"class":80},[40,485,487,490,493,495,497,500,502,505,507,510,512,514,516,518,521,524,526,529],{"class":42,"line":486},16,[40,488,489],{"class":161},"print",[40,491,492],{"class":80},"(ap[[",[40,494,471],{"class":50},[40,496,120],{"class":80},[40,498,499],{"class":50},"\"Document\"",[40,501,120],{"class":80},[40,503,504],{"class":50},"\"Due date\"",[40,506,120],{"class":80},[40,508,509],{"class":50},"\"Amount\"",[40,511,120],{"class":80},[40,513,350],{"class":50},[40,515,120],{"class":80},[40,517,395],{"class":50},[40,519,520],{"class":80},"]].to_string(",[40,522,523],{"class":123},"index",[40,525,111],{"class":76},[40,527,528],{"class":161},"False",[40,530,531],{"class":80},"))\n",[10,533,534],{},"Terms like \"2\u002F10 net 30\" mean 2% off if paid within 10 days of the invoice date, otherwise the full amount within 30. The deadline is computed per invoice from its date, which is the number that matters for this run. Joining the supplier sheet brings in bank details, so a missing IBAN can be caught before anything is proposed.",[25,536,538],{"id":537},"step-2-decide-what-goes-in-this-run","Step 2 — Decide what goes in this run",[10,540,541,542,545],{},"Each line gets a decision and a reason. An invoice is paid now if it falls due before the ",[14,543,544],{},"next"," run — waiting would make it late — or if paying now earns a discount that would be lost by waiting:",[30,547,549],{"className":67,"code":548,"language":69,"meta":35,"style":35},"def decide(row):\n    if row[\"On hold\"]:\n        return \"exclude\", \"on hold (disputed)\"\n    if pd.isna(row[\"IBAN\"]):\n        return \"exclude\", \"no bank details on file\"\n    if row[\"Amount\"] \u003C 0:\n        return \"pay\", \"credit note — offset against invoices\"\n    if pd.notna(row[\"Disc deadline\"]) and PAY_DATE \u003C= row[\"Disc deadline\"] \u003C NEXT_RUN:\n        return \"pay\", f\"take {row['Disc %']:.0%} discount (expires {row['Disc deadline']:%d %b})\"\n    if row[\"Due date\"] \u003C NEXT_RUN:\n        return \"pay\", \"overdue\" if row[\"Due date\"] \u003C PAY_DATE else \"due before next run\"\n    return \"defer\", f\"due {row['Due date']:%d %b}, after next run\"\n\nap[[\"Decision\", \"Reason\"]] = ap.apply(decide, axis=1, result_type=\"expand\")\nap[\"Discount\"] = (ap[\"Amount\"] * ap[\"Disc %\"]).where(ap[\"Reason\"].str.startswith(\"take\"), 0.0).round(2)\nap[\"To pay\"] = (ap[\"Amount\"] - ap[\"Discount\"]).where(ap[\"Decision\"] == \"pay\", 0.0)\nprint(ap[[\"Supplier\", \"Document\", \"Decision\", \"Reason\", \"To pay\"]].to_string(index=False))\n",[37,550,551,561,575,588,601,612,631,643,676,738,754,784,820,824,864,912,953],{"__ignoreMap":35},[40,552,553,555,558],{"class":42,"line":43},[40,554,195],{"class":76},[40,556,557],{"class":198}," decide",[40,559,560],{"class":80},"(row):\n",[40,562,563,566,569,572],{"class":42,"line":84},[40,564,565],{"class":76},"    if",[40,567,568],{"class":80}," row[",[40,570,571],{"class":50},"\"On hold\"",[40,573,574],{"class":80},"]:\n",[40,576,577,580,583,585],{"class":42,"line":98},[40,578,579],{"class":76},"        return",[40,581,582],{"class":50}," \"exclude\"",[40,584,120],{"class":80},[40,586,587],{"class":50},"\"on hold (disputed)\"\n",[40,589,590,592,595,598],{"class":42,"line":105},[40,591,565],{"class":76},[40,593,594],{"class":80}," pd.isna(row[",[40,596,597],{"class":50},"\"IBAN\"",[40,599,600],{"class":80},"]):\n",[40,602,603,605,607,609],{"class":42,"line":135},[40,604,579],{"class":76},[40,606,582],{"class":50},[40,608,120],{"class":80},[40,610,611],{"class":50},"\"no bank details on file\"\n",[40,613,614,616,618,620,622,625,628],{"class":42,"line":158},[40,615,565],{"class":76},[40,617,568],{"class":80},[40,619,509],{"class":50},[40,621,365],{"class":80},[40,623,624],{"class":76},"\u003C",[40,626,627],{"class":161}," 0",[40,629,630],{"class":80},":\n",[40,632,633,635,638,640],{"class":42,"line":187},[40,634,579],{"class":76},[40,636,637],{"class":50}," \"pay\"",[40,639,120],{"class":80},[40,641,642],{"class":50},"\"credit note — offset against invoices\"\n",[40,644,645,647,650,652,654,657,660,663,665,667,669,671,674],{"class":42,"line":192},[40,646,565],{"class":76},[40,648,649],{"class":80}," pd.notna(row[",[40,651,395],{"class":50},[40,653,420],{"class":80},[40,655,656],{"class":76},"and",[40,658,659],{"class":161}," PAY_DATE",[40,661,662],{"class":76}," \u003C=",[40,664,568],{"class":80},[40,666,395],{"class":50},[40,668,365],{"class":80},[40,670,624],{"class":76},[40,672,673],{"class":161}," NEXT_RUN",[40,675,630],{"class":80},[40,677,678,680,682,684,687,690,694,697,700,703,706,709,712,714,716,719,722,725,728,730,733,735],{"class":42,"line":205},[40,679,579],{"class":76},[40,681,637],{"class":50},[40,683,120],{"class":80},[40,685,686],{"class":76},"f",[40,688,689],{"class":50},"\"take ",[40,691,693],{"class":692},"sSjpA","{",[40,695,696],{"class":80},"row[",[40,698,699],{"class":50},"'Disc %'",[40,701,702],{"class":80},"]",[40,704,705],{"class":76},":.0%",[40,707,708],{"class":692},"}",[40,710,711],{"class":50}," discount (expires ",[40,713,693],{"class":692},[40,715,696],{"class":80},[40,717,718],{"class":50},"'Disc deadline'",[40,720,721],{"class":80},"]:",[40,723,724],{"class":76},"%",[40,726,727],{"class":80},"d ",[40,729,724],{"class":76},[40,731,732],{"class":80},"b",[40,734,708],{"class":692},[40,736,737],{"class":50},")\"\n",[40,739,740,742,744,746,748,750,752],{"class":42,"line":274},[40,741,565],{"class":76},[40,743,568],{"class":80},[40,745,504],{"class":50},[40,747,365],{"class":80},[40,749,624],{"class":76},[40,751,673],{"class":161},[40,753,630],{"class":80},[40,755,756,758,760,762,765,768,770,772,774,776,778,781],{"class":42,"line":334},[40,757,579],{"class":76},[40,759,637],{"class":50},[40,761,120],{"class":80},[40,763,764],{"class":50},"\"overdue\"",[40,766,767],{"class":76}," if",[40,769,568],{"class":80},[40,771,504],{"class":50},[40,773,365],{"class":80},[40,775,624],{"class":76},[40,777,659],{"class":161},[40,779,780],{"class":76}," else",[40,782,783],{"class":50}," \"due before next run\"\n",[40,785,786,788,791,793,795,798,800,802,805,807,809,811,813,815,817],{"class":42,"line":339},[40,787,277],{"class":76},[40,789,790],{"class":50}," \"defer\"",[40,792,120],{"class":80},[40,794,686],{"class":76},[40,796,797],{"class":50},"\"due ",[40,799,693],{"class":692},[40,801,696],{"class":80},[40,803,804],{"class":50},"'Due date'",[40,806,721],{"class":80},[40,808,724],{"class":76},[40,810,727],{"class":80},[40,812,724],{"class":76},[40,814,732],{"class":80},[40,816,708],{"class":692},[40,818,819],{"class":50},", after next run\"\n",[40,821,822],{"class":42,"line":356},[40,823,102],{"emptyLinePlaceholder":101},[40,825,826,829,832,834,837,840,842,845,848,850,852,854,857,859,862],{"class":42,"line":390},[40,827,828],{"class":80},"ap[[",[40,830,831],{"class":50},"\"Decision\"",[40,833,120],{"class":80},[40,835,836],{"class":50},"\"Reason\"",[40,838,839],{"class":80},"]] ",[40,841,111],{"class":76},[40,843,844],{"class":80}," ap.apply(decide, ",[40,846,847],{"class":123},"axis",[40,849,111],{"class":76},[40,851,289],{"class":161},[40,853,120],{"class":80},[40,855,856],{"class":123},"result_type",[40,858,111],{"class":76},[40,860,861],{"class":50},"\"expand\"",[40,863,132],{"class":80},[40,865,866,868,871,873,875,878,880,882,885,887,889,892,894,897,900,903,905,908,910],{"class":42,"line":456},[40,867,359],{"class":80},[40,869,870],{"class":50},"\"Discount\"",[40,872,365],{"class":80},[40,874,111],{"class":76},[40,876,877],{"class":80}," (ap[",[40,879,509],{"class":50},[40,881,365],{"class":80},[40,883,884],{"class":76},"*",[40,886,347],{"class":80},[40,888,362],{"class":50},[40,890,891],{"class":80},"]).where(ap[",[40,893,836],{"class":50},[40,895,896],{"class":80},"].str.startswith(",[40,898,899],{"class":50},"\"take\"",[40,901,902],{"class":80},"), ",[40,904,324],{"class":161},[40,906,907],{"class":80},").round(",[40,909,307],{"class":161},[40,911,132],{"class":80},[40,913,914,916,919,921,923,925,927,929,932,934,936,938,940,942,945,947,949,951],{"class":42,"line":486},[40,915,359],{"class":80},[40,917,918],{"class":50},"\"To pay\"",[40,920,365],{"class":80},[40,922,111],{"class":76},[40,924,877],{"class":80},[40,926,509],{"class":50},[40,928,365],{"class":80},[40,930,931],{"class":76},"-",[40,933,347],{"class":80},[40,935,870],{"class":50},[40,937,891],{"class":80},[40,939,831],{"class":50},[40,941,365],{"class":80},[40,943,944],{"class":76},"==",[40,946,637],{"class":50},[40,948,120],{"class":80},[40,950,324],{"class":161},[40,952,132],{"class":80},[40,954,956,958,960,962,964,966,968,970,972,974,976,978,980,982,984,986],{"class":42,"line":955},17,[40,957,489],{"class":161},[40,959,492],{"class":80},[40,961,471],{"class":50},[40,963,120],{"class":80},[40,965,499],{"class":50},[40,967,120],{"class":80},[40,969,831],{"class":50},[40,971,120],{"class":80},[40,973,836],{"class":50},[40,975,120],{"class":80},[40,977,918],{"class":50},[40,979,520],{"class":80},[40,981,523],{"class":123},[40,983,111],{"class":76},[40,985,528],{"class":161},[40,987,531],{"class":80},[10,989,990,991,994],{},"Comparing with the ",[14,992,993],{},"next run date"," rather than today is the core of a payment run: an invoice due on 10 October must be paid on 2 October, because by 16 October it would be six days late. The Acme invoice from 28 September is not due until 28 October, yet it is paid now — its 2% discount expires on 8 October, before the next run, and 2% for paying three weeks early is worth more than holding the cash. The Fjord IT invoice, on 1\u002F10 terms, is paid early for the same reason. Disputed invoices and suppliers without bank details are excluded with the reason spelled out, so nobody has to ask why.",[996,997,1005,1006,1005,1010,1005,1014,1005,1021,1005,1031,1005,1042,1005,1048,1005,1052,1005,1056,1005,1059,1005,1064,1005,1073,1005,1078,1005,1086,1005,1093,1005,1098,1005,1103,1005,1106,1005,1109,1005,1113,1005,1116,1005,1121,1005,1128,1005,1132,1005,1135,1005,1138,1005,1141,1005,1145,1005,1148,1005,1151,1005,1157,1005,1159,1005,1162,1005,1164,1005,1167,1005,1171,1005,1174,1005,1178,1005,1185,1005,1189],"svg",{"viewBox":998,"role":999,"ariaLabelledBy":1000,"xmlns":1003,"style":1004},"4 0 752 272","img",[1001,1002],"pr-decide-t","pr-decide-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[1007,1008,1009],"title",{"id":1001},"Does an invoice go into this run?",[1011,1012,1013],"desc",{"id":1002},"Held invoices and suppliers without bank details are excluded. An invoice whose discount expires before the next run is paid now to take the discount. An invoice due before the next run is paid now, and anything due later is deferred to a later run. Credit notes are paid with the supplier's invoices to reduce the payment.",[1015,1016],"rect",{"x":1017,"y":373,"width":1018,"height":1019,"fill":1020},"4","752","272","#ffffff",[1015,1022],{"x":1023,"y":1024,"width":1025,"height":1026,"rx":1027,"fill":1028,"stroke":1029,"style":1030},"240.0","16.0","280.0","75.5","12","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:2px",[1032,1033,1035],"g",{"transform":1034},"translate(368.0,29.0) scale(1.000)",[1036,1037],"path",{"d":1038,"fill":1039,"stroke":1040,"style":1041},"M6 3h9l4 4v14H6z M15 3v4h4","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[1043,1044,1047],"text",{"x":1045,"y":1026,"style":1046},"380.0","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Open invoice",[42,1049],{"x1":1045,"y1":1050,"x2":1045,"y2":1051,"stroke":1029,"style":1030},"91.5","111.5",[42,1053],{"x1":1054,"y1":1051,"x2":1055,"y2":1051,"stroke":1029,"style":1030},"104.0","656.0",[42,1057],{"x1":1054,"y1":1051,"x2":1054,"y2":1058,"stroke":1029,"style":1030},"157.5",[1060,1061],"polygon",{"points":1062,"fill":1063},"104.0,161.5 99.0,152.5 109.0,152.5","#5b5cf0",[1015,1065],{"x":1066,"y":1067,"width":1068,"height":1069,"rx":1070,"fill":1020,"stroke":1071,"style":1072},"53.5","121.5","100.9","21.0","10","var(--line,#cdd5e6)","stroke-width:1.2px",[1043,1074,1077],{"x":1054,"y":1075,"style":1076},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","held \u002F no bank",[1015,1079],{"x":1080,"y":1081,"width":1082,"height":1083,"rx":1027,"fill":1084,"stroke":1085,"style":1030},"20.0","163.5","168.0","93.0","#fdefd8","var(--gold,#b4740a)",[1032,1087,1089],{"transform":1088},"translate(92.0,176.5) scale(1.000)",[1036,1090],{"d":1091,"fill":1039,"stroke":1092,"style":1041},"M6 11h12v9H6z M8.5 11V8a3.5 3.5 0 0 1 7 0v3","var(--gold-ink,#7a4e06)",[1043,1094,1097],{"x":1054,"y":1095,"style":1096},"223.0","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","exclude",[1043,1099,1102],{"x":1054,"y":1100,"style":1101},"242.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","reason recorded",[42,1104],{"x1":1105,"y1":1051,"x2":1105,"y2":1058,"stroke":1029,"style":1030},"288.0",[1060,1107],{"points":1108,"fill":1063},"288.0,161.5 283.0,152.5 293.0,152.5",[1015,1110],{"x":1111,"y":1067,"width":1112,"height":1069,"rx":1070,"fill":1020,"stroke":1071,"style":1072},"190.3","195.4",[1043,1114,1115],{"x":1105,"y":1075,"style":1076},"discount ends before next run",[1015,1117],{"x":1118,"y":1081,"width":1082,"height":1083,"rx":1027,"fill":1119,"stroke":1120,"style":1030},"204.0","#d9f4f1","var(--teal,#0f9488)",[1032,1122,1124],{"transform":1123},"translate(276.0,176.5) scale(1.000)",[1036,1125],{"d":1126,"fill":1039,"stroke":1127,"style":1041},"M13 2L4 14h7l-1 8 9-12h-7z","var(--teal-ink,#0b6157)",[1043,1129,1131],{"x":1105,"y":1095,"style":1130},"font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","pay now",[1043,1133,1134],{"x":1105,"y":1100,"style":1101},"take the discount",[42,1136],{"x1":1137,"y1":1051,"x2":1137,"y2":1058,"stroke":1029,"style":1030},"472.0",[1060,1139],{"points":1140,"fill":1063},"472.0,161.5 467.0,152.5 477.0,152.5",[1015,1142],{"x":1143,"y":1067,"width":1144,"height":1069,"rx":1070,"fill":1020,"stroke":1071,"style":1072},"404.9","134.1",[1043,1146,1147],{"x":1137,"y":1075,"style":1076},"due before next run",[1015,1149],{"x":1150,"y":1081,"width":1082,"height":1083,"rx":1027,"fill":1028,"stroke":1029,"style":1030},"388.0",[1032,1152,1154],{"transform":1153},"translate(460.0,176.5) scale(1.000)",[1036,1155],{"d":1156,"fill":1039,"stroke":1040,"style":1041},"M4 5h16v15H4z M4 10h16 M8 3v4 M16 3v4",[1043,1158,1131],{"x":1137,"y":1095,"style":1046},[1043,1160,1161],{"x":1137,"y":1100,"style":1101},"avoid paying late",[42,1163],{"x1":1055,"y1":1051,"x2":1055,"y2":1058,"stroke":1029,"style":1030},[1060,1165],{"points":1166,"fill":1063},"656.0,161.5 651.0,152.5 661.0,152.5",[1015,1168],{"x":1169,"y":1067,"width":1170,"height":1069,"rx":1070,"fill":1020,"stroke":1071,"style":1072},"633.6","44.8",[1043,1172,1173],{"x":1055,"y":1075,"style":1076},"later",[1015,1175],{"x":1176,"y":1081,"width":1082,"height":1083,"rx":1027,"fill":1177,"stroke":1071,"style":1030},"572.0","#e7ebef",[1032,1179,1181],{"transform":1180},"translate(644.0,176.5) scale(1.000)",[1036,1182],{"d":1183,"fill":1039,"stroke":1184,"style":1041},"M12 3a9 9 0 1 0 .01 0z M12 7v5l3.5 2","var(--text,#172033)",[1043,1186,1188],{"x":1055,"y":1095,"style":1187},"font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","defer",[1043,1190,1191],{"x":1055,"y":1100,"style":1101},"next run",[25,1193,1195],{"id":1194},"step-3-net-per-supplier-and-fit-the-cash-limit","Step 3 — Net per supplier and fit the cash limit",[10,1197,1198],{},"Payments go to suppliers, not invoices, so total the lines per supplier — credit notes reduce the payment — and check the total against the cash treasury has made available:",[30,1200,1202],{"className":67,"code":1201,"language":69,"meta":35,"style":35},"CASH_LIMIT = 30000.00\npay = ap[ap[\"Decision\"] == \"pay\"]\nby_supplier = (pay.groupby([\"Supplier\", \"IBAN\"], as_index=False)\n               .agg(Lines=(\"Document\", \"count\"), Earliest_due=(\"Due date\", \"min\"), Discount=(\"Discount\", \"sum\"), Payment=(\"To pay\", \"sum\"))\n               .sort_values(\"Earliest_due\"))\nroom, in_run = CASH_LIMIT, []\nfor amount in by_supplier[\"Payment\"]:\n    in_run.append(amount \u003C= room)\n    room -= amount if amount \u003C= room else 0\nby_supplier[\"In run\"] = in_run\nprint(by_supplier.drop(columns=\"IBAN\").to_string(index=False))\nprint(f\"proposed {by_supplier.loc[by_supplier['In run'], 'Payment'].sum():,.2f} of {by_supplier['Payment'].sum():,.2f}; \"\n      f\"discounts taken {by_supplier.loc[by_supplier['In run'], 'Discount'].sum():,.2f}\")\n",[37,1203,1204,1214,1235,1263,1332,1342,1355,1372,1383,1407,1422,1447,1497],{"__ignoreMap":35},[40,1205,1206,1209,1211],{"class":42,"line":43},[40,1207,1208],{"class":161},"CASH_LIMIT",[40,1210,170],{"class":76},[40,1212,1213],{"class":161}," 30000.00\n",[40,1215,1216,1219,1221,1224,1226,1228,1230,1232],{"class":42,"line":84},[40,1217,1218],{"class":80},"pay ",[40,1220,111],{"class":76},[40,1222,1223],{"class":80}," ap[ap[",[40,1225,831],{"class":50},[40,1227,365],{"class":80},[40,1229,944],{"class":76},[40,1231,637],{"class":50},[40,1233,1234],{"class":80},"]\n",[40,1236,1237,1240,1242,1245,1247,1249,1251,1254,1257,1259,1261],{"class":42,"line":98},[40,1238,1239],{"class":80},"by_supplier ",[40,1241,111],{"class":76},[40,1243,1244],{"class":80}," (pay.groupby([",[40,1246,471],{"class":50},[40,1248,120],{"class":80},[40,1250,597],{"class":50},[40,1252,1253],{"class":80},"], ",[40,1255,1256],{"class":123},"as_index",[40,1258,111],{"class":76},[40,1260,528],{"class":161},[40,1262,132],{"class":80},[40,1264,1265,1268,1271,1273,1276,1278,1280,1283,1285,1288,1290,1292,1294,1296,1299,1301,1304,1306,1308,1310,1312,1315,1317,1320,1322,1324,1326,1328,1330],{"class":42,"line":105},[40,1266,1267],{"class":80},"               .agg(",[40,1269,1270],{"class":123},"Lines",[40,1272,111],{"class":76},[40,1274,1275],{"class":80},"(",[40,1277,499],{"class":50},[40,1279,120],{"class":80},[40,1281,1282],{"class":50},"\"count\"",[40,1284,902],{"class":80},[40,1286,1287],{"class":123},"Earliest_due",[40,1289,111],{"class":76},[40,1291,1275],{"class":80},[40,1293,504],{"class":50},[40,1295,120],{"class":80},[40,1297,1298],{"class":50},"\"min\"",[40,1300,902],{"class":80},[40,1302,1303],{"class":123},"Discount",[40,1305,111],{"class":76},[40,1307,1275],{"class":80},[40,1309,870],{"class":50},[40,1311,120],{"class":80},[40,1313,1314],{"class":50},"\"sum\"",[40,1316,902],{"class":80},[40,1318,1319],{"class":123},"Payment",[40,1321,111],{"class":76},[40,1323,1275],{"class":80},[40,1325,918],{"class":50},[40,1327,120],{"class":80},[40,1329,1314],{"class":50},[40,1331,531],{"class":80},[40,1333,1334,1337,1340],{"class":42,"line":135},[40,1335,1336],{"class":80},"               .sort_values(",[40,1338,1339],{"class":50},"\"Earliest_due\"",[40,1341,531],{"class":80},[40,1343,1344,1347,1349,1352],{"class":42,"line":158},[40,1345,1346],{"class":80},"room, in_run ",[40,1348,111],{"class":76},[40,1350,1351],{"class":161}," CASH_LIMIT",[40,1353,1354],{"class":80},", []\n",[40,1356,1357,1359,1362,1364,1367,1370],{"class":42,"line":187},[40,1358,378],{"class":76},[40,1360,1361],{"class":80}," amount ",[40,1363,384],{"class":76},[40,1365,1366],{"class":80}," by_supplier[",[40,1368,1369],{"class":50},"\"Payment\"",[40,1371,574],{"class":80},[40,1373,1374,1377,1380],{"class":42,"line":192},[40,1375,1376],{"class":80},"    in_run.append(amount ",[40,1378,1379],{"class":76},"\u003C=",[40,1381,1382],{"class":80}," room)\n",[40,1384,1385,1388,1391,1393,1395,1397,1399,1402,1404],{"class":42,"line":205},[40,1386,1387],{"class":80},"    room ",[40,1389,1390],{"class":76},"-=",[40,1392,1361],{"class":80},[40,1394,313],{"class":76},[40,1396,1361],{"class":80},[40,1398,1379],{"class":76},[40,1400,1401],{"class":80}," room ",[40,1403,319],{"class":76},[40,1405,1406],{"class":161}," 0\n",[40,1408,1409,1412,1415,1417,1419],{"class":42,"line":274},[40,1410,1411],{"class":80},"by_supplier[",[40,1413,1414],{"class":50},"\"In run\"",[40,1416,365],{"class":80},[40,1418,111],{"class":76},[40,1420,1421],{"class":80}," in_run\n",[40,1423,1424,1426,1429,1432,1434,1436,1439,1441,1443,1445],{"class":42,"line":334},[40,1425,489],{"class":161},[40,1427,1428],{"class":80},"(by_supplier.drop(",[40,1430,1431],{"class":123},"columns",[40,1433,111],{"class":76},[40,1435,597],{"class":50},[40,1437,1438],{"class":80},").to_string(",[40,1440,523],{"class":123},[40,1442,111],{"class":76},[40,1444,528],{"class":161},[40,1446,531],{"class":80},[40,1448,1449,1451,1453,1455,1458,1460,1463,1466,1468,1471,1474,1477,1479,1482,1484,1486,1488,1490,1492,1494],{"class":42,"line":339},[40,1450,489],{"class":161},[40,1452,1275],{"class":80},[40,1454,686],{"class":76},[40,1456,1457],{"class":50},"\"proposed ",[40,1459,693],{"class":692},[40,1461,1462],{"class":80},"by_supplier.loc[by_supplier[",[40,1464,1465],{"class":50},"'In run'",[40,1467,1253],{"class":80},[40,1469,1470],{"class":50},"'Payment'",[40,1472,1473],{"class":80},"].sum()",[40,1475,1476],{"class":76},":,.2f",[40,1478,708],{"class":692},[40,1480,1481],{"class":50}," of ",[40,1483,693],{"class":692},[40,1485,1411],{"class":80},[40,1487,1470],{"class":50},[40,1489,1473],{"class":80},[40,1491,1476],{"class":76},[40,1493,708],{"class":692},[40,1495,1496],{"class":50},"; \"\n",[40,1498,1499,1502,1505,1507,1509,1511,1513,1516,1518,1520,1522,1524],{"class":42,"line":356},[40,1500,1501],{"class":76},"      f",[40,1503,1504],{"class":50},"\"discounts taken ",[40,1506,693],{"class":692},[40,1508,1462],{"class":80},[40,1510,1465],{"class":50},[40,1512,1253],{"class":80},[40,1514,1515],{"class":50},"'Discount'",[40,1517,1473],{"class":80},[40,1519,1476],{"class":76},[40,1521,708],{"class":692},[40,1523,219],{"class":50},[40,1525,132],{"class":80},[10,1527,1528],{},"Acme's payment is its two invoices less the discount on one and less its 350 credit note. Suppliers are taken in order of their earliest due date, and each is included if it still fits in the remaining cash, so the most overdue are paid first and a large payment that does not fit does not block smaller ones behind it. Anything that does not fit is marked out of the run rather than silently dropped, so the approver can decide whether to find more cash or let it wait. Here 25,035.10 is proposed to five suppliers, taking 95.60 of discounts; Evergreen Facilities' 12,400 does not fit in what is left of the 30,000 and is flagged for the approver. Other priority rules — strategic suppliers first, or smallest suppliers first — are just a different sort key.",[996,1530,1005,1536,1005,1539,1005,1542,1005,1546,1005,1552,1005,1558,1005,1563,1005,1568,1005,1571,1005,1575,1005,1578,1005,1582,1005,1585,1005,1589,1005,1592,1005,1596,1005,1598,1005,1602,1005,1605,1005,1609,1005,1612,1005,1616,1005,1619,1005,1624,1005,1627,1005,1631,1005,1634],{"viewBox":1531,"role":999,"ariaLabelledBy":1532,"xmlns":1003,"style":1535},"4 0 744 260",[1533,1534],"pr-bars-t","pr-bars-d","width:100%;max-width:744px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[1007,1537,1538],{"id":1533},"The proposal against the cash limit",[1011,1540,1541],{"id":1534},"Supplier payments in due-date order are fitted to the 30,000 cash limit. Acme, Corex, Brightline, Delta and Fjord fit, totalling 25,035.10. Evergreen Facilities' 12,400 would exceed what remains and is flagged for the approver.",[1015,1543],{"x":1017,"y":373,"width":1544,"height":1545,"fill":1020},"744","260",[1015,1547],{"x":1080,"y":1024,"width":1548,"height":1549,"rx":1550,"fill":1177,"stroke":1071,"style":1551},"154.8","28.0","7","stroke-width:1px",[1043,1553,1557],{"x":1554,"y":1555,"style":1556},"97.4","34.5","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Acme Fasteners",[1015,1559],{"x":1560,"y":1024,"width":1561,"height":1549,"rx":1550,"fill":1119,"stroke":1120,"style":1562},"184.8","195.0","stroke-width:1.5px",[1043,1564,1567],{"x":1565,"y":1555,"style":1566},"387.8","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:start","5,692.40",[1015,1569],{"x":1080,"y":1570,"width":1548,"height":1549,"rx":1550,"fill":1177,"stroke":1071,"style":1551},"56.0",[1043,1572,1574],{"x":1554,"y":1573,"style":1556},"74.5","Corex Packaging",[1015,1576],{"x":1560,"y":1570,"width":1577,"height":1549,"rx":1550,"fill":1119,"stroke":1120,"style":1562},"113.4",[1043,1579,1581],{"x":1580,"y":1573,"style":1566},"306.2","3,310.50",[1015,1583],{"x":1080,"y":1584,"width":1548,"height":1549,"rx":1550,"fill":1177,"stroke":1071,"style":1551},"96.0",[1043,1586,1588],{"x":1554,"y":1587,"style":1556},"114.5","Brightline Logistics",[1015,1590],{"x":1560,"y":1584,"width":1591,"height":1549,"rx":1550,"fill":1119,"stroke":1120,"style":1562},"330.6",[1043,1593,1595],{"x":1594,"y":1587,"style":1566},"523.4","9,650.00",[1015,1597],{"x":1080,"y":1075,"width":1548,"height":1549,"rx":1550,"fill":1177,"stroke":1071,"style":1551},[1043,1599,1601],{"x":1554,"y":1600,"style":1556},"154.5","Delta Office Supply",[1015,1603],{"x":1560,"y":1075,"width":1604,"height":1549,"rx":1550,"fill":1119,"stroke":1120,"style":1562},"21.9",[1043,1606,1608],{"x":1607,"y":1600,"style":1566},"214.8","640.20",[1015,1610],{"x":1080,"y":1611,"width":1548,"height":1549,"rx":1550,"fill":1177,"stroke":1071,"style":1551},"176.0",[1043,1613,1615],{"x":1554,"y":1614,"style":1556},"194.5","Evergreen Facilities",[1015,1617],{"x":1560,"y":1611,"width":1618,"height":1549,"rx":1550,"fill":1084,"stroke":1085,"style":1562},"424.8",[1043,1620,1623],{"x":1621,"y":1614,"style":1622},"617.6","font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:start","12,400.00 flagged",[1015,1625],{"x":1080,"y":1626,"width":1548,"height":1549,"rx":1550,"fill":1177,"stroke":1071,"style":1551},"216.0",[1043,1628,1630],{"x":1554,"y":1629,"style":1556},"234.5","Fjord IT Services",[1015,1632],{"x":1560,"y":1626,"width":1633,"height":1549,"rx":1550,"fill":1119,"stroke":1120,"style":1562},"196.7",[1043,1635,1637],{"x":1636,"y":1629,"style":1566},"389.5","5,742.00",[25,1639,1641],{"id":1640},"step-4-write-the-proposal-workbook","Step 4 — Write the proposal workbook",[10,1643,1644],{},"The approver needs four views: the payments by supplier, the invoice lines behind them, everything excluded or deferred with reasons, and a place to sign:",[30,1646,1648],{"className":67,"code":1647,"language":69,"meta":35,"style":35},"from openpyxl import load_workbook\nfrom openpyxl.styles import Font, PatternFill\n\npath = \"payment_run_2026-10-02.xlsx\"\ndetail_cols = [\"Supplier\", \"Document\", \"Due date\", \"Amount\", \"Discount\", \"To pay\", \"Reason\"]\nwith pd.ExcelWriter(path, engine=\"openpyxl\", date_format=\"dd mmm yyyy\", datetime_format=\"dd mmm yyyy\") as xw:\n    by_supplier.to_excel(xw, sheet_name=\"Proposal\", index=False)\n    pay[detail_cols].to_excel(xw, sheet_name=\"Lines\", index=False)\n    ap.loc[ap[\"Decision\"] != \"pay\", [\"Supplier\", \"Document\", \"Due date\", \"Amount\", \"Decision\", \"Reason\"]].to_excel(xw, sheet_name=\"Not paid\", index=False)\n\nwb = load_workbook(path)\nws = wb[\"Proposal\"]\nn = ws.max_row\nws[f\"E{n + 2}\"], ws[f\"F{n + 2}\"] = \"Total in run\", f'=SUMIFS(F2:F{n},G2:G{n},TRUE)'\nws[f\"E{n + 3}\"], ws[f\"F{n + 3}\"] = \"Cash limit\", CASH_LIMIT\nfor c in (f\"E{n + 2}\", f\"F{n + 2}\"):\n    ws[c].font = Font(bold=True)\nfor row in ws.iter_rows(min_row=2, max_row=n):\n    if row[6].value is False:\n        for cell in row:\n            cell.fill = PatternFill(\"solid\", fgColor=\"FFF4CE\")\nfor col in \"EF\":\n    for r in range(2, n + 4):\n        ws[f\"{col}{r}\"].number_format = \"#,##0.00\"\nsign = wb.create_sheet(\"Approval\")\nfor r, label in enumerate([\"Payment run\", \"Pay date\", \"Prepared by\", \"Approved by\", \"Date approved\"], start=1):\n    sign[f\"A{r}\"] = label\nsign[\"B1\"], sign[\"B2\"], sign[\"B3\"] = \"Supplier payments\", PAY_DATE.to_pydatetime(), \"Accounts payable\"\nsign[\"B2\"].number_format = \"dd mmm yyyy\"\nfor ws_ in wb.worksheets:\n    for col in ws_.columns:\n        ws_.column_dimensions[col[0].column_letter].width = max(12, min(40, max(len(str(c.value or \"\")) for c in col) + 2))\nwb.save(path)\nprint(wb.sheetnames)\n",[37,1649,1650,1663,1675,1679,1689,1727,1770,1792,1814,1873,1877,1887,1901,1911,1987,2038,2086,2106,2136,2157,2171,2197,2212,2240,2272,2288,2338,2364,2401,2415,2428,2440,2510,2516],{"__ignoreMap":35},[40,1651,1652,1655,1658,1660],{"class":42,"line":43},[40,1653,1654],{"class":76},"from",[40,1656,1657],{"class":80}," openpyxl ",[40,1659,77],{"class":76},[40,1661,1662],{"class":80}," load_workbook\n",[40,1664,1665,1667,1670,1672],{"class":42,"line":84},[40,1666,1654],{"class":76},[40,1668,1669],{"class":80}," openpyxl.styles ",[40,1671,77],{"class":76},[40,1673,1674],{"class":80}," Font, PatternFill\n",[40,1676,1677],{"class":42,"line":98},[40,1678,102],{"emptyLinePlaceholder":101},[40,1680,1681,1684,1686],{"class":42,"line":105},[40,1682,1683],{"class":80},"path ",[40,1685,111],{"class":76},[40,1687,1688],{"class":50}," \"payment_run_2026-10-02.xlsx\"\n",[40,1690,1691,1694,1696,1699,1701,1703,1705,1707,1709,1711,1713,1715,1717,1719,1721,1723,1725],{"class":42,"line":135},[40,1692,1693],{"class":80},"detail_cols ",[40,1695,111],{"class":76},[40,1697,1698],{"class":80}," [",[40,1700,471],{"class":50},[40,1702,120],{"class":80},[40,1704,499],{"class":50},[40,1706,120],{"class":80},[40,1708,504],{"class":50},[40,1710,120],{"class":80},[40,1712,509],{"class":50},[40,1714,120],{"class":80},[40,1716,870],{"class":50},[40,1718,120],{"class":80},[40,1720,918],{"class":50},[40,1722,120],{"class":80},[40,1724,836],{"class":50},[40,1726,1234],{"class":80},[40,1728,1729,1732,1735,1738,1740,1743,1745,1748,1750,1753,1755,1758,1760,1762,1765,1767],{"class":42,"line":158},[40,1730,1731],{"class":76},"with",[40,1733,1734],{"class":80}," pd.ExcelWriter(path, ",[40,1736,1737],{"class":123},"engine",[40,1739,111],{"class":76},[40,1741,1742],{"class":50},"\"openpyxl\"",[40,1744,120],{"class":80},[40,1746,1747],{"class":123},"date_format",[40,1749,111],{"class":76},[40,1751,1752],{"class":50},"\"dd mmm yyyy\"",[40,1754,120],{"class":80},[40,1756,1757],{"class":123},"datetime_format",[40,1759,111],{"class":76},[40,1761,1752],{"class":50},[40,1763,1764],{"class":80},") ",[40,1766,92],{"class":76},[40,1768,1769],{"class":80}," xw:\n",[40,1771,1772,1775,1777,1779,1782,1784,1786,1788,1790],{"class":42,"line":187},[40,1773,1774],{"class":80},"    by_supplier.to_excel(xw, ",[40,1776,124],{"class":123},[40,1778,111],{"class":76},[40,1780,1781],{"class":50},"\"Proposal\"",[40,1783,120],{"class":80},[40,1785,523],{"class":123},[40,1787,111],{"class":76},[40,1789,528],{"class":161},[40,1791,132],{"class":80},[40,1793,1794,1797,1799,1801,1804,1806,1808,1810,1812],{"class":42,"line":192},[40,1795,1796],{"class":80},"    pay[detail_cols].to_excel(xw, ",[40,1798,124],{"class":123},[40,1800,111],{"class":76},[40,1802,1803],{"class":50},"\"Lines\"",[40,1805,120],{"class":80},[40,1807,523],{"class":123},[40,1809,111],{"class":76},[40,1811,528],{"class":161},[40,1813,132],{"class":80},[40,1815,1816,1819,1821,1823,1826,1828,1831,1833,1835,1837,1839,1841,1843,1845,1847,1849,1851,1853,1856,1858,1860,1863,1865,1867,1869,1871],{"class":42,"line":205},[40,1817,1818],{"class":80},"    ap.loc[ap[",[40,1820,831],{"class":50},[40,1822,365],{"class":80},[40,1824,1825],{"class":76},"!=",[40,1827,637],{"class":50},[40,1829,1830],{"class":80},", [",[40,1832,471],{"class":50},[40,1834,120],{"class":80},[40,1836,499],{"class":50},[40,1838,120],{"class":80},[40,1840,504],{"class":50},[40,1842,120],{"class":80},[40,1844,509],{"class":50},[40,1846,120],{"class":80},[40,1848,831],{"class":50},[40,1850,120],{"class":80},[40,1852,836],{"class":50},[40,1854,1855],{"class":80},"]].to_excel(xw, ",[40,1857,124],{"class":123},[40,1859,111],{"class":76},[40,1861,1862],{"class":50},"\"Not paid\"",[40,1864,120],{"class":80},[40,1866,523],{"class":123},[40,1868,111],{"class":76},[40,1870,528],{"class":161},[40,1872,132],{"class":80},[40,1874,1875],{"class":42,"line":274},[40,1876,102],{"emptyLinePlaceholder":101},[40,1878,1879,1882,1884],{"class":42,"line":334},[40,1880,1881],{"class":80},"wb ",[40,1883,111],{"class":76},[40,1885,1886],{"class":80}," load_workbook(path)\n",[40,1888,1889,1892,1894,1897,1899],{"class":42,"line":339},[40,1890,1891],{"class":80},"ws ",[40,1893,111],{"class":76},[40,1895,1896],{"class":80}," wb[",[40,1898,1781],{"class":50},[40,1900,1234],{"class":80},[40,1902,1903,1906,1908],{"class":42,"line":356},[40,1904,1905],{"class":80},"n ",[40,1907,111],{"class":76},[40,1909,1910],{"class":80}," ws.max_row\n",[40,1912,1913,1916,1918,1921,1923,1925,1927,1930,1932,1934,1937,1939,1942,1944,1946,1948,1950,1952,1954,1956,1958,1961,1963,1965,1968,1970,1973,1975,1978,1980,1982,1984],{"class":42,"line":390},[40,1914,1915],{"class":80},"ws[",[40,1917,686],{"class":76},[40,1919,1920],{"class":50},"\"E",[40,1922,693],{"class":692},[40,1924,1905],{"class":80},[40,1926,225],{"class":76},[40,1928,1929],{"class":161}," 2",[40,1931,708],{"class":692},[40,1933,219],{"class":50},[40,1935,1936],{"class":80},"], ws[",[40,1938,686],{"class":76},[40,1940,1941],{"class":50},"\"F",[40,1943,693],{"class":692},[40,1945,1905],{"class":80},[40,1947,225],{"class":76},[40,1949,1929],{"class":161},[40,1951,708],{"class":692},[40,1953,219],{"class":50},[40,1955,365],{"class":80},[40,1957,111],{"class":76},[40,1959,1960],{"class":50}," \"Total in run\"",[40,1962,120],{"class":80},[40,1964,686],{"class":76},[40,1966,1967],{"class":50},"'=SUMIFS(F2:F",[40,1969,693],{"class":692},[40,1971,1972],{"class":80},"n",[40,1974,708],{"class":692},[40,1976,1977],{"class":50},",G2:G",[40,1979,693],{"class":692},[40,1981,1972],{"class":80},[40,1983,708],{"class":692},[40,1985,1986],{"class":50},",TRUE)'\n",[40,1988,1989,1991,1993,1995,1997,1999,2001,2004,2006,2008,2010,2012,2014,2016,2018,2020,2022,2024,2026,2028,2030,2033,2035],{"class":42,"line":456},[40,1990,1915],{"class":80},[40,1992,686],{"class":76},[40,1994,1920],{"class":50},[40,1996,693],{"class":692},[40,1998,1905],{"class":80},[40,2000,225],{"class":76},[40,2002,2003],{"class":161}," 3",[40,2005,708],{"class":692},[40,2007,219],{"class":50},[40,2009,1936],{"class":80},[40,2011,686],{"class":76},[40,2013,1941],{"class":50},[40,2015,693],{"class":692},[40,2017,1905],{"class":80},[40,2019,225],{"class":76},[40,2021,2003],{"class":161},[40,2023,708],{"class":692},[40,2025,219],{"class":50},[40,2027,365],{"class":80},[40,2029,111],{"class":76},[40,2031,2032],{"class":50}," \"Cash limit\"",[40,2034,120],{"class":80},[40,2036,2037],{"class":161},"CASH_LIMIT\n",[40,2039,2040,2042,2045,2047,2049,2051,2053,2055,2057,2059,2061,2063,2065,2067,2069,2071,2073,2075,2077,2079,2081,2083],{"class":42,"line":486},[40,2041,378],{"class":76},[40,2043,2044],{"class":80}," c ",[40,2046,384],{"class":76},[40,2048,280],{"class":80},[40,2050,686],{"class":76},[40,2052,1920],{"class":50},[40,2054,693],{"class":692},[40,2056,1905],{"class":80},[40,2058,225],{"class":76},[40,2060,1929],{"class":161},[40,2062,708],{"class":692},[40,2064,219],{"class":50},[40,2066,120],{"class":80},[40,2068,686],{"class":76},[40,2070,1941],{"class":50},[40,2072,693],{"class":692},[40,2074,1905],{"class":80},[40,2076,225],{"class":76},[40,2078,1929],{"class":161},[40,2080,708],{"class":692},[40,2082,219],{"class":50},[40,2084,2085],{"class":80},"):\n",[40,2087,2088,2091,2093,2096,2099,2101,2104],{"class":42,"line":955},[40,2089,2090],{"class":80},"    ws[c].font ",[40,2092,111],{"class":76},[40,2094,2095],{"class":80}," Font(",[40,2097,2098],{"class":123},"bold",[40,2100,111],{"class":76},[40,2102,2103],{"class":161},"True",[40,2105,132],{"class":80},[40,2107,2109,2111,2114,2116,2119,2122,2124,2126,2128,2131,2133],{"class":42,"line":2108},18,[40,2110,378],{"class":76},[40,2112,2113],{"class":80}," row ",[40,2115,384],{"class":76},[40,2117,2118],{"class":80}," ws.iter_rows(",[40,2120,2121],{"class":123},"min_row",[40,2123,111],{"class":76},[40,2125,307],{"class":161},[40,2127,120],{"class":80},[40,2129,2130],{"class":123},"max_row",[40,2132,111],{"class":76},[40,2134,2135],{"class":80},"n):\n",[40,2137,2139,2141,2143,2146,2149,2152,2155],{"class":42,"line":2138},19,[40,2140,565],{"class":76},[40,2142,568],{"class":80},[40,2144,2145],{"class":161},"6",[40,2147,2148],{"class":80},"].value ",[40,2150,2151],{"class":76},"is",[40,2153,2154],{"class":161}," False",[40,2156,630],{"class":80},[40,2158,2160,2163,2166,2168],{"class":42,"line":2159},20,[40,2161,2162],{"class":76},"        for",[40,2164,2165],{"class":80}," cell ",[40,2167,384],{"class":76},[40,2169,2170],{"class":80}," row:\n",[40,2172,2174,2177,2179,2182,2185,2187,2190,2192,2195],{"class":42,"line":2173},21,[40,2175,2176],{"class":80},"            cell.fill ",[40,2178,111],{"class":76},[40,2180,2181],{"class":80}," PatternFill(",[40,2183,2184],{"class":50},"\"solid\"",[40,2186,120],{"class":80},[40,2188,2189],{"class":123},"fgColor",[40,2191,111],{"class":76},[40,2193,2194],{"class":50},"\"FFF4CE\"",[40,2196,132],{"class":80},[40,2198,2200,2202,2205,2207,2210],{"class":42,"line":2199},22,[40,2201,378],{"class":76},[40,2203,2204],{"class":80}," col ",[40,2206,384],{"class":76},[40,2208,2209],{"class":50}," \"EF\"",[40,2211,630],{"class":80},[40,2213,2215,2218,2221,2223,2226,2228,2230,2233,2235,2238],{"class":42,"line":2214},23,[40,2216,2217],{"class":76},"    for",[40,2219,2220],{"class":80}," r ",[40,2222,384],{"class":76},[40,2224,2225],{"class":161}," range",[40,2227,1275],{"class":80},[40,2229,307],{"class":161},[40,2231,2232],{"class":80},", n ",[40,2234,225],{"class":76},[40,2236,2237],{"class":161}," 4",[40,2239,2085],{"class":80},[40,2241,2243,2246,2248,2250,2252,2255,2258,2260,2262,2264,2267,2269],{"class":42,"line":2242},24,[40,2244,2245],{"class":80},"        ws[",[40,2247,686],{"class":76},[40,2249,219],{"class":50},[40,2251,693],{"class":692},[40,2253,2254],{"class":80},"col",[40,2256,2257],{"class":692},"}{",[40,2259,216],{"class":80},[40,2261,708],{"class":692},[40,2263,219],{"class":50},[40,2265,2266],{"class":80},"].number_format ",[40,2268,111],{"class":76},[40,2270,2271],{"class":50}," \"#,##0.00\"\n",[40,2273,2275,2278,2280,2283,2286],{"class":42,"line":2274},25,[40,2276,2277],{"class":80},"sign ",[40,2279,111],{"class":76},[40,2281,2282],{"class":80}," wb.create_sheet(",[40,2284,2285],{"class":50},"\"Approval\"",[40,2287,132],{"class":80},[40,2289,2291,2293,2296,2298,2301,2304,2307,2309,2312,2314,2317,2319,2322,2324,2327,2329,2332,2334,2336],{"class":42,"line":2290},26,[40,2292,378],{"class":76},[40,2294,2295],{"class":80}," r, label ",[40,2297,384],{"class":76},[40,2299,2300],{"class":161}," enumerate",[40,2302,2303],{"class":80},"([",[40,2305,2306],{"class":50},"\"Payment run\"",[40,2308,120],{"class":80},[40,2310,2311],{"class":50},"\"Pay date\"",[40,2313,120],{"class":80},[40,2315,2316],{"class":50},"\"Prepared by\"",[40,2318,120],{"class":80},[40,2320,2321],{"class":50},"\"Approved by\"",[40,2323,120],{"class":80},[40,2325,2326],{"class":50},"\"Date approved\"",[40,2328,1253],{"class":80},[40,2330,2331],{"class":123},"start",[40,2333,111],{"class":76},[40,2335,289],{"class":161},[40,2337,2085],{"class":80},[40,2339,2341,2344,2346,2349,2351,2353,2355,2357,2359,2361],{"class":42,"line":2340},27,[40,2342,2343],{"class":80},"    sign[",[40,2345,686],{"class":76},[40,2347,2348],{"class":50},"\"A",[40,2350,693],{"class":692},[40,2352,216],{"class":80},[40,2354,708],{"class":692},[40,2356,219],{"class":50},[40,2358,365],{"class":80},[40,2360,111],{"class":76},[40,2362,2363],{"class":80}," label\n",[40,2365,2367,2370,2373,2376,2379,2381,2384,2386,2388,2391,2393,2395,2398],{"class":42,"line":2366},28,[40,2368,2369],{"class":80},"sign[",[40,2371,2372],{"class":50},"\"B1\"",[40,2374,2375],{"class":80},"], sign[",[40,2377,2378],{"class":50},"\"B2\"",[40,2380,2375],{"class":80},[40,2382,2383],{"class":50},"\"B3\"",[40,2385,365],{"class":80},[40,2387,111],{"class":76},[40,2389,2390],{"class":50}," \"Supplier payments\"",[40,2392,120],{"class":80},[40,2394,162],{"class":161},[40,2396,2397],{"class":80},".to_pydatetime(), ",[40,2399,2400],{"class":50},"\"Accounts payable\"\n",[40,2402,2404,2406,2408,2410,2412],{"class":42,"line":2403},29,[40,2405,2369],{"class":80},[40,2407,2378],{"class":50},[40,2409,2266],{"class":80},[40,2411,111],{"class":76},[40,2413,2414],{"class":50}," \"dd mmm yyyy\"\n",[40,2416,2418,2420,2423,2425],{"class":42,"line":2417},30,[40,2419,378],{"class":76},[40,2421,2422],{"class":80}," ws_ ",[40,2424,384],{"class":76},[40,2426,2427],{"class":80}," wb.worksheets:\n",[40,2429,2431,2433,2435,2437],{"class":42,"line":2430},31,[40,2432,2217],{"class":76},[40,2434,2204],{"class":80},[40,2436,384],{"class":76},[40,2438,2439],{"class":80}," ws_.columns:\n",[40,2441,2443,2446,2448,2451,2453,2456,2458,2460,2462,2465,2467,2470,2472,2475,2477,2480,2482,2484,2487,2490,2493,2495,2497,2499,2501,2504,2506,2508],{"class":42,"line":2442},32,[40,2444,2445],{"class":80},"        ws_.column_dimensions[col[",[40,2447,373],{"class":161},[40,2449,2450],{"class":80},"].column_letter].width ",[40,2452,111],{"class":76},[40,2454,2455],{"class":161}," max",[40,2457,1275],{"class":80},[40,2459,1027],{"class":161},[40,2461,120],{"class":80},[40,2463,2464],{"class":161},"min",[40,2466,1275],{"class":80},[40,2468,2469],{"class":161},"40",[40,2471,120],{"class":80},[40,2473,2474],{"class":161},"max",[40,2476,1275],{"class":80},[40,2478,2479],{"class":161},"len",[40,2481,1275],{"class":80},[40,2483,268],{"class":161},[40,2485,2486],{"class":80},"(c.value ",[40,2488,2489],{"class":76},"or",[40,2491,2492],{"class":50}," \"\"",[40,2494,292],{"class":80},[40,2496,378],{"class":76},[40,2498,2044],{"class":80},[40,2500,384],{"class":76},[40,2502,2503],{"class":80}," col) ",[40,2505,225],{"class":76},[40,2507,1929],{"class":161},[40,2509,531],{"class":80},[40,2511,2513],{"class":42,"line":2512},33,[40,2514,2515],{"class":80},"wb.save(path)\n",[40,2517,2519,2521],{"class":42,"line":2518},34,[40,2520,489],{"class":161},[40,2522,2523],{"class":80},"(wb.sheetnames)\n",[10,2525,2526,2527,2530,2531,2534,2535,2538,2539,2542,2543,2547],{},"The total on the proposal sheet is a ",[37,2528,2529],{},"SUMIFS"," formula over the rows marked in the run, so if the approver flips Evergreen's ",[14,2532,2533],{},"In run"," cell to ",[37,2536,2537],{},"TRUE",", the total updates and can be compared with the cash limit beneath it. Suppliers outside the limit are shaded. The ",[14,2540,2541],{},"Not paid"," sheet lists every excluded or deferred line with its reason — the first thing an auditor or a chasing supplier will ask about. The approval sheet records who prepared and approved the run; protecting it and the proposal against later edits is covered in ",[19,2544,2546],{"href":2545},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Flock-cells-and-protect-a-sheet-with-openpyxl\u002F","Lock Cells and Protect a Sheet with openpyxl",". Once approved, the payment file for the bank is generated from the same proposal, never retyped.",[996,2549,1005,2555,1005,2558,1005,2561,1005,2566,1005,2571,1005,2575,1005,2581,1005,2585,1005,2589,1005,2593,1005,2597,1005,2601,1005,2605,1005,2609,1005,2613,1005,2616,1005,2620,1005,2622,1005,2626,1005,2628,1005,2630,1005,2632,1005,2634,1005,2636,1005,2638,1005,2640,1005,2642,1005,2645,1005,2648,1005,2650,1005,2653,1005,2655,1005,2658,1005,2660,1005,2663,1005,2665,1005,2667,1005,2669,1005,2671,1005,2673,1005,2676,1005,2678,1005,2680,1005,2682,1005,2684,1005,2686,1005,2689,1005,2691,1005,2693,1005,2695,1005,2697,1005,2700,1005,2703,1005,2705,1005,2707,1005,2709,1005,2711,1005,2713,1005,2715,1005,2717,1005,2719,1005,2721,1005,2723,1005,2726,1005,2730,1005,2732,1005,2734,1005,2736,1005,2738,1005,2740,1005,2742,1005,2744,1005,2746,1005,2748,1005,2750,1005,2753,1005,2756,1005,2758,1005,2761,1005,2763,1005,2765,1005,2767,1005,2769,1005,2771,1005,2774,1005,2776,1005,2779,1005,2782,1005,2785,1005,2787,1005,2789,1005,2791,1005,2793,1005,2795,1005,2798,1005,2800,1005,2802,1005,2804,1005,2806,1005,2809,1005,2813,1005,2815,1005,2817,1005,2819,1005,2823,1005,2825,1005,2828],{"viewBox":2550,"role":999,"ariaLabelledBy":2551,"xmlns":1003,"style":2554},"123 0 513 280",[2552,2553],"pr-sheet-t","pr-sheet-d","width:100%;max-width:513px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[1007,2556,2557],{"id":2552},"The Proposal sheet the approver sees",[1011,2559,2560],{"id":2553},"One row per supplier with the number of lines, earliest due date, discount and payment, and an In run column. Evergreen Facilities is shaded because it does not fit the cash limit. A SUMIFS total of the rows in the run sits below, with the cash limit beneath it.",[1015,2562],{"x":2563,"y":373,"width":2564,"height":2565,"fill":1020},"123","513","280",[1015,2567],{"x":2568,"y":1024,"width":2569,"height":2570,"rx":373,"fill":1177,"stroke":1071,"style":1551},"139.8","32.0","24.0",[1015,2572],{"x":2573,"y":1024,"width":2574,"height":2570,"rx":373,"fill":1177,"stroke":1071,"style":1551},"171.8","145.8",[1043,2576,2580],{"x":2577,"y":2578,"style":2579},"244.7","33.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[1015,2582],{"x":2583,"y":1024,"width":2584,"height":2570,"rx":373,"fill":1177,"stroke":1071,"style":1551},"317.6","56.9",[1043,2586,2588],{"x":2587,"y":2578,"style":2579},"346.1","B",[1015,2590],{"x":2591,"y":1024,"width":2592,"height":2570,"rx":373,"fill":1177,"stroke":1071,"style":1551},"374.5","93.5",[1043,2594,2596],{"x":2595,"y":2578,"style":2579},"421.3","C",[1015,2598],{"x":2599,"y":1024,"width":2600,"height":2570,"rx":373,"fill":1177,"stroke":1071,"style":1551},"468.1","88.3",[1043,2602,2604],{"x":2603,"y":2578,"style":2579},"512.2","D",[1015,2606],{"x":2607,"y":1024,"width":2608,"height":2570,"rx":373,"fill":1177,"stroke":1071,"style":1551},"556.3","63.8",[1043,2610,2612],{"x":2611,"y":2578,"style":2579},"588.3","E",[1015,2614],{"x":2568,"y":2615,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},"40.0",[1043,2617,289],{"x":2618,"y":2619,"style":2579},"155.8","59.0",[1015,2621],{"x":2573,"y":2615,"width":2574,"height":1549,"rx":373,"fill":1028,"stroke":1029,"style":1562},[1043,2623,2625],{"x":2577,"y":2619,"style":2624},"font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Supplier",[1015,2627],{"x":2583,"y":2615,"width":2584,"height":1549,"rx":373,"fill":1028,"stroke":1029,"style":1562},[1043,2629,1270],{"x":2587,"y":2619,"style":2624},[1015,2631],{"x":2591,"y":2615,"width":2592,"height":1549,"rx":373,"fill":1028,"stroke":1029,"style":1562},[1043,2633,1303],{"x":2595,"y":2619,"style":2624},[1015,2635],{"x":2599,"y":2615,"width":2600,"height":1549,"rx":373,"fill":1028,"stroke":1029,"style":1562},[1043,2637,1319],{"x":2603,"y":2619,"style":2624},[1015,2639],{"x":2607,"y":2615,"width":2608,"height":1549,"rx":373,"fill":1028,"stroke":1029,"style":1562},[1043,2641,2533],{"x":2611,"y":2619,"style":2624},[1015,2643],{"x":2568,"y":2644,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},"68.0",[1043,2646,307],{"x":2618,"y":2647,"style":2579},"87.0",[1015,2649],{"x":2573,"y":2644,"width":2574,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2651,1557],{"x":2577,"y":2647,"style":2652},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle",[1015,2654],{"x":2583,"y":2644,"width":2584,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2656,2657],{"x":2587,"y":2647,"style":2652},"3",[1015,2659],{"x":2591,"y":2644,"width":2592,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2661,2662],{"x":2595,"y":2647,"style":2652},"37.60",[1015,2664],{"x":2599,"y":2644,"width":2600,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2666,1567],{"x":2603,"y":2647,"style":2652},[1015,2668],{"x":2607,"y":2644,"width":2608,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2670,2537],{"x":2611,"y":2647,"style":2652},[1015,2672],{"x":2568,"y":1584,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},[1043,2674,2657],{"x":2618,"y":2675,"style":2579},"115.0",[1015,2677],{"x":2573,"y":1584,"width":2574,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2679,1574],{"x":2577,"y":2675,"style":2652},[1015,2681],{"x":2583,"y":1584,"width":2584,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2683,289],{"x":2587,"y":2675,"style":2652},[1015,2685],{"x":2591,"y":1584,"width":2592,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2687,2688],{"x":2595,"y":2675,"style":2652},"0.00",[1015,2690],{"x":2599,"y":1584,"width":2600,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2692,1581],{"x":2603,"y":2675,"style":2652},[1015,2694],{"x":2607,"y":1584,"width":2608,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2696,2537],{"x":2611,"y":2675,"style":2652},[1015,2698],{"x":2568,"y":2699,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},"124.0",[1043,2701,1017],{"x":2618,"y":2702,"style":2579},"143.0",[1015,2704],{"x":2573,"y":2699,"width":2574,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2706,1588],{"x":2577,"y":2702,"style":2652},[1015,2708],{"x":2583,"y":2699,"width":2584,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2710,289],{"x":2587,"y":2702,"style":2652},[1015,2712],{"x":2591,"y":2699,"width":2592,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2714,2688],{"x":2595,"y":2702,"style":2652},[1015,2716],{"x":2599,"y":2699,"width":2600,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2718,1595],{"x":2603,"y":2702,"style":2652},[1015,2720],{"x":2607,"y":2699,"width":2608,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2722,2537],{"x":2611,"y":2702,"style":2652},[1015,2724],{"x":2568,"y":2725,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},"152.0",[1043,2727,2729],{"x":2618,"y":2728,"style":2579},"171.0","5",[1015,2731],{"x":2573,"y":2725,"width":2574,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2733,1601],{"x":2577,"y":2728,"style":2652},[1015,2735],{"x":2583,"y":2725,"width":2584,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2737,289],{"x":2587,"y":2728,"style":2652},[1015,2739],{"x":2591,"y":2725,"width":2592,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2741,2688],{"x":2595,"y":2728,"style":2652},[1015,2743],{"x":2599,"y":2725,"width":2600,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2745,1608],{"x":2603,"y":2728,"style":2652},[1015,2747],{"x":2607,"y":2725,"width":2608,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2749,2537],{"x":2611,"y":2728,"style":2652},[1015,2751],{"x":2568,"y":2752,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},"180.0",[1043,2754,2145],{"x":2618,"y":2755,"style":2579},"199.0",[1015,2757],{"x":2573,"y":2752,"width":2574,"height":1549,"rx":373,"fill":1084,"stroke":1085,"style":1562},[1043,2759,1615],{"x":2577,"y":2755,"style":2760},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle",[1015,2762],{"x":2583,"y":2752,"width":2584,"height":1549,"rx":373,"fill":1084,"stroke":1085,"style":1562},[1043,2764,289],{"x":2587,"y":2755,"style":2760},[1015,2766],{"x":2591,"y":2752,"width":2592,"height":1549,"rx":373,"fill":1084,"stroke":1085,"style":1562},[1043,2768,2688],{"x":2595,"y":2755,"style":2760},[1015,2770],{"x":2599,"y":2752,"width":2600,"height":1549,"rx":373,"fill":1084,"stroke":1085,"style":1562},[1043,2772,2773],{"x":2603,"y":2755,"style":2760},"12,400.00",[1015,2775],{"x":2607,"y":2752,"width":2608,"height":1549,"rx":373,"fill":1084,"stroke":1085,"style":1562},[1043,2777,2778],{"x":2611,"y":2755,"style":2760},"FALSE",[1015,2780],{"x":2568,"y":2781,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},"208.0",[1043,2783,1550],{"x":2618,"y":2784,"style":2579},"227.0",[1015,2786],{"x":2573,"y":2781,"width":2574,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2788,1630],{"x":2577,"y":2784,"style":2652},[1015,2790],{"x":2583,"y":2781,"width":2584,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2792,289],{"x":2587,"y":2784,"style":2652},[1015,2794],{"x":2591,"y":2781,"width":2592,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2796,2797],{"x":2595,"y":2784,"style":2652},"58.00",[1015,2799],{"x":2599,"y":2781,"width":2600,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2801,1637],{"x":2603,"y":2784,"style":2652},[1015,2803],{"x":2607,"y":2781,"width":2608,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1043,2805,2537],{"x":2611,"y":2784,"style":2652},[1015,2807],{"x":2568,"y":2808,"width":2569,"height":1549,"rx":373,"fill":1177,"stroke":1071,"style":1551},"236.0",[1043,2810,2812],{"x":2618,"y":2811,"style":2579},"255.0","8",[1015,2814],{"x":2573,"y":2808,"width":2574,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1015,2816],{"x":2583,"y":2808,"width":2584,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[1015,2818],{"x":2591,"y":2808,"width":2592,"height":1549,"rx":373,"fill":1119,"stroke":1120,"style":1562},[1043,2820,2822],{"x":2595,"y":2811,"style":2821},"font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Total in run",[1015,2824],{"x":2599,"y":2808,"width":2600,"height":1549,"rx":373,"fill":1119,"stroke":1120,"style":1562},[1043,2826,2827],{"x":2603,"y":2811,"style":2821},"25,035.10",[1015,2829],{"x":2607,"y":2808,"width":2608,"height":1549,"rx":373,"fill":1020,"stroke":1071,"style":1551},[25,2831,2833],{"id":2832},"common-pitfalls","Common pitfalls",[2835,2836,2837,2845,2851,2857,2863],"ul",{},[2838,2839,2840,2844],"li",{},[2841,2842,2843],"strong",{},"Selecting by today's date."," Use the next run date, or invoices due in between are paid late.",[2838,2846,2847,2850],{},[2841,2848,2849],{},"Missing discounts."," Compute each invoice's discount deadline and compare it with the next run.",[2838,2852,2853,2856],{},[2841,2854,2855],{},"Forgetting credit notes."," Net them against the supplier's invoices.",[2838,2858,2859,2862],{},[2841,2860,2861],{},"Paying disputed invoices."," Respect the on-hold flag and show the exclusions.",[2838,2864,2865,2868],{},[2841,2866,2867],{},"Dropping lines silently at the cash limit."," Flag them for the approver.",[25,2870,2872],{"id":2871},"conclusion","Conclusion",[10,2874,2875],{},"A payment run proposal selects every invoice that would be late or lose its discount if left to the next run, excludes held invoices and suppliers without bank details with the reason recorded, nets credit notes per supplier and fits the result to the cash available in due-date order. Writing proposal, lines, exclusions and an approval sheet into one workbook — with formula totals the approver can adjust — gives finance a run they can check and sign off in minutes.",[25,2877,2879],{"id":2878},"frequently-asked-questions","Frequently asked questions",[10,2881,2882,2885],{},[2841,2883,2884],{},"Which invoices should go into a payment run?","\nInvoices due before the next run date, invoices whose early-payment discount expires before the next run, and the supplier's credit notes, excluding held invoices and suppliers without verified bank details.",[10,2887,2888,2891],{},[2841,2889,2890],{},"How do I calculate an early-payment discount deadline in pandas?","\nParse terms such as 2\u002F10 net 30 into a percentage and a number of days, and add the days to each invoice date.",[10,2893,2894,2897],{},[2841,2895,2896],{},"How should credit notes be handled in a payment run?","\nInclude them as negative lines and total per supplier, so the payment is reduced by the credit.",[10,2899,2900,2903],{},[2841,2901,2902],{},"What if the payment run exceeds the cash available?","\nSort suppliers by priority, usually earliest due date, take the cumulative total and flag those beyond the limit for the approver to decide.",[25,2905,2907],{"id":2906},"related","Related",[2835,2909,2910,2916,2923,2930],{},[2838,2911,2912,2913,2915],{},"Up one level: ",[19,2914,22],{"href":21}," — finance reports from Python.",[2838,2917,2918,2922],{},[19,2919,2921],{"href":2920},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report\u002F","Build an Accounts Receivable Aging Report"," — the customer side of the ledger.",[2838,2924,2925,2929],{},[19,2926,2928],{"href":2927},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-cash-flow-forecast-report\u002F","Build a Cash Flow Forecast Report"," — planning the cash the run uses.",[2838,2931,2932,2936],{},[19,2933,2935],{"href":2934},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-credit-control-dunning-letter-run\u002F","Build a Credit Control Dunning Letter Run"," — chasing what customers owe.",[2938,2939,2940],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .s_b0D, html code.shiki .s_b0D{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":35,"searchDepth":84,"depth":84,"links":2942},[2943,2944,2945,2946,2947,2948,2949,2950,2951],{"id":27,"depth":84,"text":28},{"id":63,"depth":84,"text":64},{"id":537,"depth":84,"text":538},{"id":1194,"depth":84,"text":1195},{"id":1640,"depth":84,"text":1641},{"id":2832,"depth":84,"text":2833},{"id":2871,"depth":84,"text":2872},{"id":2878,"depth":84,"text":2879},{"id":2906,"depth":84,"text":2907},"2026-10-02","Turn an open accounts payable listing into a payment run proposal workbook with pandas and openpyxl: select invoices due before the next run, take early-payment discounts that are still available, net off credit notes per supplier, hold back disputed invoices and suppliers without bank details, fit the run to the cash available, and lay out proposal, detail, exclusions and approval sheets.","md",[2956,2958,2960,2962],{"q":2884,"a":2957},"Invoices due before the next run date, invoices whose early-payment discount expires before the next run, and the supplier's credit notes, excluding held invoices and suppliers without verified bank details.",{"q":2890,"a":2959},"Parse terms such as 2\u002F10 net 30 into a percentage and a number of days, and add the days to each invoice date.",{"q":2896,"a":2961},"Include them as negative lines and total per supplier, so the payment is reduced by the credit.",{"q":2902,"a":2963},"Sort suppliers by priority, usually earliest due date, take the cumulative total and flag those beyond the limit for the approver to decide.","supplier payment run proposal",null,{"breadcrumb":2967},[2968,2970,2973],{"name":2969,"item":248},"Home",{"name":2971,"item":2972},"Automating Reporting Workflows with Python and Excel","\u002Fautomating-reporting-workflows\u002F",{"name":2974,"item":21},"Building Finance and Operations Reports in Excel with Python","\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal",{"title":2977,"description":2978},"Build a Supplier Payment Run Proposal in Excel with Python","Accounts payable payment run proposal from Excel data: due-date window, early-payment discounts, credit note netting, holds and missing bank details, a cash limit, and an approval-ready workbook.","build-a-supplier-payment-run-proposal","automating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-payment-run-proposal\u002Findex",[2982],"report-layouts","how-to","untiLgEdkmVM2cbOUlNmr1LX4lHQ0MD62-WTnmvD5ds",[2986,2990],{"title":2987,"path":2988,"stem":2989,"children":-1},"Build a Staff Utilisation Report from Timesheets","\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-staff-utilisation-report-from-timesheets","automating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-staff-utilisation-report-from-timesheets\u002Findex",{"title":2991,"path":2992,"stem":2993,"children":-1},"Build a Supplier Scorecard","\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-scorecard","automating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-supplier-scorecard\u002Findex",[2995,2997],{"path":2996,"title":2974},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports",{"path":2998,"title":2971},"\u002Fautomating-reporting-workflows",[],[3001,3005,3008,3011,3014,3017],{"path":3002,"title":3003,"kind":3004},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards","Building Multi-Sheet Excel Dashboards","guide",{"path":3006,"title":3007,"kind":2983},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-a-data-dictionary-sheet-to-an-excel-report","Add a Data Dictionary Sheet to an Excel Report",{"path":3009,"title":3010,"kind":2983},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-a-kpi-summary-block-to-an-excel-dashboard","Add a KPI Summary Block to an Excel Dashboard",{"path":3012,"title":3013,"kind":2983},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-a-table-of-contents-sheet-with-hyperlinks-in-excel","Add a Table of Contents Sheet with Hyperlinks in Excel",{"path":3015,"title":3016,"kind":2983},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-slicer-style-filters-to-an-excel-dashboard","Add a Dropdown Filter That Drives an Excel Dashboard",{"path":3018,"title":3019,"kind":2983},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-summary-sheet-to-excel-report-python","Add a Summary Sheet to an Excel Report with Python",1790972127307]