[{"data":1,"prerenderedAt":2500},["ShallowReactive",2],{"doc:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report":3,"surround:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report":2465,"ancestors:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report":2474,"children:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report":2479,"related:\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report":2480},{"id":4,"title":5,"body":6,"dateModified":2429,"datePublished":2429,"description":2430,"extension":2431,"faq":2432,"keyword":2441,"kind":2442,"meta":2443,"navigation":250,"path":2453,"seo":2454,"slug":2457,"stem":2458,"topics":2459,"type":2463,"__hash__":2464},"docs\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report\u002Findex.md","Build an Accounts Receivable Aging Report with Python",{"type":7,"value":8,"toc":2416},"minimark",[9,19,164,169,200,210,214,222,492,495,499,505,659,667,671,678,846,849,1173,1177,1180,1417,1420,1423,1514,1518,1521,2268,2275,2279,2322,2326,2334,2338,2347,2351,2357,2367,2373,2379,2383,2412],[10,11,12,13,18],"p",{},"The aged receivables report answers the question credit control asks every week and finance asks every month end: who owes us money, and how late is it? It takes every open invoice, works out how far past its due date it is as at a chosen date, sorts the outstanding amounts into buckets — current, 1–30 days, 31–60, 61–90, over 90 — and totals them per customer. The export from the accounting system has everything needed; the work is in getting the as-at date, the buckets, the credit notes and the tie-out right. This page is part of ",[14,15,17],"a",{"href":16},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002F","Building Finance and Operations Reports",", which covers the shared pipeline.",[20,21,29,30,29,34,29,38,29,46,29,54,29,64,29,71,29,76,29,80,29,84,29,90,29,96,29,100,29,104,29,106,29,108,29,113,29,119,29,123,29,125,29,127,29,129,29,132,29,136,29,139,29,141,29,143,29,145,29,150,29,155,29,158,29,160,29,162],"svg",{"viewBox":22,"role":23,"ariaLabelledBy":24,"xmlns":27,"style":28},"4 0 752 245","img",[25,26],"ar-buckets-t","ar-buckets-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  ",[31,32,33],"title",{"id":25},"Aging buckets measured back from the as-at date",[35,36,37],"desc",{"id":26},"A timeline of aging buckets relative to the due date, as at 30 September 2026. Current means not yet due. 1 to 30 days past due, 31 to 60, 61 to 90, and more than 90 days past due. An invoice due on 4 September is 26 days past due and falls in 1 to 30. One due on 29 June is 93 days past due and falls in 90 plus.",[39,40],"rect",{"x":41,"y":42,"width":43,"height":44,"fill":45},"4","0","752","245","#ffffff",[47,48],"line",{"x1":49,"y1":50,"x2":51,"y2":50,"stroke":52,"style":53},"76.0","122.5","684.0","var(--muted,#5b6780)","stroke-width:2.5px",[39,55],{"x":56,"y":57,"width":58,"height":59,"rx":60,"fill":61,"stroke":62,"style":63},"20.0","16.0","136.0","74.5","12","#d9f4f1","var(--teal,#0f9488)","stroke-width:2px",[65,66,70],"text",{"x":67,"y":68,"style":69},"88.0","49.0","font-size:12.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Current",[65,72,75],{"x":67,"y":73,"style":74},"67.5","font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","not yet due",[47,77],{"x1":67,"y1":78,"x2":67,"y2":50,"stroke":52,"style":79},"90.5","stroke-width:1.5px",[81,82],"circle",{"cx":67,"cy":50,"r":83,"fill":62,"stroke":45,"style":63},"7.0",[39,85],{"x":86,"y":87,"width":58,"height":59,"rx":60,"fill":88,"stroke":89,"style":63},"166.0","154.5","#f0f4ff","var(--brand,#5b5cf0)",[65,91,95],{"x":92,"y":93,"style":94},"234.0","179.0","font-size:12.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","1–30",[65,97,99],{"x":92,"y":98,"style":74},"197.5","due 4 Sep → 26",[65,101,103],{"x":92,"y":102,"style":74},"214.5","days",[47,105],{"x1":92,"y1":50,"x2":92,"y2":87,"stroke":52,"style":79},[81,107],{"cx":92,"cy":50,"r":83,"fill":89,"stroke":45,"style":63},[39,109],{"x":110,"y":57,"width":58,"height":59,"rx":60,"fill":111,"stroke":112,"style":63},"312.0","#fdefd8","var(--gold,#b4740a)",[65,114,118],{"x":115,"y":116,"style":117},"380.0","40.5","font-size:12.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","31–60",[65,120,122],{"x":115,"y":121,"style":74},"59.0","due 24 Aug → 37",[65,124,103],{"x":115,"y":49,"style":74},[47,126],{"x1":115,"y1":78,"x2":115,"y2":50,"stroke":52,"style":79},[81,128],{"cx":115,"cy":50,"r":83,"fill":112,"stroke":45,"style":63},[39,130],{"x":131,"y":87,"width":58,"height":59,"rx":60,"fill":111,"stroke":112,"style":63},"458.0",[65,133,135],{"x":134,"y":93,"style":117},"526.0","61–90",[65,137,138],{"x":134,"y":98,"style":74},"due 20 Jul → 72",[65,140,103],{"x":134,"y":102,"style":74},[47,142],{"x1":134,"y1":50,"x2":134,"y2":87,"stroke":52,"style":79},[81,144],{"cx":134,"cy":50,"r":83,"fill":112,"stroke":45,"style":63},[39,146],{"x":147,"y":57,"width":58,"height":59,"rx":60,"fill":148,"stroke":149,"style":63},"604.0","#fee8f2","var(--accent,#f43f8f)",[65,151,154],{"x":152,"y":116,"style":153},"672.0","font-size:12.5px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","90+",[65,156,157],{"x":152,"y":121,"style":74},"due 29 Jun → 93",[65,159,103],{"x":152,"y":49,"style":74},[47,161],{"x1":152,"y1":78,"x2":152,"y2":50,"stroke":52,"style":79},[81,163],{"cx":152,"cy":50,"r":83,"fill":149,"stroke":45,"style":63},[165,166,168],"h2",{"id":167},"prerequisites","Prerequisites",[170,171,176],"pre",{"className":172,"code":173,"language":174,"meta":175,"style":175},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl xlsxwriter\n","bash","",[177,178,179],"code",{"__ignoreMap":175},[180,181,183,187,191,194,197],"span",{"class":47,"line":182},1,[180,184,186],{"class":185},"sMTad","pip",[180,188,190],{"class":189},"srMev"," install",[180,192,193],{"class":189}," pandas",[180,195,196],{"class":189}," openpyxl",[180,198,199],{"class":189}," xlsxwriter\n",[10,201,202,205,206,209],{},[177,203,204],{},"open_items.xlsx"," is an open-items export: one row per document with the customer, document and due dates, the original amount and the amount paid so far. It includes a partly paid invoice, a fully paid one the export still lists, a credit note, an unapplied payment and an invoice dated after the period end. ",[177,207,208],{},"credit_limits.xlsx"," has each customer's credit limit.",[165,211,213],{"id":212},"step-1-work-out-the-outstanding-amount-and-days-past-due","Step 1 — Work out the outstanding amount and days past due",[10,215,216,217,221],{},"The balance still owed on each document is its amount less what has been paid. Days past due is measured from the ",[218,219,220],"strong",{},"as-at date"," — the period end — not from today, so the September aging gives the same answer whenever it is run:",[170,223,227],{"className":224,"code":225,"language":226,"meta":175,"style":175},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\nas_at = pd.Timestamp(\"2026-09-30\")\nitems = pd.read_excel(\"open_items.xlsx\", parse_dates=[\"Doc Date\", \"Due Date\"])\nitems[\"Outstanding\"] = items[\"Amount\"] - items[\"Paid\"]\n\nafter = items[items[\"Doc Date\"] > as_at]\nitems = items[(items[\"Doc Date\"] \u003C= as_at) & (items[\"Outstanding\"] != 0)].copy()\nitems[\"Days past due\"] = (as_at - items[\"Due Date\"]).dt.days\nprint(\"excluded, dated after as-at:\", after[\"Document\"].tolist())\nprint(items[[\"Document\", \"Customer\", \"Due Date\", \"Outstanding\", \"Days past due\"]].to_string(index=False))\n","python",[177,228,229,245,252,270,307,340,345,366,406,430,451],{"__ignoreMap":175},[180,230,231,235,239,242],{"class":47,"line":182},[180,232,234],{"class":233},"s-kum","import",[180,236,238],{"class":237},"skGVy"," pandas ",[180,240,241],{"class":233},"as",[180,243,244],{"class":237}," pd\n",[180,246,248],{"class":47,"line":247},2,[180,249,251],{"emptyLinePlaceholder":250},true,"\n",[180,253,255,258,261,264,267],{"class":47,"line":254},3,[180,256,257],{"class":237},"as_at ",[180,259,260],{"class":233},"=",[180,262,263],{"class":237}," pd.Timestamp(",[180,265,266],{"class":189},"\"2026-09-30\"",[180,268,269],{"class":237},")\n",[180,271,273,276,278,281,284,287,291,293,296,299,301,304],{"class":47,"line":272},4,[180,274,275],{"class":237},"items ",[180,277,260],{"class":233},[180,279,280],{"class":237}," pd.read_excel(",[180,282,283],{"class":189},"\"open_items.xlsx\"",[180,285,286],{"class":237},", ",[180,288,290],{"class":289},"sa561","parse_dates",[180,292,260],{"class":233},[180,294,295],{"class":237},"[",[180,297,298],{"class":189},"\"Doc Date\"",[180,300,286],{"class":237},[180,302,303],{"class":189},"\"Due Date\"",[180,305,306],{"class":237},"])\n",[180,308,310,313,316,319,321,324,327,329,332,334,337],{"class":47,"line":309},5,[180,311,312],{"class":237},"items[",[180,314,315],{"class":189},"\"Outstanding\"",[180,317,318],{"class":237},"] ",[180,320,260],{"class":233},[180,322,323],{"class":237}," items[",[180,325,326],{"class":189},"\"Amount\"",[180,328,318],{"class":237},[180,330,331],{"class":233},"-",[180,333,323],{"class":237},[180,335,336],{"class":189},"\"Paid\"",[180,338,339],{"class":237},"]\n",[180,341,343],{"class":47,"line":342},6,[180,344,251],{"emptyLinePlaceholder":250},[180,346,348,351,353,356,358,360,363],{"class":47,"line":347},7,[180,349,350],{"class":237},"after ",[180,352,260],{"class":233},[180,354,355],{"class":237}," items[items[",[180,357,298],{"class":189},[180,359,318],{"class":237},[180,361,362],{"class":233},">",[180,364,365],{"class":237}," as_at]\n",[180,367,369,371,373,376,378,380,383,386,389,392,394,396,399,403],{"class":47,"line":368},8,[180,370,275],{"class":237},[180,372,260],{"class":233},[180,374,375],{"class":237}," items[(items[",[180,377,298],{"class":189},[180,379,318],{"class":237},[180,381,382],{"class":233},"\u003C=",[180,384,385],{"class":237}," as_at) ",[180,387,388],{"class":233},"&",[180,390,391],{"class":237}," (items[",[180,393,315],{"class":189},[180,395,318],{"class":237},[180,397,398],{"class":233},"!=",[180,400,402],{"class":401},"sP0c6"," 0",[180,404,405],{"class":237},")].copy()\n",[180,407,409,411,414,416,418,421,423,425,427],{"class":47,"line":408},9,[180,410,312],{"class":237},[180,412,413],{"class":189},"\"Days past due\"",[180,415,318],{"class":237},[180,417,260],{"class":233},[180,419,420],{"class":237}," (as_at ",[180,422,331],{"class":233},[180,424,323],{"class":237},[180,426,303],{"class":189},[180,428,429],{"class":237},"]).dt.days\n",[180,431,433,436,439,442,445,448],{"class":47,"line":432},10,[180,434,435],{"class":401},"print",[180,437,438],{"class":237},"(",[180,440,441],{"class":189},"\"excluded, dated after as-at:\"",[180,443,444],{"class":237},", after[",[180,446,447],{"class":189},"\"Document\"",[180,449,450],{"class":237},"].tolist())\n",[180,452,454,456,459,461,463,466,468,470,472,474,476,478,481,484,486,489],{"class":47,"line":453},11,[180,455,435],{"class":401},[180,457,458],{"class":237},"(items[[",[180,460,447],{"class":189},[180,462,286],{"class":237},[180,464,465],{"class":189},"\"Customer\"",[180,467,286],{"class":237},[180,469,303],{"class":189},[180,471,286],{"class":237},[180,473,315],{"class":189},[180,475,286],{"class":237},[180,477,413],{"class":189},[180,479,480],{"class":237},"]].to_string(",[180,482,483],{"class":289},"index",[180,485,260],{"class":233},[180,487,488],{"class":401},"False",[180,490,491],{"class":237},"))\n",[10,493,494],{},"INV-2230 is dated 2 October, after the as-at date, so it was not owed on 30 September and is excluded. INV-2160 has been paid in full; exports often keep such documents until the payment is matched, and they drop out here because nothing is outstanding. A negative days-past-due figure means the invoice is not due yet.",[165,496,498],{"id":497},"step-2-put-each-balance-in-a-bucket","Step 2 — Put each balance in a bucket",[10,500,501,504],{},[177,502,503],{},"pd.cut"," assigns every document to a bucket from its days past due. The edges are inclusive on the right, which matches how aging is normally defined — exactly 30 days is still \"1–30\":",[170,506,508],{"className":224,"code":507,"language":226,"meta":175,"style":175},"edges = [float(\"-inf\"), 0, 30, 60, 90, float(\"inf\")]\nbuckets = [\"Current\", \"1-30\", \"31-60\", \"61-90\", \"90+\"]\nitems[\"Bucket\"] = pd.cut(items[\"Days past due\"], bins=edges, labels=buckets)\nprint(items[[\"Document\", \"Days past due\", \"Bucket\", \"Outstanding\"]].to_string(index=False))\n",[177,509,510,560,594,629],{"__ignoreMap":175},[180,511,512,515,517,520,523,525,528,531,533,535,538,540,543,545,548,550,552,554,557],{"class":47,"line":182},[180,513,514],{"class":237},"edges ",[180,516,260],{"class":233},[180,518,519],{"class":237}," [",[180,521,522],{"class":401},"float",[180,524,438],{"class":237},[180,526,527],{"class":189},"\"-inf\"",[180,529,530],{"class":237},"), ",[180,532,42],{"class":401},[180,534,286],{"class":237},[180,536,537],{"class":401},"30",[180,539,286],{"class":237},[180,541,542],{"class":401},"60",[180,544,286],{"class":237},[180,546,547],{"class":401},"90",[180,549,286],{"class":237},[180,551,522],{"class":401},[180,553,438],{"class":237},[180,555,556],{"class":189},"\"inf\"",[180,558,559],{"class":237},")]\n",[180,561,562,565,567,569,572,574,577,579,582,584,587,589,592],{"class":47,"line":247},[180,563,564],{"class":237},"buckets ",[180,566,260],{"class":233},[180,568,519],{"class":237},[180,570,571],{"class":189},"\"Current\"",[180,573,286],{"class":237},[180,575,576],{"class":189},"\"1-30\"",[180,578,286],{"class":237},[180,580,581],{"class":189},"\"31-60\"",[180,583,286],{"class":237},[180,585,586],{"class":189},"\"61-90\"",[180,588,286],{"class":237},[180,590,591],{"class":189},"\"90+\"",[180,593,339],{"class":237},[180,595,596,598,601,603,605,608,610,613,616,618,621,624,626],{"class":47,"line":254},[180,597,312],{"class":237},[180,599,600],{"class":189},"\"Bucket\"",[180,602,318],{"class":237},[180,604,260],{"class":233},[180,606,607],{"class":237}," pd.cut(items[",[180,609,413],{"class":189},[180,611,612],{"class":237},"], ",[180,614,615],{"class":289},"bins",[180,617,260],{"class":233},[180,619,620],{"class":237},"edges, ",[180,622,623],{"class":289},"labels",[180,625,260],{"class":233},[180,627,628],{"class":237},"buckets)\n",[180,630,631,633,635,637,639,641,643,645,647,649,651,653,655,657],{"class":47,"line":272},[180,632,435],{"class":401},[180,634,458],{"class":237},[180,636,447],{"class":189},[180,638,286],{"class":237},[180,640,413],{"class":189},[180,642,286],{"class":237},[180,644,600],{"class":189},[180,646,286],{"class":237},[180,648,315],{"class":189},[180,650,480],{"class":237},[180,652,483],{"class":289},[180,654,260],{"class":233},[180,656,488],{"class":401},[180,658,491],{"class":237},[10,660,661,662,666],{},"The credit note CN-0041 and the unapplied payment PAY-0917 are aged by their own dates like any other document, so they appear as negative amounts in the 1–30 bucket and reduce the customer's balance there. Some teams prefer a separate \"Unapplied\" column for them; the choice matters less than applying it consistently, because the customer total is the same either way. ",[14,663,665],{"href":664},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fbin-values-into-ranges-with-pandas-cut\u002F","Bin Values into Ranges with pandas cut"," explains the edge rules in detail.",[165,668,670],{"id":669},"step-3-pivot-to-one-row-per-customer","Step 3 — Pivot to one row per customer",[10,672,673,674,677],{},"The report itself is a pivot: customers down the side, buckets across the top, the outstanding amount in the cells. ",[177,675,676],{},"observed=False"," keeps every bucket as a column even if no customer has anything in it, so the layout is the same every month:",[170,679,681],{"className":224,"code":680,"language":226,"meta":175,"style":175},"aging = items.pivot_table(index=\"Customer\", columns=\"Bucket\", values=\"Outstanding\", aggfunc=\"sum\",\n                          fill_value=0, observed=False)\naging.columns = aging.columns.astype(str)\naging[\"Total\"] = aging.sum(axis=1)\naging[\"Over 60\"] = aging[\"61-90\"] + aging[\"90+\"]\naging = aging.sort_values(\"Total\", ascending=False)\nprint(aging.to_string())\n",[177,682,683,730,750,765,790,817,839],{"__ignoreMap":175},[180,684,685,688,690,693,695,697,699,701,704,706,708,710,713,715,717,719,722,724,727],{"class":47,"line":182},[180,686,687],{"class":237},"aging ",[180,689,260],{"class":233},[180,691,692],{"class":237}," items.pivot_table(",[180,694,483],{"class":289},[180,696,260],{"class":233},[180,698,465],{"class":189},[180,700,286],{"class":237},[180,702,703],{"class":289},"columns",[180,705,260],{"class":233},[180,707,600],{"class":189},[180,709,286],{"class":237},[180,711,712],{"class":289},"values",[180,714,260],{"class":233},[180,716,315],{"class":189},[180,718,286],{"class":237},[180,720,721],{"class":289},"aggfunc",[180,723,260],{"class":233},[180,725,726],{"class":189},"\"sum\"",[180,728,729],{"class":237},",\n",[180,731,732,735,737,739,741,744,746,748],{"class":47,"line":247},[180,733,734],{"class":289},"                          fill_value",[180,736,260],{"class":233},[180,738,42],{"class":401},[180,740,286],{"class":237},[180,742,743],{"class":289},"observed",[180,745,260],{"class":233},[180,747,488],{"class":401},[180,749,269],{"class":237},[180,751,752,755,757,760,763],{"class":47,"line":254},[180,753,754],{"class":237},"aging.columns ",[180,756,260],{"class":233},[180,758,759],{"class":237}," aging.columns.astype(",[180,761,762],{"class":401},"str",[180,764,269],{"class":237},[180,766,767,770,773,775,777,780,783,785,788],{"class":47,"line":272},[180,768,769],{"class":237},"aging[",[180,771,772],{"class":189},"\"Total\"",[180,774,318],{"class":237},[180,776,260],{"class":233},[180,778,779],{"class":237}," aging.sum(",[180,781,782],{"class":289},"axis",[180,784,260],{"class":233},[180,786,787],{"class":401},"1",[180,789,269],{"class":237},[180,791,792,794,797,799,801,804,806,808,811,813,815],{"class":47,"line":309},[180,793,769],{"class":237},[180,795,796],{"class":189},"\"Over 60\"",[180,798,318],{"class":237},[180,800,260],{"class":233},[180,802,803],{"class":237}," aging[",[180,805,586],{"class":189},[180,807,318],{"class":237},[180,809,810],{"class":233},"+",[180,812,803],{"class":237},[180,814,591],{"class":189},[180,816,339],{"class":237},[180,818,819,821,823,826,828,830,833,835,837],{"class":47,"line":342},[180,820,687],{"class":237},[180,822,260],{"class":233},[180,824,825],{"class":237}," aging.sort_values(",[180,827,772],{"class":189},[180,829,286],{"class":237},[180,831,832],{"class":289},"ascending",[180,834,260],{"class":233},[180,836,488],{"class":401},[180,838,269],{"class":237},[180,840,841,843],{"class":47,"line":347},[180,842,435],{"class":401},[180,844,845],{"class":237},"(aging.to_string())\n",[10,847,848],{},"Sorting by total puts the largest exposures first, which is how credit controllers read the list. The \"Over 60\" column is a common extra: it is the figure most collection policies act on.",[20,850,29,856,29,859,29,862,29,867,29,872,29,881,29,885,29,891,29,895,29,899,29,903,29,907,29,911,29,915,29,919,29,923,29,927,29,931,29,935,29,939,29,943,29,947,29,949,29,953,29,955,29,957,29,959,29,962,29,964,29,967,29,969,29,972,29,974,29,976,29,978,29,981,29,984,29,988,29,990,29,994,29,996,29,999,29,1001,29,1004,29,1006,29,1008,29,1010,29,1014,29,1016,29,1018,29,1020,29,1023,29,1026,29,1030,29,1032,29,1035,29,1037,29,1040,29,1042,29,1044,29,1046,29,1048,29,1050,29,1052,29,1054,29,1056,29,1058,29,1060,29,1063,29,1066,29,1068,29,1072,29,1074,29,1076,29,1078,29,1080,29,1082,29,1085,29,1087,29,1089,29,1091,29,1094,29,1096,29,1099,29,1102,29,1106,29,1108,29,1111,29,1113,29,1116,29,1118,29,1120,29,1122,29,1124,29,1126,29,1128,29,1130,29,1132,29,1134,29,1136,29,1139,29,1143,29,1145,29,1148,29,1150,29,1152,29,1154,29,1157,29,1159,29,1161,29,1163,29,1165,29,1167,29,1169,29,1171],{"viewBox":851,"role":23,"ariaLabelledBy":852,"xmlns":27,"style":855},"114 0 531 256",[853,854],"ar-pivot-t","ar-pivot-d","width:100%;max-width:531px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[31,857,858],{"id":853},"The aging as at 30 September 2026",[35,860,861],{"id":854},"One row per customer with outstanding balances by bucket. Acme Ltd has 8,400 current, 2,600 in 1 to 30, 3,100 in 61 to 90, total 14,100. Dunmore has 12,500 current. Corex has 6,900 in 31 to 60 and 1,800 over 90, total 8,700, over its credit limit of 5,000. Brightside has 2,750 current. Eastfield has an unapplied payment of minus 950.",[39,863],{"x":864,"y":42,"width":865,"height":866,"fill":45},"114","531","256",[65,868,871],{"x":115,"y":869,"style":870},"31.0","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","AR aging — as at 30 Sep 2026",[39,873],{"x":874,"y":875,"width":876,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"130.6","48.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[39,882],{"x":883,"y":875,"width":884,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"162.6","87.2",[65,886,890],{"x":887,"y":888,"style":889},"206.2","65.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[39,892],{"x":893,"y":875,"width":894,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"249.8","71.4",[65,896,898],{"x":897,"y":888,"style":889},"285.5","B",[39,900],{"x":901,"y":875,"width":902,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"321.2","61.3",[65,904,906],{"x":905,"y":888,"style":889},"351.8","C",[39,908],{"x":909,"y":875,"width":910,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"382.5","61.5",[65,912,914],{"x":913,"y":888,"style":889},"413.3","D",[39,916],{"x":917,"y":875,"width":918,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"444.0","60.2",[65,920,922],{"x":921,"y":888,"style":889},"474.1","E",[39,924],{"x":925,"y":875,"width":926,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"504.2","58.8",[65,928,930],{"x":929,"y":888,"style":889},"533.6","F",[39,932],{"x":933,"y":875,"width":934,"height":877,"rx":42,"fill":878,"stroke":879,"style":880},"563.0","66.4",[65,936,938],{"x":937,"y":888,"style":889},"596.2","G",[39,940],{"x":874,"y":941,"width":876,"height":942,"rx":42,"fill":878,"stroke":879,"style":880},"72.0","28.0",[65,944,787],{"x":945,"y":946,"style":889},"146.6","91.0",[39,948],{"x":883,"y":941,"width":884,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,950,952],{"x":887,"y":946,"style":951},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Customer",[39,954],{"x":893,"y":941,"width":894,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,956,70],{"x":897,"y":946,"style":951},[39,958],{"x":901,"y":941,"width":902,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,960,961],{"x":905,"y":946,"style":951},"1-30",[39,963],{"x":909,"y":941,"width":910,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,965,966],{"x":913,"y":946,"style":951},"31-60",[39,968],{"x":917,"y":941,"width":918,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,970,971],{"x":921,"y":946,"style":951},"61-90",[39,973],{"x":925,"y":941,"width":926,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,975,154],{"x":929,"y":946,"style":951},[39,977],{"x":933,"y":941,"width":934,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,979,980],{"x":937,"y":946,"style":951},"Total",[39,982],{"x":874,"y":983,"width":876,"height":942,"rx":42,"fill":878,"stroke":879,"style":880},"100.0",[65,985,987],{"x":945,"y":986,"style":889},"119.0","2",[39,989],{"x":883,"y":983,"width":884,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,991,993],{"x":887,"y":986,"style":992},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","Acme Ltd",[39,995],{"x":893,"y":983,"width":894,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,997,998],{"x":897,"y":986,"style":992},"8,400",[39,1000],{"x":901,"y":983,"width":902,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1002,1003],{"x":905,"y":986,"style":992},"2,600",[39,1005],{"x":909,"y":983,"width":910,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1007,42],{"x":913,"y":986,"style":992},[39,1009],{"x":917,"y":983,"width":918,"height":942,"rx":42,"fill":111,"stroke":112,"style":79},[65,1011,1013],{"x":921,"y":986,"style":1012},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","3,100",[39,1015],{"x":925,"y":983,"width":926,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1017,42],{"x":929,"y":986,"style":992},[39,1019],{"x":933,"y":983,"width":934,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1021,1022],{"x":937,"y":986,"style":992},"14,100",[39,1024],{"x":874,"y":1025,"width":876,"height":942,"rx":42,"fill":878,"stroke":879,"style":880},"128.0",[65,1027,1029],{"x":945,"y":1028,"style":889},"147.0","3",[39,1031],{"x":883,"y":1025,"width":884,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1033,1034],{"x":887,"y":1028,"style":992},"Dunmore",[39,1036],{"x":893,"y":1025,"width":894,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1038,1039],{"x":897,"y":1028,"style":992},"12,500",[39,1041],{"x":901,"y":1025,"width":902,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1043,42],{"x":905,"y":1028,"style":992},[39,1045],{"x":909,"y":1025,"width":910,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1047,42],{"x":913,"y":1028,"style":992},[39,1049],{"x":917,"y":1025,"width":918,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1051,42],{"x":921,"y":1028,"style":992},[39,1053],{"x":925,"y":1025,"width":926,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1055,42],{"x":929,"y":1028,"style":992},[39,1057],{"x":933,"y":1025,"width":934,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1059,1039],{"x":937,"y":1028,"style":992},[39,1061],{"x":874,"y":1062,"width":876,"height":942,"rx":42,"fill":878,"stroke":879,"style":880},"156.0",[65,1064,41],{"x":945,"y":1065,"style":889},"175.0",[39,1067],{"x":883,"y":1062,"width":884,"height":942,"rx":42,"fill":148,"stroke":149,"style":79},[65,1069,1071],{"x":887,"y":1065,"style":1070},"font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Corex",[39,1073],{"x":893,"y":1062,"width":894,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1075,42],{"x":897,"y":1065,"style":992},[39,1077],{"x":901,"y":1062,"width":902,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1079,42],{"x":905,"y":1065,"style":992},[39,1081],{"x":909,"y":1062,"width":910,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1083,1084],{"x":913,"y":1065,"style":992},"6,900",[39,1086],{"x":917,"y":1062,"width":918,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1088,42],{"x":921,"y":1065,"style":992},[39,1090],{"x":925,"y":1062,"width":926,"height":942,"rx":42,"fill":148,"stroke":149,"style":79},[65,1092,1093],{"x":929,"y":1065,"style":1070},"1,800",[39,1095],{"x":933,"y":1062,"width":934,"height":942,"rx":42,"fill":148,"stroke":149,"style":79},[65,1097,1098],{"x":937,"y":1065,"style":1070},"8,700",[39,1100],{"x":874,"y":1101,"width":876,"height":942,"rx":42,"fill":878,"stroke":879,"style":880},"184.0",[65,1103,1105],{"x":945,"y":1104,"style":889},"203.0","5",[39,1107],{"x":883,"y":1101,"width":884,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1109,1110],{"x":887,"y":1104,"style":992},"Brightside",[39,1112],{"x":893,"y":1101,"width":894,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1114,1115],{"x":897,"y":1104,"style":992},"2,750",[39,1117],{"x":901,"y":1101,"width":902,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1119,42],{"x":905,"y":1104,"style":992},[39,1121],{"x":909,"y":1101,"width":910,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1123,42],{"x":913,"y":1104,"style":992},[39,1125],{"x":917,"y":1101,"width":918,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1127,42],{"x":921,"y":1104,"style":992},[39,1129],{"x":925,"y":1101,"width":926,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1131,42],{"x":929,"y":1104,"style":992},[39,1133],{"x":933,"y":1101,"width":934,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1135,1115],{"x":937,"y":1104,"style":992},[39,1137],{"x":874,"y":1138,"width":876,"height":942,"rx":42,"fill":878,"stroke":879,"style":880},"212.0",[65,1140,1142],{"x":945,"y":1141,"style":889},"231.0","6",[39,1144],{"x":883,"y":1138,"width":884,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1146,1147],{"x":887,"y":1141,"style":992},"Eastfield",[39,1149],{"x":893,"y":1138,"width":894,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1151,42],{"x":897,"y":1141,"style":992},[39,1153],{"x":901,"y":1138,"width":902,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1155,1156],{"x":905,"y":1141,"style":992},"(950)",[39,1158],{"x":909,"y":1138,"width":910,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1160,42],{"x":913,"y":1141,"style":992},[39,1162],{"x":917,"y":1138,"width":918,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1164,42],{"x":921,"y":1141,"style":992},[39,1166],{"x":925,"y":1138,"width":926,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1168,42],{"x":929,"y":1141,"style":992},[39,1170],{"x":933,"y":1138,"width":934,"height":942,"rx":42,"fill":45,"stroke":879,"style":880},[65,1172,1156],{"x":937,"y":1141,"style":992},[165,1174,1176],{"id":1175},"step-4-flag-credit-limits-and-tie-out-to-the-ledger","Step 4 — Flag credit limits and tie out to the ledger",[10,1178,1179],{},"Join the credit limits and flag customers whose total exceeds theirs. Then prove the aging accounts for the whole receivables balance: its grand total must equal the outstanding total of every document dated on or before the as-at date, which in turn should match the receivables control account in the trial balance:",[170,1181,1183],{"className":224,"code":1182,"language":226,"meta":175,"style":175},"limits = pd.read_excel(\"credit_limits.xlsx\").set_index(\"Customer\")[\"Credit Limit\"]\naging[\"Credit limit\"] = limits.reindex(aging.index)\naging[\"Over limit\"] = aging[\"Total\"] > aging[\"Credit limit\"]\nprint(aging.loc[aging[\"Over limit\"], [\"Total\", \"Credit limit\"]])\n\nraw = pd.read_excel(\"open_items.xlsx\", parse_dates=[\"Doc Date\"])\nledger_balance = (raw.loc[raw[\"Doc Date\"] \u003C= as_at, \"Amount\"] - raw.loc[raw[\"Doc Date\"] \u003C= as_at, \"Paid\"]).sum()\nprint(f\"aging total {aging['Total'].sum():,.2f}  ledger {ledger_balance:,.2f}\")\nassert round(aging[\"Total\"].sum() - ledger_balance, 2) == 0\n",[177,1184,1185,1210,1224,1249,1270,1274,1297,1338,1385],{"__ignoreMap":175},[180,1186,1187,1190,1192,1194,1197,1200,1202,1205,1208],{"class":47,"line":182},[180,1188,1189],{"class":237},"limits ",[180,1191,260],{"class":233},[180,1193,280],{"class":237},[180,1195,1196],{"class":189},"\"credit_limits.xlsx\"",[180,1198,1199],{"class":237},").set_index(",[180,1201,465],{"class":189},[180,1203,1204],{"class":237},")[",[180,1206,1207],{"class":189},"\"Credit Limit\"",[180,1209,339],{"class":237},[180,1211,1212,1214,1217,1219,1221],{"class":47,"line":247},[180,1213,769],{"class":237},[180,1215,1216],{"class":189},"\"Credit limit\"",[180,1218,318],{"class":237},[180,1220,260],{"class":233},[180,1222,1223],{"class":237}," limits.reindex(aging.index)\n",[180,1225,1226,1228,1231,1233,1235,1237,1239,1241,1243,1245,1247],{"class":47,"line":254},[180,1227,769],{"class":237},[180,1229,1230],{"class":189},"\"Over limit\"",[180,1232,318],{"class":237},[180,1234,260],{"class":233},[180,1236,803],{"class":237},[180,1238,772],{"class":189},[180,1240,318],{"class":237},[180,1242,362],{"class":233},[180,1244,803],{"class":237},[180,1246,1216],{"class":189},[180,1248,339],{"class":237},[180,1250,1251,1253,1256,1258,1261,1263,1265,1267],{"class":47,"line":272},[180,1252,435],{"class":401},[180,1254,1255],{"class":237},"(aging.loc[aging[",[180,1257,1230],{"class":189},[180,1259,1260],{"class":237},"], [",[180,1262,772],{"class":189},[180,1264,286],{"class":237},[180,1266,1216],{"class":189},[180,1268,1269],{"class":237},"]])\n",[180,1271,1272],{"class":47,"line":309},[180,1273,251],{"emptyLinePlaceholder":250},[180,1275,1276,1279,1281,1283,1285,1287,1289,1291,1293,1295],{"class":47,"line":342},[180,1277,1278],{"class":237},"raw ",[180,1280,260],{"class":233},[180,1282,280],{"class":237},[180,1284,283],{"class":189},[180,1286,286],{"class":237},[180,1288,290],{"class":289},[180,1290,260],{"class":233},[180,1292,295],{"class":237},[180,1294,298],{"class":189},[180,1296,306],{"class":237},[180,1298,1299,1302,1304,1307,1309,1311,1313,1316,1318,1320,1322,1325,1327,1329,1331,1333,1335],{"class":47,"line":347},[180,1300,1301],{"class":237},"ledger_balance ",[180,1303,260],{"class":233},[180,1305,1306],{"class":237}," (raw.loc[raw[",[180,1308,298],{"class":189},[180,1310,318],{"class":237},[180,1312,382],{"class":233},[180,1314,1315],{"class":237}," as_at, ",[180,1317,326],{"class":189},[180,1319,318],{"class":237},[180,1321,331],{"class":233},[180,1323,1324],{"class":237}," raw.loc[raw[",[180,1326,298],{"class":189},[180,1328,318],{"class":237},[180,1330,382],{"class":233},[180,1332,1315],{"class":237},[180,1334,336],{"class":189},[180,1336,1337],{"class":237},"]).sum()\n",[180,1339,1340,1342,1344,1347,1350,1354,1356,1359,1362,1365,1368,1371,1373,1376,1378,1380,1383],{"class":47,"line":368},[180,1341,435],{"class":401},[180,1343,438],{"class":237},[180,1345,1346],{"class":233},"f",[180,1348,1349],{"class":189},"\"aging total ",[180,1351,1353],{"class":1352},"sSjpA","{",[180,1355,769],{"class":237},[180,1357,1358],{"class":189},"'Total'",[180,1360,1361],{"class":237},"].sum()",[180,1363,1364],{"class":233},":,.2f",[180,1366,1367],{"class":1352},"}",[180,1369,1370],{"class":189},"  ledger ",[180,1372,1353],{"class":1352},[180,1374,1375],{"class":237},"ledger_balance",[180,1377,1364],{"class":233},[180,1379,1367],{"class":1352},[180,1381,1382],{"class":189},"\"",[180,1384,269],{"class":237},[180,1386,1387,1390,1393,1396,1398,1401,1403,1406,1408,1411,1414],{"class":47,"line":408},[180,1388,1389],{"class":233},"assert",[180,1391,1392],{"class":401}," round",[180,1394,1395],{"class":237},"(aging[",[180,1397,772],{"class":189},[180,1399,1400],{"class":237},"].sum() ",[180,1402,331],{"class":233},[180,1404,1405],{"class":237}," ledger_balance, ",[180,1407,987],{"class":401},[180,1409,1410],{"class":237},") ",[180,1412,1413],{"class":233},"==",[180,1415,1416],{"class":401}," 0\n",[10,1418,1419],{},"Corex owes 8,700 against a limit of 5,000, most of it more than a month overdue. The aging total of 37,100 matches the independently computed balance. In practice the comparison figure comes from the trial balance — the receivables control account as at the period end — and a difference means documents are missing from the export, or postings bypassed the sales ledger.",[10,1421,1422],{},"Across all customers, most of the balance is not yet due, but 11,800 — almost a third — is more than 30 days past due:",[20,1424,29,1430,29,1433,29,1436,29,1440,29,1443,29,1447,29,1452,29,1456,29,1461,29,1463,29,1466,29,1469,29,1474,29,1476,29,1479,29,1482,29,1487,29,1490,29,1493,29,1496,29,1500,29,1503,29,1506,29,1509],{"viewBox":1425,"role":23,"ariaLabelledBy":1426,"xmlns":27,"style":1429},"4 0 744 252",[1427,1428],"ar-totals-t","ar-totals-d","width:100%;max-width:744px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[31,1431,1432],{"id":1427},"Receivables by bucket as at 30 September 2026",[35,1434,1435],{"id":1428},"Bar chart of the aging totals across all customers: 23,650 current, 1,650 in 1 to 30 days, 6,900 in 31 to 60, 3,100 in 61 to 90 and 1,800 over 90 days, for a total of 37,100.",[39,1437],{"x":41,"y":42,"width":1438,"height":1439,"fill":45},"744","252",[65,1441,1442],{"x":115,"y":869,"style":870},"Total 37,100",[39,1444],{"x":56,"y":875,"width":1445,"height":942,"rx":1446,"fill":878,"stroke":879,"style":880},"77.4","7",[65,1448,70],{"x":1449,"y":1450,"style":1451},"58.7","66.5","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle",[39,1453],{"x":1454,"y":875,"width":1455,"height":942,"rx":1446,"fill":61,"stroke":62,"style":79},"107.4","576.0",[65,1457,1460],{"x":1458,"y":1450,"style":1459},"691.4","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:start","23650",[39,1462],{"x":56,"y":67,"width":1445,"height":942,"rx":1446,"fill":878,"stroke":879,"style":880},[65,1464,95],{"x":1449,"y":1465,"style":1451},"106.5",[39,1467],{"x":1454,"y":67,"width":1468,"height":942,"rx":1446,"fill":88,"stroke":89,"style":79},"40.2",[65,1470,1473],{"x":1471,"y":1465,"style":1472},"155.6","font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:start","1650",[39,1475],{"x":56,"y":1025,"width":1445,"height":942,"rx":1446,"fill":878,"stroke":879,"style":880},[65,1477,118],{"x":1449,"y":1478,"style":1451},"146.5",[39,1480],{"x":1454,"y":1025,"width":1481,"height":942,"rx":1446,"fill":111,"stroke":112,"style":79},"168.1",[65,1483,1486],{"x":1484,"y":1478,"style":1485},"283.4","font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:start","6900",[39,1488],{"x":56,"y":1489,"width":1445,"height":942,"rx":1446,"fill":878,"stroke":879,"style":880},"168.0",[65,1491,135],{"x":1449,"y":1492,"style":1451},"186.5",[39,1494],{"x":1454,"y":1489,"width":1495,"height":942,"rx":1446,"fill":111,"stroke":112,"style":79},"75.5",[65,1497,1499],{"x":1498,"y":1492,"style":1485},"190.9","3100",[39,1501],{"x":56,"y":1502,"width":1445,"height":942,"rx":1446,"fill":878,"stroke":879,"style":880},"208.0",[65,1504,154],{"x":1449,"y":1505,"style":1451},"226.5",[39,1507],{"x":1454,"y":1502,"width":1508,"height":942,"rx":1446,"fill":148,"stroke":149,"style":79},"43.8",[65,1510,1513],{"x":1511,"y":1505,"style":1512},"159.2","font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:start","1800",[165,1515,1517],{"id":1516},"step-5-write-the-report","Step 5 — Write the report",[10,1519,1520],{},"Write the customer aging with the buckets in order, a totals row, money formats, and the over-limit customers highlighted. Put the invoice-level detail on a second sheet so any balance can be traced to its documents:",[170,1522,1524],{"className":224,"code":1523,"language":226,"meta":175,"style":175},"out = f\"ar_aging_{as_at:%Y-%m-%d}.xlsx\"\ncols = buckets + [\"Total\", \"Over 60\", \"Credit limit\"]\nwith pd.ExcelWriter(out, engine=\"xlsxwriter\") as writer:\n    report = aging[cols].reset_index()\n    report.to_excel(writer, sheet_name=\"Aging\", index=False, startrow=2)\n    wb, ws = writer.book, writer.sheets[\"Aging\"]\n    money = wb.add_format({\"num_format\": \"#,##0;(#,##0);-\"})\n    bold = wb.add_format({\"num_format\": \"#,##0;(#,##0);-\", \"bold\": True, \"top\": 1})\n    ws.write(\"A1\", f\"Aged receivables as at {as_at:%d %B %Y}\", wb.add_format({\"bold\": True, \"font_size\": 14}))\n    total_row = len(report) + 3\n    ws.write(total_row, 0, \"Total\", wb.add_format({\"bold\": True, \"top\": 1}))\n    for c in range(1, len(cols)):\n        col = chr(ord(\"A\") + c)\n        ws.write_formula(total_row, c, f\"=SUM({col}4:{col}{total_row})\", bold)\n    ws.set_column(\"A:A\", 16)\n    ws.set_column(1, len(cols), 11, money)\n    ws.conditional_format(3, 0, total_row - 1, 0, {\"type\": \"formula\", \"criteria\": f\"=$G4>$I4\",\n                          \"format\": wb.add_format({\"bg_color\": \"#FFC7CE\", \"font_color\": \"#9C0006\"})})\n    ws.freeze_panes(3, 1)\n\n    detail = items.sort_values([\"Customer\", \"Due Date\"])[[\"Customer\", \"Document\", \"Doc Date\", \"Due Date\", \"Outstanding\", \"Days past due\", \"Bucket\"]]\n    detail.to_excel(writer, sheet_name=\"Detail\", index=False)\n    writer.sheets[\"Detail\"].set_column(\"A:B\", 14)\n    writer.sheets[\"Detail\"].set_column(\"C:D\", 12, wb.add_format({\"num_format\": \"yyyy-mm-dd\"}))\n    writer.sheets[\"Detail\"].set_column(\"E:E\", 12, money)\n    writer.sheets[\"Detail\"].autofilter(0, 0, len(detail), 6)\n\nprint(pd.ExcelFile(out).sheet_names, \"-\", len(report), \"customers,\", len(detail), \"documents\")\n",[177,1525,1526,1566,1592,1615,1625,1657,1671,1693,1729,1792,1810,1839,1866,1894,1933,1949,1969,2018,2048,2062,2067,2116,2139,2159,2186,2204,2231,2236],{"__ignoreMap":175},[180,1527,1528,1531,1533,1536,1539,1541,1544,1547,1550,1553,1556,1558,1561,1563],{"class":47,"line":182},[180,1529,1530],{"class":237},"out ",[180,1532,260],{"class":233},[180,1534,1535],{"class":233}," f",[180,1537,1538],{"class":189},"\"ar_aging_",[180,1540,1353],{"class":1352},[180,1542,1543],{"class":237},"as_at:",[180,1545,1546],{"class":233},"%",[180,1548,1549],{"class":237},"Y",[180,1551,1552],{"class":233},"-%",[180,1554,1555],{"class":237},"m",[180,1557,1552],{"class":233},[180,1559,1560],{"class":237},"d",[180,1562,1367],{"class":1352},[180,1564,1565],{"class":189},".xlsx\"\n",[180,1567,1568,1571,1573,1576,1578,1580,1582,1584,1586,1588,1590],{"class":47,"line":247},[180,1569,1570],{"class":237},"cols ",[180,1572,260],{"class":233},[180,1574,1575],{"class":237}," buckets ",[180,1577,810],{"class":233},[180,1579,519],{"class":237},[180,1581,772],{"class":189},[180,1583,286],{"class":237},[180,1585,796],{"class":189},[180,1587,286],{"class":237},[180,1589,1216],{"class":189},[180,1591,339],{"class":237},[180,1593,1594,1597,1600,1603,1605,1608,1610,1612],{"class":47,"line":254},[180,1595,1596],{"class":233},"with",[180,1598,1599],{"class":237}," pd.ExcelWriter(out, ",[180,1601,1602],{"class":289},"engine",[180,1604,260],{"class":233},[180,1606,1607],{"class":189},"\"xlsxwriter\"",[180,1609,1410],{"class":237},[180,1611,241],{"class":233},[180,1613,1614],{"class":237}," writer:\n",[180,1616,1617,1620,1622],{"class":47,"line":272},[180,1618,1619],{"class":237},"    report ",[180,1621,260],{"class":233},[180,1623,1624],{"class":237}," aging[cols].reset_index()\n",[180,1626,1627,1630,1633,1635,1638,1640,1642,1644,1646,1648,1651,1653,1655],{"class":47,"line":309},[180,1628,1629],{"class":237},"    report.to_excel(writer, ",[180,1631,1632],{"class":289},"sheet_name",[180,1634,260],{"class":233},[180,1636,1637],{"class":189},"\"Aging\"",[180,1639,286],{"class":237},[180,1641,483],{"class":289},[180,1643,260],{"class":233},[180,1645,488],{"class":401},[180,1647,286],{"class":237},[180,1649,1650],{"class":289},"startrow",[180,1652,260],{"class":233},[180,1654,987],{"class":401},[180,1656,269],{"class":237},[180,1658,1659,1662,1664,1667,1669],{"class":47,"line":342},[180,1660,1661],{"class":237},"    wb, ws ",[180,1663,260],{"class":233},[180,1665,1666],{"class":237}," writer.book, writer.sheets[",[180,1668,1637],{"class":189},[180,1670,339],{"class":237},[180,1672,1673,1676,1678,1681,1684,1687,1690],{"class":47,"line":347},[180,1674,1675],{"class":237},"    money ",[180,1677,260],{"class":233},[180,1679,1680],{"class":237}," wb.add_format({",[180,1682,1683],{"class":189},"\"num_format\"",[180,1685,1686],{"class":237},": ",[180,1688,1689],{"class":189},"\"#,##0;(#,##0);-\"",[180,1691,1692],{"class":237},"})\n",[180,1694,1695,1698,1700,1702,1704,1706,1708,1710,1713,1715,1718,1720,1723,1725,1727],{"class":47,"line":368},[180,1696,1697],{"class":237},"    bold ",[180,1699,260],{"class":233},[180,1701,1680],{"class":237},[180,1703,1683],{"class":189},[180,1705,1686],{"class":237},[180,1707,1689],{"class":189},[180,1709,286],{"class":237},[180,1711,1712],{"class":189},"\"bold\"",[180,1714,1686],{"class":237},[180,1716,1717],{"class":401},"True",[180,1719,286],{"class":237},[180,1721,1722],{"class":189},"\"top\"",[180,1724,1686],{"class":237},[180,1726,787],{"class":401},[180,1728,1692],{"class":237},[180,1730,1731,1734,1737,1739,1741,1744,1746,1749,1752,1754,1757,1759,1762,1764,1766,1768,1770,1773,1775,1777,1779,1781,1784,1786,1789],{"class":47,"line":408},[180,1732,1733],{"class":237},"    ws.write(",[180,1735,1736],{"class":189},"\"A1\"",[180,1738,286],{"class":237},[180,1740,1346],{"class":233},[180,1742,1743],{"class":189},"\"Aged receivables as at ",[180,1745,1353],{"class":1352},[180,1747,1748],{"class":237},"as_at",[180,1750,1751],{"class":233},":",[180,1753,1546],{"class":237},[180,1755,1756],{"class":233},"d ",[180,1758,1546],{"class":237},[180,1760,1761],{"class":233},"B ",[180,1763,1546],{"class":237},[180,1765,1549],{"class":233},[180,1767,1367],{"class":1352},[180,1769,1382],{"class":189},[180,1771,1772],{"class":237},", wb.add_format({",[180,1774,1712],{"class":189},[180,1776,1686],{"class":237},[180,1778,1717],{"class":401},[180,1780,286],{"class":237},[180,1782,1783],{"class":189},"\"font_size\"",[180,1785,1686],{"class":237},[180,1787,1788],{"class":401},"14",[180,1790,1791],{"class":237},"}))\n",[180,1793,1794,1797,1799,1802,1805,1807],{"class":47,"line":432},[180,1795,1796],{"class":237},"    total_row ",[180,1798,260],{"class":233},[180,1800,1801],{"class":401}," len",[180,1803,1804],{"class":237},"(report) ",[180,1806,810],{"class":233},[180,1808,1809],{"class":401}," 3\n",[180,1811,1812,1815,1817,1819,1821,1823,1825,1827,1829,1831,1833,1835,1837],{"class":47,"line":453},[180,1813,1814],{"class":237},"    ws.write(total_row, ",[180,1816,42],{"class":401},[180,1818,286],{"class":237},[180,1820,772],{"class":189},[180,1822,1772],{"class":237},[180,1824,1712],{"class":189},[180,1826,1686],{"class":237},[180,1828,1717],{"class":401},[180,1830,286],{"class":237},[180,1832,1722],{"class":189},[180,1834,1686],{"class":237},[180,1836,787],{"class":401},[180,1838,1791],{"class":237},[180,1840,1842,1845,1848,1851,1854,1856,1858,1860,1863],{"class":47,"line":1841},12,[180,1843,1844],{"class":233},"    for",[180,1846,1847],{"class":237}," c ",[180,1849,1850],{"class":233},"in",[180,1852,1853],{"class":401}," range",[180,1855,438],{"class":237},[180,1857,787],{"class":401},[180,1859,286],{"class":237},[180,1861,1862],{"class":401},"len",[180,1864,1865],{"class":237},"(cols)):\n",[180,1867,1869,1872,1874,1877,1879,1882,1884,1887,1889,1891],{"class":47,"line":1868},13,[180,1870,1871],{"class":237},"        col ",[180,1873,260],{"class":233},[180,1875,1876],{"class":401}," chr",[180,1878,438],{"class":237},[180,1880,1881],{"class":401},"ord",[180,1883,438],{"class":237},[180,1885,1886],{"class":189},"\"A\"",[180,1888,1410],{"class":237},[180,1890,810],{"class":233},[180,1892,1893],{"class":237}," c)\n",[180,1895,1897,1900,1902,1905,1907,1910,1912,1915,1917,1919,1922,1925,1927,1930],{"class":47,"line":1896},14,[180,1898,1899],{"class":237},"        ws.write_formula(total_row, c, ",[180,1901,1346],{"class":233},[180,1903,1904],{"class":189},"\"=SUM(",[180,1906,1353],{"class":1352},[180,1908,1909],{"class":237},"col",[180,1911,1367],{"class":1352},[180,1913,1914],{"class":189},"4:",[180,1916,1353],{"class":1352},[180,1918,1909],{"class":237},[180,1920,1921],{"class":1352},"}{",[180,1923,1924],{"class":237},"total_row",[180,1926,1367],{"class":1352},[180,1928,1929],{"class":189},")\"",[180,1931,1932],{"class":237},", bold)\n",[180,1934,1936,1939,1942,1944,1947],{"class":47,"line":1935},15,[180,1937,1938],{"class":237},"    ws.set_column(",[180,1940,1941],{"class":189},"\"A:A\"",[180,1943,286],{"class":237},[180,1945,1946],{"class":401},"16",[180,1948,269],{"class":237},[180,1950,1952,1954,1956,1958,1960,1963,1966],{"class":47,"line":1951},16,[180,1953,1938],{"class":237},[180,1955,787],{"class":401},[180,1957,286],{"class":237},[180,1959,1862],{"class":401},[180,1961,1962],{"class":237},"(cols), ",[180,1964,1965],{"class":401},"11",[180,1967,1968],{"class":237},", money)\n",[180,1970,1972,1975,1977,1979,1981,1984,1986,1989,1991,1993,1996,1999,2001,2004,2006,2009,2011,2013,2016],{"class":47,"line":1971},17,[180,1973,1974],{"class":237},"    ws.conditional_format(",[180,1976,1029],{"class":401},[180,1978,286],{"class":237},[180,1980,42],{"class":401},[180,1982,1983],{"class":237},", total_row ",[180,1985,331],{"class":233},[180,1987,1988],{"class":401}," 1",[180,1990,286],{"class":237},[180,1992,42],{"class":401},[180,1994,1995],{"class":237},", {",[180,1997,1998],{"class":189},"\"type\"",[180,2000,1686],{"class":237},[180,2002,2003],{"class":189},"\"formula\"",[180,2005,286],{"class":237},[180,2007,2008],{"class":189},"\"criteria\"",[180,2010,1686],{"class":237},[180,2012,1346],{"class":233},[180,2014,2015],{"class":189},"\"=$G4>$I4\"",[180,2017,729],{"class":237},[180,2019,2021,2024,2027,2030,2032,2035,2037,2040,2042,2045],{"class":47,"line":2020},18,[180,2022,2023],{"class":189},"                          \"format\"",[180,2025,2026],{"class":237},": wb.add_format({",[180,2028,2029],{"class":189},"\"bg_color\"",[180,2031,1686],{"class":237},[180,2033,2034],{"class":189},"\"#FFC7CE\"",[180,2036,286],{"class":237},[180,2038,2039],{"class":189},"\"font_color\"",[180,2041,1686],{"class":237},[180,2043,2044],{"class":189},"\"#9C0006\"",[180,2046,2047],{"class":237},"})})\n",[180,2049,2051,2054,2056,2058,2060],{"class":47,"line":2050},19,[180,2052,2053],{"class":237},"    ws.freeze_panes(",[180,2055,1029],{"class":401},[180,2057,286],{"class":237},[180,2059,787],{"class":401},[180,2061,269],{"class":237},[180,2063,2065],{"class":47,"line":2064},20,[180,2066,251],{"emptyLinePlaceholder":250},[180,2068,2070,2073,2075,2078,2080,2082,2084,2087,2089,2091,2093,2095,2097,2099,2101,2103,2105,2107,2109,2111,2113],{"class":47,"line":2069},21,[180,2071,2072],{"class":237},"    detail ",[180,2074,260],{"class":233},[180,2076,2077],{"class":237}," items.sort_values([",[180,2079,465],{"class":189},[180,2081,286],{"class":237},[180,2083,303],{"class":189},[180,2085,2086],{"class":237},"])[[",[180,2088,465],{"class":189},[180,2090,286],{"class":237},[180,2092,447],{"class":189},[180,2094,286],{"class":237},[180,2096,298],{"class":189},[180,2098,286],{"class":237},[180,2100,303],{"class":189},[180,2102,286],{"class":237},[180,2104,315],{"class":189},[180,2106,286],{"class":237},[180,2108,413],{"class":189},[180,2110,286],{"class":237},[180,2112,600],{"class":189},[180,2114,2115],{"class":237},"]]\n",[180,2117,2119,2122,2124,2126,2129,2131,2133,2135,2137],{"class":47,"line":2118},22,[180,2120,2121],{"class":237},"    detail.to_excel(writer, ",[180,2123,1632],{"class":289},[180,2125,260],{"class":233},[180,2127,2128],{"class":189},"\"Detail\"",[180,2130,286],{"class":237},[180,2132,483],{"class":289},[180,2134,260],{"class":233},[180,2136,488],{"class":401},[180,2138,269],{"class":237},[180,2140,2142,2145,2147,2150,2153,2155,2157],{"class":47,"line":2141},23,[180,2143,2144],{"class":237},"    writer.sheets[",[180,2146,2128],{"class":189},[180,2148,2149],{"class":237},"].set_column(",[180,2151,2152],{"class":189},"\"A:B\"",[180,2154,286],{"class":237},[180,2156,1788],{"class":401},[180,2158,269],{"class":237},[180,2160,2162,2164,2166,2168,2171,2173,2175,2177,2179,2181,2184],{"class":47,"line":2161},24,[180,2163,2144],{"class":237},[180,2165,2128],{"class":189},[180,2167,2149],{"class":237},[180,2169,2170],{"class":189},"\"C:D\"",[180,2172,286],{"class":237},[180,2174,60],{"class":401},[180,2176,1772],{"class":237},[180,2178,1683],{"class":189},[180,2180,1686],{"class":237},[180,2182,2183],{"class":189},"\"yyyy-mm-dd\"",[180,2185,1791],{"class":237},[180,2187,2189,2191,2193,2195,2198,2200,2202],{"class":47,"line":2188},25,[180,2190,2144],{"class":237},[180,2192,2128],{"class":189},[180,2194,2149],{"class":237},[180,2196,2197],{"class":189},"\"E:E\"",[180,2199,286],{"class":237},[180,2201,60],{"class":401},[180,2203,1968],{"class":237},[180,2205,2207,2209,2211,2214,2216,2218,2220,2222,2224,2227,2229],{"class":47,"line":2206},26,[180,2208,2144],{"class":237},[180,2210,2128],{"class":189},[180,2212,2213],{"class":237},"].autofilter(",[180,2215,42],{"class":401},[180,2217,286],{"class":237},[180,2219,42],{"class":401},[180,2221,286],{"class":237},[180,2223,1862],{"class":401},[180,2225,2226],{"class":237},"(detail), ",[180,2228,1142],{"class":401},[180,2230,269],{"class":237},[180,2232,2234],{"class":47,"line":2233},27,[180,2235,251],{"emptyLinePlaceholder":250},[180,2237,2239,2241,2244,2247,2249,2251,2254,2257,2259,2261,2263,2266],{"class":47,"line":2238},28,[180,2240,435],{"class":401},[180,2242,2243],{"class":237},"(pd.ExcelFile(out).sheet_names, ",[180,2245,2246],{"class":189},"\"-\"",[180,2248,286],{"class":237},[180,2250,1862],{"class":401},[180,2252,2253],{"class":237},"(report), ",[180,2255,2256],{"class":189},"\"customers,\"",[180,2258,286],{"class":237},[180,2260,1862],{"class":401},[180,2262,2226],{"class":237},[180,2264,2265],{"class":189},"\"documents\"",[180,2267,269],{"class":237},[10,2269,2270,2271,2274],{},"The totals row uses ",[177,2272,2273],{},"SUM"," formulas so the reviewer can see how it adds up — opened in a spreadsheet, it shows 23,650 current and 37,100 in total; the conditional format compares each row's Total (column G) with its credit limit (column I) and shades the customer name. The detail sheet has an autofilter, so filtering on one customer shows exactly the documents behind their row.",[165,2276,2278],{"id":2277},"common-pitfalls","Common pitfalls",[2280,2281,2282,2289,2295,2301,2310,2316],"ul",{},[2283,2284,2285,2288],"li",{},[218,2286,2287],{},"Aging from today."," Always measure from the as-at date, so reruns match what was reported.",[2283,2290,2291,2294],{},[218,2292,2293],{},"Including documents after the as-at date."," Filter on document date; the export may be run days later.",[2283,2296,2297,2300],{},[218,2298,2299],{},"Dropping credit notes."," Negative items belong in the aging; leaving them out overstates the balance.",[2283,2302,2303,2306,2307,2309],{},[218,2304,2305],{},"Buckets that disappear."," Use ",[177,2308,676],{}," so every bucket is always a column.",[2283,2311,2312,2315],{},[218,2313,2314],{},"No tie-out."," The aging total must equal the receivables control account.",[2283,2317,2318,2321],{},[218,2319,2320],{},"Due date versus invoice date."," Aging by invoice date is a different report; label clearly which one it is.",[165,2323,2325],{"id":2324},"performance-notes","Performance notes",[10,2327,2328,2329,2333],{},"Aging tens of thousands of open items is instant in pandas. The slow part is usually the export; when the accounting system offers an API or a database view of open items, ",[14,2330,2332],{"href":2331},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmoving-data-between-excel-and-databases\u002Fexport-sql-query-results-to-excel-with-python\u002F","query it directly"," rather than waiting for a spreadsheet.",[165,2335,2337],{"id":2336},"conclusion","Conclusion",[10,2339,2340,2341,2343,2344,2346],{},"Compute each document's outstanding amount and its days past due as at the period end, excluding documents dated after it. Bucket the balances with ",[177,2342,503],{},", pivot them to one row per customer with ",[177,2345,676],{}," so the columns never change, and add totals and an over-60 figure. Flag customers above their credit limit, tie the grand total back to the receivables ledger, and write the aging with a traceable detail sheet.",[165,2348,2350],{"id":2349},"frequently-asked-questions","Frequently asked questions",[10,2352,2353,2356],{},[218,2354,2355],{},"How do I calculate days past due for an aging report?","\nSubtract the due date from the as-at date — usually the period end — not from today: (as_at - due_date).dt.days. Zero or negative means not yet due. Using today makes the report change every time it is rerun.",[10,2358,2359,2362,2363,2366],{},[218,2360,2361],{},"How do I put invoices into aging buckets with pandas?","\nUse pd.cut on days past due with edges such as ",[180,2364,2365],{},"-inf, 0, 30, 60, 90, inf"," and labels Current, 1–30, 31–60, 61–90 and 90+. The right edges are inclusive, so 30 days falls in 1–30 and 31 in 31–60.",[10,2368,2369,2372],{},[218,2370,2371],{},"Where do credit notes and unapplied payments go in an aging report?","\nThey reduce the customer's balance. Most teams age them by their own date like an invoice, so they sit in a bucket as a negative amount; others show them in a separate Unapplied column. Either way the customer total must equal the ledger balance.",[10,2374,2375,2378],{},[218,2376,2377],{},"Should an aging report include invoices dated after the period end?","\nNo. An aging as at 30 September shows what was owed on that date, so documents dated after it are excluded, even if the export was run later and contains them.",[165,2380,2382],{"id":2381},"related","Related",[2280,2384,2385,2391,2398,2405],{},[2283,2386,2387,2388,2390],{},"Up one level: ",[14,2389,17],{"href":16}," — the pipeline these reports share.",[2283,2392,2393,2397],{},[14,2394,2396],{"href":2395},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-bank-reconciliation-report\u002F","Build a Bank Reconciliation Report"," — matching the cash side.",[2283,2399,2400,2404],{},[14,2401,2403],{"href":2402},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fcalculate-age-and-tenure-from-dates-with-pandas\u002F","Calculate Age and Tenure from Dates with pandas"," — date differences in depth.",[2283,2406,2407,2411],{},[14,2408,2410],{"href":2409},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fexport-pandas-pivot-table-to-excel-formatted\u002F","Export pandas Pivot Table to Excel Formatted"," — styling pivot output.",[2413,2414,2415],"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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":175,"searchDepth":247,"depth":247,"links":2417},[2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428],{"id":167,"depth":247,"text":168},{"id":212,"depth":247,"text":213},{"id":497,"depth":247,"text":498},{"id":669,"depth":247,"text":670},{"id":1175,"depth":247,"text":1176},{"id":1516,"depth":247,"text":1517},{"id":2277,"depth":247,"text":2278},{"id":2324,"depth":247,"text":2325},{"id":2336,"depth":247,"text":2337},{"id":2349,"depth":247,"text":2350},{"id":2381,"depth":247,"text":2382},"2026-09-25","Turn an open-invoice export into the aging report credit control works from: balances bucketed into current, 1–30, 31–60, 61–90 and over 90 days past due as at the period end, one row per customer with totals, credit notes netted, customers over their credit limit flagged and the total tied back to the ledger.","md",[2433,2435,2437,2439],{"q":2355,"a":2434},"Subtract the due date from the as-at date — usually the period end — not from today: (as_at - due_date).dt.days. Zero or negative means not yet due. Using today makes the report change every time it is rerun.",{"q":2361,"a":2436},"Use pd.cut on days past due with edges such as [-inf, 0, 30, 60, 90, inf] and labels Current, 1–30, 31–60, 61–90 and 90+. The right edges are inclusive, so 30 days falls in 1–30 and 31 in 31–60.",{"q":2371,"a":2438},"They reduce the customer's balance. Most teams age them by their own date like an invoice, so they sit in a bucket as a negative amount; others show them in a separate Unapplied column. Either way the customer total must equal the ledger balance.",{"q":2377,"a":2440},"No. An aging as at 30 September shows what was owed on that date, so documents dated after it are excluded, even if the export was run later and contains them.","build an accounts receivable aging report",null,{"breadcrumb":2444},[2445,2448,2451],{"name":2446,"item":2447},"Home","\u002F",{"name":2449,"item":2450},"Automating Reporting Workflows with Python and Excel","\u002Fautomating-reporting-workflows\u002F",{"name":2452,"item":16},"Building Finance and Operations Reports in Excel with Python","\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report",{"title":2455,"description":2456},"Accounts Receivable Aging Report in Excel with Python","Build an AR aging report with pandas: days past due as at a date, aging buckets with pd.cut, customer pivot with totals, credit notes and unapplied cash, invoices after the as-at date, credit limit flags, a control-account tie-out and formatted Excel output.","build-an-accounts-receivable-aging-report","automating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accounts-receivable-aging-report\u002Findex",[2460,2461,2462],"report-layouts","pivots-and-summaries","pandas","how-to","Rk8T0XGA9DDrHzfFlB5f-qhL5ddG3574UPjzyQQdna4",[2466,2470],{"title":2467,"path":2468,"stem":2469,"children":-1},"Build a Work in Progress Report for Unbilled Time","\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-work-in-progress-report-for-unbilled-time","automating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-work-in-progress-report-for-unbilled-time\u002Findex",{"title":2471,"path":2472,"stem":2473,"children":-1},"Build an Accruals and Prepayments Schedule","\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accruals-and-prepayments-schedule","automating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-an-accruals-and-prepayments-schedule\u002Findex",[2475,2477],{"path":2476,"title":2452},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports",{"path":2478,"title":2449},"\u002Fautomating-reporting-workflows",[],[2481,2485,2488,2491,2494,2497],{"path":2482,"title":2483,"kind":2484},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards","Building Multi-Sheet Excel Dashboards","guide",{"path":2486,"title":2487,"kind":2463},"\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":2489,"title":2490,"kind":2463},"\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":2492,"title":2493,"kind":2463},"\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":2495,"title":2496,"kind":2463},"\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":2498,"title":2499,"kind":2463},"\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",1790972127583]